config_test.go

  1// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
  2//
  3// SPDX-License-Identifier: LicenseRef-MutuaL-1.2
  4
  5package appconfig
  6
  7import (
  8	"context"
  9	"os"
 10	"path/filepath"
 11	"strings"
 12	"testing"
 13
 14	"git.secluded.site/cooked-mcp/internal/configvalue"
 15)
 16
 17func TestLoadACIDAuthenticationCredentials21ResolvesTOMLConfigValues(t *testing.T) {
 18	t.Setenv("COOKED_USERNAME_FROM_MY_SHELL", "shell-user")
 19
 20	configPath := filepath.Join(t.TempDir(), "config.toml")
 21	writeConfig(t, configPath, `[user]
 22name = "$COOKED_USERNAME_FROM_MY_SHELL"
 23password = "!printf shell-password"
 24`)
 25
 26	got, err := Load(context.Background(), configPath, configvalue.NewResolver())
 27	if err != nil {
 28		t.Fatalf("Load() error = %v", err)
 29	}
 30
 31	if got.Username != "shell-user" {
 32		t.Fatalf("Username = %q, want shell-user", got.Username)
 33	}
 34	if got.Password != "shell-password" {
 35		t.Fatalf("Password = %q, want shell-password", got.Password)
 36	}
 37}
 38
 39func TestLoadACIDAuthenticationCredentials11EnvironmentOverridesTOML(t *testing.T) {
 40	t.Setenv("COOKED_LOGIN_USERNAME", "override-user")
 41	t.Setenv("COOKED_LOGIN_PASSWORD", "override-password")
 42
 43	configPath := filepath.Join(t.TempDir(), "config.toml")
 44	writeConfig(t, configPath, `[user]
 45name = "toml-user"
 46password = "toml-password"
 47`)
 48
 49	got, err := Load(context.Background(), configPath, configvalue.NewResolver())
 50	if err != nil {
 51		t.Fatalf("Load() error = %v", err)
 52	}
 53
 54	if got.Username != "override-user" {
 55		t.Fatalf("Username = %q, want override-user", got.Username)
 56	}
 57	if got.Password != "override-password" {
 58		t.Fatalf("Password = %q, want override-password", got.Password)
 59	}
 60}
 61
 62func TestLoadRejectsMissingExplicitConfigFile(t *testing.T) {
 63	_, err := Load(context.Background(), filepath.Join(t.TempDir(), "missing.toml"), configvalue.NewResolver())
 64	if err == nil {
 65		t.Fatal("Load() error = nil, want missing config error")
 66	}
 67}
 68
 69func TestLoadACIDServerConfig72RejectsMissingDefaultConfigHome(t *testing.T) {
 70	t.Setenv("XDG_CONFIG_HOME", "")
 71
 72	originalUserHomeDir := userHomeDir
 73	userHomeDir = func() (string, error) {
 74		return "", os.ErrNotExist
 75	}
 76	t.Cleanup(func() {
 77		userHomeDir = originalUserHomeDir
 78	})
 79
 80	_, err := Load(context.Background(), "", configvalue.NewResolver())
 81	if err == nil {
 82		t.Fatal("Load() error = nil, want default config path error")
 83	}
 84	if !strings.Contains(err.Error(), "resolve default config path") {
 85		t.Fatalf("Load() error = %v, want default config path error", err)
 86	}
 87}
 88
 89func TestLoadRejectsNonLocalHTTPBaseURL(t *testing.T) {
 90	configPath := filepath.Join(t.TempDir(), "config.toml")
 91	writeConfig(t, configPath, `[user]
 92name = "toml-user"
 93password = "toml-password"
 94
 95[cooked]
 96base_url = "http://example.com"
 97`)
 98
 99	_, err := Load(context.Background(), configPath, configvalue.NewResolver())
100	if err == nil {
101		t.Fatal("Load() error = nil, want non-local HTTP base URL error")
102	}
103	if !strings.Contains(err.Error(), "must use https") {
104		t.Fatalf("Load() error = %v, want https error", err)
105	}
106}
107
108func writeConfig(t *testing.T, path, content string) {
109	t.Helper()
110
111	if err := os.WriteFile(path, []byte(content), 0o600); err != nil {
112		t.Fatalf("write config: %v", err)
113	}
114}