Skip to content

Commit 74be758

Browse files
committed
Adding tests
1 parent 2c0ba25 commit 74be758

File tree

1 file changed

+292
-0
lines changed

1 file changed

+292
-0
lines changed

cmd/src/cmd_test.go

Lines changed: 292 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,292 @@
1+
package main
2+
3+
import (
4+
"bytes"
5+
"flag"
6+
"os"
7+
"os/exec"
8+
"testing"
9+
10+
"github.com/sourcegraph/src-cli/internal/cmderrors"
11+
)
12+
13+
func TestCommand_Matches(t *testing.T) {
14+
tests := []struct {
15+
name string
16+
cmd *command
17+
input string
18+
expected bool
19+
}{
20+
{
21+
name: "matches command name",
22+
cmd: &command{
23+
flagSet: flag.NewFlagSet("test", flag.ExitOnError),
24+
},
25+
input: "test",
26+
expected: true,
27+
},
28+
{
29+
name: "matches alias",
30+
cmd: &command{
31+
flagSet: flag.NewFlagSet("test", flag.ExitOnError),
32+
aliases: []string{"t", "tst"},
33+
},
34+
input: "t",
35+
expected: true,
36+
},
37+
{
38+
name: "matches second alias",
39+
cmd: &command{
40+
flagSet: flag.NewFlagSet("test", flag.ExitOnError),
41+
aliases: []string{"t", "tst"},
42+
},
43+
input: "tst",
44+
expected: true,
45+
},
46+
{
47+
name: "no match",
48+
cmd: &command{
49+
flagSet: flag.NewFlagSet("test", flag.ExitOnError),
50+
aliases: []string{"t"},
51+
},
52+
input: "other",
53+
expected: false,
54+
},
55+
{
56+
name: "empty string no match",
57+
cmd: &command{
58+
flagSet: flag.NewFlagSet("test", flag.ExitOnError),
59+
},
60+
input: "",
61+
expected: false,
62+
},
63+
}
64+
65+
for _, tt := range tests {
66+
t.Run(tt.name, func(t *testing.T) {
67+
result := tt.cmd.matches(tt.input)
68+
if result != tt.expected {
69+
t.Errorf("matches(%q) = %v, want %v", tt.input, result, tt.expected)
70+
}
71+
})
72+
}
73+
}
74+
75+
func TestCommander_Run_ErrorHandling(t *testing.T) {
76+
tests := []struct {
77+
name string
78+
handlerError error
79+
expectedExit int
80+
description string
81+
}{
82+
{
83+
name: "usage error",
84+
handlerError: cmderrors.Usage("invalid usage"),
85+
expectedExit: 2,
86+
description: "should exit with code 2 for usage errors",
87+
},
88+
{
89+
name: "exit code error without message",
90+
handlerError: cmderrors.ExitCode(42, nil),
91+
expectedExit: 42,
92+
description: "should exit with custom exit code",
93+
},
94+
{
95+
name: "exit code error with message",
96+
handlerError: cmderrors.ExitCode(1, cmderrors.Usage("command failed")),
97+
expectedExit: 1,
98+
description: "should exit with custom exit code and log error",
99+
},
100+
}
101+
102+
for _, tt := range tests {
103+
t.Run(tt.name, func(t *testing.T) {
104+
t.Logf("Test case: %s", tt.description)
105+
})
106+
}
107+
}
108+
109+
func TestCommander_Run_UnknownCommand(t *testing.T) {
110+
if os.Getenv("TEST_SUBPROCESS") == "1" {
111+
testHomeDir = os.Getenv("TEST_TEMP_DIR")
112+
cmdr := commander{
113+
&command{
114+
flagSet: flag.NewFlagSet("version", flag.ContinueOnError),
115+
handler: func(args []string) error { return nil },
116+
},
117+
}
118+
flagSet := flag.NewFlagSet("test", flag.ContinueOnError)
119+
cmdr.run(flagSet, "src", "usage text", []string{"beans"})
120+
return
121+
}
122+
123+
tempDir := t.TempDir()
124+
cmd := exec.Command(os.Args[0], "-test.run=^TestCommander_Run_UnknownCommand$")
125+
cmd.Env = append(os.Environ(), "TEST_SUBPROCESS=1", "TEST_TEMP_DIR="+tempDir)
126+
var stderr bytes.Buffer
127+
cmd.Stderr = &stderr
128+
err := cmd.Run()
129+
130+
if err == nil {
131+
t.Fatal("expected command to exit with non-zero code")
132+
}
133+
134+
if e, ok := err.(*exec.ExitError); ok {
135+
if e.ExitCode() != 2 {
136+
t.Errorf("expected exit code 2 for unknown command, got %d\nstderr: %s", e.ExitCode(), stderr.String())
137+
}
138+
} else {
139+
t.Errorf("unexpected error type: %v", err)
140+
}
141+
}
142+
143+
func TestCommander_Run_HelpFlag(t *testing.T) {
144+
if os.Getenv("TEST_SUBPROCESS") == "1" {
145+
testHomeDir = os.Getenv("TEST_TEMP_DIR")
146+
arg := os.Getenv("TEST_ARG")
147+
cmdr := commander{}
148+
flagSet := flag.NewFlagSet("test", flag.ContinueOnError)
149+
cmdr.run(flagSet, "src", "usage text", []string{arg})
150+
return
151+
}
152+
153+
tests := []struct {
154+
name string
155+
arg string
156+
contains string
157+
expectedExit int
158+
}{
159+
{
160+
name: "help flag at root",
161+
arg: "--help",
162+
contains: "usage text",
163+
expectedExit: 0,
164+
},
165+
{
166+
name: "-h flag at root",
167+
arg: "-h",
168+
contains: "usage text",
169+
expectedExit: 0,
170+
},
171+
{
172+
name: "help command at root",
173+
arg: "help",
174+
contains: "usage text",
175+
expectedExit: 0,
176+
},
177+
}
178+
179+
for _, tt := range tests {
180+
t.Run(tt.name, func(t *testing.T) {
181+
tempDir := t.TempDir()
182+
cmd := exec.Command(os.Args[0], "-test.run=^TestCommander_Run_HelpFlag$")
183+
cmd.Env = append(os.Environ(), "TEST_SUBPROCESS=1", "TEST_TEMP_DIR="+tempDir, "TEST_ARG="+tt.arg)
184+
var stdout, stderr bytes.Buffer
185+
cmd.Stdout = &stdout
186+
cmd.Stderr = &stderr
187+
err := cmd.Run()
188+
189+
output := stdout.String() + stderr.String()
190+
191+
if tt.expectedExit == 0 && err != nil {
192+
t.Errorf("expected success, got error: %v\noutput: %s", err, output)
193+
} else if tt.expectedExit != 0 {
194+
if err == nil {
195+
t.Errorf("expected exit code %d, got success", tt.expectedExit)
196+
} else if e, ok := err.(*exec.ExitError); ok && e.ExitCode() != tt.expectedExit {
197+
t.Errorf("expected exit code %d, got %d\noutput: %s", tt.expectedExit, e.ExitCode(), output)
198+
}
199+
}
200+
201+
if !bytes.Contains([]byte(output), []byte(tt.contains)) {
202+
t.Errorf("expected output to contain %q, got:\n%s", tt.contains, output)
203+
}
204+
})
205+
}
206+
}
207+
208+
func TestCommander_Run_NestedHelpFlags(t *testing.T) {
209+
t.Skip("Complex nested help flag testing requires integration with actual src commands")
210+
}
211+
212+
func TestCommander_Run_InvalidSubcommand(t *testing.T) {
213+
if os.Getenv("TEST_SUBPROCESS") == "1" {
214+
testHomeDir = os.Getenv("TEST_TEMP_DIR")
215+
arg := os.Getenv("TEST_ARG")
216+
cmdr := commander{
217+
&command{
218+
flagSet: flag.NewFlagSet("version", flag.ContinueOnError),
219+
handler: func(args []string) error { return nil },
220+
},
221+
}
222+
flagSet := flag.NewFlagSet("test", flag.ContinueOnError)
223+
cmdr.run(flagSet, "src", "root usage", []string{arg})
224+
return
225+
}
226+
227+
tests := []struct {
228+
name string
229+
arg string
230+
expectedExit int
231+
}{
232+
{"invalid root command", "beans", 2},
233+
{"invalid root with help", "foobar", 2},
234+
}
235+
236+
for _, tt := range tests {
237+
t.Run(tt.name, func(t *testing.T) {
238+
tempDir := t.TempDir()
239+
cmd := exec.Command(os.Args[0], "-test.run=^TestCommander_Run_InvalidSubcommand$")
240+
cmd.Env = append(os.Environ(), "TEST_SUBPROCESS=1", "TEST_TEMP_DIR="+tempDir, "TEST_ARG="+tt.arg)
241+
var stderr bytes.Buffer
242+
cmd.Stderr = &stderr
243+
err := cmd.Run()
244+
245+
if err == nil {
246+
t.Fatalf("expected exit code %d, got success", tt.expectedExit)
247+
}
248+
249+
if e, ok := err.(*exec.ExitError); ok {
250+
if e.ExitCode() != tt.expectedExit {
251+
t.Errorf("expected exit code %d, got %d\nstderr: %s", tt.expectedExit, e.ExitCode(), stderr.String())
252+
}
253+
} else {
254+
t.Errorf("unexpected error type: %v", err)
255+
}
256+
})
257+
}
258+
}
259+
260+
func TestCommander_Run_MissingRequiredArgs(t *testing.T) {
261+
if os.Getenv("TEST_SUBPROCESS") == "1" {
262+
testHomeDir = os.Getenv("TEST_TEMP_DIR")
263+
cmdr := commander{
264+
&command{
265+
flagSet: flag.NewFlagSet("version", flag.ContinueOnError),
266+
handler: func(args []string) error { return nil },
267+
},
268+
}
269+
flagSet := flag.NewFlagSet("test", flag.ContinueOnError)
270+
cmdr.run(flagSet, "src", "root usage", []string{})
271+
return
272+
}
273+
274+
tempDir := t.TempDir()
275+
cmd := exec.Command(os.Args[0], "-test.run=^TestCommander_Run_MissingRequiredArgs$")
276+
cmd.Env = append(os.Environ(), "TEST_SUBPROCESS=1", "TEST_TEMP_DIR="+tempDir)
277+
var stderr bytes.Buffer
278+
cmd.Stderr = &stderr
279+
err := cmd.Run()
280+
281+
if err == nil {
282+
t.Fatal("expected exit code 2, got success")
283+
}
284+
285+
if e, ok := err.(*exec.ExitError); ok {
286+
if e.ExitCode() != 2 {
287+
t.Errorf("expected exit code 2, got %d\nstderr: %s", e.ExitCode(), stderr.String())
288+
}
289+
} else {
290+
t.Errorf("unexpected error type: %v", err)
291+
}
292+
}

0 commit comments

Comments
 (0)