Browse Source

Polish up the Run method

pull/1/head
Stephanie Gredell 7 months ago
parent
commit
0fc1b842f4
  1. 35
      internal/simulation/engine.go
  2. 41
      internal/simulation/engine_test.go

35
internal/simulation/engine.go

@ -184,8 +184,13 @@ func (e *Engine) Run() { @@ -184,8 +184,13 @@ func (e *Engine) Run() {
e.Timeline = e.Timeline[:0]
for tick := 0; tick < e.Duration; tick++ {
entries := e.findEntryPoints()
if len(entries) == 0 {
fmt.Println("[ERROR] No entry points found! Simulation will not inject requests.")
}
// inject new requests
for _, node := range e.findEntryPoints() {
for _, node := range entries {
if shouldInject(tick) {
req := &Request{
ID: generateRequestID(tick),
@ -206,23 +211,26 @@ func (e *Engine) Run() { @@ -206,23 +211,26 @@ func (e *Engine) Run() {
}
for id, node := range e.Nodes {
snapshot.NodeHealth[id] = NodeState{
QueueSize: len(node.GetQueue()),
Alive: node.IsAlive(),
}
// tick all nodes
node.Tick(tick, currentTimeMs)
emitted := node.Emit()
// emit and forward requests to connected nodes
for _, req := range emitted {
for _, req := range node.Emit() {
for _, targetID := range node.GetTargets() {
if target, ok := e.Nodes[targetID]; ok && target.IsAlive() {
target.Receive(req)
if target, ok := e.Nodes[targetID]; ok && target.IsAlive() && !hasVisited(req, targetID) {
// Deep copy request and update path
newReq := *req
newReq.Path = append([]string{}, req.Path...)
newReq.Path = append(newReq.Path, targetID)
target.Receive(&newReq)
}
}
}
snapshot.NodeHealth[id] = NodeState{
QueueSize: len(emitted),
Alive: node.IsAlive(),
}
}
e.Timeline = append(e.Timeline, snapshot)
@ -271,3 +279,12 @@ func asString(v interface{}) string { @@ -271,3 +279,12 @@ func asString(v interface{}) string {
return s
}
func hasVisited(req *Request, nodeID string) bool {
for _, id := range req.Path {
if id == nodeID {
return true
}
}
return false
}

41
internal/simulation/engine_test.go

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
package simulation
import (
"fmt"
"os"
"path/filepath"
"testing"
@ -87,3 +88,43 @@ func TestComplexSimulationRun(t *testing.T) { @@ -87,3 +88,43 @@ func TestComplexSimulationRun(t *testing.T) {
}
}
func TestSimulationRunEndToEnd(t *testing.T) {
data, err := os.ReadFile("testdata/simple_design.json")
fmt.Print(data)
if err != nil {
t.Fatalf("Failed to read test data: %v", err)
}
var design design.Design
if err := json.Unmarshal(data, &design); err != nil {
t.Fatalf("Failed to unmarshal JSON: %v", err)
}
engine := NewEngineFromDesign(design, 20, 100) // 20 ticks, 100ms per tick
engine.Run()
if len(engine.Timeline) != 20 {
t.Errorf("Expected 20 timeline entries, got %d", len(engine.Timeline))
}
anyTraffic := false
for _, snapshot := range engine.Timeline {
for _, nodeState := range snapshot.NodeHealth {
if nodeState.QueueSize > 0 {
anyTraffic = true
break
}
}
}
if !anyTraffic {
t.Errorf("Expected at least one node to have non-zero queue size over time")
}
// Optional: check a few expected node IDs
for _, id := range []string{"node-1", "node-2"} {
if _, ok := engine.Nodes[id]; !ok {
t.Errorf("Expected node %s to be present in simulation", id)
}
}
}

Loading…
Cancel
Save