package config import ( "testing" "time" ) func TestDefaultIsValid(t *testing.T) { cfg := Default() if err := cfg.Validate(); err != nil { t.Fatalf("default config should validate: %v", err) } } func TestLoadEnvOverrides(t *testing.T) { t.Setenv("ARCHIVE_SUBJECTS", "logs.vm.> logs.k8s.vault.>") t.Setenv("LOGARCHIVER_S3_BUCKET", "my-bucket") t.Setenv("LOGARCHIVER_NATS_DURABLE", "archiver-canary") t.Setenv("NATS_CONSUMER_PASSWORD", "s3cr3t") t.Setenv("S3_ENDPOINT", "https://rgw.internal") t.Setenv("BUCKET_NAME", "logs-archive-override") cfg, err := Load("") if err != nil { t.Fatalf("Load: %v", err) } if got, want := cfg.NATS.Subjects, []string{"logs.vm.>", "logs.k8s.vault.>"}; len(got) != len(want) || got[0] != want[0] || got[1] != want[1] { t.Errorf("subjects = %v, want %v", got, want) } if cfg.NATS.Durable != "archiver-canary" { t.Errorf("durable = %q", cfg.NATS.Durable) } if cfg.NATS.Password != "s3cr3t" { t.Errorf("password from env not resolved: %q", cfg.NATS.Password) } // BUCKET_NAME (secret) should win over LOGARCHIVER_S3_BUCKET default flow. if cfg.S3.Bucket != "logs-archive-override" { t.Errorf("bucket = %q, want cephrgw secret override", cfg.S3.Bucket) } if cfg.S3.Endpoint != "https://rgw.internal" { t.Errorf("endpoint = %q", cfg.S3.Endpoint) } } func TestValidateErrors(t *testing.T) { cases := map[string]func(*Config){ "no subjects": func(c *Config) { c.NATS.Subjects = nil }, "no bucket": func(c *Config) { c.S3.Bucket = "" }, "no key name": func(c *Config) { c.Crypto.KeyName = "" }, "bad source": func(c *Config) { c.Crypto.Source = "elsewhere" }, "file no path": func(c *Config) { c.Crypto.Source = PubkeyFile; c.Crypto.PubkeyFile = "" }, "vault no addr": func(c *Config) { c.Crypto.Source = PubkeyVault; c.Crypto.Vault.Address = "" }, "zero frame": func(c *Config) { c.Crypto.FrameSize = 0 }, "no batch bounds": func(c *Config) { c.Batch = BatchConfig{} }, } for name, mutate := range cases { t.Run(name, func(t *testing.T) { cfg := Default() mutate(&cfg) if err := cfg.Validate(); err == nil { t.Errorf("expected validation error for %q", name) } }) } } func TestValidateVaultSourceOK(t *testing.T) { cfg := Default() cfg.Crypto.Source = PubkeyVault cfg.Crypto.Vault.Address = "https://vault.example:8200" cfg.Crypto.Vault.Mount = "gpg" if err := cfg.Validate(); err != nil { t.Fatalf("vault source should validate: %v", err) } } func TestParseSize(t *testing.T) { cases := map[string]int64{ "1024": 1024, "64Mi": 64 << 20, "2Gi": 2 << 30, "1Ki": 1024, "5MB": 5_000_000, " 10 ": 10, } for in, want := range cases { got, err := ParseSize(in) if err != nil { t.Errorf("ParseSize(%q): %v", in, err) continue } if got != want { t.Errorf("ParseSize(%q) = %d, want %d", in, got, want) } } if _, err := ParseSize("bogus"); err == nil { t.Errorf("expected error for bogus size") } } func TestDefaultBatchDurations(t *testing.T) { cfg := Default() if cfg.Batch.MaxAge != 5*time.Minute { t.Errorf("default MaxAge = %v", cfg.Batch.MaxAge) } }