Panel — public source drop (v0.9.0)
Self-hostable game-server control panel: controller + agent + 26 game modules. One-line install (prebuilt release, no Go required): curl -fsSL https://git.pdxtechs.com/dbledeez/panel/raw/branch/main/install.sh | sudo bash Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
package events
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
panelv1 "github.com/dbledeez/panel/proto/panel/v1"
|
||||
)
|
||||
|
||||
func stateEvent(instanceID string) *panelv1.Event {
|
||||
return &panelv1.Event{Payload: &panelv1.Event_InstanceState{
|
||||
InstanceState: &panelv1.InstanceStateUpdate{InstanceId: instanceID},
|
||||
}}
|
||||
}
|
||||
|
||||
func TestRingMonotonicIDsAndSince(t *testing.T) {
|
||||
r := newReplayRing(8)
|
||||
for i := 0; i < 5; i++ {
|
||||
id := r.append(stateEvent(fmt.Sprintf("i%d", i)))
|
||||
if want := uint64(i + 1); id != want {
|
||||
t.Fatalf("append id = %d, want %d", id, want)
|
||||
}
|
||||
}
|
||||
if r.lastID() != 5 {
|
||||
t.Fatalf("lastID = %d, want 5", r.lastID())
|
||||
}
|
||||
out, ok := r.since(2)
|
||||
if !ok {
|
||||
t.Fatalf("since(2) reported a gap on an unfilled ring")
|
||||
}
|
||||
if len(out) != 3 || out[0].ID != 3 || out[2].ID != 5 {
|
||||
t.Fatalf("since(2) = %+v, want ids 3..5", out)
|
||||
}
|
||||
// Fully caught up → empty, gapless.
|
||||
if out, ok := r.since(5); len(out) != 0 || !ok {
|
||||
t.Fatalf("since(lastID) = (%d events, ok=%v), want (0, true)", len(out), ok)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRingOverflowReportsGap(t *testing.T) {
|
||||
r := newReplayRing(4)
|
||||
for i := 0; i < 10; i++ { // ids 1..10; ring retains 7..10
|
||||
r.append(stateEvent("x"))
|
||||
}
|
||||
out, ok := r.since(3)
|
||||
if ok {
|
||||
t.Fatalf("since(3) after overflow should report a gap")
|
||||
}
|
||||
if len(out) != 4 || out[0].ID != 7 || out[3].ID != 10 {
|
||||
t.Fatalf("since(3) = %d events (first=%d), want retained suffix 7..10", len(out), out[0].ID)
|
||||
}
|
||||
// Resume point exactly at oldest-1 is gapless.
|
||||
if _, ok := r.since(6); !ok {
|
||||
t.Fatalf("since(oldest-1) should be gapless")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBusReplayFiltersAndStampedSubscribe(t *testing.T) {
|
||||
b := New(16)
|
||||
sub := b.SubscribeStamped(Filter{InstanceID: "a"})
|
||||
defer sub.Close()
|
||||
|
||||
b.Publish(stateEvent("a")) // id 1
|
||||
b.Publish(stateEvent("b")) // id 2
|
||||
b.Publish(stateEvent("a")) // id 3
|
||||
|
||||
// Stamped subscription only sees matching events, with real ids.
|
||||
got1 := <-sub.Stamped()
|
||||
got2 := <-sub.Stamped()
|
||||
if got1.ID != 1 || got2.ID != 3 {
|
||||
t.Fatalf("stamped ids = %d,%d, want 1,3", got1.ID, got2.ID)
|
||||
}
|
||||
|
||||
// Replay applies the same filter.
|
||||
out, ok := b.Replay(0, Filter{InstanceID: "a"})
|
||||
if !ok || len(out) != 2 || out[0].ID != 1 || out[1].ID != 3 {
|
||||
t.Fatalf("Replay = %+v ok=%v, want ids 1,3 gapless", out, ok)
|
||||
}
|
||||
if b.LastID() != 3 {
|
||||
t.Fatalf("LastID = %d, want 3", b.LastID())
|
||||
}
|
||||
}
|
||||
|
||||
func TestBusDroppedTotal(t *testing.T) {
|
||||
b := New(1)
|
||||
sub := b.Subscribe(Filter{})
|
||||
defer sub.Close()
|
||||
b.Publish(stateEvent("a")) // fills the 1-slot buffer
|
||||
b.Publish(stateEvent("a")) // dropped
|
||||
if b.DroppedTotal() != 1 {
|
||||
t.Fatalf("DroppedTotal = %d, want 1", b.DroppedTotal())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user