From 55cd8c398b2dcdafdd618564de4d1828f116281b Mon Sep 17 00:00:00 2001 From: Justin King Date: Tue, 22 Oct 2024 09:47:38 -0700 Subject: [PATCH] Add logical operator short circuiting tests for list and map accesses (#404) Signed-off-by: Justin King --- tests/simple/testdata/basic.textproto | 3 + tests/simple/testdata/bindings_ext.textproto | 3 + tests/simple/testdata/block_ext.textproto | 3 + tests/simple/testdata/comparisons.textproto | 3 + tests/simple/testdata/conversions.textproto | 3 + tests/simple/testdata/dynamic.textproto | 3 + tests/simple/testdata/encoders_ext.textproto | 3 + tests/simple/testdata/enums.textproto | 3 + tests/simple/testdata/fields.textproto | 178 +++++++++++++++++++ tests/simple/testdata/fp_math.textproto | 3 + tests/simple/testdata/integer_math.textproto | 3 + tests/simple/testdata/lists.textproto | 60 ++++++- tests/simple/testdata/logic.textproto | 3 + tests/simple/testdata/macros.textproto | 3 + tests/simple/testdata/math_ext.textproto | 3 + tests/simple/testdata/namespace.textproto | 3 + tests/simple/testdata/optionals.textproto | 3 + tests/simple/testdata/parse.textproto | 3 + tests/simple/testdata/plumbing.textproto | 3 + tests/simple/testdata/proto2.textproto | 3 + tests/simple/testdata/proto2_ext.textproto | 3 + tests/simple/testdata/proto3.textproto | 3 + tests/simple/testdata/string.textproto | 3 + tests/simple/testdata/string_ext.textproto | 3 + tests/simple/testdata/timestamps.textproto | 3 + tests/simple/testdata/unknowns.textproto | 3 + tests/simple/testdata/wrappers.textproto | 3 + 27 files changed, 312 insertions(+), 1 deletion(-) diff --git a/tests/simple/testdata/basic.textproto b/tests/simple/testdata/basic.textproto index 4697b6ef..169f5c3e 100644 --- a/tests/simple/testdata/basic.textproto +++ b/tests/simple/testdata/basic.textproto @@ -1,3 +1,6 @@ +# proto-file: ../../../proto/test/v1/simple.proto +# proto-message: google.api.expr.test.v1.SimpleTestFile + name: "basic" description: "Basic conformance tests that all implementations should pass." section { diff --git a/tests/simple/testdata/bindings_ext.textproto b/tests/simple/testdata/bindings_ext.textproto index 1e01b291..5617f2ff 100644 --- a/tests/simple/testdata/bindings_ext.textproto +++ b/tests/simple/testdata/bindings_ext.textproto @@ -1,3 +1,6 @@ +# proto-file: ../../../proto/test/v1/simple.proto +# proto-message: google.api.expr.test.v1.SimpleTestFile + name: "bindings_ext" description: "Tests for the bindings extension library." section: { diff --git a/tests/simple/testdata/block_ext.textproto b/tests/simple/testdata/block_ext.textproto index baa7b804..0c7f9383 100644 --- a/tests/simple/testdata/block_ext.textproto +++ b/tests/simple/testdata/block_ext.textproto @@ -1,3 +1,6 @@ +# proto-file: ../../../proto/test/v1/simple.proto +# proto-message: google.api.expr.test.v1.SimpleTestFile + # This conformance test relies on the test-only macros cel.block, cel.index, # cel.iterVar, and cel.accuVar. These test-only macros allow excercising # cel.block without the optimizers being present. diff --git a/tests/simple/testdata/comparisons.textproto b/tests/simple/testdata/comparisons.textproto index 7bae66da..919cd245 100644 --- a/tests/simple/testdata/comparisons.textproto +++ b/tests/simple/testdata/comparisons.textproto @@ -1,3 +1,6 @@ +# proto-file: ../../../proto/test/v1/simple.proto +# proto-message: google.api.expr.test.v1.SimpleTestFile + name: "comparisons" description: "Tests for boolean-valued functions and operators." section { diff --git a/tests/simple/testdata/conversions.textproto b/tests/simple/testdata/conversions.textproto index ed8f408a..1f77c678 100644 --- a/tests/simple/testdata/conversions.textproto +++ b/tests/simple/testdata/conversions.textproto @@ -1,3 +1,6 @@ +# proto-file: ../../../proto/test/v1/simple.proto +# proto-message: google.api.expr.test.v1.SimpleTestFile + name: "conversions" description: "Tests for type conversions." section { diff --git a/tests/simple/testdata/dynamic.textproto b/tests/simple/testdata/dynamic.textproto index 532a7be9..636043fc 100644 --- a/tests/simple/testdata/dynamic.textproto +++ b/tests/simple/testdata/dynamic.textproto @@ -1,3 +1,6 @@ +# proto-file: ../../../proto/test/v1/simple.proto +# proto-message: google.api.expr.test.v1.SimpleTestFile + name: "dynamic" description: "Tests for 'dynamic' proto behavior, including JSON, wrapper, and Any messages." section { diff --git a/tests/simple/testdata/encoders_ext.textproto b/tests/simple/testdata/encoders_ext.textproto index f4752406..04040ac2 100644 --- a/tests/simple/testdata/encoders_ext.textproto +++ b/tests/simple/testdata/encoders_ext.textproto @@ -1,3 +1,6 @@ +# proto-file: ../../../proto/test/v1/simple.proto +# proto-message: google.api.expr.test.v1.SimpleTestFile + name: "encoders_ext" description: "Tests for the encoders extension library." section: { diff --git a/tests/simple/testdata/enums.textproto b/tests/simple/testdata/enums.textproto index 8c316678..2b257632 100644 --- a/tests/simple/testdata/enums.textproto +++ b/tests/simple/testdata/enums.textproto @@ -1,3 +1,6 @@ +# proto-file: ../../../proto/test/v1/simple.proto +# proto-message: google.api.expr.test.v1.SimpleTestFile + name: "enums" description: "Tests for enum types." section { diff --git a/tests/simple/testdata/fields.textproto b/tests/simple/testdata/fields.textproto index 963827ba..a3946681 100644 --- a/tests/simple/testdata/fields.textproto +++ b/tests/simple/testdata/fields.textproto @@ -1,3 +1,6 @@ +# proto-file: ../../../proto/test/v1/simple.proto +# proto-message: google.api.expr.test.v1.SimpleTestFile + name: "fields" description: "Tests for field access in maps." section { @@ -86,6 +89,61 @@ section { errors: { message: "no such key" } } } + test { + name: "map_no_such_key_or_false" + expr: "dyn({0:1,2:2,5:3}[1]) || false" + eval_error: { + errors: { message: "no such key" } + } + } + test { + name: "map_no_such_key_or_true" + expr: "dyn({0:1,2:2,5:3}[1]) || true" + value: { bool_value: true } + } + test { + name: "map_no_such_key_and_false" + expr: "dyn({0:1,2:2,5:3}[1]) && false" + value: { bool_value: false } + } + test { + name: "map_no_such_key_and_true" + expr: "dyn({0:1,2:2,5:3}[1]) && true" + eval_error: { + errors: { message: "no such key" } + } + } + test { + name: "map_bad_key_type" + expr: "{0:1,2:2,5:3}[dyn(b'')]" + eval_error: { + errors: { message: "no such key" } + } + } + test { + name: "map_bad_key_type_or_false" + expr: "dyn({0:1,2:2,5:3}[dyn(b'')]) || false" + eval_error: { + errors: { message: "no such key" } + } + } + test { + name: "map_bad_key_type_or_true" + expr: "dyn({0:1,2:2,5:3}[dyn(b'')]) || true" + value: { bool_value: true } + } + test { + name: "map_bad_key_type_and_false" + expr: "dyn({0:1,2:2,5:3}[dyn(b'')]) && false" + value: { bool_value: false } + } + test { + name: "map_bad_key_type_and_true" + expr: "dyn({0:1,2:2,5:3}[dyn(b'')]) && true" + eval_error: { + errors: { message: "no such key" } + } + } test { name: "map_field_select_no_such_key" expr: "x.name" @@ -117,6 +175,126 @@ section { errors: { message:"no such key: 'name'" } } } + test { + name: "map_field_select_no_such_key_or_false" + expr: "dyn(x.name) || false" + type_env: { + name: "x", + ident: { + type: { + map_type: { + key_type: {primitive: STRING} + value_type: {primitive: STRING} + } + } + } + } + bindings: { + key: "x", + value: { + value: { + map_value: { + entries { + key: { string_value: "holiday" } + value: { string_value: "field" } + } + } + } + } + } + eval_error: { + errors: { message:"no such key: 'name'" } + } + } + test { + name: "map_field_select_no_such_key_or_true" + expr: "dyn(x.name) || true" + type_env: { + name: "x", + ident: { + type: { + map_type: { + key_type: {primitive: STRING} + value_type: {primitive: STRING} + } + } + } + } + bindings: { + key: "x", + value: { + value: { + map_value: { + entries { + key: { string_value: "holiday" } + value: { string_value: "field" } + } + } + } + } + } + value: { bool_value: true } + } + test { + name: "map_field_select_no_such_key_and_false" + expr: "dyn(x.name) && false" + type_env: { + name: "x", + ident: { + type: { + map_type: { + key_type: {primitive: STRING} + value_type: {primitive: STRING} + } + } + } + } + bindings: { + key: "x", + value: { + value: { + map_value: { + entries { + key: { string_value: "holiday" } + value: { string_value: "field" } + } + } + } + } + } + value: { bool_value: false } + } + test { + name: "map_field_select_no_such_key_and_true" + expr: "dyn(x.name) && true" + type_env: { + name: "x", + ident: { + type: { + map_type: { + key_type: {primitive: STRING} + value_type: {primitive: STRING} + } + } + } + } + bindings: { + key: "x", + value: { + value: { + map_value: { + entries { + key: { string_value: "holiday" } + value: { string_value: "field" } + } + } + } + } + } + eval_error: { + errors: { message:"no such key: 'name'" } + } + } test { name: "map_value_null" expr: '{true:null}[true]' diff --git a/tests/simple/testdata/fp_math.textproto b/tests/simple/testdata/fp_math.textproto index 38a3eae2..4ca8d766 100644 --- a/tests/simple/testdata/fp_math.textproto +++ b/tests/simple/testdata/fp_math.textproto @@ -1,3 +1,6 @@ +# proto-file: ../../../proto/test/v1/simple.proto +# proto-message: google.api.expr.test.v1.SimpleTestFile + name: "fp_math" description: "Tests for floating-point math." section { diff --git a/tests/simple/testdata/integer_math.textproto b/tests/simple/testdata/integer_math.textproto index 0d15330c..82a35b79 100644 --- a/tests/simple/testdata/integer_math.textproto +++ b/tests/simple/testdata/integer_math.textproto @@ -1,3 +1,6 @@ +# proto-file: ../../../proto/test/v1/simple.proto +# proto-message: google.api.expr.test.v1.SimpleTestFile + name: "integer_math" description: "Tests for int and uint math." section { diff --git a/tests/simple/testdata/lists.textproto b/tests/simple/testdata/lists.textproto index 5b1f4f4c..c77237a5 100644 --- a/tests/simple/testdata/lists.textproto +++ b/tests/simple/testdata/lists.textproto @@ -1,3 +1,6 @@ +# proto-file: ../../../proto/test/v1/simple.proto +# proto-message: google.api.expr.test.v1.SimpleTestFile + name: "lists" description: "Tests for list operations." section { @@ -90,12 +93,67 @@ section { value: { string_value: "Ringo" } } test { - name: "range" + name: "index_out_of_bounds" expr: "[1, 2, 3][3]" eval_error { errors { message: "invalid_argument" } } } + test { + name: "index_out_of_bounds_or_false" + expr: "dyn([1, 2, 3][3]) || false" + eval_error { + errors { message: "invalid_argument" } + } + } + test { + name: "index_out_of_bounds_or_true" + expr: "dyn([1, 2, 3][3]) || true" + value: { bool_value: true } + } + test { + name: "index_out_of_bounds_and_false" + expr: "dyn([1, 2, 3][3]) && false" + value: { bool_value: false } + } + test { + name: "index_out_of_bounds_and_true" + expr: "dyn([1, 2, 3][3]) && true" + eval_error { + errors { message: "invalid_argument" } + } + } + test { + name: "bad_index_type" + expr: "[1, 2, 3][dyn('')]" + eval_error { + errors { message: "invalid_argument" } + } + } + test { + name: "bad_index_type_or_false" + expr: "dyn([1, 2, 3][dyn('')]) || false" + eval_error { + errors { message: "invalid_argument" } + } + } + test { + name: "bad_index_type_or_true" + expr: "dyn([1, 2, 3][dyn('')]) || true" + value: { bool_value: true } + } + test { + name: "bad_index_type_and_false" + expr: "dyn([1, 2, 3][dyn('')]) && false" + value: { bool_value: false } + } + test { + name: "bad_index_type_and_true" + expr: "dyn([1, 2, 3][dyn('')]) && true" + eval_error { + errors { message: "invalid_argument" } + } + } } section { name: "in" diff --git a/tests/simple/testdata/logic.textproto b/tests/simple/testdata/logic.textproto index 42d9f7ce..c68ad0aa 100644 --- a/tests/simple/testdata/logic.textproto +++ b/tests/simple/testdata/logic.textproto @@ -1,3 +1,6 @@ +# proto-file: ../../../proto/test/v1/simple.proto +# proto-message: google.api.expr.test.v1.SimpleTestFile + name: "logic" description: "Tests for logical special operators." section { diff --git a/tests/simple/testdata/macros.textproto b/tests/simple/testdata/macros.textproto index cd2e3f8a..c5176c93 100644 --- a/tests/simple/testdata/macros.textproto +++ b/tests/simple/testdata/macros.textproto @@ -1,3 +1,6 @@ +# proto-file: ../../../proto/test/v1/simple.proto +# proto-message: google.api.expr.test.v1.SimpleTestFile + name: "macros" description: "Tests for CEL macros." section { diff --git a/tests/simple/testdata/math_ext.textproto b/tests/simple/testdata/math_ext.textproto index 8584d926..a1efaad0 100644 --- a/tests/simple/testdata/math_ext.textproto +++ b/tests/simple/testdata/math_ext.textproto @@ -1,3 +1,6 @@ +# proto-file: ../../../proto/test/v1/simple.proto +# proto-message: google.api.expr.test.v1.SimpleTestFile + name: "math_ext" description: "Tests for the math extension library." section: { diff --git a/tests/simple/testdata/namespace.textproto b/tests/simple/testdata/namespace.textproto index df439c6b..28afab75 100644 --- a/tests/simple/testdata/namespace.textproto +++ b/tests/simple/testdata/namespace.textproto @@ -1,3 +1,6 @@ +# proto-file: ../../../proto/test/v1/simple.proto +# proto-message: google.api.expr.test.v1.SimpleTestFile + name: "namespace" description: "Uses of qualified identifiers and namespaces." section { diff --git a/tests/simple/testdata/optionals.textproto b/tests/simple/testdata/optionals.textproto index 5e532d74..3c79e39d 100644 --- a/tests/simple/testdata/optionals.textproto +++ b/tests/simple/testdata/optionals.textproto @@ -1,3 +1,6 @@ +# proto-file: ../../../proto/test/v1/simple.proto +# proto-message: google.api.expr.test.v1.SimpleTestFile + name: "optionals" description: "Tests for optionals." section: { diff --git a/tests/simple/testdata/parse.textproto b/tests/simple/testdata/parse.textproto index f5749f24..f45d4c5a 100644 --- a/tests/simple/testdata/parse.textproto +++ b/tests/simple/testdata/parse.textproto @@ -1,3 +1,6 @@ +# proto-file: ../../../proto/test/v1/simple.proto +# proto-message: google.api.expr.test.v1.SimpleTestFile + name: "parse" description: "End-to-end parsing tests." section { diff --git a/tests/simple/testdata/plumbing.textproto b/tests/simple/testdata/plumbing.textproto index 2f58b3ce..9e26881f 100644 --- a/tests/simple/testdata/plumbing.textproto +++ b/tests/simple/testdata/plumbing.textproto @@ -1,3 +1,6 @@ +# proto-file: ../../../proto/test/v1/simple.proto +# proto-message: google.api.expr.test.v1.SimpleTestFile + name: "plumbing" description: "Check that the ConformanceService server can accept all arguments and return all responses." section { diff --git a/tests/simple/testdata/proto2.textproto b/tests/simple/testdata/proto2.textproto index 49f1f73e..ea5fb7a2 100644 --- a/tests/simple/testdata/proto2.textproto +++ b/tests/simple/testdata/proto2.textproto @@ -1,3 +1,6 @@ +# proto-file: ../../../proto/test/v1/simple.proto +# proto-message: google.api.expr.test.v1.SimpleTestFile + name: "proto2" description: "Protocol buffer version 2 tests. See notes for the available set of protos for tests." diff --git a/tests/simple/testdata/proto2_ext.textproto b/tests/simple/testdata/proto2_ext.textproto index 30ebd539..1a8c0d1c 100644 --- a/tests/simple/testdata/proto2_ext.textproto +++ b/tests/simple/testdata/proto2_ext.textproto @@ -1,3 +1,6 @@ +# proto-file: ../../../proto/test/v1/simple.proto +# proto-message: google.api.expr.test.v1.SimpleTestFile + name: "proto2_ext" description: "Tests for the proto extension library." section: { diff --git a/tests/simple/testdata/proto3.textproto b/tests/simple/testdata/proto3.textproto index 2d1fcbf0..45bff34e 100644 --- a/tests/simple/testdata/proto3.textproto +++ b/tests/simple/testdata/proto3.textproto @@ -1,3 +1,6 @@ +# proto-file: ../../../proto/test/v1/simple.proto +# proto-message: google.api.expr.test.v1.SimpleTestFile + name: "proto3" description: "Protocol buffer version 3 tests. See notes for the available set of protos for tests." diff --git a/tests/simple/testdata/string.textproto b/tests/simple/testdata/string.textproto index 5458080e..89218cfd 100644 --- a/tests/simple/testdata/string.textproto +++ b/tests/simple/testdata/string.textproto @@ -1,3 +1,6 @@ +# proto-file: ../../../proto/test/v1/simple.proto +# proto-message: google.api.expr.test.v1.SimpleTestFile + name: "string" description: "Tests for string and bytes operations." section { diff --git a/tests/simple/testdata/string_ext.textproto b/tests/simple/testdata/string_ext.textproto index a87c950b..dbc7515b 100644 --- a/tests/simple/testdata/string_ext.textproto +++ b/tests/simple/testdata/string_ext.textproto @@ -1,3 +1,6 @@ +# proto-file: ../../../proto/test/v1/simple.proto +# proto-message: google.api.expr.test.v1.SimpleTestFile + name: "string_ext" description: "Tests for the strings extension library." section: { diff --git a/tests/simple/testdata/timestamps.textproto b/tests/simple/testdata/timestamps.textproto index 3fc0af67..0ae59f5b 100644 --- a/tests/simple/testdata/timestamps.textproto +++ b/tests/simple/testdata/timestamps.textproto @@ -1,3 +1,6 @@ +# proto-file: ../../../proto/test/v1/simple.proto +# proto-message: google.api.expr.test.v1.SimpleTestFile + name: "timestamps" description: "Timestamp and duration tests." section { diff --git a/tests/simple/testdata/unknowns.textproto b/tests/simple/testdata/unknowns.textproto index 4b175709..9411f3df 100644 --- a/tests/simple/testdata/unknowns.textproto +++ b/tests/simple/testdata/unknowns.textproto @@ -1,2 +1,5 @@ +# proto-file: ../../../proto/test/v1/simple.proto +# proto-message: google.api.expr.test.v1.SimpleTestFile + name: "unknowns" description: "Tests for evaluation with unknown inputs." diff --git a/tests/simple/testdata/wrappers.textproto b/tests/simple/testdata/wrappers.textproto index 21844421..17f3387d 100644 --- a/tests/simple/testdata/wrappers.textproto +++ b/tests/simple/testdata/wrappers.textproto @@ -1,3 +1,6 @@ +# proto-file: ../../../proto/test/v1/simple.proto +# proto-message: google.api.expr.test.v1.SimpleTestFile + name: "wrappers" description: "Conformance tests related to wrapper types."