diff --git a/test/cases/testdata/v0/regoparsemodule/test-regoparsemodule-0320.yaml b/test/cases/testdata/v0/regoparsemodule/test-regoparsemodule-0320.yaml index b778ed6236..2ad66da1b7 100644 --- a/test/cases/testdata/v0/regoparsemodule/test-regoparsemodule-0320.yaml +++ b/test/cases/testdata/v0/regoparsemodule/test-regoparsemodule-0320.yaml @@ -1,7 +1,13 @@ --- cases: - data: - ok: "package foo.bar\n\n\t\timport data.a\n\n\t\tp { a = true }" + ok: |- + package foo.bar + + import rego.v1 + import data.a + + p if { a = true } modules: - | package generated diff --git a/test/cases/testdata/v1/regoparsemodule/test-regoparsemodule-0320.yaml b/test/cases/testdata/v1/regoparsemodule/test-regoparsemodule-0320.yaml index ecac1f0b02..90724f113b 100644 --- a/test/cases/testdata/v1/regoparsemodule/test-regoparsemodule-0320.yaml +++ b/test/cases/testdata/v1/regoparsemodule/test-regoparsemodule-0320.yaml @@ -15,8 +15,9 @@ cases: ok: |- package foo.bar - import data.a + import rego.v1 + import data.a - p { a = true } + p if { a = true } want_result: - x: foo diff --git a/topdown/cidr_test.go b/topdown/cidr_test.go index 1bbabeaa73..ac80412a87 100644 --- a/topdown/cidr_test.go +++ b/topdown/cidr_test.go @@ -18,7 +18,7 @@ func TestNetCIDRExpandCancellation(t *testing.T) { ` package test - p { net.cidr_expand("1.0.0.0/1") } # generating 2**31 hosts will take a while... + p if { net.cidr_expand("1.0.0.0/1") } # generating 2**31 hosts will take a while... `, }) diff --git a/topdown/eval_test.go b/topdown/eval_test.go index acbb06c806..b672bbf551 100644 --- a/topdown/eval_test.go +++ b/topdown/eval_test.go @@ -261,7 +261,7 @@ func TestTopdownVirtualCache(t *testing.T) { note: "different args", module: `package p f(0) = 1 - f(x) = 12 { x > 0 }`, + f(x) = 12 if { x > 0 }`, query: `data.p.f(0); data.p.f(1)`, hit: 0, miss: 2, @@ -270,7 +270,7 @@ func TestTopdownVirtualCache(t *testing.T) { note: "same args", module: `package p f(0) = 1 - f(x) = 12 { x > 0 }`, + f(x) = 12 if { x > 0 }`, query: `data.p.f(1); data.p.f(1)`, hit: 1, miss: 1, @@ -279,7 +279,7 @@ func TestTopdownVirtualCache(t *testing.T) { note: "captured output", module: `package p f(0) = 1 - f(x) = 12 { x > 0 }`, + f(x) = 12 if { x > 0 }`, query: `data.p.f(0); data.p.f(0, x)`, hit: 1, miss: 1, @@ -288,8 +288,8 @@ func TestTopdownVirtualCache(t *testing.T) { { note: "captured output, bool(false) result", module: `package p - g(x) = true { x > 0 } - g(x) = false { x <= 0 }`, + g(x) = true if { x > 0 } + g(x) = false if { x <= 0 }`, query: `data.p.g(-1, x); data.p.g(-1, y)`, hit: 1, miss: 1, @@ -299,8 +299,8 @@ func TestTopdownVirtualCache(t *testing.T) { note: "same args, iteration case", module: `package p f(0) = 1 - f(x) = 12 { x > 0 } - q = y { + f(x) = 12 if { x > 0 } + q = y if { x := f(1) y := f(1) x == y @@ -313,7 +313,7 @@ func TestTopdownVirtualCache(t *testing.T) { { note: "cache invalidation", module: `package p - f(x) = y { x+input = y }`, + f(x) = y if { x+input = y }`, query: `data.p.f(1, z) with input as 7; data.p.f(1, z2) with input as 8`, hit: 0, miss: 2, @@ -321,8 +321,8 @@ func TestTopdownVirtualCache(t *testing.T) { { note: "partial object: simple", module: `package p - s["foo"] = true { true } - s["bar"] = true { true }`, + s["foo"] = true if { true } + s["bar"] = true if { true }`, query: `data.p.s["foo"]; data.p.s["foo"]`, hit: 1, miss: 1, @@ -330,8 +330,8 @@ func TestTopdownVirtualCache(t *testing.T) { { note: "partial object: query into object value", module: `package p - s["foo"] = { "x": 42, "y": 43 } { true } - s["bar"] = { "x": 42, "y": 43 } { true }`, + s["foo"] = { "x": 42, "y": 43 } if { true } + s["bar"] = { "x": 42, "y": 43 } if { true }`, query: `data.p.s["foo"].x = x; data.p.s["foo"].y`, hit: 1, miss: 1, @@ -340,7 +340,7 @@ func TestTopdownVirtualCache(t *testing.T) { { note: "partial object: simple, general ref", module: `package p - s.t[u].v = true { x = ["foo", "bar"]; u = x[_] }`, + s.t[u].v = true if { x = ["foo", "bar"]; u = x[_] }`, query: `data.p.s.t["foo"].v = x; data.p.s.t["foo"].v`, hit: 1, miss: 1, @@ -349,7 +349,7 @@ func TestTopdownVirtualCache(t *testing.T) { { note: "partial object: simple, general ref, multiple vars", module: `package p - s.t[u].v[w] = true { x = ["foo", "bar"]; u = x[_]; y = ["do", "re"]; w = y[_] }`, + s.t[u].v[w] = true if { x = ["foo", "bar"]; u = x[_]; y = ["do", "re"]; w = y[_] }`, query: `data.p.s.t = x; data.p.s.t`, hit: 1, miss: 1, @@ -371,7 +371,7 @@ func TestTopdownVirtualCache(t *testing.T) { { note: "partial object: simple, general ref, multiple vars (2)", module: `package p - s.t[u].v[w] = true { x = ["foo", "bar"]; u = x[_]; y = ["do", "re"]; w = y[_] }`, + s.t[u].v[w] = true if { x = ["foo", "bar"]; u = x[_]; y = ["do", "re"]; w = y[_] }`, query: `data.p.s.t.foo = x; data.p.s.t["foo"]`, hit: 1, miss: 1, @@ -385,7 +385,7 @@ func TestTopdownVirtualCache(t *testing.T) { { note: "partial object: simple, general ref, multiple vars (3)", module: `package p - s.t[u].v[w] = true { x = ["foo", "bar"]; u = x[_]; y = ["do", "re"]; w = y[_] }`, + s.t[u].v[w] = true if { x = ["foo", "bar"]; u = x[_]; y = ["do", "re"]; w = y[_] }`, query: `data.p.s.t.foo.v = x; data.p.s.t["foo"].v`, hit: 1, miss: 1, @@ -397,7 +397,7 @@ func TestTopdownVirtualCache(t *testing.T) { { note: "partial object: simple, general ref, multiple vars (4)", module: `package p - s.t[u].v[w] = true { x = ["foo", "bar"]; u = x[_]; y = ["do", "re"]; w = y[_] }`, + s.t[u].v[w] = true if { x = ["foo", "bar"]; u = x[_]; y = ["do", "re"]; w = y[_] }`, query: `data.p.s.t.foo.v.re = x; data.p.s.t["foo"].v["re"]`, hit: 1, miss: 1, @@ -406,7 +406,7 @@ func TestTopdownVirtualCache(t *testing.T) { { note: "partial object: simple, general ref, miss", module: `package p - s.t[u].v[w] = true { x = ["foo", "bar"]; u = x[_]; y = ["do", "re"]; w = y[_] }`, + s.t[u].v[w] = true if { x = ["foo", "bar"]; u = x[_]; y = ["do", "re"]; w = y[_] }`, query: `data.p.s.t.foo.v.re = x; data.p.s.t.foo.v.do`, hit: 0, miss: 2, @@ -415,7 +415,7 @@ func TestTopdownVirtualCache(t *testing.T) { { note: "partial object: simple, general ref, miss (2)", module: `package p - s.t[u].v[w] = i { x = ["foo", "bar"]; u = x[_]; y = ["do", "re"]; w = y[i] }`, + s.t[u].v[w] = i if { x = ["foo", "bar"]; u = x[_]; y = ["do", "re"]; w = y[i] }`, query: `data.p.s.t.foo.v.re = x; data.p.s.t.foo.v.do; data.p.s.t.foo.v.re`, hit: 1, miss: 2, @@ -424,7 +424,7 @@ func TestTopdownVirtualCache(t *testing.T) { { note: "partial object: simple, general ref, miss (3)", module: `package p - s.t[u].v[w] = i { x = ["foo", "bar"]; u = x[_]; y = ["do", "re"]; w = y[i] }`, + s.t[u].v[w] = i if { x = ["foo", "bar"]; u = x[_]; y = ["do", "re"]; w = y[i] }`, query: `data.p.s.t.foo.v.re = x; data.p.s.t.foo.v.do; data.p.s.t.bar.v.re`, hit: 0, miss: 3, @@ -433,7 +433,7 @@ func TestTopdownVirtualCache(t *testing.T) { { note: "partial object: simple, general ref, miss (3)", module: `package p - s.t[u].v[w] = i { x = ["foo", "bar"]; u = x[_]; y = ["do", "re"]; w = y[i] }`, + s.t[u].v[w] = i if { x = ["foo", "bar"]; u = x[_]; y = ["do", "re"]; w = y[i] }`, query: `data.p.s.t.foo.v.re = x; data.p.s.t.foo.v.do; data.p.s.t.bar.v.re; data.p.s.t.foo.v.do`, hit: 1, miss: 3, @@ -442,7 +442,7 @@ func TestTopdownVirtualCache(t *testing.T) { { note: "partial object: simple, general ref, miss (4)", module: `package p - s.t[u].v[w] = i { x = ["foo", "bar"]; u = x[_]; y = ["do", "re"]; w = y[i] }`, + s.t[u].v[w] = i if { x = ["foo", "bar"]; u = x[_]; y = ["do", "re"]; w = y[i] }`, query: `data.p.s.t.foo = x; data.p.s.t.foo.v.do`, hit: 1, miss: 1, @@ -456,7 +456,7 @@ func TestTopdownVirtualCache(t *testing.T) { { note: "partial object: simple, general ref, miss (5)", module: `package p - s.t[u].v[w] = i { x = ["foo", "bar"]; u = x[_]; y = ["do", "re"]; w = y[i] }`, + s.t[u].v[w] = i if { x = ["foo", "bar"]; u = x[_]; y = ["do", "re"]; w = y[i] }`, query: `data.p.s.t.foo; data.p.s.t.foo.v.do = x`, hit: 1, miss: 1, @@ -465,7 +465,7 @@ func TestTopdownVirtualCache(t *testing.T) { { note: "partial object: simple, general ref, miss (6)", module: `package p - s.t[u].v[w] = i { x = ["foo", "bar"]; u = x[_]; y = ["do", "re"]; w = y[i] }`, + s.t[u].v[w] = i if { x = ["foo", "bar"]; u = x[_]; y = ["do", "re"]; w = y[i] }`, query: `data.p.s.t.foo.v.do = x; data.p.s.t.foo`, hit: 0, // Note: Could we be smart in query term eval order to gain an extra hit here? miss: 2, @@ -474,8 +474,8 @@ func TestTopdownVirtualCache(t *testing.T) { { note: "partial object: simple, query into value", module: `package p - s["foo"].t = { "x": 42, "y": 43 } { true } - s["bar"].t = { "x": 42, "y": 43 } { true }`, + s["foo"].t = { "x": 42, "y": 43 } if { true } + s["bar"].t = { "x": 42, "y": 43 } if { true }`, query: `data.p.s["foo"].t.x = x; data.p.s["foo"].t.x`, hit: 1, miss: 1, @@ -484,8 +484,8 @@ func TestTopdownVirtualCache(t *testing.T) { { note: "partial set: simple", module: `package p - s["foo"] { true } - s["bar"] { true }`, + s contains "foo" if { true } + s contains "bar" if { true }`, query: `data.p.s["foo"]; data.p.s["foo"]`, hit: 1, miss: 1, @@ -493,7 +493,7 @@ func TestTopdownVirtualCache(t *testing.T) { { note: "partial set: object", module: `package p - s[z] { z := {"foo": "bar"} }`, + s contains z if { z := {"foo": "bar"} }`, query: `x = {"foo": "bar"}; data.p.s[x]; data.p.s[x]`, hit: 1, miss: 1, @@ -501,7 +501,7 @@ func TestTopdownVirtualCache(t *testing.T) { { note: "partial set: miss", module: `package p - s[z] { z = true }`, + s contains z if { z = true }`, query: `data.p.s[true]; not data.p.s[false]`, hit: 0, miss: 2, @@ -509,8 +509,8 @@ func TestTopdownVirtualCache(t *testing.T) { { note: "partial set: full extent cached", module: `package test - p[x] { x = 1 } - p[x] { x = 2 } + p contains x if { x = 1 } + p contains x if { x = 2 } `, query: "data.test.p = x; data.test.p = y", hit: 1, @@ -519,9 +519,9 @@ func TestTopdownVirtualCache(t *testing.T) { { note: "partial set: all rules + each rule (non-ground var) cached", module: `package test - p = r { data.test.q = x; data.test.q[y] = z; data.test.q[a] = b; r := true } - q[x] { x = 1 } - q[x] { x = 2 } + p = r if { data.test.q = x; data.test.q[y] = z; data.test.q[a] = b; r := true } + q contains x if { x = 1 } + q contains x if { x = 2 } `, query: "data.test.p = true", hit: 3, // 'data.test.q[y] = z' + 2x 'data.test.q[a] = b' @@ -530,9 +530,9 @@ func TestTopdownVirtualCache(t *testing.T) { { note: "partial set: all rules + each rule (non-ground composite) cached", module: `package test - p { data.test.q = x; data.test.q[[y, 1]] = z; data.test.q[[a, 2]] = b } - q[[x, x]] { x = 1 } - q[[x, x]] { x = 2 } + p if { data.test.q = x; data.test.q[[y, 1]] = z; data.test.q[[a, 2]] = b } + q contains [x, x] if { x = 1 } + q contains [x, x] if { x = 2 } `, query: "data.test.p = true", hit: 2, // 'data.test.q[[y,1]] = z' + 'data.test.q[[a, 2]] = b' @@ -541,9 +541,9 @@ func TestTopdownVirtualCache(t *testing.T) { { note: "partial set: each rule (non-ground var), full extent cached", module: `package test - p = r { data.test.q[y] = z; data.test.q = x; r := true } - q[x] { x = 1 } - q[x] { x = 2 } + p = r if { data.test.q[y] = z; data.test.q = x; r := true } + q contains x if { x = 1 } + q contains x if { x = 2 } `, query: "data.test.p = x", hit: 2, // 2x 'data.test.q = x' @@ -552,9 +552,9 @@ func TestTopdownVirtualCache(t *testing.T) { { note: "partial set: each rule (non-ground composite), full extent cached", module: `package test - p = y { data.test.q[[y, 1]] = z; data.test.q = x } - q[[x, x]] { x = 1 } - q[[x, x]] { x = 2 } + p = y if { data.test.q[[y, 1]] = z; data.test.q = x } + q contains [x, x] if { x = 1 } + q contains [x, x] if { x = 2 } `, query: "data.test.p = x", hit: 0, @@ -564,7 +564,6 @@ func TestTopdownVirtualCache(t *testing.T) { { note: "partial object, ref-head, ref with unification scope", module: `package test - import rego.v1 a[x][y][z] := x + y + z if { some x in [1, 2] @@ -585,7 +584,6 @@ func TestTopdownVirtualCache(t *testing.T) { { note: "partial object, ref-head, ref with unification scope, component order", module: `package test - import rego.v1 a[x][y][a][b] := i if { some x in [1, 2] @@ -606,7 +604,6 @@ func TestTopdownVirtualCache(t *testing.T) { { note: "partial object, ref-head, ref with unification scope, diverging key scope", module: `package test - import rego.v1 a[x][y][z] := x + y + z if { some x in [1, 2] @@ -628,7 +625,6 @@ func TestTopdownVirtualCache(t *testing.T) { { note: "partial object, ref-head, ref with unification scope, trailing vars don't contribute to key scope", module: `package test - import rego.v1 a[x][y][z][x] := x + y + z if { some x in [1, 2] @@ -649,7 +645,6 @@ func TestTopdownVirtualCache(t *testing.T) { // Regression test for https://github.com/open-policy-agent/opa/issues/6926 note: "partial object, ref-head, leaf set, ref with unification scope", module: `package p - import rego.v1 obj.sub[x][x] contains x if some x in ["one", "two"] @@ -716,7 +711,7 @@ func TestPartialRule(t *testing.T) { { note: "partial set", module: `package test - p[v] { + p contains v if { v := [1, 2, 3][_] } `, @@ -726,7 +721,7 @@ func TestPartialRule(t *testing.T) { { note: "partial object", module: `package test - p[i] := v { + p[i] := v if { v := [1, 2, 3][i] } `, @@ -736,7 +731,7 @@ func TestPartialRule(t *testing.T) { { note: "partial object (const key)", module: `package test - p["foo"] := v { + p["foo"] := v if { v := 42 } `, @@ -746,7 +741,7 @@ func TestPartialRule(t *testing.T) { { note: "ref head", module: `package test - p.foo := v { + p.foo := v if { v := 42 } `, @@ -756,7 +751,7 @@ func TestPartialRule(t *testing.T) { { note: "partial object (ref head)", module: `package test - p.q.r[i] := v { + p.q.r[i] := v if { v := ["a", "b", "c"][i] } `, @@ -766,7 +761,7 @@ func TestPartialRule(t *testing.T) { { note: "partial object (ref head), query to obj root", module: `package test - p.q.r[i] := v { + p.q.r[i] := v if { v := ["a", "b", "c"][i] } `, @@ -776,7 +771,7 @@ func TestPartialRule(t *testing.T) { { note: "partial object (ref head), query to obj root, enumerating keys", module: `package test - p.q.r[i] := v { + p.q.r[i] := v if { v := ["a", "b", "c"][i] } `, @@ -787,7 +782,7 @@ func TestPartialRule(t *testing.T) { { note: "partial object (ref head), implicit 'true' value", module: `package test - p.q.r[v] { + p.q.r[v] if { v := [1, 2, 3][_] } `, @@ -832,7 +827,7 @@ func TestPartialRule(t *testing.T) { { note: "partial object (general ref head, multiple vars)", module: `package test - p.q[x].r[i] := v { + p.q[x].r[i] := v if { some i v := [1, 2, 3][i] x := ["a", "b", "c"][_] @@ -844,7 +839,7 @@ func TestPartialRule(t *testing.T) { { note: "partial object (general ref head, multiple vars) #2", module: `package test - p[j].foo[i] := v { + p[j].foo[i] := v if { v := [1, 2, 3][i] j := ["a", "b", "c"][_] } @@ -869,7 +864,7 @@ func TestPartialRule(t *testing.T) { { note: "partial object with overlapping rule (defining key/value in object)", module: `package test - foo.bar[i] := v { + foo.bar[i] := v if { v := ["a", "b", "c"][i] } foo.bar.baz := 42 @@ -880,7 +875,7 @@ func TestPartialRule(t *testing.T) { { note: "partial object with overlapping rule (dee ref on overlap)", module: `package test - p[k] := 1 { + p[k] := 1 if { k := "foo" } p.q.r.s.t := 42 @@ -891,7 +886,7 @@ func TestPartialRule(t *testing.T) { { note: "partial object with overlapping rule (dee ref on overlap; conflict)", module: `package test - p[k] := 1 { + p[k] := 1 if { k := "q" } p.q.r.s.t := 42 @@ -902,7 +897,7 @@ func TestPartialRule(t *testing.T) { { note: "partial object with overlapping rule (key conflict)", module: `package test - foo.bar[k] := v { + foo.bar[k] := v if { k := "a" v := 43 } @@ -914,10 +909,10 @@ func TestPartialRule(t *testing.T) { { note: "partial object generating conflicting nested keys (different nested object depth)", module: `package test - p.q.r { + p.q.r if { true } - p.q[r].s.t { + p.q[r].s.t if { r := "foo" }`, query: `data = x`, @@ -926,10 +921,10 @@ func TestPartialRule(t *testing.T) { { note: "partial object generating conflicting nested keys (different nested object depth; key conflict)", module: `package test - p.q[k].s := 1 { + p.q[k].s := 1 if { k := "r" } - p.q[k].s.t := 1 { + p.q[k].s.t := 1 if { k := "r" }`, query: `data = x`, @@ -938,14 +933,14 @@ func TestPartialRule(t *testing.T) { { note: "partial object (overlapping rules producing same values)", module: `package test - p.foo.bar[i] := v { + p.foo.bar[i] := v if { v := ["a", "b", "c"][i] } - p.foo[i][j] := v { + p.foo[i][j] := v if { i := "bar" v := ["a", "b", "c"][j] } - p[q][i][j] := v { + p[q][i][j] := v if { q := "foo" i := "bar" v := ["a", "b", "c"][j] @@ -957,10 +952,10 @@ func TestPartialRule(t *testing.T) { { note: "partial object (overlapping rules, same depth, producing non-conflicting keys)", module: `package test - p.foo[i].bar := v { + p.foo[i].bar := v if { v := ["a", "b", "c"][i] } - p.foo.bar[i] := v { + p.foo.bar[i] := v if { v := ["a", "b", "c"][i] } `, @@ -976,7 +971,7 @@ func TestPartialRule(t *testing.T) { note: "partial object NOT intersecting with object value of other rule", module: `package test p.foo := {"bar": {"baz": 1}} - p[k] := 2 {k := "other"} + p[k] := 2 if {k := "other"} `, query: `data = x`, exp: `[{"x": {"test": {"p": {"foo": {"bar": {"baz": 1}}, "other": 2}}}}]`, @@ -985,7 +980,7 @@ func TestPartialRule(t *testing.T) { note: "partial object NOT intersecting with object value of other rule (nested object merge along rule refs)", module: `package test p.foo.bar := {"baz": 1} # p.foo.bar == {"baz": 1} - p[k].bar2 := v {k := "foo"; v := {"other": 2}} # p.foo.bar2 == {"other": 2} + p[k].bar2 := v if {k := "foo"; v := {"other": 2}} # p.foo.bar2 == {"other": 2} `, query: `data = x`, exp: `[{"x": {"test": {"p": {"foo": {"bar": {"baz": 1}, "bar2": {"other": 2}}}}}}]`, @@ -994,7 +989,7 @@ func TestPartialRule(t *testing.T) { note: "partial object intersecting with object value of other rule (not merging otherwise conflict-free obj values)", module: `package test p.foo := {"bar": {"baz": 1}} # p == {"foo": {"bar": {"baz": 1}}} - p[k] := v {k := "foo"; v := {"bar": {"other": 2}}} # p == {"foo": {"bar": {"other": 2}}} + p[k] := v if {k := "foo"; v := {"bar": {"other": 2}}} # p == {"foo": {"bar": {"other": 2}}} `, query: `data = x`, expErr: "eval_conflict_error: object keys must be unique", // conflict on key "bar" which is inside rule values, which may not be modified by other rule @@ -1002,8 +997,8 @@ func TestPartialRule(t *testing.T) { { note: "partial object rules with overlapping known ref vars (no eval-time conflict)", module: `package test - p[k].r1 := 1 { k := "q" } - p[k].r2 := 2 { k := "q" } + p[k].r1 := 1 if { k := "q" } + p[k].r2 := 2 if { k := "q" } `, query: `data = x`, exp: `[{"x": {"test": {"p": {"q": {"r1": 1, "r2": 2}}}}}]`, @@ -1011,8 +1006,8 @@ func TestPartialRule(t *testing.T) { { note: "partial object rules with overlapping known ref vars (eval-time conflict)", module: `package test - p[k].r := 1 { k := "q" } - p[k].r := 2 { k := "q" } + p[k].r := 1 if { k := "q" } + p[k].r := 2 if { k := "q" } `, query: `data = x`, expErr: "eval_conflict_error: object keys must be unique", @@ -1020,8 +1015,8 @@ func TestPartialRule(t *testing.T) { { note: "partial object rules with overlapping known ref vars, non-overlapping object type values (eval-time conflict)", module: `package test - p[k].r := {"s1": 1} { k := "q" } - p[k].r := {"s2": 2} { k := "q" } + p[k].r := {"s1": 1} if { k := "q" } + p[k].r := {"s2": 2} if { k := "q" } `, query: `data = x`, expErr: "eval_conflict_error: object keys must be unique", @@ -1029,7 +1024,7 @@ func TestPartialRule(t *testing.T) { { note: "partial object rule with object value containing var", module: `package test - p.foo.q[y] := {"x": z} { y := ["bar", "baz"][_]; z := 4 } + p.foo.q[y] := {"x": z} if { y := ["bar", "baz"][_]; z := 4 } `, query: `data = x`, exp: `[{"x": {"test": {"p": {"foo": {"q": {"bar": {"x": 4}, "baz": {"x": 4}}}}}}}]`, @@ -1037,8 +1032,8 @@ func TestPartialRule(t *testing.T) { { note: "partial object rule with object value and intersecting key override rule (regression test #6211)", module: `package test - p.foo.q[y] := {"x": 7} { y := ["bar", "baz"][_] } - p.foo.q.baz.y = 9 { true } + p.foo.q[y] := {"x": 7} if { y := ["bar", "baz"][_] } + p.foo.q.baz.y = 9 if { true } `, query: `data = x`, expErr: "eval_conflict_error: object keys must be unique", @@ -1046,8 +1041,8 @@ func TestPartialRule(t *testing.T) { { note: "partial object rule with object value and intersecting key override rule (query up to partial object) (regression test #6211)", module: `package test - p.foo.q[y] := {"x": 7} { y := ["bar", "baz"][_] } - p.foo.q.baz.y = 9 { true } + p.foo.q[y] := {"x": 7} if { y := ["bar", "baz"][_] } + p.foo.q.baz.y = 9 if { true } `, query: `data = x.test.p.foo.q`, expErr: "eval_conflict_error: object keys must be unique", @@ -1055,8 +1050,8 @@ func TestPartialRule(t *testing.T) { { note: "partial object rule with object value and intersecting key override rule (query into partial object) (regression test #6211)", module: `package test - p.foo.q[y] := {"x": 7} { y := ["bar", "baz"][_] } - p.foo.q.baz.y = 9 { true } + p.foo.q[y] := {"x": 7} if { y := ["bar", "baz"][_] } + p.foo.q.baz.y = 9 if { true } `, query: `data.test.p.foo.q.bar = x`, exp: `[{"x": {"x": 7}}]`, @@ -1064,8 +1059,8 @@ func TestPartialRule(t *testing.T) { { note: "partial object rule with object value and intersecting key override rule (query into key override) (regression test #6211)", module: `package test - p.foo.q[y] := {"x": 7} { y := ["bar", "baz"][_] } - p.foo.q.baz.y = 9 { true } + p.foo.q[y] := {"x": 7} if { y := ["bar", "baz"][_] } + p.foo.q.baz.y = 9 if { true } `, query: `data.test.p.foo.q.baz = x`, expErr: "eval_conflict_error: object keys must be unique", @@ -1073,8 +1068,8 @@ func TestPartialRule(t *testing.T) { { note: "partial object rule with object value and intersecting key override rule (query into partial object, enumeration) (regression test #6211)", module: `package test - p.foo.q[y] := {"x": 7} { y := ["bar", "baz"][_] } - p.foo.q.baz.y = 9 { true } + p.foo.q[y] := {"x": 7} if { y := ["bar", "baz"][_] } + p.foo.q.baz.y = 9 if { true } `, query: `data.test.p.foo.q[z] = x`, expErr: "eval_conflict_error: object keys must be unique", @@ -1082,8 +1077,8 @@ func TestPartialRule(t *testing.T) { { note: "partial object rule with object value and intersecting key override rule (query into partial object, enumeration #2) (regression test #6211)", module: `package test - p.foo.q[y] := {"x": 7} { y := ["bar", "baz"][_] } - p.foo.q.baz.y = 9 { true } + p.foo.q[y] := {"x": 7} if { y := ["bar", "baz"][_] } + p.foo.q.baz.y = 9 if { true } `, query: `data.test.p.foo.q[z].x = x`, expErr: "eval_conflict_error: object keys must be unique", @@ -1091,8 +1086,8 @@ func TestPartialRule(t *testing.T) { { note: "partial object rule with object value and intersecting key override rule (query into key override, enumeration) (regression test #6211)", module: `package test - p.foo.q[y] := {"x": 7} { y := ["bar", "baz"][_] } - p.foo.q.baz.y = 9 { true } + p.foo.q[y] := {"x": 7} if { y := ["bar", "baz"][_] } + p.foo.q.baz.y = 9 if { true } `, query: `data.test.p.foo.q.baz[z] = x`, expErr: "eval_conflict_error: object keys must be unique", @@ -1101,7 +1096,7 @@ func TestPartialRule(t *testing.T) { { note: "deep query into partial object (ref head)", module: `package test - p.q[r] := 1 { r := "foo" } + p.q[r] := 1 if { r := "foo" } `, query: `data.test.p.q.foo = x`, exp: `[{"x": 1}]`, @@ -1109,7 +1104,7 @@ func TestPartialRule(t *testing.T) { { note: "deep query into partial object (ref head) and object value", module: `package test - p.q[r] := x { + p.q[r] := x if { r := "foo" x := {"bar": {"baz": 1}} } @@ -1120,7 +1115,7 @@ func TestPartialRule(t *testing.T) { { note: "deep query into partial object starting-point (general ref head) up to array value", module: `package test - p.q[r].s[t].u := x { + p.q[r].s[t].u := x if { obj := { "foo": { "do": ["a", "b", "c"], @@ -1140,7 +1135,7 @@ func TestPartialRule(t *testing.T) { { note: "deep query into partial object mid-point (general ref head) up to array value", module: `package test - p.q[r].s[t].u := x { + p.q[r].s[t].u := x if { obj := { "foo": { "do": ["a", "b", "c"], @@ -1160,7 +1155,7 @@ func TestPartialRule(t *testing.T) { { note: "deep query into partial object (general ref head) up to array value", module: `package test - p.q[r].s[t].u := x { + p.q[r].s[t].u := x if { obj := { "foo": { "do": ["a", "b", "c"], @@ -1180,7 +1175,7 @@ func TestPartialRule(t *testing.T) { { note: "deep query into partial object (general ref head) and array value", module: `package test - p.q[r].s[t].u := x { + p.q[r].s[t].u := x if { obj := { "foo": { "do": ["a", "b", "c"], @@ -1201,7 +1196,7 @@ func TestPartialRule(t *testing.T) { note: "query up to (ref head), but not into partial set", module: `package test import future.keywords - p.q.r contains s { {"foo", "bar", "bax"}[s] } + p.q.r contains s if { {"foo", "bar", "bax"}[s] } `, query: `data.test.p = x`, exp: `[{"x": {"q": {"r": ["bar", "bax", "foo"]}}}]`, @@ -1210,7 +1205,7 @@ func TestPartialRule(t *testing.T) { note: "deep query up to (ref mid-point), but not into partial set", module: `package test import future.keywords - p.q.r contains s { {"foo", "bar", "bax"}[s] } + p.q.r contains s if { {"foo", "bar", "bax"}[s] } `, query: `data.test.p.q = x`, exp: `[{"x": {"r": ["bar", "bax", "foo"]}}]`, @@ -1219,7 +1214,7 @@ func TestPartialRule(t *testing.T) { note: "deep query up to (ref tail), but not into partial set", module: `package test import future.keywords - p.q.r contains s { {"foo", "bar", "bax"}[s] } + p.q.r contains s if { {"foo", "bar", "bax"}[s] } `, query: `data.test.p.q.r = x`, exp: `[{"x": ["bar", "bax", "foo"]}]`, @@ -1228,7 +1223,7 @@ func TestPartialRule(t *testing.T) { note: "deep query into partial set", module: `package test import future.keywords - p.q contains r { {"foo", "bar", "bax"}[r] } + p.q contains r if { {"foo", "bar", "bax"}[r] } `, query: `data.test.p.q.foo = x`, exp: `[{"x": "foo"}]`, @@ -1236,7 +1231,7 @@ func TestPartialRule(t *testing.T) { { // enumeration note: "deep query into partial object and object value, full depth, enumeration on object value", module: `package test - p.q[r] := x { + p.q[r] := x if { r := ["foo", "bar"][_] x := {"s": {"do": 0, "re": 1, "mi": 2}} } @@ -1247,7 +1242,7 @@ func TestPartialRule(t *testing.T) { { // enumeration note: "deep query into partial object and object value, full depth, enumeration on rule path and object value", module: `package test - p.q[r] := x { + p.q[r] := x if { r := ["foo", "bar"][_] x := {"s": {"do": 0, "re": 1, "mi": 2}} } @@ -1259,7 +1254,7 @@ func TestPartialRule(t *testing.T) { note: "deep query into partial object (ref head) and set value", module: `package test import future.keywords - p.q contains t { + p.q contains t if { {"do", "re", "mi"}[t] } `, @@ -1270,7 +1265,7 @@ func TestPartialRule(t *testing.T) { note: "deep query into partial object (general ref head) and set value", module: `package test import future.keywords - p.q[r] contains t { + p.q[r] contains t if { r := ["foo", "bar"][_] {"do", "re", "mi"}[t] } @@ -1282,7 +1277,7 @@ func TestPartialRule(t *testing.T) { note: "deep query into partial object (general ref head, static tail) and set value", module: `package test import future.keywords - p.q[r].s contains t { + p.q[r].s contains t if { r := ["foo", "bar"][_] {"do", "re", "mi"}[t] } @@ -1294,7 +1289,7 @@ func TestPartialRule(t *testing.T) { note: "deep query into general ref to set value", module: `package test import future.keywords - p.q[r].s contains t { + p.q[r].s contains t if { r := ["foo", "bar"][_] t := ["do", "re", "mi"][_] } @@ -1305,7 +1300,7 @@ func TestPartialRule(t *testing.T) { { note: "deep query into general ref to object value", module: `package test - p.q[r].s[t] := u { + p.q[r].s[t] := u if { r := ["foo", "bar"][_] t := ["do", "re", "mi"][u] } @@ -1317,7 +1312,7 @@ func TestPartialRule(t *testing.T) { note: "deep query into general ref enumerating set values", module: `package test import future.keywords - p.q[r].s contains t { + p.q[r].s contains t if { r := ["foo", "bar"][_] {"do", "re", "mi"}[t] } @@ -1329,7 +1324,7 @@ func TestPartialRule(t *testing.T) { { note: "deep query into partial object and object value, non-tail var", module: `package test - p.q[r].s := x { + p.q[r].s := x if { r := "foo" x := {"bar": {"baz": 1}} } @@ -1340,7 +1335,7 @@ func TestPartialRule(t *testing.T) { { note: "deep query into partial object, on first var in ref", module: `package test - p.q[r].s := 1 { r := "foo" } + p.q[r].s := 1 if { r := "foo" } `, query: `data.test.p.q.foo = x`, exp: `[{"x": {"s": 1}}]`, @@ -1348,7 +1343,7 @@ func TestPartialRule(t *testing.T) { { note: "deep query into partial object, beyond first var in ref", module: `package test - p.q[r].s := 1 { r := "foo" } + p.q[r].s := 1 if { r := "foo" } `, query: `data.test.p.q.foo.s = x`, exp: `[{"x": 1}]`, @@ -1356,7 +1351,7 @@ func TestPartialRule(t *testing.T) { { note: "deep query into partial object, shallow rule ref", module: `package test - p.q[r][s] := 1 { r := "foo"; s := "bar" } + p.q[r][s] := 1 if { r := "foo"; s := "bar" } `, query: `data.test.p.q.foo = x`, exp: `[{"x": {"bar": 1}}]`, @@ -1364,7 +1359,7 @@ func TestPartialRule(t *testing.T) { { note: "deep query into partial object, shallow rule ref, multiple keys", module: `package test - p.q[r][s] := t { l := ["do", "re", "mi"]; r := "foo"; s := l[t] } + p.q[r][s] := t if { l := ["do", "re", "mi"]; r := "foo"; s := l[t] } `, query: `data.test.p.q.foo = x`, exp: `[{"x": {"do": 0, "re": 1, "mi": 2}}]`, @@ -1372,7 +1367,7 @@ func TestPartialRule(t *testing.T) { { note: "deep query into partial object, beyond first var in ref, multiple vars", module: `package test - p.q[r][s] := 1 { r := "foo"; s := "bar" } + p.q[r][s] := 1 if { r := "foo"; s := "bar" } `, query: `data.test.p.q.foo.bar = x`, exp: `[{"x": 1}]`, @@ -1380,7 +1375,7 @@ func TestPartialRule(t *testing.T) { { note: "deep query into partial object, beyond first var in ref, multiple vars", module: `package test - p.q[r][s].t := 1 { r := "foo"; s := "bar" } + p.q[r][s].t := 1 if { r := "foo"; s := "bar" } `, query: `data.test.p.q.foo.bar = x`, exp: `[{"x": {"t": 1}}]`, @@ -1388,7 +1383,7 @@ func TestPartialRule(t *testing.T) { { note: "deep query to partial object, overlapping rules (key override), no dynamic ref", module: `package test - p.q[r] := 1 { r := "foo" } + p.q[r] := 1 if { r := "foo" } p.q.r := 2 `, query: `data.test.p.q = x`, @@ -1397,7 +1392,7 @@ func TestPartialRule(t *testing.T) { { note: "deep query into partial object, overlapping rules (key override), no dynamic ref", module: `package test - p.q[r] := 1 { r := "foo" } + p.q[r] := 1 if { r := "foo" } p.q.r := 2 `, query: `data.test.p.q.r = x`, @@ -1406,8 +1401,8 @@ func TestPartialRule(t *testing.T) { { note: "deep query into partial object, overlapping rules, no dynamic ref", module: `package test - p.q[r] := 1 { r := "foo" } - p.q[r] := 2 { r := "bar" } + p.q[r] := 1 if { r := "foo" } + p.q[r] := 2 if { r := "bar" } `, query: `data.test.p.q.foo = x`, exp: `[{"x": 1}]`, @@ -1415,8 +1410,8 @@ func TestPartialRule(t *testing.T) { { note: "deep query into partial object, overlapping rules with same key/value, no dynamic ref", module: `package test - p.q[r] := 1 { r := "foo" } - p.q[r] := 1 { r := "foo" } + p.q[r] := 1 if { r := "foo" } + p.q[r] := 1 if { r := "foo" } `, query: `data.test.p.q.foo = x`, exp: `[{"x": 1}]`, @@ -1424,8 +1419,8 @@ func TestPartialRule(t *testing.T) { { note: "deep query into partial object, overlapping rules, dynamic ref", module: `package test - p.q[r].s := 1 { r := "r" } - p.q.r[s] := 2 { s := "foo" } + p.q[r].s := 1 if { r := "r" } + p.q.r[s] := 2 if { s := "foo" } `, query: `data.test.p.q.r = x`, exp: `[{"x": {"s": 1, "foo": 2}}]`, @@ -1433,8 +1428,8 @@ func TestPartialRule(t *testing.T) { { note: "deep query into partial object, overlapping rules with same key/value, dynamic ref", module: `package test - p.q[r].s := 1 { r := "r" } - p.q.r[s] := 1 { s := "s" } + p.q[r].s := 1 if { r := "r" } + p.q.r[s] := 1 if { s := "s" } `, query: `data.test.p.q.r = x`, exp: `[{"x": {"s": 1}}]`, @@ -1443,7 +1438,7 @@ func TestPartialRule(t *testing.T) { { note: "shallow query into general ref, key enumeration", module: `package test - p.q[r].s[t] := u { + p.q[r].s[t] := u if { r := ["a", "b", "c"][_] t := ["d", "e", "f"][u] }`, @@ -1455,8 +1450,8 @@ func TestPartialRule(t *testing.T) { { note: "query to partial object, overlapping rules, dynamic ref, key enumeration", module: `package test - p.q[r].s := 1 { r := "foo" } - p.q[r].s := 2 { r := "bar" } + p.q[r].s := 1 if { r := "foo" } + p.q[r].s := 2 if { r := "bar" } `, query: `data.test.p.q[i] = x`, exp: `[{"i": "bar", "x": {"s": 2}}, {"i": "foo", "x": {"s": 1}}]`, @@ -1464,8 +1459,8 @@ func TestPartialRule(t *testing.T) { { note: "deep query into partial object, overlapping rules, dynamic ref, key enumeration", module: `package test - p.q[r].s := 1 { r := "foo" } - p.q[r].s := 2 { r := "bar" } + p.q[r].s := 1 if { r := "foo" } + p.q[r].s := 2 if { r := "bar" } `, query: `data.test.p.q[i].s = x`, exp: `[{"i": "bar", "x": 2}, {"i": "foo", "x": 1}]`, @@ -1474,7 +1469,7 @@ func TestPartialRule(t *testing.T) { { note: "partial object generating conflicting keys", module: `package test - p[k] := x { + p[k] := x if { k := "foo" x := [1, 2][_] }`, @@ -1484,7 +1479,7 @@ func TestPartialRule(t *testing.T) { { note: "partial object (ref head) generating conflicting keys (dots in head)", module: `package test - p.q[k] := x { + p.q[k] := x if { k := "foo" x := [1, 2][_] }`, @@ -1494,7 +1489,7 @@ func TestPartialRule(t *testing.T) { { note: "partial object (general ref head) generating conflicting nested keys", module: `package test - p.q[k].s := x { + p.q[k].s := x if { k := "foo" x := [1, 2][_] }`, @@ -1504,7 +1499,7 @@ func TestPartialRule(t *testing.T) { { note: "partial object (general ref head) generating conflicting ref vars", module: `package test - p.q[k].s := x { + p.q[k].s := x if { k := ["foo", "foo"][x] }`, query: `data = x`, diff --git a/topdown/example_test.go b/topdown/example_test.go index 0a007a4abd..d4a498bc9a 100644 --- a/topdown/example_test.go +++ b/topdown/example_test.go @@ -195,10 +195,11 @@ func ExampleQuery_PartialRun() { modules := map[string]*ast.Module{ "authz.rego": ast.MustParseModule(` package example + import rego.v1 default allow = false - allow { + allow if { role = data.roles[i] input.group = role.groups[j] input.permission = role.permissions[k] diff --git a/topdown/print_test.go b/topdown/print_test.go index 71ee503712..8398b3e0e2 100644 --- a/topdown/print_test.go +++ b/topdown/print_test.go @@ -23,7 +23,7 @@ func TestTopDownPrint(t *testing.T) { module: ` package test - p { print() } + p if { print() } `, exp: "\n", }, @@ -32,7 +32,7 @@ func TestTopDownPrint(t *testing.T) { module: ` package test - p { + p if { x := "world" print("hello", x) } @@ -46,7 +46,7 @@ func TestTopDownPrint(t *testing.T) { xs := [1,2] - p { + p if { print("the value of xs is:", xs) } `, @@ -57,7 +57,7 @@ func TestTopDownPrint(t *testing.T) { module: ` package test - p { + p if { print("the value of foo is:", input.foo) } `, @@ -68,7 +68,7 @@ func TestTopDownPrint(t *testing.T) { module: ` package test - p { + p if { print("the value of foo is:", [input.foo]) } `, @@ -79,7 +79,7 @@ func TestTopDownPrint(t *testing.T) { module: ` package test - p { + p if { print("div by zero:", 1/0) # divide by zero will be undefined unless strict-builtin-errors are enabled } `, @@ -93,7 +93,7 @@ func TestTopDownPrint(t *testing.T) { xs := {1} ys := {"a"} - p { + p if { print(walk(xs), walk(ys)) } `, @@ -108,7 +108,13 @@ func TestTopDownPrint(t *testing.T) { for _, tc := range cases { t.Run(tc.note, func(t *testing.T) { - c := ast.MustCompileModulesWithOpts(map[string]string{"test.rego": tc.module}, ast.CompileOpts{EnablePrintStatements: true}) + c := ast.MustCompileModulesWithOpts(map[string]string{"test.rego": tc.module}, + ast.CompileOpts{ + EnablePrintStatements: true, + ParserOptions: ast.ParserOptions{ + AllFutureKeywords: true, + }, + }) buf := bytes.NewBuffer(nil) q := NewQuery(ast.MustParseBody("data.test.p = x")). WithPrintHook(NewPrintHook(buf)). diff --git a/topdown/query_test.go b/topdown/query_test.go index 68ed4ee8d8..a2ef0c496c 100644 --- a/topdown/query_test.go +++ b/topdown/query_test.go @@ -254,12 +254,12 @@ func initTracerTestQuery() *Query { compiler := compileModules([]string{ `package x - p { + p if { a := [1, 2, 3] f(a[_]) } - f(x) { + f(x) if { x == 3 } diff --git a/topdown/topdown_partial_test.go b/topdown/topdown_partial_test.go index f0de601cf4..8f68ac89b5 100644 --- a/topdown/topdown_partial_test.go +++ b/topdown/topdown_partial_test.go @@ -79,8 +79,8 @@ func TestTopDownPartialEval(t *testing.T) { query: "input.x = data.test.p; data.test.q = input.y", modules: []string{ `package test - p = x { x = "foo" } - q = x { x = "bar" }`, + p = x if { x = "foo" } + q = x if { x = "bar" }`, }, wantQueries: []string{ `"foo" = input.x; "bar" = input.y`, @@ -112,7 +112,7 @@ func TestTopDownPartialEval(t *testing.T) { ` package test - p { + p if { input.x = k data.x[k] = 7 } @@ -128,7 +128,7 @@ func TestTopDownPartialEval(t *testing.T) { ` package test - p { + p if { input.x = k data.x[k] = 7 } @@ -156,9 +156,9 @@ func TestTopDownPartialEval(t *testing.T) { query: `input.x = x; data.test.p[x]`, modules: []string{ `package test - p[1] - p[2] - p[3]`, + p contains 1 + p contains 2 + p contains 3`, }, wantQueries: []string{ `input.x = 1; x = 1`, @@ -194,8 +194,8 @@ func TestTopDownPartialEval(t *testing.T) { query: `input.x = x; data.test.p[x]`, modules: []string{ `package test - p[y] { y = "foo" } - p[z] { z = "bar" }`, + p contains y if { y = "foo" } + p contains z if { z = "bar" }`, }, wantQueries: []string{ `input.x = "foo"; x = "foo"`, @@ -214,8 +214,8 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p[x].foo = 1", modules: []string{ `package test - p[x] = {y: z} { x = input.x; y = "foo"; z = 1 } - p[x] = {y: z} { x = input.y; y = "bar"; z = 2 }`, + p[x] = {y: z} if { x = input.x; y = "foo"; z = 1 } + p[x] = {y: z} if { x = input.y; y = "bar"; z = 2 }`, }, wantQueries: []string{ `x = input.x`, @@ -226,8 +226,8 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p[x].q.foo = 1", modules: []string{ `package test - p[a].q = {b: c} { a = input.a; b = "foo"; c = 1 } - p[a].q = {b: c} { a = input.b; b = "bar"; c = 2 }`, + p[a].q = {b: c} if { a = input.a; b = "foo"; c = 1 } + p[a].q = {b: c} if { a = input.b; b = "bar"; c = 2 }`, }, wantQueries: []string{ `x = input.a`, @@ -238,8 +238,8 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p[x].q.foo", modules: []string{ `package test - p[a].q = {b: c} { a = input.a; b = "foo"; c = 1 } - p[a].q = {b: c} { a = input.b; b = "bar"; c = 2 }`, + p[a].q = {b: c} if { a = input.a; b = "foo"; c = 1 } + p[a].q = {b: c} if { a = input.b; b = "bar"; c = 2 }`, }, wantQueries: []string{ `x = input.a`, @@ -250,8 +250,8 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p[x].q", modules: []string{ `package test - p[a].q = {b: c} { a = input.a; b = "foo"; c = 1 } - p[a].q = {b: c} { a = input.b; b = "bar"; c = 2 }`, + p[a].q = {b: c} if { a = input.a; b = "foo"; c = 1 } + p[a].q = {b: c} if { a = input.b; b = "bar"; c = 2 }`, }, wantQueries: []string{ `x = input.a`, @@ -263,8 +263,8 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p[x].q[y]", modules: []string{ `package test - p[a].q = {b: c} { a = input.a; b = "foo"; c = 1 } - p[a].q = {b: c} { a = input.b; b = "bar"; c = 2 }`, + p[a].q = {b: c} if { a = input.a; b = "foo"; c = 1 } + p[a].q = {b: c} if { a = input.b; b = "bar"; c = 2 }`, }, wantQueries: []string{ `x = input.a; y = "foo"`, @@ -276,8 +276,8 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p[x].q[y] = z", modules: []string{ `package test - p[a].q = {b: c} { a = input.a; b = "foo"; c = 1 } - p[a].q = {b: c} { a = input.b; b = "bar"; c = 2 }`, + p[a].q = {b: c} if { a = input.a; b = "foo"; c = 1 } + p[a].q = {b: c} if { a = input.b; b = "bar"; c = 2 }`, }, wantQueries: []string{ `x = input.a; y = "foo"; z = 1`, @@ -289,16 +289,16 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p = z", modules: []string{ `package test - p[a].q = {b: c} { a = input.a; b = "foo"; c = 1 } - p[a].q = {b: c} { a = input.b; b = "bar"; c = 2 }`, + p[a].q = {b: c} if { a = input.a; b = "foo"; c = 1 } + p[a].q = {b: c} if { a = input.b; b = "bar"; c = 2 }`, }, wantQueries: []string{ `data.partial.test.p = z`, }, wantSupport: []string{ `package partial.test - p[a2].q = {"foo": 1} { a2 = input.a } - p[a1].q = {"bar": 2} { a1 = input.b }`, + p[a2].q = {"foo": 1} if { a2 = input.a } + p[a1].q = {"bar": 2} if { a1 = input.b }`, }, }, { @@ -306,8 +306,8 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p[x] = z", modules: []string{ `package test - p[a].q = {b: c} { a = input.a; b = "foo"; c = 1 } - p[a].q = {b: c} { a = input.b; b = "bar"; c = 2 }`, + p[a].q = {b: c} if { a = input.a; b = "foo"; c = 1 } + p[a].q = {b: c} if { a = input.b; b = "bar"; c = 2 }`, }, wantQueries: []string{ `x = input.a; z = {"q": {"foo": 1}}`, @@ -319,21 +319,21 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p = z", modules: []string{ `package test - p[a].q = {b: c} { a = input.a; b = "foo"; c = 1 } - p[a].q = {b: c} { a = input.b; b = "bar"; c = 2 } - p.foo.r = a { a = "baz" } - p.foo.s = a { a = input.c }`, + p[a].q = {b: c} if { a = input.a; b = "foo"; c = 1 } + p[a].q = {b: c} if { a = input.b; b = "bar"; c = 2 } + p.foo.r = a if { a = "baz" } + p.foo.s = a if { a = input.c }`, }, wantQueries: []string{ `data.partial.test.p = z`, }, wantSupport: []string{ `package partial.test - p[a4].q = {"foo": 1} { a4 = input.a } - p[a3].q = {"bar": 2} { a3 = input.b }`, + p[a4].q = {"foo": 1} if { a4 = input.a } + p[a3].q = {"bar": 2} if { a3 = input.b }`, `package partial.test.p.foo - r = "baz" { true } - s = a2 { a2 = input.c }`, + r = "baz" if { true } + s = a2 if { a2 = input.c }`, }, }, { @@ -341,10 +341,10 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p[x] = z", modules: []string{ `package test - p[a].q = {b: c} { a = input.a; b = "foo"; c = 1 } - p[a].q = {b: c} { a = input.b; b = "bar"; c = 2 } - p.foo.r = a { a = "baz" } - p.foo.s = a { a = input.c }`, + p[a].q = {b: c} if { a = input.a; b = "foo"; c = 1 } + p[a].q = {b: c} if { a = input.b; b = "bar"; c = 2 } + p.foo.r = a if { a = "baz" } + p.foo.s = a if { a = input.c }`, }, wantQueries: []string{ `x = input.a; z = {"q": {"foo": 1}}`, @@ -358,16 +358,16 @@ func TestTopDownPartialEval(t *testing.T) { query: `data.test.p = x`, modules: []string{ `package test - p[q].r[s] := v { v := "foo"; q := 42; s := "bar" } - p[q].r[s].t := v { v := input.x; q := input.y; s := "baz" }`, + p[q].r[s] := v if { v := "foo"; q := 42; s := "bar" } + p[q].r[s].t := v if { v := input.x; q := input.y; s := "baz" }`, }, wantQueries: []string{ `data.partial.test.p = x`, }, wantSupport: []string{ `package partial.test - p[42].r.bar = "foo" { true } - p[__local4__2].r.baz.t = __local3__2 { __local3__2 = input.x; __local4__2 = input.y }`, + p[42].r.bar = "foo" if { true } + p[__local4__2].r.baz.t = __local3__2 if { __local3__2 = input.x; __local4__2 = input.y }`, }, }, { @@ -375,8 +375,8 @@ func TestTopDownPartialEval(t *testing.T) { query: `data.test.p[42] = x`, modules: []string{ `package test - p[q].r[s] := v { v := "foo"; q := 42; s := "bar" } - p[q].r[s].t := v { v := input.x; q := input.y; s := "baz" }`, + p[q].r[s] := v if { v := "foo"; q := 42; s := "bar" } + p[q].r[s].t := v if { v := input.x; q := input.y; s := "baz" }`, }, wantQueries: []string{ `x = {"r": {"bar": "foo"}}`, @@ -389,16 +389,16 @@ func TestTopDownPartialEval(t *testing.T) { shallow: true, modules: []string{ `package test - #p[q].r[s] := v { v := "foo"; q := 42; s := "bar" } - #p[q].r[s].t := v { v := input.x; q := input.y; s := "baz" } - p[q][r][s].t := v { v := input.x; q := input.y; s := input.z; r := "known" }`, + #p[q].r[s] := v if { v := "foo"; q := 42; s := "bar" } + #p[q].r[s].t := v if { v := input.x; q := input.y; s := "baz" } + p[q][r][s].t := v if { v := input.x; q := input.y; s := input.z; r := "known" }`, }, wantQueries: []string{ `data.partial.test.p[42] = x`, }, wantSupport: []string{ `package partial.test - p[__local1__1].known[__local2__1].t = __local0__1 { __local0__1 = input.x; __local1__1 = input.y; __local2__1 = input.z }`, + p[__local1__1].known[__local2__1].t = __local0__1 if { __local0__1 = input.x; __local1__1 = input.y; __local2__1 = input.z }`, }, }, { @@ -406,8 +406,8 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p[x].foo = 1", modules: []string{ `package test - p[x] { x = {y: z}; y = "foo"; z = input.x } - p[x] { x = {y: z}; y = "bar"; z = input.x }`, + p contains x if { x = {y: z}; y = "foo"; z = input.x } + p contains x if { x = {y: z}; y = "bar"; z = input.x }`, }, wantQueries: []string{ `1 = input.x; x = {"foo": 1}`, @@ -419,8 +419,8 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test import future.keywords.contains - p[x] contains y { y = {a: b}; a = "foo"; b = input.x; x := 42 } - p[x] contains y { y = {a: b}; a = "bar"; b = input.x; x := input.y }`, + p[x] contains y if { y = {a: b}; a = "foo"; b = input.x; x := 42 } + p[x] contains y if { y = {a: b}; a = "bar"; b = input.x; x := input.y }`, }, wantQueries: []string{ `1 = input.x; y = {"foo": 1}; x = 42`, @@ -432,8 +432,8 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test import future.keywords.contains - p[x] contains y { y = {a: b}; a = "foo"; b = input.x; x = 42 } - p[x] contains y { y = {a: b}; a = "bar"; b = input.x; x = input.y }`, + p[x] contains y if { y = {a: b}; a = "foo"; b = input.x; x = 42 } + p[x] contains y if { y = {a: b}; a = "bar"; b = input.x; x = input.y }`, }, wantQueries: []string{ `1 = input.x; x = input.y; y = {"bar": 1}`, @@ -445,8 +445,8 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test import future.keywords.contains - p[x] contains y { y = {a: b}; a = "foo"; b = input.x; x := 42 } - p[x] contains y { y = {a: b}; a = "bar"; b = input.x; x := input.y }`, + p[x] contains y if { y = {a: b}; a = "foo"; b = input.x; x := 42 } + p[x] contains y if { y = {a: b}; a = "bar"; b = input.x; x := input.y }`, }, wantQueries: []string{ `1 = input.x; y = {"foo": 1}`, @@ -458,8 +458,8 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test import future.keywords.contains - p[x] contains y { y = {a: b}; a = "foo"; b = input.x; x := 42 } - p[x] contains y { y = {a: b}; a = "bar"; b = input.x; x := input.y }`, + p[x] contains y if { y = {a: b}; a = "foo"; b = input.x; x := 42 } + p[x] contains y if { y = {a: b}; a = "bar"; b = input.x; x := input.y }`, }, wantQueries: []string{ `1 = input.x; y = {"foo": 1}; x = 42`, @@ -471,8 +471,8 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test import future.keywords.contains - p[x] contains y { y = {a: b}; a = "foo"; b = input.x; x := 42 } - p[x] contains y { y = {a: b}; a = "bar"; b = input.x; x := input.y }`, + p[x] contains y if { y = {a: b}; a = "foo"; b = input.x; x := 42 } + p[x] contains y if { y = {a: b}; a = "bar"; b = input.x; x := input.y }`, }, wantQueries: []string{ `{{"foo": input.x}} = {{"foo": 1}}; x = 42`, // `1 = input.x; x = 42` would be a more precise optimization (?) @@ -484,8 +484,8 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test import future.keywords.contains - p[x] contains y { y = {a: b}; a = "foo"; b = input.x; x := 42 } - p[x] contains y { y = {a: b}; a = "bar"; b = input.x; x := input.y }`, + p[x] contains y if { y = {a: b}; a = "foo"; b = input.x; x := 42 } + p[x] contains y if { y = {a: b}; a = "bar"; b = input.x; x := input.y }`, }, wantQueries: []string{ `data.partial.test.p`, @@ -493,8 +493,8 @@ func TestTopDownPartialEval(t *testing.T) { wantSupport: []string{ `package partial.test import future.keywords.contains - p[42] contains {"foo": b1} { b1 = input.x } - p[__local1__2] contains {"bar": b2} { b2 = input.x; __local1__2 = input.y }`, + p[42] contains {"foo": b1} if { b1 = input.x } + p[__local1__2] contains {"bar": b2} if { b2 = input.x; __local1__2 = input.y }`, }, }, { @@ -503,8 +503,8 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test import future.keywords.contains - p[x] contains y { y = {a: b}; a = "foo"; b = input.x; x := 42 } - p[x] contains y { y = {a: b}; a = "bar"; b = input.x; x := input.y }`, + p[x] contains y if { y = {a: b}; a = "foo"; b = input.x; x := 42 } + p[x] contains y if { y = {a: b}; a = "bar"; b = input.x; x := input.y }`, }, wantQueries: []string{ `data.partial.test.p = x`, @@ -512,8 +512,8 @@ func TestTopDownPartialEval(t *testing.T) { wantSupport: []string{ `package partial.test import future.keywords.contains - p[42] contains {"foo": b1} { b1 = input.x } - p[__local1__2] contains {"bar": b2} { b2 = input.x; __local1__2 = input.y }`, + p[42] contains {"foo": b1} if { b1 = input.x } + p[__local1__2] contains {"bar": b2} if { b2 = input.x; __local1__2 = input.y }`, }, }, { @@ -522,8 +522,8 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test import future.keywords.contains - p[x].r contains y { y = {a: b}; a = "foo"; b = input.x; x := 42 } - p[x].r contains y { y = {a: b}; a = "bar"; b = input.x; x := input.y }`, + p[x].r contains y if { y = {a: b}; a = "foo"; b = input.x; x := 42 } + p[x].r contains y if { y = {a: b}; a = "bar"; b = input.x; x := input.y }`, }, wantQueries: []string{ `data.partial.test.p = x`, @@ -531,8 +531,8 @@ func TestTopDownPartialEval(t *testing.T) { wantSupport: []string{ `package partial.test import future.keywords.contains - p[42].r contains {"foo": b1} { b1 = input.x } - p[__local1__2].r contains {"bar": b2} { b2 = input.x; __local1__2 = input.y }`, + p[42].r contains {"foo": b1} if { b1 = input.x } + p[__local1__2].r contains {"bar": b2} if { b2 = input.x; __local1__2 = input.y }`, }, }, { @@ -541,8 +541,8 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test import future.keywords.contains - p[q].r[s] contains x { x = "foo"; q := 42; s = "bar" } - p[q].r[s].t contains x { x = input.x; q := input.y; s = "baz" }`, + p[q].r[s] contains x if { x = "foo"; q := 42; s = "bar" } + p[q].r[s].t contains x if { x = input.x; q := input.y; s = "baz" }`, }, wantQueries: []string{ `data.partial.test.p = x`, @@ -550,8 +550,8 @@ func TestTopDownPartialEval(t *testing.T) { wantSupport: []string{ `package partial.test import future.keywords.contains - p[42].r.bar contains "foo" { true } - p[__local1__2].r.baz.t contains x2 { x2 = input.x; __local1__2 = input.y }`, + p[42].r.bar contains "foo" if { true } + p[__local1__2].r.baz.t contains x2 if { x2 = input.x; __local1__2 = input.y }`, }, }, { @@ -560,8 +560,8 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test import future.keywords.contains - p[q].r[s] contains v { v := "foo"; q := 42; s := "bar" } - p[q].r[s].t contains v { v := input.x; q := input.y; s := "baz" }`, + p[q].r[s] contains v if { v := "foo"; q := 42; s := "bar" } + p[q].r[s].t contains v if { v := input.x; q := input.y; s := "baz" }`, }, wantQueries: []string{ `x = {"r": {"bar": {"foo"}}}`, @@ -574,8 +574,8 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test import future.keywords.contains - p[q].r[s] contains x { x = "foo"; q := 42; s = "bar" } - p[q].r[s].t contains x { x = input.x; q := input.y; s = "baz" }`, + p[q].r[s] contains x if { x = "foo"; q := 42; s = "bar" } + p[q].r[s].t contains x if { x = input.x; q := input.y; s = "baz" }`, }, wantQueries: []string{ `"foo" = input.y; x = {"r": {"baz": {"t": {input.x}}}}`, @@ -586,7 +586,7 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p[input.x]", modules: []string{ `package test - p[q].r[s] = v { q = {"foo", "bar"}[s]; v = "baz" } + p[q].r[s] = v if { q = {"foo", "bar"}[s]; v = "baz" } p.q.r.s := 1`, }, wantQueries: []string{ @@ -600,7 +600,7 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p.foo.r[input.x]", modules: []string{ `package test - p[q].r[s] = v { q = {"foo", "bar"}[s]; v = "baz" } + p[q].r[s] = v if { q = {"foo", "bar"}[s]; v = "baz" } p.q.r.s := 1`, }, wantQueries: []string{ @@ -612,7 +612,7 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p[input.x].r[input.y]", modules: []string{ `package test - p[q].r[s] = v { q = {"foo", "bar"}[s]; v = "baz" } + p[q].r[s] = v if { q = {"foo", "bar"}[s]; v = "baz" } p.q.r.s := 1`, }, wantQueries: []string{ @@ -626,7 +626,7 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p[x].r[y][input.x]", modules: []string{ `package test - p[q].r[s] = {v: w} { q = {"foo", "bar"}[s]; v = "baz"; w = "bax" } + p[q].r[s] = {v: w} if { q = {"foo", "bar"}[s]; v = "baz"; w = "bax" } p.q.r.s := {1: 2}`, }, wantQueries: []string{ @@ -640,7 +640,7 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p[x].r[y][input.x] = input.y", modules: []string{ `package test - p[q].r[s] = {v: w} { q = {"foo", "bar"}[s]; v = "baz"; w = "bax" } + p[q].r[s] = {v: w} if { q = {"foo", "bar"}[s]; v = "baz"; w = "bax" } p.q.r.s := {1: 2}`, }, wantQueries: []string{ @@ -654,7 +654,7 @@ func TestTopDownPartialEval(t *testing.T) { query: `data.test.p[x].r[y][input.x] = "bax"`, modules: []string{ `package test - p[q].r[s] = {v: w} { q = {"foo", "bar"}[s]; v = "baz"; w = "bax" } + p[q].r[s] = {v: w} if { q = {"foo", "bar"}[s]; v = "baz"; w = "bax" } p.q.r.s := {1: 2}`, }, wantQueries: []string{ @@ -667,7 +667,7 @@ func TestTopDownPartialEval(t *testing.T) { query: `data.test.p[x].r[y][input.x] = 2`, modules: []string{ `package test - p[q].r[s] = {v: w} { q = {"foo", "bar"}[s]; v = "baz"; w = "bax" } + p[q].r[s] = {v: w} if { q = {"foo", "bar"}[s]; v = "baz"; w = "bax" } p.q.r.s := {1: 2}`, }, wantQueries: []string{ @@ -680,7 +680,7 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p = x { input.x = x }`, + p = x if { input.x = x }`, }, wantQueries: []string{ `input.x = 1`, @@ -692,7 +692,7 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p.q = x { input.x = x }`, + p.q = x if { input.x = x }`, }, wantQueries: []string{ `input.x = 1`, @@ -704,12 +704,12 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p { + p if { a = 1 q[a] } - q = a { + q = a if { a = input }`, }, @@ -721,17 +721,17 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p { + p if { a = 1 b = 2 q[a] = r[b] } - q = a { + q = a if { a = input.a } - r = b { + r = b if { b = input.b }`, }, @@ -743,7 +743,7 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p[x] = 1 { + p[x] = 1 if { input.foo[x] = z x.bar = 1 } @@ -759,7 +759,7 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p.q[x] = 1 { + p.q[x] = 1 if { input.foo[x] = z x.bar = 1 } @@ -775,7 +775,7 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p.q[x].s = 1 { + p.q[x].s = 1 if { input.foo[x] = z x.bar = 1 } @@ -791,12 +791,12 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p { + p if { q[x] x.a = 1 } - q[x] { + q contains x if { input[x] x.b = 2 }`, @@ -816,7 +816,7 @@ func TestTopDownPartialEval(t *testing.T) { `package test default p = false - p { + p if { input.x = 1 }`, }, @@ -827,7 +827,7 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p = x", modules: []string{ `package test - p = 1 { input.y = x; x = 2 }`, + p = 1 if { input.y = x; x = 2 }`, }, wantQueries: []string{ `input.y = 2; x = 1`, @@ -838,7 +838,7 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p = x", modules: []string{ `package test - p = x { input.x = x }`, + p = x if { input.x = x }`, }, wantQueries: []string{ `input.x = x`, @@ -849,7 +849,7 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p[[x, y]]", modules: []string{ `package test - p[[y, x]] { input.z = z; z = y; a = input.a; a = x }`, + p contains [y, x] if { input.z = z; z = y; a = input.a; a = x }`, }, wantQueries: []string{ `input.z = x; y = input.a; x_term_0_0 = [x, y]`, @@ -860,7 +860,7 @@ func TestTopDownPartialEval(t *testing.T) { query: "input.x = x; data.test.p[x] = y; y = 2", modules: []string{ `package test - p[y] = x { y = "foo"; x = 2 }`, + p[y] = x if { y = "foo"; x = 2 }`, }, wantQueries: []string{ `input.x = "foo"; x = "foo"; y = 2`, @@ -871,7 +871,7 @@ func TestTopDownPartialEval(t *testing.T) { query: "input.x = x; data.test.p.q[x] = y; y = 2", modules: []string{ `package test - p.q[y] = x { y = "foo"; x = 2 }`, + p.q[y] = x if { y = "foo"; x = 2 }`, }, wantQueries: []string{ `input.x = "foo"; x = "foo"; y = 2`, @@ -882,7 +882,7 @@ func TestTopDownPartialEval(t *testing.T) { query: "input.x = x; input.y = y; data.test.p.q[x][y] = z; z = 2", modules: []string{ `package test - p.q[x][y] = z { x = "foo"; y = "bar"; z = 2 }`, + p.q[x][y] = z if { x = "foo"; y = "bar"; z = 2 }`, }, wantQueries: []string{ `input.x = "foo"; input.y = "bar"; x = "foo"; y = "bar"; z = 2`, @@ -893,7 +893,7 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p = x", modules: []string{ `package test - p = x { input.x = [y]; y = x }`, + p = x if { input.x = [y]; y = x }`, }, wantQueries: []string{ `input.x = [x]`, @@ -904,8 +904,8 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p = x", modules: []string{ `package test - p = [x, z] { input.x = y; y = x; q = z } - q = x { input.y = y; x = y }`, + p = [x, z] if { input.x = y; y = x; q = z } + q = x if { input.y = y; x = y }`, }, wantQueries: []string{ `x = [input.x, input.y]`, @@ -917,7 +917,7 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p { + p if { a = "a" b = input.b a != b @@ -934,7 +934,7 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p { + p if { input = x x.foo = true }`, @@ -949,7 +949,7 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p[x] = 1 { + p[x] = 1 if { x = input x[0] = 1 } @@ -964,7 +964,7 @@ func TestTopDownPartialEval(t *testing.T) { query: `data.test.foo(input, [[x, _]]); startswith(x, "foo")`, modules: []string{ `package test - foo(x) = o { + foo(x) = o if { o := [[x.x, x.y]] } `}, @@ -977,7 +977,7 @@ func TestTopDownPartialEval(t *testing.T) { query: `data.test.foo(input, {"x": x}); startswith(x, "foo")`, modules: []string{ `package test - foo(x) = o { + foo(x) = o if { o := { "x": x.y } } `}, @@ -990,7 +990,7 @@ func TestTopDownPartialEval(t *testing.T) { query: `data.test.foo(input, {"x": [y, z]}); startswith(y, "foo")`, modules: []string{ `package test - foo(y) = z { + foo(y) = z if { z := { "x": [y.y, y.z] } } `}, @@ -1003,7 +1003,7 @@ func TestTopDownPartialEval(t *testing.T) { query: `data.test.foo(input, {"x": [ { "a": y }, _]}); startswith(y, "foo")`, modules: []string{ `package test - foo(y) = o { + foo(y) = o if { o := { "x": [ {"a": y.y }, y.z] } } `}, @@ -1016,8 +1016,8 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p = x", modules: []string{ `package test - p = true { input.x = 1 } - p = false { input.x = 2 }`, + p = true if { input.x = 1 } + p = false if { input.x = 2 }`, }, wantQueries: []string{ `input.x = 1; x = true`, @@ -1029,8 +1029,8 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.f(1, x)", modules: []string{ `package test - f(x) = true { input.x = x } - f(x) = false { input.y = x }`, + f(x) = true if { input.x = x } + f(x) = false if { input.y = x }`, }, wantQueries: []string{ `input.x = 1; x = true`, @@ -1042,8 +1042,8 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.f(input) = x", modules: []string{ `package test - f(x) = true { x = 1 } - f(x) = false { x = 2 } + f(x) = true if { x = 1 } + f(x) = false if { x = 2 } `, }, wantQueries: []string{ @@ -1067,7 +1067,7 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p = c { + p = c if { a = input c = [1 | b = a[0]] } @@ -1094,7 +1094,7 @@ func TestTopDownPartialEval(t *testing.T) { `package test q["a"] = 2`, `package test.b - r[1]`, + r contains 1`, }, wantQueries: []string{`x = {"a": {"p": 1}, "q": {"a": 2}, "b": {"r": {1,}}}`}, }, @@ -1103,8 +1103,8 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p = true", modules: []string{ `package test - p { input.x = 1; q with input as {"y": 2} } - q { input.y = r } + p if { input.x = 1; q with input as {"y": 2} } + q if { input.y = r } r = 2`, }, wantQueries: []string{ @@ -1112,7 +1112,7 @@ func TestTopDownPartialEval(t *testing.T) { }, wantSupport: []string{ `package partial.test - q = true { 2 = input.y }`, + q = true if { 2 = input.y }`, }, }, { @@ -1121,9 +1121,9 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p { q[x] = y with input as 1 } - q[y] { x = 1; y = x } - q[2]`, + p if { q[x] = y with input as 1 } + q contains y if { x = 1; y = x } + q contains 2`, }, wantQueries: []string{ `data.partial.test.q[x1] = y1 with input as 1`, @@ -1131,8 +1131,8 @@ func TestTopDownPartialEval(t *testing.T) { wantSupport: []string{ `package partial.test - q[1] - q[2]`, + q contains 1 + q contains 2`, }, }, { @@ -1141,10 +1141,10 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p { q = true with input as 1 } - q { r[x] = input } - r[1] - r[2]`, + p if { q = true with input as 1 } + q if { r[x] = input } + r contains 1 + r contains 2`, }, wantQueries: []string{ `data.partial.test.q = true with input as 1`, @@ -1152,8 +1152,8 @@ func TestTopDownPartialEval(t *testing.T) { wantSupport: []string{ `package partial.test - q { 1 = input } - q { 2 = input }`, + q if { 1 = input } + q if { 2 = input }`, }, }, { @@ -1162,8 +1162,8 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p { input.x = z; [z] = x; q with data.foo as x } - q { data.foo = [1] }`, + p if { input.x = z; [z] = x; q with data.foo as x } + q if { data.foo = [1] }`, }, wantQueries: []string{"data.test.q with data.foo as [input.x]"}, }, @@ -1173,8 +1173,8 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - q = 1 { input.foo = 1 } - p = y { x = q with data.bar as input.bar; plus(x, 1, y) }`, + q = 1 if { input.foo = 1 } + p = y if { x = q with data.bar as input.bar; plus(x, 1, y) }`, }, wantQueries: []string{"x1 = data.test.q with data.bar as input.bar; plus(x1, 1, z)"}, }, @@ -1184,8 +1184,8 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - q[1] { input.foo = 1 } - p = y { q[x] with data.bar as input.bar; plus(x, 1, y) }`, + q contains 1 if { input.foo = 1 } + p = y if { q[x] with data.bar as input.bar; plus(x, 1, y) }`, }, wantQueries: []string{"data.test.q[x1] with data.bar as input.bar; plus(x1, 1, z)"}, }, @@ -1195,8 +1195,8 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - f(t) = 1 { input.foo = t } - p = y { f(1, x) with data.bar as input.bar; plus(x, 1, y) }`, + f(t) = 1 if { input.foo = t } + p = y if { f(1, x) with data.bar as input.bar; plus(x, 1, y) }`, }, wantQueries: []string{"data.test.f(1, x1) with data.bar as input.bar; plus(x1, 1, z)"}, }, @@ -1206,7 +1206,7 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p = y { time.now_ns(x) with data.bar as input.bar; plus(x, 1, y) }`, + p = y if { time.now_ns(x) with data.bar as input.bar; plus(x, 1, y) }`, }, wantQueries: []string{"time.now_ns(x1) with data.bar as input.bar; plus(x1, 1, z)"}, }, @@ -1216,14 +1216,14 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p { q[1] = 1 with input as 1 } - q[x] { x = 1 }`, + p if { q[1] = 1 with input as 1 } + q contains x if { x = 1 }`, }, wantQueries: []string{`data.partial.test.q[1] = 1 with input as 1`}, wantSupport: []string{ `package partial.test - q[1]`, + q contains 1`, }, }, { @@ -1232,14 +1232,14 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p { q[x] = 1 with input as 1 } - q[x] { x = 1 }`, + p if { q[x] = 1 with input as 1 } + q contains x if { x = 1 }`, }, wantQueries: []string{`data.partial.test.q[x1] = 1 with input as 1`}, wantSupport: []string{ `package partial.test - q[1]`, + q contains 1`, }, }, { @@ -1249,8 +1249,8 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p[x] { q[x] } - q[7] { false with input as 1 }`, + p contains x if { q[x] } + q contains 7 if { false with input as 1 }`, }, wantQueries: []string{`set() = a`}, }, @@ -1261,8 +1261,8 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p[x] = y { q[x] = y } - q[7] = 8 { false with input as 1 }`, + p[x] = y if { q[x] = y } + q[7] = 8 if { false with input as 1 }`, }, wantQueries: []string{`{} = a`}, }, @@ -1273,8 +1273,8 @@ func TestTopDownPartialEval(t *testing.T) { `package test mock_concat(_, _) = "foo/bar" - p { q with concat as mock_concat } - q { concat("/", ["a", "b"], "foo/bar") }`, + p if { q with concat as mock_concat } + q if { concat("/", ["a", "b"], "foo/bar") }`, }, wantQueries: []string{`a = true`}, }, @@ -1284,8 +1284,8 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p { q with concat as "foo/bar" } - q { concat("/", ["a", "b"], "foo/bar") }`, + p if { q with concat as "foo/bar" } + q if { concat("/", ["a", "b"], "foo/bar") }`, }, wantQueries: []string{`a = true`}, }, @@ -1296,8 +1296,8 @@ func TestTopDownPartialEval(t *testing.T) { `package test f(_, _) = "x" mock_f(_, _) = "foo/bar" - p { q with f as mock_f } - q { f("/", ["a", "b"], "foo/bar") }`, + p if { q with f as mock_f } + q if { f("/", ["a", "b"], "foo/bar") }`, }, wantQueries: []string{`a = true`}, }, @@ -1307,8 +1307,8 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test f(_, _) = "x" - p { q with f as "foo/bar" } - q { f("/", ["a", "b"], "foo/bar") }`, + p if { q with f as "foo/bar" } + q if { f("/", ["a", "b"], "foo/bar") }`, }, wantQueries: []string{`a = true`}, }, @@ -1319,14 +1319,14 @@ func TestTopDownPartialEval(t *testing.T) { `package test mock_concat(x, _) = concat(x, input) - p { q with concat as mock_concat} - q { concat("/", ["a", "b"], "foo/bar") }`, + p if { q with concat as mock_concat} + q if { concat("/", ["a", "b"], "foo/bar") }`, }, wantQueries: []string{`data.partial.test.mock_concat("/", ["a", "b"], "foo/bar"); a = true`}, wantSupport: []string{ `package partial.test - mock_concat(__local0__3, __local1__3) = __local2__3 { + mock_concat(__local0__3, __local1__3) = __local2__3 if { __local3__3 = input concat(__local0__3, __local3__3, __local2__3) }`, @@ -1338,15 +1338,15 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test f(_) = "x/y" - mock_f(_) = "foo/bar" { input.y } - p { q with f as mock_f} - q { f("/", "foo/bar") }`, + mock_f(_) = "foo/bar" if { input.y } + p if { q with f as mock_f} + q if { f("/", "foo/bar") }`, }, wantQueries: []string{`data.partial.test.mock_f("/", "foo/bar"); a = true`}, wantSupport: []string{ `package partial.test - mock_f(__local1__3) = "foo/bar" { + mock_f(__local1__3) = "foo/bar" if { input.y = x_term_3_03 x_term_3_03 }`, @@ -1359,10 +1359,10 @@ func TestTopDownPartialEval(t *testing.T) { `package test mock_concat(_, _) = ["foo", "bar"] - p { + p if { q with array.concat as mock_concat } - q { + q if { array.concat(["foo"], input, ["foo", "bar"]) }`, }, @@ -1372,7 +1372,7 @@ func TestTopDownPartialEval(t *testing.T) { `}, wantSupport: []string{`package partial.test - q { + q if { data.partial.test.mock_concat(["foo"], input, ["foo", "bar"]) } mock_concat(__local0__3, __local1__3) = ["foo", "bar"] @@ -1385,10 +1385,10 @@ func TestTopDownPartialEval(t *testing.T) { `package test my_concat(x, y) = concat(x, y) mock_concat(_, _) = "foo,bar" - p { + p if { q with my_concat as mock_concat } - q { + q if { my_concat("/", input, "foo,bar") }`, }, @@ -1398,7 +1398,7 @@ func TestTopDownPartialEval(t *testing.T) { `}, wantSupport: []string{`package partial.test - q { + q if { data.partial.test.mock_concat("/", input, "foo,bar") } mock_concat(__local2__3, __local3__3) = "foo,bar" @@ -1410,11 +1410,11 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - mock_concat(_, _) = ["foo", "bar"] { input.foo } - mock_concat(_, _) = ["bar", "baz"] { input.bar } + mock_concat(_, _) = ["foo", "bar"] if { input.foo } + mock_concat(_, _) = ["bar", "baz"] if { input.bar } - p { q with array.concat as mock_concat } - q { x := array.concat(["foo"], input) }`, + p if { q with array.concat as mock_concat } + q if { x := array.concat(["foo"], input) }`, }, wantQueries: []string{` data.partial.test.q @@ -1422,16 +1422,16 @@ func TestTopDownPartialEval(t *testing.T) { `}, wantSupport: []string{`package partial.test - q { + q if { __local6__2 = input data.partial.test.mock_concat(["foo"], __local6__2, __local5__2) __local4__2 = __local5__2 } - mock_concat(__local0__3, __local1__3) = ["foo", "bar"] { + mock_concat(__local0__3, __local1__3) = ["foo", "bar"] if { input.foo = x_term_3_03 x_term_3_03 } - mock_concat(__local2__4, __local3__4) = ["bar", "baz"] { + mock_concat(__local2__4, __local3__4) = ["bar", "baz"] if { input.bar = x_term_4_04 x_term_4_04 }`}, @@ -1442,11 +1442,11 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test my_concat(x, y) = concat(x, y) - mock_concat(_, _) = "foo,bar" { input.foo } - mock_concat(_, _) = "bar,baz" { input.bar } + mock_concat(_, _) = "foo,bar" if { input.foo } + mock_concat(_, _) = "bar,baz" if { input.bar } - p { q with my_concat as mock_concat } - q { x := my_concat(",", input) }`, + p if { q with my_concat as mock_concat } + q if { x := my_concat(",", input) }`, }, wantQueries: []string{` data.partial.test.q @@ -1454,16 +1454,16 @@ func TestTopDownPartialEval(t *testing.T) { `}, wantSupport: []string{`package partial.test - q { + q if { __local9__2 = input data.partial.test.mock_concat(",", __local9__2, __local8__2) __local6__2 = __local8__2 } - mock_concat(__local2__3, __local3__3) = "foo,bar" { + mock_concat(__local2__3, __local3__3) = "foo,bar" if { input.foo = x_term_3_03 x_term_3_03 } - mock_concat(__local4__4, __local5__4) = "bar,baz" { + mock_concat(__local4__4, __local5__4) = "bar,baz" if { input.bar = x_term_4_04 x_term_4_04 }`}, @@ -1475,11 +1475,11 @@ func TestTopDownPartialEval(t *testing.T) { package test mock_count(_) = 100 - p { + p if { not q with input.x as 1 with count as mock_count } - q { + q if { count([1,2,3]) = input.x } `}, @@ -1487,7 +1487,7 @@ func TestTopDownPartialEval(t *testing.T) { wantSupport: []string{` package partial.test - q { 100 = input.x } + q if { 100 = input.x } `}, }, { @@ -1497,11 +1497,11 @@ func TestTopDownPartialEval(t *testing.T) { package test my_count(x) = count(x) mock_count(_) = 100 - p { + p if { not q with input.x as 1 with my_count as mock_count } - q { + q if { my_count([1,2,3]) = input.x } `}, @@ -1509,7 +1509,7 @@ func TestTopDownPartialEval(t *testing.T) { wantSupport: []string{` package partial.test - q { 100 = input.x } + q if { 100 = input.x } `}, }, { @@ -1519,11 +1519,11 @@ func TestTopDownPartialEval(t *testing.T) { package test mock_count(_) = 100 - p { + p if { not q with input.x as 1 with count as mock_count } - q { + q if { count(input.y) = input.x # unknown arg for mocked func } `}, @@ -1531,7 +1531,7 @@ func TestTopDownPartialEval(t *testing.T) { wantSupport: []string{` package partial.test - q { data.partial.test.mock_count(input.y, __local1__3); __local1__3 = input.x } + q if { data.partial.test.mock_count(input.y, __local1__3); __local1__3 = input.x } mock_count(__local0__4) = 100 `}, }, @@ -1542,11 +1542,11 @@ func TestTopDownPartialEval(t *testing.T) { package test my_count(x) = count(x) mock_count(_) = 100 - p { + p if { not q with input.x as 1 with my_count as mock_count } - q { + q if { my_count(input.y) = input.x # unknown arg for mocked func } `}, @@ -1554,7 +1554,7 @@ func TestTopDownPartialEval(t *testing.T) { wantSupport: []string{` package partial.test - q { data.partial.test.mock_count(input.y, __local3__3); __local3__3 = input.x } + q if { data.partial.test.mock_count(input.y, __local3__3); __local3__3 = input.x } mock_count(__local1__4) = 100 `}, }, @@ -1564,13 +1564,13 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{` package test - mock_count(_) = 100 { input.y } - mock_count(_) = 101 { input.z } - p { + mock_count(_) = 100 if { input.y } + mock_count(_) = 101 if { input.z } + p if { not q with input.x as 1 with count as mock_count } - q { + q if { count([1]) = input.x # unknown arg for mocked func } `}, @@ -1578,9 +1578,9 @@ func TestTopDownPartialEval(t *testing.T) { wantSupport: []string{` package partial.test - q { data.partial.test.mock_count([1], __local2__3); __local2__3 = input.x } - mock_count(__local0__4) = 100 { input.y = x_term_4_04; x_term_4_04 } - mock_count(__local1__5) = 101 { input.z = x_term_5_05; x_term_5_05 } + q if { data.partial.test.mock_count([1], __local2__3); __local2__3 = input.x } + mock_count(__local0__4) = 100 if { input.y = x_term_4_04; x_term_4_04 } + mock_count(__local1__5) = 101 if { input.z = x_term_5_05; x_term_5_05 } `}, }, { @@ -1589,13 +1589,13 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{` package test my_count(x) = count(x) - mock_count(_) = 100 { input.y } - mock_count(_) = 101 { input.z } - p { + mock_count(_) = 100 if { input.y } + mock_count(_) = 101 if { input.z } + p if { not q with input.x as 1 with my_count as mock_count } - q { + q if { my_count([1]) = input.x # unknown arg for mocked func } `}, @@ -1603,9 +1603,9 @@ func TestTopDownPartialEval(t *testing.T) { wantSupport: []string{` package partial.test - q { data.partial.test.mock_count([1], __local4__3); __local4__3 = input.x } - mock_count(__local1__4) = 100 { input.y = x_term_4_04; x_term_4_04 } - mock_count(__local2__5) = 101 { input.z = x_term_5_05; x_term_5_05 } + q if { data.partial.test.mock_count([1], __local4__3); __local4__3 = input.x } + mock_count(__local1__4) = 100 if { input.y = x_term_4_04; x_term_4_04 } + mock_count(__local2__5) = 101 if { input.z = x_term_5_05; x_term_5_05 } `}, }, { @@ -1625,8 +1625,8 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p = 1; data.test.q = 2", modules: []string{ `package test - p = x { x = 1 } - q = y { y = input.y }`, + p = x if { x = 1 } + q = y if { y = input.y }`, }, wantQueries: []string{ `data.test.p = 1; 2 = input.y`, @@ -1641,14 +1641,14 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p = x", modules: []string{ `package test - p[x] { input.x = x } - p[x] { input.y = x }`, + p contains x if { input.x = x } + p contains x if { input.y = x }`, }, wantQueries: []string{`data.partial.test.p = x`}, wantSupport: []string{` package partial.test - p[x1] { input.y = x1 } - p[x2] { input.x = x2 } + p contains x1 if { input.y = x1 } + p contains x2 if { input.x = x2 } `}, }, { @@ -1657,15 +1657,15 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test import future.keywords.contains - p.q contains x { input.x = x } - p.q[r].s contains t { input.r = r; input.t = t }`, + p.q contains x if { input.x = x } + p.q[r].s contains t if { input.r = r; input.t = t }`, }, wantQueries: []string{`data.partial.test.p.q = x`}, wantSupport: []string{` package partial.test.p import future.keywords.contains - q[x2] { input.x = x2 } - q[r1].s contains t1 { input.r = r1; input.t = t1 } + q contains x2 if { input.x = x2 } + q[r1].s contains t1 if { input.r = r1; input.t = t1 } `}, }, { @@ -1673,14 +1673,14 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p = x", modules: []string{ `package test - p[x] = y { x = input.x; y = input.y } - p[x] = y { x = input.z; y = input.a }`, + p[x] = y if { x = input.x; y = input.y } + p[x] = y if { x = input.z; y = input.a }`, }, wantQueries: []string{`data.partial.test.p = x`}, wantSupport: []string{` package partial.test - p[x1] = y1 { x1 = input.z; y1 = input.a } - p[x2] = y2 { x2 = input.x; y2 = input.y } + p[x1] = y1 if { x1 = input.z; y1 = input.a } + p[x2] = y2 if { x2 = input.x; y2 = input.y } `}, }, { @@ -1688,14 +1688,14 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p.q = x", modules: []string{ `package test - p.q[x] = y { x = input.x; y = input.y } - p.q[r].s[t] = y { r = input.r; t = input.t; y = input.y }`, + p.q[x] = y if { x = input.x; y = input.y } + p.q[r].s[t] = y if { r = input.r; t = input.t; y = input.y }`, }, wantQueries: []string{`data.partial.test.p.q = x`}, wantSupport: []string{` package partial.test.p - q[x2] = y2 { x2 = input.x; y2 = input.y } - q[r1].s[t1] = y1 { r1 = input.r; t1 = input.t; y1 = input.y } + q[x2] = y2 if { x2 = input.x; y2 = input.y } + q[r1].s[t1] = y1 if { r1 = input.r; t1 = input.t; y1 = input.y } `}, }, { @@ -1704,7 +1704,7 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p[1] { input = 1; false }`, + p contains 1 if { input = 1; false }`, }, wantQueries: []string{`x = set()`}, }, @@ -1713,12 +1713,12 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test[x] = y", modules: []string{ `package test - import future.keywords.contains - s[x] { x = input.x } - s2[x].u contains y { x = input.x; y = input.y } - p[x] = y { x = input.x; y = input.y } - p2[x].r[y] = z { x = input.x; y = input.y; z = input.z } - r = x { x = input.x }`, + + s contains x if { x = input.x } + s2[x].u contains y if { x = input.x; y = input.y } + p[x] = y if { x = input.x; y = input.y } + p2[x].r[y] = z if { x = input.x; y = input.y; z = input.z } + r = x if { x = input.x }`, }, wantQueries: []string{ `data.partial.test.s = y; x = "s"`, @@ -1729,11 +1729,10 @@ func TestTopDownPartialEval(t *testing.T) { }, wantSupport: []string{` package partial.test - import future.keywords.contains - p[x1] = y1 { x1 = input.x; y1 = input.y } - p2[x2].r[y2] = z2 { x2 = input.x; y2 = input.y; z2 = input.z } - s[x4] { x4 = input.x } - s2[x5].u contains y5 { x5 = input.x; y5 = input.y } + p[x1] = y1 if { x1 = input.x; y1 = input.y } + p2[x2].r[y2] = z2 if { x2 = input.x; y2 = input.y; z2 = input.z } + s contains x4 if { x4 = input.x } + s2[x5].u contains y5 if { x5 = input.x; y5 = input.y } `}, }, { @@ -1741,7 +1740,7 @@ func TestTopDownPartialEval(t *testing.T) { query: `data.test.p = true`, modules: []string{` package test - p { x = input; {x} = {1} }`}, + p if { x = input; {x} = {1} }`}, wantQueries: []string{`{input} = {1}`}, }, { @@ -1763,8 +1762,8 @@ func TestTopDownPartialEval(t *testing.T) { query: `input = x; data.test.f(x)`, modules: []string{` package test - f(x) = true { x = 1 } - else = false { x = 2 }`}, + f(x) = true if { x = 1 } + else = false if { x = 2 }`}, wantQueries: []string{ `input = x; data.test.f(x)`, }, @@ -1774,15 +1773,15 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p = {1,2}", modules: []string{ `package test - p[1] - p[2] { 1 with data.foo as 1 }`, + p contains 1 + p contains 2 if { 1 with data.foo as 1 }`, }, wantQueries: []string{`data.partial.test.p = {1,2}`}, // can't evaluate full extent of `p` because it depends on with statements that will be saved. wantSupport: []string{` package partial.test - p[1] { true } - p[2] { true } # note: the expression containing 'with' gets partially evaluated because it does not depend on unknowns + p contains 1 if { true } + p contains 2 if { true } # note: the expression containing 'with' gets partially evaluated because it does not depend on unknowns `}, }, { @@ -1790,8 +1789,8 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p = x", modules: []string{ `package test - p = x { q = x } - q = 100 { false } else = 200 { true }`, + p = x if { q = x } + q = 100 if { false } else = 200 if { true }`, }, wantQueries: []string{ `x = 200`, @@ -1802,8 +1801,8 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p = x", modules: []string{ `package test - p = x { q = x } - q = 100 { input.x = 1 } else = 200 { true }`, + p = x if { q = x } + q = 100 if { input.x = 1 } else = 200 if { true }`, }, wantQueries: []string{ `data.test.q = x`, @@ -1815,8 +1814,8 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p { input = z; [z] = x; f(x, true) } - f(x) { x > 1 } else = false { x < 0 }`, + p if { input = z; [z] = x; f(x, true) } + f(x) if { x > 1 } else = false if { x < 0 }`, }, wantQueries: []string{ `data.test.f([input], true)`, @@ -1834,13 +1833,13 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p = true", modules: []string{ `package test - p { q = x } - q[1] { time.now_ns() == 1579276766010057000 }`, // full extent, must save caller because time.now_ns() should not be partially evaluated + p if { q = x } + q contains 1 if { time.now_ns() == 1579276766010057000 }`, // full extent, must save caller because time.now_ns() should not be partially evaluated }, wantQueries: []string{"x1 = data.partial.test.q"}, wantSupport: []string{` package partial.test - q[1] { time.now_ns(1579276766010057000) } + q contains 1 if { time.now_ns(1579276766010057000) } `}, }, { @@ -1849,8 +1848,8 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test default p = false - p { q } - q { input.x = 1 } + p if { q } + q if { input.x = 1 } `, }, wantQueries: []string{ @@ -1858,7 +1857,7 @@ func TestTopDownPartialEval(t *testing.T) { }, wantSupport: []string{ `package partial.test - p = true { input.x = 1 } + p = true if { input.x = 1 } default p = false`, }, }, @@ -1868,9 +1867,9 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test default p = false - p { q } - q { input.x = 1 } - q { input.x = 2 } + p if { q } + q if { input.x = 1 } + q if { input.x = 2 } `, }, wantQueries: []string{ @@ -1878,8 +1877,8 @@ func TestTopDownPartialEval(t *testing.T) { }, wantSupport: []string{ `package partial.test - p = true { input.x = 1 } - p = true { input.x = 2 } + p = true if { input.x = 1 } + p = true if { input.x = 2 } default p = false `, }, @@ -1890,8 +1889,8 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test default p = false - p { q } - q { input.x = a[i] } + p if { q } + q if { input.x = a[i] } a = [1, 2] `, }, @@ -1900,8 +1899,8 @@ func TestTopDownPartialEval(t *testing.T) { }, wantSupport: []string{ `package partial.test - p = true { 1 = input.x } - p = true { 2 = input.x } + p = true if { 1 = input.x } + p = true if { 2 = input.x } default p = false`, }, }, @@ -1911,10 +1910,10 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test default p = 0 - p = 1 { q } - p = 2 { r } - q { input.x = 1 } - r { input.x = 2 } + p = 1 if { q } + p = 2 if { r } + q if { input.x = 1 } + r if { input.x = 2 } `, }, wantQueries: []string{ @@ -1922,8 +1921,8 @@ func TestTopDownPartialEval(t *testing.T) { }, wantSupport: []string{ `package partial.test - p = 1 { input.x = 1 } - p = 2 { input.x = 2 } + p = 1 if { input.x = 1 } + p = 2 if { input.x = 2 } default p = 0 `, }, @@ -1934,8 +1933,8 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test default p = 0 - p = x { x = 1; input.x = 1 } - p = x { input.x = x } + p = x if { x = 1; input.x = 1 } + p = x if { input.x = x } `, }, wantQueries: []string{ @@ -1943,8 +1942,8 @@ func TestTopDownPartialEval(t *testing.T) { }, wantSupport: []string{ `package partial.test - p = 1 { input.x = 1 } - p = x1 { input.x = x1 } + p = 1 if { input.x = 1 } + p = x1 if { input.x = x1 } default p = 0 `, }, @@ -1955,22 +1954,22 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test default p = false - p { q = true; s } # using q = true syntax to avoid dealing with implicit != false expr + p if { q = true; s } # using q = true syntax to avoid dealing with implicit != false expr default q = true # same value as expr above so default must be kept - q { r } - r { input.x = 1 } - r { input.y = 2 } - s { input.z = 3 }`, + q if { r } + r if { input.x = 1 } + r if { input.y = 2 } + s if { input.z = 3 }`, }, wantQueries: []string{ `data.partial.test.p = x`, }, wantSupport: []string{ `package partial.test - q = true { input.x = 1 } - q = true { input.y = 2 } + q = true if { input.x = 1 } + q = true if { input.y = 2 } default q = true - p = true { data.partial.test.q = true; input.z = 3 } + p = true if { data.partial.test.q = true; input.z = 3 } default p = false `, }, @@ -1981,10 +1980,10 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test default p = false - p { q[x]; not r[x] } - q[1] { input.x = 1 } - q[2] { input.y = 2 } - r[1] { input.z = 3 }`, + p if { q[x]; not r[x] } + q contains 1 if { input.x = 1 } + q contains 2 if { input.y = 2 } + r contains 1 if { input.z = 3 }`, }, wantQueries: []string{ `data.partial.test.p = x`, @@ -1992,8 +1991,8 @@ func TestTopDownPartialEval(t *testing.T) { wantSupport: []string{ `package partial.test - p = true { input.x = 1; not input.z = 3 } - p = true { input.y = 2 } + p = true if { input.x = 1; not input.z = 3 } + p = true if { input.y = 2 } default p = false `, }, @@ -2004,8 +2003,8 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test default p = 0 - p = 1 { q } - q { input.x = 1 } + p = 1 if { q } + q if { input.x = 1 } `, }, wantQueries: []string{ @@ -2014,7 +2013,7 @@ func TestTopDownPartialEval(t *testing.T) { }, wantSupport: []string{ `package partial.test - p = 1 { input.x = 1 } + p = 1 if { input.x = 1 } default p = 0`, }, }, @@ -2027,7 +2026,7 @@ func TestTopDownPartialEval(t *testing.T) { q = [1,2] default p = false - p { input.x = 1 }`, + p if { input.x = 1 }`, }, wantQueries: []string{ `data.partial.test.p = z; x = 0; y = 1`, @@ -2036,7 +2035,7 @@ func TestTopDownPartialEval(t *testing.T) { wantSupport: []string{ `package partial.test - p = true { input.x = 1 } + p = true if { input.x = 1 } default p = false`, }, }, @@ -2060,7 +2059,7 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p = x { input.x = y; y = z; z = x }`, + p = x if { input.x = y; y = z; z = x }`, }, wantQueries: []string{ `input.x > 1`, @@ -2072,7 +2071,7 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p = y { input.x = x; plus(x, 1, y) }`, + p = y if { input.x = x; plus(x, 1, y) }`, }, wantQueries: []string{ `input.x+1 > 1`, @@ -2084,7 +2083,7 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p = x { x = [input.x] } + p = x if { x = [input.x] } `, }, wantQueries: []string{ @@ -2097,7 +2096,7 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p = x { input.x = x }`, + p = x if { input.x = x }`, }, wantQueries: []string{ `input.x[0] > 1`, @@ -2109,7 +2108,7 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p = x { sort(input.x, y); y = x }`, + p = x if { sort(input.x, y); y = x }`, }, wantQueries: []string{ // copy propagation cannot remove the intermediate variable currently because @@ -2123,7 +2122,7 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p { + p if { input.x[i] = a; a.foo = 1 # same semantics as next line input.y[j].bar = 2; input.z[k]; k.baz = 3 # different semantics from previous two lines @@ -2141,7 +2140,7 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p { + p if { split(input, ":", x) y = x y[0] = "a" @@ -2171,7 +2170,7 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p { + p if { input.x = ["foo", a] input.y = a }`, @@ -2186,7 +2185,7 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p { + p if { input = y x = y x.foo = 1 @@ -2200,7 +2199,7 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p { + p if { input = y x = y x.foo = 1 @@ -2215,7 +2214,7 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p = x { + p = x if { input = x x = 100 }`, @@ -2230,11 +2229,11 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{` package test - p { + p if { not q } - q { + q if { input.x = x x = y y = 1 @@ -2248,11 +2247,11 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{` package test - p { + p if { input.x = z; not q[z] } - q[y] { + q contains y if { x = 1 x = a a = y @@ -2266,12 +2265,12 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p { + p if { input.x[i] = x not f(x) } - f(x) { + f(x) if { input.y = x }`, }, @@ -2285,7 +2284,7 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p { + p if { x = data.y[c] x.z = 1 not x.z = 2 @@ -2303,7 +2302,7 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p { + p if { x = input.y[c] x.z = 1 not x.z = 2 @@ -2321,7 +2320,7 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p { + p if { x = data.y[c] not x.z = 2 } @@ -2339,7 +2338,7 @@ func TestTopDownPartialEval(t *testing.T) { ` package test - p { + p if { x = input.x y = input.y x = {y: 1} @@ -2354,7 +2353,7 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{` package test - p { + p if { input = x y = x == 1 y @@ -2377,10 +2376,10 @@ func TestTopDownPartialEval(t *testing.T) { note: "copy propagation: circular reference (bug 3559)", query: "data.test.p", modules: []string{`package test - p { + p if { q[_] } - q[x] { + q contains x if { x = input[x] }`, }, @@ -2390,7 +2389,7 @@ func TestTopDownPartialEval(t *testing.T) { note: "copy propagation: circular reference (bug 3071)", query: "data.test.p", modules: []string{`package test - p[y] { + p contains y if { s := { i | input[i] } s & set() != s y := sprintf("%v", [s]) @@ -2398,7 +2397,7 @@ func TestTopDownPartialEval(t *testing.T) { }, wantQueries: []string{`data.partial.test.p`}, wantSupport: []string{`package partial.test - p[__local1__1] { __local0__1 = {i1 | input[i1]}; neq(and(__local0__1, set()), __local0__1); sprintf("%v", [__local0__1], __local1__1) } + p contains __local1__1 if { __local0__1 = {i1 | input[i1]}; neq(and(__local0__1, set()), __local0__1); sprintf("%v", [__local0__1], __local1__1) } `}, }, { @@ -2415,7 +2414,7 @@ func TestTopDownPartialEval(t *testing.T) { note: "copy propagation: tautology, input ref", query: "data.test.p", modules: []string{`package test - p { + p if { input.a == input.a }`, }, @@ -2425,7 +2424,7 @@ func TestTopDownPartialEval(t *testing.T) { note: "copy propagation: tautology, var ref, ref is input", query: "data.test.p", modules: []string{`package test - p { + p if { x := input x.a == x.a }`, @@ -2437,7 +2436,7 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p", unknowns: []string{"data.bar.foo"}, modules: []string{`package test - p { + p if { data.bar.foo.a == data.bar.foo.a }`, }, @@ -2451,7 +2450,7 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p", unknowns: []string{"input"}, modules: []string{`package test - p { + p if { input.foo.a == input.foo.a }`, }, @@ -2461,7 +2460,7 @@ func TestTopDownPartialEval(t *testing.T) { note: "copy propagation: tautology, var ref, ref is head var", query: "data.test.p(input)", modules: []string{`package test - p(x) { + p(x) if { x.a == x.a }`, }, @@ -2473,7 +2472,7 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - f(x) { x >= x }`, + f(x) if { x >= x }`, }, wantQueries: []string{ `input = x`, @@ -2485,8 +2484,8 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p { not q } - q { ((input.x + 7) / input.y) > 100 }`, + p if { not q } + q if { ((input.x + 7) / input.y) > 100 }`, }, wantQueries: []string{ `not data.partial.__not1_0_2__`, @@ -2494,7 +2493,7 @@ func TestTopDownPartialEval(t *testing.T) { wantSupport: []string{ `package partial - __not1_0_2__ { + __not1_0_2__ if { ((input.x + 7) / input.y) > 100 }`, }, @@ -2505,8 +2504,8 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p { not q } - q { a = input.x + 7; b = a / input.y; b > 100 }`, + p if { not q } + q if { a = input.x + 7; b = a / input.y; b > 100 }`, }, wantQueries: []string{ `not data.partial.__not1_0_2__`, @@ -2514,7 +2513,7 @@ func TestTopDownPartialEval(t *testing.T) { wantSupport: []string{ `package partial - __not1_0_2__ { + __not1_0_2__ if { ((input.x + 7) / input.y) > 100 }`, }, @@ -2525,7 +2524,7 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p { + p if { input.x = 1; # no op not q; # support not r; # fail @@ -2533,15 +2532,15 @@ func TestTopDownPartialEval(t *testing.T) { input.z = [z]; z1 = z; t(z1) # inline transitive } - q { + q if { input.a[i] = 1 } - r { false } + r if { false } - s { input.y = 2 } + s if { input.y = 2 } - t(z2) { + t(z2) if { z2 = z3 z3[0] = 1 } @@ -2553,7 +2552,7 @@ func TestTopDownPartialEval(t *testing.T) { wantSupport: []string{ `package partial - __not1_1_2__ { + __not1_1_2__ if { input.a[i3] = 1 }`, }, @@ -2564,17 +2563,17 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p { + p if { q not r } - q { + q if { input.x[i] = a startswith(a, "foo") } - r { + r if { input.y[i] = 1 }`, }, @@ -2582,7 +2581,7 @@ func TestTopDownPartialEval(t *testing.T) { wantSupport: []string{ `package partial - __not1_1_3__ { input.y[i4] = 1 }`, + __not1_1_3__ if { input.y[i4] = 1 }`, }, }, { @@ -2591,11 +2590,11 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p { + p if { input.x = x; not f(x) } - f(x) { + f(x) if { input.y[i] = a sort(x, z) z[a] = 1 @@ -2605,7 +2604,7 @@ func TestTopDownPartialEval(t *testing.T) { wantSupport: []string{` package partial - __not1_1_2__(x1) { + __not1_1_2__(x1) if { sort(x1, z3) z3[input.y[i3]] = 1 } @@ -2617,7 +2616,7 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - f(x) { + f(x) if { count(x) != 3 }`, }, @@ -2627,7 +2626,7 @@ func TestTopDownPartialEval(t *testing.T) { wantSupport: []string{ `package partial - __not0_1_1__(x) { + __not0_1_1__(x) if { count(x) != 3 }`, }, @@ -2638,11 +2637,11 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p { + p if { input = x; not f(x) } - f(x) { + f(x) if { count(x) > 3 }`, }, @@ -2652,7 +2651,7 @@ func TestTopDownPartialEval(t *testing.T) { wantSupport: []string{ `package partial - __not1_1_2__(x1) { count(x1) > 3 }`, + __not1_1_2__(x1) if { count(x1) > 3 }`, }, }, { @@ -2661,14 +2660,14 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p { + p if { y = input.y z = y x = [z, 1] not f(x) } - f(x) { + f(x) if { sum(x) > 3 }`, }, @@ -2678,7 +2677,7 @@ func TestTopDownPartialEval(t *testing.T) { wantSupport: []string{ `package partial - __not1_3_2__(z1) { + __not1_3_2__(z1) if { sum([z1, 1]) > 3 }`, }, @@ -2689,9 +2688,9 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p { not q } - q { input.x = 1 } - q { input.x = 2 } + p if { not q } + q if { input.x = 1 } + q if { input.x = 2 } `, }, wantQueries: []string{ @@ -2705,9 +2704,9 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p { input.x = x; not q(x) } - q(x) { x = 1 } - q(x) { x = 2 }`, + p if { input.x = x; not q(x) } + q(x) if { x = 1 } + q(x) if { x = 2 }`, }, wantQueries: []string{ `not input.x = 1; not input.x = 2`, @@ -2720,21 +2719,21 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{` package test - p { + p if { x = input[i] not f(x) } - f(x) { + f(x) if { q[y] not g(y, x) } - g(1, x) { + g(1, x) if { x.a = "foo" } - g(2, x) { + g(2, x) if { x.b < 7 } @@ -2748,7 +2747,7 @@ func TestTopDownPartialEval(t *testing.T) { wantSupport: []string{ `package partial - __not3_1_8__(__local0__3) { __local0__3.b < 7 }`, + __not3_1_8__(__local0__3) if { __local0__3.b < 7 }`, }, }, { @@ -2757,24 +2756,24 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p { + p if { not q } - q { + q if { x = r[_] not f(x) } - f({"key": "a", "values": values}) { + f({"key": "a", "values": values}) if { input.x = values[_] } - f({"key": "b", "values": values}) { + f({"key": "b", "values": values}) if { input.y = values[_] } - f({"key": "c", "values": values}) { + f({"key": "c", "values": values}) if { input.z = values[_] } @@ -2799,8 +2798,8 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p[[0, 1]] - p[[2, 3]]`, + p contains [0, 1] + p contains [2, 3]`, }, wantQueries: []string{ `input.x = x; input.y = y; not x = 0; not x = 2`, @@ -2814,10 +2813,10 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p = true", modules: []string{ `package test - p { + p if { not q } - q { + q if { # size of cross product is 27 which exceeds default limit a = {1,2,3} a[x] @@ -2831,9 +2830,9 @@ func TestTopDownPartialEval(t *testing.T) { wantSupport: []string{ `package partial - __not1_0_2__ { input.x = 1; input.y = 1; input.z = 0 } - __not1_0_2__ { input.x = 2; input.y = 2; input.z = 0 } - __not1_0_2__ { input.x = 3; input.y = 3; input.z = 0 } + __not1_0_2__ if { input.x = 1; input.y = 1; input.z = 0 } + __not1_0_2__ if { input.x = 2; input.y = 2; input.z = 0 } + __not1_0_2__ if { input.x = 3; input.y = 3; input.z = 0 } `, }, }, @@ -2843,7 +2842,7 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p[y] { + p contains y if { y = input not y = 1 } @@ -2859,10 +2858,10 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p { input = z; [z] = x; not q[x] } + p if { input = z; [z] = x; not q[x] } - q[[1]] - q[[2]]`, + q contains [1] + q contains [2]`, }, wantQueries: []string{ `not input = 1; not input = 2`, @@ -2873,10 +2872,10 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p = true", modules: []string{` package test - f(x) = y { + f(x) = y if { y = x == 1 } - p { + p if { f(input) } `}, @@ -2897,13 +2896,13 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p = true", modules: []string{` package test - p { q; r } - q { s[input] } - q { t[input] } - r { s[input] } - s[1] - s[2] - t[3] + p if { q; r } + q if { s[input] } + q if { t[input] } + r if { s[input] } + s contains 1 + s contains 2 + t contains 3 `}, wantQueries: []string{ "data.partial.test.q; 1 = input", @@ -2912,9 +2911,9 @@ func TestTopDownPartialEval(t *testing.T) { wantSupport: []string{ `package partial.test - q { 1 = input } - q { 2 = input } - q { 3 = input } `, + q if { 1 = input } + q if { 2 = input } + q if { 3 = input } `, }, disableInlining: []string{`data.test.q`}, }, @@ -2923,10 +2922,10 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p = true", modules: []string{` package test - p { s; q[x] } - q = ["a", "b"] { r[_] = input } + p if { s; q[x] } + q = ["a", "b"] if { r[_] = input } r = [1, 2] - s { r[_] = input } + s if { r[_] = input } `}, wantQueries: []string{ "1 = input; data.partial.test.q[x1]", @@ -2935,8 +2934,8 @@ func TestTopDownPartialEval(t *testing.T) { wantSupport: []string{ `package partial.test - q = ["a", "b"] { 1 = input } - q = ["a", "b"] { 2 = input }`, + q = ["a", "b"] if { 1 = input } + q = ["a", "b"] if { 2 = input }`, }, disableInlining: []string{`data.test.q`}, }, @@ -2946,9 +2945,9 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{` package test - p { q[x]; f(x) } + p if { q[x]; f(x) } q = {"a", "b"} - f(x) { input = x } + f(x) if { input = x } `}, wantQueries: []string{ `data.partial.test.f("a")`, @@ -2957,7 +2956,7 @@ func TestTopDownPartialEval(t *testing.T) { wantSupport: []string{ `package partial.test - f(__local0__3) { input = __local0__3 }`, + f(__local0__3) if { input = __local0__3 }`, }, disableInlining: []string{"data.test.f"}, }, @@ -2966,11 +2965,11 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p = true", modules: []string{` package test - p { q[x]; r[x] } - q[x] { s[x] = input } - r[x] { s[x] = input } - s[1] - s[2] + p if { q[x]; r[x] } + q contains x if { s[x] = input } + r contains x if { s[x] = input } + s contains 1 + s contains 2 `}, wantQueries: []string{ "data.partial.test.q[1]; 1 = input", @@ -2979,8 +2978,8 @@ func TestTopDownPartialEval(t *testing.T) { wantSupport: []string{ `package partial.test - q[1] { 1 = input } - q[2] { 2 = input }`, + q contains 1 if { 1 = input } + q contains 2 if { 2 = input }`, }, disableInlining: []string{`data.test.q`}, }, @@ -2989,10 +2988,10 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p = true", modules: []string{` package test - p { y = 0; q[x][y]; r } - q[x] = [1, 2] { s[x] = input } - r { input = 1 } - r { input = 2 } + p if { y = 0; q[x][y]; r } + q[x] = [1, 2] if { s[x] = input } + r if { input = 1 } + r if { input = 2 } s["a"] = 3 s["b"] = 4 `}, @@ -3003,8 +3002,8 @@ func TestTopDownPartialEval(t *testing.T) { wantSupport: []string{ `package partial.test.q - a = [1, 2] { 3 = input } - b = [1, 2] { 4 = input }`, + a = [1, 2] if { 3 = input } + b = [1, 2] if { 4 = input }`, }, disableInlining: []string{`data.test.q`}, }, @@ -3015,7 +3014,7 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p[y] { + p contains y if { y = input not y = 1 } @@ -3027,7 +3026,7 @@ func TestTopDownPartialEval(t *testing.T) { wantSupport: []string{ `package partial.test - p[y1] { y1 = input; not y1 = 1 }`, + p contains y1 if { y1 = input; not y1 = 1 }`, }, }, { @@ -3037,7 +3036,7 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p = y { + p = y if { y = input not y = 1 } @@ -3049,7 +3048,7 @@ func TestTopDownPartialEval(t *testing.T) { wantSupport: []string{ `package partial.test - p = y1 { y1 = input; not y1 = 1 }`, + p = y1 if { y1 = input; not y1 = 1 }`, }, }, { @@ -3058,26 +3057,26 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test.foo - p { + p if { data.test.bar.q[input.x] }`, `package test.bar - q[x] { data.test.baz.r[x] }`, + q contains x if { data.test.baz.r[x] }`, `package test.baz - r[1] - r[2]`, + r contains 1 + r contains 2`, }, disableInlining: []string{"data.test.bar"}, wantQueries: []string{`data.partial.test.bar.q[input.x]`}, wantSupport: []string{ `package partial.test.bar - q[1] - q[2]`, + q contains 1 + q contains 2`, }, }, { @@ -3086,7 +3085,7 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p { k = "foo"; m = "bar"; data.base[k][x][m] = 1 }`, + p if { k = "foo"; m = "bar"; data.base[k][x][m] = 1 }`, }, disableInlining: []string{"data.base"}, wantQueries: []string{"data.base.foo[x1].bar = 1"}, @@ -3097,7 +3096,7 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p { k = "bar"; data.base.foo[k].baz = 1 }`, + p if { k = "bar"; data.base.foo[k].baz = 1 }`, }, disableInlining: []string{"data.base"}, wantQueries: []string{"data.base.foo.bar.baz = 1"}, @@ -3108,9 +3107,9 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p { not q } + p if { not q } - q { r } + q if { r } r = false`, }, @@ -3128,9 +3127,9 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p = x { x = [1 | q] } + p = x if { x = [1 | q] } - q { r } + q if { r } r = true`, }, @@ -3143,11 +3142,11 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p { q = {1,2,3} } + p if { q = {1,2,3} } - q[1] - q[2] - q[3] { r } + q contains 1 + q contains 2 + q contains 3 if { r } r = true`, }, @@ -3156,9 +3155,9 @@ func TestTopDownPartialEval(t *testing.T) { wantSupport: []string{` package partial.test - q[1] - q[2] - q[3] { data.partial.test.r } + q contains 1 + q contains 2 + q contains 3 if { data.partial.test.r } r = true `}, }, @@ -3168,7 +3167,7 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p { + p if { q[input.x] } @@ -3184,17 +3183,17 @@ func TestTopDownPartialEval(t *testing.T) { ` package test - p { + p if { q = 1 } - q = x { + q = x if { r # 'r' should be inlined completely y = input.x x = y } - r { s } + r if { s } s = true `, @@ -3204,8 +3203,8 @@ func TestTopDownPartialEval(t *testing.T) { wantSupport: []string{ `package partial.test - q = x2 { y2 = input.x; x2 = y2 } - p { data.partial.test.q = 1 } + q = x2 if { y2 = input.x; x2 = y2 } + p if { data.partial.test.q = 1 } `, }, }, @@ -3216,13 +3215,13 @@ func TestTopDownPartialEval(t *testing.T) { ` package test - p { + p if { r[x] not input[x] } - r[1] - r[2] + r contains 1 + r contains 2 `, }, shallow: true, @@ -3231,14 +3230,14 @@ func TestTopDownPartialEval(t *testing.T) { ` package partial.test - p { not data.partial.__not1_1_4__ } - p { not data.partial.__not1_1_5__ } + p if { not data.partial.__not1_1_4__ } + p if { not data.partial.__not1_1_5__ } `, ` package partial - __not1_1_4__ { input[1] = x_term_4_01; x_term_4_01 } - __not1_1_5__ { input[2] = x_term_5_01; x_term_5_01 } + __not1_1_4__ if { input[1] = x_term_4_01; x_term_4_01 } + __not1_1_5__ if { input[2] = x_term_5_01; x_term_5_01 } `, }, }, @@ -3248,13 +3247,13 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{` package test - f(x) = y { + f(x) = y if { y = x == 1 } - f(x) = y { + f(x) = y if { y = x == 2 } - p { + p if { f(input) } `}, @@ -3263,9 +3262,9 @@ func TestTopDownPartialEval(t *testing.T) { wantSupport: []string{ `package partial.test - p = true { __local4__1 = input; data.partial.test.f(__local4__1) } - f(__local0__2) = y2 { equal(__local0__2, 1, __local2__2); y2 = __local2__2 } - f(__local1__3) = y3 { equal(__local1__3, 2, __local3__3); y3 = __local3__3 }`, + p = true if { __local4__1 = input; data.partial.test.f(__local4__1) } + f(__local0__2) = y2 if { equal(__local0__2, 1, __local2__2); y2 = __local2__2 } + f(__local1__3) = y3 if { equal(__local1__3, 2, __local3__3); y3 = __local3__3 }`, }, }, { @@ -3274,14 +3273,14 @@ func TestTopDownPartialEval(t *testing.T) { shallow: true, modules: []string{ `package test - f(x) = true { input.x = x } - f(x) = false { input.y = x }`, + f(x) = true if { input.x = x } + f(x) = false if { input.y = x }`, }, wantQueries: []string{`data.partial.test.f(1, x)`}, wantSupport: []string{ `package partial.test - f(__local0__2) = true { input.x = __local0__2 } - f(__local1__1) = false { input.y = __local1__1 }`, + f(__local0__2) = true if { input.x = __local0__2 } + f(__local1__1) = false if { input.y = __local1__1 }`, }, }, { @@ -3290,9 +3289,9 @@ func TestTopDownPartialEval(t *testing.T) { shallow: true, modules: []string{ `package test - f(x) = true { x >= 1 } - f(x) = false { x < 0 } - f(x) = "meow" { false }`, + f(x) = true if { x >= 1 } + f(x) = false if { x < 0 } + f(x) = "meow" if { false }`, }, wantQueries: []string{`y = true`}, }, @@ -3302,8 +3301,8 @@ func TestTopDownPartialEval(t *testing.T) { shallow: true, modules: []string{ `package test - f(x, y) = true { x > 1 } - f(x, y) = false { + f(x, y) = true if { x > 1 } + f(x, y) = false if { x <= 0 count(y) == 3 }`, @@ -3316,9 +3315,9 @@ func TestTopDownPartialEval(t *testing.T) { shallow: true, modules: []string{ `package test - f(x) = "uhm" { input.x = "x"; false } - f(x) = "like" { input.y = "y"; false } - f(x) = "whatever" { false }`, + f(x) = "uhm" if { input.x = "x"; false } + f(x) = "like" if { input.y = "y"; false } + f(x) = "whatever" if { false }`, }, wantQueries: []string{}, }, @@ -3329,7 +3328,7 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test f(true) = true - f(x) = false { x != true }`, + f(x) = false if { x != true }`, }, wantQueries: []string{`y = false`}, }, @@ -3339,7 +3338,7 @@ func TestTopDownPartialEval(t *testing.T) { shallow: true, modules: []string{ `package test - f([x, y]) { + f([x, y]) if { z = 7 x > (y+z) }`, @@ -3347,7 +3346,7 @@ func TestTopDownPartialEval(t *testing.T) { wantQueries: []string{`input = x; data.partial.test.f([1, x])`}, wantSupport: []string{ `package partial.test - f([__local0__1, __local1__1]) = true { + f([__local0__1, __local1__1]) = true if { plus(__local1__1, 7, __local2__1) gt(__local0__1, __local2__1) }`, @@ -3361,15 +3360,15 @@ func TestTopDownPartialEval(t *testing.T) { ` package test - p { + p if { f(1) } - f(x) { + f(x) if { g(x) } - g(x) { + g(x) if { x = input } `, @@ -3379,9 +3378,9 @@ func TestTopDownPartialEval(t *testing.T) { ` package partial.test - p { data.partial.test.f(1) } - f(__local0__2) { data.partial.test.g(__local0__2) } - g(__local1__3) { __local1__3 = input } + p if { data.partial.test.f(1) } + f(__local0__2) if { data.partial.test.g(__local0__2) } + g(__local1__3) if { __local1__3 = input } `, }, }, @@ -3393,20 +3392,20 @@ func TestTopDownPartialEval(t *testing.T) { ` package test - p { + p if { f(1) # unknown dependency so must be saved h(8) # known so can be evaluated } - f(x) { + f(x) if { g(x) } - g(x) { + g(x) if { x = input } - h(x) { + h(x) if { x > 7 } `, @@ -3416,9 +3415,9 @@ func TestTopDownPartialEval(t *testing.T) { ` package partial.test - p { data.partial.test.f(1) } - f(__local0__2) { data.partial.test.g(__local0__2) } - g(__local1__3) { __local1__3 = input } + p if { data.partial.test.f(1) } + f(__local0__2) if { data.partial.test.g(__local0__2) } + g(__local1__3) if { __local1__3 = input } `, }, }, @@ -3428,12 +3427,12 @@ func TestTopDownPartialEval(t *testing.T) { shallow: true, modules: []string{ `package test - p { + p if { y = f(1) count(y) } - f(x) = [] { + f(x) = [] if { # NOTE(sr): if we use '_' here, we cannot ever have a match # when comparing the actual and expected support modules. _x = input # anything dependent on an unknown will do @@ -3442,12 +3441,12 @@ func TestTopDownPartialEval(t *testing.T) { wantQueries: []string{`data.partial.test.p = x_term_0_0; x_term_0_0`}, wantSupport: []string{ `package partial.test - p { + p if { data.partial.test.f(1, __local1__1) y1 = __local1__1 count(y1) } - f(__local0__2) = [] { _x2 = input } + f(__local0__2) = [] if { _x2 = input } `, }, }, @@ -3457,7 +3456,7 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ // include an unknown in the comprehension to force saving `package test - p { + p if { x = [0]; y = {true | x[0]; input.y = 1} } `}, @@ -3469,15 +3468,15 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p[x] { q[x] } - q[x] { + p contains x if { q[x] } + q contains x if { y = { 1 | input } x = true } `}, wantQueries: []string{`data.partial.test.p`}, wantSupport: []string{`package partial.test - p[true] { y2 = {1 | input} } + p contains true if { y2 = {1 | input} } `}, }, { @@ -3486,15 +3485,15 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p[x] { q[x] } - q[x] { + p contains x if { q[x] } + q contains x if { { 1 | input; x } = y x = true } `}, wantQueries: []string{`data.partial.test.p`}, wantSupport: []string{`package partial.test - p[true] { {1 | input; x2; x2 = true} = y2 } + p contains true if { {1 | input; x2; x2 = true} = y2 } `}, }, { @@ -3503,15 +3502,15 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p[x] { q[x] } - q[x] { + p contains x if { q[x] } + q contains x if { { x | input } = y x = true } `}, wantQueries: []string{`data.partial.test.p`}, wantSupport: []string{`package partial.test - p[true] { {x2 | input; x2 = true} = y2 } + p contains true if { {x2 | input; x2 = true} = y2 } `}, }, { @@ -3523,15 +3522,15 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p[x] { q[x] } - q[x] { + p contains x if { q[x] } + q contains x if { { false | input } = { true | input; x } x = true } `}, wantQueries: []string{`data.partial.test.p`}, wantSupport: []string{`package partial.test - p[true] { {false | input} = {true | input; x2; x2 = true} } + p contains true if { {false | input} = {true | input; x2; x2 = true} } `}, }, { @@ -3540,15 +3539,15 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p[x] { q[x] } - q[x] { + p contains x if { q[x] } + q contains x if { { false | input } = { x | input } x = true } `}, wantQueries: []string{`data.partial.test.p`}, wantSupport: []string{`package partial.test - p[true] { {false | input} = {x2 | input; x2 = true} } + p contains true if { {false | input} = {x2 | input; x2 = true} } `}, }, { @@ -3557,15 +3556,15 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{ `package test - p[x] { q[x] } - q[x] { + p contains x if { q[x] } + q contains x if { { "foo": false | input } = { "foo": x | input } x = true } `}, wantQueries: []string{`data.partial.test.p`}, wantSupport: []string{`package partial.test - p[true] { {"foo": false | input} = {"foo": x2 | input; x2 = true} } + p contains true if { {"foo": false | input} = {"foo": x2 | input; x2 = true} } `}, }, { @@ -3585,25 +3584,25 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{` package test - p { + p if { x = 1 not q with input.x as x } - q { + q if { r[input.x] } - r[1] - r[2] + r contains 1 + r contains 2 `}, disableInlining: []string{"data.test.q"}, wantQueries: []string{"not data.partial.test.q with input.x as 1"}, wantSupport: []string{` package partial.test - q { 1 = input.x } - q { 2 = input.x } + q if { 1 = input.x } + q if { 2 = input.x } `}, }, { @@ -3617,7 +3616,7 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{` package test - p = x { + p = x if { a = input.foo1 b = input.foo2 c = input.foo3 @@ -3639,10 +3638,10 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{` package test - p { q.foo } - p { q.foo } + p if { q.foo } + p if { q.foo } - q[x] = 1 { input[x] }`, + q[x] = 1 if { input[x] }`, }, wantQueries: []string{`input.foo`, `input.foo`}, }, @@ -3652,10 +3651,10 @@ func TestTopDownPartialEval(t *testing.T) { modules: []string{` package test - p { q.foo } - p { q.foo } + p if { q.foo } + p if { q.foo } - q[x] { input[x] }`, + q contains x if { input[x] }`, }, wantQueries: []string{`input.foo`, `input.foo`}, }, @@ -3664,37 +3663,37 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p = x", modules: []string{` package test - pkg = "foo" { input.x = "foo" } - pkg = "bar" { input.x = "bar" } - p = x { k = pkg; x = data.other[k].p } + pkg = "foo" if { input.x = "foo" } + pkg = "bar" if { input.x = "bar" } + p = x if { k = pkg; x = data.other[k].p } `, ` package other.foo - p = 1 { input = a } + p = 1 if { input = a } `, ` package other.bar - p = 2 { input = a } + p = 2 if { input = a } `}, wantQueries: []string{"data.test.p = x"}, wantSupport: []string{ ` package other.foo - p = 1 { input = a5 } + p = 1 if { input = a5 } `, ` package other.bar - p = 2 { input = a4 } + p = 2 if { input = a4 } `, ` package test - pkg = "foo" { input.x = "foo" } + pkg = "foo" if { input.x = "foo" } - pkg = "bar" { input.x = "bar" } + pkg = "bar" if { input.x = "bar" } - p = x1 { data.test.pkg = k1; "bar" = k1; data.other[k1].p = x1 } - p = x1 { data.test.pkg = k1; "foo" = k1; data.other[k1].p = x1 } + p = x1 if { data.test.pkg = k1; "bar" = k1; data.other[k1].p = x1 } + p = x1 if { data.test.pkg = k1; "foo" = k1; data.other[k1].p = x1 } `, }, shallow: true, @@ -3704,7 +3703,7 @@ func TestTopDownPartialEval(t *testing.T) { note: "every: empty domain, no unknowns", query: "data.test.p", modules: []string{`package test - p { + p if { every x in [] { x } }`}, wantQueries: []string{``}, @@ -3713,7 +3712,7 @@ func TestTopDownPartialEval(t *testing.T) { note: "every: no unknowns", query: "data.test.p", modules: []string{`package test - p { + p if { every x in [1, 2, 3] { x != 4 } }`}, wantQueries: []string{``}, @@ -3722,7 +3721,7 @@ func TestTopDownPartialEval(t *testing.T) { note: "every: empty domain, unknowns in body", query: "data.test.p", modules: []string{`package test - p { + p if { every x in [] { x > input } }`}, wantQueries: []string{`every __local0__1, __local1__1 in [] { @@ -3734,7 +3733,7 @@ func TestTopDownPartialEval(t *testing.T) { note: "every: known domain, unknowns in body", query: "data.test.p", modules: []string{`package test - p { + p if { every x in [1, 2, 3] { x > input } }`}, wantQueries: []string{`every __local0__1, __local1__1 in [1, 2, 3] { @@ -3746,7 +3745,7 @@ func TestTopDownPartialEval(t *testing.T) { note: "every: known domain, unknowns in body (with call+assignment)", query: "data.test.p", modules: []string{`package test - p { + p if { every x in [1, 2, 3] { y := x+10; y > input } }`}, wantQueries: []string{`every __local0__1, __local1__1 in [1, 2, 3] { @@ -3760,7 +3759,7 @@ func TestTopDownPartialEval(t *testing.T) { note: "every: known domain, unknowns in body, body impossible", query: "data.test.p", modules: []string{`package test - p { + p if { every x in [1, 2, 3] { false; x > input } }`}, wantQueries: []string{`every __local0__1, __local1__1 in [1, 2, 3] { @@ -3773,7 +3772,7 @@ func TestTopDownPartialEval(t *testing.T) { note: "every: unknown domain", query: "data.test.p", modules: []string{`package test - p { + p if { every x in input { x > 1 } }`}, wantQueries: []string{`every __local0__1, __local1__1 in input { __local1__1 > 1 }`}, @@ -3782,7 +3781,7 @@ func TestTopDownPartialEval(t *testing.T) { note: "every: in-scope var in body", query: "data.test.p", modules: []string{`package test - p { + p if { y := 3 every x in [1, 2] { x != 0; input > y } }`}, @@ -3792,7 +3791,7 @@ func TestTopDownPartialEval(t *testing.T) { note: "every: unknown domain, call in body", query: "data.test.p", modules: []string{`package test - p { + p if { every x in input { y = concat(",", [x]) } @@ -3803,10 +3802,10 @@ func TestTopDownPartialEval(t *testing.T) { note: "every: closing over function args", query: "data.test.p", modules: []string{`package test - p { + p if { f(input) } - f(x) { + f(x) if { every y in [1] { a = x 1 == y @@ -3818,10 +3817,10 @@ func TestTopDownPartialEval(t *testing.T) { note: "every: nested and closing over function args", query: "data.test.p", modules: []string{`package test - p { + p if { f(input) } - f(x) { + f(x) if { every y in [1] { every z in [2] { a = x @@ -3839,9 +3838,9 @@ func TestTopDownPartialEval(t *testing.T) { note: "copypropagation: keep equations that are only found in comprehensions, inlined function call", query: "data.test.p", modules: []string{`package test - key_exists(obj, k) { x = obj[k] } + key_exists(obj, k) if { x = obj[k] } - p { + p if { key_exists(input, "foo") { true | input.foo } }`}, @@ -3851,7 +3850,7 @@ func TestTopDownPartialEval(t *testing.T) { note: "copypropagation: keep equations that are only found in comprehensions", query: "data.test.p", modules: []string{`package test - p { + p if { x = input.foo { true | input.foo } }`}, @@ -3861,7 +3860,7 @@ func TestTopDownPartialEval(t *testing.T) { note: "copypropagation: keep equations that are only found in 'every' body", query: "data.test.p", modules: []string{`package test - p { + p if { x = input.foo every y in input.ys { y = input.foo } }`}, @@ -3871,7 +3870,7 @@ func TestTopDownPartialEval(t *testing.T) { note: "ref heads: \"double\" unification, single-value rule", query: "data.test.foo[input.a][input.b]", modules: []string{`package test - foo.bar[baz] { + foo.bar contains baz if { baz := "baz" }`}, wantQueries: []string{`"bar" = input.a; "baz" = input.b`}, @@ -3880,7 +3879,7 @@ func TestTopDownPartialEval(t *testing.T) { note: "general ref heads: \"triple\" unification, single-value rule", query: "data.test.foo[input.a][input.b][input.c]", modules: []string{`package test - foo.bar[baz][bax] { + foo.bar[baz] contains bax if { baz := "baz" bax := "bax" }`}, @@ -3891,7 +3890,7 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.foo[input.a][input.b]", modules: []string{`package test import future.keywords.contains - foo.bar contains baz { + foo.bar contains baz if { baz := "baz" }`}, wantQueries: []string{`"bar" = input.a; "baz" = input.b`}, @@ -3901,7 +3900,7 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.foo[input.a][input.b][input.c]", modules: []string{`package test import future.keywords.contains - foo.bar[baz] contains bax { + foo.bar[baz] contains bax if { baz := "baz" bax := "bax" }`}, @@ -3912,7 +3911,7 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p.q[x]", shallow: false, modules: []string{`package test - p.q[x] := y { + p.q[x] := y if { x := "foo" y := input.y }`}, @@ -3922,7 +3921,7 @@ func TestTopDownPartialEval(t *testing.T) { note: "ref heads: unknown ref var, unknown rule value", query: "data.test.p.q[x]", modules: []string{`package test - p.q[x] := y { + p.q[x] := y if { x := input.x y := input.y }`}, @@ -3933,12 +3932,12 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p.q.r[x]", shallow: true, modules: []string{`package test - p.q.r.s := y { + p.q.r.s := y if { y := input.y }`}, wantQueries: []string{`data.partial.test.p.q.r.s = x_term_0_0; x_term_0_0; x = "s"`}, wantSupport: []string{`package partial.test.p.q.r - s = __local0__1 { + s = __local0__1 if { __local0__1 = input.y }`}, }, @@ -3947,7 +3946,7 @@ func TestTopDownPartialEval(t *testing.T) { query: "y = data.test.p.q[x]", shallow: true, modules: []string{`package test - p.q.r.s := y { + p.q.r.s := y if { y := input.y }`}, wantQueries: []string{`data.test.p.q.r = y; x = "r"`}, @@ -3957,13 +3956,13 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p.q[x]", shallow: true, modules: []string{`package test - p.q[x] := y { + p.q[x] := y if { x := "foo" y := input.y }`}, wantQueries: []string{`data.partial.test.p.q[x] = x_term_0_0; x_term_0_0`}, wantSupport: []string{`package partial.test.p.q - foo = __local1__1 { + foo = __local1__1 if { __local1__1 = input.y }`}, }, @@ -3972,13 +3971,13 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p.q[x]", shallow: true, modules: []string{`package test - p.q[x] := y { + p.q[x] := y if { x := input.x y := input.y }`}, wantQueries: []string{`data.partial.test.p.q[x] = x_term_0_0; x_term_0_0`}, wantSupport: []string{`package partial.test.p - q[__local0__1] = __local1__1 { + q[__local0__1] = __local1__1 if { __local0__1 = input.x __local1__1 = input.y }`}, @@ -3988,13 +3987,13 @@ func TestTopDownPartialEval(t *testing.T) { query: "data.test.p.q.r.s[x]", shallow: true, modules: []string{`package test - p.q.r.s[x] := y { + p.q.r.s[x] := y if { x := input.x y := input.y }`}, wantQueries: []string{`data.partial.test.p.q.r.s[x] = x_term_0_0; x_term_0_0`}, wantSupport: []string{`package partial.test.p.q.r - s[__local0__1] = __local1__1 { + s[__local0__1] = __local1__1 if { __local0__1 = input.x __local1__1 = input.y }`}, @@ -4005,12 +4004,12 @@ func TestTopDownPartialEval(t *testing.T) { shallow: true, modules: []string{`package test import future.keywords.contains - p.q contains y { + p.q contains y if { y := input.y }`}, wantQueries: []string{`data.partial.test.p.q[x] = x_term_0_0; x_term_0_0`}, wantSupport: []string{`package partial.test.p - q[__local0__1] { + q contains __local0__1 if { __local0__1 = input.y }`}, }, @@ -4018,13 +4017,13 @@ func TestTopDownPartialEval(t *testing.T) { note: "ref heads: special characters in ref var", query: `data.test.p.q[input.z]`, modules: []string{`package test - p.q["foo/bar"][x] { + p.q["foo/bar"][x] if { x := "baz" input.x == input.y }`}, wantQueries: []string{`"foo/bar" = input.z; data.partial.test.p.q["foo/bar"]`}, wantSupport: []string{`package partial.test.p - q["foo/bar"].baz = true { + q["foo/bar"].baz = true if { input.x = input.y }`}, }, @@ -4032,13 +4031,13 @@ func TestTopDownPartialEval(t *testing.T) { note: "ref heads: special characters in ref var (multiple)", query: `data.test.p.q[input.a][input.b]`, modules: []string{`package test - p.q["do/re"]["mi/fa"][x] { + p.q["do/re"]["mi/fa"][x] if { x := "baz" input.x == input.y }`}, wantQueries: []string{`"do/re" = input.a; "mi/fa" = input.b; data.partial.test.p.q["do/re"]["mi/fa"]`}, wantSupport: []string{`package partial.test.p - q["do/re"]["mi/fa"].baz = true { + q["do/re"]["mi/fa"].baz = true if { input.x = input.y }`}, }, @@ -4125,7 +4124,7 @@ func TestTopDownPartialEval(t *testing.T) { expectedSupport = tc.wantSupportASTs } else { for i := range tc.wantSupport { - expectedSupport = append(expectedSupport, ast.MustParseModule(tc.wantSupport[i])) + expectedSupport = append(expectedSupport, ast.MustParseModuleWithOpts(tc.wantSupport[i], opts)) } } supportA, supportB := moduleSet(support), moduleSet(expectedSupport) diff --git a/topdown/topdown_test.go b/topdown/topdown_test.go index f7955c39e5..63c0555517 100644 --- a/topdown/topdown_test.go +++ b/topdown/topdown_test.go @@ -41,8 +41,8 @@ func TestTopDownQueryIDsUnique(t *testing.T) { compiler := compileModules([]string{ `package x - p { 1 } - p { 2 }`}) + p if { 1 } + p if { 2 }`}) tr := []*Event{} @@ -79,12 +79,12 @@ func TestTopDownIndexExpr(t *testing.T) { compiler := compileModules([]string{ `package test - p = true { + p = true if { 1 > 0 q } - q = true { true }`}) + q = true if { true }`}) tr := []*Event{} @@ -139,14 +139,14 @@ func TestTopDownWithKeyword(t *testing.T) { note: "invalidate comprehension cache", exp: `[[{"b": ["a", "c"]}], [{"b": ["a"]}]]`, modules: []string{`package ex - s[x] { + s contains x if { x = {v: ks | v = input[i] ks = {k | v = input[k]} } } `}, - rules: []string{`p = [x, y] { + rules: []string{`p = [x, y] if { x = data.ex.s with input as {"a": "b", "c": "b"} y = data.ex.s with input as {"a": "b"} }`}, @@ -189,7 +189,7 @@ func TestTopDownQueryCancellation(t *testing.T) { ` package test - p { data.arr[_] = x; test.sleep("10ms"); x == 999 } + p if { data.arr[_] = x; test.sleep("10ms"); x == 999 } `, }) @@ -234,8 +234,9 @@ func TestTopDownQueryCancellationEvery(t *testing.T) { module := func(ev ast.Every, _ ...interface{}) *ast.Module { t.Helper() - m := ast.MustParseModule(`package test - p { true }`) + m := ast.MustParseModuleWithOpts(`package test + p if { true }`, + ast.ParserOptions{AllFutureKeywords: true}) m.Rules[0].Body = ast.NewBody(ast.NewExpr(&ev)) return m } @@ -352,19 +353,19 @@ func TestTopDownEarlyExit(t *testing.T) { note: "complete doc", module: ` package test - p { trace("a") } - p { trace("b") }`, + p if { trace("a") } + p if { trace("b") }`, notes: n("a"), }, { note: "complete doc, nested, both exit early", module: ` package test - p { q; trace("a") } - p { q; trace("b") } + p if { q; trace("a") } + p if { q; trace("b") } - q { trace("c") } - q { trace("d") }`, + q if { trace("c") } + q if { trace("d") }`, extraExit: 1, // p + q notes: n("a", "c"), }, @@ -372,12 +373,12 @@ func TestTopDownEarlyExit(t *testing.T) { note: "complete doc, nested, both exit early (else)", module: ` package test - p { q; trace("a") } - p { q; trace("b") } + p if { q; trace("a") } + p if { q; trace("b") } - q { trace("c"); false } - else = true { trace("d")} - q { trace("e") }`, + q if { trace("c"); false } + else = true if { trace("d")} + q if { trace("e") }`, extraExit: 1, // p + q notes: n("a", "c", "d"), }, @@ -385,39 +386,39 @@ func TestTopDownEarlyExit(t *testing.T) { note: "complete doc: other complete doc that cannot exit early", module: ` package test - p { q } + p if { q } - q = x { x := true; trace("a") } - q = x { x := true; trace("b") }`, + q = x if { x := true; trace("a") } + q = x if { x := true; trace("b") }`, notes: n("a", "b"), }, { note: "complete doc: other complete doc that cannot exit early, one undefined", module: ` package test - p { q } + p if { q } - q = x { x := true; trace("a"); false } - q = x { x := true; trace("b") }`, + q = x if { x := true; trace("a"); false } + q = x if { x := true; trace("b") }`, notes: n("a", "b"), }, { note: "complete doc: other complete doc that cannot exit early (else)", module: ` package test - p { q } + p if { q } - q = x { x := true; trace("a"); false } - else = x { x := true; trace("b") }`, + q = x if { x := true; trace("a"); false } + else = x if { x := true; trace("b") }`, notes: n("a", "b"), }, { note: "complete doc: other complete doc that cannot exit early, partial doc", module: ` package test - p { q } + p if { q } - q[x] { + q contains x if { x := [1, 2, 3][_]; trace("a") }`, notes: n("a", "a", "a"), @@ -426,12 +427,12 @@ func TestTopDownEarlyExit(t *testing.T) { note: "complete doc, iteration: other partial doc that cannot exit early", module: ` package test - p { + p if { data.arr[_] = x; trace("x") q } - q[x] { + q contains x if { x := [1, 2, 3][_]; trace("a") }`, notes: n("x", "a", "a", "a"), @@ -440,16 +441,16 @@ func TestTopDownEarlyExit(t *testing.T) { note: "complete doc, iteration: multiple other partial docs that cannot exit early", module: ` package test - p { + p if { data.arr[_] = x; trace("x") q } - q[x] { + q contains x if { x := [1, 2, 3][_]; trace("a") } - q[x] { + q contains x if { x := [4, 5, 6][_]; trace("b") }`, notes: n("x", "a", "a", "a", "b", "b", "b"), @@ -458,22 +459,22 @@ func TestTopDownEarlyExit(t *testing.T) { note: "complete doc: other function that cannot exit early", module: ` package test - p { q(1) } + p if { q(1) } - q(_) = x { x := true; trace("a") } - q(_) = x { x := true; trace("b") }`, + q(_) = x if { x := true; trace("a") } + q(_) = x if { x := true; trace("b") }`, notes: n("a", "b"), }, { note: "complete doc: other function that cannot exit early (else)", module: ` package test - p { q(1) } + p if { q(1) } - q(_) = x { x := true; trace("a"); false } - else = true { trace("b") } + q(_) = x if { x := true; trace("a"); false } + else = true if { trace("b") } - q(_) = x { x := true; trace("c") }`, + q(_) = x if { x := true; trace("c") }`, notes: n("a", "b", "c"), }, { @@ -481,8 +482,8 @@ func TestTopDownEarlyExit(t *testing.T) { module: ` package test p = f(1) - f(_) { trace("a") } - f(_) { trace("b") }`, + f(_) if { trace("a") } + f(_) if { trace("b") }`, notes: n("a"), }, { @@ -490,10 +491,10 @@ func TestTopDownEarlyExit(t *testing.T) { module: ` package test p = f(1) - f(_) { g(1); trace("a") } - f(_) { g(1); trace("b") } - g(_) { trace("c") } - g(_) { trace("d") }`, + f(_) if { g(1); trace("a") } + f(_) if { g(1); trace("b") } + g(_) if { trace("c") } + g(_) if { trace("d") }`, notes: n("a", "c"), extraExit: 1, // f() + g() }, @@ -503,12 +504,12 @@ func TestTopDownEarlyExit(t *testing.T) { package test p = f(1) - f(_) { g(1); trace("a") } - f(_) { g(1); trace("b") } + f(_) if { g(1); trace("a") } + f(_) if { g(1); trace("b") } - g(_) { trace("c"); false } - else = true { trace("d") } - g(_) { trace("e") }`, + g(_) if { trace("c"); false } + else = true if { trace("d") } + g(_) if { trace("e") }`, notes: n("a", "c", "d"), extraExit: 1, // f() + g() }, @@ -517,9 +518,9 @@ func TestTopDownEarlyExit(t *testing.T) { module: ` package test p = f(1) - f(_) { q } - q = x { x := true; trace("a") } - q = x { x := true; trace("b") }`, + f(_) if { q } + q = x if { x := true; trace("a") } + q = x if { x := true; trace("b") }`, notes: n("a", "b"), }, { @@ -527,16 +528,16 @@ func TestTopDownEarlyExit(t *testing.T) { module: ` package test p = f(1) - f(_) { q } - q = x { x := true; trace("a"); false } - else = x { x := true; trace("b") }`, + f(_) if { q } + q = x if { x := true; trace("a"); false } + else = x if { x := true; trace("b") }`, notes: n("a", "b"), }, { note: "complete doc, array iteration", module: ` package test - p { data.arr[_] = _; trace("x") } + p if { data.arr[_] = _; trace("x") } `, notes: n("x"), }, @@ -544,7 +545,7 @@ func TestTopDownEarlyExit(t *testing.T) { note: "complete doc, multiple array iteration", module: ` package test - p { + p if { data.arr[_] = x; trace("x") data.arr[_] = y; trace("y") data.arr[_] = z; trace("z") @@ -556,13 +557,13 @@ func TestTopDownEarlyExit(t *testing.T) { note: "complete doc, multiple array iteration, ref to other complete doc with iteration", module: ` package test - p { + p if { data.arr[_] = x; trace("x") data.arr[_] = y; trace("y") q; trace("q") } - q { + q if { data.arr[_] = a; trace("a") data.arr[_] = b; trace("b") } @@ -574,19 +575,19 @@ func TestTopDownEarlyExit(t *testing.T) { note: "complete doc, multiple array iteration, ref to multiple other complete docs with iteration", module: ` package test - p { + p if { data.arr[_] = x; trace("x") data.arr[_] = y; trace("y") q; trace("q") } - q { + q if { data.arr[_] = a; trace("a") data.arr[_] = b; trace("b") } # Not called because of EE - q { + q if { data.arr[_] = a; trace("c") data.arr[_] = b; trace("d") } @@ -598,14 +599,14 @@ func TestTopDownEarlyExit(t *testing.T) { note: "complete doc, multiple array iterations, ref to other complete doc with iteration and cached result", module: ` package test - p { + p if { data.arr[_] = x; trace("x") data.arr[_] = y; trace("y") q; trace("q1") q; trace("q2") # result of q in cache } - q { + q if { data.arr[_] = a; trace("a") data.arr[_] = b; trace("b") } @@ -617,20 +618,20 @@ func TestTopDownEarlyExit(t *testing.T) { note: "complete doc, multiple array iterations, ref to multiple other complete docs with iteration and cached result", module: ` package test - p { + p if { data.arr[_] = x; trace("x") data.arr[_] = y; trace("y") q; trace("q1") q; trace("q2") # result of q in cache } - q { + q if { data.arr[_] = a; trace("a") data.arr[_] = b; trace("b") } # Not called because of EE - q { + q if { data.arr[_] = a; trace("c") data.arr[_] = b; trace("d") } @@ -642,19 +643,19 @@ func TestTopDownEarlyExit(t *testing.T) { note: "complete doc, multiple array iterations, ref to other multiple complete docs with iteration", module: ` package test - p { + p if { data.arr[_] = x; trace("x") data.arr[_] = y; trace("y") q; trace("q") r; trace("r") } - q { + q if { data.arr[_] = a; trace("a") data.arr[_] = b; trace("b") } - r { + r if { data.arr[_] = c; trace("c") data.arr[_] = d; trace("d") } @@ -667,7 +668,7 @@ func TestTopDownEarlyExit(t *testing.T) { module: ` package test arr := ["a", "b", "c"] - p { + p if { arr[_] = x; trace("x") } `, @@ -679,7 +680,7 @@ func TestTopDownEarlyExit(t *testing.T) { module: ` package test arr := ["a", "b", "c"] - p { + p if { arr[_] = x; trace("x") arr[_] = y; trace("y") # arr in cache } @@ -690,12 +691,12 @@ func TestTopDownEarlyExit(t *testing.T) { { // Regression test for: https://github.com/open-policy-agent/opa/issues/6566 note: "complete doc, array iteration, ref to other complete doc without early exit", module: `package test - p { + p if { data.arr[_]; trace("x") q; trace("y") } - q := x { + q := x if { x := 1 }`, notes: n("x", "y"), @@ -703,16 +704,16 @@ func TestTopDownEarlyExit(t *testing.T) { { // Regression test for: https://github.com/open-policy-agent/opa/issues/6566 note: "complete doc, array iteration, ref to other complete doc without early exit (multiple rules)", module: `package test - p { + p if { data.arr[_]; trace("x") q; trace("y") } - q := x { + q := x if { x := 1; trace("a") } - q := x { + q := x if { x := 1; trace("b") }`, notes: n("x", "a", "b", "y"), @@ -720,17 +721,17 @@ func TestTopDownEarlyExit(t *testing.T) { { // Regression test for: https://github.com/open-policy-agent/opa/issues/6566 note: "complete doc, array iteration, multiple refs to other complete docs without early exit", module: `package test - p { + p if { data.arr[_]; trace("x") q; trace("y") r; trace("z") } - q := x { + q := x if { x := 1 } - r := x { + r := x if { x := 2 }`, notes: n("x", "y", "z"), @@ -739,12 +740,12 @@ func TestTopDownEarlyExit(t *testing.T) { note: "complete doc, array iteration, func call with early exit", module: ` package test - p { + p if { data.arr[_] = x; trace("x") f(1) == 1 } - f(x) := 1 { + f(x) := 1 if { trace("a") } `, @@ -755,16 +756,16 @@ func TestTopDownEarlyExit(t *testing.T) { note: "complete doc, multiple array iterations, func call multiple early exit", module: ` package test - p { + p if { data.arr[_] = x; trace("x") f(1) == 1 } - f(x) := 1 { + f(x) := 1 if { trace("a") } - f(x) := 1 { + f(x) := 1 if { trace("b") } `, @@ -775,20 +776,20 @@ func TestTopDownEarlyExit(t *testing.T) { note: "complete doc, multiple array iterations, func call without early exit", module: ` package test - p { + p if { data.arr[_] = x; trace("x") f(1) == 1 } - f(x) := 1 { + f(x) := 1 if { trace("a") } - f(x) := 1 { + f(x) := 1 if { trace("b") } - f(x) := 2 { + f(x) := 2 if { trace("c") false # to avoid eval_conflict_error error } @@ -799,12 +800,12 @@ func TestTopDownEarlyExit(t *testing.T) { note: "complete doc, multiple array iterations, func call with early exit and iteration", module: ` package test - p { + p if { data.arr[_] = x; trace("x") f(1) == 1 } - f(x) := 1 { + f(x) := 1 if { data.arr[_] = a; trace("a") } `, @@ -815,12 +816,12 @@ func TestTopDownEarlyExit(t *testing.T) { note: "complete doc, array iteration, func call without early exit, static arg", module: ` package test - p { + p if { data.arr[_] = x; trace("x") f(1) == 1 } - f(x) := x { + f(x) := x if { trace("a") } `, @@ -830,12 +831,12 @@ func TestTopDownEarlyExit(t *testing.T) { note: "complete doc, array iteration -> func call without early exit, dynamic arg", module: ` package test - p { + p if { data.arr[_] = x; trace("x") f(x) == x } - f(x) := x { + f(x) := x if { trace("a") } `, @@ -847,12 +848,12 @@ func TestTopDownEarlyExit(t *testing.T) { package test s := { 1, 2, 3 } - p { + p if { s[_] = x; trace("x") f(x) == x } - f(x) := x { + f(x) := x if { trace("a") } `, @@ -869,12 +870,12 @@ func TestTopDownEarlyExit(t *testing.T) { "c": 3, } - p { + p if { o[_] = x; trace("x") f(x) == x } - f(x) := x { + f(x) := x if { trace("a") } `, @@ -885,14 +886,14 @@ func TestTopDownEarlyExit(t *testing.T) { note: "complete doc, array iteration -> func call without early exit, array iteration, dynamic arg", module: ` package test - p { + p if { arr[_] = x; trace("x") f(x) == x } arr := [1, 2, 3, 4, 2] - f(x) := x { + f(x) := x if { arr[_] = y; trace("a") y == 2; trace("b") # y will have exactly two matches, so we expect two "b" notes, and an exhaustive number of "a" notes } @@ -907,12 +908,12 @@ func TestTopDownEarlyExit(t *testing.T) { s := { 1, 2, 3, 4, 5 } - p { + p if { s[_] = x; trace("x") f(x) == x } - f(x) := x { + f(x) := x if { s[_] = y; trace("a") y == 1; trace("b") # y will have exactly one match, so we expect one "b" note, and an exhaustive number of "a" notes } @@ -932,12 +933,12 @@ func TestTopDownEarlyExit(t *testing.T) { "d": 2, } - p { + p if { o[_] = x; trace("x") f(x) == x } - f(x) := x { + f(x) := x if { o[_] = y; trace("a") y == 2; trace("b") # y will have exactly two matches, so we expect two "b" notes, and an exhaustive number of "a" notes } @@ -949,14 +950,14 @@ func TestTopDownEarlyExit(t *testing.T) { note: "complete doc, array iteration -> func call without early exit, virtual doc array iteration, dynamic arg", module: ` package test - p { + p if { data.arr[_] = x; trace("x") f(x) == x } arr := [1, 2, 3, 4, 5] - f(x) := x { + f(x) := x if { arr[_] = y; trace("a") y == 3; trace("b") } @@ -968,21 +969,21 @@ arr := [1, 2, 3, 4, 5] note: "complete doc, array iteration -> func (multi) call without early exit, static arg", module: ` package test - p { + p if { data.arr[_] = x; trace("x") f(1) == 1 } - f(x) := x { + f(x) := x if { trace("a") } - f(x) := x { + f(x) := x if { trace("b") false } - f(x) := x { + f(x) := x if { trace("c") } `, @@ -992,7 +993,7 @@ arr := [1, 2, 3, 4, 5] note: "complete doc, obj iteration", module: ` package test - p { data.obj[_] = _; trace("x") } + p if { data.obj[_] = _; trace("x") } `, notes: n("x"), }, @@ -1001,7 +1002,7 @@ arr := [1, 2, 3, 4, 5] module: ` package test xs := { i | data.arr[i] } - p { xs[_] = _; trace("x") } + p if { xs[_] = _; trace("x") } `, notes: n("x"), }, @@ -1010,7 +1011,7 @@ arr := [1, 2, 3, 4, 5] module: ` package test p = f(1) - f(_) { data.arr[_] = _; trace("x") } + f(_) if { data.arr[_] = _; trace("x") } `, notes: n("x"), }, @@ -1019,7 +1020,7 @@ arr := [1, 2, 3, 4, 5] module: ` package test p = f(1) - f(_) { data.obj[_] = _; trace("x") } + f(_) if { data.obj[_] = _; trace("x") } `, notes: n("x"), }, @@ -1029,24 +1030,24 @@ arr := [1, 2, 3, 4, 5] package test xs := { i | data.arr[i] } p = f(1) - f(_) { xs[_] = _; trace("x") } + f(_) if { xs[_] = _; trace("x") } `, notes: n("x"), }, { note: "ee -> ee -> ee", module: `package test - p { + p if { data.arr[_] = x; trace("a") q; trace("b") } - q { + q if { data.arr[_] = x; trace("c") r; trace("d") } - r { + r if { data.arr[i] = x; trace("e") } `, @@ -1056,17 +1057,17 @@ arr := [1, 2, 3, 4, 5] { note: "ee -> no ee -> ee", module: `package test - p { + p if { data.arr[i] = x; trace("a") q; trace("b") } - q[x] { + q contains x if { [1, 2, 3][_] = x; trace("c") r; trace("d") } - r { + r if { data.arr[i] = x; trace("e") } `, @@ -1076,22 +1077,22 @@ arr := [1, 2, 3, 4, 5] { note: "ee -> no ee (multiple) -> ee", module: `package test - p { + p if { data.arr[i] = x; trace("a") q; trace("b") } - q[x] { + q contains x if { [1, 2, 3][_] = x; trace("c") r; trace("d") } - q[x] { + q contains x if { [4, 5, 6][_] = x; trace("e") r; trace("f") } - r { + r if { data.arr[i] = x; trace("g") } `, @@ -1101,17 +1102,17 @@ arr := [1, 2, 3, 4, 5] { note: "ee -> (no ee, ee)", module: `package test - p { + p if { data.arr[i] = x; trace("a") q; trace("b") r; trace("c") } - q[x] { + q contains x if { [1, 2, 3][_] = x; trace("d") } - r { + r if { data.arr[i] = x; trace("e") } `, @@ -1123,7 +1124,7 @@ arr := [1, 2, 3, 4, 5] note: "complete doc with every", module: `package test import future.keywords - p { + p if { data.arr[_] = x; trace("x") every x in [1, 2, 3] { x; trace("a") } } @@ -1135,7 +1136,7 @@ arr := [1, 2, 3, 4, 5] note: "complete doc -> every, array iteration", module: `package test import future.keywords - p { + p if { data.arr[_] = x; trace("x") every x in [1, 2, 3] { data.arr[_] = y; trace("a") @@ -1150,7 +1151,7 @@ arr := [1, 2, 3, 4, 5] note: "complete doc -> every, array iteration -> complete doc with ee -> complete doc no ee", module: `package test import future.keywords - p { + p if { data.arr_small[_] = x; trace("x") every x in [1, 2, 3] { data.arr_small[_] = y; trace("e1") @@ -1159,12 +1160,12 @@ arr := [1, 2, 3, 4, 5] } } - q { + q if { data.arr_small[_] = x; trace("q1") r; trace("q2") } - r := x { + r := x if { x := 1 data.arr_small[_] = y; trace("r1") } @@ -1176,7 +1177,7 @@ arr := [1, 2, 3, 4, 5] note: "complete doc -> every, array iteration -> complete doc no ee -> complete doc with ee", module: `package test import future.keywords - p { + p if { data.arr[_] = x; trace("x") every x in [1, 2, 3] { data.arr_small[_] = y; trace("e1") @@ -1185,13 +1186,13 @@ arr := [1, 2, 3, 4, 5] } } - q := x { + q := x if { x := 1 data.arr_small[_] = y; trace("q1") r; trace("q2") } - r { + r if { data.arr[_] = y; trace("r1") } `, @@ -1202,14 +1203,14 @@ arr := [1, 2, 3, 4, 5] note: "complete doc -> complete doc, no ee, with every", module: `package test import future.keywords - p { + p if { data.arr[_] = x; trace("x") q } arr := [1, 2] - q := x { + q := x if { x := 1 arr[_] = y; trace("a") every v in [1, 2, 3] { @@ -1224,14 +1225,14 @@ arr := [1, 2, 3, 4, 5] note: "complete doc -> complete doc, no ee, with every -> complete doc ee", module: `package test import future.keywords - p { + p if { data.arr[_] = x; trace("x") q } arr := [1, 2] - q := x { + q := x if { x := 1 arr[_] = y; trace("a") every v in [1, 2, 3] { @@ -1239,7 +1240,7 @@ arr := [1, 2, 3, 4, 5] } } - r { + r if { data.arr[_] = x; trace("c") } `, @@ -1251,12 +1252,12 @@ arr := [1, 2, 3, 4, 5] note: "complete doc, array iteration, ee -> array comprehension -> complete doc, ee", module: ` package test - p { + p if { data.arr[_] = x; trace("p1") y := [v | v = data.arr[_]; q]; trace("p2") } - q { + q if { data.arr[_] = x; trace("q") } `, @@ -1267,17 +1268,17 @@ arr := [1, 2, 3, 4, 5] note: "complete doc, array iteration, ee -> array comprehension -> complete doc, ee -> complete doc, no ee", module: ` package test - p { + p if { data.arr[_] = x; trace("p1") y := [v | v = data.arr[_]; q]; trace("p2") } - q { + q if { data.arr[_] = x; trace("q") r } - r := v { + r := v if { v := 1 data.arr_small[_] = x; trace("r") } @@ -1290,12 +1291,12 @@ arr := [1, 2, 3, 4, 5] note: "complete doc, array iteration, ee -> set comprehension -> complete doc, ee", module: ` package test - p { + p if { data.arr[_] = x; trace("p1") y := {v | v = data.arr[_]; q}; trace("p2") } - q { + q if { data.arr[_] = x; trace("q") } `, @@ -1306,17 +1307,17 @@ arr := [1, 2, 3, 4, 5] note: "complete doc, array iteration, ee -> set comprehension -> complete doc, ee -> complete doc, no ee", module: ` package test - p { + p if { data.arr[_] = x; trace("p1") y := {v | v = data.arr[_]; q}; trace("p2") } - q { + q if { data.arr[_] = x; trace("q") r } - r := v { + r := v if { v := 1 data.arr_small[_] = x; trace("r") } @@ -1329,12 +1330,12 @@ arr := [1, 2, 3, 4, 5] note: "complete doc, array iteration, ee -> object comprehension -> complete doc, ee", module: ` package test - p { + p if { data.arr[_] = x; trace("p1") y := {k: v | v = data.arr[k]; q}; trace("p2") } - q { + q if { data.arr[_] = x; trace("q") } `, @@ -1345,17 +1346,17 @@ arr := [1, 2, 3, 4, 5] note: "complete doc, array iteration, ee -> object comprehension -> complete doc, ee -> complete doc, no ee", module: ` package test - p { + p if { data.arr[_] = x; trace("p1") y := {k: v | v = data.arr[k]; q}; trace("p2") } - q { + q if { data.arr[_] = x; trace("q") r } - r := v { + r := v if { v := 1 data.arr_small[_] = x; trace("r") } @@ -1368,12 +1369,12 @@ arr := [1, 2, 3, 4, 5] note: "complete doc, array iteration, ee -> with -> complete doc, ee", module: ` package test - p { + p if { data.arr[_] = x; trace("p1") q with input.x as data.arr; trace("p2") } - q { + q if { input.x[_] = x; trace("q") } `, @@ -1384,12 +1385,12 @@ arr := [1, 2, 3, 4, 5] note: "complete doc, array iteration, ee -> with -> complete doc, no ee", module: ` package test - p { + p if { data.arr[_] = x; trace("p1") q with input.x as data.arr_small; trace("p2") } - q := v { + q := v if { v := 1 input.x[_] = x; trace("q") } @@ -1400,17 +1401,17 @@ arr := [1, 2, 3, 4, 5] note: "complete doc, array iteration, ee -> with -> complete doc, ee -> complete doc, no ee", module: ` package test - p { + p if { data.arr[_] = x; trace("p1") q with input.x as data.arr_small; trace("p2") } - q { + q if { input.x[_] = x; trace("q1") r; trace("q2") } - r := v { + r := v if { v := 1 input.x[_] = x; trace("r") } @@ -1422,18 +1423,18 @@ arr := [1, 2, 3, 4, 5] note: "complete doc, array iteration, ee -> with -> complete doc, no ee -> complete doc, ee", module: ` package test - p { + p if { data.arr[_] = x; trace("p1") q with input.x as data.arr_small; trace("p2") } - q := v { + q := v if { v := 1 input.x[_] = x; trace("q1") r; trace("q2") } - r { + r if { input.x[_] = x; trace("r") } `, @@ -1447,12 +1448,12 @@ arr := [1, 2, 3, 4, 5] note: "complete doc, array iteration, ee -> negated complete doc, ee", module: ` package test - p { + p if { data.arr[_] = x; trace("p1") not q; trace("p2") } - q := false { + q := false if { data.arr[_] = x; trace("q") } `, @@ -1463,12 +1464,12 @@ arr := [1, 2, 3, 4, 5] note: "complete doc, array iteration, ee -> negated complete doc, no ee", module: ` package test - p { + p if { data.arr[_] = x; trace("p1") not q; trace("p2") } - q := x { + q := x if { x := false data.arr_small[_] = y; trace("q") } @@ -1479,12 +1480,12 @@ arr := [1, 2, 3, 4, 5] note: "complete doc, array iteration, ee -> negated complete doc, aborted ee", module: ` package test - p { + p if { data.arr[_] = x; trace("p1") not q; trace("p2") } - q { + q if { data.arr_small[_] = x; trace("q") false } @@ -1563,21 +1564,21 @@ func TestTopDownEvery(t *testing.T) { { note: "domain empty", module: `package test - p { every x in [] { print(x) } } + p if { every x in [] { print(x) } } `, notes: n(), }, { note: "domain undefined", module: `package test - p { every x in input { print(x) } } + p if { every x in input { print(x) } } `, fail: true, }, { note: "domain is call", module: `package test - p { + p if { d := numbers.range(1, 5) every x in d { x >= 1; print(x) } }`, @@ -1586,7 +1587,7 @@ func TestTopDownEvery(t *testing.T) { { note: "simple value", module: `package test - p { + p if { every x in [1, 2] { print(x) } }`, notes: n("1", "2"), @@ -1594,7 +1595,7 @@ func TestTopDownEvery(t *testing.T) { { note: "simple key+value", module: `package test - p { + p if { every k, v in [1, 2] { k < v; print(v) } }`, notes: n("1", "2"), @@ -1602,7 +1603,7 @@ func TestTopDownEvery(t *testing.T) { { note: "outer bindings", module: `package test - p { + p if { i = "outer" every x in [1, 2] { print(x); print(i) } }`, @@ -1611,7 +1612,7 @@ func TestTopDownEvery(t *testing.T) { { note: "simple failure, last", module: `package test - p { + p if { every x in [1, 2] { x < 2; print(x) } }`, notes: n("1"), @@ -1620,7 +1621,7 @@ func TestTopDownEvery(t *testing.T) { { note: "simple failure, first", module: `package test - p { + p if { every x in [1, 2] { x > 1; print(x) } }`, notes: n(), @@ -1629,7 +1630,7 @@ func TestTopDownEvery(t *testing.T) { { note: "early exit in body eval on success", module: `package test - p { + p if { every x in [1, 2] { y := [false, true, true][_]; print(x); y } }`, notes: n("1", "1", "2", "2"), // Would be triples if EE in the body didn't work @@ -1637,8 +1638,8 @@ func TestTopDownEvery(t *testing.T) { { note: "early exit suppressed in body eval", module: `package test - q { print("q") } - p { + q if { print("q") } + p if { every x in [1, 2] { q; print(x) } }`, notes: n("q", "1", "2"), // Would be only "1" if the EE of q wasn't surppressed @@ -1646,7 +1647,7 @@ func TestTopDownEvery(t *testing.T) { { note: "with: domain", module: `package test - p { + p if { every x in input { print(x) } with input as [1] }`, notes: n("1"), @@ -1654,7 +1655,7 @@ func TestTopDownEvery(t *testing.T) { { note: "with: body", module: `package test - p { + p if { every x in [1, 2] { print(x); print(input) } with input as "input" }`, notes: n("1", "input", "2", "input"), @@ -1664,7 +1665,7 @@ func TestTopDownEvery(t *testing.T) { t.Run(tc.note, func(t *testing.T) { ctx := context.Background() c := ast.NewCompiler().WithEnablePrintStatements(true) - mod := ast.MustParseModuleWithOpts(tc.module, ast.ParserOptions{FutureKeywords: []string{"every"}}) + mod := ast.MustParseModuleWithOpts(tc.module, ast.ParserOptions{AllFutureKeywords: true}) if c.Compile(map[string]*ast.Module{"test": mod}); c.Failed() { t.Fatal(c.Errors) } @@ -1748,8 +1749,8 @@ func TestTopDownContextPropagation(t *testing.T) { compiler := ast.NewCompiler() compiler.Compile(map[string]*ast.Module{ "mod1": ast.MustParseModule(`package ex - -p[x] { data.a[i] = x }`, +import rego.v1 +p contains x if { data.a[i] = x }`, ), }) @@ -1898,7 +1899,7 @@ func compileModules(input []string) *ast.Compiler { for idx, i := range input { id := fmt.Sprintf("testMod%d", idx) - mods[id] = ast.MustParseModule(i) + mods[id] = ast.MustParseModuleWithOpts(i, ast.ParserOptions{AllFutureKeywords: true}) } c := ast.NewCompiler() @@ -1918,6 +1919,8 @@ func compileRules(imports []string, input []string, modules []string) (*ast.Comp }) } + popts := ast.ParserOptions{AllFutureKeywords: true} + m := &ast.Module{ Package: ast.MustParsePackage("package generated"), Imports: is, @@ -1925,7 +1928,7 @@ func compileRules(imports []string, input []string, modules []string) (*ast.Comp rules := []*ast.Rule{} for i := range input { - rules = append(rules, ast.MustParseRule(input[i])) + rules = append(rules, ast.MustParseRuleWithOpts(input[i], popts)) rules[i].Module = m } @@ -1938,7 +1941,7 @@ func compileRules(imports []string, input []string, modules []string) (*ast.Comp mods := map[string]*ast.Module{"testMod": m} for i, s := range modules { - mods[fmt.Sprintf("testMod%d", i)] = ast.MustParseModule(s) + mods[fmt.Sprintf("testMod%d", i)] = ast.MustParseModuleWithOpts(s, popts) } c := ast.NewCompiler() diff --git a/topdown/trace_test.go b/topdown/trace_test.go index dec5496cb0..d57dd3c9c9 100644 --- a/topdown/trace_test.go +++ b/topdown/trace_test.go @@ -56,8 +56,8 @@ func TestEventEqual(t *testing.T) { func TestPrettyTrace(t *testing.T) { module := `package test - p { q[x]; plus(x, 1, n) } - q[x] { x = data.a[_] }` + p if { q[x]; plus(x, 1, n) } + q contains x if { x = data.a[_] }` ctx := context.Background() compiler := compileModules([]string{module}) @@ -116,8 +116,8 @@ Redo data.test.p = _ func TestPrettyTraceWithLocation(t *testing.T) { module := `package test - p { q[x]; plus(x, 1, n) } - q[x] { x = data.a[_] }` + p if { q[x]; plus(x, 1, n) } + q contains x if { x = data.a[_] }` ctx := context.Background() compiler := compileModules([]string{module}) @@ -176,17 +176,21 @@ query:3 | | Redo data.test.q[x] func TestPrettyTraceWithLocationTruncatedPaths(t *testing.T) { ctx := context.Background() - compiler := ast.MustCompileModules(map[string]string{ + compiler := ast.MustCompileModulesWithOpts(map[string]string{ "authz_bundle/com/foo/bar/baz/qux/acme/corp/internal/authz/policies/abac/v1/beta/policy.rego": `package test import data.utils.q - p = true { q[x]; plus(x, 1, n) } + p = true if { q[x]; plus(x, 1, n) } `, "authz_bundle/com/foo/bar/baz/qux/acme/corp/internal/authz/policies/utils/utils.rego": `package utils - q[x] { x = data.a[_] } + q contains x if { x = data.a[_] } `, + }, ast.CompileOpts{ + ParserOptions: ast.ParserOptions{ + AllFutureKeywords: true, + }, }) data := loadSmallTestData() store := inmem.NewFromObject(data) @@ -243,13 +247,13 @@ authz_bundle/...ternal/authz/policies/abac/v1/beta/policy.rego:5 | | Redo da func TestPrettyTracePartialWithLocationTruncatedPaths(t *testing.T) { ctx := context.Background() - compiler := ast.MustCompileModules(map[string]string{ + compiler := ast.MustCompileModulesWithOpts(map[string]string{ "authz_bundle/com/foo/bar/baz/qux/acme/corp/internal/authz/policies/rbac/v1/beta/policy.rego": ` package example_rbac default allow = false - allow { + allow if { data.utils.user_has_role[role_name] data.utils.role_has_permission[role_name] @@ -259,19 +263,23 @@ func TestPrettyTracePartialWithLocationTruncatedPaths(t *testing.T) { "authz_bundle/com/foo/bar/baz/qux/acme/corp/internal/authz/policies/utils/user.rego": ` package utils - user_has_role[role_name] { + user_has_role contains role_name if { role_binding = data.bindings[_] role_binding.role = role_name role_binding.user = input.subject.user } - role_has_permission[role_name] { + role_has_permission contains role_name if { role = data.roles[_] role.name = role_name role.operation = input.action.operation role.resource = input.action.resource } `, + }, ast.CompileOpts{ + ParserOptions: ast.ParserOptions{ + AllFutureKeywords: true, + }, }) var data map[string]interface{} @@ -414,9 +422,9 @@ func TestTraceDuplicate(t *testing.T) { // Having `p[1]` queried first will side-step the caching optimization. module := `package test - p[1] - p[2] - p[1] + p contains 1 + p contains 2 + p contains 1 ` ctx := context.Background() @@ -453,8 +461,8 @@ func TestTraceDuplicate(t *testing.T) { func TestTraceNote(t *testing.T) { module := `package test - p { q[x]; plus(x, 1, n); trace(sprintf("n=%v", [n])) } - q[x] { x = data.a[_] }` + p if { q[x]; plus(x, 1, n); trace(sprintf("n=%v", [n])) } + q contains x if { x = data.a[_] }` ctx := context.Background() compiler := compileModules([]string{module}) @@ -518,8 +526,8 @@ Redo data.test.p = _ func TestTraceNoteWithLocation(t *testing.T) { module := `package test - p { q[x]; plus(x, 1, n); trace(sprintf("n=%v", [n])) } - q[x] { x = data.a[_] }` + p if { q[x]; plus(x, 1, n); trace(sprintf("n=%v", [n])) } + q contains x if { x = data.a[_] }` ctx := context.Background() compiler := compileModules([]string{module}) @@ -761,7 +769,7 @@ func TestTraceEveryEvaluation(t *testing.T) { note: "empty domain", query: "data.test.p = x", module: `package test - p { every k, v in [] { k != v } }`, + p if { every k, v in [] { k != v } }`, exp: events( `Enter every __local0__, __local1__ in __local2__ { neq(__local0__, __local1__) } {} (qid=2, pqid=1)`, `Exit every __local0__, __local1__ in __local2__ { neq(__local0__, __local1__) } {} (qid=2, pqid=1)`, @@ -771,7 +779,7 @@ func TestTraceEveryEvaluation(t *testing.T) { note: "successful eval", query: "data.test.p = x", module: `package test - p { every k, v in [1] { k != v } }`, + p if { every k, v in [1] { k != v } }`, exp: events( `Enter every __local0__, __local1__ in __local2__ { neq(__local0__, __local1__) } {} (qid=2, pqid=1)`, `Enter neq(__local0__, __local1__) {} (qid=3, pqid=2)`, @@ -784,7 +792,7 @@ func TestTraceEveryEvaluation(t *testing.T) { note: "failure in first body query", query: "data.test.p = x", module: `package test - p { every v in [1, 2] { 1 != v } }`, + p if { every v in [1, 2] { 1 != v } }`, exp: events( `Enter every __local0__, __local1__ in __local2__ { neq(1, __local1__) } {} (qid=2, pqid=1)`, `Enter neq(1, __local1__) {} (qid=3, pqid=2)`, @@ -797,7 +805,7 @@ func TestTraceEveryEvaluation(t *testing.T) { note: "failure in last body query", query: "data.test.p = x", module: `package test - p { every v in [0, 1] { 1 != v } }`, + p if { every v in [0, 1] { 1 != v } }`, exp: events( `Enter every __local0__, __local1__ in __local2__ { neq(1, __local1__) } {} (qid=2, pqid=1)`, `Enter neq(1, __local1__) {} (qid=3, pqid=2)`, @@ -812,7 +820,7 @@ func TestTraceEveryEvaluation(t *testing.T) { for _, tc := range tests { - opts := ast.CompileOpts{ParserOptions: ast.ParserOptions{FutureKeywords: []string{"every"}}} + opts := ast.CompileOpts{ParserOptions: ast.ParserOptions{AllFutureKeywords: true}} compiler, err := ast.CompileModulesWithOpt(map[string]string{"test.rego": tc.module}, opts) if err != nil { t.Fatal(err) @@ -1026,7 +1034,7 @@ func TestTraceInput(t *testing.T) { module := ` package test - rule = x { + rule = x if { x = input.v } ` @@ -1068,7 +1076,7 @@ func TestTracePlug(t *testing.T) { module := ` package test - rule[[a, b]] { + rule contains [a, b] if { a = [1, 2][_] b = [2, 1][_] } @@ -1158,14 +1166,14 @@ func TestPrettyTraceWithLocationForMetadataCall(t *testing.T) { module := `package test rule_no_output_var := rego.metadata.rule() -rule_with_output_var { +rule_with_output_var if { foo := rego.metadata.rule() foo == {} } chain_no_output_var := rego.metadata.chain() -chain_with_output_var { +chain_with_output_var if { foo := rego.metadata.chain() foo == [] }` @@ -1246,7 +1254,7 @@ query:1 | Redo data.test = _ func TestPrettyTraceWithUnifyOps(t *testing.T) { module := `package test - p[x] { + p contains x if { x = 1 }` @@ -1303,7 +1311,6 @@ func removeUnifyOps(trace []*Event) (result []*Event) { func TestPrettyTraceWithLocalVars(t *testing.T) { { module := `package test -import rego.v1 p if { x := 1 @@ -1388,7 +1395,6 @@ Redo data.test = _ {_: {"p": true}} func TestPrettyTraceExprVars(t *testing.T) { { module := `package test -import rego.v1 p if { x := 1