(t *testing.T)
| 229 | } |
| 230 | |
| 231 | func TestReload(t *testing.T) { |
| 232 | t.Parallel() |
| 233 | |
| 234 | t.Run("SingleReloadUpdatesSnapshot", func(t *testing.T) { |
| 235 | t.Parallel() |
| 236 | ctx := testutil.Context(t, testutil.WaitLong) |
| 237 | logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug) |
| 238 | dir := t.TempDir() |
| 239 | |
| 240 | _, entry := fakeMCPServerConfig(t, "srv") |
| 241 | configPath := writeMCPConfig(t, dir, map[string]mcpServerEntry{"srv": entry}) |
| 242 | |
| 243 | m := NewManager(ctx, logger, agentexec.DefaultExecer, nil) |
| 244 | t.Cleanup(func() { _ = m.Close() }) |
| 245 | |
| 246 | err := m.Reload(ctx, []string{configPath}) |
| 247 | require.NoError(t, err) |
| 248 | |
| 249 | tools := m.cachedTools() |
| 250 | require.Len(t, tools, 1, "should have one tool from the fake server") |
| 251 | assert.Contains(t, tools[0].Name, "echo") |
| 252 | |
| 253 | // Snapshot should be fresh. |
| 254 | assert.False(t, m.SnapshotChanged([]string{configPath})) |
| 255 | }) |
| 256 | |
| 257 | t.Run("ReloadAfterClose", func(t *testing.T) { |
| 258 | t.Parallel() |
| 259 | ctx := testutil.Context(t, testutil.WaitLong) |
| 260 | logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug) |
| 261 | |
| 262 | m := NewManager(ctx, logger, agentexec.DefaultExecer, nil) |
| 263 | require.NoError(t, m.Close()) |
| 264 | |
| 265 | err := m.Reload(ctx, []string{"/nonexistent"}) |
| 266 | require.Error(t, err, "reload after close should fail") |
| 267 | }) |
| 268 | |
| 269 | t.Run("ConcurrentReloadsCoalesce", func(t *testing.T) { |
| 270 | t.Parallel() |
| 271 | ctx := testutil.Context(t, testutil.WaitLong) |
| 272 | logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug) |
| 273 | dir := t.TempDir() |
| 274 | |
| 275 | _, entry := fakeMCPServerConfig(t, "srv") |
| 276 | configPath := writeMCPConfig(t, dir, map[string]mcpServerEntry{"srv": entry}) |
| 277 | |
| 278 | m := NewManager(ctx, logger, agentexec.DefaultExecer, nil) |
| 279 | t.Cleanup(func() { _ = m.Close() }) |
| 280 | |
| 281 | // Launch multiple concurrent reloads. |
| 282 | const numCallers = 5 |
| 283 | var wg sync.WaitGroup |
| 284 | errs := make([]error, numCallers) |
| 285 | for i := range numCallers { |
| 286 | wg.Go(func() { |
| 287 | errs[i] = m.Reload(ctx, []string{configPath}) |
| 288 | }) |
nothing calls this directly
no test coverage detected