diff --git a/extensions/src/main/java/dev/cel/extensions/BUILD.bazel b/extensions/src/main/java/dev/cel/extensions/BUILD.bazel index 2eb26846f..454b2a2fd 100644 --- a/extensions/src/main/java/dev/cel/extensions/BUILD.bazel +++ b/extensions/src/main/java/dev/cel/extensions/BUILD.bazel @@ -42,6 +42,7 @@ java_library( ":strings", "//common:options", "//extensions:extension_library", + "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", ], ) diff --git a/extensions/src/main/java/dev/cel/extensions/CelExtensions.java b/extensions/src/main/java/dev/cel/extensions/CelExtensions.java index 2d14ed118..8f1770f3f 100644 --- a/extensions/src/main/java/dev/cel/extensions/CelExtensions.java +++ b/extensions/src/main/java/dev/cel/extensions/CelExtensions.java @@ -19,7 +19,9 @@ import com.google.common.collect.ImmutableSet; import com.google.common.collect.Streams; +import com.google.errorprone.annotations.InlineMe; import dev.cel.common.CelOptions; +import dev.cel.extensions.CelMathExtensions.Function; import java.util.Set; /** @@ -121,12 +123,9 @@ public static CelProtoExtensions protos() { *

This will include all functions denoted in {@link CelMathExtensions.Function}, including any * future additions. To expose only a subset of these, use {@link #math(CelOptions, * CelMathExtensions.Function...)} or {@link #math(CelOptions,int)} instead. - * - * @param celOptions CelOptions to configure CelMathExtension with. This should be the same - * options object used to configure the compilation/runtime environments. */ - public static CelMathExtensions math(CelOptions celOptions) { - return CelMathExtensions.library(celOptions).latest(); + public static CelMathExtensions math() { + return CelMathExtensions.library().latest(); } /** @@ -134,8 +133,8 @@ public static CelMathExtensions math(CelOptions celOptions) { * *

Refer to README.md for functions available in each version. */ - public static CelMathExtensions math(CelOptions celOptions, int version) { - return CelMathExtensions.library(celOptions).version(version); + public static CelMathExtensions math(int version) { + return CelMathExtensions.library().version(version); } /** @@ -150,13 +149,9 @@ public static CelMathExtensions math(CelOptions celOptions, int version) { * collision. * *

This will include only the specific functions denoted by {@link CelMathExtensions.Function}. - * - * @param celOptions CelOptions to configure CelMathExtension with. This should be the same - * options object used to configure the compilation/runtime environments. */ - public static CelMathExtensions math( - CelOptions celOptions, CelMathExtensions.Function... functions) { - return math(celOptions, ImmutableSet.copyOf(functions)); + public static CelMathExtensions math(CelMathExtensions.Function... functions) { + return math(ImmutableSet.copyOf(functions)); } /** @@ -171,13 +166,49 @@ public static CelMathExtensions math( * collision. * *

This will include only the specific functions denoted by {@link CelMathExtensions.Function}. - * - * @param celOptions CelOptions to configure CelMathExtension with. This should be the same - * options object used to configure the compilation/runtime environments. */ + public static CelMathExtensions math(Set functions) { + return new CelMathExtensions(functions); + } + + /** + * @deprecated Use {@link #math()} instead. + */ + @Deprecated + @InlineMe(replacement = "CelExtensions.math()", imports = "dev.cel.extensions.CelExtensions") + public static CelMathExtensions math(CelOptions unused) { + return math(); + } + + /** + * @deprecated Use {@link #math(int)} instead. + */ + @Deprecated + @InlineMe( + replacement = "CelExtensions.math(version)", + imports = "dev.cel.extensions.CelExtensions") + public static CelMathExtensions math(CelOptions unused, int version) { + return math(version); + } + + /** + * @deprecated Use {@link #math(Function...)} instead. + */ + @Deprecated + public static CelMathExtensions math(CelOptions unused, CelMathExtensions.Function... functions) { + return math(ImmutableSet.copyOf(functions)); + } + + /** + * @deprecated Use {@link #math(Set)} instead. + */ + @Deprecated + @InlineMe( + replacement = "CelExtensions.math(functions)", + imports = "dev.cel.extensions.CelExtensions") public static CelMathExtensions math( - CelOptions celOptions, Set functions) { - return new CelMathExtensions(celOptions, functions); + CelOptions unused, Set functions) { + return math(functions); } /** @@ -354,7 +385,7 @@ public static CelExtensionLibrary getE case "lists": return CelListsExtensions.library(); case "math": - return CelMathExtensions.library(options); + return CelMathExtensions.library(); case "optional": return CelOptionalLibrary.library(); case "protos": diff --git a/extensions/src/main/java/dev/cel/extensions/CelMathExtensions.java b/extensions/src/main/java/dev/cel/extensions/CelMathExtensions.java index 22336eb22..78a0fd51c 100644 --- a/extensions/src/main/java/dev/cel/extensions/CelMathExtensions.java +++ b/extensions/src/main/java/dev/cel/extensions/CelMathExtensions.java @@ -27,7 +27,6 @@ import dev.cel.checker.CelCheckerBuilder; import dev.cel.common.CelFunctionDecl; import dev.cel.common.CelIssue; -import dev.cel.common.CelOptions; import dev.cel.common.CelOverloadDecl; import dev.cel.common.ast.CelConstant; import dev.cel.common.ast.CelExpr; @@ -136,7 +135,8 @@ public final class CelMathExtensions return builder.buildOrThrow(); } - enum Function { + /** Enumeration of functions for Math extension. */ + public enum Function { MAX( CelFunctionDecl.newFunctionDeclaration( MATH_MAX_FUNCTION, @@ -206,51 +206,59 @@ enum Function { MATH_MAX_OVERLOAD_DOC, SimpleType.DYN, ListType.create(SimpleType.DYN))), - ImmutableSet.of( - CelFunctionBinding.from("math_@max_double", Double.class, x -> x), - CelFunctionBinding.from("math_@max_int", Long.class, x -> x), - CelFunctionBinding.from( - "math_@max_double_double", Double.class, Double.class, CelMathExtensions::maxPair), - CelFunctionBinding.from( - "math_@max_int_int", Long.class, Long.class, CelMathExtensions::maxPair), - CelFunctionBinding.from( - "math_@max_int_double", Long.class, Double.class, CelMathExtensions::maxPair), - CelFunctionBinding.from( - "math_@max_double_int", Double.class, Long.class, CelMathExtensions::maxPair), - CelFunctionBinding.from("math_@max_list_dyn", List.class, CelMathExtensions::maxList)), - ImmutableSet.of( - CelFunctionBinding.from("math_@max_uint", Long.class, x -> x), - CelFunctionBinding.from( - "math_@max_uint_uint", Long.class, Long.class, CelMathExtensions::maxPair), - CelFunctionBinding.from( - "math_@max_double_uint", Double.class, Long.class, CelMathExtensions::maxPair), - CelFunctionBinding.from( - "math_@max_uint_int", Long.class, Long.class, CelMathExtensions::maxPair), - CelFunctionBinding.from( - "math_@max_uint_double", Long.class, Double.class, CelMathExtensions::maxPair), - CelFunctionBinding.from( - "math_@max_int_uint", Long.class, Long.class, CelMathExtensions::maxPair)), - ImmutableSet.of( - CelFunctionBinding.from("math_@max_uint", UnsignedLong.class, x -> x), - CelFunctionBinding.from( - "math_@max_uint_uint", - UnsignedLong.class, - UnsignedLong.class, - CelMathExtensions::maxPair), - CelFunctionBinding.from( - "math_@max_double_uint", - Double.class, - UnsignedLong.class, - CelMathExtensions::maxPair), - CelFunctionBinding.from( - "math_@max_uint_int", UnsignedLong.class, Long.class, CelMathExtensions::maxPair), - CelFunctionBinding.from( - "math_@max_uint_double", - UnsignedLong.class, - Double.class, - CelMathExtensions::maxPair), - CelFunctionBinding.from( - "math_@max_int_uint", Long.class, UnsignedLong.class, CelMathExtensions::maxPair))), + ImmutableSet.builder() + .add(CelFunctionBinding.from("math_@max_double", Double.class, x -> x)) + .add(CelFunctionBinding.from("math_@max_int", Long.class, x -> x)) + .add( + CelFunctionBinding.from( + "math_@max_double_double", + Double.class, + Double.class, + CelMathExtensions::maxPair)) + .add( + CelFunctionBinding.from( + "math_@max_int_int", Long.class, Long.class, CelMathExtensions::maxPair)) + .add( + CelFunctionBinding.from( + "math_@max_int_double", Long.class, Double.class, CelMathExtensions::maxPair)) + .add( + CelFunctionBinding.from( + "math_@max_double_int", Double.class, Long.class, CelMathExtensions::maxPair)) + .add( + CelFunctionBinding.from( + "math_@max_list_dyn", List.class, CelMathExtensions::maxList)) + .add(CelFunctionBinding.from("math_@max_uint", UnsignedLong.class, x -> x)) + .add( + CelFunctionBinding.from( + "math_@max_uint_uint", + UnsignedLong.class, + UnsignedLong.class, + CelMathExtensions::maxPair)) + .add( + CelFunctionBinding.from( + "math_@max_double_uint", + Double.class, + UnsignedLong.class, + CelMathExtensions::maxPair)) + .add( + CelFunctionBinding.from( + "math_@max_uint_int", + UnsignedLong.class, + Long.class, + CelMathExtensions::maxPair)) + .add( + CelFunctionBinding.from( + "math_@max_uint_double", + UnsignedLong.class, + Double.class, + CelMathExtensions::maxPair)) + .add( + CelFunctionBinding.from( + "math_@max_int_uint", + Long.class, + UnsignedLong.class, + CelMathExtensions::maxPair)) + .build()), MIN( CelFunctionDecl.newFunctionDeclaration( MATH_MIN_FUNCTION, @@ -320,51 +328,59 @@ enum Function { MATH_MIN_OVERLOAD_DOC, SimpleType.DYN, ListType.create(SimpleType.DYN))), - ImmutableSet.of( - CelFunctionBinding.from("math_@min_double", Double.class, x -> x), - CelFunctionBinding.from("math_@min_int", Long.class, x -> x), - CelFunctionBinding.from( - "math_@min_double_double", Double.class, Double.class, CelMathExtensions::minPair), - CelFunctionBinding.from( - "math_@min_int_int", Long.class, Long.class, CelMathExtensions::minPair), - CelFunctionBinding.from( - "math_@min_int_double", Long.class, Double.class, CelMathExtensions::minPair), - CelFunctionBinding.from( - "math_@min_double_int", Double.class, Long.class, CelMathExtensions::minPair), - CelFunctionBinding.from("math_@min_list_dyn", List.class, CelMathExtensions::minList)), - ImmutableSet.of( - CelFunctionBinding.from("math_@min_uint", Long.class, x -> x), - CelFunctionBinding.from( - "math_@min_uint_uint", Long.class, Long.class, CelMathExtensions::minPair), - CelFunctionBinding.from( - "math_@min_double_uint", Double.class, Long.class, CelMathExtensions::minPair), - CelFunctionBinding.from( - "math_@min_uint_int", Long.class, Long.class, CelMathExtensions::minPair), - CelFunctionBinding.from( - "math_@min_uint_double", Long.class, Double.class, CelMathExtensions::minPair), - CelFunctionBinding.from( - "math_@min_int_uint", Long.class, Long.class, CelMathExtensions::minPair)), - ImmutableSet.of( - CelFunctionBinding.from("math_@min_uint", UnsignedLong.class, x -> x), - CelFunctionBinding.from( - "math_@min_uint_uint", - UnsignedLong.class, - UnsignedLong.class, - CelMathExtensions::minPair), - CelFunctionBinding.from( - "math_@min_double_uint", - Double.class, - UnsignedLong.class, - CelMathExtensions::minPair), - CelFunctionBinding.from( - "math_@min_uint_int", UnsignedLong.class, Long.class, CelMathExtensions::minPair), - CelFunctionBinding.from( - "math_@min_uint_double", - UnsignedLong.class, - Double.class, - CelMathExtensions::minPair), - CelFunctionBinding.from( - "math_@min_int_uint", Long.class, UnsignedLong.class, CelMathExtensions::minPair))), + ImmutableSet.builder() + .add(CelFunctionBinding.from("math_@min_double", Double.class, x -> x)) + .add(CelFunctionBinding.from("math_@min_int", Long.class, x -> x)) + .add( + CelFunctionBinding.from( + "math_@min_double_double", + Double.class, + Double.class, + CelMathExtensions::minPair)) + .add( + CelFunctionBinding.from( + "math_@min_int_int", Long.class, Long.class, CelMathExtensions::minPair)) + .add( + CelFunctionBinding.from( + "math_@min_int_double", Long.class, Double.class, CelMathExtensions::minPair)) + .add( + CelFunctionBinding.from( + "math_@min_double_int", Double.class, Long.class, CelMathExtensions::minPair)) + .add( + CelFunctionBinding.from( + "math_@min_list_dyn", List.class, CelMathExtensions::minList)) + .add(CelFunctionBinding.from("math_@min_uint", UnsignedLong.class, x -> x)) + .add( + CelFunctionBinding.from( + "math_@min_uint_uint", + UnsignedLong.class, + UnsignedLong.class, + CelMathExtensions::minPair)) + .add( + CelFunctionBinding.from( + "math_@min_double_uint", + Double.class, + UnsignedLong.class, + CelMathExtensions::minPair)) + .add( + CelFunctionBinding.from( + "math_@min_uint_int", + UnsignedLong.class, + Long.class, + CelMathExtensions::minPair)) + .add( + CelFunctionBinding.from( + "math_@min_uint_double", + UnsignedLong.class, + Double.class, + CelMathExtensions::minPair)) + .add( + CelFunctionBinding.from( + "math_@min_int_uint", + Long.class, + UnsignedLong.class, + CelMathExtensions::minPair)) + .build()), CEIL( CelFunctionDecl.newFunctionDeclaration( MATH_CEIL_FUNCTION, @@ -646,36 +662,14 @@ enum Function { private final CelFunctionDecl functionDecl; private final ImmutableSet functionBindings; - private final ImmutableSet functionBindingsULongSigned; - private final ImmutableSet functionBindingsULongUnsigned; String getFunction() { return functionDecl.name(); } Function(CelFunctionDecl functionDecl, ImmutableSet bindings) { - this(functionDecl, bindings, ImmutableSet.of(), ImmutableSet.of()); - } - - Function( - CelFunctionDecl functionDecl, - ImmutableSet functionBindings, - ImmutableSet functionBindingsULongSigned, - ImmutableSet functionBindingsULongUnsigned) { this.functionDecl = functionDecl; - this.functionBindings = - functionBindings.isEmpty() - ? ImmutableSet.of() - : CelFunctionBinding.fromOverloads(functionDecl.name(), functionBindings); - this.functionBindingsULongSigned = - functionBindingsULongSigned.isEmpty() - ? ImmutableSet.of() - : CelFunctionBinding.fromOverloads(functionDecl.name(), functionBindingsULongSigned); - this.functionBindingsULongUnsigned = - functionBindingsULongUnsigned.isEmpty() - ? ImmutableSet.of() - : CelFunctionBinding.fromOverloads( - functionDecl.name(), functionBindingsULongUnsigned); + this.functionBindings = bindings; } } @@ -684,10 +678,8 @@ private static final class Library implements CelExtensionLibrarybuilder() .addAll(version1.functions) .add(Function.SQRT) - .build(), - enableUnsignedLongs); + .build()); } @Override @@ -734,25 +724,20 @@ public ImmutableSet versions() { } } - private static final Library LIBRARY_UNSIGNED_LONGS_ENABLED = new Library(true); - private static final Library LIBRARY_UNSIGNED_LONGS_DISABLED = new Library(false); + private static final Library LIBRARY = new Library(); - static CelExtensionLibrary library(CelOptions celOptions) { - return celOptions.enableUnsignedLongs() - ? LIBRARY_UNSIGNED_LONGS_ENABLED - : LIBRARY_UNSIGNED_LONGS_DISABLED; + static CelExtensionLibrary library() { + return LIBRARY; } - private final boolean enableUnsignedLongs; private final ImmutableSet functions; private final int version; - CelMathExtensions(CelOptions celOptions, Set functions) { - this(-1, functions, celOptions.enableUnsignedLongs()); + CelMathExtensions(Set functions) { + this(-1, functions); } - private CelMathExtensions(int version, Set functions, boolean enableUnsignedLongs) { - this.enableUnsignedLongs = enableUnsignedLongs; + private CelMathExtensions(int version, Set functions) { this.version = version; this.functions = ImmutableSet.copyOf(functions); } @@ -788,11 +773,11 @@ public void setCheckerOptions(CelCheckerBuilder checkerBuilder) { public void setRuntimeOptions(CelRuntimeBuilder runtimeBuilder) { functions.forEach( function -> { - runtimeBuilder.addFunctionBindings(function.functionBindings); - runtimeBuilder.addFunctionBindings( - enableUnsignedLongs - ? function.functionBindingsULongUnsigned - : function.functionBindingsULongSigned); + ImmutableSet combined = function.functionBindings; + if (!combined.isEmpty()) { + runtimeBuilder.addFunctionBindings( + CelFunctionBinding.fromOverloads(function.functionDecl.name(), combined)); + } }); } diff --git a/extensions/src/test/java/dev/cel/extensions/BUILD.bazel b/extensions/src/test/java/dev/cel/extensions/BUILD.bazel index 19fd3657e..eed240317 100644 --- a/extensions/src/test/java/dev/cel/extensions/BUILD.bazel +++ b/extensions/src/test/java/dev/cel/extensions/BUILD.bazel @@ -12,6 +12,7 @@ java_library( "//bundle:cel", "//bundle:cel_experimental_factory", "//common:cel_ast", + "//common:cel_exception", "//common:compiler_common", "//common:container", "//common:options", diff --git a/extensions/src/test/java/dev/cel/extensions/CelBindingsExtensionsTest.java b/extensions/src/test/java/dev/cel/extensions/CelBindingsExtensionsTest.java index b87967d0e..00fcad473 100644 --- a/extensions/src/test/java/dev/cel/extensions/CelBindingsExtensionsTest.java +++ b/extensions/src/test/java/dev/cel/extensions/CelBindingsExtensionsTest.java @@ -23,7 +23,6 @@ import com.google.testing.junit.testparameterinjector.TestParameterInjector; import com.google.testing.junit.testparameterinjector.TestParameters; import dev.cel.bundle.Cel; -import dev.cel.common.CelAbstractSyntaxTree; import dev.cel.common.CelFunctionDecl; import dev.cel.common.CelOptions; import dev.cel.common.CelOverloadDecl; @@ -36,36 +35,24 @@ import dev.cel.parser.CelStandardMacro; import dev.cel.runtime.CelEvaluationException; import dev.cel.runtime.CelFunctionBinding; -import dev.cel.testing.CelRuntimeFlavor; import java.util.Arrays; import java.util.List; -import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; -import org.junit.Assume; -import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @RunWith(TestParameterInjector.class) -public final class CelBindingsExtensionsTest { - - @TestParameter public CelRuntimeFlavor runtimeFlavor; - @TestParameter public boolean isParseOnly; - - private Cel cel; - - @Before - public void setUp() { - // Legacy runtime does not support parsed-only evaluation mode. - Assume.assumeFalse(runtimeFlavor.equals(CelRuntimeFlavor.LEGACY) && isParseOnly); - cel = - runtimeFlavor - .builder() - .setOptions(CelOptions.current().enableHeterogeneousNumericComparisons(true).build()) - .setStandardMacros(CelStandardMacro.STANDARD_MACROS) - .addCompilerLibraries(CelOptionalLibrary.INSTANCE, CelExtensions.bindings()) - .addRuntimeLibraries(CelOptionalLibrary.INSTANCE) - .build(); +public final class CelBindingsExtensionsTest extends CelExtensionTestBase { + + @Override + protected Cel newCelEnv() { + return runtimeFlavor + .builder() + .setOptions(CelOptions.current().enableHeterogeneousNumericComparisons(true).build()) + .setStandardMacros(CelStandardMacro.STANDARD_MACROS) + .addCompilerLibraries(CelOptionalLibrary.INSTANCE, CelExtensions.bindings()) + .addRuntimeLibraries(CelOptionalLibrary.INSTANCE) + .build(); } @Test @@ -331,21 +318,5 @@ public void lazyBinding_boundAttributeInNestedComprehension() throws Exception { assertThat(invocation.get()).isEqualTo(1); } - private Object eval(Cel cel, String expression) throws Exception { - return eval(cel, expression, ImmutableMap.of()); - } - - private Object eval(Cel cel, String expression, Map variables) throws Exception { - CelAbstractSyntaxTree ast; - if (isParseOnly) { - ast = cel.parse(expression).getAst(); - } else { - ast = cel.compile(expression).getAst(); - } - return cel.createProgram(ast).eval(variables); - } - private Object eval(String expression) throws Exception { - return eval(this.cel, expression, ImmutableMap.of()); - } } diff --git a/extensions/src/test/java/dev/cel/extensions/CelComprehensionsExtensionsTest.java b/extensions/src/test/java/dev/cel/extensions/CelComprehensionsExtensionsTest.java index 207178cfe..42dc3e07d 100644 --- a/extensions/src/test/java/dev/cel/extensions/CelComprehensionsExtensionsTest.java +++ b/extensions/src/test/java/dev/cel/extensions/CelComprehensionsExtensionsTest.java @@ -19,7 +19,6 @@ import static org.junit.Assert.assertThrows; import com.google.common.base.Throwables; -import com.google.common.collect.ImmutableMap; import com.google.testing.junit.testparameterinjector.TestParameter; import com.google.testing.junit.testparameterinjector.TestParameterInjector; import com.google.testing.junit.testparameterinjector.TestParameters; @@ -40,15 +39,13 @@ import dev.cel.parser.CelUnparserFactory; import dev.cel.runtime.CelEvaluationException; import dev.cel.testing.CelRuntimeFlavor; -import java.util.Map; import org.junit.Assume; -import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; /** Test for {@link CelExtensions#comprehensions()} */ @RunWith(TestParameterInjector.class) -public class CelComprehensionsExtensionsTest { +public class CelComprehensionsExtensionsTest extends CelExtensionTestBase { private static final CelOptions CEL_OPTIONS = CelOptions.current() @@ -57,29 +54,21 @@ public class CelComprehensionsExtensionsTest { .populateMacroCalls(true) .build(); - @TestParameter public CelRuntimeFlavor runtimeFlavor; - @TestParameter public boolean isParseOnly; - - private Cel cel; - - @Before - public void setUp() { - // Legacy runtime does not support parsed-only evaluation mode. - Assume.assumeFalse(runtimeFlavor.equals(CelRuntimeFlavor.LEGACY) && isParseOnly); - this.cel = - runtimeFlavor - .builder() - .setOptions(CEL_OPTIONS) - .setStandardMacros(CelStandardMacro.STANDARD_MACROS) - .addCompilerLibraries(CelExtensions.comprehensions()) - .addCompilerLibraries(CelExtensions.lists()) - .addCompilerLibraries(CelExtensions.strings()) - .addCompilerLibraries(CelOptionalLibrary.INSTANCE, CelExtensions.bindings()) - .addRuntimeLibraries(CelOptionalLibrary.INSTANCE) - .addRuntimeLibraries(CelExtensions.lists()) - .addRuntimeLibraries(CelExtensions.strings()) - .addRuntimeLibraries(CelExtensions.comprehensions()) - .build(); + @Override + protected Cel newCelEnv() { + return runtimeFlavor + .builder() + .setOptions(CEL_OPTIONS) + .setStandardMacros(CelStandardMacro.STANDARD_MACROS) + .addCompilerLibraries(CelExtensions.comprehensions()) + .addCompilerLibraries(CelExtensions.lists()) + .addCompilerLibraries(CelExtensions.strings()) + .addCompilerLibraries(CelOptionalLibrary.INSTANCE, CelExtensions.bindings()) + .addRuntimeLibraries(CelOptionalLibrary.INSTANCE) + .addRuntimeLibraries(CelExtensions.lists()) + .addRuntimeLibraries(CelExtensions.strings()) + .addRuntimeLibraries(CelExtensions.comprehensions()) + .build(); } private static final CelUnparser UNPARSER = CelUnparserFactory.newUnparser(); @@ -376,17 +365,5 @@ public void mutableMapValue_select_missingKeyException() throws Exception { assertThat(e).hasCauseThat().hasMessageThat().contains("key 'b' is not present in map."); } - private Object eval(String expression) throws Exception { - return eval(this.cel, expression, ImmutableMap.of()); - } - private Object eval(Cel cel, String expression, Map variables) throws Exception { - CelAbstractSyntaxTree ast; - if (isParseOnly) { - ast = cel.parse(expression).getAst(); - } else { - ast = cel.compile(expression).getAst(); - } - return cel.createProgram(ast).eval(variables); - } } diff --git a/extensions/src/test/java/dev/cel/extensions/CelEncoderExtensionsTest.java b/extensions/src/test/java/dev/cel/extensions/CelEncoderExtensionsTest.java index b0a501ddb..afeaa9105 100644 --- a/extensions/src/test/java/dev/cel/extensions/CelEncoderExtensionsTest.java +++ b/extensions/src/test/java/dev/cel/extensions/CelEncoderExtensionsTest.java @@ -19,44 +19,32 @@ import static org.junit.Assert.assertThrows; import com.google.common.collect.ImmutableMap; -import com.google.testing.junit.testparameterinjector.TestParameter; import com.google.testing.junit.testparameterinjector.TestParameterInjector; import dev.cel.bundle.Cel; -import dev.cel.common.CelAbstractSyntaxTree; import dev.cel.common.CelFunctionDecl; import dev.cel.common.CelOptions; import dev.cel.common.CelValidationException; import dev.cel.common.types.SimpleType; import dev.cel.common.values.CelByteString; import dev.cel.runtime.CelEvaluationException; -import dev.cel.testing.CelRuntimeFlavor; import org.junit.Assume; -import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @RunWith(TestParameterInjector.class) -public class CelEncoderExtensionsTest { +public class CelEncoderExtensionsTest extends CelExtensionTestBase { private static final CelOptions CEL_OPTIONS = CelOptions.current().enableHeterogeneousNumericComparisons(true).build(); - @TestParameter public CelRuntimeFlavor runtimeFlavor; - @TestParameter public boolean isParseOnly; - - private Cel cel; - - @Before - public void setUp() { - // Legacy runtime does not support parsed-only evaluation mode. - Assume.assumeFalse(runtimeFlavor.equals(CelRuntimeFlavor.LEGACY) && isParseOnly); - this.cel = - runtimeFlavor - .builder() - .setOptions(CEL_OPTIONS) - .addCompilerLibraries(CelExtensions.encoders(CEL_OPTIONS)) - .addRuntimeLibraries(CelExtensions.encoders(CEL_OPTIONS)) - .addVar("stringVar", SimpleType.STRING) - .build(); + @Override + protected Cel newCelEnv() { + return runtimeFlavor + .builder() + .setOptions(CEL_OPTIONS) + .addCompilerLibraries(CelExtensions.encoders(CEL_OPTIONS)) + .addRuntimeLibraries(CelExtensions.encoders(CEL_OPTIONS)) + .addVar("stringVar", SimpleType.STRING) + .build(); } @Test @@ -132,12 +120,5 @@ public void decode_malformedBase64Char_throwsEvaluationException() throws Except assertThat(e).hasCauseThat().hasMessageThat().contains("Illegal base64 character"); } - private Object eval(String expr) throws Exception { - return eval(expr, ImmutableMap.of()); - } - private Object eval(String expr, ImmutableMap vars) throws Exception { - CelAbstractSyntaxTree ast = isParseOnly ? cel.parse(expr).getAst() : cel.compile(expr).getAst(); - return cel.createProgram(ast).eval(vars); - } } diff --git a/extensions/src/test/java/dev/cel/extensions/CelExtensionTestBase.java b/extensions/src/test/java/dev/cel/extensions/CelExtensionTestBase.java new file mode 100644 index 000000000..c80ee38b6 --- /dev/null +++ b/extensions/src/test/java/dev/cel/extensions/CelExtensionTestBase.java @@ -0,0 +1,66 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package dev.cel.extensions; + +import com.google.common.collect.ImmutableMap; +import com.google.testing.junit.testparameterinjector.TestParameter; +import dev.cel.bundle.Cel; +import dev.cel.common.CelAbstractSyntaxTree; +import dev.cel.common.CelException; +import dev.cel.testing.CelRuntimeFlavor; +import java.util.Map; +import org.junit.Assume; +import org.junit.Before; + +/** + * Abstract base class for extension tests to facilitate executing tests with both legacy and + * planner runtime, along with parsed-only and checked expression evaluations for the planner. + */ +abstract class CelExtensionTestBase { + @TestParameter public CelRuntimeFlavor runtimeFlavor; + @TestParameter public boolean isParseOnly; + + @Before + public void setUpBase() { + // Legacy runtime does not support parsed-only evaluation. + Assume.assumeFalse(runtimeFlavor.equals(CelRuntimeFlavor.LEGACY) && isParseOnly); + this.cel = newCelEnv(); + } + + protected Cel cel; + + /** + * Subclasses must implement this to provide a Cel instance configured with the specific + * extensions being tested. + */ + protected abstract Cel newCelEnv(); + + protected Object eval(String expr) throws CelException { + return eval(cel, expr, ImmutableMap.of()); + } + + protected Object eval(String expr, Map variables) throws CelException { + return eval(cel, expr, variables); + } + + protected Object eval(Cel cel, String expr) throws CelException { + return eval(cel, expr, ImmutableMap.of()); + } + + protected Object eval(Cel cel, String expr, Map variables) throws CelException { + CelAbstractSyntaxTree ast = isParseOnly ? cel.parse(expr).getAst() : cel.compile(expr).getAst(); + return cel.createProgram(ast).eval(variables); + } +} diff --git a/extensions/src/test/java/dev/cel/extensions/CelListsExtensionsTest.java b/extensions/src/test/java/dev/cel/extensions/CelListsExtensionsTest.java index f36d90e2d..f5536da4e 100644 --- a/extensions/src/test/java/dev/cel/extensions/CelListsExtensionsTest.java +++ b/extensions/src/test/java/dev/cel/extensions/CelListsExtensionsTest.java @@ -19,12 +19,9 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSortedMultiset; import com.google.common.collect.ImmutableSortedSet; -import com.google.testing.junit.testparameterinjector.TestParameter; import com.google.testing.junit.testparameterinjector.TestParameterInjector; import com.google.testing.junit.testparameterinjector.TestParameters; import dev.cel.bundle.Cel; -import dev.cel.bundle.CelBuilder; -import dev.cel.common.CelAbstractSyntaxTree; import dev.cel.common.CelContainer; import dev.cel.common.CelValidationException; import dev.cel.common.CelValidationResult; @@ -32,25 +29,24 @@ import dev.cel.expr.conformance.test.SimpleTest; import dev.cel.parser.CelStandardMacro; import dev.cel.runtime.CelEvaluationException; -import dev.cel.testing.CelRuntimeFlavor; -import java.util.Map; import org.junit.Assume; -import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @RunWith(TestParameterInjector.class) -public class CelListsExtensionsTest { - @TestParameter public CelRuntimeFlavor runtimeFlavor; - @TestParameter public boolean isParseOnly; +public class CelListsExtensionsTest extends CelExtensionTestBase { - private Cel cel; - - @Before - public void setUp() { - // Legacy runtime does not support parsed-only evaluation mode. - Assume.assumeFalse(runtimeFlavor.equals(CelRuntimeFlavor.LEGACY) && isParseOnly); - this.cel = setupEnv(runtimeFlavor.builder()); + @Override + protected Cel newCelEnv() { + return runtimeFlavor + .builder() + .setStandardMacros(CelStandardMacro.STANDARD_MACROS) + .addCompilerLibraries(CelExtensions.lists()) + .addRuntimeLibraries(CelExtensions.lists()) + .setContainer(CelContainer.ofName("cel.expr.conformance.test")) + .addMessageTypes(SimpleTest.getDescriptor()) + .addVar("non_list", SimpleType.DYN) + .build(); } @Test @@ -322,23 +318,5 @@ public void sortBy_throws_evaluationException(String expression, String expected .contains(expectedError); } - private static Cel setupEnv(CelBuilder celBuilder) { - return celBuilder - .setStandardMacros(CelStandardMacro.STANDARD_MACROS) - .addCompilerLibraries(CelExtensions.lists()) - .addRuntimeLibraries(CelExtensions.lists()) - .setContainer(CelContainer.ofName("cel.expr.conformance.test")) - .addMessageTypes(SimpleTest.getDescriptor()) - .addVar("non_list", SimpleType.DYN) - .build(); - } - - private Object eval(Cel cel, String expr) throws Exception { - return eval(cel, expr, ImmutableMap.of()); - } - private Object eval(Cel cel, String expr, Map vars) throws Exception { - CelAbstractSyntaxTree ast = isParseOnly ? cel.parse(expr).getAst() : cel.compile(expr).getAst(); - return cel.createProgram(ast).eval(vars); - } } diff --git a/extensions/src/test/java/dev/cel/extensions/CelMathExtensionsTest.java b/extensions/src/test/java/dev/cel/extensions/CelMathExtensionsTest.java index bcdfb0a21..383e50aa2 100644 --- a/extensions/src/test/java/dev/cel/extensions/CelMathExtensionsTest.java +++ b/extensions/src/test/java/dev/cel/extensions/CelMathExtensionsTest.java @@ -20,8 +20,10 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.primitives.UnsignedLong; +import com.google.testing.junit.testparameterinjector.TestParameter; import com.google.testing.junit.testparameterinjector.TestParameterInjector; import com.google.testing.junit.testparameterinjector.TestParameters; +import dev.cel.bundle.Cel; import dev.cel.common.CelAbstractSyntaxTree; import dev.cel.common.CelFunctionDecl; import dev.cel.common.CelOptions; @@ -35,34 +37,36 @@ import dev.cel.runtime.CelFunctionBinding; import dev.cel.runtime.CelRuntime; import dev.cel.runtime.CelRuntimeFactory; +import dev.cel.testing.CelRuntimeFlavor; +import java.util.Map; +import org.junit.Assume; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @RunWith(TestParameterInjector.class) public class CelMathExtensionsTest { - private static final CelOptions CEL_OPTIONS = - CelOptions.current().enableUnsignedLongs(false).build(); - private static final CelCompiler CEL_COMPILER = - CelCompilerFactory.standardCelCompilerBuilder() - .setOptions(CEL_OPTIONS) - .addLibraries(CelExtensions.math(CEL_OPTIONS)) - .build(); - private static final CelRuntime CEL_RUNTIME = - CelRuntimeFactory.standardCelRuntimeBuilder() - .setOptions(CEL_OPTIONS) - .addLibraries(CelExtensions.math(CEL_OPTIONS)) - .build(); - private static final CelOptions CEL_UNSIGNED_OPTIONS = CelOptions.current().build(); - private static final CelCompiler CEL_UNSIGNED_COMPILER = - CelCompilerFactory.standardCelCompilerBuilder() - .setOptions(CEL_UNSIGNED_OPTIONS) - .addLibraries(CelExtensions.math(CEL_UNSIGNED_OPTIONS)) - .build(); - private static final CelRuntime CEL_UNSIGNED_RUNTIME = - CelRuntimeFactory.standardCelRuntimeBuilder() - .setOptions(CEL_UNSIGNED_OPTIONS) - .addLibraries(CelExtensions.math(CEL_UNSIGNED_OPTIONS)) - .build(); + @TestParameter public CelRuntimeFlavor runtimeFlavor; + @TestParameter public boolean isParseOnly; + + private Cel cel; + + @Before + public void setUp() { + // Legacy runtime does not support parsed-only evaluation mode. + Assume.assumeFalse(runtimeFlavor.equals(CelRuntimeFlavor.LEGACY) && isParseOnly); + this.cel = + runtimeFlavor + .builder() + .setOptions( + CelOptions.current() + .enableHeterogeneousNumericComparisons( + runtimeFlavor.equals(CelRuntimeFlavor.PLANNER)) + .build()) + .addCompilerLibraries(CelExtensions.math()) + .addRuntimeLibraries(CelExtensions.math()) + .build(); + } @Test @TestParameters("{expr: 'math.greatest(-5)', expectedResult: -5}") @@ -97,9 +101,7 @@ public class CelMathExtensionsTest { "{expr: 'math.greatest([dyn(5.4), dyn(10), dyn(3u), dyn(-5.0), dyn(3.5)])', expectedResult:" + " 10}") public void greatest_intResult_success(String expr, long expectedResult) throws Exception { - CelAbstractSyntaxTree ast = CEL_COMPILER.compile(expr).getAst(); - - Object result = CEL_RUNTIME.createProgram(ast).eval(); + Object result = eval(expr); assertThat(result).isEqualTo(expectedResult); } @@ -136,9 +138,7 @@ public void greatest_intResult_success(String expr, long expectedResult) throws "{expr: 'math.greatest([dyn(5.4), dyn(10.0), dyn(3u), dyn(-5.0), dyn(3.5)])', expectedResult:" + " 10.0}") public void greatest_doubleResult_success(String expr, double expectedResult) throws Exception { - CelAbstractSyntaxTree ast = CEL_COMPILER.compile(expr).getAst(); - - Object result = CEL_RUNTIME.createProgram(ast).eval(); + Object result = eval(expr); assertThat(result).isEqualTo(expectedResult); } @@ -163,16 +163,16 @@ public void greatest_doubleResult_success(String expr, double expectedResult) th + " '10.0'}") public void greatest_doubleResult_withUnsignedLongsEnabled_success( String expr, double expectedResult) throws Exception { - CelOptions celOptions = CelOptions.current().enableUnsignedLongs(true).build(); + CelOptions celOptions = CelOptions.DEFAULT; CelCompiler celCompiler = CelCompilerFactory.standardCelCompilerBuilder() .setOptions(celOptions) - .addLibraries(CelExtensions.math(celOptions)) + .addLibraries(CelExtensions.math()) .build(); CelRuntime celRuntime = CelRuntimeFactory.standardCelRuntimeBuilder() .setOptions(celOptions) - .addLibraries(CelExtensions.math(celOptions)) + .addLibraries(CelExtensions.math()) .build(); CelAbstractSyntaxTree ast = celCompiler.compile(expr).getAst(); @@ -182,44 +182,7 @@ public void greatest_doubleResult_withUnsignedLongsEnabled_success( } @Test - @TestParameters("{expr: 'math.greatest(5u)', expectedResult: 5}") - @TestParameters("{expr: 'math.greatest(1u, 1.0)', expectedResult: 1}") - @TestParameters("{expr: 'math.greatest(1u, 1)', expectedResult: 1}") - @TestParameters("{expr: 'math.greatest(1u, 1u)', expectedResult: 1}") - @TestParameters("{expr: 'math.greatest(3u, 3.0)', expectedResult: 3}") - @TestParameters("{expr: 'math.greatest(9u, 10u)', expectedResult: 10}") - @TestParameters("{expr: 'math.greatest(15u, 14u)', expectedResult: 15}") - @TestParameters( - "{expr: 'math.greatest(1, 9223372036854775807u)', expectedResult: 9223372036854775807}") - @TestParameters( - "{expr: 'math.greatest(9223372036854775807u, 1)', expectedResult: 9223372036854775807}") - @TestParameters("{expr: 'math.greatest(1u, 1, 1)', expectedResult: 1}") - @TestParameters("{expr: 'math.greatest(3u, 1u, 10u)', expectedResult: 10}") - @TestParameters("{expr: 'math.greatest(1u, 5u, 2u)', expectedResult: 5}") - @TestParameters("{expr: 'math.greatest(-1, 1u, 0u)', expectedResult: 1}") - @TestParameters("{expr: 'math.greatest(dyn(1u), 1, 1.0)', expectedResult: 1}") - @TestParameters("{expr: 'math.greatest(5u, 1.0, 3u)', expectedResult: 5}") - @TestParameters("{expr: 'math.greatest(5.4, 10u, 3u, -5.0, 3.5)', expectedResult: 10}") - @TestParameters( - "{expr: 'math.greatest(5.4, 10, 3u, -5.0, 9223372036854775807)', expectedResult:" - + " 9223372036854775807}") - @TestParameters( - "{expr: 'math.greatest(9223372036854775807, 10, 3u, -5.0, 0)', expectedResult:" - + " 9223372036854775807}") - @TestParameters("{expr: 'math.greatest([5.4, 10, 3u, -5.0, 3.5])', expectedResult: 10}") - @TestParameters( - "{expr: 'math.greatest([dyn(5.4), dyn(10), dyn(3u), dyn(-5.0), dyn(3.5)])', expectedResult:" - + " 10}") - public void greatest_unsignedLongResult_withSignedLongType_success( - String expr, long expectedResult) throws Exception { - CelAbstractSyntaxTree ast = CEL_COMPILER.compile(expr).getAst(); - - Object result = CEL_RUNTIME.createProgram(ast).eval(); - - assertThat(result).isEqualTo(expectedResult); - } - - @Test + @TestParameters("{expr: 'math.greatest(5u)', expectedResult: '5'}") @TestParameters( "{expr: 'math.greatest(18446744073709551615u)', expectedResult: '18446744073709551615'}") @TestParameters("{expr: 'math.greatest(1u, 1.0)', expectedResult: '1'}") @@ -251,16 +214,16 @@ public void greatest_unsignedLongResult_withSignedLongType_success( + " '10'}") public void greatest_unsignedLongResult_withUnsignedLongType_success( String expr, String expectedResult) throws Exception { - CelOptions celOptions = CelOptions.current().enableUnsignedLongs(true).build(); + CelOptions celOptions = CelOptions.DEFAULT; CelCompiler celCompiler = CelCompilerFactory.standardCelCompilerBuilder() .setOptions(celOptions) - .addLibraries(CelExtensions.math(celOptions)) + .addLibraries(CelExtensions.math()) .build(); CelRuntime celRuntime = CelRuntimeFactory.standardCelRuntimeBuilder() .setOptions(celOptions) - .addLibraries(CelExtensions.math(celOptions)) + .addLibraries(CelExtensions.math()) .build(); CelAbstractSyntaxTree ast = celCompiler.compile(expr).getAst(); @@ -271,9 +234,9 @@ public void greatest_unsignedLongResult_withUnsignedLongType_success( @Test public void greatest_noArgs_throwsCompilationException() { + Assume.assumeFalse(isParseOnly); CelValidationException e = - assertThrows( - CelValidationException.class, () -> CEL_COMPILER.compile("math.greatest()").getAst()); + assertThrows(CelValidationException.class, () -> cel.compile("math.greatest()").getAst()); assertThat(e).hasMessageThat().contains("math.greatest() requires at least one argument"); } @@ -283,8 +246,9 @@ public void greatest_noArgs_throwsCompilationException() { @TestParameters("{expr: 'math.greatest({})'}") @TestParameters("{expr: 'math.greatest([])'}") public void greatest_invalidSingleArg_throwsCompilationException(String expr) { + Assume.assumeFalse(isParseOnly); CelValidationException e = - assertThrows(CelValidationException.class, () -> CEL_COMPILER.compile(expr).getAst()); + assertThrows(CelValidationException.class, () -> cel.compile(expr).getAst()); assertThat(e).hasMessageThat().contains("math.greatest() invalid single argument value"); } @@ -297,8 +261,9 @@ public void greatest_invalidSingleArg_throwsCompilationException(String expr) { @TestParameters("{expr: 'math.greatest([1, {}, 2])'}") @TestParameters("{expr: 'math.greatest([1, [], 2])'}") public void greatest_invalidArgs_throwsCompilationException(String expr) { + Assume.assumeFalse(isParseOnly); CelValidationException e = - assertThrows(CelValidationException.class, () -> CEL_COMPILER.compile(expr).getAst()); + assertThrows(CelValidationException.class, () -> cel.compile(expr).getAst()); assertThat(e) .hasMessageThat() @@ -312,19 +277,16 @@ public void greatest_invalidArgs_throwsCompilationException(String expr) { @TestParameters("{expr: 'math.greatest([1, dyn({}), 2])'}") @TestParameters("{expr: 'math.greatest([1, dyn([]), 2])'}") public void greatest_invalidDynArgs_throwsRuntimeException(String expr) throws Exception { - CelAbstractSyntaxTree ast = CEL_COMPILER.compile(expr).getAst(); - - CelEvaluationException e = - assertThrows(CelEvaluationException.class, () -> CEL_RUNTIME.createProgram(ast).eval()); + CelEvaluationException e = assertThrows(CelEvaluationException.class, () -> eval(expr)); - assertThat(e).hasMessageThat().contains("Function 'math_@max_list_dyn' failed with arg(s)"); + assertThat(e).hasMessageThat().contains("failed with arg(s)"); } @Test public void greatest_listVariableIsEmpty_throwsRuntimeException() throws Exception { CelCompiler celCompiler = CelCompilerFactory.standardCelCompilerBuilder() - .addLibraries(CelExtensions.math(CEL_OPTIONS)) + .addLibraries(CelExtensions.math()) .addVar("listVar", ListType.create(SimpleType.INT)) .build(); CelAbstractSyntaxTree ast = celCompiler.compile("math.greatest(listVar)").getAst(); @@ -332,12 +294,9 @@ public void greatest_listVariableIsEmpty_throwsRuntimeException() throws Excepti CelEvaluationException e = assertThrows( CelEvaluationException.class, - () -> - CEL_RUNTIME - .createProgram(ast) - .eval(ImmutableMap.of("listVar", ImmutableList.of()))); + () -> cel.createProgram(ast).eval(ImmutableMap.of("listVar", ImmutableList.of()))); - assertThat(e).hasMessageThat().contains("Function 'math_@max_list_dyn' failed with arg(s)"); + assertThat(e).hasMessageThat().contains("failed with arg(s)"); assertThat(e) .hasCauseThat() .hasMessageThat() @@ -347,25 +306,25 @@ public void greatest_listVariableIsEmpty_throwsRuntimeException() throws Excepti @Test @TestParameters("{expr: '100.greatest(1) == 1'}") @TestParameters("{expr: 'dyn(100).greatest(1) == 1'}") - public void greatest_nonProtoNamespace_success(String expr) throws Exception { - CelCompiler celCompiler = - CelCompilerFactory.standardCelCompilerBuilder() - .addLibraries(CelExtensions.math(CEL_OPTIONS)) + public void greatest_nonMathNamespace_success(String expr) throws Exception { + Cel cel = + runtimeFlavor + .builder() + .addCompilerLibraries(CelExtensions.math()) + .addRuntimeLibraries(CelExtensions.math()) .addFunctionDeclarations( CelFunctionDecl.newFunctionDeclaration( "greatest", CelOverloadDecl.newMemberOverload( "int_greatest_int", SimpleType.INT, SimpleType.INT, SimpleType.INT))) - .build(); - CelRuntime celRuntime = - CelRuntimeFactory.standardCelRuntimeBuilder() .addFunctionBindings( - CelFunctionBinding.from( - "int_greatest_int", Long.class, Long.class, (arg1, arg2) -> arg2)) + CelFunctionBinding.fromOverloads( + "greatest", + CelFunctionBinding.from( + "int_greatest_int", Long.class, Long.class, (arg1, arg2) -> arg2))) .build(); - CelAbstractSyntaxTree ast = celCompiler.compile(expr).getAst(); - boolean result = (boolean) celRuntime.createProgram(ast).eval(); + boolean result = (boolean) eval(cel, expr); assertThat(result).isTrue(); } @@ -400,13 +359,14 @@ public void greatest_nonProtoNamespace_success(String expr) throws Exception { "{expr: 'math.least(-9223372036854775808, 10, 3u, -5.0, 0)', expectedResult:" + " -9223372036854775808}") @TestParameters("{expr: 'math.least([5.4, -10, 3u, -5.0, 3.5])', expectedResult: -10}") + @TestParameters("{expr: 'math.least(1, 9223372036854775807u)', expectedResult: 1}") + @TestParameters("{expr: 'math.least(9223372036854775807u, 1)', expectedResult: 1}") + @TestParameters("{expr: 'math.least(9223372036854775807, 10, 3u, 5.0, 0)', expectedResult: 0}") @TestParameters( "{expr: 'math.least([dyn(5.4), dyn(-10), dyn(3u), dyn(-5.0), dyn(3.5)])', expectedResult:" + " -10}") public void least_intResult_success(String expr, long expectedResult) throws Exception { - CelAbstractSyntaxTree ast = CEL_COMPILER.compile(expr).getAst(); - - Object result = CEL_RUNTIME.createProgram(ast).eval(); + Object result = eval(expr); assertThat(result).isEqualTo(expectedResult); } @@ -443,9 +403,7 @@ public void least_intResult_success(String expr, long expectedResult) throws Exc "{expr: 'math.least([dyn(5.4), dyn(10.0), dyn(3u), dyn(-5.0), dyn(3.5)])', expectedResult:" + " -5.0}") public void least_doubleResult_success(String expr, double expectedResult) throws Exception { - CelAbstractSyntaxTree ast = CEL_COMPILER.compile(expr).getAst(); - - Object result = CEL_RUNTIME.createProgram(ast).eval(); + Object result = eval(expr); assertThat(result).isEqualTo(expectedResult); } @@ -474,12 +432,12 @@ public void least_doubleResult_withUnsignedLongsEnabled_success( CelCompiler celCompiler = CelCompilerFactory.standardCelCompilerBuilder() .setOptions(celOptions) - .addLibraries(CelExtensions.math(celOptions)) + .addLibraries(CelExtensions.math()) .build(); CelRuntime celRuntime = CelRuntimeFactory.standardCelRuntimeBuilder() .setOptions(celOptions) - .addLibraries(CelExtensions.math(celOptions)) + .addLibraries(CelExtensions.math()) .build(); CelAbstractSyntaxTree ast = celCompiler.compile(expr).getAst(); @@ -489,37 +447,15 @@ public void least_doubleResult_withUnsignedLongsEnabled_success( } @Test - @TestParameters("{expr: 'math.least(5u)', expectedResult: 5}") - @TestParameters("{expr: 'math.least(1u, 1.0)', expectedResult: 1}") - @TestParameters("{expr: 'math.least(1u, 1)', expectedResult: 1}") - @TestParameters("{expr: 'math.least(1u, 1u)', expectedResult: 1}") - @TestParameters("{expr: 'math.least(3u, 3.0)', expectedResult: 3}") - @TestParameters("{expr: 'math.least(9u, 10u)', expectedResult: 9}") - @TestParameters("{expr: 'math.least(15u, 14u)', expectedResult: 14}") - @TestParameters("{expr: 'math.least(1, 9223372036854775807u)', expectedResult: 1}") - @TestParameters("{expr: 'math.least(9223372036854775807u, 1)', expectedResult: 1}") - @TestParameters("{expr: 'math.least(1u, 1, 1)', expectedResult: 1}") - @TestParameters("{expr: 'math.least(3u, 1u, 10u)', expectedResult: 1}") - @TestParameters("{expr: 'math.least(1u, 5u, 2u)', expectedResult: 1}") - @TestParameters("{expr: 'math.least(9, 1u, 0u)', expectedResult: 0}") - @TestParameters("{expr: 'math.least(dyn(1u), 1, 1.0)', expectedResult: 1}") - @TestParameters("{expr: 'math.least(5.0, 1u, 3u)', expectedResult: 1}") - @TestParameters("{expr: 'math.least(5.4, 1u, 3u, 9, 3.5)', expectedResult: 1}") - @TestParameters("{expr: 'math.least(5.4, 10, 3u, 5.0, 9223372036854775807)', expectedResult: 3}") - @TestParameters("{expr: 'math.least(9223372036854775807, 10, 3u, 5.0, 0)', expectedResult: 0}") - @TestParameters("{expr: 'math.least([5.4, 10, 3u, 5.0, 3.5])', expectedResult: 3}") + @TestParameters("{expr: 'math.least(9, 1u, 0u)', expectedResult: '0'}") + @TestParameters("{expr: 'math.least(dyn(1u), 1, 1.0)', expectedResult: '1'}") + @TestParameters("{expr: 'math.least(5.0, 1u, 3u)', expectedResult: '1'}") + @TestParameters("{expr: 'math.least(5.4, 1u, 3u, 9, 3.5)', expectedResult: '1'}") @TestParameters( - "{expr: 'math.least([dyn(5.4), dyn(10), dyn(3u), dyn(5.0), dyn(3.5)])', expectedResult: 3}") - public void least_unsignedLongResult_withSignedLongType_success(String expr, long expectedResult) - throws Exception { - CelAbstractSyntaxTree ast = CEL_COMPILER.compile(expr).getAst(); - - Object result = CEL_RUNTIME.createProgram(ast).eval(); - - assertThat(result).isEqualTo(expectedResult); - } - - @Test + "{expr: 'math.least(5.4, 10, 3u, 5.0, 9223372036854775807)', expectedResult: '3'}") + @TestParameters("{expr: 'math.least([5.4, 10, 3u, 5.0, 3.5])', expectedResult: '3'}") + @TestParameters( + "{expr: 'math.least([dyn(5.4), dyn(10), dyn(3u), dyn(5.0), dyn(3.5)])', expectedResult: '3'}") @TestParameters( "{expr: 'math.least(18446744073709551615u)', expectedResult: '18446744073709551615'}") @TestParameters("{expr: 'math.least(1u, 1.0)', expectedResult: '1'}") @@ -553,12 +489,12 @@ public void least_unsignedLongResult_withUnsignedLongType_success( CelCompiler celCompiler = CelCompilerFactory.standardCelCompilerBuilder() .setOptions(celOptions) - .addLibraries(CelExtensions.math(celOptions)) + .addLibraries(CelExtensions.math()) .build(); CelRuntime celRuntime = CelRuntimeFactory.standardCelRuntimeBuilder() .setOptions(celOptions) - .addLibraries(CelExtensions.math(celOptions)) + .addLibraries(CelExtensions.math()) .build(); CelAbstractSyntaxTree ast = celCompiler.compile(expr).getAst(); @@ -569,9 +505,9 @@ public void least_unsignedLongResult_withUnsignedLongType_success( @Test public void least_noArgs_throwsCompilationException() { + Assume.assumeFalse(isParseOnly); CelValidationException e = - assertThrows( - CelValidationException.class, () -> CEL_COMPILER.compile("math.least()").getAst()); + assertThrows(CelValidationException.class, () -> cel.compile("math.least()").getAst()); assertThat(e).hasMessageThat().contains("math.least() requires at least one argument"); } @@ -581,8 +517,9 @@ public void least_noArgs_throwsCompilationException() { @TestParameters("{expr: 'math.least({})'}") @TestParameters("{expr: 'math.least([])'}") public void least_invalidSingleArg_throwsCompilationException(String expr) { + Assume.assumeFalse(isParseOnly); CelValidationException e = - assertThrows(CelValidationException.class, () -> CEL_COMPILER.compile(expr).getAst()); + assertThrows(CelValidationException.class, () -> cel.compile(expr).getAst()); assertThat(e).hasMessageThat().contains("math.least() invalid single argument value"); } @@ -595,8 +532,9 @@ public void least_invalidSingleArg_throwsCompilationException(String expr) { @TestParameters("{expr: 'math.least([1, {}, 2])'}") @TestParameters("{expr: 'math.least([1, [], 2])'}") public void least_invalidArgs_throwsCompilationException(String expr) { + Assume.assumeFalse(isParseOnly); CelValidationException e = - assertThrows(CelValidationException.class, () -> CEL_COMPILER.compile(expr).getAst()); + assertThrows(CelValidationException.class, () -> cel.compile(expr).getAst()); assertThat(e) .hasMessageThat() @@ -610,19 +548,16 @@ public void least_invalidArgs_throwsCompilationException(String expr) { @TestParameters("{expr: 'math.least([1, dyn({}), 2])'}") @TestParameters("{expr: 'math.least([1, dyn([]), 2])'}") public void least_invalidDynArgs_throwsRuntimeException(String expr) throws Exception { - CelAbstractSyntaxTree ast = CEL_COMPILER.compile(expr).getAst(); - - CelEvaluationException e = - assertThrows(CelEvaluationException.class, () -> CEL_RUNTIME.createProgram(ast).eval()); + CelEvaluationException e = assertThrows(CelEvaluationException.class, () -> eval(expr)); - assertThat(e).hasMessageThat().contains("Function 'math_@min_list_dyn' failed with arg(s)"); + assertThat(e).hasMessageThat().contains("failed with arg(s)"); } @Test public void least_listVariableIsEmpty_throwsRuntimeException() throws Exception { CelCompiler celCompiler = CelCompilerFactory.standardCelCompilerBuilder() - .addLibraries(CelExtensions.math(CEL_OPTIONS)) + .addLibraries(CelExtensions.math()) .addVar("listVar", ListType.create(SimpleType.INT)) .build(); CelAbstractSyntaxTree ast = celCompiler.compile("math.least(listVar)").getAst(); @@ -630,12 +565,9 @@ public void least_listVariableIsEmpty_throwsRuntimeException() throws Exception CelEvaluationException e = assertThrows( CelEvaluationException.class, - () -> - CEL_RUNTIME - .createProgram(ast) - .eval(ImmutableMap.of("listVar", ImmutableList.of()))); + () -> cel.createProgram(ast).eval(ImmutableMap.of("listVar", ImmutableList.of()))); - assertThat(e).hasMessageThat().contains("Function 'math_@min_list_dyn' failed with arg(s)"); + assertThat(e).hasMessageThat().contains("failed with arg(s)"); assertThat(e) .hasCauseThat() .hasMessageThat() @@ -645,24 +577,25 @@ public void least_listVariableIsEmpty_throwsRuntimeException() throws Exception @Test @TestParameters("{expr: '100.least(1) == 1'}") @TestParameters("{expr: 'dyn(100).least(1) == 1'}") - public void least_nonProtoNamespace_success(String expr) throws Exception { - CelCompiler celCompiler = - CelCompilerFactory.standardCelCompilerBuilder() - .addLibraries(CelExtensions.math(CEL_OPTIONS)) + public void least_nonMathNamespace_success(String expr) throws Exception { + Cel cel = + runtimeFlavor + .builder() + .addCompilerLibraries(CelExtensions.math()) + .addRuntimeLibraries(CelExtensions.math()) .addFunctionDeclarations( CelFunctionDecl.newFunctionDeclaration( "least", CelOverloadDecl.newMemberOverload( "int_least", SimpleType.INT, SimpleType.INT, SimpleType.INT))) - .build(); - CelRuntime celRuntime = - CelRuntimeFactory.standardCelRuntimeBuilder() .addFunctionBindings( - CelFunctionBinding.from("int_least", Long.class, Long.class, (arg1, arg2) -> arg2)) + CelFunctionBinding.fromOverloads( + "least", + CelFunctionBinding.from( + "int_least", Long.class, Long.class, (arg1, arg2) -> arg2))) .build(); - CelAbstractSyntaxTree ast = celCompiler.compile(expr).getAst(); - boolean result = (boolean) celRuntime.createProgram(ast).eval(); + boolean result = (boolean) eval(cel, expr); assertThat(result).isTrue(); } @@ -676,9 +609,9 @@ public void least_nonProtoNamespace_success(String expr) throws Exception { @TestParameters("{expr: 'math.isNaN(math.sign(0.0/0.0))', expectedResult: true}") @TestParameters("{expr: 'math.isNaN(math.sqrt(-4))', expectedResult: true}") public void isNaN_success(String expr, boolean expectedResult) throws Exception { - CelAbstractSyntaxTree ast = CEL_COMPILER.compile(expr).getAst(); + CelAbstractSyntaxTree ast = cel.compile(expr).getAst(); - Object result = CEL_RUNTIME.createProgram(ast).eval(); + Object result = cel.createProgram(ast).eval(); assertThat(result).isEqualTo(expectedResult); } @@ -690,7 +623,7 @@ public void isNaN_success(String expr, boolean expectedResult) throws Exception @TestParameters("{expr: 'math.isNaN(1u)'}") public void isNaN_invalidArgs_throwsException(String expr) { CelValidationException e = - assertThrows(CelValidationException.class, () -> CEL_COMPILER.compile(expr).getAst()); + assertThrows(CelValidationException.class, () -> cel.compile(expr).getAst()); assertThat(e).hasMessageThat().contains("found no matching overload for 'math.isNaN'"); } @@ -701,9 +634,9 @@ public void isNaN_invalidArgs_throwsException(String expr) { @TestParameters("{expr: 'math.isFinite(1.0/0.0)', expectedResult: false}") @TestParameters("{expr: 'math.isFinite(0.0/0.0)', expectedResult: false}") public void isFinite_success(String expr, boolean expectedResult) throws Exception { - CelAbstractSyntaxTree ast = CEL_COMPILER.compile(expr).getAst(); + CelAbstractSyntaxTree ast = cel.compile(expr).getAst(); - Object result = CEL_RUNTIME.createProgram(ast).eval(); + Object result = cel.createProgram(ast).eval(); assertThat(result).isEqualTo(expectedResult); } @@ -715,7 +648,7 @@ public void isFinite_success(String expr, boolean expectedResult) throws Excepti @TestParameters("{expr: 'math.isFinite(1u)'}") public void isFinite_invalidArgs_throwsException(String expr) { CelValidationException e = - assertThrows(CelValidationException.class, () -> CEL_COMPILER.compile(expr).getAst()); + assertThrows(CelValidationException.class, () -> cel.compile(expr).getAst()); assertThat(e).hasMessageThat().contains("found no matching overload for 'math.isFinite'"); } @@ -726,9 +659,9 @@ public void isFinite_invalidArgs_throwsException(String expr) { @TestParameters("{expr: 'math.isInf(0.0/0.0)', expectedResult: false}") @TestParameters("{expr: 'math.isInf(10.0)', expectedResult: false}") public void isInf_success(String expr, boolean expectedResult) throws Exception { - CelAbstractSyntaxTree ast = CEL_COMPILER.compile(expr).getAst(); + CelAbstractSyntaxTree ast = cel.compile(expr).getAst(); - Object result = CEL_RUNTIME.createProgram(ast).eval(); + Object result = cel.createProgram(ast).eval(); assertThat(result).isEqualTo(expectedResult); } @@ -740,7 +673,7 @@ public void isInf_success(String expr, boolean expectedResult) throws Exception @TestParameters("{expr: 'math.isInf(1u)'}") public void isInf_invalidArgs_throwsException(String expr) { CelValidationException e = - assertThrows(CelValidationException.class, () -> CEL_COMPILER.compile(expr).getAst()); + assertThrows(CelValidationException.class, () -> cel.compile(expr).getAst()); assertThat(e).hasMessageThat().contains("found no matching overload for 'math.isInf'"); } @@ -752,9 +685,9 @@ public void isInf_invalidArgs_throwsException(String expr) { @TestParameters("{expr: 'math.ceil(20.0)' , expectedResult: 20.0}") @TestParameters("{expr: 'math.ceil(0.0/0.0)' , expectedResult: NaN}") public void ceil_success(String expr, double expectedResult) throws Exception { - CelAbstractSyntaxTree ast = CEL_COMPILER.compile(expr).getAst(); + CelAbstractSyntaxTree ast = cel.compile(expr).getAst(); - Object result = CEL_RUNTIME.createProgram(ast).eval(); + Object result = cel.createProgram(ast).eval(); assertThat(result).isEqualTo(expectedResult); } @@ -766,7 +699,7 @@ public void ceil_success(String expr, double expectedResult) throws Exception { @TestParameters("{expr: 'math.ceil(1u)'}") public void ceil_invalidArgs_throwsException(String expr) { CelValidationException e = - assertThrows(CelValidationException.class, () -> CEL_COMPILER.compile(expr).getAst()); + assertThrows(CelValidationException.class, () -> cel.compile(expr).getAst()); assertThat(e).hasMessageThat().contains("found no matching overload for 'math.ceil'"); } @@ -777,9 +710,9 @@ public void ceil_invalidArgs_throwsException(String expr) { @TestParameters("{expr: 'math.floor(0.0/0.0)' , expectedResult: NaN}") @TestParameters("{expr: 'math.floor(50.0)' , expectedResult: 50.0}") public void floor_success(String expr, double expectedResult) throws Exception { - CelAbstractSyntaxTree ast = CEL_COMPILER.compile(expr).getAst(); + CelAbstractSyntaxTree ast = cel.compile(expr).getAst(); - Object result = CEL_RUNTIME.createProgram(ast).eval(); + Object result = cel.createProgram(ast).eval(); assertThat(result).isEqualTo(expectedResult); } @@ -791,7 +724,7 @@ public void floor_success(String expr, double expectedResult) throws Exception { @TestParameters("{expr: 'math.floor(1u)'}") public void floor_invalidArgs_throwsException(String expr) { CelValidationException e = - assertThrows(CelValidationException.class, () -> CEL_COMPILER.compile(expr).getAst()); + assertThrows(CelValidationException.class, () -> cel.compile(expr).getAst()); assertThat(e).hasMessageThat().contains("found no matching overload for 'math.floor'"); } @@ -806,9 +739,9 @@ public void floor_invalidArgs_throwsException(String expr) { @TestParameters("{expr: 'math.round(1.0/0.0)' , expectedResult: Infinity}") @TestParameters("{expr: 'math.round(-1.0/0.0)' , expectedResult: -Infinity}") public void round_success(String expr, double expectedResult) throws Exception { - CelAbstractSyntaxTree ast = CEL_COMPILER.compile(expr).getAst(); + CelAbstractSyntaxTree ast = cel.compile(expr).getAst(); - Object result = CEL_RUNTIME.createProgram(ast).eval(); + Object result = cel.createProgram(ast).eval(); assertThat(result).isEqualTo(expectedResult); } @@ -820,7 +753,7 @@ public void round_success(String expr, double expectedResult) throws Exception { @TestParameters("{expr: 'math.round(1u)'}") public void round_invalidArgs_throwsException(String expr) { CelValidationException e = - assertThrows(CelValidationException.class, () -> CEL_COMPILER.compile(expr).getAst()); + assertThrows(CelValidationException.class, () -> cel.compile(expr).getAst()); assertThat(e).hasMessageThat().contains("found no matching overload for 'math.round'"); } @@ -832,9 +765,9 @@ public void round_invalidArgs_throwsException(String expr) { @TestParameters("{expr: 'math.trunc(1.0/0.0)' , expectedResult: Infinity}") @TestParameters("{expr: 'math.trunc(-1.0/0.0)' , expectedResult: -Infinity}") public void trunc_success(String expr, double expectedResult) throws Exception { - CelAbstractSyntaxTree ast = CEL_COMPILER.compile(expr).getAst(); + CelAbstractSyntaxTree ast = cel.compile(expr).getAst(); - Object result = CEL_RUNTIME.createProgram(ast).eval(); + Object result = cel.createProgram(ast).eval(); assertThat(result).isEqualTo(expectedResult); } @@ -846,7 +779,7 @@ public void trunc_success(String expr, double expectedResult) throws Exception { @TestParameters("{expr: 'math.trunc(1u)'}") public void trunc_invalidArgs_throwsException(String expr) { CelValidationException e = - assertThrows(CelValidationException.class, () -> CEL_COMPILER.compile(expr).getAst()); + assertThrows(CelValidationException.class, () -> cel.compile(expr).getAst()); assertThat(e).hasMessageThat().contains("found no matching overload for 'math.trunc'"); } @@ -856,9 +789,9 @@ public void trunc_invalidArgs_throwsException(String expr) { @TestParameters("{expr: 'math.abs(-1657643)', expectedResult: 1657643}") @TestParameters("{expr: 'math.abs(-2147483648)', expectedResult: 2147483648}") public void abs_intResult_success(String expr, long expectedResult) throws Exception { - CelAbstractSyntaxTree ast = CEL_COMPILER.compile(expr).getAst(); + CelAbstractSyntaxTree ast = cel.compile(expr).getAst(); - Object result = CEL_RUNTIME.createProgram(ast).eval(); + Object result = cel.createProgram(ast).eval(); assertThat(result).isEqualTo(expectedResult); } @@ -871,9 +804,9 @@ public void abs_intResult_success(String expr, long expectedResult) throws Excep @TestParameters("{expr: 'math.abs(1.0/0.0)' , expectedResult: Infinity}") @TestParameters("{expr: 'math.abs(-1.0/0.0)' , expectedResult: Infinity}") public void abs_doubleResult_success(String expr, double expectedResult) throws Exception { - CelAbstractSyntaxTree ast = CEL_COMPILER.compile(expr).getAst(); + CelAbstractSyntaxTree ast = cel.compile(expr).getAst(); - Object result = CEL_RUNTIME.createProgram(ast).eval(); + Object result = cel.createProgram(ast).eval(); assertThat(result).isEqualTo(expectedResult); } @@ -883,7 +816,7 @@ public void abs_overflow_throwsException() { CelValidationException e = assertThrows( CelValidationException.class, - () -> CEL_COMPILER.compile("math.abs(-9223372036854775809)").getAst()); + () -> cel.compile("math.abs(-9223372036854775809)").getAst()); assertThat(e) .hasMessageThat() @@ -896,9 +829,9 @@ public void abs_overflow_throwsException() { @TestParameters("{expr: 'math.sign(-0)', expectedResult: 0}") @TestParameters("{expr: 'math.sign(11213)', expectedResult: 1}") public void sign_intResult_success(String expr, int expectedResult) throws Exception { - CelAbstractSyntaxTree ast = CEL_COMPILER.compile(expr).getAst(); + CelAbstractSyntaxTree ast = cel.compile(expr).getAst(); - Object result = CEL_RUNTIME.createProgram(ast).eval(); + Object result = cel.createProgram(ast).eval(); assertThat(result).isEqualTo(expectedResult); } @@ -914,9 +847,9 @@ public void sign_intResult_success(String expr, int expectedResult) throws Excep @TestParameters("{expr: 'math.sign(1.0/0.0)' , expectedResult: 1.0}") @TestParameters("{expr: 'math.sign(-1.0/0.0)' , expectedResult: -1.0}") public void sign_doubleResult_success(String expr, double expectedResult) throws Exception { - CelAbstractSyntaxTree ast = CEL_COMPILER.compile(expr).getAst(); + CelAbstractSyntaxTree ast = cel.compile(expr).getAst(); - Object result = CEL_RUNTIME.createProgram(ast).eval(); + Object result = cel.createProgram(ast).eval(); assertThat(result).isEqualTo(expectedResult); } @@ -926,7 +859,7 @@ public void sign_doubleResult_success(String expr, double expectedResult) throws @TestParameters("{expr: 'math.sign(\"\")'}") public void sign_invalidArgs_throwsException(String expr) { CelValidationException e = - assertThrows(CelValidationException.class, () -> CEL_COMPILER.compile(expr).getAst()); + assertThrows(CelValidationException.class, () -> cel.compile(expr).getAst()); assertThat(e).hasMessageThat().contains("found no matching overload for 'math.sign'"); } @@ -938,9 +871,9 @@ public void sign_invalidArgs_throwsException(String expr) { "{expr: 'math.bitAnd(9223372036854775807,9223372036854775807)' , expectedResult:" + " 9223372036854775807}") public void bitAnd_signedInt_success(String expr, long expectedResult) throws Exception { - CelAbstractSyntaxTree ast = CEL_COMPILER.compile(expr).getAst(); + CelAbstractSyntaxTree ast = cel.compile(expr).getAst(); - Object result = CEL_RUNTIME.createProgram(ast).eval(); + Object result = cel.createProgram(ast).eval(); assertThat(result).isEqualTo(expectedResult); } @@ -950,9 +883,9 @@ public void bitAnd_signedInt_success(String expr, long expectedResult) throws Ex @TestParameters("{expr: 'math.bitAnd(1u,3u)' , expectedResult: 1}") public void bitAnd_unSignedInt_success(String expr, UnsignedLong expectedResult) throws Exception { - CelAbstractSyntaxTree ast = CEL_UNSIGNED_COMPILER.compile(expr).getAst(); + CelAbstractSyntaxTree ast = cel.compile(expr).getAst(); - Object result = CEL_UNSIGNED_RUNTIME.createProgram(ast).eval(); + Object result = cel.createProgram(ast).eval(); assertThat(result).isEqualTo(expectedResult); } @@ -963,7 +896,7 @@ public void bitAnd_unSignedInt_success(String expr, UnsignedLong expectedResult) @TestParameters("{expr: 'math.bitAnd(1)'}") public void bitAnd_invalidArgs_throwsException(String expr) { CelValidationException e = - assertThrows(CelValidationException.class, () -> CEL_COMPILER.compile(expr).getAst()); + assertThrows(CelValidationException.class, () -> cel.compile(expr).getAst()); assertThat(e).hasMessageThat().contains("found no matching overload for 'math.bitAnd'"); } @@ -973,10 +906,7 @@ public void bitAnd_maxValArg_throwsException() { CelValidationException e = assertThrows( CelValidationException.class, - () -> - CEL_COMPILER - .compile("math.bitAnd(9223372036854775807,9223372036854775809)") - .getAst()); + () -> cel.compile("math.bitAnd(9223372036854775807,9223372036854775809)").getAst()); assertThat(e) .hasMessageThat() @@ -987,9 +917,9 @@ public void bitAnd_maxValArg_throwsException() { @TestParameters("{expr: 'math.bitOr(1,2)' , expectedResult: 3}") @TestParameters("{expr: 'math.bitOr(1,-1)' , expectedResult: -1}") public void bitOr_signedInt_success(String expr, long expectedResult) throws Exception { - CelAbstractSyntaxTree ast = CEL_COMPILER.compile(expr).getAst(); + CelAbstractSyntaxTree ast = cel.compile(expr).getAst(); - Object result = CEL_RUNTIME.createProgram(ast).eval(); + Object result = cel.createProgram(ast).eval(); assertThat(result).isEqualTo(expectedResult); } @@ -998,9 +928,9 @@ public void bitOr_signedInt_success(String expr, long expectedResult) throws Exc @TestParameters("{expr: 'math.bitOr(1u,2u)' , expectedResult: 3}") @TestParameters("{expr: 'math.bitOr(1090u,3u)' , expectedResult: 1091}") public void bitOr_unSignedInt_success(String expr, UnsignedLong expectedResult) throws Exception { - CelAbstractSyntaxTree ast = CEL_UNSIGNED_COMPILER.compile(expr).getAst(); + CelAbstractSyntaxTree ast = cel.compile(expr).getAst(); - Object result = CEL_UNSIGNED_RUNTIME.createProgram(ast).eval(); + Object result = cel.createProgram(ast).eval(); assertThat(result).isEqualTo(expectedResult); } @@ -1011,7 +941,7 @@ public void bitOr_unSignedInt_success(String expr, UnsignedLong expectedResult) @TestParameters("{expr: 'math.bitOr(1)'}") public void bitOr_invalidArgs_throwsException(String expr) { CelValidationException e = - assertThrows(CelValidationException.class, () -> CEL_COMPILER.compile(expr).getAst()); + assertThrows(CelValidationException.class, () -> cel.compile(expr).getAst()); assertThat(e).hasMessageThat().contains("found no matching overload for 'math.bitOr'"); } @@ -1020,9 +950,9 @@ public void bitOr_invalidArgs_throwsException(String expr) { @TestParameters("{expr: 'math.bitXor(1,2)' , expectedResult: 3}") @TestParameters("{expr: 'math.bitXor(3,5)' , expectedResult: 6}") public void bitXor_signedInt_success(String expr, long expectedResult) throws Exception { - CelAbstractSyntaxTree ast = CEL_COMPILER.compile(expr).getAst(); + CelAbstractSyntaxTree ast = cel.compile(expr).getAst(); - Object result = CEL_RUNTIME.createProgram(ast).eval(); + Object result = cel.createProgram(ast).eval(); assertThat(result).isEqualTo(expectedResult); } @@ -1032,9 +962,9 @@ public void bitXor_signedInt_success(String expr, long expectedResult) throws Ex @TestParameters("{expr: 'math.bitXor(3u, 5u)' , expectedResult: 6}") public void bitXor_unSignedInt_success(String expr, UnsignedLong expectedResult) throws Exception { - CelAbstractSyntaxTree ast = CEL_UNSIGNED_COMPILER.compile(expr).getAst(); + CelAbstractSyntaxTree ast = cel.compile(expr).getAst(); - Object result = CEL_UNSIGNED_RUNTIME.createProgram(ast).eval(); + Object result = cel.createProgram(ast).eval(); assertThat(result).isEqualTo(expectedResult); } @@ -1045,7 +975,7 @@ public void bitXor_unSignedInt_success(String expr, UnsignedLong expectedResult) @TestParameters("{expr: 'math.bitXor(1)'}") public void bitXor_invalidArgs_throwsException(String expr) { CelValidationException e = - assertThrows(CelValidationException.class, () -> CEL_COMPILER.compile(expr).getAst()); + assertThrows(CelValidationException.class, () -> cel.compile(expr).getAst()); assertThat(e).hasMessageThat().contains("found no matching overload for 'math.bitXor'"); } @@ -1055,9 +985,9 @@ public void bitXor_invalidArgs_throwsException(String expr) { @TestParameters("{expr: 'math.bitNot(0)' , expectedResult: -1}") @TestParameters("{expr: 'math.bitNot(-1)' , expectedResult: 0}") public void bitNot_signedInt_success(String expr, long expectedResult) throws Exception { - CelAbstractSyntaxTree ast = CEL_COMPILER.compile(expr).getAst(); + CelAbstractSyntaxTree ast = cel.compile(expr).getAst(); - Object result = CEL_RUNTIME.createProgram(ast).eval(); + Object result = cel.createProgram(ast).eval(); assertThat(result).isEqualTo(expectedResult); } @@ -1067,9 +997,9 @@ public void bitNot_signedInt_success(String expr, long expectedResult) throws Ex @TestParameters("{expr: 'math.bitNot(12310u)' , expectedResult: 18446744073709539305}") public void bitNot_unSignedInt_success(String expr, UnsignedLong expectedResult) throws Exception { - CelAbstractSyntaxTree ast = CEL_UNSIGNED_COMPILER.compile(expr).getAst(); + CelAbstractSyntaxTree ast = cel.compile(expr).getAst(); - Object result = CEL_UNSIGNED_RUNTIME.createProgram(ast).eval(); + Object result = cel.createProgram(ast).eval(); assertThat(result).isEqualTo(expectedResult); } @@ -1080,7 +1010,7 @@ public void bitNot_unSignedInt_success(String expr, UnsignedLong expectedResult) @TestParameters("{expr: 'math.bitNot(\"\")'}") public void bitNot_invalidArgs_throwsException(String expr) { CelValidationException e = - assertThrows(CelValidationException.class, () -> CEL_COMPILER.compile(expr).getAst()); + assertThrows(CelValidationException.class, () -> cel.compile(expr).getAst()); assertThat(e).hasMessageThat().contains("found no matching overload for 'math.bitNot'"); } @@ -1090,9 +1020,9 @@ public void bitNot_invalidArgs_throwsException(String expr) { @TestParameters("{expr: 'math.bitShiftLeft(12121, 11)' , expectedResult: 24823808}") @TestParameters("{expr: 'math.bitShiftLeft(-1, 64)' , expectedResult: 0}") public void bitShiftLeft_signedInt_success(String expr, long expectedResult) throws Exception { - CelAbstractSyntaxTree ast = CEL_COMPILER.compile(expr).getAst(); + CelAbstractSyntaxTree ast = cel.compile(expr).getAst(); - Object result = CEL_RUNTIME.createProgram(ast).eval(); + Object result = cel.createProgram(ast).eval(); assertThat(result).isEqualTo(expectedResult); } @@ -1103,9 +1033,9 @@ public void bitShiftLeft_signedInt_success(String expr, long expectedResult) thr @TestParameters("{expr: 'math.bitShiftLeft(1u, 65)' , expectedResult: 0}") public void bitShiftLeft_unSignedInt_success(String expr, UnsignedLong expectedResult) throws Exception { - CelAbstractSyntaxTree ast = CEL_UNSIGNED_COMPILER.compile(expr).getAst(); + CelAbstractSyntaxTree ast = cel.compile(expr).getAst(); - Object result = CEL_UNSIGNED_RUNTIME.createProgram(ast).eval(); + Object result = cel.createProgram(ast).eval(); assertThat(result).isEqualTo(expectedResult); } @@ -1114,11 +1044,10 @@ public void bitShiftLeft_unSignedInt_success(String expr, UnsignedLong expectedR @TestParameters("{expr: 'math.bitShiftLeft(1, -2)'}") @TestParameters("{expr: 'math.bitShiftLeft(1u, -2)'}") public void bitShiftLeft_invalidArgs_throwsException(String expr) throws Exception { - CelAbstractSyntaxTree ast = CEL_COMPILER.compile(expr).getAst(); + CelAbstractSyntaxTree ast = cel.compile(expr).getAst(); CelEvaluationException e = - assertThrows( - CelEvaluationException.class, () -> CEL_UNSIGNED_RUNTIME.createProgram(ast).eval()); + assertThrows(CelEvaluationException.class, () -> cel.createProgram(ast).eval()); assertThat(e).hasMessageThat().contains("evaluation error"); assertThat(e).hasCauseThat().isInstanceOf(IllegalArgumentException.class); @@ -1131,9 +1060,9 @@ public void bitShiftLeft_invalidArgs_throwsException(String expr) throws Excepti @TestParameters("{expr: 'math.bitShiftRight(12121, 11)' , expectedResult: 5}") @TestParameters("{expr: 'math.bitShiftRight(-1, 64)' , expectedResult: 0}") public void bitShiftRight_signedInt_success(String expr, long expectedResult) throws Exception { - CelAbstractSyntaxTree ast = CEL_COMPILER.compile(expr).getAst(); + CelAbstractSyntaxTree ast = cel.compile(expr).getAst(); - Object result = CEL_RUNTIME.createProgram(ast).eval(); + Object result = cel.createProgram(ast).eval(); assertThat(result).isEqualTo(expectedResult); } @@ -1144,9 +1073,7 @@ public void bitShiftRight_signedInt_success(String expr, long expectedResult) th @TestParameters("{expr: 'math.bitShiftRight(1u, 65)' , expectedResult: 0}") public void bitShiftRight_unSignedInt_success(String expr, UnsignedLong expectedResult) throws Exception { - CelAbstractSyntaxTree ast = CEL_UNSIGNED_COMPILER.compile(expr).getAst(); - - Object result = CEL_UNSIGNED_RUNTIME.createProgram(ast).eval(); + Object result = eval(expr); assertThat(result).isEqualTo(expectedResult); } @@ -1155,11 +1082,7 @@ public void bitShiftRight_unSignedInt_success(String expr, UnsignedLong expected @TestParameters("{expr: 'math.bitShiftRight(23111u, -212)'}") @TestParameters("{expr: 'math.bitShiftRight(23, -212)'}") public void bitShiftRight_invalidArgs_throwsException(String expr) throws Exception { - CelAbstractSyntaxTree ast = CEL_COMPILER.compile(expr).getAst(); - - CelEvaluationException e = - assertThrows( - CelEvaluationException.class, () -> CEL_UNSIGNED_RUNTIME.createProgram(ast).eval()); + CelEvaluationException e = assertThrows(CelEvaluationException.class, () -> eval(expr)); assertThat(e).hasMessageThat().contains("evaluation error"); assertThat(e).hasCauseThat().isInstanceOf(IllegalArgumentException.class); @@ -1174,10 +1097,26 @@ public void bitShiftRight_invalidArgs_throwsException(String expr) throws Except @TestParameters("{expr: 'math.sqrt(1.0/0.0)', expectedResult: Infinity}") @TestParameters("{expr: 'math.sqrt(-1)', expectedResult: NaN}") public void sqrt_success(String expr, double expectedResult) throws Exception { - CelAbstractSyntaxTree ast = CEL_UNSIGNED_COMPILER.compile(expr).getAst(); - - Object result = CEL_UNSIGNED_RUNTIME.createProgram(ast).eval(); + Object result = eval(expr); assertThat(result).isEqualTo(expectedResult); } + + private Object eval(Cel cel, String expression, Map variables) throws Exception { + CelAbstractSyntaxTree ast; + if (isParseOnly) { + ast = cel.parse(expression).getAst(); + } else { + ast = cel.compile(expression).getAst(); + } + return cel.createProgram(ast).eval(variables); + } + + private Object eval(Cel celInstance, String expression) throws Exception { + return eval(celInstance, expression, ImmutableMap.of()); + } + + private Object eval(String expression) throws Exception { + return eval(this.cel, expression, ImmutableMap.of()); + } } diff --git a/extensions/src/test/java/dev/cel/extensions/CelProtoExtensionsTest.java b/extensions/src/test/java/dev/cel/extensions/CelProtoExtensionsTest.java index 2e55619db..f46ea5b1a 100644 --- a/extensions/src/test/java/dev/cel/extensions/CelProtoExtensionsTest.java +++ b/extensions/src/test/java/dev/cel/extensions/CelProtoExtensionsTest.java @@ -26,7 +26,6 @@ import com.google.testing.junit.testparameterinjector.TestParameterInjector; import com.google.testing.junit.testparameterinjector.TestParameters; import dev.cel.bundle.Cel; -import dev.cel.common.CelAbstractSyntaxTree; import dev.cel.common.CelContainer; import dev.cel.common.CelFunctionDecl; import dev.cel.common.CelOptions; @@ -41,34 +40,23 @@ import dev.cel.parser.CelMacro; import dev.cel.parser.CelStandardMacro; import dev.cel.runtime.CelFunctionBinding; -import dev.cel.testing.CelRuntimeFlavor; -import java.util.Map; import org.junit.Assume; -import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @RunWith(TestParameterInjector.class) -public final class CelProtoExtensionsTest { - - @TestParameter public CelRuntimeFlavor runtimeFlavor; - @TestParameter public boolean isParseOnly; - - private Cel cel; - - @Before - public void setUp() { - // Legacy runtime does not support parsed-only evaluation mode. - Assume.assumeFalse(runtimeFlavor.equals(CelRuntimeFlavor.LEGACY) && isParseOnly); - this.cel = - runtimeFlavor - .builder() - .addCompilerLibraries(CelExtensions.protos()) - .setStandardMacros(CelStandardMacro.STANDARD_MACROS) - .addFileTypes(TestAllTypesExtensions.getDescriptor()) - .addVar("msg", StructTypeReference.create("cel.expr.conformance.proto2.TestAllTypes")) - .setContainer(CelContainer.ofName("cel.expr.conformance.proto2")) - .build(); +public final class CelProtoExtensionsTest extends CelExtensionTestBase { + + @Override + protected Cel newCelEnv() { + return runtimeFlavor + .builder() + .addCompilerLibraries(CelExtensions.protos()) + .setStandardMacros(CelStandardMacro.STANDARD_MACROS) + .addFileTypes(TestAllTypesExtensions.getDescriptor()) + .addVar("msg", StructTypeReference.create("cel.expr.conformance.proto2.TestAllTypes")) + .setContainer(CelContainer.ofName("cel.expr.conformance.proto2")) + .build(); } private static final TestAllTypes PACKAGE_SCOPED_EXT_MSG = @@ -342,13 +330,5 @@ public void parseErrors(@TestParameter ParseErrorTestCase testcase) { assertThat(e).hasMessageThat().isEqualTo(testcase.error); } - private Object eval(String expression, Map variables) throws Exception { - return eval(this.cel, expression, variables); - } - private Object eval(Cel cel, String expression, Map variables) throws Exception { - CelAbstractSyntaxTree ast = - this.isParseOnly ? cel.parse(expression).getAst() : cel.compile(expression).getAst(); - return cel.createProgram(ast).eval(variables); - } } diff --git a/extensions/src/test/java/dev/cel/extensions/CelRegexExtensionsTest.java b/extensions/src/test/java/dev/cel/extensions/CelRegexExtensionsTest.java index 924344b25..97d0cc90c 100644 --- a/extensions/src/test/java/dev/cel/extensions/CelRegexExtensionsTest.java +++ b/extensions/src/test/java/dev/cel/extensions/CelRegexExtensionsTest.java @@ -21,35 +21,23 @@ import com.google.testing.junit.testparameterinjector.TestParameterInjector; import com.google.testing.junit.testparameterinjector.TestParameters; import dev.cel.bundle.Cel; -import dev.cel.common.CelAbstractSyntaxTree; import dev.cel.common.CelFunctionDecl; import dev.cel.common.CelOptions; import dev.cel.runtime.CelEvaluationException; -import dev.cel.testing.CelRuntimeFlavor; import java.util.Optional; -import org.junit.Assume; -import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @RunWith(TestParameterInjector.class) -public final class CelRegexExtensionsTest { - - @TestParameter public CelRuntimeFlavor runtimeFlavor; - @TestParameter public boolean isParseOnly; - - private Cel cel; - - @Before - public void setUp() { - // Legacy runtime does not support parsed-only evaluation mode. - Assume.assumeFalse(runtimeFlavor.equals(CelRuntimeFlavor.LEGACY) && isParseOnly); - this.cel = - runtimeFlavor - .builder() - .addCompilerLibraries(CelExtensions.regex()) - .addRuntimeLibraries(CelExtensions.regex()) - .build(); +public final class CelRegexExtensionsTest extends CelExtensionTestBase { + + @Override + protected Cel newCelEnv() { + return runtimeFlavor + .builder() + .addCompilerLibraries(CelExtensions.regex()) + .addRuntimeLibraries(CelExtensions.regex()) + .build(); } @@ -276,9 +264,5 @@ public void extractAll_multipleCaptureGroups_throwsException(String target, Stri .contains("Regular expression has more than one capturing group:"); } - private Object eval(String expr) throws Exception { - CelAbstractSyntaxTree ast = - isParseOnly ? cel.parse(expr).getAst() : cel.compile(expr).getAst(); - return cel.createProgram(ast).eval(); - } + } diff --git a/extensions/src/test/java/dev/cel/extensions/CelSetsExtensionsTest.java b/extensions/src/test/java/dev/cel/extensions/CelSetsExtensionsTest.java index 9007bba2e..091d456f5 100644 --- a/extensions/src/test/java/dev/cel/extensions/CelSetsExtensionsTest.java +++ b/extensions/src/test/java/dev/cel/extensions/CelSetsExtensionsTest.java @@ -23,7 +23,6 @@ import com.google.testing.junit.testparameterinjector.TestParameterInjector; import com.google.testing.junit.testparameterinjector.TestParameters; import dev.cel.bundle.Cel; -import dev.cel.bundle.CelBuilder; import dev.cel.common.CelAbstractSyntaxTree; import dev.cel.common.CelContainer; import dev.cel.common.CelFunctionDecl; @@ -39,27 +38,39 @@ import dev.cel.runtime.CelRuntime; import dev.cel.testing.CelRuntimeFlavor; import java.util.List; -import java.util.Map; import org.junit.Assume; -import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @RunWith(TestParameterInjector.class) -public final class CelSetsExtensionsTest { +public final class CelSetsExtensionsTest extends CelExtensionTestBase { private static final CelOptions CEL_OPTIONS = CelOptions.current().enableHeterogeneousNumericComparisons(true).build(); - @TestParameter public CelRuntimeFlavor runtimeFlavor; - @TestParameter public boolean isParseOnly; - - private Cel cel; - - @Before - public void setUp() { - // Legacy runtime does not support parsed-only evaluation mode. - Assume.assumeFalse(runtimeFlavor.equals(CelRuntimeFlavor.LEGACY) && isParseOnly); - this.cel = setupEnv(runtimeFlavor.builder()); + @Override + protected Cel newCelEnv() { + return runtimeFlavor + .builder() + .addMessageTypes(TestAllTypes.getDescriptor()) + .setOptions(CEL_OPTIONS) + .setContainer(CelContainer.ofName("cel.expr.conformance.proto3")) + .addCompilerLibraries(CelExtensions.sets(CEL_OPTIONS)) + .addRuntimeLibraries(CelExtensions.sets(CEL_OPTIONS)) + .addVar("list", ListType.create(SimpleType.INT)) + .addVar("subList", ListType.create(SimpleType.INT)) + .addFunctionDeclarations( + CelFunctionDecl.newFunctionDeclaration( + "new_int", + CelOverloadDecl.newGlobalOverload("new_int_int64", SimpleType.INT, SimpleType.INT))) + .addFunctionBindings( + CelFunctionBinding.fromOverloads( + "new_int", + CelFunctionBinding.from( + "new_int_int64", + Long.class, + // Intentionally return java.lang.Integer to test primitive type adaptation + Math::toIntExact))) + .build(); } @Test @@ -375,7 +386,7 @@ public void setsExtension_containsFunctionSubset_succeeds() throws Exception { .addRuntimeLibraries(setsExtensions) .build(); - Object evaluatedResult = eval(cel, "sets.contains([1, 2], [2])", ImmutableMap.of()); + Object evaluatedResult = eval(cel, "sets.contains([1, 2], [2])"); assertThat(evaluatedResult).isEqualTo(true); } @@ -391,7 +402,7 @@ public void setsExtension_equivalentFunctionSubset_succeeds() throws Exception { .addRuntimeLibraries(setsExtensions) .build(); - Object evaluatedResult = eval(cel, "sets.equivalent([1, 1], [1])", ImmutableMap.of()); + Object evaluatedResult = eval(cel, "sets.equivalent([1, 1], [1])"); assertThat(evaluatedResult).isEqualTo(true); } @@ -407,7 +418,7 @@ public void setsExtension_intersectsFunctionSubset_succeeds() throws Exception { .addRuntimeLibraries(setsExtensions) .build(); - Object evaluatedResult = eval(cel, "sets.intersects([1, 1], [1])", ImmutableMap.of()); + Object evaluatedResult = eval(cel, "sets.intersects([1, 1], [1])"); assertThat(evaluatedResult).isEqualTo(true); } @@ -450,45 +461,5 @@ public void setsExtension_evaluateUnallowedFunction_throws() throws Exception { } } - private Object eval(Cel cel, String expression, Map variables) throws Exception { - CelAbstractSyntaxTree ast; - if (isParseOnly) { - ast = cel.parse(expression).getAst(); - } else { - ast = cel.compile(expression).getAst(); - } - return cel.createProgram(ast).eval(variables); - } - - private Object eval(String expression) throws Exception { - return eval(this.cel, expression, ImmutableMap.of()); - } - - private Object eval(String expression, Map variables) throws Exception { - return eval(this.cel, expression, variables); - } - private static Cel setupEnv(CelBuilder celBuilder) { - return celBuilder - .addMessageTypes(TestAllTypes.getDescriptor()) - .setOptions(CEL_OPTIONS) - .setContainer(CelContainer.ofName("cel.expr.conformance.proto3")) - .addCompilerLibraries(CelExtensions.sets(CEL_OPTIONS)) - .addRuntimeLibraries(CelExtensions.sets(CEL_OPTIONS)) - .addVar("list", ListType.create(SimpleType.INT)) - .addVar("subList", ListType.create(SimpleType.INT)) - .addFunctionDeclarations( - CelFunctionDecl.newFunctionDeclaration( - "new_int", - CelOverloadDecl.newGlobalOverload("new_int_int64", SimpleType.INT, SimpleType.INT))) - .addFunctionBindings( - CelFunctionBinding.fromOverloads( - "new_int", - CelFunctionBinding.from( - "new_int_int64", - Long.class, - // Intentionally return java.lang.Integer to test primitive type adaptation - Math::toIntExact))) - .build(); - } } diff --git a/extensions/src/test/java/dev/cel/extensions/CelStringExtensionsTest.java b/extensions/src/test/java/dev/cel/extensions/CelStringExtensionsTest.java index e7542b7b7..4b242ddcd 100644 --- a/extensions/src/test/java/dev/cel/extensions/CelStringExtensionsTest.java +++ b/extensions/src/test/java/dev/cel/extensions/CelStringExtensionsTest.java @@ -33,40 +33,29 @@ import dev.cel.extensions.CelStringExtensions.Function; import dev.cel.runtime.CelEvaluationException; import dev.cel.runtime.CelRuntime; -import dev.cel.testing.CelRuntimeFlavor; import java.util.List; -import java.util.Map; import org.junit.Assume; -import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @RunWith(TestParameterInjector.class) -public final class CelStringExtensionsTest { - - @TestParameter public CelRuntimeFlavor runtimeFlavor; - @TestParameter public boolean isParseOnly; - - private Cel cel; - - @Before - public void setUp() { - // Legacy runtime does not support parsed-only evaluation mode. - Assume.assumeFalse(runtimeFlavor.equals(CelRuntimeFlavor.LEGACY) && isParseOnly); - this.cel = - runtimeFlavor - .builder() - .addCompilerLibraries(CelExtensions.strings()) - .addRuntimeLibraries(CelExtensions.strings()) - .addVar("s", SimpleType.STRING) - .addVar("separator", SimpleType.STRING) - .addVar("index", SimpleType.INT) - .addVar("offset", SimpleType.INT) - .addVar("indexOfParam", SimpleType.STRING) - .addVar("beginIndex", SimpleType.INT) - .addVar("endIndex", SimpleType.INT) - .addVar("limit", SimpleType.INT) - .build(); +public final class CelStringExtensionsTest extends CelExtensionTestBase { + + @Override + protected Cel newCelEnv() { + return runtimeFlavor + .builder() + .addCompilerLibraries(CelExtensions.strings()) + .addRuntimeLibraries(CelExtensions.strings()) + .addVar("s", SimpleType.STRING) + .addVar("separator", SimpleType.STRING) + .addVar("index", SimpleType.INT) + .addVar("offset", SimpleType.INT) + .addVar("indexOfParam", SimpleType.STRING) + .addVar("beginIndex", SimpleType.INT) + .addVar("endIndex", SimpleType.INT) + .addVar("limit", SimpleType.INT) + .build(); } @Test @@ -388,13 +377,10 @@ public void split_withLimit_separatorIsNonString_throwsException() { @Test public void split_withLimitOverflow_throwsException() throws Exception { + ImmutableMap variables = ImmutableMap.of("limit", 2147483648L); // INT_MAX + 1 CelEvaluationException exception = assertThrows( - CelEvaluationException.class, - () -> - eval( - "'test'.split('', limit)", - ImmutableMap.of("limit", 2147483648L))); // INT_MAX + 1 + CelEvaluationException.class, () -> eval("'test'.split('', limit)", variables)); assertThat(exception) .hasMessageThat() @@ -454,13 +440,10 @@ public void substring_beginAndEndIndex_unicode_success( @TestParameters("{string: '', beginIndex: 2}") public void substring_beginIndexOutOfRange_ascii_throwsException(String string, int beginIndex) throws Exception { + ImmutableMap variables = ImmutableMap.of("s", string, "beginIndex", beginIndex); CelEvaluationException exception = assertThrows( - CelEvaluationException.class, - () -> - eval( - "s.substring(beginIndex)", - ImmutableMap.of("s", string, "beginIndex", beginIndex))); + CelEvaluationException.class, () -> eval("s.substring(beginIndex)", variables)); String exceptionMessage = String.format( @@ -478,13 +461,10 @@ public void substring_beginIndexOutOfRange_ascii_throwsException(String string, @TestParameters("{string: '😁가나', beginIndex: 4, uniqueCharCount: 3}") public void substring_beginIndexOutOfRange_unicode_throwsException( String string, int beginIndex, int uniqueCharCount) throws Exception { + ImmutableMap variables = ImmutableMap.of("s", string, "beginIndex", beginIndex); CelEvaluationException exception = assertThrows( - CelEvaluationException.class, - () -> - eval( - "s.substring(beginIndex)", - ImmutableMap.of("s", string, "beginIndex", beginIndex))); + CelEvaluationException.class, () -> eval("s.substring(beginIndex)", variables)); String exceptionMessage = String.format( @@ -501,13 +481,12 @@ public void substring_beginIndexOutOfRange_unicode_throwsException( @TestParameters("{string: '😁😑😦', beginIndex: 2, endIndex: 1}") public void substring_beginAndEndIndexOutOfRange_throwsException( String string, int beginIndex, int endIndex) throws Exception { + ImmutableMap variables = + ImmutableMap.of("s", string, "beginIndex", beginIndex, "endIndex", endIndex); CelEvaluationException exception = assertThrows( CelEvaluationException.class, - () -> - eval( - "s.substring(beginIndex, endIndex)", - ImmutableMap.of("s", string, "beginIndex", beginIndex, "endIndex", endIndex))); + () -> eval("s.substring(beginIndex, endIndex)", variables)); String exceptionMessage = String.format("substring failure: Range [%d, %d) out of bounds", beginIndex, endIndex); @@ -516,13 +495,11 @@ public void substring_beginAndEndIndexOutOfRange_throwsException( @Test public void substring_beginIndexOverflow_throwsException() throws Exception { + ImmutableMap variables = + ImmutableMap.of("beginIndex", 2147483648L); // INT_MAX + 1 CelEvaluationException exception = assertThrows( - CelEvaluationException.class, - () -> - eval( - "'abcd'.substring(beginIndex)", - ImmutableMap.of("beginIndex", 2147483648L))); // INT_MAX + 1 + CelEvaluationException.class, () -> eval("'abcd'.substring(beginIndex)", variables)); assertThat(exception) .hasMessageThat() @@ -1381,10 +1358,7 @@ public void stringExtension_functionSubset_success() throws Exception { .build(); Object evaluatedResult = - eval( - customCel, - "'test'.substring(2) == 'st' && 'hello'.charAt(1) == 'e'", - ImmutableMap.of()); + eval(customCel, "'test'.substring(2) == 'st' && 'hello'.charAt(1) == 'e'"); assertThat(evaluatedResult).isEqualTo(true); } @@ -1499,21 +1473,5 @@ public void stringExtension_evaluateUnallowedFunction_throws() throws Exception assertThrows(CelEvaluationException.class, () -> customRuntimeCel.createProgram(ast).eval()); } - private Object eval(Cel cel, String expression, Map variables) throws Exception { - CelAbstractSyntaxTree ast; - if (isParseOnly) { - ast = cel.parse(expression).getAst(); - } else { - ast = cel.compile(expression).getAst(); - } - return cel.createProgram(ast).eval(variables); - } - - private Object eval(String expression) throws Exception { - return eval(this.cel, expression, ImmutableMap.of()); - } - private Object eval(String expression, Map variables) throws Exception { - return eval(this.cel, expression, variables); - } }