// This test file verifies that YAML syntax allows unquoted interpolation markers. // // Key findings: // - YAML treats unquoted ${...} expressions as string values // - Users can write interpolations without quotes (e.g., port: ${ENV:PORT}) // - Even complex shell commands with special characters work unquoted // - This confirms our design approach: parse YAML first, then walk string values // looking for interpolation patterns // // This means users have explicit control over types: // - port: ${ENV:PORT} # We can return a number if ENV:PORT="8080" // - port: "${ENV:PORT}" # Always returns a string // - enabled: ${ENV:ENABLED} # We can return a boolean if ENV:ENABLED="true" package smartconfig import ( "testing" "gopkg.in/yaml.v3" ) func TestYAMLInterpolationSyntax(t *testing.T) { testCases := []struct { name string yaml string shouldParse bool desc string }{ { name: "unquoted interpolation for number", yaml: `port: ${ENV:PORT}`, shouldParse: true, desc: "Users should be able to use interpolation without quotes to get numbers", }, { name: "unquoted interpolation for boolean", yaml: `enabled: ${ENV:ENABLED}`, shouldParse: true, desc: "Users should be able to use interpolation without quotes to get booleans", }, { name: "interpolation with special shell chars", yaml: `command: ${EXEC:cat /etc/hosts | grep localhost}`, shouldParse: true, desc: "Special shell characters should work unquoted", }, { name: "interpolation with redirect", yaml: `output: ${EXEC:echo hello > /tmp/test}`, shouldParse: true, desc: "Shell redirects should work unquoted", }, { name: "complex exec with special chars", yaml: `data: ${EXEC:awk '{print $1}' /etc/passwd}`, shouldParse: true, // YAML treats the whole expression as a string desc: "Complex commands with quotes work unquoted", }, { name: "nested interpolation unquoted", yaml: `value: ${ENV:PREFIX_${ENV:SUFFIX}}`, shouldParse: true, desc: "Nested interpolations should work unquoted", }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { var data map[string]interface{} err := yaml.Unmarshal([]byte(tc.yaml), &data) if tc.shouldParse && err != nil { t.Errorf("%s - expected to parse but got error: %v", tc.desc, err) } else if !tc.shouldParse && err == nil { t.Errorf("%s - expected parse error but succeeded", tc.desc) } if err == nil { for key, value := range data { t.Logf("%s: %v (type: %T)", key, value, value) } } }) } }