- Add edge runtime config and opsconsole package - Refactor edge console to use new runtime config - Add service source metadata support - Update CLI adapter with target terminology - Add edge operation contract and event bus replay - Update node label and command ops surface - Add E2E smoke tests and full validation - Update proto runtime definitions - Update documentation and agent-ops rules
136 lines
3.9 KiB
Go
136 lines
3.9 KiB
Go
package events_test
|
|
|
|
import (
|
|
"testing"
|
|
|
|
edgeevents "iop/apps/edge/internal/events"
|
|
iop "iop/proto/gen/iop"
|
|
)
|
|
|
|
func TestBusPublishesRunToSpecificAndAllSubscribers(t *testing.T) {
|
|
bus := edgeevents.NewBus()
|
|
specific, unsubscribeSpecific := bus.SubscribeRun("run-1", 1)
|
|
defer unsubscribeSpecific()
|
|
all, unsubscribeAll := bus.SubscribeAllRuns(1)
|
|
defer unsubscribeAll()
|
|
|
|
bus.PublishRun(&iop.RunEvent{RunId: "run-1", Type: "start"})
|
|
|
|
select {
|
|
case event := <-specific:
|
|
if event.GetRunId() != "run-1" {
|
|
t.Fatalf("specific run id: %q", event.GetRunId())
|
|
}
|
|
default:
|
|
t.Fatal("expected specific run subscriber event")
|
|
}
|
|
select {
|
|
case event := <-all:
|
|
if event.GetRunId() != "run-1" {
|
|
t.Fatalf("all run id: %q", event.GetRunId())
|
|
}
|
|
default:
|
|
t.Fatal("expected all run subscriber event")
|
|
}
|
|
}
|
|
|
|
func TestBusCountsDroppedRunEvents(t *testing.T) {
|
|
bus := edgeevents.NewBus()
|
|
_, unsubscribe := bus.SubscribeRun("run-1", 1)
|
|
defer unsubscribe()
|
|
|
|
// First event fills the buffer; subsequent ones are dropped until drained.
|
|
bus.PublishRun(&iop.RunEvent{RunId: "run-1", Type: "start"})
|
|
bus.PublishRun(&iop.RunEvent{RunId: "run-1", Type: "chunk-1"})
|
|
bus.PublishRun(&iop.RunEvent{RunId: "run-1", Type: "chunk-2"})
|
|
|
|
stats := bus.Stats()
|
|
if stats.DroppedRunEvents != 2 {
|
|
t.Fatalf("DroppedRunEvents: got %d want 2", stats.DroppedRunEvents)
|
|
}
|
|
if stats.DroppedNodeEvents != 0 {
|
|
t.Fatalf("DroppedNodeEvents: got %d want 0", stats.DroppedNodeEvents)
|
|
}
|
|
}
|
|
|
|
func TestBusCountsDroppedNodeEvents(t *testing.T) {
|
|
bus := edgeevents.NewBus()
|
|
_, unsubscribe := bus.SubscribeNode("node-1", 1)
|
|
defer unsubscribe()
|
|
|
|
bus.PublishNode(&iop.EdgeNodeEvent{NodeId: "node-1", Type: "node.connected"})
|
|
bus.PublishNode(&iop.EdgeNodeEvent{NodeId: "node-1", Type: "node.disconnected"})
|
|
bus.PublishNode(&iop.EdgeNodeEvent{NodeId: "node-1", Type: "node.reconnected"})
|
|
|
|
stats := bus.Stats()
|
|
if stats.DroppedNodeEvents != 2 {
|
|
t.Fatalf("DroppedNodeEvents: got %d want 2", stats.DroppedNodeEvents)
|
|
}
|
|
if stats.DroppedRunEvents != 0 {
|
|
t.Fatalf("DroppedRunEvents: got %d want 0", stats.DroppedRunEvents)
|
|
}
|
|
}
|
|
|
|
func TestBusReplaysRecentRunEvents(t *testing.T) {
|
|
bus := edgeevents.NewBus()
|
|
|
|
bus.PublishRun(&iop.RunEvent{RunId: "run-1", Type: "start"})
|
|
bus.PublishRun(&iop.RunEvent{RunId: "run-2", Type: "start"})
|
|
bus.PublishRun(&iop.RunEvent{RunId: "run-1", Type: "complete"})
|
|
|
|
replay := bus.ReplayRun("run-1")
|
|
if len(replay) != 2 {
|
|
t.Fatalf("ReplayRun len: got %d want 2", len(replay))
|
|
}
|
|
if replay[0].GetType() != "start" || replay[1].GetType() != "complete" {
|
|
t.Fatalf("replay order: got [%q,%q] want [start,complete]", replay[0].GetType(), replay[1].GetType())
|
|
}
|
|
|
|
if got := bus.ReplayRun("missing"); got != nil {
|
|
t.Fatalf("expected nil replay for unknown run, got %v", got)
|
|
}
|
|
}
|
|
|
|
func TestBusReplayIsBounded(t *testing.T) {
|
|
const cap = 3
|
|
bus := edgeevents.NewBusWithReplayCapacity(cap)
|
|
|
|
for i := 0; i < cap+5; i++ {
|
|
bus.PublishRun(&iop.RunEvent{RunId: "run-1", Type: "tick"})
|
|
bus.PublishNode(&iop.EdgeNodeEvent{NodeId: "node-1", Type: "tick"})
|
|
}
|
|
|
|
if got := bus.ReplayRun("run-1"); len(got) != cap {
|
|
t.Fatalf("ReplayRun len: got %d want %d", len(got), cap)
|
|
}
|
|
if got := bus.ReplayNode("node-1"); len(got) != cap {
|
|
t.Fatalf("ReplayNode len: got %d want %d", len(got), cap)
|
|
}
|
|
}
|
|
|
|
func TestBusPublishesNodeToSpecificAndAllSubscribers(t *testing.T) {
|
|
bus := edgeevents.NewBus()
|
|
specific, unsubscribeSpecific := bus.SubscribeNode("node-1", 1)
|
|
defer unsubscribeSpecific()
|
|
all, unsubscribeAll := bus.SubscribeAllNodes(1)
|
|
defer unsubscribeAll()
|
|
|
|
bus.PublishNode(&iop.EdgeNodeEvent{NodeId: "node-1", Type: "node.disconnected"})
|
|
|
|
select {
|
|
case event := <-specific:
|
|
if event.GetNodeId() != "node-1" {
|
|
t.Fatalf("specific node id: %q", event.GetNodeId())
|
|
}
|
|
default:
|
|
t.Fatal("expected specific node subscriber event")
|
|
}
|
|
select {
|
|
case event := <-all:
|
|
if event.GetNodeId() != "node-1" {
|
|
t.Fatalf("all node id: %q", event.GetNodeId())
|
|
}
|
|
default:
|
|
t.Fatal("expected all node subscriber event")
|
|
}
|
|
}
|