mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-07-07 21:17:58 +02:00
108 lines
3.3 KiB
Go
108 lines
3.3 KiB
Go
package workflow
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
)
|
|
|
|
func TestEvalCondition_extendedOperators(t *testing.T) {
|
|
state := newWorkflowLocalState(map[string]interface{}{"score": 9, "message": "status: ok"}, "run-expr")
|
|
state.LastOutput = map[string]any{"output": "asset-123.example.com"}
|
|
|
|
tests := []string{
|
|
"{{inputs.score}} >= 9",
|
|
"{{inputs.message}} contains ok",
|
|
"{{previous.output}} matches ^asset-[0-9]+\\.example\\.com$",
|
|
"{{inputs.score}} > 5 && {{inputs.message}} contains status",
|
|
}
|
|
for _, expr := range tests {
|
|
if err := validateConditionExpression(expr); err != nil {
|
|
t.Fatalf("validate %q: %v", expr, err)
|
|
}
|
|
if !evalCondition(expr, state) {
|
|
t.Fatalf("evalCondition(%q) = false, want true", expr)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestEvalCondition_jsonPathAndJQSafeSubset(t *testing.T) {
|
|
state := newWorkflowLocalState(map[string]interface{}{
|
|
"payload": map[string]any{
|
|
"risk": 9,
|
|
"items": []any{
|
|
map[string]any{"name": "first"},
|
|
},
|
|
},
|
|
}, "run-jsonpath")
|
|
state.LastOutput = map[string]any{"output": `{"status":"ok","score":7}`}
|
|
|
|
tests := []string{
|
|
`jsonpath({{inputs.payload}}, "$.risk") >= 8`,
|
|
`jq({{inputs.payload}}, ".items[0].name") == first`,
|
|
`jsonpath({{previous.output}}, "$.status") == ok`,
|
|
}
|
|
for _, expr := range tests {
|
|
if err := validateConditionExpression(expr); err != nil {
|
|
t.Fatalf("validate %q: %v", expr, err)
|
|
}
|
|
if !evalCondition(expr, state) {
|
|
t.Fatalf("evalCondition(%q) = false, want true", expr)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestMergeUpstreamOutputs_allMerge(t *testing.T) {
|
|
got := mergeUpstreamOutputs(JoinAllMerge, []map[string]any{
|
|
{"output": "a", "left": 1},
|
|
{"output": "b", "right": 2},
|
|
})
|
|
if got["kind"] != "join" || got["strategy"] != JoinAllMerge {
|
|
t.Fatalf("join metadata = %#v", got)
|
|
}
|
|
values, ok := got["output"].([]any)
|
|
if !ok || len(values) != 2 || values[0] != "a" || values[1] != "b" {
|
|
t.Fatalf("merged output = %#v", got["output"])
|
|
}
|
|
if got["left"] != 1 || got["right"] != 2 {
|
|
t.Fatalf("merged fields = %#v", got)
|
|
}
|
|
}
|
|
|
|
func TestMergeUpstreamOutputs_firstNonEmpty(t *testing.T) {
|
|
got := mergeUpstreamOutputs(JoinFirstNonEmpty, []map[string]any{
|
|
{"output": ""},
|
|
{"output": "winner"},
|
|
})
|
|
if got["output"] != "winner" {
|
|
t.Fatalf("output = %#v, want winner", got["output"])
|
|
}
|
|
}
|
|
|
|
func TestDryRunGraphJSON_simulatesUnsafeNodes(t *testing.T) {
|
|
graph := `{
|
|
"nodes": [
|
|
{"id": "start-1", "type": "start", "label": "开始", "position": {"x": 0, "y": 0}, "config": {}},
|
|
{"id": "agent-1", "type": "agent", "label": "Agent", "position": {"x": 0, "y": 80}, "config": {"instruction": "noop", "output_key": "agent_result"}},
|
|
{"id": "out-1", "type": "output", "label": "输出", "position": {"x": 0, "y": 160}, "config": {"output_key": "result", "source_binding": {"from": "outputs", "field": "agent_result"}}}
|
|
],
|
|
"edges": [
|
|
{"id": "e1", "source": "start-1", "target": "agent-1"},
|
|
{"id": "e2", "source": "agent-1", "target": "out-1"}
|
|
]
|
|
}`
|
|
result, err := DryRunGraphJSON(nilContext(), graph, map[string]any{"message": "hello"})
|
|
if err != nil {
|
|
t.Fatalf("DryRunGraphJSON: %v", err)
|
|
}
|
|
if got := result.Outputs["result"]; got != "[dry-run] agent execution skipped" {
|
|
t.Fatalf("result output = %#v", got)
|
|
}
|
|
if len(result.Trace) != 3 {
|
|
t.Fatalf("trace len = %d, want 3", len(result.Trace))
|
|
}
|
|
}
|
|
|
|
func nilContext() context.Context {
|
|
return context.Background()
|
|
}
|