mirror of
https://github.com/open-policy-agent/opa.git
synced 2026-08-13 03:42:35 -06:00
45c292e834
There are two kinds of else conflicts in the e2e tests, and one had been failing in WASM (i.e., it didn't fail when it should).
With this change to the planner, the underlying issue is resolved:
With multiple rule bodies for one rule like this, where r1 and r2 both fail,
- r1
- else1
- r2
- else2
previously, else1 and else2 checked if the output variable used for both r1 and r2 was defined, and didn't run it was.
Topdown, however, evaluates both else1 and else2, and checks that they have the same outcome.
The output variable checking in WASM would prohibit else2 from being run when the output variable was set by else1.
Now, each rule and its else branches use an output variable different from the overall output; and an extra block writing that output variable's value into the overall output variable of that rule. The extra layering allows each else block to check its rule body's output, and not the overall rule output.
Also:
* planner+wasm: add nop stmt
Useful for debugging planner->ir->compiler->wasm action
* wasm: reuse local variable for separate function bodies+elses
* wasm-e2e: map multiple wasm errors to eval_conflict_error
* planner: fix functon errors with multiple returns (single)
For rule bodies and their else's, the AssignVarOnceStmt would be
no different from the AssignVarStmt -- since it's zeroed by the
starting ResetLocalStmt.
For function bodies involving ScanStmt, it does make a difference,
since it the AssignVarOnceStmt ends up in a its block:
| | *ir.Func g0.data.p.p (3 params: [0 1 3], 3 blocks)
| | | *ir.Block Block (3 statements)
| | | | *ir.ResetLocalStmt &{Target:4 Location:{Index:0 Col:5 Row:3 file:module-0.rego text:p(a) = y}}
| | | | *ir.AssignVarStmt &{Source:3 Target:5 Location:{Index:0 Col:5 Row:3 file:module-0.rego text:p(a) = y}}
| | | | *ir.ScanStmt &{Source:5 Key:6 Value:7 Block:Block (3 statements) Location:{Index:0 Col:7 Row:4 file:module-0.rego text:y = a[_]}}
| | | | | *ir.Block Block (3 statements)
| | | | | | *ir.AssignVarStmt &{Source:6 Target:8 Location:{Index:0 Col:7 Row:4 file:module-0.rego text:y = a[_]}}
| | | | | | *ir.AssignVarStmt &{Source:7 Target:9 Location:{Index:0 Col:7 Row:4 file:module-0.rego text:y = a[_]}}
|H|E|R|E|>| *ir.AssignVarOnceStmt &{Target:4 Source:9 Location:{Index:0 Col:5 Row:3 file:module-0.rego text:p(a) = y}}
| | | *ir.Block Block (2 statements)
| | | | *ir.IsDefinedStmt &{Source:4 Location:{Index:0 Col:5 Row:3 file:module-0.rego text:p(a) = y}}
| | | | *ir.AssignVarOnceStmt &{Target:2 Source:4 Location:{Index:0 Col:5 Row:3 file:module-0.rego text:p(a) = y}}
| | | *ir.Block Block (1 statements)
| | | | *ir.ReturnLocalStmt &{Source:2 Location:{Index:0 Col:5 Row:3 file:module-0.rego text:p(a) = y}}
Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com>
18 lines
333 B
YAML
18 lines
333 B
YAML
cases:
|
|
- data:
|
|
modules:
|
|
- |
|
|
package test1
|
|
|
|
p(a) = y {
|
|
y = a[_]
|
|
}
|
|
|
|
r = y {
|
|
data.test1.p([1, 2, 3], y)
|
|
}
|
|
note: functionerrors/function output conflict single
|
|
query: data.test1.r = x
|
|
want_error: functions must not produce multiple outputs for same inputs
|
|
want_error_code: eval_conflict_error
|