Files
glchat/internal/config/config_test.go
T
grendervill 69aa98e18c feat(server): скелет Go-сервера с healthz, readyz и api/v1/meta
- internal/config: конфигурация из env с валидацией и дефолтами (§5.1, §9.1)
- internal/httpx: middleware (request id, slog-логи, recover, security-заголовки),
  единый формат ошибок §8.5 и лимит тела запроса
- internal/database: SQLite WAL + busy_timeout + foreign_keys, один writer
  и пул чтения, goose-миграции embedded, PRAGMA optimize по расписанию
- internal/meta: полезная нагрузка /api/v1/meta (версия, фичи, лимиты)
- internal/server: маршруты, SPA-раздача собранного клиента, OpenAPI 3.1
- cmd/glchat: точка входа с graceful shutdown и JSON-логами
- тесты: конфиг, миграции и идемпотентность, HTTP-эндпоинты, статика, 404/405
2026-09-19 18:20:56 +03:00

122 lines
3.5 KiB
Go

package config
import "testing"
func TestLoadDefaults(t *testing.T) {
t.Setenv("DOMAIN", "")
t.Setenv("LISTEN_ADDR", "")
t.Setenv("DATA_DIR", "")
t.Setenv("DATABASE_PATH", "")
t.Setenv("INSTANCE_NAME", "")
t.Setenv("FILES_DOMAIN", "")
t.Setenv("LOG_LEVEL", "")
t.Setenv("LOG_FORMAT", "")
t.Setenv("SQLITE_READ_POOL", "")
t.Setenv("MAX_UPLOAD_SIZE", "")
t.Setenv("SHUTDOWN_TIMEOUT_SECONDS", "")
t.Setenv("DB_MAINTENANCE_INTERVAL_SECONDS", "")
t.Setenv("APP_VERSION", "")
t.Setenv("APP_COMMIT", "")
t.Setenv("APP_BUILD_DATE", "")
cfg, err := Load()
if err != nil {
t.Fatalf("Load() returned error: %v", err)
}
if cfg.ListenAddr != DefaultListenAddr {
t.Errorf("ListenAddr = %q, want %q", cfg.ListenAddr, DefaultListenAddr)
}
if cfg.DataDir != DefaultDataDir {
t.Errorf("DataDir = %q, want %q", cfg.DataDir, DefaultDataDir)
}
if cfg.DatabasePath != DefaultDataDir+"/db/glchat.db" {
t.Errorf("DatabasePath = %q, want default under data dir", cfg.DatabasePath)
}
if cfg.FilesDomain != "files.localhost" {
t.Errorf("FilesDomain = %q, want files.localhost", cfg.FilesDomain)
}
if cfg.ReadPoolSize != 4 {
t.Errorf("ReadPoolSize = %d, want 4", cfg.ReadPoolSize)
}
if cfg.MaxUploadSize != 26214400 {
t.Errorf("MaxUploadSize = %d, want 26214400", cfg.MaxUploadSize)
}
if cfg.Version != "dev" {
t.Errorf("Version = %q, want dev", cfg.Version)
}
if cfg.LogLevelNumeric() != 0 {
t.Errorf("LogLevelNumeric() = %d, want 0 for info", cfg.LogLevelNumeric())
}
}
func TestLoadEnvOverrides(t *testing.T) {
t.Setenv("DOMAIN", "gl.mhspx.su")
t.Setenv("FILES_DOMAIN", "")
t.Setenv("LISTEN_ADDR", "0.0.0.0:9090")
t.Setenv("DATA_DIR", "/srv/glchat")
t.Setenv("DATABASE_PATH", "/srv/glchat/db/custom.db")
t.Setenv("LOG_LEVEL", "debug")
t.Setenv("LOG_FORMAT", "text")
t.Setenv("SQLITE_READ_POOL", "8")
t.Setenv("MAX_UPLOAD_SIZE", "104857600")
t.Setenv("APP_VERSION", "v0.1.0")
t.Setenv("APP_COMMIT", "abc1234")
t.Setenv("SHUTDOWN_TIMEOUT_SECONDS", "5")
cfg, err := Load()
if err != nil {
t.Fatalf("Load() returned error: %v", err)
}
if cfg.Domain != "gl.mhspx.su" {
t.Errorf("Domain = %q", cfg.Domain)
}
if cfg.FilesDomain != "files.gl.mhspx.su" {
t.Errorf("FilesDomain = %q, want derived subdomain", cfg.FilesDomain)
}
if cfg.DatabasePath != "/srv/glchat/db/custom.db" {
t.Errorf("DatabasePath = %q", cfg.DatabasePath)
}
if cfg.ReadPoolSize != 8 {
t.Errorf("ReadPoolSize = %d", cfg.ReadPoolSize)
}
if cfg.MaxUploadSize != 104857600 {
t.Errorf("MaxUploadSize = %d", cfg.MaxUploadSize)
}
if cfg.LogLevelNumeric() != -4 {
t.Errorf("LogLevelNumeric() = %d, want -4 for debug", cfg.LogLevelNumeric())
}
if cfg.LogFormat != "text" {
t.Errorf("LogFormat = %q", cfg.LogFormat)
}
if cfg.BaseURL() != "https://gl.mhspx.su" {
t.Errorf("BaseURL() = %q", cfg.BaseURL())
}
if cfg.FilesURL() != "https://files.gl.mhspx.su" {
t.Errorf("FilesURL() = %q", cfg.FilesURL())
}
}
func TestLoadRejectsInvalidValues(t *testing.T) {
cases := []struct {
name string
env map[string]string
}{
{name: "log level", env: map[string]string{"LOG_LEVEL": "verbose"}},
{name: "log format", env: map[string]string{"LOG_FORMAT": "xml"}},
{name: "read pool", env: map[string]string{"SQLITE_READ_POOL": "0"}},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
t.Setenv("LOG_LEVEL", "info")
t.Setenv("LOG_FORMAT", "json")
t.Setenv("SQLITE_READ_POOL", "4")
for k, v := range tc.env {
t.Setenv(k, v)
}
if _, err := Load(); err == nil {
t.Fatalf("Load() accepted invalid %s", tc.name)
}
})
}
}