package httpapi import ( "testing" "time" "github.com/google/uuid" ) // The cursor carries both created_at and entity_id because executions are // ordered by the pair. created_at alone is not unique — several executions can // share a millisecond — and paginating on a non-unique key silently drops or // repeats rows at page boundaries. The previous cursor was the target slug, // which is far less unique still: every execution against the same host shares // it. func TestExecutionCursorRoundTrips(t *testing.T) { created := time.Date(2026, 7, 28, 9, 15, 30, 123456789, time.UTC) id := uuid.MustParse("018f3a2b-0000-7000-8000-000000000042") cursor := formatExecutionCursor(created, id) gotTime, gotID, err := parseExecutionCursor(&cursor) if err != nil { t.Fatalf("parse: %v", err) } if !gotTime.Equal(created) { t.Errorf("time round-trip: got %v, want %v", gotTime, created) } if *gotID != id { t.Errorf("id round-trip: got %v, want %v", *gotID, id) } } func TestExecutionCursorNanosecondsSurvive(t *testing.T) { // Truncating to seconds would make the cursor ambiguous for executions // started in the same second, which is the normal case for a plan whose // steps run back to back. a := time.Date(2026, 7, 28, 9, 15, 30, 1, time.UTC) b := time.Date(2026, 7, 28, 9, 15, 30, 2, time.UTC) id := uuid.New() if formatExecutionCursor(a, id) == formatExecutionCursor(b, id) { t.Error("cursors one nanosecond apart must not collide") } } func TestExecutionCursorRejectsGarbage(t *testing.T) { empty := "" tm, id, err := parseExecutionCursor(&empty) if err != nil || tm != nil || id != nil { t.Errorf("empty cursor should mean 'no cursor', got %v/%v/%v", tm, id, err) } if tm, id, err := parseExecutionCursor(nil); err != nil || tm != nil || id != nil { t.Errorf("nil cursor should mean 'no cursor', got %v/%v/%v", tm, id, err) } for _, bad := range []string{"nonsense", "2026-07-28T09:15:30Z", "notatime,018f3a2b-0000-7000-8000-000000000042", "2026-07-28T09:15:30Z,notauuid"} { b := bad if _, _, err := parseExecutionCursor(&b); err == nil { t.Errorf("cursor %q should have been rejected", bad) } } }