internal/control/control_test.go
88 lines · 2865 bytes
1package control
2
3import (
4 "strings"
5 "testing"
6
7 "gitbay.org/gitbay/internal/protocol"
8)
9
10// TestEveryCommandReachableFromBareSSH asserts that each registered command's
11// path, rendered exactly as a user would type it after `ssh <host>`, resolves
12// back to that command through the tokenizer and Lookup. This is the guard
13// that keeps the forge CLI optional.
14func TestEveryCommandReachableFromBareSSH(t *testing.T) {
15 cmds := Commands()
16 if len(cmds) == 0 {
17 t.Fatal("no commands registered")
18 }
19 for _, cmd := range cmds {
20 line := strings.Join(cmd.Path, " ")
21 argv, err := protocol.Tokenize(line)
22 if err != nil {
23 t.Errorf("command %q not tokenizable: %v", line, err)
24 continue
25 }
26 got, rest, ok := Lookup(argv)
27 if !ok {
28 t.Errorf("command %q not found by Lookup", line)
29 continue
30 }
31 if strings.Join(got.Path, " ") != line || len(rest) != 0 {
32 t.Errorf("Lookup(%q) resolved to %q with rest %v", line, strings.Join(got.Path, " "), rest)
33 }
34 if cmd.Run == nil {
35 t.Errorf("command %q has no Run", line)
36 }
37 if cmd.Summary == "" {
38 t.Errorf("command %q has no summary", line)
39 }
40 }
41}
42
43func TestLookupLongestMatch(t *testing.T) {
44 // "keys list" must not resolve to a hypothetical shorter prefix and
45 // unknown commands must not match.
46 if _, _, ok := Lookup([]string{"keys"}); ok {
47 t.Error("bare \"keys\" resolved; group prefixes must not be runnable")
48 }
49 if _, _, ok := Lookup([]string{"nope"}); ok {
50 t.Error("unknown command resolved")
51 }
52 cmd, rest, ok := Lookup([]string{"keys", "list", "--json"})
53 if !ok || strings.Join(cmd.Path, " ") != "keys list" || len(rest) != 1 {
54 t.Errorf("Lookup keys list --json = %v %v %v", cmd.Path, rest, ok)
55 }
56}
57
58// TestBuildJobsIsAReadCommand pins the properties the surfaces depend on:
59// the web build page and a read-scoped API token both need it over GET.
60func TestBuildJobsIsAReadCommand(t *testing.T) {
61 cmd, _, ok := Lookup([]string{"build", "jobs"})
62 if !ok {
63 t.Fatal("build jobs not registered")
64 }
65 if !cmd.ReadOnly {
66 t.Error("build jobs must be ReadOnly; listing jobs changes nothing")
67 }
68 if cmd.SSHOnly {
69 t.Error("build jobs must not be SSHOnly; the web and the app need it")
70 }
71}
72
73// A merge request's dedup key must not collide with a commit sha. It did:
74// a bare "#N" in a commit message recorded (issue, sha) first, and the
75// description's "Closes #N" then found the key taken and silently gave
76// up. That is how krz/gitbay-ios#8 stayed open after its own MR merged.
77func TestMRDedupKeyCannotCollideWithASHA(t *testing.T) {
78 key := mrRefKey(24)
79 if key == "51b6a14eab49ab08e890597653fcf02f8f38f3d6" || len(key) == 40 {
80 t.Errorf("mrRefKey(24) = %q, which is shaped like a sha", key)
81 }
82 if key != "mr-24" {
83 t.Errorf("mrRefKey(24) = %q, want \"mr-24\"", key)
84 }
85 if mrRefKey(24) == mrRefKey(25) {
86 t.Error("different merge requests share a dedup key")
87 }
88}