package caddylog import ( "strings" "testing" "time" ) func TestParseLineWithNumericTimestamp(t *testing.T) { t.Parallel() line := `{"ts":1710000000.5,"status":404,"request":{"remote_ip":"198.51.100.10","client_ip":"203.0.113.5","host":"example.test","method":"GET","uri":"/wp-login.php?foo=bar","headers":{"User-Agent":["UnitTestBot/1.0"]}}}` record, err := ParseLine(line) if err != nil { t.Fatalf("parse line: %v", err) } if got, want := record.ClientIP, "203.0.113.5"; got != want { t.Fatalf("unexpected client ip: got %q want %q", got, want) } if got, want := record.RemoteIP, "198.51.100.10"; got != want { t.Fatalf("unexpected remote ip: got %q want %q", got, want) } if got, want := record.Path, "/wp-login.php"; got != want { t.Fatalf("unexpected path: got %q want %q", got, want) } if got, want := record.UserAgent, "UnitTestBot/1.0"; got != want { t.Fatalf("unexpected user agent: got %q want %q", got, want) } if got, want := record.Method, "GET"; got != want { t.Fatalf("unexpected method: got %q want %q", got, want) } expected := time.Unix(1710000000, 500000000).UTC() if !record.OccurredAt.Equal(expected) { t.Fatalf("unexpected timestamp: got %s want %s", record.OccurredAt, expected) } } func TestParseLineWithRFC3339TimestampAndMissingClientIP(t *testing.T) { t.Parallel() line := `{"ts":"2025-03-11T12:13:14.123456Z","status":401,"request":{"remote_ip":"2001:db8::1","host":"git.example.test","method":"POST","uri":"user/login","headers":{"user-agent":["curl/8.0"]}}}` record, err := ParseLine(line) if err != nil { t.Fatalf("parse line: %v", err) } if got, want := record.ClientIP, "2001:db8::1"; got != want { t.Fatalf("unexpected fallback client ip: got %q want %q", got, want) } if got, want := record.Path, "/user/login"; got != want { t.Fatalf("unexpected path: got %q want %q", got, want) } if !strings.Contains(record.RawJSON, `"status":401`) { t.Fatalf("raw json was not preserved") } }