Skip to content

Commit 39ff1a2

Browse files
committed
Monitor tests
Signed-off-by: trangevi <trangevi@microsoft.com>
1 parent df10e4d commit 39ff1a2

File tree

1 file changed

+214
-0
lines changed

1 file changed

+214
-0
lines changed

cli/azd/extensions/azure.ai.agents/internal/cmd/monitor_test.go

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,13 @@
44
package cmd
55

66
import (
7+
"encoding/json"
8+
"os"
9+
"path/filepath"
710
"testing"
811

912
"github.com/stretchr/testify/assert"
13+
"github.com/stretchr/testify/require"
1014
)
1115

1216
func TestMonitorCommand_RequiredFlags(t *testing.T) {
@@ -95,4 +99,214 @@ func TestMonitorCommand_DefaultValues(t *testing.T) {
9599

96100
follow, _ := cmd.Flags().GetBool("follow")
97101
assert.Equal(t, false, follow)
102+
103+
session, _ := cmd.Flags().GetString("session")
104+
assert.Equal(t, "", session)
105+
}
106+
107+
func TestMonitorCommand_SessionFlagRegistered(t *testing.T) {
108+
cmd := newMonitorCommand()
109+
110+
// The --session / -s flag must be defined
111+
f := cmd.Flags().Lookup("session")
112+
require.NotNil(t, f, "--session flag should be registered")
113+
assert.Equal(t, "s", f.Shorthand)
114+
}
115+
116+
func TestMonitorCommand_FollowFlagRegistered(t *testing.T) {
117+
cmd := newMonitorCommand()
118+
119+
f := cmd.Flags().Lookup("follow")
120+
require.NotNil(t, f, "--follow flag should be registered")
121+
assert.Equal(t, "f", f.Shorthand)
122+
}
123+
124+
func TestValidateMonitorFlags_SessionBypassesTailAndType(t *testing.T) {
125+
// When a session ID is set, tail and logType are irrelevant (used only for container logstream).
126+
// Validation should still pass with valid defaults even when session is set.
127+
flags := &monitorFlags{
128+
sessionID: "some-session-id",
129+
tail: 50,
130+
logType: "console",
131+
}
132+
err := validateMonitorFlags(flags)
133+
assert.NoError(t, err)
134+
}
135+
136+
func TestValidateMonitorFlags_TableDriven(t *testing.T) {
137+
t.Parallel()
138+
139+
tests := []struct {
140+
name string
141+
flags monitorFlags
142+
wantErr string
143+
}{
144+
{
145+
name: "valid console defaults",
146+
flags: monitorFlags{tail: 50, logType: "console"},
147+
wantErr: "",
148+
},
149+
{
150+
name: "valid system log type",
151+
flags: monitorFlags{tail: 1, logType: "system"},
152+
wantErr: "",
153+
},
154+
{
155+
name: "tail at max boundary",
156+
flags: monitorFlags{tail: 300, logType: "console"},
157+
wantErr: "",
158+
},
159+
{
160+
name: "tail zero",
161+
flags: monitorFlags{tail: 0, logType: "console"},
162+
wantErr: "--tail must be between 1 and 300",
163+
},
164+
{
165+
name: "tail negative",
166+
flags: monitorFlags{tail: -1, logType: "console"},
167+
wantErr: "--tail must be between 1 and 300",
168+
},
169+
{
170+
name: "tail exceeds max",
171+
flags: monitorFlags{tail: 301, logType: "console"},
172+
wantErr: "--tail must be between 1 and 300",
173+
},
174+
{
175+
name: "invalid log type",
176+
flags: monitorFlags{tail: 50, logType: "debug"},
177+
wantErr: "--type must be 'console' or 'system'",
178+
},
179+
{
180+
name: "empty log type",
181+
flags: monitorFlags{tail: 50, logType: ""},
182+
wantErr: "--type must be 'console' or 'system'",
183+
},
184+
}
185+
186+
for _, tt := range tests {
187+
t.Run(tt.name, func(t *testing.T) {
188+
t.Parallel()
189+
err := validateMonitorFlags(&tt.flags)
190+
if tt.wantErr == "" {
191+
assert.NoError(t, err)
192+
} else {
193+
assert.ErrorContains(t, err, tt.wantErr)
194+
}
195+
})
196+
}
197+
}
198+
199+
func TestLoadLocalContext_WithSessions(t *testing.T) {
200+
t.Parallel()
201+
202+
dir := t.TempDir()
203+
configPath := filepath.Join(dir, ConfigFile)
204+
205+
ctx := &AgentLocalContext{
206+
AgentName: "my-agent",
207+
Sessions: map[string]string{
208+
"agent-a": "session-123",
209+
"agent-b": "session-456",
210+
},
211+
}
212+
data, err := json.MarshalIndent(ctx, "", " ")
213+
require.NoError(t, err)
214+
require.NoError(t, os.WriteFile(configPath, data, 0600))
215+
216+
loaded := loadLocalContext(configPath)
217+
assert.Equal(t, "my-agent", loaded.AgentName)
218+
assert.Equal(t, "session-123", loaded.Sessions["agent-a"])
219+
assert.Equal(t, "session-456", loaded.Sessions["agent-b"])
220+
}
221+
222+
func TestLoadLocalContext_MissingFile(t *testing.T) {
223+
t.Parallel()
224+
225+
loaded := loadLocalContext(filepath.Join(t.TempDir(), "nonexistent.json"))
226+
assert.NotNil(t, loaded)
227+
assert.Nil(t, loaded.Sessions)
228+
}
229+
230+
func TestLoadLocalContext_InvalidJSON(t *testing.T) {
231+
t.Parallel()
232+
233+
dir := t.TempDir()
234+
configPath := filepath.Join(dir, ConfigFile)
235+
require.NoError(t, os.WriteFile(configPath, []byte("{invalid json"), 0600))
236+
237+
loaded := loadLocalContext(configPath)
238+
assert.NotNil(t, loaded)
239+
assert.Nil(t, loaded.Sessions)
240+
}
241+
242+
func TestLoadLocalContext_EmptyFile(t *testing.T) {
243+
t.Parallel()
244+
245+
dir := t.TempDir()
246+
configPath := filepath.Join(dir, ConfigFile)
247+
require.NoError(t, os.WriteFile(configPath, []byte("{}"), 0600))
248+
249+
loaded := loadLocalContext(configPath)
250+
assert.NotNil(t, loaded)
251+
assert.Empty(t, loaded.AgentName)
252+
assert.Nil(t, loaded.Sessions)
253+
}
254+
255+
func TestSaveAndLoadLocalContext_RoundTrip(t *testing.T) {
256+
t.Parallel()
257+
258+
dir := t.TempDir()
259+
configPath := filepath.Join(dir, ConfigFile)
260+
261+
original := &AgentLocalContext{
262+
AgentName: "echo-bot",
263+
Sessions: map[string]string{
264+
"echo-bot": "sess-abc",
265+
},
266+
Conversations: map[string]string{
267+
"echo-bot": "conv-xyz",
268+
},
269+
}
270+
271+
require.NoError(t, saveLocalContext(original, configPath))
272+
273+
loaded := loadLocalContext(configPath)
274+
assert.Equal(t, original.AgentName, loaded.AgentName)
275+
assert.Equal(t, original.Sessions, loaded.Sessions)
276+
assert.Equal(t, original.Conversations, loaded.Conversations)
277+
}
278+
279+
func TestMonitorFlags_SessionBranchingDecision(t *testing.T) {
280+
t.Parallel()
281+
282+
tests := []struct {
283+
name string
284+
sessionID string
285+
wantSessionLog bool
286+
}{
287+
{
288+
name: "session ID set uses session logstream",
289+
sessionID: "session-abc-123",
290+
wantSessionLog: true,
291+
},
292+
{
293+
name: "empty session ID uses container logstream",
294+
sessionID: "",
295+
wantSessionLog: false,
296+
},
297+
}
298+
299+
for _, tt := range tests {
300+
t.Run(tt.name, func(t *testing.T) {
301+
t.Parallel()
302+
flags := &monitorFlags{
303+
sessionID: tt.sessionID,
304+
tail: 50,
305+
logType: "console",
306+
}
307+
// The branching logic in MonitorAction.Run checks flags.sessionID != ""
308+
useSessionLog := flags.sessionID != ""
309+
assert.Equal(t, tt.wantSessionLog, useSessionLog)
310+
})
311+
}
98312
}

0 commit comments

Comments
 (0)