- add custom LogLevel constructors and richer color configuration - support ANSI, 256-color, RGB, and text attributes on LogLevel - introduce clearer preferred APIs such as NewLogger and SetName - preserve backward compatibility with deprecated wrappers for v2.0.1 APIs - restore legacy ColorStringBuilder signatures as compatibility wrappers - fix newline separator handling in Println-style output - add tests for color precedence, deprecated aliases, and LogLevel attributes - update GoDoc and bilingual README documentation
This commit is contained in:
+184
@@ -189,6 +189,190 @@ func TestJsonWriterPrintPreservesTrailingNewlineSemantic(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestTextWriterPrintlnDoesNotLeaveTrailingMessageSeparator(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
formatter := NewFormatter().
|
||||
SetFormat("%m (%S)").
|
||||
SetColorOutput(false)
|
||||
writer := CreateTextWriter(&buf).SetFormatter(formatter)
|
||||
|
||||
if err := writer.Print(DEBUG, "TEST", nil, "debug details", "\n"); err != nil {
|
||||
t.Fatalf("Print() error = %v", err)
|
||||
}
|
||||
|
||||
got := strings.TrimSuffix(buf.String(), "\n")
|
||||
if got != "debug details (%S)" {
|
||||
t.Fatalf("println newline marker should not leave trailing message separator, got %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTextWriterPrintlnDoesNotLeaveTrailingMessageSeparatorAfterReplacement(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
formatter := NewFormatter().
|
||||
SetFormat("%m (%S)").
|
||||
SetColorOutput(false)
|
||||
writer := CreateTextWriter(&buf).SetFormatter(formatter)
|
||||
logger := CreateLogger().
|
||||
SetLevel(DEBUG).
|
||||
AddWriter(writer).
|
||||
AddReplacer("details", "details")
|
||||
|
||||
logger.Debugln("debug details")
|
||||
|
||||
got := strings.TrimSuffix(buf.String(), "\n")
|
||||
if got != "debug details (%S)" {
|
||||
t.Fatalf("println newline marker should not leave trailing message separator after replacements, got %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestJsonWriterPrintlnDoesNotLeaveTrailingMessageSeparator(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
writer := CreateJsonWriter(&buf, false)
|
||||
|
||||
if err := writer.Print(INFO, "TEST", nil, "hello", "\n"); err != nil {
|
||||
t.Fatalf("Print() error = %v", err)
|
||||
}
|
||||
|
||||
var message LoggerJsonMessage
|
||||
if err := json.Unmarshal(bytes.TrimSuffix(buf.Bytes(), []byte("\n")), &message); err != nil {
|
||||
t.Fatalf("json.Unmarshal() error = %v", err)
|
||||
}
|
||||
if message.Message != "hello" {
|
||||
t.Fatalf("message should not include trailing separator from newline marker, got %q", message.Message)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLogLevelForegroundSettersOverridePreviousColorMode(t *testing.T) {
|
||||
level := NewLogLevel(0, "custom")
|
||||
formatter := NewFormatter()
|
||||
|
||||
level.SetFgColor(FgRed)
|
||||
if got := formatter.ColorizeString("x", level); !strings.HasPrefix(got, FgRed.String()) {
|
||||
t.Fatalf("expected plain foreground color prefix %q, got %q", FgRed.String(), got)
|
||||
}
|
||||
|
||||
level.SetForeground256Color(FgColor256(123))
|
||||
if got := formatter.ColorizeString("x", level); !strings.HasPrefix(got, FgColor256(123).String()) {
|
||||
t.Fatalf("expected 256-color foreground prefix %q, got %q", FgColor256(123).String(), got)
|
||||
}
|
||||
|
||||
level.SetForegroundRGB(1, 2, 3)
|
||||
expectedRGB := NewFgColorRGB(1, 2, 3).String()
|
||||
if got := formatter.ColorizeString("x", level); !strings.HasPrefix(got, expectedRGB) {
|
||||
t.Fatalf("expected RGB foreground prefix %q, got %q", expectedRGB, got)
|
||||
}
|
||||
|
||||
level.SetFgColor(FgBlue)
|
||||
if got := formatter.ColorizeString("x", level); !strings.HasPrefix(got, FgBlue.String()) {
|
||||
t.Fatalf("expected last plain foreground color to win with prefix %q, got %q", FgBlue.String(), got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLogLevelBackgroundSettersOverridePreviousColorMode(t *testing.T) {
|
||||
level := NewLogLevel(0, "custom")
|
||||
formatter := NewFormatter()
|
||||
|
||||
level.SetBgColor(BgRed)
|
||||
if got := formatter.ColorizeString("x", level); !strings.HasPrefix(got, BgRed.String()) {
|
||||
t.Fatalf("expected plain background color prefix %q, got %q", BgRed.String(), got)
|
||||
}
|
||||
|
||||
level.SetBackground256Color(BgColor256(123))
|
||||
if got := formatter.ColorizeString("x", level); !strings.HasPrefix(got, BgColor256(123).String()) {
|
||||
t.Fatalf("expected 256-color background prefix %q, got %q", BgColor256(123).String(), got)
|
||||
}
|
||||
|
||||
level.SetBackgroundRGB(1, 2, 3)
|
||||
expectedRGB := NewBgColorRGB(1, 2, 3).String()
|
||||
if got := formatter.ColorizeString("x", level); !strings.HasPrefix(got, expectedRGB) {
|
||||
t.Fatalf("expected RGB background prefix %q, got %q", expectedRGB, got)
|
||||
}
|
||||
|
||||
level.SetBgColor(BgBlue)
|
||||
if got := formatter.ColorizeString("x", level); !strings.HasPrefix(got, BgBlue.String()) {
|
||||
t.Fatalf("expected last plain background color to win with prefix %q, got %q", BgBlue.String(), got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLogLevelAttributesAffectColorizedOutput(t *testing.T) {
|
||||
level := NewLogLevel(0, "custom")
|
||||
level.AddAttribute(Italic).AddAttribute(Bold)
|
||||
|
||||
got := NewFormatter().ColorizeString("x", level)
|
||||
if !strings.Contains(got, Italic.String()) {
|
||||
t.Fatalf("expected italic attribute in colorized output, got %q", got)
|
||||
}
|
||||
if !strings.Contains(got, Bold.String()) {
|
||||
t.Fatalf("expected bold attribute in colorized output, got %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLogLevelRemoveAttributeRemovesAllMatches(t *testing.T) {
|
||||
level := NewLogLevel(0, "custom")
|
||||
level.AddAttribute(Bold).AddAttribute(Italic).AddAttribute(Bold)
|
||||
|
||||
level.RemoveAttribute(Bold)
|
||||
|
||||
got := level.GetAttributes()
|
||||
if len(got) != 1 || got[0] != Italic {
|
||||
t.Fatalf("expected only italic attribute to remain, got %#v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLogLevelSetAttributesCopiesInputSlice(t *testing.T) {
|
||||
level := NewLogLevel(0, "custom")
|
||||
attrs := []Attribute{Bold, Italic}
|
||||
|
||||
level.SetAttributes(attrs)
|
||||
attrs[0] = Underline
|
||||
|
||||
got := level.GetAttributes()
|
||||
if len(got) != 2 || got[0] != Bold || got[1] != Italic {
|
||||
t.Fatalf("expected SetAttributes to copy input slice, got %#v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLogLevelGetAttributesReturnsCopy(t *testing.T) {
|
||||
level := NewLogLevel(0, "custom")
|
||||
level.SetAttributes([]Attribute{Bold, Italic})
|
||||
|
||||
got := level.GetAttributes()
|
||||
got[0] = Underline
|
||||
|
||||
again := level.GetAttributes()
|
||||
if len(again) != 2 || again[0] != Bold || again[1] != Italic {
|
||||
t.Fatalf("expected GetAttributes to return a copy, got %#v", again)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLogLevelDeprecatedForegroundAccessorsRemainCompatible(t *testing.T) {
|
||||
level := NewLogLevel(0, "custom")
|
||||
|
||||
level.SetFgColor(FgBlue)
|
||||
if got := level.GetFgColor(); got != FgBlue {
|
||||
t.Fatalf("expected deprecated foreground accessors to round-trip %v, got %v", FgBlue, got)
|
||||
}
|
||||
|
||||
level.SetForegroundColor(FgRed)
|
||||
if got := level.GetFgColor(); got != FgRed {
|
||||
t.Fatalf("expected deprecated getter to reflect new foreground setter, got %v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLogLevelDeprecatedBackgroundAccessorsRemainCompatible(t *testing.T) {
|
||||
level := NewLogLevel(0, "custom")
|
||||
|
||||
level.SetBgColor(BgBlue)
|
||||
if got := level.GetBgColor(); got != BgBlue {
|
||||
t.Fatalf("expected deprecated background accessors to round-trip %v, got %v", BgBlue, got)
|
||||
}
|
||||
|
||||
level.SetBackgroundColor(BgRed)
|
||||
if got := level.GetBgColor(); got != BgRed {
|
||||
t.Fatalf("expected deprecated getter to reflect new background setter, got %v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormatterHandlesEmptyTracebackPlaceholders(t *testing.T) {
|
||||
formatter := NewFormatter().
|
||||
SetFormat("%m|%b|%B|%M|%f|%n|%s|%p")
|
||||
|
||||
Reference in New Issue
Block a user