Artifact e21ca0fd4b8566ad69fd6a36ba8867ef56464b5927038a5daad8ce31031d8616:
- File
simio/simclock_test.go
— part of check-in
[f5744359d3]
at
2026-04-19 16:30:54
on branch trunk
— Initial open source release
libfossil is a pure-Go implementation of the Fossil SCM, reading and writing the same .fossil SQLite repository format as upstream Fossil.
This is the first public release of code that previously lived in a private repository. The module path is github.com/danmestas/libfossil and the binary is named libfossil to avoid $PATH collisions with upstream fossil.
Included: - Repo lifecycle (create, clone), checkout/checkin, timeline, merge, diff, annotate, shun, tag, branch, bisect, stash, undo/redo - Sync-over-HTTP protocol (client and handler) - Two SQLite drivers: modernc (pure Go, default) and ncruces (wasm-capable) - Observer interfaces (SyncObserver, CheckoutObserver) with an optional OpenTelemetry implementation in observer/otel (separate submodule) - Deterministic simulation testing harness with BUGGIFY fault injection - Kong-based embeddable CLI under cli/ and a standalone binary under cmd/libfossil/ (user: [email protected], size: 2642) [annotate] [blame] [check-ins using]
package simio import ( "testing" "time" ) func TestSimClockNow(t *testing.T) { c := NewSimClock() if got := c.Now(); !got.Equal(time.Unix(0, 0)) { t.Fatalf("expected epoch, got %v", got) } } func TestSimClockAt(t *testing.T) { start := time.Date(2025, 1, 1, 0, 0, 0, 0, time.UTC) c := NewSimClockAt(start) if got := c.Now(); !got.Equal(start) { t.Fatalf("expected %v, got %v", start, got) } } func TestSimClockAdvance(t *testing.T) { c := NewSimClock() c.Advance(5 * time.Second) want := time.Unix(5, 0) if got := c.Now(); !got.Equal(want) { t.Fatalf("expected %v, got %v", want, got) } } func TestSimClockAdvanceToBackwards(t *testing.T) { c := NewSimClockAt(time.Unix(100, 0)) defer func() { if r := recover(); r == nil { t.Fatal("expected panic for backwards AdvanceTo") } }() c.AdvanceTo(time.Unix(50, 0)) t.Fatal("should not reach here") } func TestSimClockAfterFiresOnAdvance(t *testing.T) { c := NewSimClock() ch := c.After(10 * time.Second) select { case <-ch: t.Fatal("should not fire before advance") default: } c.Advance(10 * time.Second) select { case got := <-ch: if !got.Equal(time.Unix(10, 0)) { t.Fatalf("expected t=10s, got %v", got) } default: t.Fatal("should have fired after advance") } } func TestSimClockAfterZeroDuration(t *testing.T) { c := NewSimClock() ch := c.After(0) select { case <-ch: // ok — zero duration fires immediately default: t.Fatal("After(0) should fire immediately") } } func TestSimClockMultipleWaiters(t *testing.T) { c := NewSimClock() ch5 := c.After(5 * time.Second) ch10 := c.After(10 * time.Second) ch15 := c.After(15 * time.Second) c.Advance(10 * time.Second) // ch5 and ch10 should fire, ch15 should not select { case <-ch5: default: t.Fatal("ch5 should have fired") } select { case <-ch10: default: t.Fatal("ch10 should have fired") } select { case <-ch15: t.Fatal("ch15 should not have fired") default: } if c.PendingCount() != 1 { t.Fatalf("expected 1 pending, got %d", c.PendingCount()) } c.Advance(5 * time.Second) select { case <-ch15: default: t.Fatal("ch15 should have fired after second advance") } if c.PendingCount() != 0 { t.Fatalf("expected 0 pending, got %d", c.PendingCount()) } } func TestSimClockSleep(t *testing.T) { c := NewSimClock() done := make(chan struct{}) go func() { c.Sleep(5 * time.Second) close(done) }() // Give goroutine a moment to register the waiter time.Sleep(10 * time.Millisecond) c.Advance(5 * time.Second) select { case <-done: case <-time.After(time.Second): t.Fatal("Sleep did not unblock after Advance") } }