Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/vole.git

Write over SSH with a registered key:

git clone ssh://git@rodent.software:2222/vole.git

A free and open-source forge that lives in your Git repo.

Blame · forge/config/config_test.go

Line attribution on main · 146 line(s)

8d336083
Keenan Nemetz
17d ago
1 package config
2
3 import (
4 "os"
5 "path/filepath"
6 "testing"
7 )
8
c36d5073
Keenan Nemetz
16d ago
9 // TestDefaultPathFindsThePerUserInstance is the flow `vole admin init --dir
10 // ~/.vole` promises: later commands find that config without --config.
11 func TestDefaultPathFindsThePerUserInstance(t *testing.T) {
12 home := t.TempDir()
13 t.Setenv("HOME", home)
14 t.Setenv("USERPROFILE", home)
15 t.Setenv("VOLE_CONFIG", "")
16 t.Chdir(t.TempDir())
17
18 if got := DefaultPath(); got != "vole.toml" {
19 t.Fatalf("default path with no instance = %q, want vole.toml", got)
20 }
21
22 homeConfig := filepath.Join(home, ".vole", "vole.toml")
23 if err := os.MkdirAll(filepath.Dir(homeConfig), 0o755); err != nil {
24 t.Fatal(err)
25 }
26 if err := os.WriteFile(homeConfig, []byte("data_dir = \"/tmp/vole-data\"\n"), 0o644); err != nil {
27 t.Fatal(err)
28 }
29 if got := DefaultPath(); got != homeConfig {
30 t.Fatalf("default path = %q, want %q", got, homeConfig)
31 }
32
33 // A config in the working directory belongs to the checkout or instance the
34 // operator is standing in, so it wins over the home instance.
35 if err := os.WriteFile("vole.toml", []byte("data_dir = \"./data\"\n"), 0o644); err != nil {
36 t.Fatal(err)
37 }
38 if got := DefaultPath(); got != "vole.toml" {
39 t.Fatalf("local config did not win: %q", got)
40 }
41
42 // An explicit environment choice wins over both.
43 t.Setenv("VOLE_CONFIG", "/srv/vole/vole.toml")
44 if got := DefaultPath(); got != "/srv/vole/vole.toml" {
45 t.Fatalf("VOLE_CONFIG did not win: %q", got)
46 }
47 }
48
49 // TestResolvePathKeepsExplicitChoice: an empty path means discover, but a named
50 // path must never be silently replaced.
51 func TestResolvePathKeepsExplicitChoice(t *testing.T) {
52 t.Setenv("VOLE_CONFIG", "/from/env.toml")
53 if got := ResolvePath("/explicit/vole.toml"); got != "/explicit/vole.toml" {
54 t.Fatalf("ResolvePath explicit = %q", got)
55 }
56 if got := ResolvePath(""); got != "/from/env.toml" {
57 t.Fatalf("ResolvePath empty = %q", got)
58 }
59 }
60
8d336083
Keenan Nemetz
17d ago
61 // A mistyped TOML tag does not fail anything: the key is simply ignored and the
62 // default applies, which is invisible until somebody's cap does nothing. So the one
63 // setting whose absence is a *silent* policy change is pinned here.
64 func TestMaxJobsPerRepoLoads(t *testing.T) {
44530e74
Keenan Nemetz
17d ago
65 t.Parallel()
8d336083
Keenan Nemetz
17d ago
66 path := filepath.Join(t.TempDir(), "vole.toml")
67 if err := os.WriteFile(path, []byte("max_jobs_per_repo = 3\n"), 0o644); err != nil {
68 t.Fatal(err)
69 }
70 c, err := Load(path)
71 if err != nil {
72 t.Fatal(err)
73 }
74 if c.MaxJobsPerRepo != 3 {
75 t.Fatalf("MaxJobsPerRepo = %d, want 3", c.MaxJobsPerRepo)
76 }
77
78 // Absent means no bound, which is the behaviour before the key existed.
79 unset, err := Load("")
80 if err != nil {
81 t.Fatal(err)
82 }
83 if unset.MaxJobsPerRepo != 0 {
84 t.Fatalf("default = %d, want 0 (no cap)", unset.MaxJobsPerRepo)
85 }
86 }
642e5994
Keenan Nemetz
14d ago
87
88 // Automatic HTTPS is opted into by naming an address; the rest of the settings
89 // only matter once that switch is on, so pin their TOML names as a group.
90 func TestACMESettingsLoad(t *testing.T) {
91 t.Parallel()
92 path := filepath.Join(t.TempDir(), "vole.toml")
93 body := `https_addr = ":443"
94 acme_email = "admin@example.com"
95 acme_domains = ["forge.example.com", "git.example.com"]
96 acme_cache_dir = "/var/lib/vole/acme"
97 acme_directory_url = "https://acme-staging-v02.api.letsencrypt.org/directory"
98 `
99 if err := os.WriteFile(path, []byte(body), 0o644); err != nil {
100 t.Fatal(err)
101 }
102 c, err := Load(path)
103 if err != nil {
104 t.Fatal(err)
105 }
106 if c.HTTPSAddr != ":443" {
107 t.Fatalf("HTTPSAddr = %q", c.HTTPSAddr)
108 }
109 if c.ACMEEmail != "admin@example.com" {
110 t.Fatalf("ACMEEmail = %q", c.ACMEEmail)
111 }
112 if got := len(c.ACMEDomains); got != 2 || c.ACMEDomains[0] != "forge.example.com" {
113 t.Fatalf("ACMEDomains = %v", c.ACMEDomains)
114 }
115 if got := c.ACMECachePath(); got != "/var/lib/vole/acme" {
116 t.Fatalf("ACMECachePath = %q", got)
117 }
118 if c.ACMEDirectoryURL != "https://acme-staging-v02.api.letsencrypt.org/directory" {
119 t.Fatalf("ACMEDirectoryURL = %q", c.ACMEDirectoryURL)
120 }
121 }
4506a4d3
Keenan Nemetz
14d ago
122
123 // Load records whether it actually read a file, so the status page can tell an
124 // operator whether the effective values came from disk or the built-in defaults.
125 func TestLoadRecordsTheSource(t *testing.T) {
126 t.Parallel()
127 path := filepath.Join(t.TempDir(), "vole.toml")
128 if err := os.WriteFile(path, []byte("data_dir = \"/srv/vole\"\n"), 0o644); err != nil {
129 t.Fatal(err)
130 }
131 c, err := Load(path)
132 if err != nil {
133 t.Fatal(err)
134 }
135 if !c.Loaded || c.Path != path {
136 t.Fatalf("loaded config = %+v, want Loaded with path %q", c, path)
137 }
138
139 missing, err := Load(filepath.Join(t.TempDir(), "missing.toml"))
140 if err != nil {
141 t.Fatal(err)
142 }
143 if missing.Loaded {
144 t.Fatal("a missing config file was reported as loaded")
145 }
146 }