diff --git a/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerBaselineTest.java b/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerBaselineTest.java index ca3e0f77a..2cd093ab1 100644 --- a/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerBaselineTest.java +++ b/optimizer/src/test/java/dev/cel/optimizer/optimizers/SubexpressionOptimizerBaselineTest.java @@ -465,6 +465,7 @@ private enum CseTestCase { MACRO_SHADOWED_VARIABLE("[x - 1 > 3 ? x - 1 : 5].exists(x, x - 1 > 3) || x - 1 > 3"), MACRO_SHADOWED_VARIABLE_2("[\"foo\", \"bar\"].map(x, [x + x, x + x]).map(x, [x + x, x + x])"), PRESENCE_TEST("has({'a': true}.a) && {'a':true}['a']"), + PRESENCE_TEST_2("has({'a': true}.a) && has({'a': true}.a)"), PRESENCE_TEST_WITH_TERNARY( "(has(msg.oneof_type.payload) ? msg.oneof_type.payload.single_int64 : 0) == 10"), PRESENCE_TEST_WITH_TERNARY_2( diff --git a/optimizer/src/test/resources/constfold_before_subexpression_unparsed.baseline b/optimizer/src/test/resources/constfold_before_subexpression_unparsed.baseline index 2ebaf7ac2..849e8d5ca 100644 --- a/optimizer/src/test/resources/constfold_before_subexpression_unparsed.baseline +++ b/optimizer/src/test/resources/constfold_before_subexpression_unparsed.baseline @@ -430,6 +430,22 @@ Result: true [BLOCK_RECURSION_DEPTH_8]: true [BLOCK_RECURSION_DEPTH_9]: true +Test case: PRESENCE_TEST_2 +Source: has({'a': true}.a) && has({'a': true}.a) +=====> +Result: true +[CASCADED_BINDS]: true +[BLOCK_COMMON_SUBEXPR_ONLY]: true +[BLOCK_RECURSION_DEPTH_1]: true +[BLOCK_RECURSION_DEPTH_2]: true +[BLOCK_RECURSION_DEPTH_3]: true +[BLOCK_RECURSION_DEPTH_4]: true +[BLOCK_RECURSION_DEPTH_5]: true +[BLOCK_RECURSION_DEPTH_6]: true +[BLOCK_RECURSION_DEPTH_7]: true +[BLOCK_RECURSION_DEPTH_8]: true +[BLOCK_RECURSION_DEPTH_9]: true + Test case: PRESENCE_TEST_WITH_TERNARY Source: (has(msg.oneof_type.payload) ? msg.oneof_type.payload.single_int64 : 0) == 10 =====> diff --git a/optimizer/src/test/resources/subexpression_ast_block_common_subexpr_only.baseline b/optimizer/src/test/resources/subexpression_ast_block_common_subexpr_only.baseline index 960821d8a..d3026dd15 100644 --- a/optimizer/src/test/resources/subexpression_ast_block_common_subexpr_only.baseline +++ b/optimizer/src/test/resources/subexpression_ast_block_common_subexpr_only.baseline @@ -2228,6 +2228,43 @@ CALL [1] { } } } +Test case: PRESENCE_TEST_2 +Source: has({'a': true}.a) && has({'a': true}.a) +=====> +CALL [1] { + function: cel.@block + args: { + CREATE_LIST [2] { + elements: { + CREATE_MAP [3] { + MAP_ENTRY [4] { + key: { + CONSTANT [5] { value: "a" } + } + value: { + CONSTANT [6] { value: true } + } + } + } + } + } + CALL [7] { + function: _&&_ + args: { + SELECT [8] { + IDENT [9] { + name: @index0 + }.a~presence_test + } + SELECT [10] { + IDENT [11] { + name: @index0 + }.a~presence_test + } + } + } + } +} Test case: PRESENCE_TEST_WITH_TERNARY Source: (has(msg.oneof_type.payload) ? msg.oneof_type.payload.single_int64 : 0) == 10 =====> diff --git a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_1.baseline b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_1.baseline index 3b4233150..4a37c61ff 100644 --- a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_1.baseline +++ b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_1.baseline @@ -2846,6 +2846,43 @@ CALL [1] { } } } +Test case: PRESENCE_TEST_2 +Source: has({'a': true}.a) && has({'a': true}.a) +=====> +CALL [1] { + function: cel.@block + args: { + CREATE_LIST [2] { + elements: { + CREATE_MAP [3] { + MAP_ENTRY [4] { + key: { + CONSTANT [5] { value: "a" } + } + value: { + CONSTANT [6] { value: true } + } + } + } + } + } + CALL [7] { + function: _&&_ + args: { + SELECT [8] { + IDENT [9] { + name: @index0 + }.a~presence_test + } + SELECT [10] { + IDENT [11] { + name: @index0 + }.a~presence_test + } + } + } + } +} Test case: PRESENCE_TEST_WITH_TERNARY Source: (has(msg.oneof_type.payload) ? msg.oneof_type.payload.single_int64 : 0) == 10 =====> diff --git a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_2.baseline b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_2.baseline index e294e828b..47c8e9e13 100644 --- a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_2.baseline +++ b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_2.baseline @@ -2629,6 +2629,43 @@ CALL [1] { } } } +Test case: PRESENCE_TEST_2 +Source: has({'a': true}.a) && has({'a': true}.a) +=====> +CALL [1] { + function: cel.@block + args: { + CREATE_LIST [2] { + elements: { + CREATE_MAP [3] { + MAP_ENTRY [4] { + key: { + CONSTANT [5] { value: "a" } + } + value: { + CONSTANT [6] { value: true } + } + } + } + } + } + CALL [7] { + function: _&&_ + args: { + SELECT [8] { + IDENT [9] { + name: @index0 + }.a~presence_test + } + SELECT [10] { + IDENT [11] { + name: @index0 + }.a~presence_test + } + } + } + } +} Test case: PRESENCE_TEST_WITH_TERNARY Source: (has(msg.oneof_type.payload) ? msg.oneof_type.payload.single_int64 : 0) == 10 =====> diff --git a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_3.baseline b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_3.baseline index 6e9a08799..ae572aed0 100644 --- a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_3.baseline +++ b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_3.baseline @@ -2384,6 +2384,43 @@ CALL [1] { } } } +Test case: PRESENCE_TEST_2 +Source: has({'a': true}.a) && has({'a': true}.a) +=====> +CALL [1] { + function: cel.@block + args: { + CREATE_LIST [2] { + elements: { + CREATE_MAP [3] { + MAP_ENTRY [4] { + key: { + CONSTANT [5] { value: "a" } + } + value: { + CONSTANT [6] { value: true } + } + } + } + } + } + CALL [7] { + function: _&&_ + args: { + SELECT [8] { + IDENT [9] { + name: @index0 + }.a~presence_test + } + SELECT [10] { + IDENT [11] { + name: @index0 + }.a~presence_test + } + } + } + } +} Test case: PRESENCE_TEST_WITH_TERNARY Source: (has(msg.oneof_type.payload) ? msg.oneof_type.payload.single_int64 : 0) == 10 =====> diff --git a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_4.baseline b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_4.baseline index 9b7787c5a..d7df4463a 100644 --- a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_4.baseline +++ b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_4.baseline @@ -2321,6 +2321,43 @@ CALL [1] { } } } +Test case: PRESENCE_TEST_2 +Source: has({'a': true}.a) && has({'a': true}.a) +=====> +CALL [1] { + function: cel.@block + args: { + CREATE_LIST [2] { + elements: { + CREATE_MAP [3] { + MAP_ENTRY [4] { + key: { + CONSTANT [5] { value: "a" } + } + value: { + CONSTANT [6] { value: true } + } + } + } + } + } + CALL [7] { + function: _&&_ + args: { + SELECT [8] { + IDENT [9] { + name: @index0 + }.a~presence_test + } + SELECT [10] { + IDENT [11] { + name: @index0 + }.a~presence_test + } + } + } + } +} Test case: PRESENCE_TEST_WITH_TERNARY Source: (has(msg.oneof_type.payload) ? msg.oneof_type.payload.single_int64 : 0) == 10 =====> diff --git a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_5.baseline b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_5.baseline index 470c6a612..ce5eafd5f 100644 --- a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_5.baseline +++ b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_5.baseline @@ -2291,6 +2291,43 @@ CALL [1] { } } } +Test case: PRESENCE_TEST_2 +Source: has({'a': true}.a) && has({'a': true}.a) +=====> +CALL [1] { + function: cel.@block + args: { + CREATE_LIST [2] { + elements: { + CREATE_MAP [3] { + MAP_ENTRY [4] { + key: { + CONSTANT [5] { value: "a" } + } + value: { + CONSTANT [6] { value: true } + } + } + } + } + } + CALL [7] { + function: _&&_ + args: { + SELECT [8] { + IDENT [9] { + name: @index0 + }.a~presence_test + } + SELECT [10] { + IDENT [11] { + name: @index0 + }.a~presence_test + } + } + } + } +} Test case: PRESENCE_TEST_WITH_TERNARY Source: (has(msg.oneof_type.payload) ? msg.oneof_type.payload.single_int64 : 0) == 10 =====> diff --git a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_6.baseline b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_6.baseline index 107cf04c7..614a372a6 100644 --- a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_6.baseline +++ b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_6.baseline @@ -2285,6 +2285,43 @@ CALL [1] { } } } +Test case: PRESENCE_TEST_2 +Source: has({'a': true}.a) && has({'a': true}.a) +=====> +CALL [1] { + function: cel.@block + args: { + CREATE_LIST [2] { + elements: { + CREATE_MAP [3] { + MAP_ENTRY [4] { + key: { + CONSTANT [5] { value: "a" } + } + value: { + CONSTANT [6] { value: true } + } + } + } + } + } + CALL [7] { + function: _&&_ + args: { + SELECT [8] { + IDENT [9] { + name: @index0 + }.a~presence_test + } + SELECT [10] { + IDENT [11] { + name: @index0 + }.a~presence_test + } + } + } + } +} Test case: PRESENCE_TEST_WITH_TERNARY Source: (has(msg.oneof_type.payload) ? msg.oneof_type.payload.single_int64 : 0) == 10 =====> diff --git a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_7.baseline b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_7.baseline index 866f2c073..773c56aa2 100644 --- a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_7.baseline +++ b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_7.baseline @@ -2282,6 +2282,43 @@ CALL [1] { } } } +Test case: PRESENCE_TEST_2 +Source: has({'a': true}.a) && has({'a': true}.a) +=====> +CALL [1] { + function: cel.@block + args: { + CREATE_LIST [2] { + elements: { + CREATE_MAP [3] { + MAP_ENTRY [4] { + key: { + CONSTANT [5] { value: "a" } + } + value: { + CONSTANT [6] { value: true } + } + } + } + } + } + CALL [7] { + function: _&&_ + args: { + SELECT [8] { + IDENT [9] { + name: @index0 + }.a~presence_test + } + SELECT [10] { + IDENT [11] { + name: @index0 + }.a~presence_test + } + } + } + } +} Test case: PRESENCE_TEST_WITH_TERNARY Source: (has(msg.oneof_type.payload) ? msg.oneof_type.payload.single_int64 : 0) == 10 =====> diff --git a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_8.baseline b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_8.baseline index 7da4bdebb..1d8371442 100644 --- a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_8.baseline +++ b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_8.baseline @@ -2264,6 +2264,43 @@ CALL [1] { } } } +Test case: PRESENCE_TEST_2 +Source: has({'a': true}.a) && has({'a': true}.a) +=====> +CALL [1] { + function: cel.@block + args: { + CREATE_LIST [2] { + elements: { + CREATE_MAP [3] { + MAP_ENTRY [4] { + key: { + CONSTANT [5] { value: "a" } + } + value: { + CONSTANT [6] { value: true } + } + } + } + } + } + CALL [7] { + function: _&&_ + args: { + SELECT [8] { + IDENT [9] { + name: @index0 + }.a~presence_test + } + SELECT [10] { + IDENT [11] { + name: @index0 + }.a~presence_test + } + } + } + } +} Test case: PRESENCE_TEST_WITH_TERNARY Source: (has(msg.oneof_type.payload) ? msg.oneof_type.payload.single_int64 : 0) == 10 =====> diff --git a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_9.baseline b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_9.baseline index b20801a0f..cd73ba02a 100644 --- a/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_9.baseline +++ b/optimizer/src/test/resources/subexpression_ast_block_recursion_depth_9.baseline @@ -2252,6 +2252,43 @@ CALL [1] { } } } +Test case: PRESENCE_TEST_2 +Source: has({'a': true}.a) && has({'a': true}.a) +=====> +CALL [1] { + function: cel.@block + args: { + CREATE_LIST [2] { + elements: { + CREATE_MAP [3] { + MAP_ENTRY [4] { + key: { + CONSTANT [5] { value: "a" } + } + value: { + CONSTANT [6] { value: true } + } + } + } + } + } + CALL [7] { + function: _&&_ + args: { + SELECT [8] { + IDENT [9] { + name: @index0 + }.a~presence_test + } + SELECT [10] { + IDENT [11] { + name: @index0 + }.a~presence_test + } + } + } + } +} Test case: PRESENCE_TEST_WITH_TERNARY Source: (has(msg.oneof_type.payload) ? msg.oneof_type.payload.single_int64 : 0) == 10 =====> diff --git a/optimizer/src/test/resources/subexpression_ast_cascaded_binds.baseline b/optimizer/src/test/resources/subexpression_ast_cascaded_binds.baseline index 08e584050..78f8c433b 100644 --- a/optimizer/src/test/resources/subexpression_ast_cascaded_binds.baseline +++ b/optimizer/src/test/resources/subexpression_ast_cascaded_binds.baseline @@ -2949,6 +2949,56 @@ COMPREHENSION [1] { } } } +Test case: PRESENCE_TEST_2 +Source: has({'a': true}.a) && has({'a': true}.a) +=====> +COMPREHENSION [1] { + iter_var: #unused + iter_range: { + CREATE_LIST [2] { + elements: { + } + } + } + accu_var: @r0 + accu_init: { + CREATE_MAP [3] { + MAP_ENTRY [4] { + key: { + CONSTANT [5] { value: "a" } + } + value: { + CONSTANT [6] { value: true } + } + } + } + } + loop_condition: { + CONSTANT [7] { value: false } + } + loop_step: { + IDENT [8] { + name: @r0 + } + } + result: { + CALL [9] { + function: _&&_ + args: { + SELECT [10] { + IDENT [11] { + name: @r0 + }.a~presence_test + } + SELECT [12] { + IDENT [13] { + name: @r0 + }.a~presence_test + } + } + } + } +} Test case: PRESENCE_TEST_WITH_TERNARY Source: (has(msg.oneof_type.payload) ? msg.oneof_type.payload.single_int64 : 0) == 10 =====> diff --git a/optimizer/src/test/resources/subexpression_unparsed.baseline b/optimizer/src/test/resources/subexpression_unparsed.baseline index 83a434ac4..b38a971aa 100644 --- a/optimizer/src/test/resources/subexpression_unparsed.baseline +++ b/optimizer/src/test/resources/subexpression_unparsed.baseline @@ -430,6 +430,22 @@ Result: true [BLOCK_RECURSION_DEPTH_8]: cel.@block([{"a": true}], has(@index0.a) && @index0["a"]) [BLOCK_RECURSION_DEPTH_9]: cel.@block([{"a": true}], has(@index0.a) && @index0["a"]) +Test case: PRESENCE_TEST_2 +Source: has({'a': true}.a) && has({'a': true}.a) +=====> +Result: true +[CASCADED_BINDS]: cel.bind(@r0, {"a": true}, has(@r0.a) && has(@r0.a)) +[BLOCK_COMMON_SUBEXPR_ONLY]: cel.@block([{"a": true}], has(@index0.a) && has(@index0.a)) +[BLOCK_RECURSION_DEPTH_1]: cel.@block([{"a": true}], has(@index0.a) && has(@index0.a)) +[BLOCK_RECURSION_DEPTH_2]: cel.@block([{"a": true}], has(@index0.a) && has(@index0.a)) +[BLOCK_RECURSION_DEPTH_3]: cel.@block([{"a": true}], has(@index0.a) && has(@index0.a)) +[BLOCK_RECURSION_DEPTH_4]: cel.@block([{"a": true}], has(@index0.a) && has(@index0.a)) +[BLOCK_RECURSION_DEPTH_5]: cel.@block([{"a": true}], has(@index0.a) && has(@index0.a)) +[BLOCK_RECURSION_DEPTH_6]: cel.@block([{"a": true}], has(@index0.a) && has(@index0.a)) +[BLOCK_RECURSION_DEPTH_7]: cel.@block([{"a": true}], has(@index0.a) && has(@index0.a)) +[BLOCK_RECURSION_DEPTH_8]: cel.@block([{"a": true}], has(@index0.a) && has(@index0.a)) +[BLOCK_RECURSION_DEPTH_9]: cel.@block([{"a": true}], has(@index0.a) && has(@index0.a)) + Test case: PRESENCE_TEST_WITH_TERNARY Source: (has(msg.oneof_type.payload) ? msg.oneof_type.payload.single_int64 : 0) == 10 =====>