Files
HackBrowserData/log/logger_test.go
T
Roger d0971ca098 chore: update CI, golangci-lint, and CLAUDE.md (#511)
* chore: update CI, golangci-lint, and CLAUDE.md
* fix: resolve CI failures on Windows test and lint
* fix: resolve Windows test path and main.go line length lint issues
* fix: auto-format log/ with gofumpt, exclude pre-refactoring lint issues
* fix: resolve remaining lint issues, remove unnecessary exclusions
* fix: remove invalid G117 gosec rule, use text exclusion for secret pattern
* fix: align CI golangci-lint version with local (v2.4 -> v2.10)
2026-03-23 01:40:59 +08:00

259 lines
6.4 KiB
Go

package log
import (
"bytes"
"fmt"
"testing"
"github.com/stretchr/testify/assert"
level2 "github.com/moond4rk/hackbrowserdata/log/level"
)
const (
pattern = `^\[hack\-browser\-data] \w+\.go:\d+:`
)
type baseTestCase struct {
description string
message string
suffix string
level level2.Level
wantedPattern string
}
var baseTestCases = []baseTestCase{
{
description: "without trailing newline, logger adds newline",
message: "hello, hacker!",
suffix: "",
},
{
description: "with trailing newline, logger preserves newline",
message: "hello, hacker!",
suffix: "\n",
},
}
func TestLoggerDebug(t *testing.T) {
for _, tc := range baseTestCases {
tc := tc
tc.level = level2.DebugLevel
message := tc.message + tc.suffix
tc.wantedPattern = fmt.Sprintf("%s %s: %s\n$", pattern, tc.level, tc.message)
t.Run(tc.description, func(t *testing.T) {
var buf bytes.Buffer
logger := NewLogger(newBase(&buf))
logger.SetLevel(level2.DebugLevel)
logger.Debug(message)
got := buf.String()
assert.Regexp(t, tc.wantedPattern, got)
})
}
}
func TestLoggerWarn(t *testing.T) {
for _, tc := range baseTestCases {
tc := tc
tc.level = level2.WarnLevel
message := tc.message + tc.suffix
tc.wantedPattern = fmt.Sprintf("%s %s: %s\n$", pattern, tc.level, tc.message)
t.Run(tc.description, func(t *testing.T) {
var buf bytes.Buffer
logger := NewLogger(newBase(&buf))
logger.Warn(message)
got := buf.String()
assert.Regexp(t, tc.wantedPattern, got)
})
}
}
func TestLoggerError(t *testing.T) {
for _, tc := range baseTestCases {
tc := tc
tc.level = level2.ErrorLevel
message := tc.message + tc.suffix
tc.wantedPattern = fmt.Sprintf("%s %s: %s\n$", pattern, tc.level, tc.message)
t.Run(tc.description, func(t *testing.T) {
var buf bytes.Buffer
logger := NewLogger(newBase(&buf))
logger.Error(message)
got := buf.String()
assert.Regexp(t, tc.wantedPattern, got)
})
}
}
func TestLoggerFatal(t *testing.T) {
originalOsExit := osExit
defer func() { osExit = originalOsExit }()
for _, tc := range baseTestCases {
tc := tc
tc.level = level2.FatalLevel
message := tc.message + tc.suffix
tc.wantedPattern = fmt.Sprintf("%s %s: %s\n$", pattern, tc.level, tc.message)
t.Run(tc.description, func(t *testing.T) {
var buf bytes.Buffer
exitCalled := false
exitCode := 0
osExit = func(code int) {
exitCalled = true
exitCode = code
}
logger := NewLogger(newBase(&buf))
logger.Fatal(message)
got := buf.String()
assert.Regexp(t, tc.wantedPattern, got)
assert.True(t, exitCalled)
assert.Equal(t, 1, exitCode)
})
}
}
type formatTestCase struct {
description string
format string
args []interface{}
level level2.Level
wantedPattern string
}
var formatTestCases = []formatTestCase{
{
description: "message with format prefix",
format: "hello, %s!",
args: []any{"Hacker"},
},
{
description: "message with format prefix",
format: "hello, %d,%d,%d!",
args: []any{1, 2, 3},
},
{
description: "message with format prefix",
format: "hello, %s,%d,%d!",
args: []any{"Hacker", 2, 3},
},
}
func TestLoggerDebugf(t *testing.T) {
for _, tc := range formatTestCases {
tc := tc
tc.level = level2.DebugLevel
message := fmt.Sprintf(tc.format, tc.args...)
tc.wantedPattern = fmt.Sprintf("%s %s: %s\n$", pattern, tc.level, message)
t.Run(tc.description, func(t *testing.T) {
var buf bytes.Buffer
logger := NewLogger(newBase(&buf))
logger.SetLevel(level2.DebugLevel)
logger.Debugf(tc.format, tc.args...)
got := buf.String()
assert.Regexp(t, tc.wantedPattern, got)
})
}
}
func TestLoggerWarnf(t *testing.T) {
for _, tc := range formatTestCases {
tc := tc
tc.level = level2.WarnLevel
message := fmt.Sprintf(tc.format, tc.args...)
tc.wantedPattern = fmt.Sprintf("%s %s: %s\n$", pattern, tc.level, message)
t.Run(tc.description, func(t *testing.T) {
var buf bytes.Buffer
logger := NewLogger(newBase(&buf))
logger.Warnf(tc.format, tc.args...)
got := buf.String()
assert.Regexp(t, tc.wantedPattern, got)
})
}
}
func TestLoggerErrorf(t *testing.T) {
for _, tc := range formatTestCases {
tc := tc
tc.level = level2.ErrorLevel
message := fmt.Sprintf(tc.format, tc.args...)
tc.wantedPattern = fmt.Sprintf("%s %s: %s\n$", pattern, tc.level, message)
t.Run(tc.description, func(t *testing.T) {
var buf bytes.Buffer
logger := NewLogger(newBase(&buf))
logger.Errorf(tc.format, tc.args...)
got := buf.String()
assert.Regexp(t, tc.wantedPattern, got)
})
}
}
func TestLoggerFatalf(t *testing.T) {
originalOsExit := osExit
defer func() { osExit = originalOsExit }()
for _, tc := range formatTestCases {
tc := tc
tc.level = level2.FatalLevel
message := fmt.Sprintf(tc.format, tc.args...)
tc.wantedPattern = fmt.Sprintf("%s %s: %s\n$", pattern, tc.level, message)
t.Run(tc.description, func(t *testing.T) {
var buf bytes.Buffer
exitCalled := false
exitCode := 0
osExit = func(code int) {
exitCalled = true
exitCode = code
}
logger := NewLogger(newBase(&buf))
logger.Fatalf(tc.format, tc.args...)
got := buf.String()
assert.Regexp(t, tc.wantedPattern, got)
assert.True(t, exitCalled)
assert.Equal(t, 1, exitCode)
})
}
}
func TestLoggerWithLowerLevels(t *testing.T) {
// Logger should not log messages at a level
// lower than the specified level.
levels := []level2.Level{level2.DebugLevel, level2.WarnLevel, level2.ErrorLevel, level2.FatalLevel}
ops := []struct {
op string
level level2.Level
logFunc func(*Logger)
expected bool
}{
{"Debug", level2.DebugLevel, func(l *Logger) { l.Debug("hello") }, false},
{"Warn", level2.WarnLevel, func(l *Logger) { l.Warn("hello") }, false},
{"Error", level2.ErrorLevel, func(l *Logger) { l.Error("hello") }, false},
{"Fatal", level2.FatalLevel, func(l *Logger) { l.Fatal("hello") }, false},
}
for _, setLevel := range levels {
for _, op := range ops {
var buf bytes.Buffer
logger := NewLogger(newBase(&buf))
logger.SetLevel(setLevel)
expectedOutput := op.level >= setLevel
exitCalled := false
exitCode := 0
osExit = func(code int) {
exitCalled = true
exitCode = code
}
op.logFunc(logger)
output := buf.String()
if expectedOutput {
assert.NotEmpty(t, output)
} else {
assert.Empty(t, output)
}
if op.op == "Fatal" {
assert.True(t, exitCalled)
assert.Equal(t, 1, exitCode)
}
}
}
}