package config import ( "os" "path/filepath" "strings" "testing" ) func TestResolveConfigPathWithLookupMatrix(t *testing.T) { statFor := func(existing map[string]bool) func(string) (os.FileInfo, error) { return func(path string) (os.FileInfo, error) { if existing[path] { return nil, nil } return nil, os.ErrNotExist } } tests := []struct { name string cliPath string cliPathSet bool lookup func(string) (string, bool) stat func(string) (os.FileInfo, error) defaultSearchPaths []string wantPath string wantSource string wantErrContains string }{ { name: "explicit config path", cliPath: "/tmp/explicit.yml", cliPathSet: true, lookup: func(string) (string, bool) { return "", false }, stat: statFor(map[string]bool{"/tmp/explicit.yml": true}), defaultSearchPaths: []string{ "/usr/local/etc/audita/config.yml", "/etc/audita/config.yml", }, wantPath: "/tmp/explicit.yml", wantSource: "flag", }, { name: "env config path", cliPathSet: false, lookup: func(key string) (string, bool) { if key == "AUDITA_CONFIG" { return "/tmp/from-env.yml", true } return "", false }, stat: statFor(map[string]bool{"/tmp/from-env.yml": true}), defaultSearchPaths: []string{"/usr/local/etc/audita/config.yml", "/etc/audita/config.yml"}, wantPath: "/tmp/from-env.yml", wantSource: "env", }, { name: "default search path", cliPathSet: false, lookup: func(string) (string, bool) { return "", false }, stat: statFor(map[string]bool{ "/usr/local/etc/audita/config.yml": true, "/etc/audita/config.yml": true, }), defaultSearchPaths: []string{"/usr/local/etc/audita/config.yml", "/etc/audita/config.yml"}, wantPath: "/usr/local/etc/audita/config.yml", wantSource: "default", }, { name: "explicit missing path", cliPath: "/tmp/missing.yml", cliPathSet: true, lookup: func(string) (string, bool) { return "", false }, stat: statFor(map[string]bool{}), defaultSearchPaths: []string{ "/usr/local/etc/audita/config.yml", "/etc/audita/config.yml", }, wantErrContains: "config file not found", }, { name: "missing env path", cliPathSet: false, lookup: func(key string) (string, bool) { if key == "AUDITA_CONFIG" { return "/tmp/missing-from-env.yml", true } return "", false }, stat: statFor(map[string]bool{}), defaultSearchPaths: []string{"/usr/local/etc/audita/config.yml", "/etc/audita/config.yml"}, wantErrContains: "config file not found", }, { name: "missing default paths", cliPathSet: false, lookup: func(string) (string, bool) { return "", false }, stat: statFor(map[string]bool{}), defaultSearchPaths: []string{ "/usr/local/etc/audita/config.yml", "/etc/audita/config.yml", }, wantPath: "", wantSource: "", }, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { gotPath, gotSource, err := resolveConfigPathWithLookup(tc.cliPath, tc.cliPathSet, tc.lookup, tc.stat, tc.defaultSearchPaths) if tc.wantErrContains != "" { if err == nil || !strings.Contains(err.Error(), tc.wantErrContains) { t.Fatalf("expected error containing %q, got %v", tc.wantErrContains, err) } return } if err != nil { t.Fatalf("unexpected error: %v", err) } if gotPath != tc.wantPath || gotSource != tc.wantSource { t.Fatalf("unexpected result: got path=%q source=%q, want path=%q source=%q", gotPath, gotSource, tc.wantPath, tc.wantSource) } }) } } func TestLoadEffectiveConfigWithLookupAppliesDefaultsFileThenEnv(t *testing.T) { tempDir := t.TempDir() configPath := filepath.Join(tempDir, "config.yml") configYAML := "version: 1\nllm:\n proposal:\n model: file-model\n" if err := os.WriteFile(configPath, []byte(configYAML), 0o644); err != nil { t.Fatalf("write config file: %v", err) } lookup := func(key string) (string, bool) { switch key { case "AUDITA_CONFIG": return configPath, true case "AUDITA_MODEL": return "env-model", true default: return "", false } } result, err := loadEffectiveConfigWithLookup("", false, lookup, os.Stat, DefaultConfigSearchPaths) if err != nil { t.Fatalf("loadEffectiveConfigWithLookup error: %v", err) } if result.ConfigPath != configPath { t.Fatalf("unexpected config path: %q", result.ConfigPath) } if result.ConfigSource != "env" { t.Fatalf("unexpected config source: %q", result.ConfigSource) } if result.ConfigVersion == nil || *result.ConfigVersion != SupportedFileConfigVersion { t.Fatalf("unexpected config version: %#v", result.ConfigVersion) } if result.Config.PrimaryLLM.Model != "env-model" { t.Fatalf("expected env override to win over file value, got %q", result.Config.PrimaryLLM.Model) } }