From 9d597172f3029193ccc773743192098f18855417 Mon Sep 17 00:00:00 2001 From: Justin King Date: Wed, 2 Apr 2025 07:46:54 -0700 Subject: [PATCH] Add basic conformance tests for some comprehensions v2 macros Signed-off-by: Justin King --- tests/simple/testdata/macros2.textproto | 354 ++++++++++++++++++++++++ 1 file changed, 354 insertions(+) create mode 100644 tests/simple/testdata/macros2.textproto diff --git a/tests/simple/testdata/macros2.textproto b/tests/simple/testdata/macros2.textproto new file mode 100644 index 0000000..a3f9301 --- /dev/null +++ b/tests/simple/testdata/macros2.textproto @@ -0,0 +1,354 @@ +# proto-file: ../../../proto/cel/expr/conformance/test/simple.proto +# proto-message: google.api.expr.test.v1.SimpleTestFile + +name: "macros2" +description: "Tests for CEL comprehensions v2" +section { + name: "exists" + description: "Tests for the .exists() macro, which is equivalent to joining the evaluated elements with logical-OR." + test { + name: "list_elem_all_true" + expr: "[1, 2, 3].exists(i, v, i > -1 && v > 0)" + value: { bool_value: true } + } + test { + name: "list_elem_some_true" + expr: "[1, 2, 3].exists(i, v, i == 1 && v == 2)" + value: { bool_value: true } + } + test { + name: "list_elem_none_true" + expr: "[1, 2, 3].exists(i, v, i > 2 && v > 3)" + value: { bool_value: false } + } + test { + name: "list_elem_type_shortcircuit" + expr: "[1, 'foo', 3].exists(i, v, i == 1 && v != '1')" + value: { bool_value: true } + } + test { + name: "list_elem_type_exhaustive" + expr: "[1, 'foo', 3].exists(i, v, i == 3 || v == '10')" + value: { bool_value: false } + } + test { + name: "list_elem_exists_error" + expr: "[1, 2, 3].exists(i, v, v / i == 17)" + eval_error: { + errors: { message: "divide by zero" } + } + } + test { + name: "list_empty" + expr: "[].exists(i, v, i == 0 || v == 2)" + value: { bool_value: false } + } + test { + name: "map_key" + expr: "{'key1':1, 'key2':2}.exists(k, v, k == 'key2' && v == 2)" + value: { bool_value: true } + } + test { + name: "not_map_key" + expr: "!{'key1':1, 'key2':2}.exists(k, v, k == 'key3' || v == 3)" + value: { bool_value: true } + } + test { + name: "map_key_type_shortcircuit" + expr: "{'key':1, 1:21}.exists(k, v, k != 2 && v != 22)" + value: { bool_value: true } + } + test { + name: "map_key_type_exhaustive" + expr: "!{'key':1, 1:42}.exists(k, v, k == 2 && v == 43)" + value: { bool_value: true } + } +} +section { + name: "all" + description: "Tests for the .all() macro, which is equivalent to joining the evaluated elements with logical-AND." + test { + name: "list_elem_all_true" + expr: "[1, 2, 3].all(i, v, i > -1 && v > 0)" + value: { bool_value: true } + } + test { + name: "list_elem_some_true" + expr: "[1, 2, 3].all(i, v, i == 1 && v == 2)" + value: { bool_value: false } + } + test { + name: "list_elem_none_true" + expr: "[1, 2, 3].all(i, v, i == 3 || v == 4)" + value: { bool_value: false } + } + test { + name: "list_elem_type_shortcircuit" + expr: "[1, 'foo', 3].all(i, v, i == 0 || v == 1)" + value: { bool_value: false } + } + test { + name: "list_elem_type_exhaustive" + expr: "[0, 'foo', 3].all(i, v, v % 2 == i)" + value: { bool_value: false } + } + test { + name: "list_elem_type_error_exhaustive" + expr: "[0, 'foo', 5].all(i, v, v % 3 == i)" + eval_error: { + errors: { message: "no_such_overload" } + } + } + test { + name: "list_elem_error_shortcircuit" + expr: "[1, 2, 3].all(i, v, 6 / (2 - v) == i)" + value: { bool_value: false } + } + test { + name: "list_elem_error_exhaustive" + expr: "[1, 2, 3].all(i, v, v / i != 17)" + eval_error: { + errors: { message: "divide by zero" } + } + } + test { + name: "list_empty" + expr: "[].all(i, v, i > -1 || v > 0)" + value: { bool_value: true } + } + test { + name: "map_key" + expr: "{'key1':1, 'key2':2}.all(k, v, k == 'key2' && v == 2)" + value: { bool_value: false } + } +} +section { + name: "existsOne" + description: "Tests for existsOne() macro. An expression 'L.existsOne(I, E)' is equivalent to 'size(L.filter(I, E)) == 1'." + test { + name: "list_empty" + expr: "[].existsOne(i, v, i == 3 || v == 7)" + value: { bool_value: false } + } + test { + name: "list_one_true" + expr: "[7].existsOne(i, v, i == 0 && v == 7)" + value: { bool_value: true } + } + test { + name: "list_one_false" + expr: "[8].existsOne(i, v, i == 0 && v == 7)" + value: { bool_value: false } + } + test { + name: "list_none" + expr: "[1, 2, 3].existsOne(i, v, i > 2 || v > 3)" + value: { bool_value: false } + } + test { + name: "list_one" + expr: "[5, 7, 8].existsOne(i, v, v % 5 == i)" + value: { bool_value: true } + } + test { + name: "list_many" + expr: "[0, 1, 2, 3, 4].existsOne(i, v, v % 2 == i)" + value: { bool_value: false } + } + test { + name: "list_all" + expr: "['foal', 'foo', 'four'].existsOne(i, v, i > -1 && v.startsWith('fo'))" + value: { bool_value: false } + } + test { + name: "list_no_shortcircuit" + expr: "[3, 2, 1, 0].existsOne(i, v, v / i > 1)" + eval_error { + errors: { message: "divide by zero" } + } + } + test { + name: "map_one" + expr: "{6: 'six', 7: 'seven', 8: 'eight'}.existsOne(k, v, k % 5 == 2 && v == 'seven')" + value: { bool_value: true } + } +} +section { + name: "transformList" + description: "Tests for transformList() macro." + test { + name: "empty" + expr: "[].transformList(i, v, i / v)" + value: { list_value: {} } + } + test { + name: "empty_filter" + expr: "[].transformList(i, v, i > v, i / v)" + value: { list_value: {} } + } + test { + name: "one" + expr: "[3].transformList(i, v, v * v + i)" + value: { list_value { + values: { int64_value: 9 } + } + } + } + test { + name: "one_filter" + expr: "[3].transformList(i, v, i == 0 && v == 3, v * v + i)" + value: { list_value { + values: { int64_value: 9 } + } + } + } + test { + name: "many" + expr: "[2, 4, 6].transformList(i, v, v / 2 + i)" + value: { list_value { + values: { int64_value: 1 } + values: { int64_value: 3 } + values: { int64_value: 5 } + } + } + } + test { + name: "many_filter" + expr: "[2, 4, 6].transformList(i, v, i != 1 && v != 4, v / 2 + i)" + value: { list_value { + values: { int64_value: 1 } + values: { int64_value: 5 } + } + } + } + test { + name: "error" + expr: "[2, 1, 0].transformList(i, v, v / i)" + eval_error { + errors: { message: "divide by zero" } + } + } + test { + name: "error_filter" + expr: "[2, 1, 0].transformList(i, v, v / i > 0, v)" + eval_error { + errors: { message: "divide by zero" } + } + } +} +section { + name: "transformMap" + description: "Tests for transformMap() macro." + test { + name: "empty" + expr: "{}.transformMap(k, v, k + v)" + value: { map_value: {} } + } + test { + name: "empty_filter" + expr: "{}.transformMap(k, v, k == 'foo' && v == 'bar', k + v)" + value: { map_value: {} } + } + test { + name: "one" + expr: "{'foo': 'bar'}.transformMap(k, v, k + v)" + value: { + map_value: { + entries: { + key: { + string_value: "foo" + } + value: { + string_value: "foobar" + } + } + } + } + } + test { + name: "one_filter" + expr: "{'foo': 'bar'}.transformMap(k, v, k == 'foo' && v == 'bar', k + v)" + value: { + map_value: { + entries: { + key: { + string_value: "foo" + } + value: { + string_value: "foobar" + } + } + } + } + } + test { + name: "many" + expr: "{'foo': 'bar', 'baz': 'bux', 'hello': 'world'}.transformMap(k, v, k + v)" + value: { + map_value: { + entries: { + key: { + string_value: "foo" + } + value: { + string_value: "foobar" + } + } + entries: { + key: { + string_value: "baz" + } + value: { + string_value: "bazbux" + } + } + entries: { + key: { + string_value: "hello" + } + value: { + string_value: "helloworld" + } + } + } + } + } + test { + name: "many_filter" + expr: "{'foo': 'bar', 'baz': 'bux', 'hello': 'world'}.transformMap(k, v, k != 'baz' && v != 'bux', k + v)" + value: { + map_value: { + entries: { + key: { + string_value: "foo" + } + value: { + string_value: "foobar" + } + } + entries: { + key: { + string_value: "hello" + } + value: { + string_value: "helloworld" + } + } + } + } + } + test { + name: "error" + expr: "{'foo': 2, 'bar': 1, 'baz': 0}.transformMap(k, v, 4 / v)" + eval_error { + errors: { message: "divide by zero" } + } + } + test { + name: "error_filter" + expr: "{'foo': 2, 'bar': 1, 'baz': 0}.transformMap(k, v, k == 'baz' && 4 / v == 0, v)" + eval_error { + errors: { message: "divide by zero" } + } + } +} \ No newline at end of file