163 lines
4.7 KiB
Go
163 lines
4.7 KiB
Go
package config
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestSavePersistsRelativePaths(t *testing.T) {
|
|
root := t.TempDir()
|
|
cfg := defaults(root)
|
|
cfg.Initialized = true
|
|
cfg.ConfigPath = filepath.Join(root, "config.json")
|
|
|
|
if err := Save(cfg); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
data, err := os.ReadFile(filepath.Join(root, "config.json"))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var saved Config
|
|
if err := json.Unmarshal(data, &saved); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if saved.BaseDir != "." {
|
|
t.Fatalf("BaseDir = %q, want relative dot", saved.BaseDir)
|
|
}
|
|
for name, value := range map[string]string{
|
|
"storage_dir": saved.StorageDir,
|
|
"data_dir": saved.DataDir,
|
|
"update_public_dir": saved.UpdatePublicDir,
|
|
"update_notice_dir": saved.UpdateNoticeDir,
|
|
"downloads_dir": saved.DownloadsDir,
|
|
"sqlite_path": saved.Database.SQLitePath,
|
|
} {
|
|
if filepath.IsAbs(value) || strings.Contains(value, root) {
|
|
t.Fatalf("%s saved as absolute path %q", name, value)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestPreflightCreatesRuntimeDirectoriesAndNoticeIndex(t *testing.T) {
|
|
root := t.TempDir()
|
|
cfg := defaults(root)
|
|
checks := Preflight(cfg)
|
|
for _, path := range []string{
|
|
cfg.UpdatePublicDir,
|
|
cfg.UpdateNoticeDir,
|
|
cfg.DownloadsDir,
|
|
filepath.Join(cfg.UpdatePublicDir, "update-info.json"),
|
|
filepath.Join(cfg.UpdatePublicDir, "media-types.json"),
|
|
filepath.Join(cfg.UpdateNoticeDir, "total.json"),
|
|
} {
|
|
if _, err := os.Stat(path); err != nil {
|
|
t.Fatalf("expected preflight to create %s: %v", path, err)
|
|
}
|
|
}
|
|
for _, line := range FormatPreflight(cfg, checks) {
|
|
if strings.Contains(line, root) {
|
|
t.Fatalf("preflight line leaked absolute base path: %s", line)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestLoadRewritesAbsoluteConfigPaths(t *testing.T) {
|
|
root := t.TempDir()
|
|
t.Setenv("YMHUT_BASE_DIR", root)
|
|
configPath := filepath.Join(root, "config.json")
|
|
payload := map[string]any{
|
|
"initialized": true,
|
|
"listen": ":33550",
|
|
"storage_dir": filepath.Join(root, "storage"),
|
|
"data_dir": filepath.Join(root, "data"),
|
|
"update_public_dir": filepath.Join(root, "data", "update", "public"),
|
|
"update_notice_dir": filepath.Join(root, "data", "update-notice"),
|
|
"downloads_dir": filepath.Join(root, "data", "update", "public", "downloads"),
|
|
"database": map[string]any{
|
|
"provider": "sqlite",
|
|
"sqlite_path": filepath.Join(root, "storage", "unified.sqlite"),
|
|
},
|
|
}
|
|
data, err := json.Marshal(payload)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(configPath, data, 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := Load(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
rewritten, err := os.ReadFile(configPath)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if strings.Contains(string(rewritten), root) {
|
|
t.Fatalf("config still contains absolute base path: %s", string(rewritten))
|
|
}
|
|
}
|
|
|
|
func TestReleaseUploadLimitCanBeConfiguredFromEnvironment(t *testing.T) {
|
|
t.Setenv("YMHUT_RELEASE_UPLOAD_MAX_BYTES", "67108864")
|
|
cfg := defaults(t.TempDir())
|
|
applyEnv(cfg)
|
|
normalize(cfg.BaseDir, cfg)
|
|
if cfg.ReleaseUploadMaxBytes != 64*1024*1024 {
|
|
t.Fatalf("ReleaseUploadMaxBytes = %d, want %d", cfg.ReleaseUploadMaxBytes, 64*1024*1024)
|
|
}
|
|
}
|
|
|
|
func TestAdminAssetModeCanBeConfiguredFromEnvironment(t *testing.T) {
|
|
t.Setenv("YMHUT_ADMIN_ASSET_MODE", "embedded")
|
|
cfg := defaults(t.TempDir())
|
|
applyEnv(cfg)
|
|
normalize(cfg.BaseDir, cfg)
|
|
if cfg.AdminAssetMode != "embedded" {
|
|
t.Fatalf("AdminAssetMode = %q, want embedded", cfg.AdminAssetMode)
|
|
}
|
|
|
|
t.Setenv("YMHUT_ADMIN_ASSET_MODE", "invalid")
|
|
applyEnv(cfg)
|
|
normalize(cfg.BaseDir, cfg)
|
|
if cfg.AdminAssetMode != defaultAdminAssetMode() {
|
|
t.Fatalf("invalid AdminAssetMode normalized to %q, want %q", cfg.AdminAssetMode, defaultAdminAssetMode())
|
|
}
|
|
}
|
|
|
|
func TestPreflightReportsMissingAdminAssetName(t *testing.T) {
|
|
root := t.TempDir()
|
|
cfg := defaults(root)
|
|
cfg.AdminAssetMode = "disk"
|
|
if err := os.MkdirAll(filepath.Join(cfg.AdminWebDir, "assets"), 0o755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(
|
|
filepath.Join(cfg.AdminWebDir, "index.html"),
|
|
[]byte(`<script type="module" src="/admin/assets/missing.js"></script>`),
|
|
0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(filepath.Join(cfg.AdminWebDir, "admin-build.json"), []byte(`{"buildId":"dev"}`), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(filepath.Join(cfg.AdminWebDir, "asset-manifest.json"), []byte(`{"src/main.ts":{"file":"assets/missing.js","isEntry":true}}`), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
checks := Preflight(cfg)
|
|
admin := checks[0]
|
|
for _, check := range checks {
|
|
if check.Name == "admin web dist" {
|
|
admin = check
|
|
break
|
|
}
|
|
}
|
|
if !strings.Contains(admin.Message, "assets/missing.js") {
|
|
t.Fatalf("admin preflight message = %q, want missing asset name", admin.Message)
|
|
}
|
|
}
|