Files
knox/internal/hlc/hlc_test.go
T
david 6845975b7b fix: harden gossip, HLC restarts, watcher races, MCP args, pagination
- gossip: validate push batches (4 MiB / 1000-row caps); reject rows
  claiming the local node id (vector-poisoning), empty ids, negative HCLs
- gossip: reconcile derived state after pulls (pulls only append to the
  observation log, so entry-count comparison could never trigger it)
- hlc: seek clock from persisted MAX(hcl) at Open so a restart with a
  regressed wall clock cannot reissue values (locator/cursor safety)
- db: serialize writers via BEGIN IMMEDIATE DSN, single conn per pool,
  and a per-KnoxDB mutex around RecordObservation's dedup
- watch: atomic ticker guards (was a cross-goroutine data race),
  trailing-edge per-path debounce, recursive directory watches,
  rename re-ingest, remove cancels pending ingests
- mcp: strict argument validation (no silent clamping), thread existence
  checks before writes, nil-safe golden-thread tool
- cli: --page 0 no longer panics; query/recent pagination actually pages
- tests: hlc SeekTo monotonicity, concurrent dedup race, push validation,
  batch caps, idempotency on observation counts
2026-09-17 01:52:06 -07:00

69 lines
1.8 KiB
Go

package hlc
import "testing"
// TestSeekToFutureValueKeepsMonotonic: after resuming from a persisted value
// ahead of the wall clock (clock regression), every subsequent Now must still
// be strictly greater than the resumed position.
func TestSeekToFutureValueKeepsMonotonic(t *testing.T) {
c := New()
resumed := int64(1) << 62 // packed value far ahead of any real wall clock
c.SeekTo(resumed)
prev, _ := c.Now()
if prev <= resumed {
t.Fatalf("first Now after SeekTo = %d, want > resumed %d", prev, resumed)
}
for i := 0; i < 100; i++ {
next, _ := c.Now()
if next <= prev {
t.Fatalf("HLC regressed: %d then %d", prev, next)
}
prev = next
}
}
// TestSeekToLowerValueIgnored: resuming from a value behind the current clock
// (or a fresh 0-padded DB) must not rewind it.
func TestSeekToLowerValueIgnored(t *testing.T) {
c := New()
first, _ := c.Now()
c.SeekTo(0)
second, _ := c.Now()
if second <= first {
t.Fatalf("SeekTo(0) rewound the clock: %d then %d", first, second)
}
// Seek to exactly the last emitted value: the next value must exceed it.
c.SeekTo(second)
third, _ := c.Now()
if third <= second {
t.Fatalf("SeekTo(last) did not preserve monotonicity: %d then %d", second, third)
}
}
// TestSeekToAcrossRestart mirrors Open's reopen path: a fresh clock resumed
// from the persisted max keeps issuing strictly increasing values.
func TestSeekToAcrossRestart(t *testing.T) {
c1 := New()
var last int64
for i := 0; i < 50; i++ {
last, _ = c1.Now()
}
c2 := New() // fresh process clock
c2.SeekTo(last)
prev, _ := c2.Now()
if prev <= last {
t.Fatalf("reopened clock reissued a value: %d <= %d", prev, last)
}
for i := 0; i < 50; i++ {
next, _ := c2.Now()
if next <= prev {
t.Fatalf("reopened clock regressed: %d then %d", prev, next)
}
prev = next
}
}