internal/config/config_test.go
121 lines · 2743 bytes
1package config
2
3import (
4 "os"
5 "path/filepath"
6 "strings"
7 "testing"
8)
9
10func writeConfig(t *testing.T, body string) string {
11 t.Helper()
12 p := filepath.Join(t.TempDir(), "config.toml")
13 if err := os.WriteFile(p, []byte(body), 0o600); err != nil {
14 t.Fatal(err)
15 }
16 return p
17}
18
19const minimal = `
20[server]
21root = "/var/lib/forge"
22site_url = "https://forge.example"
23`
24
25func TestLoadMinimal(t *testing.T) {
26 cfg, err := Load(writeConfig(t, minimal))
27 if err != nil {
28 t.Fatal(err)
29 }
30 // Defaults applied.
31 if cfg.SSH.Mode != "embedded" || cfg.SSH.Port != 22 {
32 t.Errorf("ssh defaults wrong: %+v", cfg.SSH)
33 }
34 if cfg.Web.Mode != "view_only" {
35 t.Errorf("web default wrong: %+v", cfg.Web)
36 }
37 if cfg.Registration.Mode != "closed" {
38 t.Errorf("registration default wrong: %+v", cfg.Registration)
39 }
40}
41
42func TestContradictions(t *testing.T) {
43 cases := []struct {
44 name string
45 body string
46 wantErr string
47 }{
48 {
49 "registration open without smtp",
50 minimal + "\n[registration]\nmode = \"open\"\n",
51 "requires [mail] smtp_host",
52 },
53 {
54 "system ssh with open registration",
55 minimal + "\n[ssh]\nmode = \"system\"\n[registration]\nmode = \"open\"\n[mail]\nsmtp_host = \"mx.example\"\nfrom = \"forge@example\"\n",
56 "requires registration.mode = \"closed\"",
57 },
58 {
59 "password auth in view_only",
60 minimal + "\n[web]\nmode = \"view_only\"\npassword_auth = true\n",
61 "password_auth",
62 },
63 {
64 "bad ssh mode",
65 minimal + "\n[ssh]\nmode = \"tcp\"\n",
66 "ssh.mode",
67 },
68 {
69 "unknown key",
70 "[server]\nroot = \"/var/lib/forge\"\nsite_url = \"https://forge.example\"\nbogus = 1\n",
71 "unknown config key",
72 },
73 {
74 "missing site_url",
75 "[server]\nroot = \"/var/lib/forge\"\n",
76 "site_url",
77 },
78 }
79 for _, tc := range cases {
80 t.Run(tc.name, func(t *testing.T) {
81 _, err := Load(writeConfig(t, tc.body))
82 if err == nil {
83 t.Fatalf("expected error containing %q, got nil", tc.wantErr)
84 }
85 if !strings.Contains(err.Error(), tc.wantErr) {
86 t.Fatalf("error %q does not contain %q", err, tc.wantErr)
87 }
88 })
89 }
90}
91
92func TestValidCombinations(t *testing.T) {
93 cases := []struct {
94 name string
95 body string
96 }{
97 {
98 "invite with smtp",
99 minimal + "\n[registration]\nmode = \"invite\"\n[mail]\nsmtp_host = \"mx.example\"\nfrom = \"forge@example\"\n",
100 },
101 {
102 "system ssh closed registration",
103 minimal + "\n[ssh]\nmode = \"system\"\n",
104 },
105 {
106 "accounts web with password auth",
107 minimal + "\n[web]\nmode = \"accounts\"\npassword_auth = true\n",
108 },
109 {
110 "closed registration, no smtp at all",
111 minimal,
112 },
113 }
114 for _, tc := range cases {
115 t.Run(tc.name, func(t *testing.T) {
116 if _, err := Load(writeConfig(t, tc.body)); err != nil {
117 t.Fatal(err)
118 }
119 })
120 }
121}