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}