config_test.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. package config
  2. import (
  3. "strings"
  4. "testing"
  5. )
  6. // setAll 设置一组完整的必填环境变量,供各用例在此基础上调整。
  7. func setAll(t *testing.T) {
  8. t.Helper()
  9. t.Setenv("HAVEN_LISTEN_ADDR", "127.0.0.1:8080")
  10. t.Setenv("HAVEN_DB_DSN", "postgres://haven@127.0.0.1:5432/haven?sslmode=disable")
  11. t.Setenv("HAVEN_FRONTEND_DIR", "/opt/haven/frontend/dist")
  12. t.Setenv("HAVEN_GOGS_BASE_URL", "https://gogs.example.com")
  13. t.Setenv("HAVEN_COOKIE_DOMAIN", "app.example.com")
  14. }
  15. func TestLoadDefaults(t *testing.T) {
  16. setAll(t)
  17. cfg, err := Load()
  18. if err != nil {
  19. t.Fatalf("Load() 返回错误: %v", err)
  20. }
  21. if !cfg.CookieSecure {
  22. t.Error("HAVEN_COOKIE_SECURE 未设置时应默认 true")
  23. }
  24. if cfg.TotpIssuer != "Haven" {
  25. t.Errorf("HAVEN_TOTP_ISSUER 默认为 Haven,实际 %q", cfg.TotpIssuer)
  26. }
  27. if cfg.LogLevel != "info" {
  28. t.Errorf("HAVEN_LOG_LEVEL 默认为 info,实际 %q", cfg.LogLevel)
  29. }
  30. }
  31. func TestLoadMissingRequired(t *testing.T) {
  32. setAll(t)
  33. t.Setenv("HAVEN_DB_DSN", "")
  34. t.Setenv("HAVEN_COOKIE_DOMAIN", " ")
  35. _, err := Load()
  36. if err == nil {
  37. t.Fatal("缺少必填项时应返回错误")
  38. }
  39. // 应一次性列出全部缺失项,而不是只报第一个
  40. for _, name := range []string{"HAVEN_DB_DSN", "HAVEN_COOKIE_DOMAIN"} {
  41. if !strings.Contains(err.Error(), name) {
  42. t.Errorf("错误信息应包含 %s,实际 %q", name, err.Error())
  43. }
  44. }
  45. }
  46. func TestLoadCookieSecureFalse(t *testing.T) {
  47. setAll(t)
  48. t.Setenv("HAVEN_COOKIE_SECURE", "false")
  49. cfg, err := Load()
  50. if err != nil {
  51. t.Fatalf("Load() 返回错误: %v", err)
  52. }
  53. if cfg.CookieSecure {
  54. t.Error("HAVEN_COOKIE_SECURE=false 时应为 false")
  55. }
  56. }
  57. func TestLoadInvalidCookieSecure(t *testing.T) {
  58. setAll(t)
  59. t.Setenv("HAVEN_COOKIE_SECURE", "yes-please")
  60. if _, err := Load(); err == nil {
  61. t.Fatal("非法的 HAVEN_COOKIE_SECURE 应返回错误")
  62. }
  63. }
  64. func TestLoadLogLevel(t *testing.T) {
  65. cases := []struct {
  66. raw string
  67. want string
  68. wantErr bool
  69. }{
  70. {raw: "", want: "info"},
  71. {raw: "DEBUG", want: "debug"},
  72. {raw: "warn", want: "warn"},
  73. {raw: "error", want: "error"},
  74. {raw: "verbose", wantErr: true},
  75. }
  76. for _, tc := range cases {
  77. t.Run(tc.raw, func(t *testing.T) {
  78. setAll(t)
  79. t.Setenv("HAVEN_LOG_LEVEL", tc.raw)
  80. cfg, err := Load()
  81. if tc.wantErr {
  82. if err == nil {
  83. t.Fatalf("HAVEN_LOG_LEVEL=%q 应返回错误", tc.raw)
  84. }
  85. return
  86. }
  87. if err != nil {
  88. t.Fatalf("Load() 返回错误: %v", err)
  89. }
  90. if cfg.LogLevel != tc.want {
  91. t.Errorf("HAVEN_LOG_LEVEL=%q 解析为 %q,期望 %q", tc.raw, cfg.LogLevel, tc.want)
  92. }
  93. })
  94. }
  95. }
  96. func TestLoadTrimsTrailingSlash(t *testing.T) {
  97. setAll(t)
  98. t.Setenv("HAVEN_GOGS_BASE_URL", "https://gogs.example.com/")
  99. cfg, err := Load()
  100. if err != nil {
  101. t.Fatalf("Load() 返回错误: %v", err)
  102. }
  103. // 作品集 URL 由 GogsBaseURL + "/" + repo_path 拼接,末尾斜杠必须去掉
  104. if cfg.GogsBaseURL != "https://gogs.example.com" {
  105. t.Errorf("GogsBaseURL 应去掉末尾斜杠,实际 %q", cfg.GogsBaseURL)
  106. }
  107. }
苏ICP备2026082406号
苏公网安备 待审核