package config import "os" import "path/filepath" import "testing" import "time" import yaml "github.com/goccy/go-yaml" func TestLoadDefaults(t *testing.T) { var cfg Config var err error cfg, err = Load("") if err != nil { t.Fatalf("Load() error: %v", err) } if cfg.DBDriver == "" || cfg.DBDSN == "" { t.Fatalf("defaults not populated: driver=%q dsn=%q", cfg.DBDriver, cfg.DBDSN) } if cfg.DataDir != "./codit-data" { t.Fatalf("unexpected data dir default: %s", cfg.DataDir) } if cfg.DBDSN != "file:./codit-data/codit.db" { t.Fatalf("unexpected db dsn default: %s", cfg.DBDSN) } if cfg.GitHTTPPrefix != "/git" { t.Fatalf("unexpected git prefix default: %s", cfg.GitHTTPPrefix) } if cfg.DockerHTTPPrefix != "/v2" { t.Fatalf("unexpected docker prefix default: %s", cfg.DockerHTTPPrefix) } if cfg.FrontendDir == "" { t.Fatalf("frontend-dir default missing") } } func TestLoadDefaultsFromEnvPrefix(t *testing.T) { var cfg Config var err error cfg, err = LoadWithEnvPrefix("", "CO_DIT_") if err != nil { t.Fatalf("LoadWithEnvPrefix() error: %v", err) } if cfg.DataDir != "./co-dit-data" { t.Fatalf("unexpected data dir default: %s", cfg.DataDir) } if cfg.DBDSN != "file:./co-dit-data/co-dit.db" { t.Fatalf("unexpected db dsn default: %s", cfg.DBDSN) } } func TestLoadFromYAMLAndEnvOverride(t *testing.T) { var dir string var path string var data string var err error var cfg Config dir = t.TempDir() path = filepath.Join(dir, "config.yaml") data = "db-driver: sqlite\ndb-dsn: file:test.db\nauth-mode: HyBrId\ngit-http-prefix: /g\ndocker-http-prefix: registry\napp:\n log-mask: [error, warn]\n log-file: /tmp/codit.log\n log-max-size: 1234\n log-rotate: 3\n" err = os.WriteFile(path, []byte(data), 0o644) if err != nil { t.Fatalf("write config file: %v", err) } t.Setenv("CODIT_DB_DSN", "file:override.db") t.Setenv("CODIT_FRONTEND_DIR", "/srv/codit/frontend") cfg, err = Load(path) if err != nil { t.Fatalf("Load() error: %v", err) } if cfg.DBDSN != "file:override.db" { t.Fatalf("env override failed: %s", cfg.DBDSN) } if cfg.AuthMode != "hybrid" { t.Fatalf("auth-mode normalization failed: %s", cfg.AuthMode) } if cfg.FrontendDir != "/srv/codit/frontend" { t.Fatalf("frontend-dir env override failed: %s", cfg.FrontendDir) } if cfg.DockerHTTPPrefix != "/registry" { t.Fatalf("docker-http-prefix normalization failed: %s", cfg.DockerHTTPPrefix) } if len(cfg.App.LogMask) != 2 || cfg.App.LogMask[0] != "error" || cfg.App.LogMask[1] != "warn" { t.Fatalf("log-mask load failed: %#v", cfg.App.LogMask) } if cfg.App.LogFile != "/tmp/codit.log" || cfg.App.LogMaxSize != 1234 || cfg.App.LogRotate != 3 { t.Fatalf("log config load failed: file=%q max=%d rotate=%d", cfg.App.LogFile, cfg.App.LogMaxSize, cfg.App.LogRotate) } } func TestLoadFilesLaterWinsAndGlob(t *testing.T) { var dir string var first string var second string var cfg Config var err error dir = t.TempDir() first = filepath.Join(dir, "10-base.yaml") second = filepath.Join(dir, "20-override.yaml") err = os.WriteFile(first, []byte("db-dsn: file:base.db\nctl:\n service:\n addresses: [':1080']\n"), 0o644) if err != nil { t.Fatalf("write first config: %v", err) } err = os.WriteFile(second, []byte("db-dsn: file:override.db\nctl:\n service:\n addresses: [':1443']\n tls:\n enabled: true\n"), 0o644) if err != nil { t.Fatalf("write second config: %v", err) } cfg, err = LoadFiles([]string{filepath.Join(dir, "*.yaml")}) if err != nil { t.Fatalf("LoadFiles() error: %v", err) } if cfg.DBDSN != "file:override.db" { t.Fatalf("later config did not win: %s", cfg.DBDSN) } if !cfg.CTL.TLS.Enabled || len(cfg.CTL.Service.Addrs) != 1 || cfg.CTL.Service.Addrs[0] != ":1443" { t.Fatalf("glob config did not load ctl tls address: enabled=%t addrs=%#v", cfg.CTL.TLS.Enabled, cfg.CTL.Service.Addrs) } } func TestLoadWithEnvPrefix(t *testing.T) { var cfg Config var err error t.Setenv("CODIT2_DB_DSN", "file:codit2.db") t.Setenv("CODIT2_DOCKER_HTTP_PREFIX", "/docker/") t.Setenv("CODIT_DB_DSN", "file:codit.db") cfg, err = LoadWithEnvPrefix("", "CODIT2_") if err != nil { t.Fatalf("LoadWithEnvPrefix() error: %v", err) } if cfg.DBDSN != "file:codit2.db" { t.Fatalf("custom env prefix override failed: %s", cfg.DBDSN) } if cfg.DockerHTTPPrefix != "/docker" { t.Fatalf("custom env docker prefix override failed: %s", cfg.DockerHTTPPrefix) } } func TestDurationUnmarshalYAML(t *testing.T) { var item struct { Duration Duration `yaml:"duration"` } var err error err = yaml.Unmarshal([]byte("duration: 90m\n"), &item) if err != nil { t.Fatalf("UnmarshalYAML() string duration error: %v", err) } if item.Duration.Duration() != 90*time.Minute { t.Fatalf("unexpected duration: %v", item.Duration.Duration()) } err = yaml.Unmarshal([]byte("duration: 60000000000\n"), &item) if err != nil { t.Fatalf("UnmarshalYAML() numeric duration error: %v", err) } if item.Duration.Duration() != time.Duration(60000000000) { t.Fatalf("unexpected numeric duration: %v", item.Duration.Duration()) } }