textmachine/backend/cmd/tmctl/dotenv_test.go

51 lines
1.8 KiB
Go

package main
import (
"os"
"path/filepath"
"reflect"
"strings"
"testing"
)
// dotenv_test.go pins the .env parsing rules that used to live only in comments:
// paired quotes (a regression «simplifying to strings.Trim» would corrupt API keys and
// surface as 401s mid-run) and «do not override an already-set environment».
func TestParseDotEnvPairedQuotes(t *testing.T) {
in := strings.Join([]string{
`A="v1"`, // paired double quotes — strip
`B='v2'`, // paired single quotes — strip
`C="v3'`, // MISMATCHED quotes — leave alone
`D=v4"`, // trailing quote with no pair — keep (the main regression case)
`E="`, // single quote (n<2) — keep
`F=""`, // empty pair — empty string
` G = v7 `, // trim key and value
`# comment`, // comment — skip
``, // empty — skip
`no-equals-line`, // no «=» — skip
}, "\n")
got := parseDotEnv(strings.NewReader(in))
want := []dotenvPair{
{"A", "v1"}, {"B", "v2"}, {"C", `"v3'`}, {"D", `v4"`}, {"E", `"`}, {"F", ""}, {"G", "v7"},
}
if !reflect.DeepEqual(got, want) {
t.Fatalf("parseDotEnv:\n got %+v\n want %+v", got, want)
}
}
func TestLoadDotEnvDoesNotOverride(t *testing.T) {
path := filepath.Join(t.TempDir(), ".env")
if err := os.WriteFile(path, []byte("TM_TEST_SET=from_file\nTM_TEST_UNSET=filled\n"), 0o600); err != nil {
t.Fatal(err)
}
t.Setenv("TM_TEST_SET", "from_env")
t.Setenv("TM_TEST_UNSET", "") // set to EMPTY counts as unset (frozen behaviour)
loadDotEnv(path)
if got := os.Getenv("TM_TEST_SET"); got != "from_env" {
t.Fatalf("an already-set variable must win over .env, got %q", got)
}
if got := os.Getenv("TM_TEST_UNSET"); got != "filled" {
t.Fatalf("an empty variable is treated as unset (frozen behaviour), got %q", got)
}
}