package event import ( "testing" "time" ) func TestExtractK8s(t *testing.T) { raw := []byte(`{"message":"hello from pod","stream":"stdout","timestamp":"2026-07-27T00:00:00Z","kubernetes":{"pod_name":"web-abc","pod_namespace":"shop","container_name":"web","pod_node_name":"node-1"},"ns_token":"shop","cont_token":"web"}`) m := Extract(raw) if m.Host != "node-1" { t.Errorf("host = %q, want node-1 (pod_node_name)", m.Host) } if !m.Ok { t.Fatalf("timestamp not parsed") } if !m.Timestamp.Equal(time.Date(2026, 7, 27, 0, 0, 0, 0, time.UTC)) { t.Errorf("timestamp = %v", m.Timestamp) } } func TestExtractVMHostAndFallbacks(t *testing.T) { raw := []byte(`{"message":"sshd started","host":"vm-db-1","severity":"info","role":"database","host_token":"vm-db-1"}`) m := Extract(raw) if m.Host != "vm-db-1" { t.Errorf("host = %q, want vm-db-1", m.Host) } if m.Ok { t.Errorf("no timestamp field present; Ok should be false") } } func TestExtractHostnameFallback(t *testing.T) { m := Extract([]byte(`{"hostname":"legacy-box","ts":"2026-01-02T03:04:05Z"}`)) if m.Host != "legacy-box" { t.Errorf("host = %q, want legacy-box (hostname fallback)", m.Host) } if !m.Ok || !m.Timestamp.Equal(time.Date(2026, 1, 2, 3, 4, 5, 0, time.UTC)) { t.Errorf("ts fallback failed: ok=%v ts=%v", m.Ok, m.Timestamp) } } func TestExtractHostPrecedence(t *testing.T) { // .host wins over .kubernetes.pod_node_name when both present. m := Extract([]byte(`{"host":"explicit","kubernetes":{"pod_node_name":"node-x"}}`)) if m.Host != "explicit" { t.Errorf("host precedence wrong: %q", m.Host) } } func TestExtractNumericTimestamp(t *testing.T) { // unix millis m := Extract([]byte(`{"host":"h","timestamp":1769472000000}`)) if !m.Ok { t.Fatalf("numeric millis not parsed") } if !m.Timestamp.Equal(time.Date(2026, 1, 27, 0, 0, 0, 0, time.UTC)) { t.Errorf("numeric ts = %v", m.Timestamp.UTC()) } } func TestExtractMalformed(t *testing.T) { m := Extract([]byte(`not json`)) if m.Host != "" || m.Ok { t.Errorf("malformed event should yield zero Meta, got %+v", m) } } func TestExtractEmptyHost(t *testing.T) { m := Extract([]byte(`{"host":"","hostname":"backup"}`)) if m.Host != "backup" { t.Errorf("empty host should fall through to hostname, got %q", m.Host) } } func TestSubjectToken(t *testing.T) { cases := map[string]string{ "logs.k8s.vault.audit": "logs.k8s.vault.audit", "logs.vm.vm-db-1": "logs.vm.vm-db-1", "logs.k8s.a/b.c": "logs.k8s.a_b.c", "": "_", } for in, want := range cases { if got := SubjectToken(in); got != want { t.Errorf("SubjectToken(%q) = %q, want %q", in, got, want) } } }