package config import ( "encoding/json" "errors" "fmt" "os" "strings" "sync" "testing" "time" ) type referenceConfig struct { Port int `json:"port"` BatchSize int `json:"batchSize"` Enabled bool `json:"enabled"` Password string `json:"password"` Address string `json:"address"` Timeout time.Duration `json:"timeout"` Optional *int `json:"optional"` Labels map[string]string `json:"labels"` Numbers []int64 `json:"numbers"` Dynamic any `json:"dynamic"` } func (c referenceConfig) Validate() error { if c.Port < 0 { return Invalid("port", "must not be negative") } return nil } func TestExplicitReferencesAcrossFormats(t *testing.T) { // Delimiters, quotes and newlines belong to the credential, never file syntax. secret := " DDSFLKJlsf:saf:-123\"\n${DO_NOT_READ}&<>\\ " sources := map[string]string{ "json": `{"port":"${PORT:-3306}","enabled":"${ENABLED:-true}","password":"${PASSWORD}","address":"https://${HOST}:${PORT:-3306}/v1","timeout":"${TIMEOUT:-3s}","optional":"${ZERO}","numbers":["${BIG}"],"dynamic":"${ZERO}","labels":{"literal":"$${NOT_READ}","empty":"${OPTIONAL:-}","dollars":"$$cost"}}`, "yaml": "port: \"${PORT:-3306}\"\nenabled: \"${ENABLED:-true}\"\npassword: \"${PASSWORD}\"\naddress: \"https://${HOST}:${PORT:-3306}/v1\"\ntimeout: \"${TIMEOUT:-3s}\"\noptional: \"${ZERO}\"\nnumbers: [\"${BIG}\"]\ndynamic: \"${ZERO}\"\nlabels:\n literal: \"$${NOT_READ}\"\n empty: \"${OPTIONAL:-}\"\n dollars: \"$$cost\"\n", "xml": `${PORT:-3306}${ENABLED:-true}${PASSWORD}
https://${HOST}:${PORT:-3306}/v1
${TIMEOUT:-3s}${ZERO}${BIG}${ZERO}$${NOT_READ}${OPTIONAL:-}$$cost
`, } for ext, source := range sources { t.Run(ext, func(t *testing.T) { calls := map[string]int{} values := map[string]string{"PORT": "0", "ENABLED": "false", "PASSWORD": secret, "HOST": "example.test", "ZERO": "0", "BIG": "9007199254740993"} l := testLoader(func(name string) (string, bool) { calls[name]++; v, ok := values[name]; return v, ok }) got, err := LoadProject(configFile(t, ext, source), referenceConfig{Port: 77, BatchSize: 100, Enabled: true, Password: "old"}, l) if err != nil { t.Fatal(err) } if got.Port != 0 || got.BatchSize != 100 || got.Enabled || got.Password != secret || got.Address != "https://example.test:0/v1" || got.Timeout != 3*time.Second || got.Optional == nil || *got.Optional != 0 || got.Numbers[0] != 9007199254740993 || got.Dynamic != "0" { t.Fatal("binding changed values") } if got.Labels["literal"] != "${NOT_READ}" || got.Labels["empty"] != "" || got.Labels["dollars"] != "$cost" { t.Fatal(got.Labels) } for name, n := range calls { if n != 1 { t.Fatal("not cached", name, n) } } if calls["DO_NOT_READ"] != 0 || calls["NOT_READ"] != 0 { t.Fatal("recursive expansion") } }) } } func TestReferenceFallbackAndFixedValues(t *testing.T) { for _, present := range []bool{false, true} { l := testLoader(func(string) (string, bool) { return "", present }) got, err := LoadProject(configFile(t, "yaml", "port: \"${PORT:-3306}\"\npassword: \"${PASSWORD:-DDSFLKJlsf:saf:-123}\""), referenceConfig{}, l) if err != nil || got.Port != 3306 || got.Password != "DDSFLKJlsf:saf:-123" { t.Fatal(got, err) } for _, ext := range []string{"json", "yaml", "xml"} { raw := `{"password":"${PASSWORD}"}` if ext == "yaml" { raw = "password: '${PASSWORD}'" } if ext == "xml" { raw = "${PASSWORD}" } path := configFile(t, ext, raw) _, err = LoadProject(path, referenceConfig{Password: "initial"}, l) var d *Error if !errors.As(err, &d) || d.Env != "PASSWORD" || d.File != path || d.Field != "password" || d.Line < 1 { t.Fatal("missing required-reference diagnostic", err) } } } calls := 0 l := testLoader(func(string) (string, bool) { calls++; return "999", true }) got, err := LoadProject(configFile(t, "json", `{"port":0,"enabled":false,"password":""}`), referenceConfig{Port: 77, BatchSize: 100, Enabled: true, Password: "old"}, l) if err != nil || got.Port != 0 || got.BatchSize != 100 || got.Enabled || got.Password != "" || calls != 0 { t.Fatal(got, err, calls) } got, err = LoadProject(configFile(t, "yaml", "password: '${VALUE}'"), referenceConfig{}, testLoader(func(string) (string, bool) { return " ", true })) if err != nil || got.Password != " " { t.Fatal("trimmed credential", err) } } func TestReferenceDiagnosticsAndScalarLimits(t *testing.T) { for _, value := range []string{"private-not-int", "92233720368547758080", "false", "null", "-1"} { path := configFile(t, "yaml", "port: '${PORT}'") _, err := LoadProject(path, referenceConfig{}, testLoader(func(string) (string, bool) { return value, true })) var d *Error if !errors.As(err, &d) || d.File != path || d.Env != "PORT" || d.Field != "port" || d.Line != 1 || d.Column < 1 || strings.Contains(err.Error(), value) { t.Fatalf("invalid diagnostic: %v", err) } } for _, raw := range []string{"${BAD-123}", "${}", "${X", "${1BAD}", "${BAD NAME}", "${X:-${Y}}"} { encoded, _ := json.Marshal(map[string]string{"password": raw}) if _, err := LoadProject(configFile(t, "json", string(encoded)), referenceConfig{}, testLoader(noEnvironment)); err == nil { t.Fatal("invalid syntax accepted", raw) } } for _, value := range []string{string([]byte{0xff}), strings.Repeat("x", maxConfigBytes+1)} { if _, err := LoadProject(configFile(t, "yaml", "password: '${SECRET}'"), referenceConfig{}, testLoader(func(string) (string, bool) { return value, true })); err == nil { t.Fatal("unbounded/invalid environment") } } path := configFile(t, "yaml", "labels:\n a: '${BIG}'\n b: '${BIG}'\n c: '${BIG}'\n d: '${BIG}'\n e: '${BIG}'") if _, err := LoadProject(path, referenceConfig{}, testLoader(func(string) (string, bool) { return strings.Repeat("x", maxConfigBytes), true })); err == nil { t.Fatal("expansion budget bypassed") } // An environment value cannot inject an array/object or coerce dynamic null. for _, raw := range []string{"[1,2]", "{\"x\":1}", "null"} { _, err := LoadProject(configFile(t, "yaml", "numbers: '${VALUE}'"), referenceConfig{}, testLoader(func(string) (string, bool) { return raw, true })) if err == nil { t.Fatal("structure injected") } } } func TestReferenceCacheIsolationAndRemovedRules(t *testing.T) { path := configFile(t, "yaml", "password: '${TOKEN}'") for i := 0; i < 24; i++ { t.Run(fmt.Sprint(i), func(t *testing.T) { t.Parallel() v := fmt.Sprint(i) l := testLoader(func(string) (string, bool) { return v, true }) for n := 0; n < 4; n++ { got, err := LoadProject(path, referenceConfig{}, l) if err != nil || got.Password != v { t.Fatal("load leaked", err) } } }) } } func TestReferenceLookupPerLoadAndConcurrentLoader(t *testing.T) { var mu sync.Mutex reads := 0 l := testLoader(func(string) (string, bool) { mu.Lock(); defer mu.Unlock(); reads++; return "secret", true }) path := configFile(t, "yaml", "password: '${TOKEN}${TOKEN}'") var wg sync.WaitGroup for i := 0; i < 24; i++ { wg.Add(1) go func() { defer wg.Done() got, err := LoadProject(path, referenceConfig{}, l) if err != nil || got.Password != "secretsecret" { t.Error(err) } }() } wg.Wait() if reads != 24 { t.Fatal(reads) } } func TestRemovedEnvTagsAndFieldSuggestion(t *testing.T) { type old struct { Value int `json:"value" envDefault:"9"` } if _, err := LoadProject("", old{}); err == nil || !strings.Contains(err.Error(), "removed") { t.Fatal(err) } type oldSecret struct { Token string `json:"-" env:"TOKEN"` } if _, err := DecodeFile(configFile(t, "json", `{}`), oldSecret{}); err == nil { t.Fatal("old env tag ignored") } _, err := LoadProject(configFile(t, "yaml", "batchSiz: 10"), referenceConfig{}) if err == nil || !strings.Contains(err.Error(), `did you mean "batchSize"`) { t.Fatal(err) } t.Setenv("GO_OMNI_BATCH_SIZE", "999") got, err := LoadProject("", referenceConfig{BatchSize: 100}) if err != nil || got.BatchSize != 100 { t.Fatal("implicit overlay", err) } } func FuzzConfigurationReferences(f *testing.F) { for _, s := range []string{"${X}", "$${X}", "${X:-DDS:abc:-123}", "${X:-}", "https://${X}/${X}", "${X:-${Y}}"} { f.Add(s, " secret${NO}\n\" ") } f.Fuzz(func(t *testing.T, raw, value string) { if len(raw) > 8192 || len(value) > 8192 { return } doc := Document{Value: map[string]any{"password": raw}} resolved, err := resolveDocument(doc, func(string) (string, bool) { return value, true }) if err != nil { return } _, _ = bindDocument(resolved, referenceConfig{}) }) } func BenchmarkExplicitConfiguration(b *testing.B) { for _, refs := range []bool{false, true} { b.Run(fmt.Sprint(refs), func(b *testing.B) { source := `{"port":3306,"enabled":false,"password":"fixed","batchSize":0}` if refs { source = `{"port":"${PORT:-3306}","enabled":"${ENABLED:-false}","password":"${PASSWORD}","batchSize":0}` } path := b.TempDir() + "/config.json" if err := os.WriteFile(path, []byte(source), 0600); err != nil { b.Fatal(err) } l := testLoader(func(k string) (string, bool) { return "private", k == "PASSWORD" }) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { if _, err := LoadProject(path, referenceConfig{BatchSize: 100}, l); err != nil { b.Fatal(err) } } }) } }