package config import ( "os" "path/filepath" "sync" "testing" "time" ) func writeTestConfig(t *testing.T, content string) string { dir := t.TempDir() path := filepath.Join(dir, "config.yaml") if err := os.WriteFile(path, []byte(content), 0644); err != nil { t.Fatalf("write test config: %v", err) } return path } func TestLoadDefaults(t *testing.T) { path := writeTestConfig(t, ` server: host: "127.0.0.1" port: 9090 models: general-chat: provider: ollama actual_model: qwen2.5:0.5b endpoint: http://127.0.0.1:11434 context_window: 32768 max_output_tokens: 4096 max_concurrency: 4 residency: always cancel_supported: true `) cfg, err := Load(path) if err != nil { t.Fatalf("Load failed: %v", err) } if cfg.Server.Port != 9090 { t.Errorf("expected port 9090, got %d", cfg.Server.Port) } if cfg.Scheduler.MaxRunningTasks != 8 { t.Errorf("expected default max_running_tasks 8, got %d", cfg.Scheduler.MaxRunningTasks) } if cfg.Timeouts.DefaultQueueMs != 5000 { t.Errorf("expected default queue_ms 5000, got %d", cfg.Timeouts.DefaultQueueMs) } if cfg.Context.SafetyMarginRatio != 0.08 { t.Errorf("expected default safety_margin 0.08, got %f", cfg.Context.SafetyMarginRatio) } if _, ok := cfg.Models["general-chat"]; !ok { t.Error("expected general-chat model in config") } } func TestValidate(t *testing.T) { path := writeTestConfig(t, ` scheduler: max_running_tasks: -1 `) _, err := Load(path) if err == nil { t.Error("expected validation error for max_running_tasks=-1") } } func TestValidateBackpressure(t *testing.T) { path := writeTestConfig(t, ` backpressure: level1_threshold: 0.90 level2_threshold: 0.80 level3_threshold: 0.95 `) _, err := Load(path) if err == nil { t.Error("expected validation error for level1 >= level2") } } func TestEnvOverride(t *testing.T) { path := writeTestConfig(t, ` server: port: 8080 `) os.Setenv("EDGEAI_SERVER_PORT", "9999") defer os.Unsetenv("EDGEAI_SERVER_PORT") cfg, err := Load(path) if err != nil { t.Fatalf("Load failed: %v", err) } if cfg.Server.Port != 9999 { t.Errorf("expected port 9999 from env, got %d", cfg.Server.Port) } } func TestParsePriority(t *testing.T) { tests := []struct { input string want int }{ {"P0", 0}, {"P1", 1}, {"P2", 2}, {"P3", 3}, {"P4", 4}, {"p0", 0}, {"invalid", 2}, {"", 2}, } for _, tt := range tests { got := ParsePriority(tt.input) if got != tt.want { t.Errorf("ParsePriority(%q) = %d, want %d", tt.input, got, tt.want) } } } func TestPriorityName(t *testing.T) { if PriorityName(0) != "P0" { t.Errorf("expected P0, got %s", PriorityName(0)) } if PriorityName(2) != "P2" { t.Errorf("expected P2, got %s", PriorityName(2)) } if PriorityName(10) != "P2" { t.Errorf("expected P2 for out-of-range, got %s", PriorityName(10)) } } func TestGetUpdate(t *testing.T) { cfg := &Config{} Update(cfg) time.Sleep(10 * time.Millisecond) got := Get() if got != cfg { t.Error("Get/Update mismatch") } } func TestConfigPath(t *testing.T) { os.Unsetenv("EDGEAI_CONFIG_PATH") if got := ConfigPath(); got != "configs/config.yaml" { t.Errorf("expected default path, got %s", got) } os.Setenv("EDGEAI_CONFIG_PATH", "/tmp/test.yaml") defer os.Unsetenv("EDGEAI_CONFIG_PATH") if got := ConfigPath(); got != "/tmp/test.yaml" { t.Errorf("expected env path, got %s", got) } } // Ensure package compiles with sync import. var _ = sync.RWMutex{}