Files
langship.sh/pkg/engine/subgraph_test.go
T

79 lines
2.4 KiB
Go
Raw Normal View History

package engine
import (
"testing"
"github.com/lyzrai/flow/pkg/models"
)
// Loop has two outputs: 0 → body entry, 1 → continuation.
// Layout:
//
// Trigger → Loop → (out0) Body1 → Body2
// └→ (out1) After
func TestGetLoopBody_topologicalAndTerminal(t *testing.T) {
wf := &models.WorkflowDefinition{
Nodes: []models.NodeDef{
{ID: "1", Name: "T", Type: "flow-nodes-base.trigger"},
{ID: "2", Name: "Loop", Type: "flow-nodes-base.splitInBatches"},
{ID: "3", Name: "Body1", Type: "flow-nodes-base.set"},
{ID: "4", Name: "Body2", Type: "flow-nodes-base.noOp"},
{ID: "5", Name: "After", Type: "flow-nodes-base.noOp"},
},
Connections: []models.ConnectionDef{
{SourceNode: "T", TargetNode: "Loop"},
{SourceNode: "Loop", SourceOutputIndex: 0, TargetNode: "Body1"},
{SourceNode: "Body1", TargetNode: "Body2"},
{SourceNode: "Loop", SourceOutputIndex: 1, TargetNode: "After"},
},
}
dag, err := BuildDAG(wf)
if err != nil {
t.Fatalf("build dag: %v", err)
}
body, err := GetLoopBody(dag, "Loop")
if err != nil {
t.Fatalf("body: %v", err)
}
if len(body.Order) != 2 {
t.Fatalf("expected 2 body nodes, got %v", body.Order)
}
// Body1 must come before Body2 in topo order.
idx := map[string]int{}
for i, n := range body.Order {
idx[n] = i
}
if !(idx["Body1"] < idx["Body2"]) {
t.Errorf("expected Body1 before Body2, got %v", body.Order)
}
if !body.Nodes["Body1"] || !body.Nodes["Body2"] {
t.Errorf("body nodes set: %v", body.Nodes)
}
if body.Nodes["After"] {
t.Error("After should NOT be in body (it's behind output 1)")
}
// Body2 has no successors inside the body → terminal.
if len(body.TerminalNodes) != 1 || body.TerminalNodes[0] != "Body2" {
t.Errorf("terminals: %v", body.TerminalNodes)
}
}
func TestGetLoopBody_returnsErrorWithNoBody(t *testing.T) {
wf := &models.WorkflowDefinition{
Nodes: []models.NodeDef{
{ID: "1", Name: "T", Type: "flow-nodes-base.trigger"},
{ID: "2", Name: "Loop", Type: "flow-nodes-base.splitInBatches"},
{ID: "3", Name: "After", Type: "flow-nodes-base.noOp"},
},
Connections: []models.ConnectionDef{
{SourceNode: "T", TargetNode: "Loop"},
// Only output 1 wired — no body.
{SourceNode: "Loop", SourceOutputIndex: 1, TargetNode: "After"},
},
}
dag, _ := BuildDAG(wf)
if _, err := GetLoopBody(dag, "Loop"); err == nil {
t.Fatal("expected error when loop has no body")
}
}