package logger import ( "bytes" "strings" "testing" "time" ) func TestLogger_Basic(t *testing.T) { var buf bytes.Buffer logger := New() logger.SetOutput(&buf) logger.SetLevel(DEBUG) logger.Info("test message") output := buf.String() if !strings.Contains(output, "INFO") { t.Errorf("expected INFO in output, got %s", output) } if !strings.Contains(output, "test message") { t.Errorf("expected 'test message' in output, got %s", output) } } func TestLogger_WithField(t *testing.T) { var buf bytes.Buffer logger := New() logger.SetOutput(&buf) logger.SetLevel(DEBUG) logger.WithField("key", "value").Info("test with field") output := buf.String() if !strings.Contains(output, "key=value") { t.Errorf("expected 'key=value' in output, got %s", output) } } func TestLogger_WithFields(t *testing.T) { var buf bytes.Buffer logger := New() logger.SetOutput(&buf) logger.SetLevel(DEBUG) logger.WithFields(Fields{ "key1": "value1", "key2": 42, }).Info("test with fields") output := buf.String() if !strings.Contains(output, "key1=value1") { t.Errorf("expected 'key1=value1' in output, got %s", output) } if !strings.Contains(output, "key2=42") { t.Errorf("expected 'key2=42' in output, got %s", output) } } func TestTimingEntry(t *testing.T) { var buf bytes.Buffer logger := New() logger.SetOutput(&buf) logger.SetLevel(DEBUG) timing := logger.BeginTiming("test_operation") time.Sleep(10 * time.Millisecond) timing.End("operation completed") output := buf.String() if !strings.Contains(output, "test_operation") { t.Errorf("expected 'test_operation' in output, got %s", output) } if !strings.Contains(output, "duration_ms") { t.Errorf("expected 'duration_ms' in output, got %s", output) } } func TestErrorHook(t *testing.T) { var buf bytes.Buffer hook := NewErrorHook(&buf, 10) logger := New() logger.AddHook(hook) logger.SetLevel(ERROR) logger.Error("error 1") logger.Error("error 2") logger.Error("error 3") errors := hook.GetErrors() if len(errors) != 3 { t.Errorf("expected 3 errors, got %d", len(errors)) } output := buf.String() if !strings.Contains(output, "error 1") { t.Errorf("expected 'error 1' in output, got %s", output) } } func TestPerformanceHook(t *testing.T) { hook := NewPerformanceHook(50.0) logger := New() logger.AddHook(hook) logger.SetLevel(INFO) logger.WithFields(Fields{ "operation": "fast_op", "duration_ms": 10.0, }).Info("fast operation") logger.WithFields(Fields{ "operation": "slow_op", "duration_ms": 100.0, }).Info("slow operation") slowOps := hook.GetSlowOps() if len(slowOps) != 1 { t.Errorf("expected 1 slow op, got %d", len(slowOps)) } if len(slowOps) > 0 { if slowOps[0]["operation"] != "slow_op" { t.Errorf("expected 'slow_op', got %v", slowOps[0]["operation"]) } } } func TestConcurrentLogging(t *testing.T) { var buf bytes.Buffer logger := New() logger.SetOutput(&buf) logger.SetLevel(DEBUG) done := make(chan bool, 10) for i := 0; i < 10; i++ { go func(id int) { logger.Infof("concurrent log %d", id) done <- true }(i) } for i := 0; i < 10; i++ { <-done } output := buf.String() for i := 0; i < 10; i++ { expected := "concurrent log" if !strings.Contains(output, expected) { t.Errorf("expected '%s' in output, got %s", expected, output) } } }