test: add comprehensive tests to improve coverage
- observability: added tests for LogLevel.String(), Warn(), Warnf(), Infof(), Debugf(), Error(), WithFields(), and concurrent access patterns - file: added tests for Reopen(), Close(), empty/whitespace paths, validateFilePath allowed/rejected paths, concurrent writes, Flush(), and marshal errors - config: added tests for TimeWindowConfig.GetDuration(), CorrelationConfig getters, validation scenarios (no inputs, no outputs, duplicate sockets, ClickHouse validation), and LogConfig.GetLevel() Coverage improvements: - observability: 57.7% → 79.5% - file: 68.6% → 78.6% - config: 69.8% → 97.7% - total: 68.6% → 74.4% Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
@ -140,3 +140,167 @@ func TestLogger_Name(t *testing.T) {
|
||||
t.Errorf("expected prefix 'myservice', got %s", logger.prefix)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLogLevel_String(t *testing.T) {
|
||||
tests := []struct {
|
||||
level LogLevel
|
||||
expected string
|
||||
}{
|
||||
{DEBUG, "DEBUG"},
|
||||
{INFO, "INFO"},
|
||||
{WARN, "WARN"},
|
||||
{ERROR, "ERROR"},
|
||||
{99, "INFO"}, // Unknown level defaults to INFO
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.expected, func(t *testing.T) {
|
||||
result := tt.level.String()
|
||||
if result != tt.expected {
|
||||
t.Errorf("LogLevel(%d).String() = %q, want %q", tt.level, result, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestLogger_Warn(t *testing.T) {
|
||||
logger := NewLoggerWithLevel("test", "WARN")
|
||||
|
||||
// WARN should be logged
|
||||
if !logger.ShouldLog(WARN) {
|
||||
t.Error("WARN should be enabled")
|
||||
}
|
||||
logger.Warn("warning message") // Should not panic
|
||||
}
|
||||
|
||||
func TestLogger_Warnf(t *testing.T) {
|
||||
logger := NewLoggerWithLevel("test", "WARN")
|
||||
logger.Warnf("formatted %s %d", "message", 42) // Should not panic
|
||||
}
|
||||
|
||||
func TestLogger_Infof(t *testing.T) {
|
||||
logger := NewLoggerWithLevel("test", "INFO")
|
||||
logger.Infof("formatted %s %d", "message", 42) // Should not panic
|
||||
}
|
||||
|
||||
func TestLogger_Debugf(t *testing.T) {
|
||||
logger := NewLoggerWithLevel("test", "DEBUG")
|
||||
logger.Debugf("formatted %s %d", "message", 42) // Should not panic
|
||||
|
||||
// Debug disabled
|
||||
logger.SetLevel("INFO")
|
||||
logger.Debugf("should not be logged") // Should not panic
|
||||
}
|
||||
|
||||
func TestLogger_Error_WithError(t *testing.T) {
|
||||
logger := NewLoggerWithLevel("test", "ERROR")
|
||||
testErr := &testError{"test error"}
|
||||
logger.Error("error occurred", testErr) // Should not panic
|
||||
}
|
||||
|
||||
func TestLogger_Error_WithNilError(t *testing.T) {
|
||||
logger := NewLoggerWithLevel("test", "ERROR")
|
||||
logger.Error("error occurred", nil) // Should not panic
|
||||
}
|
||||
|
||||
func TestLogger_WithFields_MergesFields(t *testing.T) {
|
||||
logger := NewLogger("test")
|
||||
logger.fields["existing"] = "value"
|
||||
|
||||
fieldsLogger := logger.WithFields(map[string]any{
|
||||
"new": "field",
|
||||
})
|
||||
|
||||
if len(fieldsLogger.fields) != 2 {
|
||||
t.Errorf("expected 2 fields, got %d", len(fieldsLogger.fields))
|
||||
}
|
||||
if _, ok := fieldsLogger.fields["existing"]; !ok {
|
||||
t.Error("expected existing field to be preserved")
|
||||
}
|
||||
if _, ok := fieldsLogger.fields["new"]; !ok {
|
||||
t.Error("expected new field to be added")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLogger_WithFields_EmptyFields(t *testing.T) {
|
||||
logger := NewLogger("test")
|
||||
fieldsLogger := logger.WithFields(map[string]any{})
|
||||
|
||||
if len(fieldsLogger.fields) != 0 {
|
||||
t.Errorf("expected 0 fields, got %d", len(fieldsLogger.fields))
|
||||
}
|
||||
}
|
||||
|
||||
func TestLogger_ShouldLog_Concurrent(t *testing.T) {
|
||||
logger := NewLoggerWithLevel("test", "DEBUG")
|
||||
|
||||
done := make(chan bool)
|
||||
for i := 0; i < 10; i++ {
|
||||
go func() {
|
||||
_ = logger.ShouldLog(DEBUG)
|
||||
done <- true
|
||||
}()
|
||||
}
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
<-done
|
||||
}
|
||||
}
|
||||
|
||||
func TestLogger_Log_Concurrent(t *testing.T) {
|
||||
logger := NewLoggerWithLevel("test", "DEBUG")
|
||||
|
||||
done := make(chan bool)
|
||||
for i := 0; i < 10; i++ {
|
||||
go func(n int) {
|
||||
logger.Debugf("message %d", n)
|
||||
done <- true
|
||||
}(i)
|
||||
}
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
<-done
|
||||
}
|
||||
}
|
||||
|
||||
func TestLogger_WithFields_Concurrent(t *testing.T) {
|
||||
logger := NewLogger("test")
|
||||
|
||||
done := make(chan bool)
|
||||
for i := 0; i < 10; i++ {
|
||||
go func(n int) {
|
||||
_ = logger.WithFields(map[string]any{"key": n})
|
||||
done <- true
|
||||
}(i)
|
||||
}
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
<-done
|
||||
}
|
||||
}
|
||||
|
||||
func TestLogger_SetLevel_Concurrent(t *testing.T) {
|
||||
logger := NewLogger("test")
|
||||
|
||||
done := make(chan bool)
|
||||
for i := 0; i < 10; i++ {
|
||||
go func() {
|
||||
logger.SetLevel("DEBUG")
|
||||
logger.SetLevel("INFO")
|
||||
done <- true
|
||||
}()
|
||||
}
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
<-done
|
||||
}
|
||||
}
|
||||
|
||||
// testError implements error for testing
|
||||
type testError struct {
|
||||
msg string
|
||||
}
|
||||
|
||||
func (e *testError) Error() string {
|
||||
return e.msg
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user