]> git.giacomolli.uk - onechat/blob - config_test.go
Require field names in struct literals
[onechat] / config_test.go
1 package main
2
3 import (
4 "os"
5 "path/filepath"
6 "testing"
7
8 "github.com/stretchr/testify/require"
9 )
10
11 func TestLoadConfigGivesDefaultsWithoutAFile(t *testing.T) {
12 dir := t.TempDir()
13 config, err := loadConfig(dir)
14 require.NoError(t, err)
15 require.Equal(t, defaultConfig(), config)
16 require.NoFileExists(t, filepath.Join(dir, "config.json"))
17 }
18
19 func TestLoadConfigKeepsDefaultsForMissingFields(t *testing.T) {
20 dir := t.TempDir()
21 writeConfig(t, dir, `{"endpoint": "api", "compactor": {"effort": "xhigh"}}`)
22
23 config, err := loadConfig(dir)
24 require.NoError(t, err)
25 require.Equal(t, Config{
26 Endpoint: endpointAPI,
27 Compactor: ModelConfig{
28 Model: "gpt-6-luna",
29 Effort: "xhigh",
30 },
31 }, config)
32 }
33
34 func TestLoadConfigRejectsInvalidFiles(t *testing.T) {
35 testCases := []struct {
36 name string
37 text string
38 }{
39 {"unknown field", `{"endpont": "api"}`},
40 {"unknown nested field", `{"compactor": {"modle": "x"}}`},
41 {"endpoint URL", `{"endpoint": "https://example.com/v1/responses"}`},
42 {"empty model", `{"compactor": {"model": ""}}`},
43 {"second object", `{} {}`},
44 {"broken JSON", `{"endpoint": `},
45 }
46
47 for _, tc := range testCases {
48 t.Run(tc.name, func(t *testing.T) {
49 dir := t.TempDir()
50 writeConfig(t, dir, tc.text)
51
52 _, err := loadConfig(dir)
53 require.Error(t, err)
54 })
55 }
56 }
57
58 func TestDataDirFollowsTheOrder(t *testing.T) {
59 root := t.TempDir()
60 testCases := []struct {
61 name string
62 dir string
63 xdg string
64 home string
65 want string
66 }{
67 {"ONECHAT_DIR first", filepath.Join(root, "a"), filepath.Join(root, "xdg"), root, filepath.Join(root, "a")},
68 {"absolute XDG_DATA_HOME", "", filepath.Join(root, "xdg"), root, filepath.Join(root, "xdg", "onechat")},
69 {"relative XDG_DATA_HOME ignored", "", "xdg", root, filepath.Join(root, ".local", "share", "onechat")},
70 {"home directory last", "", "", root, filepath.Join(root, ".local", "share", "onechat")},
71 }
72
73 for _, tc := range testCases {
74 t.Run(tc.name, func(t *testing.T) {
75 t.Setenv("ONECHAT_DIR", tc.dir)
76 t.Setenv("XDG_DATA_HOME", tc.xdg)
77 t.Setenv("HOME", tc.home)
78
79 dir, err := dataDir()
80 require.NoError(t, err)
81 require.Equal(t, tc.want, dir)
82
83 info, err := os.Stat(dir)
84 require.NoError(t, err)
85 require.Equal(t, os.FileMode(0o700), info.Mode().Perm())
86 })
87 }
88 }
89
90 func TestDataDirFailsWithoutAHome(t *testing.T) {
91 t.Setenv("ONECHAT_DIR", "")
92 t.Setenv("XDG_DATA_HOME", "")
93 t.Setenv("HOME", "")
94
95 _, err := dataDir()
96 require.ErrorContains(t, err, "ONECHAT_DIR")
97 }
98
99 func writeConfig(t *testing.T, dir, text string) {
100 t.Helper()
101
102 err := os.WriteFile(filepath.Join(dir, "config.json"), []byte(text), 0o600)
103 require.NoError(t, err)
104 }