package config import ( "os" "path/filepath" "testing" ) func TestDataDir(t *testing.T) { ResetForTest() t.Setenv("DATA_DIR", "") // default should be data under cwd d := DataDir() if d == "" { t.Fatal("DataDir empty") } // once behavior: change env shouldn't affect without reset t.Setenv("DATA_DIR", "/tmp/should-not-affect") d2 := DataDir() if d != d2 { t.Error("DataDir ignored Once") } ResetForTest() t.Setenv("DATA_DIR", "/tmp/testdata123") d3 := DataDir() if d3 != "/tmp/testdata123" { t.Errorf("DATA_DIR override failed: got %s", d3) } } func TestResolve(t *testing.T) { ResetForTest() tmp := t.TempDir() t.Setenv("DATA_DIR", tmp) tests := []struct { sub string wantBase string // suffix check }{ {"db.bolt", filepath.Join(tmp, "db.bolt")}, {"certs", filepath.Join(tmp, "certs")}, {"logs", filepath.Join(tmp, "logs")}, {"letsencrypt-acme-challenge", filepath.Join(tmp, "letsencrypt-acme-challenge")}, {"www", filepath.Join(tmp, "www")}, {"unknown", filepath.Join(tmp, "unknown")}, } for _, tt := range tests { got := Resolve(tt.sub) if got != tt.wantBase { t.Errorf("Resolve(%q) = %q want %q", tt.sub, got, tt.wantBase) } } // override CERTS_DIR (uses as base + join sub per current impl) ResetForTest() certsBase := filepath.Join(tmp, "mycerts-base") t.Setenv("CERTS_DIR", certsBase) t.Setenv("DATA_DIR", tmp) wantCerts := filepath.Join(certsBase, "certs") if got := Resolve("certs"); got != wantCerts { t.Errorf("CERTS_DIR override: got %s want %s", got, wantCerts) } // WWW_DIR / HTML_DIR (special case returns dir directly; overrides conditioned on exact sub to avoid cross-contamination) ResetForTest() wwwDir := filepath.Join(tmp, "mywww") t.Setenv("WWW_DIR", wwwDir) if got := Resolve("www"); got != wwwDir { t.Errorf("WWW_DIR: got %s", got) } ResetForTest() htmlDir := filepath.Join(tmp, "myhtml") t.Setenv("HTML_DIR", htmlDir) if got := Resolve("html"); got != htmlDir { t.Errorf("HTML_DIR: got %s", got) } // mixed overrides: only HTML set should not affect Resolve("www") (falls to DATA_DIR/www); vice-versa // (explicitly clear the other *_DIR to counter t.Setenv lingering within one TestResolve func) ResetForTest() t.Setenv("WWW_DIR", "") t.Setenv("HTML_DIR", htmlDir) t.Setenv("DATA_DIR", tmp) if got := Resolve("www"); got != filepath.Join(tmp, "www") { t.Errorf("mixed: only HTML should not affect www: got %s", got) } ResetForTest() t.Setenv("HTML_DIR", "") t.Setenv("WWW_DIR", wwwDir) t.Setenv("DATA_DIR", tmp) if got := Resolve("html"); got != filepath.Join(tmp, "html") { t.Errorf("mixed: only WWW should not affect html: got %s", got) } // CHALLENGE_DIR (uses as base + join per impl) ResetForTest() chBase := filepath.Join(tmp, "ch-base") t.Setenv("CHALLENGE_DIR", chBase) wantCh := filepath.Join(chBase, "letsencrypt-acme-challenge") if got := Resolve("letsencrypt-acme-challenge"); got != wantCh { t.Errorf("CHALLENGE: got %s want %s", got, wantCh) } } func TestEnsureDataDirs(t *testing.T) { ResetForTest() tmp := t.TempDir() t.Setenv("DATA_DIR", tmp) if err := EnsureDataDirs(); err != nil { t.Fatalf("EnsureDataDirs: %v", err) } // verify layout dirs := []string{ tmp, filepath.Join(tmp, "certs"), filepath.Join(tmp, "logs"), filepath.Join(tmp, "letsencrypt-acme-challenge"), filepath.Join(tmp, "www"), filepath.Join(tmp, "letsencrypt-acme-challenge", ".well-known", "acme-challenge"), } for _, d := range dirs { if fi, err := os.Stat(d); err != nil || !fi.IsDir() { t.Errorf("expected dir %s: %v", d, err) } } } func TestIsDevelopment(t *testing.T) { ResetForTest() t.Setenv("PROXY_MODE", "") if IsDevelopment() { t.Error("default should be production (not dev)") } t.Setenv("PROXY_MODE", "development") if !IsDevelopment() { t.Error("PROXY_MODE=development should be dev") } t.Setenv("PROXY_MODE", "dev") if !IsDevelopment() { t.Error("PROXY_MODE=dev should be dev") } t.Setenv("PROXY_MODE", "production") if IsDevelopment() { t.Error("PROXY_MODE=production should not be dev") } // case insensitive t.Setenv("PROXY_MODE", "DEVELOPMENT") if !IsDevelopment() { t.Error("case insensitive") } }