]> git.giacomolli.uk - onechat/blob - config_test.go
Send the compaction view in blocks of four lines
[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.1-sol",
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 {
40 name: "unknown field",
41 text: `{"endpont": "api"}`,
42 },
43 {
44 name: "unknown nested field",
45 text: `{"compactor": {"modle": "x"}}`,
46 },
47 {
48 name: "endpoint URL",
49 text: `{"endpoint": "https://example.com/v1/responses"}`,
50 },
51 {
52 name: "empty model",
53 text: `{"compactor": {"model": ""}}`,
54 },
55 {
56 name: "second object",
57 text: `{} {}`,
58 },
59 {
60 name: "broken JSON",
61 text: `{"endpoint": `,
62 },
63 }
64
65 for _, tc := range testCases {
66 t.Run(tc.name, func(t *testing.T) {
67 dir := t.TempDir()
68 writeConfig(t, dir, tc.text)
69
70 _, err := loadConfig(dir)
71 require.Error(t, err)
72 })
73 }
74 }
75
76 func TestDataDirFollowsTheOrder(t *testing.T) {
77 root := t.TempDir()
78 testCases := []struct {
79 name string
80 dir string
81 xdg string
82 home string
83 want string
84 }{
85 {
86 name: "ONECHAT_DIR first",
87 dir: filepath.Join(root, "a"),
88 xdg: filepath.Join(root, "xdg"),
89 home: root,
90 want: filepath.Join(root, "a"),
91 },
92 {
93 name: "absolute XDG_DATA_HOME",
94 dir: "",
95 xdg: filepath.Join(root, "xdg"),
96 home: root,
97 want: filepath.Join(root, "xdg", "onechat"),
98 },
99 {
100 name: "relative XDG_DATA_HOME ignored",
101 dir: "",
102 xdg: "xdg",
103 home: root,
104 want: filepath.Join(root, ".local", "share", "onechat"),
105 },
106 {
107 name: "home directory last",
108 dir: "",
109 xdg: "",
110 home: root,
111 want: filepath.Join(root, ".local", "share", "onechat"),
112 },
113 }
114
115 for _, tc := range testCases {
116 t.Run(tc.name, func(t *testing.T) {
117 t.Setenv("ONECHAT_DIR", tc.dir)
118 t.Setenv("XDG_DATA_HOME", tc.xdg)
119 t.Setenv("HOME", tc.home)
120
121 dir, err := dataDir()
122 require.NoError(t, err)
123 require.Equal(t, tc.want, dir)
124
125 info, err := os.Stat(dir)
126 require.NoError(t, err)
127 require.Equal(t, os.FileMode(0o700), info.Mode().Perm())
128 })
129 }
130 }
131
132 func TestDataDirFailsWithoutAHome(t *testing.T) {
133 t.Setenv("ONECHAT_DIR", "")
134 t.Setenv("XDG_DATA_HOME", "")
135 t.Setenv("HOME", "")
136
137 _, err := dataDir()
138 require.ErrorContains(t, err, "ONECHAT_DIR")
139 }
140
141 func writeConfig(t *testing.T, dir, text string) {
142 t.Helper()
143
144 err := os.WriteFile(filepath.Join(dir, "config.json"), []byte(text), 0o600)
145 require.NoError(t, err)
146 }