package models import ( "testing" "time" ) func TestNewLogEntry(t *testing.T) { tests := []struct { name string filename string line string wantLevel string wantTimestamp bool }{ { name: "Log with ISO8601 timestamp and INFO level", filename: "app.log", line: "2025-11-19T10:00:00 INFO Application started", wantLevel: "INFO", wantTimestamp: true, }, { name: "Log with space-separated timestamp and ERROR level", filename: "app.log", line: "2025-11-19 10:00:00 ERROR Connection failed", wantLevel: "ERROR", wantTimestamp: true, }, { name: "Log with DEBUG level", filename: "debug.log", line: "DEBUG: Entering function processRequest", wantLevel: "DEBUG", wantTimestamp: false, }, { name: "Log with WARN level", filename: "app.log", line: "WARN: Memory usage high", wantLevel: "WARN", wantTimestamp: false, }, { name: "Log without level or timestamp", filename: "simple.log", line: "Simple log message", wantLevel: "", wantTimestamp: false, }, { name: "Log with FATAL level", filename: "app.log", line: "FATAL: System crash", wantLevel: "FATAL", wantTimestamp: false, }, { name: "Log with carriage return", filename: "windows.log", line: "Log line with CR\r\n", wantLevel: "", wantTimestamp: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { entry := NewLogEntry(tt.filename, tt.line) if entry.Filename != tt.filename { t.Errorf("Filename = %v, want %v", entry.Filename, tt.filename) } if entry.Level != tt.wantLevel { t.Errorf("Level = %v, want %v", entry.Level, tt.wantLevel) } if tt.wantTimestamp && entry.Timestamp.IsZero() { t.Error("Expected timestamp to be parsed, but got zero value") } if !tt.wantTimestamp && !entry.Timestamp.IsZero() { t.Error("Expected no timestamp, but got one") } // Line should have CR/LF trimmed if entry.Line != tt.line && entry.Line != tt.line[:len(tt.line)-2] { t.Errorf("Line not properly trimmed: %q", entry.Line) } }) } } func TestLogEntry_TimestampString(t *testing.T) { tests := []struct { name string timestamp time.Time line string want string }{ { name: "ISO8601 format", timestamp: time.Date(2025, 11, 19, 10, 0, 0, 0, time.UTC), line: "2025-11-19T10:00:00 INFO Test", want: "2025-11-19T10:00:00", }, { name: "Space-separated format", timestamp: time.Date(2025, 11, 19, 10, 0, 0, 0, time.UTC), line: "2025-11-19 10:00:00 INFO Test", want: "2025-11-19 10:00:00", }, { name: "Zero timestamp", timestamp: time.Time{}, line: "No timestamp", want: "", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { entry := LogEntry{ Filename: "test.log", Line: tt.line, Timestamp: tt.timestamp, } got := entry.TimestampString() if got != tt.want { t.Errorf("TimestampString() = %v, want %v", got, tt.want) } }) } } func BenchmarkNewLogEntry(b *testing.B) { line := "2025-11-19T10:00:00 INFO Application started successfully" filename := "app.log" b.ResetTimer() for i := 0; i < b.N; i++ { _ = NewLogEntry(filename, line) } }