|
32 | 32 | import dev.cel.common.CelOverloadDecl; |
33 | 33 | import dev.cel.common.types.ListType; |
34 | 34 | import dev.cel.common.types.MapType; |
| 35 | +import dev.cel.common.types.NullableType; |
| 36 | +import dev.cel.common.types.OptionalType; |
35 | 37 | import dev.cel.common.types.SimpleType; |
36 | 38 | import dev.cel.common.types.StructTypeReference; |
37 | 39 | import dev.cel.expr.conformance.proto2.TestAllTypes.NestedMessage; |
@@ -80,6 +82,28 @@ private static Cel setupEnv(CelBuilder celBuilder) { |
80 | 82 | return celBuilder |
81 | 83 | .addVar("x", SimpleType.DYN) |
82 | 84 | .addVar("y", SimpleType.DYN) |
| 85 | + .addVar("dyn_x", SimpleType.DYN) |
| 86 | + .addVar("int_x", SimpleType.INT) |
| 87 | + .addVar("double_x", SimpleType.DOUBLE) |
| 88 | + .addVar("bool_x", SimpleType.BOOL) |
| 89 | + .addVar("string_x", SimpleType.STRING) |
| 90 | + .addVar("int_list_x", ListType.create(SimpleType.INT)) |
| 91 | + .addVar("double_list_x", ListType.create(SimpleType.DOUBLE)) |
| 92 | + .addVar("dyn_list_x", ListType.create(SimpleType.DYN)) |
| 93 | + .addVar("map_string_int_x", MapType.create(SimpleType.STRING, SimpleType.INT)) |
| 94 | + .addVar("map_string_double_x", MapType.create(SimpleType.STRING, SimpleType.DOUBLE)) |
| 95 | + .addVar("optional_int_x", OptionalType.create(SimpleType.INT)) |
| 96 | + .addVar("optional_double_x", OptionalType.create(SimpleType.DOUBLE)) |
| 97 | + .addVar("nested_list_int_x", ListType.create(ListType.create(SimpleType.INT))) |
| 98 | + .addVar("nested_list_double_x", ListType.create(ListType.create(SimpleType.DOUBLE))) |
| 99 | + .addVar( |
| 100 | + "nested_map_list_int_x", |
| 101 | + MapType.create(SimpleType.STRING, ListType.create(SimpleType.INT))) |
| 102 | + .addVar( |
| 103 | + "nested_map_list_double_x", |
| 104 | + MapType.create(SimpleType.STRING, ListType.create(SimpleType.DOUBLE))) |
| 105 | + .addVar("nullable_int_x", NullableType.create(SimpleType.INT)) |
| 106 | + .addVar("nullable_double_x", NullableType.create(SimpleType.DOUBLE)) |
83 | 107 | .addVar("bool_var", SimpleType.BOOL) |
84 | 108 | .addVar("list_var", ListType.create(SimpleType.STRING)) |
85 | 109 | .addVar("map_var", MapType.create(SimpleType.STRING, SimpleType.STRING)) |
@@ -151,7 +175,48 @@ private static Cel setupEnv(CelBuilder celBuilder) { |
151 | 175 | @TestParameters("{source: '5 in [1, 1 + 2, 1 + (2 + 3)]', expected: 'false'}") |
152 | 176 | @TestParameters("{source: '5 in [1, x, y, 5]', expected: 'true'}") |
153 | 177 | @TestParameters("{source: '!(5 in [1, x, y, 5])', expected: 'false'}") |
154 | | - @TestParameters("{source: 'x in [1, x, y, 5]', expected: 'true'}") |
| 178 | + @TestParameters("{source: 'x in [1, x, y, 5]', expected: 'x in [1, x, y, 5]'}") |
| 179 | + @TestParameters("{source: 'dyn_x in [1, 2, dyn_x]', expected: 'dyn_x in [1, 2, dyn_x]'}") |
| 180 | + @TestParameters("{source: 'int_x in [1, 2, int_x]', expected: 'true'}") |
| 181 | + @TestParameters("{source: 'bool_x in [true, false, bool_x]', expected: 'true'}") |
| 182 | + @TestParameters("{source: 'string_x in [\"a\", \"b\", string_x]', expected: 'true'}") |
| 183 | + @TestParameters( |
| 184 | + "{source: 'double_x in [1.0, 2.0, double_x]', expected: 'double_x in [1.0, 2.0, double_x]'}") |
| 185 | + @TestParameters("{source: 'int_list_x in [[1], [2], int_list_x]', expected: 'true'}") |
| 186 | + @TestParameters( |
| 187 | + "{source: 'double_list_x in [[1.0], double_list_x]', expected: 'double_list_x in [[1.0]," |
| 188 | + + " double_list_x]'}") |
| 189 | + @TestParameters( |
| 190 | + "{source: 'dyn_list_x in [[1], dyn_list_x]', expected: 'dyn_list_x in [[1], dyn_list_x]'}") |
| 191 | + @TestParameters( |
| 192 | + "{source: 'map_string_int_x in [{\"a\": 1}, map_string_int_x]', expected: 'true'}") |
| 193 | + @TestParameters( |
| 194 | + "{source: 'map_string_double_x in [{\"a\": 1.0}, map_string_double_x]', expected:" |
| 195 | + + " 'map_string_double_x in [{\"a\": 1.0}, map_string_double_x]'}") |
| 196 | + @TestParameters( |
| 197 | + "{source: 'optional_int_x in [optional.of(1), optional_int_x]', expected: 'true'}") |
| 198 | + @TestParameters( |
| 199 | + "{source: 'optional_double_x in [optional.of(1.0), optional_double_x]', expected:" |
| 200 | + + " 'optional_double_x in [optional.of(1.0), optional_double_x]'}") |
| 201 | + @TestParameters("{source: 'nullable_int_x in [1, 2, nullable_int_x]', expected: 'true'}") |
| 202 | + @TestParameters( |
| 203 | + "{source: 'nullable_double_x in [1.0, 2.0, nullable_double_x]', expected:" |
| 204 | + + " 'nullable_double_x in [1.0, 2.0, nullable_double_x]'}") |
| 205 | + @TestParameters( |
| 206 | + "{source: 'double(\"NaN\") in [double(\"NaN\"), double_x]', expected: 'NaN in" |
| 207 | + + " [NaN, double_x]'}") |
| 208 | + @TestParameters( |
| 209 | + "{source: 'nested_list_int_x in [[[1]], [[2]], nested_list_int_x]', expected: 'true'}") |
| 210 | + @TestParameters( |
| 211 | + "{source: 'nested_list_double_x in [[[1.0]], [[2.0]], nested_list_double_x]'," |
| 212 | + + " expected: 'nested_list_double_x in [[[1.0]], [[2.0]], nested_list_double_x]'}") |
| 213 | + @TestParameters( |
| 214 | + "{source: 'nested_map_list_int_x in [{\"a\": [1]}, nested_map_list_int_x]', expected:" |
| 215 | + + " 'true'}") |
| 216 | + @TestParameters( |
| 217 | + "{source: 'nested_map_list_double_x in [{\"a\": [1.0]}, nested_map_list_double_x]'," |
| 218 | + + " expected: 'nested_map_list_double_x in [{\"a\": [1.0]}," |
| 219 | + + " nested_map_list_double_x]'}") |
155 | 220 | @TestParameters("{source: 'x in [1, 1 + 2, 1 + (2 + 3)]', expected: 'x in [1, 3, 6]'}") |
156 | 221 | @TestParameters("{source: 'duration(string(7 * 24) + ''h'')', expected: 'duration(\"168h\")'}") |
157 | 222 | @TestParameters("{source: '[1, ?optional.of(3)]', expected: '[1, 3]'}") |
@@ -395,7 +460,8 @@ public void constantFold_protoMessageLiteral_success(String source, String expec |
395 | 460 | @TestParameters( |
396 | 461 | "{source: 'cel.bind(myMap, {\"foo\": \"bar\"}, myMap[?\"foo\"].optMap(x, x + \"baz\"))', " |
397 | 462 | + "expected: 'optional.of(\"barbaz\")'}") |
398 | | - @TestParameters("{source: '(1 + 2 + 3 == x) && (x in [1, 2, x])', expected: '6 == x'}") |
| 463 | + @TestParameters( |
| 464 | + "{source: '(1 + 2 + 3 == x) && (x in [1, 2, x])', expected: '6 == x && x in [1, 2, x]'}") |
399 | 465 | public void constantFold_macros_macroCallMetadataPopulated(String source, String expected) |
400 | 466 | throws Exception { |
401 | 467 | Cel cel = |
@@ -862,4 +928,20 @@ public void iterationLimitReached_throws() throws Exception { |
862 | 928 | assertThrows(CelOptimizationException.class, () -> optimizer.optimize(ast)); |
863 | 929 | assertThat(e).hasMessageThat().contains("Optimization failure: Max iteration count reached."); |
864 | 930 | } |
| 931 | + |
| 932 | + @Test |
| 933 | + public void constantFold_inOperator_withoutMacros_skipsDoubleNan() throws Exception { |
| 934 | + Cel celWithoutMacros = |
| 935 | + setupEnv(runtimeFlavor.builder()).toCelBuilder().setStandardMacros().build(); |
| 936 | + CelOptimizer optimizer = |
| 937 | + CelOptimizerFactory.standardCelOptimizerBuilder(celWithoutMacros) |
| 938 | + .addAstOptimizers(ConstantFoldingOptimizer.getInstance()) |
| 939 | + .build(); |
| 940 | + CelAbstractSyntaxTree ast = |
| 941 | + celWithoutMacros.compile("double('NaN') in [double('NaN'), double_x]").getAst(); |
| 942 | + |
| 943 | + CelAbstractSyntaxTree optimizedAst = optimizer.optimize(ast); |
| 944 | + |
| 945 | + assertThat(CEL_UNPARSER.unparse(optimizedAst)).isEqualTo("NaN in [NaN, double_x]"); |
| 946 | + } |
865 | 947 | } |
0 commit comments