diff --git a/MODULE.bazel b/MODULE.bazel
index 0b67c825c..cb8c63393 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -46,7 +46,7 @@ TRUTH_VERSION = "1.4.4"
PROTOBUF_JAVA_VERSION = "4.33.5"
-CEL_VERSION = "0.12.0"
+CEL_VERSION = "0.13.0"
# Compile only artifacts
[
diff --git a/README.md b/README.md
index 40bd9deac..78e38961f 100644
--- a/README.md
+++ b/README.md
@@ -55,14 +55,14 @@ CEL-Java is available in Maven Central Repository. [Download the JARs here][8] o
dev.cel
cel
- 0.12.0
+ 0.13.0
```
**Gradle**
```gradle
-implementation 'dev.cel:cel:0.12.0'
+implementation 'dev.cel:cel:0.13.0'
```
Then run this example:
diff --git a/extensions/src/main/java/dev/cel/extensions/BUILD.bazel b/extensions/src/main/java/dev/cel/extensions/BUILD.bazel
index 2eb26846f..f8e4bfc8c 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",
],
)
@@ -121,7 +122,6 @@ java_library(
":extension_library",
"//checker:checker_builder",
"//common:compiler_common",
- "//common:options",
"//common/ast",
"//common/exceptions:numeric_overflow",
"//common/internal:comparison_functions",
diff --git a/extensions/src/main/java/dev/cel/extensions/CelEncoderExtensions.java b/extensions/src/main/java/dev/cel/extensions/CelEncoderExtensions.java
index a98f9db41..498b8555e 100644
--- a/extensions/src/main/java/dev/cel/extensions/CelEncoderExtensions.java
+++ b/extensions/src/main/java/dev/cel/extensions/CelEncoderExtensions.java
@@ -135,9 +135,13 @@ public void setRuntimeOptions(CelRuntimeBuilder runtimeBuilder) {
functions.forEach(
function -> {
if (celOptions.evaluateCanonicalTypesToNativeValues()) {
- runtimeBuilder.addFunctionBindings(function.nativeBytesFunctionBinding);
+ runtimeBuilder.addFunctionBindings(
+ CelFunctionBinding.fromOverloads(
+ function.getFunction(), function.nativeBytesFunctionBinding));
} else {
- runtimeBuilder.addFunctionBindings(function.protoBytesFunctionBinding);
+ runtimeBuilder.addFunctionBindings(
+ CelFunctionBinding.fromOverloads(
+ function.getFunction(), function.protoBytesFunctionBinding));
}
});
}
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 extends CelExtensionLibrary.FeatureSet> 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/main/java/dev/cel/extensions/CelStringExtensions.java b/extensions/src/main/java/dev/cel/extensions/CelStringExtensions.java
index 37c8270cc..2bb477b82 100644
--- a/extensions/src/main/java/dev/cel/extensions/CelStringExtensions.java
+++ b/extensions/src/main/java/dev/cel/extensions/CelStringExtensions.java
@@ -23,7 +23,6 @@
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Lists;
import com.google.errorprone.annotations.Immutable;
import dev.cel.checker.CelCheckerBuilder;
import dev.cel.common.CelFunctionDecl;
@@ -37,7 +36,6 @@
import dev.cel.runtime.CelFunctionBinding;
import dev.cel.runtime.CelRuntimeBuilder;
import dev.cel.runtime.CelRuntimeLibrary;
-import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@@ -475,7 +473,7 @@ private static String quote(String s) {
sb.append('"');
for (int i = 0; i < s.length(); ) {
int codePoint = s.codePointAt(i);
- if (isMalformedUtf16(s, i, codePoint)) {
+ if (isMalformedUtf16(s, i)) {
sb.append('\uFFFD');
i++;
continue;
@@ -518,7 +516,7 @@ private static String quote(String s) {
return sb.toString();
}
- private static boolean isMalformedUtf16(String s, int index, int codePoint) {
+ private static boolean isMalformedUtf16(String s, int index) {
char currentChar = s.charAt(index);
if (Character.isLowSurrogate(currentChar)) {
return true;
@@ -587,14 +585,14 @@ private static String reverse(String s) {
return new StringBuilder(s).reverse().toString();
}
- private static List split(String str, String separator) {
+ private static ImmutableList split(String str, String separator) {
return split(str, separator, Integer.MAX_VALUE);
}
/**
* @param args Object array with indices of: [0: string], [1: separator], [2: limit]
*/
- private static List split(Object[] args) throws CelEvaluationException {
+ private static ImmutableList split(Object[] args) throws CelEvaluationException {
long limitInLong = (Long) args[2];
int limit;
try {
@@ -609,16 +607,14 @@ private static List split(Object[] args) throws CelEvaluationException {
return split((String) args[0], (String) args[1], limit);
}
- /** Returns a **mutable** list of strings split on the separator */
- private static List split(String str, String separator, int limit) {
+ /** Returns an immutable list of strings split on the separator */
+ private static ImmutableList split(String str, String separator, int limit) {
if (limit == 0) {
- return new ArrayList<>();
+ return ImmutableList.of();
}
if (limit == 1) {
- List singleElementList = new ArrayList<>();
- singleElementList.add(str);
- return singleElementList;
+ return ImmutableList.of(str);
}
if (limit < 0) {
@@ -630,7 +626,7 @@ private static List split(String str, String separator, int limit) {
}
Iterable splitString = Splitter.on(separator).limit(limit).split(str);
- return Lists.newArrayList(splitString);
+ return ImmutableList.copyOf(splitString);
}
/**
@@ -643,8 +639,8 @@ private static List split(String str, String separator, int limit) {
* This exists because neither the built-in String.split nor Guava's splitter is able to deal
* with separating single printable characters.
*/
- private static List explode(String str, int limit) {
- List exploded = new ArrayList<>();
+ private static ImmutableList explode(String str, int limit) {
+ ImmutableList.Builder exploded = ImmutableList.builder();
CelCodePointArray codePointArray = CelCodePointArray.fromString(str);
if (limit > 0) {
limit -= 1;
@@ -656,7 +652,7 @@ private static List explode(String str, int limit) {
if (codePointArray.length() > limit) {
exploded.add(codePointArray.slice(limit, codePointArray.length()).toString());
}
- return exploded;
+ return exploded.build();
}
private static Object substring(String s, long i) throws CelEvaluationException {
diff --git a/extensions/src/main/java/dev/cel/extensions/README.md b/extensions/src/main/java/dev/cel/extensions/README.md
index c3fbf8c54..b1d3611b4 100644
--- a/extensions/src/main/java/dev/cel/extensions/README.md
+++ b/extensions/src/main/java/dev/cel/extensions/README.md
@@ -522,7 +522,7 @@ Examples:
### Split
-Returns a mutable list of strings split from the input by the given separator. The
+Returns a list of strings split from the input by the given separator. The
function accepts an optional argument specifying a limit on the number of
substrings produced by the split.
@@ -1069,4 +1069,4 @@ Examples:
{valueVar: indexVar}) // returns {1:0, 2:1, 3:2}
{'greeting': 'aloha', 'farewell': 'aloha'}
- .transformMapEntry(k, v, {v: k}) // error, duplicate key
\ No newline at end of file
+ .transformMapEntry(k, v, {v: k}) // error, duplicate key
diff --git a/extensions/src/main/java/dev/cel/extensions/SetsExtensionsRuntimeImpl.java b/extensions/src/main/java/dev/cel/extensions/SetsExtensionsRuntimeImpl.java
index a42fba189..a02fdba8a 100644
--- a/extensions/src/main/java/dev/cel/extensions/SetsExtensionsRuntimeImpl.java
+++ b/extensions/src/main/java/dev/cel/extensions/SetsExtensionsRuntimeImpl.java
@@ -45,28 +45,34 @@ ImmutableSet newFunctionBindings() {
for (SetsFunction function : functions) {
switch (function) {
case CONTAINS:
- bindingBuilder.add(
- CelFunctionBinding.from(
- "list_sets_contains_list",
- Collection.class,
- Collection.class,
- this::containsAll));
+ bindingBuilder.addAll(
+ CelFunctionBinding.fromOverloads(
+ function.getFunction(),
+ CelFunctionBinding.from(
+ "list_sets_contains_list",
+ Collection.class,
+ Collection.class,
+ this::containsAll)));
break;
case EQUIVALENT:
- bindingBuilder.add(
- CelFunctionBinding.from(
- "list_sets_equivalent_list",
- Collection.class,
- Collection.class,
- (listA, listB) -> containsAll(listA, listB) && containsAll(listB, listA)));
+ bindingBuilder.addAll(
+ CelFunctionBinding.fromOverloads(
+ function.getFunction(),
+ CelFunctionBinding.from(
+ "list_sets_equivalent_list",
+ Collection.class,
+ Collection.class,
+ (listA, listB) -> containsAll(listA, listB) && containsAll(listB, listA))));
break;
case INTERSECTS:
- bindingBuilder.add(
- CelFunctionBinding.from(
- "list_sets_intersects_list",
- Collection.class,
- Collection.class,
- this::setIntersects));
+ bindingBuilder.addAll(
+ CelFunctionBinding.fromOverloads(
+ function.getFunction(),
+ CelFunctionBinding.from(
+ "list_sets_intersects_list",
+ Collection.class,
+ Collection.class,
+ this::setIntersects)));
break;
}
}
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 374178540..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;
@@ -28,6 +27,7 @@
import dev.cel.common.CelFunctionDecl;
import dev.cel.common.CelOptions;
import dev.cel.common.CelValidationException;
+import dev.cel.common.CelValidationResult;
import dev.cel.common.exceptions.CelAttributeNotFoundException;
import dev.cel.common.exceptions.CelDivideByZeroException;
import dev.cel.common.exceptions.CelIndexOutOfBoundsException;
@@ -39,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()
@@ -56,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();
@@ -312,8 +302,8 @@ public void unparseAST_twoVarComprehension(
+ " err: 'no matching overload'}")
public void twoVarComprehension_compilerErrors(String expr, String err) throws Exception {
Assume.assumeFalse(isParseOnly);
- CelValidationException e =
- assertThrows(CelValidationException.class, () -> cel.compile(expr).getAst());
+ CelValidationResult result = cel.compile(expr);
+ CelValidationException e = assertThrows(CelValidationException.class, () -> result.getAst());
assertThat(e).hasMessageThat().contains(err);
}
@@ -375,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 7eed3dd5a..afeaa9105 100644
--- a/extensions/src/test/java/dev/cel/extensions/CelEncoderExtensionsTest.java
+++ b/extensions/src/test/java/dev/cel/extensions/CelEncoderExtensionsTest.java
@@ -20,35 +20,32 @@
import com.google.common.collect.ImmutableMap;
import com.google.testing.junit.testparameterinjector.TestParameterInjector;
-import dev.cel.common.CelAbstractSyntaxTree;
+import dev.cel.bundle.Cel;
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.compiler.CelCompiler;
-import dev.cel.compiler.CelCompilerFactory;
import dev.cel.runtime.CelEvaluationException;
-import dev.cel.runtime.CelRuntime;
-import dev.cel.runtime.CelRuntimeFactory;
+import org.junit.Assume;
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().build();
-
- private static final CelCompiler CEL_COMPILER =
- CelCompilerFactory.standardCelCompilerBuilder()
- .addVar("stringVar", SimpleType.STRING)
- .addLibraries(CelExtensions.encoders(CEL_OPTIONS))
- .build();
- private static final CelRuntime CEL_RUNTIME =
- CelRuntimeFactory.standardCelRuntimeBuilder()
- .setOptions(CEL_OPTIONS)
- .addLibraries(CelExtensions.encoders(CEL_OPTIONS))
- .build();
+ CelOptions.current().enableHeterogeneousNumericComparisons(true).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
public void library() {
@@ -63,22 +60,14 @@ public void library() {
@Test
public void encode_success() throws Exception {
- String encodedBytes =
- (String)
- CEL_RUNTIME
- .createProgram(CEL_COMPILER.compile("base64.encode(b'hello')").getAst())
- .eval();
+ String encodedBytes = (String) eval("base64.encode(b'hello')");
assertThat(encodedBytes).isEqualTo("aGVsbG8=");
}
@Test
public void decode_success() throws Exception {
- CelByteString decodedBytes =
- (CelByteString)
- CEL_RUNTIME
- .createProgram(CEL_COMPILER.compile("base64.decode('aGVsbG8=')").getAst())
- .eval();
+ CelByteString decodedBytes = (CelByteString) eval("base64.decode('aGVsbG8=')");
assertThat(decodedBytes.size()).isEqualTo(5);
assertThat(new String(decodedBytes.toByteArray(), ISO_8859_1)).isEqualTo("hello");
@@ -86,12 +75,7 @@ public void decode_success() throws Exception {
@Test
public void decode_withoutPadding_success() throws Exception {
- CelByteString decodedBytes =
- (CelByteString)
- CEL_RUNTIME
- // RFC2045 6.8, padding can be ignored.
- .createProgram(CEL_COMPILER.compile("base64.decode('aGVsbG8')").getAst())
- .eval();
+ CelByteString decodedBytes = (CelByteString) eval("base64.decode('aGVsbG8')");
assertThat(decodedBytes.size()).isEqualTo(5);
assertThat(new String(decodedBytes.toByteArray(), ISO_8859_1)).isEqualTo("hello");
@@ -99,50 +83,42 @@ public void decode_withoutPadding_success() throws Exception {
@Test
public void roundTrip_success() throws Exception {
- String encodedString =
- (String)
- CEL_RUNTIME
- .createProgram(CEL_COMPILER.compile("base64.encode(b'Hello World!')").getAst())
- .eval();
+ String encodedString = (String) eval("base64.encode(b'Hello World!')");
CelByteString decodedBytes =
(CelByteString)
- CEL_RUNTIME
- .createProgram(CEL_COMPILER.compile("base64.decode(stringVar)").getAst())
- .eval(ImmutableMap.of("stringVar", encodedString));
+ eval("base64.decode(stringVar)", ImmutableMap.of("stringVar", encodedString));
assertThat(new String(decodedBytes.toByteArray(), ISO_8859_1)).isEqualTo("Hello World!");
}
@Test
public void encode_invalidParam_throwsCompilationException() {
+ Assume.assumeFalse(isParseOnly);
CelValidationException e =
assertThrows(
- CelValidationException.class,
- () -> CEL_COMPILER.compile("base64.encode('hello')").getAst());
+ CelValidationException.class, () -> cel.compile("base64.encode('hello')").getAst());
assertThat(e).hasMessageThat().contains("found no matching overload for 'base64.encode'");
}
@Test
public void decode_invalidParam_throwsCompilationException() {
+ Assume.assumeFalse(isParseOnly);
CelValidationException e =
assertThrows(
- CelValidationException.class,
- () -> CEL_COMPILER.compile("base64.decode(b'aGVsbG8=')").getAst());
+ CelValidationException.class, () -> cel.compile("base64.decode(b'aGVsbG8=')").getAst());
assertThat(e).hasMessageThat().contains("found no matching overload for 'base64.decode'");
}
@Test
public void decode_malformedBase64Char_throwsEvaluationException() throws Exception {
- CelAbstractSyntaxTree ast = CEL_COMPILER.compile("base64.decode('z!')").getAst();
-
CelEvaluationException e =
- assertThrows(CelEvaluationException.class, () -> CEL_RUNTIME.createProgram(ast).eval());
+ assertThrows(CelEvaluationException.class, () -> eval("base64.decode('z!')"));
- assertThat(e)
- .hasMessageThat()
- .contains("Function 'base64_decode_string' failed with arg(s) 'z!'");
+ assertThat(e).hasMessageThat().contains("failed with arg(s) 'z!'");
assertThat(e).hasCauseThat().hasMessageThat().contains("Illegal base64 character");
}
+
+
}
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 b36e0e92e..4520f81ba 100644
--- a/extensions/src/test/java/dev/cel/extensions/CelListsExtensionsTest.java
+++ b/extensions/src/test/java/dev/cel/extensions/CelListsExtensionsTest.java
@@ -19,37 +19,35 @@
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;
import dev.cel.common.types.SimpleType;
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
@@ -146,7 +144,7 @@ public void flatten_negativeDepth_throws() {
CelEvaluationException e =
assertThrows(CelEvaluationException.class, () -> eval(cel, "[1,2,3,4].flatten(-1)"));
- if (isParseOnly) {
+ if (runtimeFlavor.equals(CelRuntimeFlavor.PLANNER)) {
assertThat(e)
.hasMessageThat()
.contains("evaluation error at :17: Function 'flatten' failed");
@@ -300,10 +298,8 @@ public void sortBy_success(String expression, String expected) throws Exception
+ "expectedError: 'variable name must be a simple identifier'}")
public void sortBy_throws_validationException(String expression, String expectedError)
throws Exception {
- assertThat(
- assertThrows(
- CelValidationException.class,
- () -> cel.createProgram(cel.compile(expression).getAst()).eval()))
+ CelValidationResult result = cel.compile(expression);
+ assertThat(assertThrows(CelValidationException.class, () -> result.getAst()))
.hasMessageThat()
.contains(expectedError);
}
@@ -323,23 +319,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 1aac5a023..091d456f5 100644
--- a/extensions/src/test/java/dev/cel/extensions/CelSetsExtensionsTest.java
+++ b/extensions/src/test/java/dev/cel/extensions/CelSetsExtensionsTest.java
@@ -19,8 +19,10 @@
import com.google.common.collect.ImmutableList;
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;
+import dev.cel.bundle.Cel;
import dev.cel.common.CelAbstractSyntaxTree;
import dev.cel.common.CelContainer;
import dev.cel.common.CelFunctionDecl;
@@ -30,47 +32,46 @@
import dev.cel.common.CelValidationResult;
import dev.cel.common.types.ListType;
import dev.cel.common.types.SimpleType;
-import dev.cel.compiler.CelCompiler;
-import dev.cel.compiler.CelCompilerFactory;
import dev.cel.expr.conformance.proto3.TestAllTypes;
import dev.cel.runtime.CelEvaluationException;
import dev.cel.runtime.CelFunctionBinding;
import dev.cel.runtime.CelRuntime;
-import dev.cel.runtime.CelRuntimeFactory;
+import dev.cel.testing.CelRuntimeFlavor;
import java.util.List;
+import org.junit.Assume;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(TestParameterInjector.class)
-public final class CelSetsExtensionsTest {
- private static final CelOptions CEL_OPTIONS = CelOptions.current().build();
- private static final CelCompiler COMPILER =
- CelCompilerFactory.standardCelCompilerBuilder()
- .addMessageTypes(TestAllTypes.getDescriptor())
- .setOptions(CEL_OPTIONS)
- .setContainer(CelContainer.ofName("cel.expr.conformance.proto3"))
- .addLibraries(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)))
- .build();
-
- private static final CelRuntime RUNTIME =
- CelRuntimeFactory.standardCelRuntimeBuilder()
- .addMessageTypes(TestAllTypes.getDescriptor())
- .addLibraries(CelExtensions.sets(CEL_OPTIONS))
- .setOptions(CEL_OPTIONS)
- .addFunctionBindings(
- CelFunctionBinding.from(
- "new_int_int64",
- Long.class,
- // Intentionally return java.lang.Integer to test primitive type adaptation
- Math::toIntExact))
- .build();
+public final class CelSetsExtensionsTest extends CelExtensionTestBase {
+ private static final CelOptions CEL_OPTIONS =
+ CelOptions.current().enableHeterogeneousNumericComparisons(true).build();
+
+ @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
public void library() {
@@ -87,22 +88,14 @@ public void library() {
public void contains_integerListWithSameValue_succeeds() throws Exception {
ImmutableList list = ImmutableList.of(1, 2, 3, 4);
ImmutableList subList = ImmutableList.of(1, 2, 3, 4);
- CelAbstractSyntaxTree ast = COMPILER.compile("sets.contains(list, subList)").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- Object result = program.eval(ImmutableMap.of("list", list, "subList", subList));
-
- assertThat(result).isEqualTo(true);
+ assertThat(
+ eval("sets.contains(list, subList)", ImmutableMap.of("list", list, "subList", subList)))
+ .isEqualTo(true);
}
@Test
public void contains_integerListAsExpression_succeeds() throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("sets.contains([1, 1], [1])").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- Object result = program.eval();
-
- assertThat(result).isEqualTo(true);
+ assertThat(eval("sets.contains([1, 1], [1])")).isEqualTo(true);
}
@Test
@@ -119,12 +112,7 @@ public void contains_integerListAsExpression_succeeds() throws Exception {
+ " [TestAllTypes{single_int64: 2, single_uint64: 3u}])', expected: false}")
public void contains_withProtoMessage_succeeds(String expression, boolean expected)
throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile(expression).getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- boolean result = (boolean) program.eval();
-
- assertThat(result).isEqualTo(expected);
+ assertThat(eval(expression)).isEqualTo(expected);
}
@Test
@@ -133,12 +121,7 @@ public void contains_withProtoMessage_succeeds(String expression, boolean expect
@TestParameters("{expression: 'sets.contains([new_int(2)], [1])', expected: false}")
public void contains_withFunctionReturningInteger_succeeds(String expression, boolean expected)
throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile(expression).getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- boolean result = (boolean) program.eval();
-
- assertThat(result).isEqualTo(expected);
+ assertThat(eval(expression)).isEqualTo(expected);
}
@Test
@@ -157,12 +140,9 @@ public void contains_withFunctionReturningInteger_succeeds(String expression, bo
@TestParameters("{list: [1], subList: [1, 2], expected: false}")
public void contains_withIntTypes_succeeds(
List list, List subList, boolean expected) throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("sets.contains(list, subList)").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- Object result = program.eval(ImmutableMap.of("list", list, "subList", subList));
-
- assertThat(result).isEqualTo(expected);
+ assertThat(
+ eval("sets.contains(list, subList)", ImmutableMap.of("list", list, "subList", subList)))
+ .isEqualTo(expected);
}
@Test
@@ -177,12 +157,9 @@ public void contains_withIntTypes_succeeds(
@TestParameters("{list: [2, 3.0], subList: [2, 3], expected: true}")
public void contains_withDoubleTypes_succeeds(
List list, List subList, boolean expected) throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("sets.contains(list, subList)").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- Object result = program.eval(ImmutableMap.of("list", list, "subList", subList));
-
- assertThat(result).isEqualTo(expected);
+ assertThat(
+ eval("sets.contains(list, subList)", ImmutableMap.of("list", list, "subList", subList)))
+ .isEqualTo(expected);
}
@Test
@@ -193,12 +170,7 @@ public void contains_withDoubleTypes_succeeds(
@TestParameters("{expression: 'sets.contains([[1], [2, 3.0]], [[2, 3]])', expected: true}")
public void contains_withNestedLists_succeeds(String expression, boolean expected)
throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile(expression).getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- Object result = program.eval();
-
- assertThat(result).isEqualTo(expected);
+ assertThat(eval(expression)).isEqualTo(expected);
}
@Test
@@ -206,19 +178,16 @@ public void contains_withNestedLists_succeeds(String expression, boolean expecte
@TestParameters("{expression: 'sets.contains([1], [1, \"1\"])', expected: false}")
public void contains_withMixingIntAndString_succeeds(String expression, boolean expected)
throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile(expression).getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- Object result = program.eval();
-
- assertThat(result).isEqualTo(expected);
+ assertThat(eval(expression)).isEqualTo(expected);
}
@Test
- @TestParameters("{expression: 'sets.contains([1], [\"1\"])'}")
- @TestParameters("{expression: 'sets.contains([\"1\"], [1])'}")
- public void contains_withMixingIntAndString_throwsException(String expression) throws Exception {
- CelValidationResult invalidData = COMPILER.compile(expression);
+ public void contains_withMixingIntAndString_throwsException(
+ @TestParameter({"sets.contains([1], [\"1\"])", "sets.contains([\"1\"], [1])"})
+ String expression)
+ throws Exception {
+ Assume.assumeFalse(isParseOnly);
+ CelValidationResult invalidData = cel.compile(expression);
assertThat(invalidData.getErrors()).hasSize(1);
assertThat(invalidData.getErrors().get(0).getMessage())
@@ -227,12 +196,7 @@ public void contains_withMixingIntAndString_throwsException(String expression) t
@Test
public void contains_withMixedValues_succeeds() throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("sets.contains([1, 2], [2u, 2.0])").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- Object result = program.eval();
-
- assertThat(result).isEqualTo(true);
+ assertThat(eval("sets.contains([1, 2], [2u, 2.0])")).isEqualTo(true);
}
@Test
@@ -249,12 +213,7 @@ public void contains_withMixedValues_succeeds() throws Exception {
"{expression: 'sets.contains([[[[[[5]]]]]], [[1], [2, 3.0], [[[[[5]]]]]])', expected: false}")
public void contains_withMultiLevelNestedList_succeeds(String expression, boolean expected)
throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile(expression).getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- Object result = program.eval();
-
- assertThat(result).isEqualTo(expected);
+ assertThat(eval(expression)).isEqualTo(expected);
}
@Test
@@ -269,12 +228,7 @@ public void contains_withMultiLevelNestedList_succeeds(String expression, boolea
+ " false}")
public void contains_withMapValues_succeeds(String expression, boolean expected)
throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile(expression).getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- boolean result = (boolean) program.eval();
-
- assertThat(result).isEqualTo(expected);
+ assertThat(eval(expression)).isEqualTo(expected);
}
@Test
@@ -289,12 +243,7 @@ public void contains_withMapValues_succeeds(String expression, boolean expected)
@TestParameters("{expression: 'sets.equivalent([1, 2], [2, 2, 2])', expected: false}")
public void equivalent_withIntTypes_succeeds(String expression, boolean expected)
throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile(expression).getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- Object result = program.eval();
-
- assertThat(result).isEqualTo(expected);
+ assertThat(eval(expression)).isEqualTo(expected);
}
@Test
@@ -308,12 +257,7 @@ public void equivalent_withIntTypes_succeeds(String expression, boolean expected
@TestParameters("{expression: 'sets.equivalent([1, 2], [1u, 2, 2.3])', expected: false}")
public void equivalent_withMixedTypes_succeeds(String expression, boolean expected)
throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile(expression).getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- Object result = program.eval();
-
- assertThat(result).isEqualTo(expected);
+ assertThat(eval(expression)).isEqualTo(expected);
}
@Test
@@ -338,12 +282,7 @@ public void equivalent_withMixedTypes_succeeds(String expression, boolean expect
+ " [TestAllTypes{single_int64: 2, single_uint64: 3u}])', expected: false}")
public void equivalent_withProtoMessage_succeeds(String expression, boolean expected)
throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile(expression).getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- boolean result = (boolean) program.eval();
-
- assertThat(result).isEqualTo(expected);
+ assertThat(eval(expression)).isEqualTo(expected);
}
@Test
@@ -361,12 +300,7 @@ public void equivalent_withProtoMessage_succeeds(String expression, boolean expe
+ " expected: false}")
public void equivalent_withMapValues_succeeds(String expression, boolean expected)
throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile(expression).getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- boolean result = (boolean) program.eval();
-
- assertThat(result).isEqualTo(expected);
+ assertThat(eval(expression)).isEqualTo(expected);
}
@Test
@@ -391,12 +325,7 @@ public void equivalent_withMapValues_succeeds(String expression, boolean expecte
@TestParameters("{expression: 'sets.intersects([1], [1.1, 2u])', expected: false}")
public void intersects_withMixedTypes_succeeds(String expression, boolean expected)
throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile(expression).getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- Object result = program.eval();
-
- assertThat(result).isEqualTo(expected);
+ assertThat(eval(expression)).isEqualTo(expected);
}
@Test
@@ -414,12 +343,11 @@ public void intersects_withMixedTypes_succeeds(String expression, boolean expect
@TestParameters("{expression: 'sets.intersects([{2: 1}], [{1: 1}])', expected: false}")
public void intersects_withMapValues_succeeds(String expression, boolean expected)
throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile(expression).getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- boolean result = (boolean) program.eval();
+ // The LEGACY runtime is not spec compliant, because decimal keys are not allowed for maps.
+ Assume.assumeFalse(
+ runtimeFlavor.equals(CelRuntimeFlavor.PLANNER) && expression.contains("1.0:"));
- assertThat(result).isEqualTo(expected);
+ assertThat(eval(expression)).isEqualTo(expected);
}
@Test
@@ -444,25 +372,21 @@ public void intersects_withMapValues_succeeds(String expression, boolean expecte
+ " [TestAllTypes{single_int64: 2, single_uint64: 3u}])', expected: false}")
public void intersects_withProtoMessage_succeeds(String expression, boolean expected)
throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile(expression).getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- boolean result = (boolean) program.eval();
-
- assertThat(result).isEqualTo(expected);
+ assertThat(eval(expression)).isEqualTo(expected);
}
@Test
public void setsExtension_containsFunctionSubset_succeeds() throws Exception {
CelSetsExtensions setsExtensions =
CelExtensions.sets(CelOptions.DEFAULT, SetsFunction.CONTAINS);
- CelCompiler celCompiler =
- CelCompilerFactory.standardCelCompilerBuilder().addLibraries(setsExtensions).build();
- CelRuntime celRuntime =
- CelRuntimeFactory.standardCelRuntimeBuilder().addLibraries(setsExtensions).build();
+ Cel cel =
+ runtimeFlavor
+ .builder()
+ .addCompilerLibraries(setsExtensions)
+ .addRuntimeLibraries(setsExtensions)
+ .build();
- Object evaluatedResult =
- celRuntime.createProgram(celCompiler.compile("sets.contains([1, 2], [2])").getAst()).eval();
+ Object evaluatedResult = eval(cel, "sets.contains([1, 2], [2])");
assertThat(evaluatedResult).isEqualTo(true);
}
@@ -471,15 +395,14 @@ public void setsExtension_containsFunctionSubset_succeeds() throws Exception {
public void setsExtension_equivalentFunctionSubset_succeeds() throws Exception {
CelSetsExtensions setsExtensions =
CelExtensions.sets(CelOptions.DEFAULT, SetsFunction.EQUIVALENT);
- CelCompiler celCompiler =
- CelCompilerFactory.standardCelCompilerBuilder().addLibraries(setsExtensions).build();
- CelRuntime celRuntime =
- CelRuntimeFactory.standardCelRuntimeBuilder().addLibraries(setsExtensions).build();
+ Cel cel =
+ runtimeFlavor
+ .builder()
+ .addCompilerLibraries(setsExtensions)
+ .addRuntimeLibraries(setsExtensions)
+ .build();
- Object evaluatedResult =
- celRuntime
- .createProgram(celCompiler.compile("sets.equivalent([1, 1], [1])").getAst())
- .eval();
+ Object evaluatedResult = eval(cel, "sets.equivalent([1, 1], [1])");
assertThat(evaluatedResult).isEqualTo(true);
}
@@ -488,44 +411,55 @@ public void setsExtension_equivalentFunctionSubset_succeeds() throws Exception {
public void setsExtension_intersectsFunctionSubset_succeeds() throws Exception {
CelSetsExtensions setsExtensions =
CelExtensions.sets(CelOptions.DEFAULT, SetsFunction.INTERSECTS);
- CelCompiler celCompiler =
- CelCompilerFactory.standardCelCompilerBuilder().addLibraries(setsExtensions).build();
- CelRuntime celRuntime =
- CelRuntimeFactory.standardCelRuntimeBuilder().addLibraries(setsExtensions).build();
+ Cel cel =
+ runtimeFlavor
+ .builder()
+ .addCompilerLibraries(setsExtensions)
+ .addRuntimeLibraries(setsExtensions)
+ .build();
- Object evaluatedResult =
- celRuntime
- .createProgram(celCompiler.compile("sets.intersects([1, 1], [1])").getAst())
- .eval();
+ Object evaluatedResult = eval(cel, "sets.intersects([1, 1], [1])");
assertThat(evaluatedResult).isEqualTo(true);
}
@Test
public void setsExtension_compileUnallowedFunction_throws() {
+ Assume.assumeFalse(isParseOnly);
CelSetsExtensions setsExtensions =
CelExtensions.sets(CelOptions.DEFAULT, SetsFunction.EQUIVALENT);
- CelCompiler celCompiler =
- CelCompilerFactory.standardCelCompilerBuilder().addLibraries(setsExtensions).build();
+ Cel cel = runtimeFlavor.builder().addCompilerLibraries(setsExtensions).build();
assertThrows(
- CelValidationException.class,
- () -> celCompiler.compile("sets.contains([1, 2], [2])").getAst());
+ CelValidationException.class, () -> cel.compile("sets.contains([1, 2], [2])").getAst());
}
@Test
public void setsExtension_evaluateUnallowedFunction_throws() throws Exception {
CelSetsExtensions setsExtensions =
CelExtensions.sets(CelOptions.DEFAULT, SetsFunction.CONTAINS, SetsFunction.EQUIVALENT);
- CelCompiler celCompiler =
- CelCompilerFactory.standardCelCompilerBuilder().addLibraries(setsExtensions).build();
- CelRuntime celRuntime =
- CelRuntimeFactory.standardCelRuntimeBuilder()
- .addLibraries(CelExtensions.sets(CelOptions.DEFAULT, SetsFunction.EQUIVALENT))
+ CelSetsExtensions runtimeLibrary =
+ CelExtensions.sets(CelOptions.DEFAULT, SetsFunction.EQUIVALENT);
+ Cel cel =
+ runtimeFlavor
+ .builder()
+ .addCompilerLibraries(setsExtensions)
+ .addRuntimeLibraries(runtimeLibrary)
.build();
- CelAbstractSyntaxTree ast = celCompiler.compile("sets.contains([1, 2], [2])").getAst();
-
- assertThrows(CelEvaluationException.class, () -> celRuntime.createProgram(ast).eval());
+ CelAbstractSyntaxTree ast =
+ isParseOnly
+ ? cel.parse("sets.contains([1, 2], [2])").getAst()
+ : cel.compile("sets.contains([1, 2], [2])").getAst();
+
+ if (runtimeFlavor.equals(CelRuntimeFlavor.PLANNER) && !isParseOnly) {
+ // Fails at plan time
+ assertThrows(CelEvaluationException.class, () -> cel.createProgram(ast));
+ } else {
+ CelRuntime.Program program = cel.createProgram(ast);
+ assertThrows(CelEvaluationException.class, () -> program.eval());
+ }
}
+
+
}
diff --git a/extensions/src/test/java/dev/cel/extensions/CelStringExtensionsTest.java b/extensions/src/test/java/dev/cel/extensions/CelStringExtensionsTest.java
index 3624e0902..4b242ddcd 100644
--- a/extensions/src/test/java/dev/cel/extensions/CelStringExtensionsTest.java
+++ b/extensions/src/test/java/dev/cel/extensions/CelStringExtensionsTest.java
@@ -18,43 +18,45 @@
import static org.junit.Assert.assertThrows;
import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
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;
import dev.cel.common.CelValidationException;
+import dev.cel.common.CelValidationResult;
import dev.cel.common.types.SimpleType;
import dev.cel.compiler.CelCompiler;
import dev.cel.compiler.CelCompilerFactory;
import dev.cel.extensions.CelStringExtensions.Function;
import dev.cel.runtime.CelEvaluationException;
import dev.cel.runtime.CelRuntime;
-import dev.cel.runtime.CelRuntimeFactory;
import java.util.List;
+import org.junit.Assume;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(TestParameterInjector.class)
-public final class CelStringExtensionsTest {
-
- private static final CelCompiler COMPILER =
- CelCompilerFactory.standardCelCompilerBuilder()
- .addLibraries(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();
-
- private static final CelRuntime RUNTIME =
- CelRuntimeFactory.standardCelRuntimeBuilder().addLibraries(CelExtensions.strings()).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
public void library() {
@@ -92,10 +94,8 @@ public void library() {
@TestParameters("{string: '😁😑😦', beginIndex: 3, expectedResult: ''}")
public void substring_beginIndex_success(String string, int beginIndex, String expectedResult)
throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("s.substring(beginIndex)").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- Object evaluatedResult = program.eval(ImmutableMap.of("s", string, "beginIndex", beginIndex));
+ Object evaluatedResult =
+ eval("s.substring(beginIndex)", ImmutableMap.of("s", string, "beginIndex", beginIndex));
assertThat(evaluatedResult).isEqualTo(expectedResult);
}
@@ -108,10 +108,7 @@ public void substring_beginIndex_success(String string, int beginIndex, String e
@TestParameters(
"{string: 'A!@#$%^&*()-_+=?/<>.,;:''\"\\', expectedResult: 'a!@#$%^&*()-_+=?/<>.,;:''\"\\'}")
public void lowerAscii_success(String string, String expectedResult) throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("s.lowerAscii()").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- Object evaluatedResult = program.eval(ImmutableMap.of("s", string));
+ Object evaluatedResult = eval("s.lowerAscii()", ImmutableMap.of("s", string));
assertThat(evaluatedResult).isEqualTo(expectedResult);
}
@@ -127,10 +124,7 @@ public void lowerAscii_success(String string, String expectedResult) throws Exce
@TestParameters("{string: 'A😁B 😑C가😦D', expectedResult: 'a😁b 😑c가😦d'}")
public void lowerAscii_outsideAscii_success(String string, String expectedResult)
throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("s.lowerAscii()").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- Object evaluatedResult = program.eval(ImmutableMap.of("s", string));
+ Object evaluatedResult = eval("s.lowerAscii()", ImmutableMap.of("s", string));
assertThat(evaluatedResult).isEqualTo(expectedResult);
}
@@ -161,10 +155,8 @@ public void lowerAscii_outsideAscii_success(String string, String expectedResult
+ " ['The quick brown ', ' jumps over the lazy dog']}")
public void split_ascii_success(String string, String separator, List expectedResult)
throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("s.split(separator)").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- Object evaluatedResult = program.eval(ImmutableMap.of("s", string, "separator", separator));
+ Object evaluatedResult =
+ eval("s.split(separator)", ImmutableMap.of("s", string, "separator", separator));
assertThat(evaluatedResult).isEqualTo(expectedResult);
}
@@ -182,34 +174,30 @@ public void split_ascii_success(String string, String separator, List ex
@TestParameters("{string: '😁a😦나😑 😦', separator: '😁a😦나😑 😦', expectedResult: ['','']}")
public void split_unicode_success(String string, String separator, List expectedResult)
throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("s.split(separator)").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- Object evaluatedResult = program.eval(ImmutableMap.of("s", string, "separator", separator));
+ Object evaluatedResult =
+ eval("s.split(separator)", ImmutableMap.of("s", string, "separator", separator));
assertThat(evaluatedResult).isEqualTo(expectedResult);
}
@Test
@SuppressWarnings("unchecked") // Test only, need List cast to test mutability
- public void split_collectionIsMutable() throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("'test'.split('')").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
+ public void split_collectionIsImmutable() throws Exception {
+ CelAbstractSyntaxTree ast = cel.compile("'test'.split('')").getAst();
+ CelRuntime.Program program = cel.createProgram(ast);
List evaluatedResult = (List) program.eval();
- evaluatedResult.add("a");
- evaluatedResult.add("b");
- evaluatedResult.add("c");
- evaluatedResult.remove("c");
- assertThat(evaluatedResult).containsExactly("t", "e", "s", "t", "a", "b").inOrder();
+ assertThrows(UnsupportedOperationException.class, () -> evaluatedResult.add("a"));
}
@Test
public void split_separatorIsNonString_throwsException() {
+ // This is a type-check failure.
+ Assume.assumeFalse(isParseOnly);
+ CelValidationResult result = cel.compile("'12'.split(2)");
CelValidationException exception =
- assertThrows(
- CelValidationException.class, () -> COMPILER.compile("'12'.split(2)").getAst());
+ assertThrows(CelValidationException.class, () -> result.getAst());
assertThat(exception).hasMessageThat().contains("found no matching overload for 'split'");
}
@@ -295,11 +283,10 @@ public void split_separatorIsNonString_throwsException() {
+ " expectedResult: ['The quick brown ', ' jumps over the lazy dog']}")
public void split_asciiWithLimit_success(
String string, String separator, int limit, List expectedResult) throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("s.split(separator, limit)").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
Object evaluatedResult =
- program.eval(ImmutableMap.of("s", string, "separator", separator, "limit", limit));
+ eval(
+ "s.split(separator, limit)",
+ ImmutableMap.of("s", string, "separator", separator, "limit", limit));
assertThat(evaluatedResult).isEqualTo(expectedResult);
}
@@ -351,11 +338,10 @@ public void split_asciiWithLimit_success(
"{string: '😁a😦나😑 😦', separator: '😁a😦나😑 😦', limit: -1, expectedResult: ['','']}")
public void split_unicodeWithLimit_success(
String string, String separator, int limit, List expectedResult) throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("s.split(separator, limit)").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
Object evaluatedResult =
- program.eval(ImmutableMap.of("s", string, "separator", separator, "limit", limit));
+ eval(
+ "s.split(separator, limit)",
+ ImmutableMap.of("s", string, "separator", separator, "limit", limit));
assertThat(evaluatedResult).isEqualTo(expectedResult);
}
@@ -368,35 +354,33 @@ public void split_unicodeWithLimit_success(
@TestParameters("{separator: 'te', limit: 1}")
@TestParameters("{separator: 'te', limit: 2}")
@SuppressWarnings("unchecked") // Test only, need List cast to test mutability
- public void split_withLimit_collectionIsMutable(String separator, int limit) throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("'test'.split(separator, limit)").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
+ public void split_withLimit_collectionIsImmutable(String separator, int limit) throws Exception {
List evaluatedResult =
- (List) program.eval(ImmutableMap.of("separator", separator, "limit", limit));
- evaluatedResult.add("a");
+ (List)
+ eval(
+ "'test'.split(separator, limit)",
+ ImmutableMap.of("separator", separator, "limit", limit));
- assertThat(Iterables.getLast(evaluatedResult)).isEqualTo("a");
+ assertThrows(UnsupportedOperationException.class, () -> evaluatedResult.add("a"));
}
@Test
public void split_withLimit_separatorIsNonString_throwsException() {
+ // This is a type-check failure.
+ Assume.assumeFalse(isParseOnly);
+ CelValidationResult result = cel.compile("'12'.split(2, 3)");
CelValidationException exception =
- assertThrows(
- CelValidationException.class, () -> COMPILER.compile("'12'.split(2, 3)").getAst());
+ assertThrows(CelValidationException.class, () -> result.getAst());
assertThat(exception).hasMessageThat().contains("found no matching overload for 'split'");
}
@Test
public void split_withLimitOverflow_throwsException() throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("'test'.split('', limit)").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
+ ImmutableMap variables = ImmutableMap.of("limit", 2147483648L); // INT_MAX + 1
CelEvaluationException exception =
assertThrows(
- CelEvaluationException.class,
- () -> program.eval(ImmutableMap.of("limit", 2147483648L))); // INT_MAX + 1
+ CelEvaluationException.class, () -> eval("'test'.split('', limit)", variables));
assertThat(exception)
.hasMessageThat()
@@ -416,11 +400,10 @@ public void split_withLimitOverflow_throwsException() throws Exception {
@TestParameters("{string: '', beginIndex: 0, endIndex: 0, expectedResult: ''}")
public void substring_beginAndEndIndex_ascii_success(
String string, int beginIndex, int endIndex, String expectedResult) throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("s.substring(beginIndex, endIndex)").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
Object evaluatedResult =
- program.eval(ImmutableMap.of("s", string, "beginIndex", beginIndex, "endIndex", endIndex));
+ eval(
+ "s.substring(beginIndex, endIndex)",
+ ImmutableMap.of("s", string, "beginIndex", beginIndex, "endIndex", endIndex));
assertThat(evaluatedResult).isEqualTo(expectedResult);
}
@@ -444,11 +427,10 @@ public void substring_beginAndEndIndex_ascii_success(
@TestParameters("{string: 'a😁나', beginIndex: 3, endIndex: 3, expectedResult: ''}")
public void substring_beginAndEndIndex_unicode_success(
String string, int beginIndex, int endIndex, String expectedResult) throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("s.substring(beginIndex, endIndex)").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
Object evaluatedResult =
- program.eval(ImmutableMap.of("s", string, "beginIndex", beginIndex, "endIndex", endIndex));
+ eval(
+ "s.substring(beginIndex, endIndex)",
+ ImmutableMap.of("s", string, "beginIndex", beginIndex, "endIndex", endIndex));
assertThat(evaluatedResult).isEqualTo(expectedResult);
}
@@ -458,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 {
- CelAbstractSyntaxTree ast = COMPILER.compile("s.substring(beginIndex)").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
+ ImmutableMap variables = ImmutableMap.of("s", string, "beginIndex", beginIndex);
CelEvaluationException exception =
assertThrows(
- CelEvaluationException.class,
- () -> program.eval(ImmutableMap.of("s", string, "beginIndex", beginIndex)));
+ CelEvaluationException.class, () -> eval("s.substring(beginIndex)", variables));
String exceptionMessage =
String.format(
@@ -482,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 {
- CelAbstractSyntaxTree ast = COMPILER.compile("s.substring(beginIndex)").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
+ ImmutableMap variables = ImmutableMap.of("s", string, "beginIndex", beginIndex);
CelEvaluationException exception =
assertThrows(
- CelEvaluationException.class,
- () -> program.eval(ImmutableMap.of("s", string, "beginIndex", beginIndex)));
+ CelEvaluationException.class, () -> eval("s.substring(beginIndex)", variables));
String exceptionMessage =
String.format(
@@ -505,15 +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 {
- CelAbstractSyntaxTree ast = COMPILER.compile("s.substring(beginIndex, endIndex)").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
+ ImmutableMap variables =
+ ImmutableMap.of("s", string, "beginIndex", beginIndex, "endIndex", endIndex);
CelEvaluationException exception =
assertThrows(
CelEvaluationException.class,
- () ->
- program.eval(
- 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);
@@ -522,13 +495,11 @@ public void substring_beginAndEndIndexOutOfRange_throwsException(
@Test
public void substring_beginIndexOverflow_throwsException() throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("'abcd'.substring(beginIndex)").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
+ ImmutableMap variables =
+ ImmutableMap.of("beginIndex", 2147483648L); // INT_MAX + 1
CelEvaluationException exception =
assertThrows(
- CelEvaluationException.class,
- () -> program.eval(ImmutableMap.of("beginIndex", 2147483648L))); // INT_MAX + 1
+ CelEvaluationException.class, () -> eval("'abcd'.substring(beginIndex)", variables));
assertThat(exception)
.hasMessageThat()
@@ -540,13 +511,13 @@ public void substring_beginIndexOverflow_throwsException() throws Exception {
@TestParameters("{beginIndex: 2147483648, endIndex: 2147483648}")
public void substring_beginOrEndIndexOverflow_throwsException(long beginIndex, long endIndex)
throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("'abcd'.substring(beginIndex, endIndex)").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
CelEvaluationException exception =
assertThrows(
CelEvaluationException.class,
- () -> program.eval(ImmutableMap.of("beginIndex", beginIndex, "endIndex", endIndex)));
+ () ->
+ eval(
+ "'abcd'.substring(beginIndex, endIndex)",
+ ImmutableMap.of("beginIndex", beginIndex, "endIndex", endIndex)));
assertThat(exception)
.hasMessageThat()
@@ -563,10 +534,7 @@ public void substring_beginOrEndIndexOverflow_throwsException(long beginIndex, l
@TestParameters("{string: 'world', index: 5, expectedResult: ''}")
public void charAt_ascii_success(String string, long index, String expectedResult)
throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("s.charAt(index)").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- Object evaluatedResult = program.eval(ImmutableMap.of("s", string, "index", index));
+ Object evaluatedResult = eval("s.charAt(index)", ImmutableMap.of("s", string, "index", index));
assertThat(evaluatedResult).isEqualTo(expectedResult);
}
@@ -588,10 +556,7 @@ public void charAt_ascii_success(String string, long index, String expectedResul
@TestParameters("{string: 'a😁나', index: 3, expectedResult: ''}")
public void charAt_unicode_success(String string, long index, String expectedResult)
throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("s.charAt(index)").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- Object evaluatedResult = program.eval(ImmutableMap.of("s", string, "index", index));
+ Object evaluatedResult = eval("s.charAt(index)", ImmutableMap.of("s", string, "index", index));
assertThat(evaluatedResult).isEqualTo(expectedResult);
}
@@ -602,26 +567,21 @@ public void charAt_unicode_success(String string, long index, String expectedRes
@TestParameters("{string: '😁😑😦', index: -1}")
@TestParameters("{string: '😁😑😦', index: 4}")
public void charAt_outOfBounds_throwsException(String string, long index) throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("s.charAt(index)").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
CelEvaluationException exception =
assertThrows(
CelEvaluationException.class,
- () -> program.eval(ImmutableMap.of("s", string, "index", index)));
+ () -> eval("s.charAt(index)", ImmutableMap.of("s", string, "index", index)));
assertThat(exception).hasMessageThat().contains("charAt failure: Index out of range");
}
@Test
public void charAt_indexOverflow_throwsException() throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("'test'.charAt(index)").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
CelEvaluationException exception =
assertThrows(
CelEvaluationException.class,
- () -> program.eval(ImmutableMap.of("index", 2147483648L))); // INT_MAX + 1
+ () ->
+ eval("'test'.charAt(index)", ImmutableMap.of("index", 2147483648L))); // INT_MAX + 1
assertThat(exception)
.hasMessageThat()
@@ -650,10 +610,8 @@ public void charAt_indexOverflow_throwsException() throws Exception {
@TestParameters("{string: 'hello mellow', indexOf: ' ', expectedResult: -1}")
public void indexOf_ascii_success(String string, String indexOf, int expectedResult)
throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("s.indexOf(indexOfParam)").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- Object evaluatedResult = program.eval(ImmutableMap.of("s", string, "indexOfParam", indexOf));
+ Object evaluatedResult =
+ eval("s.indexOf(indexOfParam)", ImmutableMap.of("s", string, "indexOfParam", indexOf));
assertThat(evaluatedResult).isEqualTo(expectedResult);
}
@@ -682,10 +640,8 @@ public void indexOf_ascii_success(String string, String indexOf, int expectedRes
@TestParameters("{string: 'a😁😑 나😦😁😑다', indexOf: 'a😁😑 나😦😁😑다😁', expectedResult: -1}")
public void indexOf_unicode_success(String string, String indexOf, int expectedResult)
throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("s.indexOf(indexOfParam)").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- Object evaluatedResult = program.eval(ImmutableMap.of("s", string, "indexOfParam", indexOf));
+ Object evaluatedResult =
+ eval("s.indexOf(indexOfParam)", ImmutableMap.of("s", string, "indexOfParam", indexOf));
assertThat(evaluatedResult).isEqualTo(expectedResult);
}
@@ -697,13 +653,10 @@ public void indexOf_unicode_success(String string, String indexOf, int expectedR
@TestParameters("{indexOf: '나'}")
@TestParameters("{indexOf: '😁'}")
public void indexOf_onEmptyString_throwsException(String indexOf) throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("''.indexOf(indexOfParam)").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
CelEvaluationException exception =
assertThrows(
CelEvaluationException.class,
- () -> program.eval(ImmutableMap.of("indexOfParam", indexOf)));
+ () -> eval("''.indexOf(indexOfParam)", ImmutableMap.of("indexOfParam", indexOf)));
assertThat(exception).hasMessageThat().contains("indexOf failure: Offset out of range");
}
@@ -728,11 +681,10 @@ public void indexOf_onEmptyString_throwsException(String indexOf) throws Excepti
@TestParameters("{string: 'hello mellow', indexOf: 'l', offset: 10, expectedResult: -1}")
public void indexOf_asciiWithOffset_success(
String string, String indexOf, int offset, int expectedResult) throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("s.indexOf(indexOfParam, offset)").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
Object evaluatedResult =
- program.eval(ImmutableMap.of("s", string, "indexOfParam", indexOf, "offset", offset));
+ eval(
+ "s.indexOf(indexOfParam, offset)",
+ ImmutableMap.of("s", string, "indexOfParam", indexOf, "offset", offset));
assertThat(evaluatedResult).isEqualTo(expectedResult);
}
@@ -779,11 +731,10 @@ public void indexOf_asciiWithOffset_success(
"{string: 'a😁😑 나😦😁😑다', indexOf: 'a😁😑 나😦😁😑다😁', offset: 0, expectedResult: -1}")
public void indexOf_unicodeWithOffset_success(
String string, String indexOf, int offset, int expectedResult) throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("s.indexOf(indexOfParam, offset)").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
Object evaluatedResult =
- program.eval(ImmutableMap.of("s", string, "indexOfParam", indexOf, "offset", offset));
+ eval(
+ "s.indexOf(indexOfParam, offset)",
+ ImmutableMap.of("s", string, "indexOfParam", indexOf, "offset", offset));
assertThat(evaluatedResult).isEqualTo(expectedResult);
}
@@ -797,14 +748,12 @@ public void indexOf_unicodeWithOffset_success(
@TestParameters("{string: '😁😑 😦', indexOf: '😦', offset: 4}")
public void indexOf_withOffsetOutOfBounds_throwsException(
String string, String indexOf, int offset) throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("s.indexOf(indexOfParam, offset)").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
CelEvaluationException exception =
assertThrows(
CelEvaluationException.class,
() ->
- program.eval(
+ eval(
+ "s.indexOf(indexOfParam, offset)",
ImmutableMap.of("s", string, "indexOfParam", indexOf, "offset", offset)));
assertThat(exception).hasMessageThat().contains("indexOf failure: Offset out of range");
@@ -812,13 +761,13 @@ public void indexOf_withOffsetOutOfBounds_throwsException(
@Test
public void indexOf_offsetOverflow_throwsException() throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("'test'.indexOf('t', offset)").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
CelEvaluationException exception =
assertThrows(
CelEvaluationException.class,
- () -> program.eval(ImmutableMap.of("offset", 2147483648L))); // INT_MAX + 1
+ () ->
+ eval(
+ "'test'.indexOf('t', offset)",
+ ImmutableMap.of("offset", 2147483648L))); // INT_MAX + 1
assertThat(exception)
.hasMessageThat()
@@ -835,10 +784,7 @@ public void indexOf_offsetOverflow_throwsException() throws Exception {
@TestParameters("{list: '[''x'', '' '', '' y '', ''z '']', expectedResult: 'x y z '}")
@TestParameters("{list: '[''hello '', ''world'']', expectedResult: 'hello world'}")
public void join_ascii_success(String list, String expectedResult) throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile(String.format("%s.join()", list)).getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- String result = (String) program.eval();
+ String result = (String) eval(String.format("%s.join()", list));
assertThat(result).isEqualTo(expectedResult);
}
@@ -847,10 +793,7 @@ public void join_ascii_success(String list, String expectedResult) throws Except
@TestParameters("{list: '[''가'', ''😁'']', expectedResult: '가😁'}")
@TestParameters("{list: '[''😁😦😑 😦'', ''나'']', expectedResult: '😁😦😑 😦나'}")
public void join_unicode_success(String list, String expectedResult) throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile(String.format("%s.join()", list)).getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- String result = (String) program.eval();
+ String result = (String) eval(String.format("%s.join()", list));
assertThat(result).isEqualTo(expectedResult);
}
@@ -874,11 +817,7 @@ public void join_unicode_success(String list, String expectedResult) throws Exce
"{list: '[''hello '', ''world'']', separator: '/', expectedResult: 'hello /world'}")
public void join_asciiWithSeparator_success(String list, String separator, String expectedResult)
throws Exception {
- CelAbstractSyntaxTree ast =
- COMPILER.compile(String.format("%s.join('%s')", list, separator)).getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- String result = (String) program.eval();
+ String result = (String) eval(String.format("%s.join('%s')", list, separator));
assertThat(result).isEqualTo(expectedResult);
}
@@ -893,20 +832,17 @@ public void join_asciiWithSeparator_success(String list, String separator, Strin
+ " -😑-나'}")
public void join_unicodeWithSeparator_success(
String list, String separator, String expectedResult) throws Exception {
- CelAbstractSyntaxTree ast =
- COMPILER.compile(String.format("%s.join('%s')", list, separator)).getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- String result = (String) program.eval();
+ String result = (String) eval(String.format("%s.join('%s')", list, separator));
assertThat(result).isEqualTo(expectedResult);
}
@Test
public void join_separatorIsNonString_throwsException() {
+ // This is a type-check failure.
+ Assume.assumeFalse(isParseOnly);
CelValidationException exception =
- assertThrows(
- CelValidationException.class, () -> COMPILER.compile("['x','y'].join(2)").getAst());
+ assertThrows(CelValidationException.class, () -> cel.compile("['x','y'].join(2)").getAst());
assertThat(exception).hasMessageThat().contains("found no matching overload for 'join'");
}
@@ -935,11 +871,10 @@ public void join_separatorIsNonString_throwsException() {
@TestParameters("{string: 'hello mellow', lastIndexOf: ' ', expectedResult: -1}")
public void lastIndexOf_ascii_success(String string, String lastIndexOf, int expectedResult)
throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("s.lastIndexOf(indexOfParam)").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
Object evaluatedResult =
- program.eval(ImmutableMap.of("s", string, "indexOfParam", lastIndexOf));
+ eval(
+ "s.lastIndexOf(indexOfParam)",
+ ImmutableMap.of("s", string, "indexOfParam", lastIndexOf));
assertThat(evaluatedResult).isEqualTo(expectedResult);
}
@@ -969,11 +904,10 @@ public void lastIndexOf_ascii_success(String string, String lastIndexOf, int exp
@TestParameters("{string: 'a😁😑 나😦😁😑다', lastIndexOf: 'a😁😑 나😦😁😑다😁', expectedResult: -1}")
public void lastIndexOf_unicode_success(String string, String lastIndexOf, int expectedResult)
throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("s.lastIndexOf(indexOfParam)").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
Object evaluatedResult =
- program.eval(ImmutableMap.of("s", string, "indexOfParam", lastIndexOf));
+ eval(
+ "s.lastIndexOf(indexOfParam)",
+ ImmutableMap.of("s", string, "indexOfParam", lastIndexOf));
assertThat(evaluatedResult).isEqualTo(expectedResult);
}
@@ -987,10 +921,8 @@ public void lastIndexOf_unicode_success(String string, String lastIndexOf, int e
@TestParameters("{lastIndexOf: '😁'}")
public void lastIndexOf_strLengthLessThanSubstrLength_returnsMinusOne(String lastIndexOf)
throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("''.lastIndexOf(indexOfParam)").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- Object evaluatedResult = program.eval(ImmutableMap.of("s", "", "indexOfParam", lastIndexOf));
+ Object evaluatedResult =
+ eval("''.lastIndexOf(indexOfParam)", ImmutableMap.of("s", "", "indexOfParam", lastIndexOf));
assertThat(evaluatedResult).isEqualTo(-1);
}
@@ -1022,11 +954,10 @@ public void lastIndexOf_strLengthLessThanSubstrLength_returnsMinusOne(String las
"{string: 'hello mellow', lastIndexOf: 'hello mellowwww ', offset: 11, expectedResult: -1}")
public void lastIndexOf_asciiWithOffset_success(
String string, String lastIndexOf, int offset, int expectedResult) throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("s.lastIndexOf(indexOfParam, offset)").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
Object evaluatedResult =
- program.eval(ImmutableMap.of("s", string, "indexOfParam", lastIndexOf, "offset", offset));
+ eval(
+ "s.lastIndexOf(indexOfParam, offset)",
+ ImmutableMap.of("s", string, "indexOfParam", lastIndexOf, "offset", offset));
assertThat(evaluatedResult).isEqualTo(expectedResult);
}
@@ -1097,11 +1028,10 @@ public void lastIndexOf_asciiWithOffset_success(
"{string: 'a😁😑 나😦😁😑다', lastIndexOf: 'a😁😑 나😦😁😑다😁', offset: 8, expectedResult: -1}")
public void lastIndexOf_unicodeWithOffset_success(
String string, String lastIndexOf, int offset, int expectedResult) throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("s.lastIndexOf(indexOfParam, offset)").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
Object evaluatedResult =
- program.eval(ImmutableMap.of("s", string, "indexOfParam", lastIndexOf, "offset", offset));
+ eval(
+ "s.lastIndexOf(indexOfParam, offset)",
+ ImmutableMap.of("s", string, "indexOfParam", lastIndexOf, "offset", offset));
assertThat(evaluatedResult).isEqualTo(expectedResult);
}
@@ -1115,14 +1045,12 @@ public void lastIndexOf_unicodeWithOffset_success(
@TestParameters("{string: '😁😑 😦', lastIndexOf: '😦', offset: 4}")
public void lastIndexOf_withOffsetOutOfBounds_throwsException(
String string, String lastIndexOf, int offset) throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("s.lastIndexOf(indexOfParam, offset)").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
CelEvaluationException exception =
assertThrows(
CelEvaluationException.class,
() ->
- program.eval(
+ eval(
+ "s.lastIndexOf(indexOfParam, offset)",
ImmutableMap.of("s", string, "indexOfParam", lastIndexOf, "offset", offset)));
assertThat(exception).hasMessageThat().contains("lastIndexOf failure: Offset out of range");
@@ -1130,13 +1058,13 @@ public void lastIndexOf_withOffsetOutOfBounds_throwsException(
@Test
public void lastIndexOf_offsetOverflow_throwsException() throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("'test'.lastIndexOf('t', offset)").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
CelEvaluationException exception =
assertThrows(
CelEvaluationException.class,
- () -> program.eval(ImmutableMap.of("offset", 2147483648L))); // INT_MAX + 1
+ () ->
+ eval(
+ "'test'.lastIndexOf('t', offset)",
+ ImmutableMap.of("offset", 2147483648L))); // INT_MAX + 1
assertThat(exception)
.hasMessageThat()
@@ -1163,13 +1091,8 @@ public void lastIndexOf_offsetOverflow_throwsException() throws Exception {
public void replace_ascii_success(
String string, String searchString, String replacement, String expectedResult)
throws Exception {
- CelAbstractSyntaxTree ast =
- COMPILER
- .compile(String.format("'%s'.replace('%s', '%s')", string, searchString, replacement))
- .getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- Object evaluatedResult = program.eval();
+ Object evaluatedResult =
+ eval(String.format("'%s'.replace('%s', '%s')", string, searchString, replacement));
assertThat(evaluatedResult).isEqualTo(expectedResult);
}
@@ -1188,13 +1111,8 @@ public void replace_ascii_success(
public void replace_unicode_success(
String string, String searchString, String replacement, String expectedResult)
throws Exception {
- CelAbstractSyntaxTree ast =
- COMPILER
- .compile(String.format("'%s'.replace('%s', '%s')", string, searchString, replacement))
- .getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- Object evaluatedResult = program.eval();
+ Object evaluatedResult =
+ eval(String.format("'%s'.replace('%s', '%s')", string, searchString, replacement));
assertThat(evaluatedResult).isEqualTo(expectedResult);
}
@@ -1273,15 +1191,10 @@ public void replace_unicode_success(
public void replace_ascii_withLimit_success(
String string, String searchString, String replacement, int limit, String expectedResult)
throws Exception {
- CelAbstractSyntaxTree ast =
- COMPILER
- .compile(
- String.format(
- "'%s'.replace('%s', '%s', %d)", string, searchString, replacement, limit))
- .getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- Object evaluatedResult = program.eval();
+ Object evaluatedResult =
+ eval(
+ String.format(
+ "'%s'.replace('%s', '%s', %d)", string, searchString, replacement, limit));
assertThat(evaluatedResult).isEqualTo(expectedResult);
}
@@ -1334,28 +1247,23 @@ public void replace_ascii_withLimit_success(
public void replace_unicode_withLimit_success(
String string, String searchString, String replacement, int limit, String expectedResult)
throws Exception {
- CelAbstractSyntaxTree ast =
- COMPILER
- .compile(
- String.format(
- "'%s'.replace('%s', '%s', %d)", string, searchString, replacement, limit))
- .getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- Object evaluatedResult = program.eval();
+ Object evaluatedResult =
+ eval(
+ String.format(
+ "'%s'.replace('%s', '%s', %d)", string, searchString, replacement, limit));
assertThat(evaluatedResult).isEqualTo(expectedResult);
}
@Test
public void replace_limitOverflow_throwsException() throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("'test'.replace('','',index)").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
CelEvaluationException exception =
assertThrows(
CelEvaluationException.class,
- () -> program.eval(ImmutableMap.of("index", 2147483648L))); // INT_MAX + 1
+ () ->
+ eval(
+ "'test'.replace('','',index)",
+ ImmutableMap.of("index", 2147483648L))); // INT_MAX + 1
assertThat(exception)
.hasMessageThat()
@@ -1406,10 +1314,7 @@ private enum TrimTestCase {
@Test
public void trim_success(@TestParameter TrimTestCase testCase) throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("s.trim()").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- Object evaluatedResult = program.eval(ImmutableMap.of("s", testCase.text));
+ Object evaluatedResult = eval("s.trim()", ImmutableMap.of("s", testCase.text));
assertThat(evaluatedResult).isEqualTo(testCase.expectedResult);
}
@@ -1422,10 +1327,7 @@ public void trim_success(@TestParameter TrimTestCase testCase) throws Exception
@TestParameters(
"{string: 'a!@#$%^&*()-_+=?/<>.,;:''\"\\', expectedResult: 'A!@#$%^&*()-_+=?/<>.,;:''\"\\'}")
public void upperAscii_success(String string, String expectedResult) throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("s.upperAscii()").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- Object evaluatedResult = program.eval(ImmutableMap.of("s", string));
+ Object evaluatedResult = eval("s.upperAscii()", ImmutableMap.of("s", string));
assertThat(evaluatedResult).isEqualTo(expectedResult);
}
@@ -1441,30 +1343,22 @@ public void upperAscii_success(String string, String expectedResult) throws Exce
@TestParameters("{string: 'a😁b 😑c가😦d', expectedResult: 'A😁B 😑C가😦D'}")
public void upperAscii_outsideAscii_success(String string, String expectedResult)
throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("s.upperAscii()").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- Object evaluatedResult = program.eval(ImmutableMap.of("s", string));
+ Object evaluatedResult = eval("s.upperAscii()", ImmutableMap.of("s", string));
assertThat(evaluatedResult).isEqualTo(expectedResult);
}
@Test
public void stringExtension_functionSubset_success() throws Exception {
- CelStringExtensions stringExtensions =
- CelExtensions.strings(Function.CHAR_AT, Function.SUBSTRING);
- CelCompiler celCompiler =
- CelCompilerFactory.standardCelCompilerBuilder().addLibraries(stringExtensions).build();
- CelRuntime celRuntime =
- CelRuntimeFactory.standardCelRuntimeBuilder().addLibraries(stringExtensions).build();
+ Cel customCel =
+ runtimeFlavor
+ .builder()
+ .addCompilerLibraries(CelExtensions.strings(Function.CHAR_AT, Function.SUBSTRING))
+ .addRuntimeLibraries(CelExtensions.strings(Function.CHAR_AT, Function.SUBSTRING))
+ .build();
Object evaluatedResult =
- celRuntime
- .createProgram(
- celCompiler
- .compile("'test'.substring(2) == 'st' && 'hello'.charAt(1) == 'e'")
- .getAst())
- .eval();
+ eval(customCel, "'test'.substring(2) == 'st' && 'hello'.charAt(1) == 'e'");
assertThat(evaluatedResult).isEqualTo(true);
}
@@ -1476,10 +1370,7 @@ public void stringExtension_functionSubset_success() throws Exception {
@TestParameters("{string: 'hello world', expectedResult: 'dlrow olleh'}")
@TestParameters("{string: 'ab가cd', expectedResult: 'dc가ba'}")
public void reverse_success(String string, String expectedResult) throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("s.reverse()").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- Object evaluatedResult = program.eval(ImmutableMap.of("s", string));
+ Object evaluatedResult = eval("s.reverse()", ImmutableMap.of("s", string));
assertThat(evaluatedResult).isEqualTo(expectedResult);
}
@@ -1490,10 +1381,7 @@ public void reverse_success(String string, String expectedResult) throws Excepti
"{string: '\u180e\u200b\u200c\u200d\u2060\ufeff', expectedResult:"
+ " '\ufeff\u2060\u200d\u200c\u200b\u180e'}")
public void reverse_unicode(String string, String expectedResult) throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("s.reverse()").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- Object evaluatedResult = program.eval(ImmutableMap.of("s", string));
+ Object evaluatedResult = eval("s.reverse()", ImmutableMap.of("s", string));
assertThat(evaluatedResult).isEqualTo(expectedResult);
}
@@ -1502,14 +1390,14 @@ public void reverse_unicode(String string, String expectedResult) throws Excepti
@TestParameters("{string: 'hello', expectedResult: '\"hello\"'}")
@TestParameters("{string: '', expectedResult: '\"\"'}")
@TestParameters(
- "{string: 'contains \\\"quotes\\\"', expectedResult: '\"contains \\\\\\\"quotes\\\\\\\"\"'}")
- @TestParameters("{string: 'ends with \\\\', expectedResult: '\"ends with \\\\\\\\\"'}")
- @TestParameters("{string: '\\\\ starts with', expectedResult: '\"\\\\\\\\ starts with\"'}")
+ "{string: 'contains \\\\\\\"quotes\\\\\\\"', expectedResult: '\"contains"
+ + " \\\\\\\\\\\\\\\"quotes\\\\\\\\\\\\\\\"\"'}")
+ @TestParameters(
+ "{string: 'ends with \\\\\\\\', expectedResult: '\"ends with \\\\\\\\\\\\\\\\\"'}")
+ @TestParameters(
+ "{string: '\\\\\\\\ starts with', expectedResult: '\"\\\\\\\\\\\\\\\\ starts with\"'}")
public void quote_success(String string, String expectedResult) throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("strings.quote(s)").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- Object evaluatedResult = program.eval(ImmutableMap.of("s", string));
+ Object evaluatedResult = eval("strings.quote(s)", ImmutableMap.of("s", string));
assertThat(evaluatedResult).isEqualTo(expectedResult);
}
@@ -1518,21 +1406,16 @@ public void quote_success(String string, String expectedResult) throws Exception
public void quote_singleWithDoubleQuotes() throws Exception {
String expr = "strings.quote('single-quote with \"double quote\"')";
String expected = "\"\\\"single-quote with \\\\\\\"double quote\\\\\\\"\\\"\"";
- CelAbstractSyntaxTree ast = COMPILER.compile(expr + " == " + expected).getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
- Object evaluatedResult = program.eval();
+ Object evaluatedResult = eval(expr + " == " + expected);
assertThat(evaluatedResult).isEqualTo(true);
}
@Test
public void quote_escapesSpecialCharacters() throws Exception {
- CelAbstractSyntaxTree ast = COMPILER.compile("strings.quote(s)").getAst();
- CelRuntime.Program program = RUNTIME.createProgram(ast);
-
Object evaluatedResult =
- program.eval(
+ eval(
+ "strings.quote(s)",
ImmutableMap.of("s", "\u0007bell\u000Bvtab\bback\ffeed\rret\nline\ttab\\slash 가 😁"));
assertThat(evaluatedResult)
@@ -1541,25 +1424,19 @@ public void quote_escapesSpecialCharacters() throws Exception {
@Test
public void quote_escapesMalformed_endWithHighSurrogate() throws Exception {
- CelRuntime.Program program =
- RUNTIME.createProgram(COMPILER.compile("strings.quote(s)").getAst());
- assertThat(program.eval(ImmutableMap.of("s", "end with high surrogate \uD83D")))
+ assertThat(eval("strings.quote(s)", ImmutableMap.of("s", "end with high surrogate \uD83D")))
.isEqualTo("\"end with high surrogate \uFFFD\"");
}
@Test
public void quote_escapesMalformed_unpairedHighSurrogate() throws Exception {
- CelRuntime.Program program =
- RUNTIME.createProgram(COMPILER.compile("strings.quote(s)").getAst());
- assertThat(program.eval(ImmutableMap.of("s", "bad pair \uD83DA")))
+ assertThat(eval("strings.quote(s)", ImmutableMap.of("s", "bad pair \uD83DA")))
.isEqualTo("\"bad pair \uFFFDA\"");
}
@Test
public void quote_escapesMalformed_unpairedLowSurrogate() throws Exception {
- CelRuntime.Program program =
- RUNTIME.createProgram(COMPILER.compile("strings.quote(s)").getAst());
- assertThat(program.eval(ImmutableMap.of("s", "bad pair \uDC00A")))
+ assertThat(eval("strings.quote(s)", ImmutableMap.of("s", "bad pair \uDC00A")))
.isEqualTo("\"bad pair \uFFFDA\"");
}
@@ -1570,23 +1447,31 @@ public void stringExtension_compileUnallowedFunction_throws() {
.addLibraries(CelExtensions.strings(Function.REPLACE))
.build();
- assertThrows(
- CelValidationException.class,
- () -> celCompiler.compile("'test'.substring(2) == 'st'").getAst());
+ // This is a type-check failure.
+ Assume.assumeFalse(isParseOnly);
+ CelValidationResult result = celCompiler.compile("'test'.substring(2) == 'st'");
+ assertThrows(CelValidationException.class, () -> result.getAst());
}
@Test
public void stringExtension_evaluateUnallowedFunction_throws() throws Exception {
- CelCompiler celCompiler =
- CelCompilerFactory.standardCelCompilerBuilder()
- .addLibraries(CelExtensions.strings(Function.SUBSTRING))
+ Cel customCompilerCel =
+ runtimeFlavor
+ .builder()
+ .addCompilerLibraries(CelExtensions.strings(Function.SUBSTRING))
.build();
- CelRuntime celRuntime =
- CelRuntimeFactory.standardCelRuntimeBuilder()
- .addLibraries(CelExtensions.strings(Function.REPLACE))
+ Cel customRuntimeCel =
+ runtimeFlavor
+ .builder()
+ .addRuntimeLibraries(CelExtensions.strings(Function.REPLACE))
.build();
- CelAbstractSyntaxTree ast = celCompiler.compile("'test'.substring(2) == 'st'").getAst();
+ CelAbstractSyntaxTree ast =
+ isParseOnly
+ ? customCompilerCel.parse("'test'.substring(2) == 'st'").getAst()
+ : customCompilerCel.compile("'test'.substring(2) == 'st'").getAst();
- assertThrows(CelEvaluationException.class, () -> celRuntime.createProgram(ast).eval());
+ assertThrows(CelEvaluationException.class, () -> customRuntimeCel.createProgram(ast).eval());
}
+
+
}
diff --git a/publish/cel_version.bzl b/publish/cel_version.bzl
index b40addd73..70fa1a010 100644
--- a/publish/cel_version.bzl
+++ b/publish/cel_version.bzl
@@ -12,4 +12,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
"""Maven artifact version for CEL."""
-CEL_VERSION = "0.12.0"
+CEL_VERSION = "0.13.0"
diff --git a/runtime/src/main/java/dev/cel/runtime/BUILD.bazel b/runtime/src/main/java/dev/cel/runtime/BUILD.bazel
index 6f0607de4..ef0ac71d4 100644
--- a/runtime/src/main/java/dev/cel/runtime/BUILD.bazel
+++ b/runtime/src/main/java/dev/cel/runtime/BUILD.bazel
@@ -53,6 +53,7 @@ LITE_PROGRAM_IMPL_SOURCES = [
FUNCTION_BINDING_SOURCES = [
"CelFunctionBinding.java",
"FunctionBindingImpl.java",
+ "InternalCelFunctionBinding.java",
]
# keep sorted
@@ -740,6 +741,7 @@ java_library(
deps = [
":evaluation_exception",
":function_overload",
+ "//common/annotations",
"//common/exceptions:overload_not_found",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven//:com_google_guava_guava",
@@ -754,6 +756,7 @@ cel_android_library(
deps = [
":evaluation_exception",
":function_overload_android",
+ "//common/annotations",
"//common/exceptions:overload_not_found",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven_android//:com_google_guava_guava",
@@ -890,7 +893,6 @@ java_library(
"//common/types:type_providers",
"//common/values:cel_value_provider",
"//common/values:proto_message_value_provider",
- "//runtime/standard:add",
"//runtime/standard:int",
"//runtime/standard:timestamp",
"@maven//:com_google_code_findbugs_annotations",
diff --git a/runtime/src/main/java/dev/cel/runtime/CelFunctionBinding.java b/runtime/src/main/java/dev/cel/runtime/CelFunctionBinding.java
index 88be0d3c3..98991d383 100644
--- a/runtime/src/main/java/dev/cel/runtime/CelFunctionBinding.java
+++ b/runtime/src/main/java/dev/cel/runtime/CelFunctionBinding.java
@@ -100,6 +100,7 @@ static CelFunctionBinding from(
overloadId, ImmutableList.copyOf(argTypes), impl, /* isStrict= */ true);
}
+
/** See {@link #fromOverloads(String, Collection)}. */
static ImmutableSet fromOverloads(
String functionName, CelFunctionBinding... overloadBindings) {
diff --git a/runtime/src/main/java/dev/cel/runtime/CelLateFunctionBindings.java b/runtime/src/main/java/dev/cel/runtime/CelLateFunctionBindings.java
index 3d75845cf..2da08120c 100644
--- a/runtime/src/main/java/dev/cel/runtime/CelLateFunctionBindings.java
+++ b/runtime/src/main/java/dev/cel/runtime/CelLateFunctionBindings.java
@@ -63,7 +63,12 @@ public static CelLateFunctionBindings from(Collection functi
}
private static CelResolvedOverload createResolvedOverload(CelFunctionBinding binding) {
+ String functionName = binding.getOverloadId();
+ if (binding instanceof InternalCelFunctionBinding) {
+ functionName = ((InternalCelFunctionBinding) binding).getFunctionName();
+ }
return CelResolvedOverload.of(
+ functionName,
binding.getOverloadId(),
binding.getDefinition(),
binding.isStrict(),
diff --git a/runtime/src/main/java/dev/cel/runtime/CelResolvedOverload.java b/runtime/src/main/java/dev/cel/runtime/CelResolvedOverload.java
index 7063720a1..fbe9a3289 100644
--- a/runtime/src/main/java/dev/cel/runtime/CelResolvedOverload.java
+++ b/runtime/src/main/java/dev/cel/runtime/CelResolvedOverload.java
@@ -30,6 +30,9 @@
@Internal
public abstract class CelResolvedOverload {
+ /** The base function name. */
+ public abstract String getFunctionName();
+
/** The overload id of the function. */
public abstract String getOverloadId();
@@ -61,7 +64,7 @@ public Object invoke(Object[] args) throws CelEvaluationException {
|| CelFunctionOverload.canHandle(args, getParameterTypes(), isStrict())) {
return getDefinition().apply(args);
}
- throw new CelOverloadNotFoundException(getOverloadId());
+ throw new CelOverloadNotFoundException(getFunctionName(), ImmutableList.of(getOverloadId()));
}
public Object invoke(Object arg) throws CelEvaluationException {
@@ -69,7 +72,7 @@ public Object invoke(Object arg) throws CelEvaluationException {
|| CelFunctionOverload.canHandle(arg, getParameterTypes(), isStrict())) {
return getOptimizedDefinition().apply(arg);
}
- throw new CelOverloadNotFoundException(getOverloadId());
+ throw new CelOverloadNotFoundException(getFunctionName(), ImmutableList.of(getOverloadId()));
}
public Object invoke(Object arg1, Object arg2) throws CelEvaluationException {
@@ -77,24 +80,28 @@ public Object invoke(Object arg1, Object arg2) throws CelEvaluationException {
|| CelFunctionOverload.canHandle(arg1, arg2, getParameterTypes(), isStrict())) {
return getOptimizedDefinition().apply(arg1, arg2);
}
- throw new CelOverloadNotFoundException(getOverloadId());
+ throw new CelOverloadNotFoundException(getFunctionName(), ImmutableList.of(getOverloadId()));
}
/**
- * Creates a new resolved overload from the given overload id, parameter types, and definition.
+ * Creates a new resolved overload from the given function name, overload id, parameter types, and
+ * definition.
*/
public static CelResolvedOverload of(
+ String functionName,
String overloadId,
CelFunctionOverload definition,
boolean isStrict,
Class>... parameterTypes) {
- return of(overloadId, definition, isStrict, ImmutableList.copyOf(parameterTypes));
+ return of(functionName, overloadId, definition, isStrict, ImmutableList.copyOf(parameterTypes));
}
/**
- * Creates a new resolved overload from the given overload id, parameter types, and definition.
+ * Creates a new resolved overload from the given function name, overload id, parameter types, and
+ * definition.
*/
public static CelResolvedOverload of(
+ String functionName,
String overloadId,
CelFunctionOverload definition,
boolean isStrict,
@@ -104,7 +111,12 @@ public static CelResolvedOverload of(
? (OptimizedFunctionOverload) definition
: definition::apply;
return new AutoValue_CelResolvedOverload(
- overloadId, ImmutableList.copyOf(parameterTypes), isStrict, definition, optimizedDef);
+ functionName,
+ overloadId,
+ ImmutableList.copyOf(parameterTypes),
+ isStrict,
+ definition,
+ optimizedDef);
}
/**
diff --git a/runtime/src/main/java/dev/cel/runtime/CelRuntimeImpl.java b/runtime/src/main/java/dev/cel/runtime/CelRuntimeImpl.java
index cab2c666e..43b223fa0 100644
--- a/runtime/src/main/java/dev/cel/runtime/CelRuntimeImpl.java
+++ b/runtime/src/main/java/dev/cel/runtime/CelRuntimeImpl.java
@@ -381,7 +381,12 @@ private static DefaultDispatcher newDispatcher(
DefaultDispatcher.Builder builder = DefaultDispatcher.newBuilder();
for (CelFunctionBinding binding :
standardFunctions.newFunctionBindings(runtimeEquality, options)) {
+ String functionName = binding.getOverloadId();
+ if (binding instanceof InternalCelFunctionBinding) {
+ functionName = ((InternalCelFunctionBinding) binding).getFunctionName();
+ }
builder.addOverload(
+ functionName,
binding.getOverloadId(),
binding.getArgTypes(),
binding.isStrict(),
@@ -389,7 +394,12 @@ private static DefaultDispatcher newDispatcher(
}
for (CelFunctionBinding binding : customFunctionBindings) {
+ String functionName = binding.getOverloadId();
+ if (binding instanceof InternalCelFunctionBinding) {
+ functionName = ((InternalCelFunctionBinding) binding).getFunctionName();
+ }
builder.addOverload(
+ functionName,
binding.getOverloadId(),
binding.getArgTypes(),
binding.isStrict(),
diff --git a/runtime/src/main/java/dev/cel/runtime/CelRuntimeLegacyImpl.java b/runtime/src/main/java/dev/cel/runtime/CelRuntimeLegacyImpl.java
index 8ae4a9e3e..33702b2c6 100644
--- a/runtime/src/main/java/dev/cel/runtime/CelRuntimeLegacyImpl.java
+++ b/runtime/src/main/java/dev/cel/runtime/CelRuntimeLegacyImpl.java
@@ -305,7 +305,12 @@ public CelRuntimeLegacyImpl build() {
DefaultDispatcher.Builder dispatcherBuilder = DefaultDispatcher.newBuilder();
for (CelFunctionBinding standardFunctionBinding :
newStandardFunctionBindings(runtimeEquality)) {
+ String functionName = standardFunctionBinding.getOverloadId();
+ if (standardFunctionBinding instanceof InternalCelFunctionBinding) {
+ functionName = ((InternalCelFunctionBinding) standardFunctionBinding).getFunctionName();
+ }
dispatcherBuilder.addOverload(
+ functionName,
standardFunctionBinding.getOverloadId(),
standardFunctionBinding.getArgTypes(),
standardFunctionBinding.isStrict(),
@@ -313,7 +318,12 @@ public CelRuntimeLegacyImpl build() {
}
for (CelFunctionBinding customBinding : customFunctionBindings.values()) {
+ String functionName = customBinding.getOverloadId();
+ if (customBinding instanceof InternalCelFunctionBinding) {
+ functionName = ((InternalCelFunctionBinding) customBinding).getFunctionName();
+ }
dispatcherBuilder.addOverload(
+ functionName,
customBinding.getOverloadId(),
customBinding.getArgTypes(),
customBinding.isStrict(),
diff --git a/runtime/src/main/java/dev/cel/runtime/DefaultDispatcher.java b/runtime/src/main/java/dev/cel/runtime/DefaultDispatcher.java
index d6ddf3965..0a467db81 100644
--- a/runtime/src/main/java/dev/cel/runtime/DefaultDispatcher.java
+++ b/runtime/src/main/java/dev/cel/runtime/DefaultDispatcher.java
@@ -134,6 +134,8 @@ public static class Builder {
@AutoValue
@Immutable
abstract static class OverloadEntry {
+ abstract String functionName();
+
abstract ImmutableList> argTypes();
abstract boolean isStrict();
@@ -141,8 +143,12 @@ abstract static class OverloadEntry {
abstract CelFunctionOverload overload();
private static OverloadEntry of(
- ImmutableList> argTypes, boolean isStrict, CelFunctionOverload overload) {
- return new AutoValue_DefaultDispatcher_Builder_OverloadEntry(argTypes, isStrict, overload);
+ String functionName,
+ ImmutableList> argTypes,
+ boolean isStrict,
+ CelFunctionOverload overload) {
+ return new AutoValue_DefaultDispatcher_Builder_OverloadEntry(
+ functionName, argTypes, isStrict, overload);
}
}
@@ -150,16 +156,19 @@ private static OverloadEntry of(
@CanIgnoreReturnValue
public Builder addOverload(
+ String functionName,
String overloadId,
ImmutableList> argTypes,
boolean isStrict,
CelFunctionOverload overload) {
+ checkNotNull(functionName);
+ checkArgument(!functionName.isEmpty(), "Function name cannot be empty.");
checkNotNull(overloadId);
checkArgument(!overloadId.isEmpty(), "Overload ID cannot be empty.");
checkNotNull(argTypes);
checkNotNull(overload);
- OverloadEntry newEntry = OverloadEntry.of(argTypes, isStrict, overload);
+ OverloadEntry newEntry = OverloadEntry.of(functionName, argTypes, isStrict, overload);
overloads.merge(
overloadId,
@@ -188,7 +197,7 @@ private OverloadEntry mergeDynamicDispatchesOrThrow(
boolean isStrict =
mergedOverload.getOverloadBindings().stream().allMatch(CelFunctionBinding::isStrict);
- return OverloadEntry.of(incoming.argTypes(), isStrict, mergedOverload);
+ return OverloadEntry.of(overloadId, incoming.argTypes(), isStrict, mergedOverload);
}
throw new IllegalArgumentException("Duplicate overload ID binding: " + overloadId);
@@ -204,7 +213,11 @@ public DefaultDispatcher build() {
resolvedOverloads.put(
overloadId,
CelResolvedOverload.of(
- overloadId, overloadImpl, overloadEntry.isStrict(), overloadEntry.argTypes()));
+ overloadEntry.functionName(),
+ overloadId,
+ overloadImpl,
+ overloadEntry.isStrict(),
+ overloadEntry.argTypes()));
}
return new DefaultDispatcher(resolvedOverloads.buildOrThrow());
diff --git a/runtime/src/main/java/dev/cel/runtime/FunctionBindingImpl.java b/runtime/src/main/java/dev/cel/runtime/FunctionBindingImpl.java
index c1306ce19..7b8efe8fd 100644
--- a/runtime/src/main/java/dev/cel/runtime/FunctionBindingImpl.java
+++ b/runtime/src/main/java/dev/cel/runtime/FunctionBindingImpl.java
@@ -23,7 +23,9 @@
import dev.cel.common.exceptions.CelOverloadNotFoundException;
@Immutable
-final class FunctionBindingImpl implements CelFunctionBinding {
+final class FunctionBindingImpl implements InternalCelFunctionBinding {
+
+ private final String functionName;
private final String overloadId;
@@ -33,6 +35,11 @@ final class FunctionBindingImpl implements CelFunctionBinding {
private final boolean isStrict;
+ @Override
+ public String getFunctionName() {
+ return functionName;
+ }
+
@Override
public String getOverloadId() {
return overloadId;
@@ -54,20 +61,34 @@ public boolean isStrict() {
}
FunctionBindingImpl(
+ String functionName,
String overloadId,
ImmutableList> argTypes,
CelFunctionOverload definition,
boolean isStrict) {
+ this.functionName = functionName;
this.overloadId = overloadId;
this.argTypes = argTypes;
this.definition = definition;
this.isStrict = isStrict;
}
+ FunctionBindingImpl(
+ String overloadId,
+ ImmutableList> argTypes,
+ CelFunctionOverload definition,
+ boolean isStrict) {
+ this(overloadId, overloadId, argTypes, definition, isStrict);
+ }
+
static ImmutableSet groupOverloadsToFunction(
String functionName, ImmutableSet overloadBindings) {
ImmutableSet.Builder builder = ImmutableSet.builder();
- builder.addAll(overloadBindings);
+ for (CelFunctionBinding b : overloadBindings) {
+ builder.add(
+ new FunctionBindingImpl(
+ functionName, b.getOverloadId(), b.getArgTypes(), b.getDefinition(), b.isStrict()));
+ }
// If there is already a binding with the same name as the function, we treat it as a
// "Singleton" binding and do not create a dynamic dispatch wrapper for it.
@@ -80,11 +101,12 @@ static ImmutableSet groupOverloadsToFunction(
CelFunctionBinding singleBinding = Iterables.getOnlyElement(overloadBindings);
builder.add(
new FunctionBindingImpl(
+ functionName,
functionName,
singleBinding.getArgTypes(),
singleBinding.getDefinition(),
singleBinding.isStrict()));
- } else {
+ } else if (overloadBindings.size() > 1) {
builder.add(new DynamicDispatchBinding(functionName, overloadBindings));
}
}
@@ -93,7 +115,7 @@ static ImmutableSet groupOverloadsToFunction(
}
@Immutable
- static final class DynamicDispatchBinding implements CelFunctionBinding {
+ static final class DynamicDispatchBinding implements InternalCelFunctionBinding {
private final boolean isStrict;
private final DynamicDispatchOverload dynamicDispatchOverload;
@@ -103,6 +125,11 @@ public String getOverloadId() {
return dynamicDispatchOverload.functionName;
}
+ @Override
+ public String getFunctionName() {
+ return dynamicDispatchOverload.functionName;
+ }
+
@Override
public ImmutableList> getArgTypes() {
return ImmutableList.of();
diff --git a/runtime/src/main/java/dev/cel/runtime/InternalCelFunctionBinding.java b/runtime/src/main/java/dev/cel/runtime/InternalCelFunctionBinding.java
new file mode 100644
index 000000000..48a0f36d1
--- /dev/null
+++ b/runtime/src/main/java/dev/cel/runtime/InternalCelFunctionBinding.java
@@ -0,0 +1,29 @@
+// 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.runtime;
+
+import com.google.errorprone.annotations.Immutable;
+import dev.cel.common.annotations.Internal;
+
+/**
+ * Internal interface to expose the function name associated with a binding.
+ *
+ * CEL Library Internals. Do Not Use.
+ */
+@Internal
+@Immutable
+public interface InternalCelFunctionBinding extends CelFunctionBinding {
+ String getFunctionName();
+}
diff --git a/runtime/src/main/java/dev/cel/runtime/LiteRuntimeImpl.java b/runtime/src/main/java/dev/cel/runtime/LiteRuntimeImpl.java
index 0e5c5cf30..d58eb3be4 100644
--- a/runtime/src/main/java/dev/cel/runtime/LiteRuntimeImpl.java
+++ b/runtime/src/main/java/dev/cel/runtime/LiteRuntimeImpl.java
@@ -162,9 +162,18 @@ public CelLiteRuntime build() {
functionBindingsBuilder
.buildOrThrow()
.forEach(
- (String overloadId, CelFunctionBinding func) ->
- dispatcherBuilder.addOverload(
- overloadId, func.getArgTypes(), func.isStrict(), func.getDefinition()));
+ (String overloadId, CelFunctionBinding func) -> {
+ String functionName = func.getOverloadId();
+ if (func instanceof InternalCelFunctionBinding) {
+ functionName = ((InternalCelFunctionBinding) func).getFunctionName();
+ }
+ dispatcherBuilder.addOverload(
+ functionName,
+ overloadId,
+ func.getArgTypes(),
+ func.isStrict(),
+ func.getDefinition());
+ });
Interpreter interpreter =
new DefaultInterpreter(
diff --git a/runtime/src/main/java/dev/cel/runtime/planner/EvalBinary.java b/runtime/src/main/java/dev/cel/runtime/planner/EvalBinary.java
index 7771da3e6..16eba3cce 100644
--- a/runtime/src/main/java/dev/cel/runtime/planner/EvalBinary.java
+++ b/runtime/src/main/java/dev/cel/runtime/planner/EvalBinary.java
@@ -25,6 +25,7 @@
final class EvalBinary extends PlannedInterpretable {
+ private final String functionName;
private final CelResolvedOverload resolvedOverload;
private final PlannedInterpretable arg1;
private final PlannedInterpretable arg2;
@@ -48,25 +49,29 @@ public Object eval(GlobalResolver resolver, ExecutionFrame frame) throws CelEval
return unknowns;
}
- return EvalHelpers.dispatch(resolvedOverload, celValueConverter, argVal1, argVal2);
+ return EvalHelpers.dispatch(
+ functionName, resolvedOverload, celValueConverter, argVal1, argVal2);
}
static EvalBinary create(
long exprId,
+ String functionName,
CelResolvedOverload resolvedOverload,
PlannedInterpretable arg1,
PlannedInterpretable arg2,
CelValueConverter celValueConverter) {
- return new EvalBinary(exprId, resolvedOverload, arg1, arg2, celValueConverter);
+ return new EvalBinary(exprId, functionName, resolvedOverload, arg1, arg2, celValueConverter);
}
private EvalBinary(
long exprId,
+ String functionName,
CelResolvedOverload resolvedOverload,
PlannedInterpretable arg1,
PlannedInterpretable arg2,
CelValueConverter celValueConverter) {
super(exprId);
+ this.functionName = functionName;
this.resolvedOverload = resolvedOverload;
this.arg1 = arg1;
this.arg2 = arg2;
diff --git a/runtime/src/main/java/dev/cel/runtime/planner/EvalHelpers.java b/runtime/src/main/java/dev/cel/runtime/planner/EvalHelpers.java
index a30f91880..220642f4a 100644
--- a/runtime/src/main/java/dev/cel/runtime/planner/EvalHelpers.java
+++ b/runtime/src/main/java/dev/cel/runtime/planner/EvalHelpers.java
@@ -56,7 +56,10 @@ static Object evalStrictly(
}
static Object dispatch(
- CelResolvedOverload overload, CelValueConverter valueConverter, Object[] args)
+ String functionName,
+ CelResolvedOverload overload,
+ CelValueConverter valueConverter,
+ Object[] args)
throws CelEvaluationException {
try {
Object result = overload.invoke(args);
@@ -66,7 +69,11 @@ static Object dispatch(
}
}
- static Object dispatch(CelResolvedOverload overload, CelValueConverter valueConverter, Object arg)
+ static Object dispatch(
+ String functionName,
+ CelResolvedOverload overload,
+ CelValueConverter valueConverter,
+ Object arg)
throws CelEvaluationException {
try {
Object result = overload.invoke(arg);
@@ -77,7 +84,11 @@ static Object dispatch(CelResolvedOverload overload, CelValueConverter valueConv
}
static Object dispatch(
- CelResolvedOverload overload, CelValueConverter valueConverter, Object arg1, Object arg2)
+ String functionName,
+ CelResolvedOverload overload,
+ CelValueConverter valueConverter,
+ Object arg1,
+ Object arg2)
throws CelEvaluationException {
try {
Object result = overload.invoke(arg1, arg2);
@@ -97,7 +108,7 @@ private static RuntimeException handleDispatchException(
return new IllegalArgumentException(
String.format(
"Function '%s' failed with arg(s) '%s'",
- overload.getOverloadId(), Joiner.on(", ").join(args)),
+ overload.getFunctionName(), Joiner.on(", ").join(args)),
e);
}
diff --git a/runtime/src/main/java/dev/cel/runtime/planner/EvalLateBoundCall.java b/runtime/src/main/java/dev/cel/runtime/planner/EvalLateBoundCall.java
index cdee878ee..0bd251185 100644
--- a/runtime/src/main/java/dev/cel/runtime/planner/EvalLateBoundCall.java
+++ b/runtime/src/main/java/dev/cel/runtime/planner/EvalLateBoundCall.java
@@ -55,7 +55,7 @@ public Object eval(GlobalResolver resolver, ExecutionFrame frame) throws CelEval
.findOverload(functionName, overloadIds, argVals)
.orElseThrow(() -> new CelOverloadNotFoundException(functionName, overloadIds));
- return EvalHelpers.dispatch(resolvedOverload, celValueConverter, argVals);
+ return EvalHelpers.dispatch(functionName, resolvedOverload, celValueConverter, argVals);
}
static EvalLateBoundCall create(
diff --git a/runtime/src/main/java/dev/cel/runtime/planner/EvalUnary.java b/runtime/src/main/java/dev/cel/runtime/planner/EvalUnary.java
index 322648ee3..57834161f 100644
--- a/runtime/src/main/java/dev/cel/runtime/planner/EvalUnary.java
+++ b/runtime/src/main/java/dev/cel/runtime/planner/EvalUnary.java
@@ -24,6 +24,7 @@
final class EvalUnary extends PlannedInterpretable {
+ private final String functionName;
private final CelResolvedOverload resolvedOverload;
private final PlannedInterpretable arg;
private final CelValueConverter celValueConverter;
@@ -34,23 +35,26 @@ public Object eval(GlobalResolver resolver, ExecutionFrame frame) throws CelEval
resolvedOverload.isStrict()
? evalStrictly(arg, resolver, frame)
: evalNonstrictly(arg, resolver, frame);
- return EvalHelpers.dispatch(resolvedOverload, celValueConverter, argVal);
+ return EvalHelpers.dispatch(functionName, resolvedOverload, celValueConverter, argVal);
}
static EvalUnary create(
long exprId,
+ String functionName,
CelResolvedOverload resolvedOverload,
PlannedInterpretable arg,
CelValueConverter celValueConverter) {
- return new EvalUnary(exprId, resolvedOverload, arg, celValueConverter);
+ return new EvalUnary(exprId, functionName, resolvedOverload, arg, celValueConverter);
}
private EvalUnary(
long exprId,
+ String functionName,
CelResolvedOverload resolvedOverload,
PlannedInterpretable arg,
CelValueConverter celValueConverter) {
super(exprId);
+ this.functionName = functionName;
this.resolvedOverload = resolvedOverload;
this.arg = arg;
this.celValueConverter = celValueConverter;
diff --git a/runtime/src/main/java/dev/cel/runtime/planner/EvalVarArgsCall.java b/runtime/src/main/java/dev/cel/runtime/planner/EvalVarArgsCall.java
index eb8745632..fe7c6c430 100644
--- a/runtime/src/main/java/dev/cel/runtime/planner/EvalVarArgsCall.java
+++ b/runtime/src/main/java/dev/cel/runtime/planner/EvalVarArgsCall.java
@@ -25,6 +25,7 @@
final class EvalVarArgsCall extends PlannedInterpretable {
+ private final String functionName;
private final CelResolvedOverload resolvedOverload;
@SuppressWarnings("Immutable")
@@ -50,23 +51,26 @@ public Object eval(GlobalResolver resolver, ExecutionFrame frame) throws CelEval
return unknowns;
}
- return EvalHelpers.dispatch(resolvedOverload, celValueConverter, argVals);
+ return EvalHelpers.dispatch(functionName, resolvedOverload, celValueConverter, argVals);
}
static EvalVarArgsCall create(
long exprId,
+ String functionName,
CelResolvedOverload resolvedOverload,
PlannedInterpretable[] args,
CelValueConverter celValueConverter) {
- return new EvalVarArgsCall(exprId, resolvedOverload, args, celValueConverter);
+ return new EvalVarArgsCall(exprId, functionName, resolvedOverload, args, celValueConverter);
}
private EvalVarArgsCall(
long exprId,
+ String functionName,
CelResolvedOverload resolvedOverload,
PlannedInterpretable[] args,
CelValueConverter celValueConverter) {
super(exprId);
+ this.functionName = functionName;
this.resolvedOverload = resolvedOverload;
this.args = args;
this.celValueConverter = celValueConverter;
diff --git a/runtime/src/main/java/dev/cel/runtime/planner/EvalZeroArity.java b/runtime/src/main/java/dev/cel/runtime/planner/EvalZeroArity.java
index 5b3138207..7798c8253 100644
--- a/runtime/src/main/java/dev/cel/runtime/planner/EvalZeroArity.java
+++ b/runtime/src/main/java/dev/cel/runtime/planner/EvalZeroArity.java
@@ -22,22 +22,30 @@
final class EvalZeroArity extends PlannedInterpretable {
private static final Object[] EMPTY_ARRAY = new Object[0];
+ private final String functionName;
private final CelResolvedOverload resolvedOverload;
private final CelValueConverter celValueConverter;
@Override
public Object eval(GlobalResolver resolver, ExecutionFrame frame) throws CelEvaluationException {
- return EvalHelpers.dispatch(resolvedOverload, celValueConverter, EMPTY_ARRAY);
+ return EvalHelpers.dispatch(functionName, resolvedOverload, celValueConverter, EMPTY_ARRAY);
}
static EvalZeroArity create(
- long exprId, CelResolvedOverload resolvedOverload, CelValueConverter celValueConverter) {
- return new EvalZeroArity(exprId, resolvedOverload, celValueConverter);
+ long exprId,
+ String functionName,
+ CelResolvedOverload resolvedOverload,
+ CelValueConverter celValueConverter) {
+ return new EvalZeroArity(exprId, functionName, resolvedOverload, celValueConverter);
}
private EvalZeroArity(
- long exprId, CelResolvedOverload resolvedOverload, CelValueConverter celValueConverter) {
+ long exprId,
+ String functionName,
+ CelResolvedOverload resolvedOverload,
+ CelValueConverter celValueConverter) {
super(exprId);
+ this.functionName = functionName;
this.resolvedOverload = resolvedOverload;
this.celValueConverter = celValueConverter;
}
diff --git a/runtime/src/main/java/dev/cel/runtime/planner/ProgramPlanner.java b/runtime/src/main/java/dev/cel/runtime/planner/ProgramPlanner.java
index 9bd5f3ecd..a0b74fc99 100644
--- a/runtime/src/main/java/dev/cel/runtime/planner/ProgramPlanner.java
+++ b/runtime/src/main/java/dev/cel/runtime/planner/ProgramPlanner.java
@@ -308,15 +308,21 @@ private PlannedInterpretable planCall(CelExpr expr, PlannerContext ctx) {
switch (argCount) {
case 0:
- return EvalZeroArity.create(expr.id(), resolvedOverload, celValueConverter);
+ return EvalZeroArity.create(expr.id(), functionName, resolvedOverload, celValueConverter);
case 1:
- return EvalUnary.create(expr.id(), resolvedOverload, evaluatedArgs[0], celValueConverter);
+ return EvalUnary.create(
+ expr.id(), functionName, resolvedOverload, evaluatedArgs[0], celValueConverter);
case 2:
return EvalBinary.create(
- expr.id(), resolvedOverload, evaluatedArgs[0], evaluatedArgs[1], celValueConverter);
+ expr.id(),
+ functionName,
+ resolvedOverload,
+ evaluatedArgs[0],
+ evaluatedArgs[1],
+ celValueConverter);
default:
return EvalVarArgsCall.create(
- expr.id(), resolvedOverload, evaluatedArgs, celValueConverter);
+ expr.id(), functionName, resolvedOverload, evaluatedArgs, celValueConverter);
}
}
diff --git a/runtime/src/test/java/dev/cel/runtime/BUILD.bazel b/runtime/src/test/java/dev/cel/runtime/BUILD.bazel
index 577010971..7cd24f040 100644
--- a/runtime/src/test/java/dev/cel/runtime/BUILD.bazel
+++ b/runtime/src/test/java/dev/cel/runtime/BUILD.bazel
@@ -2,6 +2,7 @@ load("@rules_java//java:defs.bzl", "java_library")
load("//:cel_android_rules.bzl", "cel_android_local_test")
load("//:testing.bzl", "junit4_test_suites")
+# Invalidate cache after file removal
package(
default_applicable_licenses = ["//:license"],
default_testonly = True,
diff --git a/runtime/src/test/java/dev/cel/runtime/CelLiteRuntimeAndroidTest.java b/runtime/src/test/java/dev/cel/runtime/CelLiteRuntimeAndroidTest.java
index 54ce24417..73492d126 100644
--- a/runtime/src/test/java/dev/cel/runtime/CelLiteRuntimeAndroidTest.java
+++ b/runtime/src/test/java/dev/cel/runtime/CelLiteRuntimeAndroidTest.java
@@ -149,9 +149,10 @@ public void toRuntimeBuilder_propertiesCopied() {
assertThat(newRuntimeBuilder.standardFunctionBuilder.build())
.containsExactly(intFunction, equalsOperator)
.inOrder();
- assertThat(newRuntimeBuilder.customFunctionBindings).hasSize(2);
+ assertThat(newRuntimeBuilder.customFunctionBindings).hasSize(3);
assertThat(newRuntimeBuilder.customFunctionBindings).containsKey("string_isEmpty");
assertThat(newRuntimeBuilder.customFunctionBindings).containsKey("list_sets_intersects_list");
+ assertThat(newRuntimeBuilder.customFunctionBindings).containsKey("sets.intersects");
}
@Test
diff --git a/runtime/src/test/java/dev/cel/runtime/CelResolvedOverloadTest.java b/runtime/src/test/java/dev/cel/runtime/CelResolvedOverloadTest.java
index c1210c1ba..471282117 100644
--- a/runtime/src/test/java/dev/cel/runtime/CelResolvedOverloadTest.java
+++ b/runtime/src/test/java/dev/cel/runtime/CelResolvedOverloadTest.java
@@ -27,11 +27,13 @@ public final class CelResolvedOverloadTest {
CelResolvedOverload getIncrementIntOverload() {
return CelResolvedOverload.of(
- "increment_int",
- (args) -> {
- Long arg = (Long) args[0];
- return arg + 1;
- },
+ /* functionName= */ "increment_int",
+ /* overloadId= */ "increment_int_overload",
+ (CelFunctionOverload)
+ (args) -> {
+ Long arg = (Long) args[0];
+ return arg + 1;
+ },
/* isStrict= */ true,
Long.class);
}
@@ -45,14 +47,23 @@ public void canHandle_matchingTypes_returnsTrue() {
public void canHandle_nullMessageType_returnsFalse() {
CelResolvedOverload overload =
CelResolvedOverload.of(
- "identity", (args) -> args[0], /* isStrict= */ true, TestAllTypes.class);
+ /* functionName= */ "identity",
+ /* overloadId= */ "identity_overload",
+ (CelFunctionOverload) (args) -> args[0],
+ /* isStrict= */ true,
+ TestAllTypes.class);
assertThat(overload.canHandle(new Object[] {null})).isFalse();
}
@Test
public void canHandle_nullPrimitive_returnsFalse() {
CelResolvedOverload overload =
- CelResolvedOverload.of("identity", (args) -> args[0], /* isStrict= */ true, Long.class);
+ CelResolvedOverload.of(
+ /* functionName= */ "identity",
+ /* overloadId= */ "identity_overload",
+ (CelFunctionOverload) (args) -> args[0],
+ /* isStrict= */ true,
+ Long.class);
assertThat(overload.canHandle(new Object[] {null})).isFalse();
}
@@ -70,10 +81,12 @@ public void canHandle_nonMatchingArgCount_returnsFalse() {
public void canHandle_nonStrictOverload_returnsTrue() {
CelResolvedOverload nonStrictOverload =
CelResolvedOverload.of(
- "non_strict",
- (args) -> {
- return false;
- },
+ /* functionName= */ "non_strict",
+ /* overloadId= */ "non_strict_overload",
+ (CelFunctionOverload)
+ (args) -> {
+ return false;
+ },
/* isStrict= */ false,
Long.class,
Long.class);
@@ -87,10 +100,12 @@ public void canHandle_nonStrictOverload_returnsTrue() {
public void canHandle_nonStrictOverload_returnsFalse() {
CelResolvedOverload nonStrictOverload =
CelResolvedOverload.of(
- "non_strict",
- (args) -> {
- return false;
- },
+ /* functionName= */ "non_strict",
+ /* overloadId= */ "non_strict_overload",
+ (CelFunctionOverload)
+ (args) -> {
+ return false;
+ },
/* isStrict= */ false,
Long.class,
Long.class);
diff --git a/runtime/src/test/java/dev/cel/runtime/DefaultDispatcherTest.java b/runtime/src/test/java/dev/cel/runtime/DefaultDispatcherTest.java
index 255360ee1..d862ddb33 100644
--- a/runtime/src/test/java/dev/cel/runtime/DefaultDispatcherTest.java
+++ b/runtime/src/test/java/dev/cel/runtime/DefaultDispatcherTest.java
@@ -37,11 +37,19 @@ public void setup() {
overloads.put(
"overload_1",
CelResolvedOverload.of(
- "overload_1", args -> (Long) args[0] + 1, /* isStrict= */ true, Long.class));
+ /* functionName= */ "overload_1",
+ /* overloadId= */ "overload_1",
+ args -> (Long) args[0] + 1,
+ /* isStrict= */ true,
+ Long.class));
overloads.put(
"overload_2",
CelResolvedOverload.of(
- "overload_2", args -> (Long) args[0] + 2, /* isStrict= */ true, Long.class));
+ /* functionName= */ "overload_2",
+ /* overloadId= */ "overload_2",
+ args -> (Long) args[0] + 2,
+ /* isStrict= */ true,
+ Long.class));
}
@Test
diff --git a/runtime/src/test/java/dev/cel/runtime/DefaultInterpreterTest.java b/runtime/src/test/java/dev/cel/runtime/DefaultInterpreterTest.java
index 1a8f45161..bd0e96856 100644
--- a/runtime/src/test/java/dev/cel/runtime/DefaultInterpreterTest.java
+++ b/runtime/src/test/java/dev/cel/runtime/DefaultInterpreterTest.java
@@ -77,15 +77,21 @@ public Object adapt(String messageName, Object message) {
CelAbstractSyntaxTree ast = celCompiler.compile("[1].all(x, [2].all(y, error()))").getAst();
DefaultDispatcher.Builder dispatcherBuilder = DefaultDispatcher.newBuilder();
dispatcherBuilder.addOverload(
- "error",
- ImmutableList.of(long.class),
+ /* functionName= */ "error",
+ /* overloadId= */ "error_overload",
+ ImmutableList.>of(long.class),
/* isStrict= */ true,
(args) -> new IllegalArgumentException("Always throws"));
CelFunctionBinding notStrictlyFalseBinding =
NotStrictlyFalseOverload.NOT_STRICTLY_FALSE.newFunctionBinding(
CelOptions.DEFAULT,
RuntimeEquality.create(RuntimeHelpers.create(), CelOptions.DEFAULT));
+ String functionName = notStrictlyFalseBinding.getOverloadId();
+ if (notStrictlyFalseBinding instanceof InternalCelFunctionBinding) {
+ functionName = ((InternalCelFunctionBinding) notStrictlyFalseBinding).getFunctionName();
+ }
dispatcherBuilder.addOverload(
+ functionName,
notStrictlyFalseBinding.getOverloadId(),
notStrictlyFalseBinding.getArgTypes(),
notStrictlyFalseBinding.isStrict(),
diff --git a/runtime/src/test/java/dev/cel/runtime/PlannerInterpreterTest.java b/runtime/src/test/java/dev/cel/runtime/PlannerInterpreterTest.java
index 2b0e53298..c0b0f76c4 100644
--- a/runtime/src/test/java/dev/cel/runtime/PlannerInterpreterTest.java
+++ b/runtime/src/test/java/dev/cel/runtime/PlannerInterpreterTest.java
@@ -82,13 +82,14 @@ protected CelAbstractSyntaxTree prepareTest(CelTypeProvider typeProvider) {
@Override
public void optional_errors() {
- if (isParseOnly) {
- // Parsed-only evaluation contains function name in the
- // error message instead of the function overload.
- skipBaselineVerification();
- } else {
- super.optional_errors();
- }
+ // Exercised in planner_optional_errors instead
+ skipBaselineVerification();
+ }
+
+ @Test
+ public void planner_optional_errors() {
+ source = "optional.unwrap([dyn(1)])";
+ runTest(ImmutableMap.of());
}
@Override
diff --git a/runtime/src/test/java/dev/cel/runtime/planner/ProgramPlannerTest.java b/runtime/src/test/java/dev/cel/runtime/planner/ProgramPlannerTest.java
index de30902d3..c58ae782b 100644
--- a/runtime/src/test/java/dev/cel/runtime/planner/ProgramPlannerTest.java
+++ b/runtime/src/test/java/dev/cel/runtime/planner/ProgramPlannerTest.java
@@ -75,6 +75,7 @@
import dev.cel.runtime.CelUnknownSet;
import dev.cel.runtime.DefaultDispatcher;
import dev.cel.runtime.DescriptorTypeResolver;
+import dev.cel.runtime.InternalCelFunctionBinding;
import dev.cel.runtime.PartialVars;
import dev.cel.runtime.Program;
import dev.cel.runtime.RuntimeEquality;
@@ -244,6 +245,7 @@ private static void addBindingsToDispatcher(
overloadBindings.forEach(
overload ->
builder.addOverload(
+ ((InternalCelFunctionBinding) overload).getFunctionName(),
overload.getOverloadId(),
overload.getArgTypes(),
overload.isStrict(),
@@ -494,15 +496,11 @@ public void plan_call_zeroArgs() throws Exception {
public void plan_call_throws() throws Exception {
CelAbstractSyntaxTree ast = compile("error()");
Program program = PLANNER.plan(ast);
- String expectedOverloadId = isParseOnly ? "error" : "error_overload";
CelEvaluationException e = assertThrows(CelEvaluationException.class, program::eval);
assertThat(e)
.hasMessageThat()
- .contains(
- "evaluation error at :5: Function '"
- + expectedOverloadId
- + "' failed with arg(s) ''");
+ .contains("evaluation error at :5: Function 'error' failed with arg(s) ''");
assertThat(e).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
assertThat(e.getCause()).hasMessageThat().contains("Intentional error");
}
@@ -562,13 +560,11 @@ public void plan_call_mapIndex() throws Exception {
public void plan_call_noMatchingOverload_throws() throws Exception {
CelAbstractSyntaxTree ast = compile("concat(b'abc', dyn_var)");
Program program = PLANNER.plan(ast);
- String errorMsg;
+ String errorMsg =
+ "No matching overload for function 'concat'. Overload candidates: concat_bytes_bytes";
if (isParseOnly) {
- errorMsg =
- "No matching overload for function 'concat'. Overload candidates: concat_bytes_bytes,"
- + " bytes_concat_bytes";
- } else {
- errorMsg = "No matching overload for function 'concat_bytes_bytes'";
+ // Parsed-only evaluation includes both overloads as candidates due to dynamic dispatch
+ errorMsg += ", bytes_concat_bytes";
}
CelEvaluationException e =
diff --git a/runtime/src/test/resources/planner_optional_errors.baseline b/runtime/src/test/resources/planner_optional_errors.baseline
new file mode 100644
index 000000000..3d59fefca
--- /dev/null
+++ b/runtime/src/test/resources/planner_optional_errors.baseline
@@ -0,0 +1,5 @@
+Source: optional.unwrap([dyn(1)])
+=====>
+bindings: {}
+error: evaluation error at test_location:15: Function 'optional.unwrap' failed with arg(s) '[1]'
+error_code: INTERNAL_ERROR