From 5430bc7923ab1b184cdbfbceadf3d31b5387ee68 Mon Sep 17 00:00:00 2001 From: efiten Date: Thu, 17 Sep 2026 16:52:20 +0200 Subject: [PATCH] test(ingestor): anchor the RF-sample fixtures to now, not to a calendar date (#2034) The three ClientRfDeltas tests seeded 2026-08-17T10:00:00.000Z and queried that window back. resolveRxTimeCore (cmd/ingestor/main.go:1527) replaces timestamps older than 30 days with the ingest time, so from 2026-09-16T10:00Z the seeds landed at time.Now() and every delta fell outside the queried window. Master and every open PR went red on it. Fixtures now derive from a package-level base two hours in the past, computed once per test binary so two seeds cannot straddle a second boundary and break the exact WallMillis assertion. Merged by the interim maintainer without a second human reviewer: CI is the only independent check (run 35222316327, ingestor tests ok in 97.033s, race detector ok, no --- FAIL). Fixed dates elsewhere in the ingestor tests are untouched, they assert row counts rather than querying by the seeded date. --- cmd/ingestor/client_rf_sample_test.go | 60 ++++++++++++++++++++------- 1 file changed, 45 insertions(+), 15 deletions(-) diff --git a/cmd/ingestor/client_rf_sample_test.go b/cmd/ingestor/client_rf_sample_test.go index bbc0dc48..1aae0a19 100644 --- a/cmd/ingestor/client_rf_sample_test.go +++ b/cmd/ingestor/client_rf_sample_test.go @@ -5,10 +5,40 @@ import ( "time" ) +// rfFixtureTime returns a sample timestamp offset seconds from a base two +// hours in the past, in the layout the handler round-trips. +// +// The times have to be anchored to now, not to a calendar date. +// resolveRxTimeCore (main.go:1527) replaces any timestamp more than 30 days +// old with the ingest time, so a fixed fixture date stops round-tripping 30 +// days after it is written: the seeded rows land at time.Now() while the query +// window stays in the past, and every delta disappears. The 2026-08-17 +// fixtures this file used to carry did exactly that on 2026-09-16T10:00Z, +// which turned all three delta tests red on master and on every open PR. +// The base is computed once for the whole test binary, not per call: two +// calls straddling a wall-clock second boundary would otherwise sit 16 s +// apart instead of 15 s, and TestRfDeltaBreaksOnReboot asserts the exact +// WallMillis. Truncating to the second keeps the formatted values ending in +// ".000Z", the shape these fixtures have always had. +var rfFixtureBase = time.Now().UTC().Add(-2 * time.Hour).Truncate(time.Second) + +func rfFixtureTime(offset time.Duration) string { + return rfFixtureBase.Add(offset).Format(rxTimeMillisLayout) +} + +// rfFixtureWindow brackets the rfFixtureTime series. Bounds are compared +// lexicographically against millisecond-precision sampled_at values, so they +// must themselves be in the millisecond layout: a second-resolution +// "...:00:00Z" bound would lexicographically exclude "...:00:00.000Z", +// because `.` sorts before `Z`. +func rfFixtureWindow() (from, to string) { + return rfFixtureTime(-time.Hour), rfFixtureTime(time.Hour) +} + func TestHandleClientRfSample(t *testing.T) { s := newTestStore(t) msg := map[string]interface{}{ - "type": "RF_SAMPLE", "timestamp": "2026-08-17T10:00:00.000Z", + "type": "RF_SAMPLE", "timestamp": rfFixtureTime(0), "gps": map[string]interface{}{"lat": 51.2, "lon": 4.4, "acc_m": 8.0}, "stationary": false, "uptime_secs": 84213.0, "noise_floor": -119.0, "rx_air_secs": 20877.0, @@ -46,7 +76,7 @@ func TestHandleClientRfSampleRejects(t *testing.T) { s := newTestStore(t) base := func() map[string]interface{} { return map[string]interface{}{ - "timestamp": "2026-08-17T10:00:00.000Z", + "timestamp": rfFixtureTime(0), "gps": map[string]interface{}{"lat": 51.2, "lon": 4.4}, "uptime_secs": 1.0, } @@ -89,14 +119,12 @@ func TestRfDeltaBreaksOnReboot(t *testing.T) { "rx_air_secs": rxAir, }) } - seed("2026-08-17T10:00:00.000Z", 1000, 500) - seed("2026-08-17T10:00:15.000Z", 1015, 512) // +12 s of RX air over 15 s - seed("2026-08-17T10:00:30.000Z", 10, 3) // rebooted: uptime dropped + seed(rfFixtureTime(0), 1000, 500) + seed(rfFixtureTime(15*time.Second), 1015, 512) // +12 s of RX air over 15 s + seed(rfFixtureTime(30*time.Second), 10, 3) // rebooted: uptime dropped - // Bounds are compared lexicographically against millisecond-precision - // sampled_at values, so they must themselves be in the millisecond layout - // — "10:00:00Z" would lexicographically exclude "10:00:00.000Z" (`.` < `Z`). - deltas, err := s.ClientRfDeltas("aa11", "2026-08-17T00:00:00.000Z", "2026-08-18T00:00:00.000Z") + from, to := rfFixtureWindow() + deltas, err := s.ClientRfDeltas("aa11", from, to) if err != nil { t.Fatalf("deltas: %v", err) } @@ -126,10 +154,11 @@ func TestRfDeltaNilWhenEitherEndpointMissingCounter(t *testing.T) { handleClientRfSample(s, "test", "aa11", msg) } five := int64(5) - seed("2026-08-17T10:00:00.000Z", 1000, nil) // firmware without the counter - seed("2026-08-17T10:00:15.000Z", 1015, &five) + seed(rfFixtureTime(0), 1000, nil) // firmware without the counter + seed(rfFixtureTime(15*time.Second), 1015, &five) - deltas, err := s.ClientRfDeltas("aa11", "2026-08-17T00:00:00.000Z", "2026-08-18T00:00:00.000Z") + from, to := rfFixtureWindow() + deltas, err := s.ClientRfDeltas("aa11", from, to) if err != nil { t.Fatalf("deltas: %v", err) } @@ -156,10 +185,11 @@ func TestClientRfDeltasNormalizesPubkeyCase(t *testing.T) { "rx_air_secs": rxAir, }) } - seed("2026-08-17T10:00:00.000Z", 1000, 500) - seed("2026-08-17T10:00:15.000Z", 1015, 512) + seed(rfFixtureTime(0), 1000, 500) + seed(rfFixtureTime(15*time.Second), 1015, 512) - deltas, err := s.ClientRfDeltas("AA11", "2026-08-17T00:00:00.000Z", "2026-08-18T00:00:00.000Z") + from, to := rfFixtureWindow() + deltas, err := s.ClientRfDeltas("AA11", from, to) if err != nil { t.Fatalf("deltas: %v", err) }