1package agent
2
3import (
4 "bytes"
5 "os"
6 "os/exec"
7 "strings"
8 "testing"
9)
10
11func TestParseArgsExplicitEmptySystemPromptIsSet(t *testing.T) {
12 args, err := ParseArgs([]string{"--system-prompt", ""})
13 if err != nil {
14 t.Fatalf("ParseArgs returned %v", err)
15 }
16 if !args.SystemPromptSet {
17 t.Fatal("SystemPromptSet = false; want true for an explicitly empty flag value")
18 }
19 if args.SystemPrompt != "" {
20 t.Fatalf("SystemPrompt = %q; want empty", args.SystemPrompt)
21 }
22}
23
24func TestParseArgsTemperatureAllowsZero(t *testing.T) {
25 args, err := ParseArgs([]string{"--temperature", "0"})
26 if err != nil {
27 t.Fatalf("ParseArgs returned %v", err)
28 }
29 if args.Temperature == nil || *args.Temperature != 0 {
30 t.Fatalf("Temperature = %v; want 0", args.Temperature)
31 }
32}
33
34func TestParseArgsTemperatureRejectsOutOfRange(t *testing.T) {
35 if _, err := ParseArgs([]string{"--temperature", "2.1"}); err == nil {
36 t.Fatal("ParseArgs accepted out-of-range temperature")
37 }
38}
39
40func TestParseArgsYes(t *testing.T) {
41 for _, flag := range []string{"-y", "--yes"} {
42 args, err := ParseArgs([]string{flag, "--print", "hi"})
43 if err != nil {
44 t.Fatalf("ParseArgs(%q): %v", flag, err)
45 }
46 if !args.Yes {
47 t.Fatalf("ParseArgs(%q): Yes = false", flag)
48 }
49 if args.Mode != ModePrint || args.Prompt != "hi" {
50 t.Fatalf("ParseArgs(%q): Mode=%q Prompt=%q", flag, args.Mode, args.Prompt)
51 }
52 }
53}
54
55func TestParseArgsStatsRequiresPrintMode(t *testing.T) {
56 args, err := ParseArgs([]string{"-p", "--stats", "stats.json", "hi"})
57 if err != nil {
58 t.Fatal(err)
59 }
60 if args.StatsPath != "stats.json" || args.Mode != ModePrint {
61 t.Fatalf("StatsPath=%q Mode=%q", args.StatsPath, args.Mode)
62 }
63
64 if _, err := ParseArgs([]string{"--stats", "stats.json", "hi"}); err == nil {
65 t.Fatal("ParseArgs accepted --stats without print mode")
66 }
67}
68
69func TestParseArgsNoContextFiles(t *testing.T) {
70 for _, flag := range []string{"--no-context-files", "-nc"} {
71 args, err := ParseArgs([]string{flag})
72 if err != nil {
73 t.Fatalf("ParseArgs(%q): %v", flag, err)
74 }
75 if !args.NoContextFiles {
76 t.Fatalf("ParseArgs(%q): NoContextFiles = false", flag)
77 }
78 }
79}
80
81func TestParseArgsStream(t *testing.T) {
82 args, err := ParseArgs([]string{"--stream", "hi"})
83 if err != nil {
84 t.Fatal(err)
85 }
86 if args.Mode != ModeStream || args.Prompt != "hi" {
87 t.Fatalf("Mode=%q Prompt=%q", args.Mode, args.Prompt)
88 }
89}
90
91func TestRunHelpHelperProcess(t *testing.T) {
92 if os.Getenv("ZOT_HELP_HELPER") == "" {
93 return
94 }
95 if err := runWithArgsRaw(strings.Fields(os.Getenv("ZOT_HELP_HELPER")), "test"); err != nil {
96 os.Exit(1)
97 }
98 os.Exit(0)
99}
100
101func TestRunSetsAgentEnvironment(t *testing.T) {
102 t.Setenv("ZOT_AGENT", "")
103 t.Setenv("AI_AGENT", "")
104 isolateSessionEnvironment(t)
105 if err := Run([]string{"--help"}, "test"); err != nil {
106 t.Fatalf("Run returned %v", err)
107 }
108 if got := os.Getenv("ZOT_AGENT"); got != "1" {
109 t.Fatalf("ZOT_AGENT = %q, want %q", got, "1")
110 }
111 if got := os.Getenv("AI_AGENT"); got != "zot" {
112 t.Fatalf("AI_AGENT = %q, want %q", got, "zot")
113 }
114}
115
116func TestHelpOutputStreams(t *testing.T) {
117 run := func(args string) (stdout, stderr string, err error) {
118 t.Helper()
119 cmd := exec.Command(os.Args[0], "-test.run=^TestRunHelpHelperProcess$")
120 cmd.Env = append(os.Environ(), "ZOT_HELP_HELPER="+args)
121 var outBuf, errBuf bytes.Buffer
122 cmd.Stdout = &outBuf
123 cmd.Stderr = &errBuf
124 err = cmd.Run()
125 return outBuf.String(), errBuf.String(), err
126 }
127
128 stdout, stderr, err := run("--help")
129 if err != nil {
130 t.Fatalf("--help returned %v; stderr:\n%s", err, stderr)
131 }
132 if !strings.Contains(stdout, "zot. yet another coding agent harness.") {
133 t.Fatalf("stdout does not contain help text:\n%s", stdout)
134 }
135 if stderr != "" {
136 t.Fatalf("stderr = %q, want empty", stderr)
137 }
138 if strings.Contains(stdout, "\x1b[") {
139 t.Fatalf("redirected help contains ANSI escapes: %q", stdout)
140 }
141
142 stdout, stderr, err = run("--unknown")
143 if err == nil {
144 t.Fatal("unknown flag exited successfully")
145 }
146 if stdout != "" {
147 t.Fatalf("stdout = %q, want empty for an argument error", stdout)
148 }
149 if !strings.Contains(stderr, "zot. yet another coding agent harness.") {
150 t.Fatalf("stderr does not contain help text:\n%s", stderr)
151 }
152}