package udp import ( "testing" "time" ) // WSJT-X stamps a decode with a time of DAY and no date, so the date has to come // from our own clock — and around midnight the two disagree. A decode stamped // 23:59:58 that reaches us at 00:00:01 would be dated the NEW day, putting it // almost 24 hours in the future: it would sort to the top of the decodes panel // and stay there for the rest of the session, and its period would never line up // with the ones around it. func TestDecodeTimeCrossesMidnight(t *testing.T) { const ms = 1000 sec := func(h, m, s int) uint32 { return uint32((h*3600 + m*60 + s) * ms) } got := decodeTime(sec(23, 59, 58)) now := time.Now().UTC() // Whatever the clock says, a decode must never land in the future beyond the // slack of a single period, nor more than a day in the past. if d := got.Sub(now); d > time.Minute { t.Errorf("decode at 23:59:58 resolved to %s, %s in the FUTURE", got.Format(time.RFC3339), d) } if d := now.Sub(got); d > 24*time.Hour { t.Errorf("decode at 23:59:58 resolved to %s, %s in the past", got.Format(time.RFC3339), d) } // And the ordinary case: a stamp close to now stays on today. near := decodeTime(sec(now.Hour(), now.Minute(), now.Second())) if diff := near.Sub(now); diff > 2*time.Second || diff < -2*time.Second { t.Errorf("a decode stamped at the current time resolved to %s (%s off)", near.Format(time.RFC3339), diff) } } // The whole point of the timestamp is grouping, so two decodes from the same // fifteen-second slot must floor to the same period however far apart in the // slot they were heard. func TestDecodesInOneSlotShareAPeriod(t *testing.T) { const ms = 1000 at := func(h, m, s int) time.Time { return decodeTime(uint32((h*3600 + m*60 + s) * ms)) } floor := func(x time.Time) int64 { return x.Unix() / 15 * 15 } a, b := at(12, 30, 0), at(12, 30, 14) if floor(a) != floor(b) { t.Errorf("12:30:00 and 12:30:14 fell in different periods (%d vs %d)", floor(a), floor(b)) } c := at(12, 30, 15) if floor(a) == floor(c) { t.Error("12:30:00 and 12:30:15 shared a period — the slot boundary was not honoured") } }