package config import ( "os" "path/filepath" "strings" "testing" ) func writeFile(t *testing.T, mode os.FileMode, content string) string { t.Helper() dir := t.TempDir() path := filepath.Join(dir, "env") if err := os.WriteFile(path, []byte(content), mode); err != nil { t.Fatal(err) } if err := os.Chmod(path, mode); err != nil { // umask may have tightened t.Fatal(err) } return path } func clearEnv(t *testing.T) { t.Helper() for _, k := range []string{KeyServerURL, KeyAccessToken, KeyClientID, KeyClientSecret} { t.Setenv(k, "") os.Unsetenv(k) } } func TestLoadFromEnvFile(t *testing.T) { clearEnv(t) path := writeFile(t, 0o600, "# comment\nBW_SERVER_URL=https://vault.example.com\nBW_ACCESS_TOKEN='0.uuid.secret:key=='\n") cfg, _, err := Load(path) if err != nil { t.Fatalf("load: %v", err) } if cfg.ServerURL != "https://vault.example.com" { t.Fatalf("server url: %s", cfg.ServerURL) } if cfg.AccessToken != "0.uuid.secret:key==" { t.Fatalf("access token: %s", cfg.AccessToken) } } func TestLoadRefusesLooseMode(t *testing.T) { clearEnv(t) path := writeFile(t, 0o644, "BW_ACCESS_TOKEN=x\n") _, _, err := Load(path) if err == nil { t.Fatal("loose file accepted") } if !strings.Contains(err.Error(), "insecure mode") { t.Fatalf("wrong error: %v", err) } } func TestLoadRefusesEvenLooserBeforeReading(t *testing.T) { clearEnv(t) // 0644 file whose contents would break parsing: the mode check must // fire first (the parse error is never reached, contents never read). path := writeFile(t, 0o666, "this is not valid at all\n") _, _, err := Load(path) if err == nil || !strings.Contains(err.Error(), "insecure mode") { t.Fatalf("mode check did not fire first: %v", err) } } func TestLoadStricterThan0600OK(t *testing.T) { clearEnv(t) path := writeFile(t, 0o400, "BW_CLIENTID=id\nBW_CLIENTSECRET=sec\n") cfg, _, err := Load(path) if err != nil { t.Fatalf("load: %v", err) } if cfg.ClientID != "id" || cfg.ClientSecret != "sec" { t.Fatal("split credentials not loaded") } } func TestEnvWinsOverFile(t *testing.T) { clearEnv(t) path := writeFile(t, 0o600, "BW_ACCESS_TOKEN=file-token\n") t.Setenv("BW_ACCESS_TOKEN", "env-token") cfg, _, err := Load(path) if err != nil { t.Fatalf("load: %v", err) } if cfg.AccessToken != "env-token" { t.Fatal("env did not win over file") } } func TestNoCredentialsIsTypedError(t *testing.T) { clearEnv(t) _, _, err := Load("") if err == nil { t.Fatal("missing credentials accepted") } if !strings.Contains(err.Error(), "no credentials") { t.Fatalf("wrong error: %v", err) } } func TestMissingFileOK(t *testing.T) { clearEnv(t) // Env credentials plus an explicit-but-missing file path: the file is // simply not there to consult; env carries the login. t.Setenv("BW_CLIENTID", "id") t.Setenv("BW_CLIENTSECRET", "sec") path := writeFile(t, 0o600, "BW_CLIENTID=id\nBW_CLIENTSECRET=sec\n") cfg, _, err := Load(path + "-does-not-exist") if err != nil { t.Fatalf("explicit missing file: %v", err) } if cfg.ServerURL != DefaultServerURL { t.Fatalf("default server url: %s", cfg.ServerURL) } } func TestParseEnvFileDiscipline(t *testing.T) { vals, err := parseEnvFile([]byte("\n# c\nexport BW_A=1\nBW_B = spaced \nBW_C=\"quoted\"\nBW_C=later-wins\nBW_D=val # trailing comment\n")) if err != nil { t.Fatalf("parse: %v", err) } want := map[string]string{"BW_A": "1", "BW_B": "spaced", "BW_C": "later-wins", "BW_D": "val"} for k, v := range want { if vals[k] != v { t.Fatalf("%s: %q != %q", k, vals[k], v) } } _, err = parseEnvFile([]byte("BAD LINE WITHOUT EQUALS\n")) if err == nil || !strings.Contains(err.Error(), "line 1") { t.Fatalf("malformed line error: %v", err) } if strings.Contains(err.Error(), "BAD LINE") { t.Fatalf("error echoes file contents: %v", err) } }