package config import ( "testing" ) func TestNewDefaultsToSQLite(t *testing.T) { t.Setenv("FCB_DB_DRIVER", "") t.Setenv("FCB_DB_DSN", "") t.Setenv("FCB_REDIS_ADDR", "") t.Setenv("FCB_LISTEN", "") t.Setenv("FCB_STORAGE_ENGINE", "") c, err := New() if err != nil { t.Fatalf("默认(无 DSN)应可构造: %v", err) } if c.Env.DBDriver != DBDriverSQLite { t.Errorf("默认驱动应为 sqlite,实际 %s", c.Env.DBDriver) } if c.SQLitePath() != DefaultSQLitePath { t.Errorf("SQLite 默认路径 = %s", c.SQLitePath()) } if c.Env.Listen != ":8466" { t.Errorf("默认监听地址错误: %s", c.Env.Listen) } if c.Env.StorageEngine != "local" { t.Errorf("默认存储引擎错误: %s", c.Env.StorageEngine) } if c.Env.RedisAddr != "" { t.Errorf("RedisAddr 应为空: %s", c.Env.RedisAddr) } } func TestNewPostgresRequiresDSN(t *testing.T) { t.Setenv("FCB_DB_DRIVER", "postgres") t.Setenv("FCB_DB_DSN", "") if _, err := New(); err == nil { t.Fatal("postgres 模式缺少 FCB_DB_DSN 应报错") } t.Setenv("FCB_DB_DSN", "postgres://user:pass@localhost:5432/fcb") c, err := New() if err != nil { t.Fatalf("postgres + DSN 应可构造: %v", err) } if c.Env.DBDriver != DBDriverPostgres { t.Errorf("驱动应为 postgres,实际 %s", c.Env.DBDriver) } if c.SQLitePath() != "" { t.Errorf("postgres 模式 SQLitePath 应为空: %s", c.SQLitePath()) } } func TestNewInvalidDriver(t *testing.T) { t.Setenv("FCB_DB_DRIVER", "mysql") t.Setenv("FCB_DB_DSN", "x") if _, err := New(); err == nil { t.Fatal("非法驱动应报错") } } func TestNewInvalidEngine(t *testing.T) { t.Setenv("FCB_DB_DSN", "postgres://x") t.Setenv("FCB_STORAGE_ENGINE", "onedrive") if _, err := New(); err == nil { t.Fatal("非法引擎应报错") } } func TestEnvOverridesAndDefaults(t *testing.T) { t.Setenv("FCB_DB_DSN", "postgres://x") t.Setenv("FCB_LISTEN", ":9999") t.Setenv("FCB_STORAGE_ENGINE", "webdav") c, err := New() if err != nil { t.Fatalf("New 失败: %v", err) } if c.Env.Listen != ":9999" || c.Env.StorageEngine != "webdav" { t.Fatalf("env 覆盖失败: %+v", c.Env) } // 默认值对齐参考 DEFAULT_CONFIG if got := c.GetInt("uploadSize"); got != 1024*1024*10 { t.Errorf("uploadSize 默认值 = %d", got) } if got := c.GetInt("errorCount"); got != 10 { t.Errorf("errorCount 默认值 = %d", got) } if got := c.GetInt("loginCount"); got != 5 { t.Errorf("loginCount 默认值 = %d", got) } if got := c.GetInt("loginMinute"); got != 15 { t.Errorf("loginMinute 默认值 = %d", got) } if got := c.GetBool("openUpload"); !got { t.Error("openUpload 默认应为开启") } if c.EnableChunk() { t.Error("enableChunk 默认应关闭") } // 新增字段(需求 ①) if c.LogoURL() != DefaultLogoURL { t.Errorf("logo_url 默认值 = %s", c.LogoURL()) } if c.FaviconURL() != DefaultFaviconURL { t.Errorf("favicon_url 默认值 = %s", c.FaviconURL()) } if c.SiteName() == "" { t.Error("site_name 默认值不应为空") } // 过期方式与文件类型 if len(c.ExpireStyle()) != 5 { t.Errorf("expireStyle 默认值 = %v", c.ExpireStyle()) } if len(c.AllowedFileTypes()) != 1 || c.AllowedFileTypes()[0] != "*" { t.Errorf("allowed_file_types 默认值 = %v", c.AllowedFileTypes()) } } func TestKVOverridesEnvAndDefaults(t *testing.T) { t.Setenv("FCB_DB_DSN", "postgres://x") c, _ := New() c.ApplyKV(map[string]any{ "uploadSize": 1024, "openUpload": 0, "site_name": "我的快递柜", "logo_url": "https://example.com/logo.svg", "internalKey": "x", // 非下划线开头允许;下划线开头被拒 "_secret": "no", }) if got := c.GetInt("uploadSize"); got != 1024 { t.Errorf("KV 覆盖 uploadSize 失败: %d", got) } if c.OpenUpload() { t.Error("KV 覆盖 openUpload 失败") } if c.SiteName() != "我的快递柜" { t.Errorf("site_name KV 覆盖失败: %s", c.SiteName()) } if c.LogoURL() != "https://example.com/logo.svg" { t.Errorf("logo_url KV 覆盖失败: %s", c.LogoURL()) } if _, ok := c.Get("_secret"); ok { t.Error("下划线内部键不应可通过 ApplyKV 覆盖") } } func TestAdminSessionExpireClamp(t *testing.T) { t.Setenv("FCB_DB_DSN", "postgres://x") c, _ := New() if got := c.AdminSessionExpireSeconds(); got != AdminSessionExpireDefault { t.Errorf("默认会话有效期 = %d", got) } c.ApplyKV(map[string]any{"adminSessionExpire": 7 * 24 * 60 * 60}) if got := c.AdminSessionExpireSeconds(); got != 7*24*60*60 { t.Errorf("7 天会话有效期 = %d", got) } c.ApplyKV(map[string]any{"adminSessionExpire": 3600}) // 非整天,回落默认 if got := c.AdminSessionExpireSeconds(); got != AdminSessionExpireDefault { t.Errorf("非法值应回落默认 = %d", got) } }