Files
grendervill 3d1816a640 feat(config): схема URL в meta зависит от TLS_ENABLED
- при установке без TLS (--skip-tls, стенд без домена) клиент получает
  http:// и ws:// вместо неработающих https:// и wss://
- установщик пишет TLS_ENABLED в .env; тесты фиксируют обе схемы
2026-09-19 19:58:32 +03:00

133 lines
3.8 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", "")
t.Setenv("TLS_ENABLED", "")
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.TLSEnabled {
t.Error("TLSEnabled = false, want true by default")
}
if cfg.BaseURL() != "https://localhost" {
t.Errorf("BaseURL() = %q", cfg.BaseURL())
}
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")
t.Setenv("TLS_ENABLED", "false")
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() != "http://gl.mhspx.su" {
t.Errorf("BaseURL() = %q", cfg.BaseURL())
}
if cfg.FilesURL() != "http://files.gl.mhspx.su" {
t.Errorf("FilesURL() = %q", cfg.FilesURL())
}
if cfg.GatewayURL() != "ws://gl.mhspx.su/gateway" {
t.Errorf("GatewayURL() = %q", cfg.GatewayURL())
}
}
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)
}
})
}
}