chore: release v0.26.0
This commit is contained in:
@@ -5,31 +5,50 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
const ms = 1000
|
||||
|
||||
func sec(h, m, s int) uint32 { return uint32((h*3600 + m*60 + s) * ms) }
|
||||
|
||||
// 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.
|
||||
//
|
||||
// The clock is passed IN. The previous version of this test read the real one
|
||||
// and so failed every afternoon — a 23:59:58 stamp seen at 17:00 is genuinely
|
||||
// hours in the future, and no rule can make it otherwise. A suite that is red
|
||||
// for half the day is a suite nobody reads.
|
||||
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)
|
||||
// Just after midnight, a stamp from the last seconds of yesterday.
|
||||
now := time.Date(2026, 3, 14, 0, 0, 1, 0, time.UTC)
|
||||
got := decodeTimeAt(sec(23, 59, 58), now)
|
||||
if want := time.Date(2026, 3, 13, 23, 59, 58, 0, time.UTC); !got.Equal(want) {
|
||||
t.Errorf("23:59:58 seen at 00:00:01 → %s, want %s (yesterday)", got, want)
|
||||
}
|
||||
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)
|
||||
if got.After(now) {
|
||||
t.Errorf("%s is in the future — it would sort to the top of the list for the session", got)
|
||||
}
|
||||
}
|
||||
|
||||
// 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 mirror case: just before midnight, a stamp from the first seconds of
|
||||
// tomorrow. Our clock is still on the old day.
|
||||
func TestDecodeTimeCrossesMidnightBackwards(t *testing.T) {
|
||||
now := time.Date(2026, 3, 13, 23, 59, 58, 0, time.UTC)
|
||||
got := decodeTimeAt(sec(0, 0, 1), now)
|
||||
if want := time.Date(2026, 3, 14, 0, 0, 1, 0, time.UTC); !got.Equal(want) {
|
||||
t.Errorf("00:00:01 seen at 23:59:58 → %s, want %s (tomorrow)", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// The ordinary case, which is every decode that is not within a few seconds of
|
||||
// midnight: the stamp belongs to today and is left alone.
|
||||
func TestDecodeTimeOrdinary(t *testing.T) {
|
||||
now := time.Date(2026, 3, 13, 14, 30, 0, 0, time.UTC)
|
||||
got := decodeTimeAt(sec(14, 29, 45), now)
|
||||
if want := time.Date(2026, 3, 13, 14, 29, 45, 0, time.UTC); !got.Equal(want) {
|
||||
t.Errorf("a stamp close to now → %s, want %s", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,16 +56,15 @@ func TestDecodeTimeCrossesMidnight(t *testing.T) {
|
||||
// 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)) }
|
||||
now := time.Date(2026, 3, 13, 12, 30, 7, 0, time.UTC)
|
||||
at := func(h, m, s int) time.Time { return decodeTimeAt(sec(h, m, s), now) }
|
||||
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))
|
||||
t.Errorf("%s and %s fell in different periods", a, 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")
|
||||
if floor(at(12, 30, 14)) == floor(at(12, 30, 15)) {
|
||||
t.Error("12:30:14 and 12:30:15 are different slots and must not share a period")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user