package configrefresh_test import ( "context" "testing" "iop/apps/edge/internal/configrefresh" ) // TestClassifyNodeRuntimeConcurrencyApplied verifies S15: node runtime // concurrency is applied live. func TestClassifyNodeRuntimeConcurrencyApplied(t *testing.T) { dir := t.TempDir() currentYAML := ` server: listen: "0.0.0.0:9090" nodes: - id: "node-1" alias: "n1" token: "tok-1" adapters: cli: enabled: true runtime: concurrency: 2 ` currentPath := writeYAML(t, dir, "current.yaml", currentYAML) concurrencyOnlyYAML := ` server: listen: "0.0.0.0:9090" nodes: - id: "node-1" alias: "n1" token: "tok-1" adapters: cli: enabled: true runtime: concurrency: 4 ` concurrencyOnlyPath := writeYAML(t, dir, "concurrency.yaml", concurrencyOnlyYAML) current := buildNormalizedCurrent(t, currentPath) ctx := context.Background() // concurrency-only change → applied. result, _, err := configrefresh.Evaluate(ctx, current, configrefresh.Request{ Mode: configrefresh.ModeDryRun, ConfigPath: concurrencyOnlyPath, RequestID: "test-s15-conc", }) if err != nil { t.Fatalf("Evaluate concurrency: %v", err) } if result.Status != configrefresh.StatusApplied { t.Fatalf("expected concurrency change status=applied, got %q (summary: %s)", result.Status, result.Summary) } foundConc := false for _, c := range result.Changes { if c.Path == `nodes["node-1"].runtime.concurrency` { foundConc = true if c.Class != configrefresh.StatusApplied { t.Errorf("expected concurrency class=applied, got %q", c.Class) } } if c.Class == configrefresh.StatusRestartRequired { t.Errorf("unexpected restart_required change for concurrency-only diff: %s", c.Path) } } if !foundConc { t.Errorf("concurrency change path not found in: %+v", result.Changes) } } func TestClassifyModelCatalogProviderMappingApplied(t *testing.T) { dir := t.TempDir() currentYAML := ` server: listen: "0.0.0.0:9090" nodes: - id: "node-1" alias: "n1" token: "tok-1" adapters: cli: enabled: true providers: - id: "prov-a" type: "ollama" category: "local_inference" adapter: "cli" models: ["llama3.1"] capacity: 2 - id: "prov-b" type: "ollama" category: "local_inference" adapter: "cli" models: ["llama3.1"] capacity: 2 models: - id: "qwen3.6:35b" display_name: "Qwen" context_window_tokens: 131072 default_max_tokens: 8192 min_max_tokens: 8192 providers: prov-a: "llama3.1" ` candidateYAML := ` server: listen: "0.0.0.0:9090" nodes: - id: "node-1" alias: "n1" token: "tok-1" adapters: cli: enabled: true providers: - id: "prov-a" type: "ollama" category: "local_inference" adapter: "cli" models: ["llama3.1"] capacity: 2 - id: "prov-b" type: "ollama" category: "local_inference" adapter: "cli" models: ["llama3.1"] capacity: 2 models: - id: "qwen3.6:35b" display_name: "Qwen" context_window_tokens: 262144 default_max_tokens: 32768 min_max_tokens: 32768 default_thinking_token_budget: 8192 providers: prov-b: "llama3.1" ` currentPath := writeYAML(t, dir, "current.yaml", currentYAML) candidatePath := writeYAML(t, dir, "candidate.yaml", candidateYAML) current := buildNormalizedCurrent(t, currentPath) result, _, err := configrefresh.Evaluate(context.Background(), current, configrefresh.Request{ Mode: configrefresh.ModeDryRun, ConfigPath: candidatePath, RequestID: "test-model-catalog", }) if err != nil { t.Fatalf("Evaluate: %v", err) } if result.Status != configrefresh.StatusApplied { t.Fatalf("expected status=%q, got %q changes=%+v", configrefresh.StatusApplied, result.Status, result.Changes) } found := map[string]bool{} for _, change := range result.Changes { if change.Class == configrefresh.StatusApplied { found[change.Path] = true } } for _, path := range []string{ `models["qwen3.6:35b"].context_window_tokens`, `models["qwen3.6:35b"].default_max_tokens`, `models["qwen3.6:35b"].min_max_tokens`, `models["qwen3.6:35b"].default_thinking_token_budget`, `models["qwen3.6:35b"].providers`, } { if !found[path] { t.Fatalf("model catalog change %s not found in %+v", path, result.Changes) } } } func TestClassifyLongContextThresholdApplied(t *testing.T) { dir := t.TempDir() currentYAML := ` server: listen: "0.0.0.0:9090" long_context_threshold_tokens: 100000 nodes: - id: "node-1" alias: "n1" token: "tok-1" adapters: cli: enabled: true ` candidateYAML := ` server: listen: "0.0.0.0:9090" long_context_threshold_tokens: 120000 nodes: - id: "node-1" alias: "n1" token: "tok-1" adapters: cli: enabled: true ` currentPath := writeYAML(t, dir, "current.yaml", currentYAML) candidatePath := writeYAML(t, dir, "candidate.yaml", candidateYAML) current := buildNormalizedCurrent(t, currentPath) result, _, err := configrefresh.Evaluate(context.Background(), current, configrefresh.Request{ Mode: configrefresh.ModeDryRun, ConfigPath: candidatePath, RequestID: "test-long-threshold", }) if err != nil { t.Fatalf("Evaluate: %v", err) } if result.Status != configrefresh.StatusApplied { t.Fatalf("expected status=%q, got %q changes=%+v", configrefresh.StatusApplied, result.Status, result.Changes) } found := false for _, change := range result.Changes { if change.Path == "long_context_threshold_tokens" { found = true if change.Class != configrefresh.StatusApplied { t.Errorf("threshold class: got %q, want applied", change.Class) } if change.Previous != "100000" || change.Next != "120000" { t.Errorf("threshold diff: got %s→%s", change.Previous, change.Next) } } if change.Class == configrefresh.StatusRestartRequired { t.Errorf("unexpected restart_required threshold change: %s", change.Path) } } if !found { t.Fatalf("long_context_threshold_tokens change not found in %+v", result.Changes) } }