aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/aflow/loop_test.go
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2026-01-23 15:25:16 +0100
committerDmitry Vyukov <dvyukov@google.com>2026-01-24 07:02:54 +0000
commit55a4296bd1fe1c873e4de2d099ab561e5fca592e (patch)
treeb8e7752b90800c8052c5b63a1dd931d0b95421cc /pkg/aflow/loop_test.go
parent8534bc8373e09185ab613e4b39eb1ee6bf6d180c (diff)
pkg/aflow: add DoWhile loop action
DoWhile represents "do { body } while (cond)" loop. See added test for an example.
Diffstat (limited to 'pkg/aflow/loop_test.go')
-rw-r--r--pkg/aflow/loop_test.go96
1 files changed, 96 insertions, 0 deletions
diff --git a/pkg/aflow/loop_test.go b/pkg/aflow/loop_test.go
new file mode 100644
index 000000000..e68191c2b
--- /dev/null
+++ b/pkg/aflow/loop_test.go
@@ -0,0 +1,96 @@
+// Copyright 2026 syzkaller project authors. All rights reserved.
+// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
+
+package aflow
+
+import (
+ "testing"
+)
+
+func TestDoWhile(t *testing.T) {
+ type inputs struct {
+ Bug string
+ }
+ type outputs struct {
+ Diff string
+ }
+ type patchArgs struct {
+ Bug string
+ Diff string
+ TestError string
+ }
+ type patchResults struct {
+ Patch string
+ }
+ type testArgs struct {
+ Patch string
+ }
+ type testResults struct {
+ Diff string
+ TestError string
+ }
+ iter := 0
+ testFlow[inputs, outputs](t, map[string]any{"Bug": "bug"}, map[string]any{"Diff": "diff"},
+ &DoWhile{
+ Do: Pipeline(
+ NewFuncAction("patch-generator", func(ctx *Context, args patchArgs) (patchResults, error) {
+ iter++
+ if iter <= 2 {
+ return patchResults{"bad"}, nil
+ }
+ return patchResults{"good"}, nil
+ }),
+ NewFuncAction("patch-tester", func(ctx *Context, args testArgs) (testResults, error) {
+ if args.Patch == "bad" {
+ return testResults{TestError: "error"}, nil
+ }
+ return testResults{Diff: "diff"}, nil
+ }),
+ ),
+ While: "TestError",
+ },
+ nil,
+ )
+}
+
+func TestDoWhileErrors(t *testing.T) {
+ testRegistrationError[struct{}, struct{}](t,
+ "flow test: action body: no input Missing, available inputs: []",
+ Pipeline(
+ &DoWhile{
+ Do: NewFuncAction("body", func(ctx *Context, args struct {
+ Missing string
+ }) (struct{}, error) {
+ return struct{}{}, nil
+ }),
+ While: "Condition",
+ },
+ ))
+
+ testRegistrationError[struct{ Input string }, struct{}](t,
+ "flow test: action DoWhile: While must not be empty",
+ Pipeline(
+ &DoWhile{
+ Do: NewFuncAction("body", func(ctx *Context, args struct {
+ Input string
+ }) (struct{}, error) {
+ return struct{}{}, nil
+ }),
+ },
+ ))
+
+ type output struct {
+ Output1 string
+ Output2 string
+ }
+ testRegistrationError[struct{}, struct{}](t,
+ "flow test: action body: output Output2 is unused",
+ Pipeline(
+ &DoWhile{
+ Do: NewFuncAction("body", func(ctx *Context, args struct{}) (output, error) {
+ return output{}, nil
+ }),
+ While: "Output1",
+ },
+ ))
+}