package starlog import ( "bytes" "strings" "testing" ) func TestConfigGetAndApply(t *testing.T) { var buf bytes.Buffer logger := newStructuredTestLogger(&buf) logger.SetLevel(LvWarning) logger.SetStdErrLevel(LvCritical) logger.SetShowColor(false) logger.SetOnlyColorLevel(false) logger.SetShowLevel(false) logger.SetShowFlag(false) logger.SetShowFieldColor(false) logger.SetPendingWriteLimit(8) logger.SetPendingDropPolicy(PendingDropOldest) logger.SetRedactFailMode(RedactFailMaskAll) logger.SetRedactMaskToken("[MASK]") cfg := logger.GetConfig() if cfg.Level != LvWarning { t.Fatalf("unexpected level in config snapshot: %d", cfg.Level) } if cfg.StdErrLevel != LvCritical { t.Fatalf("unexpected stderr level in config snapshot: %d", cfg.StdErrLevel) } if cfg.ShowColor { t.Fatalf("show color should be false in config snapshot") } if cfg.PendingWriteLimit != 8 { t.Fatalf("unexpected pending write limit in config snapshot: %d", cfg.PendingWriteLimit) } cfg.Level = LvInfo cfg.ShowColor = true cfg.OnlyColorLevel = true cfg.ShowLevel = true cfg.ShowFlag = true cfg.ShowFieldColor = true cfg.LevelColors = map[int][]Attr{ LvInfo: []Attr{FgCyan}, LvError: []Attr{FgRed}, } cfg.KeywordColors = map[string][]Attr{ "panic": []Attr{FgRed}, } cfg.FieldTypeColors = map[string][]Attr{ FieldTypeString: []Attr{FgGreen}, } cfg.FieldValueColors = map[string][]Attr{ "user": []Attr{FgYellow}, } cfg.PendingWriteLimit = 2 cfg.PendingDropPolicy = PendingDropNewest cfg.RedactFailMode = RedactFailOpen cfg.RedactMaskToken = "***" cfg.RateLimit = RateLimitConfig{ Enable: true, Levels: []int{LvInfo}, Rate: 3, Burst: 5, } logger.ApplyConfig(cfg) if logger.GetLevel() != LvInfo { t.Fatalf("apply config should update level") } if !logger.GetShowColor() || !logger.GetOnlyColorLevel() { t.Fatalf("apply config should update color mode flags") } if logger.GetPendingWriteLimit() != 2 { t.Fatalf("apply config should update pending write limit") } if logger.GetPendingDropPolicy() != PendingDropNewest { t.Fatalf("apply config should update pending drop policy") } applied := logger.GetConfig() if applied.RedactFailMode != RedactFailOpen || applied.RedactMaskToken != "***" { t.Fatalf("apply config should update redaction options") } if !applied.RateLimit.Enable || applied.RateLimit.Rate != 3 || applied.RateLimit.Burst != 5 { t.Fatalf("apply config should update rate limit options, got %+v", applied.RateLimit) } if len(applied.KeywordColors) == 0 || len(applied.LevelColors) == 0 { t.Fatalf("apply config should keep configured color maps") } } func TestUpdateConfigBatch(t *testing.T) { var buf bytes.Buffer logger := newStructuredTestLogger(&buf) logger.UpdateConfig(func(cfg *Config) { cfg.Level = LvError cfg.ShowLevel = true cfg.ShowFlag = false cfg.ShowOriginFile = false cfg.ShowFuncName = false cfg.PendingWriteLimit = 4 cfg.PendingDropPolicy = PendingDropOldest cfg.RedactFailMode = RedactFailOpen cfg.RedactMaskToken = "[R]" }) logger.Info("filtered") logger.Error("visible") got := buf.String() if strings.Contains(got, "filtered") { t.Fatalf("info should be filtered after UpdateConfig, got %q", got) } if !strings.Contains(got, "visible") { t.Fatalf("error should be visible after UpdateConfig, got %q", got) } snapshot := logger.GetConfig() if snapshot.PendingWriteLimit != 4 || snapshot.PendingDropPolicy != PendingDropOldest { t.Fatalf("update config should apply pending queue settings") } } func TestApplyConfigPendingLimitTrim(t *testing.T) { var buf bytes.Buffer logger := newStructuredTestLogger(&buf) logger.SetPendingWriteLimit(5) logger.SetPendingDropPolicy(PendingDropOldest) logger.SetSwitching(true) logger.Infoln("one") logger.Infoln("two") logger.Infoln("three") beforeDrop := logger.GetPendingDropCount() cfg := logger.GetConfig() cfg.PendingWriteLimit = 2 cfg.PendingDropPolicy = PendingDropOldest cfg.Switching = true logger.ApplyConfig(cfg) stats := logger.GetPendingStats() if stats.Length != 2 { t.Fatalf("pending queue should be trimmed to limit, got length=%d", stats.Length) } if logger.GetPendingDropCount() <= beforeDrop { t.Fatalf("applying lower pending limit should increase drop count") } logger.SetSwitching(false) } func TestDefaultConfig(t *testing.T) { cfg := DefaultConfig() if cfg.Level != LvDebug { t.Fatalf("default level should be LvDebug, got %d", cfg.Level) } if cfg.StdErrLevel != LvError { t.Fatalf("default stderr level should be LvError, got %d", cfg.StdErrLevel) } if !cfg.ShowColor || !cfg.ShowStd { t.Fatalf("default config should enable show color/std") } if cfg.PendingWriteLimit != 1024 { t.Fatalf("default pending write limit should be 1024, got %d", cfg.PendingWriteLimit) } if cfg.RateLimit.Burst <= 0 || cfg.RateLimit.MaxKeys <= 0 { t.Fatalf("default config should include normalized rate limit defaults, got %+v", cfg.RateLimit) } if len(cfg.LevelColors) == 0 { t.Fatalf("default config should include level colors") } } func TestStdConfigAPIBridge(t *testing.T) { backup := GetConfig() defer ApplyConfig(backup) UpdateConfig(func(cfg *Config) { cfg.Level = LvCritical cfg.ShowColor = false cfg.OnlyColorLevel = false }) cfg := GetConfig() if cfg.Level != LvCritical { t.Fatalf("std update config should change level") } if cfg.ShowColor || cfg.OnlyColorLevel { t.Fatalf("std update config should change color flags") } }