From e966e90577bb83dfead7e2cd4ad353cbb68bf1e9 Mon Sep 17 00:00:00 2001 From: Sokwhan Huh Date: Mon, 5 Jan 2026 12:59:34 -0800 Subject: [PATCH] Migrate the runtime to use canonical CEL exception classes PiperOrigin-RevId: 852421357 --- common/BUILD.bazel | 7 -- common/exceptions/BUILD.bazel | 6 ++ .../src/main/java/dev/cel/common/BUILD.bazel | 12 --- .../dev/cel/common/exceptions/BUILD.bazel | 26 +++-- .../CelAttributeNotFoundException.java | 1 - .../exceptions/CelBadFormatException.java | 1 - .../exceptions/CelDivideByZeroException.java | 1 - .../CelIndexOutOfBoundsException.java | 1 - .../CelInvalidArgumentException.java | 1 - .../CelIterationLimitExceededException.java | 1 - .../CelNumericOverflowException.java | 1 - .../{ => exceptions}/CelRuntimeException.java | 9 +- .../java/dev/cel/common/internal/BUILD.bazel | 13 +-- .../cel/common/internal/DateTimeHelpers.java | 7 +- .../dev/cel/common/internal/ProtoAdapter.java | 7 +- .../cel/common/internal/ProtoLiteAdapter.java | 11 +-- .../main/java/dev/cel/extensions/BUILD.bazel | 1 + .../dev/cel/extensions/CelMathExtensions.java | 9 +- .../test/java/dev/cel/extensions/BUILD.bazel | 3 +- .../CelComprehensionsExtensionsTest.java | 8 +- .../src/main/java/dev/cel/runtime/BUILD.bazel | 32 +++--- .../CelEvaluationExceptionBuilder.java | 9 +- .../runtime/CelValueRuntimeTypeProvider.java | 15 +-- .../dev/cel/runtime/DefaultInterpreter.java | 2 +- .../runtime/DescriptorMessageProvider.java | 22 +---- .../java/dev/cel/runtime/RuntimeEquality.java | 7 +- .../java/dev/cel/runtime/RuntimeHelpers.java | 41 ++++---- .../java/dev/cel/runtime/planner/BUILD.bazel | 6 +- .../dev/cel/runtime/planner/EvalHelpers.java | 2 +- .../cel/runtime/planner/PlannedProgram.java | 2 +- .../runtime/planner/StrictErrorException.java | 2 +- .../dev/cel/runtime/standard/AddOperator.java | 9 +- .../runtime/standard/ArithmeticHelpers.java | 31 ------ .../java/dev/cel/runtime/standard/BUILD.bazel | 98 ++++++------------- .../cel/runtime/standard/BoolFunction.java | 11 +-- .../cel/runtime/standard/DivideOperator.java | 5 +- .../cel/runtime/standard/DoubleFunction.java | 5 +- .../runtime/standard/DurationFunction.java | 7 +- .../dev/cel/runtime/standard/IntFunction.java | 18 ++-- .../cel/runtime/standard/MatchesFunction.java | 7 +- .../cel/runtime/standard/ModuloOperator.java | 5 +- .../runtime/standard/MultiplyOperator.java | 9 +- .../cel/runtime/standard/NegateOperator.java | 5 +- .../cel/runtime/standard/StringFunction.java | 15 +-- .../runtime/standard/SubtractOperator.java | 9 +- .../runtime/standard/TimestampFunction.java | 7 +- .../cel/runtime/standard/UintFunction.java | 26 ++--- .../src/test/java/dev/cel/runtime/BUILD.bazel | 5 +- .../CelEvaluationExceptionBuilderTest.java | 8 +- .../cel/runtime/CelRuntimeLegacyImplTest.java | 3 +- .../DescriptorMessageProviderTest.java | 8 +- .../ProtoMessageRuntimeEqualityTest.java | 2 +- .../ProtoMessageRuntimeHelpersTest.java | 21 ++-- .../java/dev/cel/runtime/planner/BUILD.bazel | 1 + .../runtime/planner/ProgramPlannerTest.java | 7 +- 55 files changed, 226 insertions(+), 362 deletions(-) rename common/src/main/java/dev/cel/common/{ => exceptions}/CelRuntimeException.java (84%) delete mode 100644 runtime/src/main/java/dev/cel/runtime/standard/ArithmeticHelpers.java diff --git a/common/BUILD.bazel b/common/BUILD.bazel index 7b5c7af4c..21a124565 100644 --- a/common/BUILD.bazel +++ b/common/BUILD.bazel @@ -53,13 +53,6 @@ java_library( exports = ["//common/src/main/java/dev/cel/common:mutable_source"], ) -java_library( - name = "runtime_exception", - # used_by_android - visibility = ["//:internal"], - exports = ["//common/src/main/java/dev/cel/common:runtime_exception"], -) - java_library( name = "proto_json_adapter", exports = ["//common/src/main/java/dev/cel/common:proto_json_adapter"], diff --git a/common/exceptions/BUILD.bazel b/common/exceptions/BUILD.bazel index 96e07ac65..e24f2629c 100644 --- a/common/exceptions/BUILD.bazel +++ b/common/exceptions/BUILD.bazel @@ -5,6 +5,12 @@ package( default_visibility = ["//:internal"], ) +java_library( + name = "runtime_exception", + # used_by_android + exports = ["//common/src/main/java/dev/cel/common/exceptions:runtime_exception"], +) + java_library( name = "attribute_not_found", # used_by_android diff --git a/common/src/main/java/dev/cel/common/BUILD.bazel b/common/src/main/java/dev/cel/common/BUILD.bazel index 333ec4b78..ba223d213 100644 --- a/common/src/main/java/dev/cel/common/BUILD.bazel +++ b/common/src/main/java/dev/cel/common/BUILD.bazel @@ -172,18 +172,6 @@ java_library( ], ) -java_library( - name = "runtime_exception", - srcs = ["CelRuntimeException.java"], - # used_by_android - tags = [ - ], - deps = [ - ":error_codes", - "//common/annotations", - ], -) - java_library( name = "mutable_ast", srcs = ["CelMutableAst.java"], diff --git a/common/src/main/java/dev/cel/common/exceptions/BUILD.bazel b/common/src/main/java/dev/cel/common/exceptions/BUILD.bazel index 203866928..d000ef926 100644 --- a/common/src/main/java/dev/cel/common/exceptions/BUILD.bazel +++ b/common/src/main/java/dev/cel/common/exceptions/BUILD.bazel @@ -8,6 +8,18 @@ package( ], ) +java_library( + name = "runtime_exception", + srcs = ["CelRuntimeException.java"], + # used_by_android + tags = [ + ], + deps = [ + "//common:error_codes", + "//common/annotations", + ], +) + java_library( name = "attribute_not_found", srcs = ["CelAttributeNotFoundException.java"], @@ -15,8 +27,8 @@ java_library( tags = [ ], deps = [ + ":runtime_exception", "//common:error_codes", - "//common:runtime_exception", "//common/annotations", ], ) @@ -28,8 +40,8 @@ java_library( tags = [ ], deps = [ + ":runtime_exception", "//common:error_codes", - "//common:runtime_exception", "//common/annotations", ], ) @@ -41,8 +53,8 @@ java_library( tags = [ ], deps = [ + ":runtime_exception", "//common:error_codes", - "//common:runtime_exception", "//common/annotations", ], ) @@ -54,8 +66,8 @@ java_library( tags = [ ], deps = [ + ":runtime_exception", "//common:error_codes", - "//common:runtime_exception", "//common/annotations", ], ) @@ -67,8 +79,8 @@ java_library( tags = [ ], deps = [ + ":runtime_exception", "//common:error_codes", - "//common:runtime_exception", "//common/annotations", ], ) @@ -80,8 +92,8 @@ java_library( tags = [ ], deps = [ + ":runtime_exception", "//common:error_codes", - "//common:runtime_exception", "//common/annotations", ], ) @@ -93,8 +105,8 @@ java_library( tags = [ ], deps = [ + ":runtime_exception", "//common:error_codes", - "//common:runtime_exception", "//common/annotations", ], ) diff --git a/common/src/main/java/dev/cel/common/exceptions/CelAttributeNotFoundException.java b/common/src/main/java/dev/cel/common/exceptions/CelAttributeNotFoundException.java index 4aa43693d..6204fd2fe 100644 --- a/common/src/main/java/dev/cel/common/exceptions/CelAttributeNotFoundException.java +++ b/common/src/main/java/dev/cel/common/exceptions/CelAttributeNotFoundException.java @@ -15,7 +15,6 @@ package dev.cel.common.exceptions; import dev.cel.common.CelErrorCode; -import dev.cel.common.CelRuntimeException; import dev.cel.common.annotations.Internal; import java.util.Arrays; import java.util.Collection; diff --git a/common/src/main/java/dev/cel/common/exceptions/CelBadFormatException.java b/common/src/main/java/dev/cel/common/exceptions/CelBadFormatException.java index 92dde0101..ba4db602a 100644 --- a/common/src/main/java/dev/cel/common/exceptions/CelBadFormatException.java +++ b/common/src/main/java/dev/cel/common/exceptions/CelBadFormatException.java @@ -15,7 +15,6 @@ package dev.cel.common.exceptions; import dev.cel.common.CelErrorCode; -import dev.cel.common.CelRuntimeException; import dev.cel.common.annotations.Internal; /** Indicates that a data conversion failed due to a mismatch in the format specification. */ diff --git a/common/src/main/java/dev/cel/common/exceptions/CelDivideByZeroException.java b/common/src/main/java/dev/cel/common/exceptions/CelDivideByZeroException.java index d433d804c..c507797c5 100644 --- a/common/src/main/java/dev/cel/common/exceptions/CelDivideByZeroException.java +++ b/common/src/main/java/dev/cel/common/exceptions/CelDivideByZeroException.java @@ -15,7 +15,6 @@ package dev.cel.common.exceptions; import dev.cel.common.CelErrorCode; -import dev.cel.common.CelRuntimeException; import dev.cel.common.annotations.Internal; /** Indicates that a division by zero occurred. */ diff --git a/common/src/main/java/dev/cel/common/exceptions/CelIndexOutOfBoundsException.java b/common/src/main/java/dev/cel/common/exceptions/CelIndexOutOfBoundsException.java index 3c2d0d03a..72a6cd1c0 100644 --- a/common/src/main/java/dev/cel/common/exceptions/CelIndexOutOfBoundsException.java +++ b/common/src/main/java/dev/cel/common/exceptions/CelIndexOutOfBoundsException.java @@ -15,7 +15,6 @@ package dev.cel.common.exceptions; import dev.cel.common.CelErrorCode; -import dev.cel.common.CelRuntimeException; import dev.cel.common.annotations.Internal; /** Indicates that a list index access was attempted using an index that is out of bounds. */ diff --git a/common/src/main/java/dev/cel/common/exceptions/CelInvalidArgumentException.java b/common/src/main/java/dev/cel/common/exceptions/CelInvalidArgumentException.java index 5bbaf6cab..41358bb79 100644 --- a/common/src/main/java/dev/cel/common/exceptions/CelInvalidArgumentException.java +++ b/common/src/main/java/dev/cel/common/exceptions/CelInvalidArgumentException.java @@ -15,7 +15,6 @@ package dev.cel.common.exceptions; import dev.cel.common.CelErrorCode; -import dev.cel.common.CelRuntimeException; import dev.cel.common.annotations.Internal; /** Indicates that an invalid argument was supplied to a function. */ diff --git a/common/src/main/java/dev/cel/common/exceptions/CelIterationLimitExceededException.java b/common/src/main/java/dev/cel/common/exceptions/CelIterationLimitExceededException.java index ef0f1d8e3..cfaa25f35 100644 --- a/common/src/main/java/dev/cel/common/exceptions/CelIterationLimitExceededException.java +++ b/common/src/main/java/dev/cel/common/exceptions/CelIterationLimitExceededException.java @@ -15,7 +15,6 @@ package dev.cel.common.exceptions; import dev.cel.common.CelErrorCode; -import dev.cel.common.CelRuntimeException; import dev.cel.common.annotations.Internal; import java.util.Locale; diff --git a/common/src/main/java/dev/cel/common/exceptions/CelNumericOverflowException.java b/common/src/main/java/dev/cel/common/exceptions/CelNumericOverflowException.java index 439d1348f..78fbe807e 100644 --- a/common/src/main/java/dev/cel/common/exceptions/CelNumericOverflowException.java +++ b/common/src/main/java/dev/cel/common/exceptions/CelNumericOverflowException.java @@ -15,7 +15,6 @@ package dev.cel.common.exceptions; import dev.cel.common.CelErrorCode; -import dev.cel.common.CelRuntimeException; import dev.cel.common.annotations.Internal; /** diff --git a/common/src/main/java/dev/cel/common/CelRuntimeException.java b/common/src/main/java/dev/cel/common/exceptions/CelRuntimeException.java similarity index 84% rename from common/src/main/java/dev/cel/common/CelRuntimeException.java rename to common/src/main/java/dev/cel/common/exceptions/CelRuntimeException.java index 3856d77f5..c87e192bd 100644 --- a/common/src/main/java/dev/cel/common/CelRuntimeException.java +++ b/common/src/main/java/dev/cel/common/exceptions/CelRuntimeException.java @@ -12,21 +12,22 @@ // See the License for the specific language governing permissions and // limitations under the License. -package dev.cel.common; +package dev.cel.common.exceptions; +import dev.cel.common.CelErrorCode; import dev.cel.common.annotations.Internal; /** * Wrapper for an unchecked runtime exception with a CelErrorCode supplied. * *

Note: This is not to be confused with the notion of CEL Runtime. Use {@code - * CelEvaluationException} instead to signify an evaluation error. corresponds to the CelErrorCode. + * CelEvaluationException} instead to signify an evaluation error. */ @Internal -public class CelRuntimeException extends RuntimeException { +public abstract class CelRuntimeException extends RuntimeException { private final CelErrorCode errorCode; - public CelRuntimeException(String errorMessage, CelErrorCode errorCode) { + CelRuntimeException(String errorMessage, CelErrorCode errorCode) { super(errorMessage); this.errorCode = errorCode; } diff --git a/common/src/main/java/dev/cel/common/internal/BUILD.bazel b/common/src/main/java/dev/cel/common/internal/BUILD.bazel index ca8f6375e..a0e564788 100644 --- a/common/src/main/java/dev/cel/common/internal/BUILD.bazel +++ b/common/src/main/java/dev/cel/common/internal/BUILD.bazel @@ -173,11 +173,9 @@ java_library( ":proto_lite_adapter", ":proto_message_factory", ":well_known_proto", - "//:auto_value", - "//common:error_codes", "//common:options", - "//common:runtime_exception", "//common/annotations", + "//common/exceptions:numeric_overflow", "//common/values", "//common/values:cel_byte_string", "@maven//:com_google_code_findbugs_annotations", @@ -194,11 +192,10 @@ java_library( ], deps = [ ":well_known_proto", - "//common:error_codes", "//common:options", "//common:proto_json_adapter", - "//common:runtime_exception", "//common/annotations", + "//common/exceptions:numeric_overflow", "//common/internal:proto_time_utils", "//common/values", "//common/values:cel_byte_string", @@ -441,9 +438,8 @@ java_library( tags = [ ], deps = [ - "//common:error_codes", - "//common:runtime_exception", "//common/annotations", + "//common/exceptions:bad_format", "@maven//:com_google_guava_guava", "@maven//:com_google_protobuf_protobuf_java", ], @@ -455,9 +451,8 @@ cel_android_library( tags = [ ], deps = [ - "//common:error_codes", - "//common:runtime_exception", "//common/annotations", + "//common/exceptions:bad_format", "@maven_android//:com_google_guava_guava", "@maven_android//:com_google_protobuf_protobuf_javalite", ], diff --git a/common/src/main/java/dev/cel/common/internal/DateTimeHelpers.java b/common/src/main/java/dev/cel/common/internal/DateTimeHelpers.java index 1d11caf63..805a9bd75 100644 --- a/common/src/main/java/dev/cel/common/internal/DateTimeHelpers.java +++ b/common/src/main/java/dev/cel/common/internal/DateTimeHelpers.java @@ -16,9 +16,8 @@ import com.google.common.base.Strings; import com.google.protobuf.Timestamp; -import dev.cel.common.CelErrorCode; -import dev.cel.common.CelRuntimeException; import dev.cel.common.annotations.Internal; +import dev.cel.common.exceptions.CelBadFormatException; import java.time.DateTimeException; import java.time.Duration; import java.time.Instant; @@ -184,7 +183,7 @@ private static ZoneId timeZone(String tz) { try { int ind = tz.indexOf(":"); if (ind == -1) { - throw new CelRuntimeException(e, CelErrorCode.BAD_FORMAT); + throw new CelBadFormatException(e); } int hourOffset = Integer.parseInt(tz.substring(0, ind)); @@ -199,7 +198,7 @@ private static ZoneId timeZone(String tz) { return ZoneId.of(formattedOffset); } catch (DateTimeException e2) { - throw new CelRuntimeException(e2, CelErrorCode.BAD_FORMAT); + throw new CelBadFormatException(e2); } } } diff --git a/common/src/main/java/dev/cel/common/internal/ProtoAdapter.java b/common/src/main/java/dev/cel/common/internal/ProtoAdapter.java index cd4be2f5e..3c3382ef2 100644 --- a/common/src/main/java/dev/cel/common/internal/ProtoAdapter.java +++ b/common/src/main/java/dev/cel/common/internal/ProtoAdapter.java @@ -31,10 +31,9 @@ import com.google.protobuf.MapEntry; import com.google.protobuf.Message; import com.google.protobuf.MessageOrBuilder; -import dev.cel.common.CelErrorCode; import dev.cel.common.CelOptions; -import dev.cel.common.CelRuntimeException; import dev.cel.common.annotations.Internal; +import dev.cel.common.exceptions.CelNumericOverflowException; import dev.cel.common.values.CelByteString; import dev.cel.common.values.NullValue; import java.util.ArrayList; @@ -361,7 +360,7 @@ private static int intCheckedCast(long value) { try { return Ints.checkedCast(value); } catch (IllegalArgumentException e) { - throw new CelRuntimeException(e, CelErrorCode.NUMERIC_OVERFLOW); + throw new CelNumericOverflowException(e); } } @@ -369,7 +368,7 @@ private static int unsignedIntCheckedCast(long value) { try { return UnsignedInts.checkedCast(value); } catch (IllegalArgumentException e) { - throw new CelRuntimeException(e, CelErrorCode.NUMERIC_OVERFLOW); + throw new CelNumericOverflowException(e); } } } diff --git a/common/src/main/java/dev/cel/common/internal/ProtoLiteAdapter.java b/common/src/main/java/dev/cel/common/internal/ProtoLiteAdapter.java index e05d92f68..3b13ecea1 100644 --- a/common/src/main/java/dev/cel/common/internal/ProtoLiteAdapter.java +++ b/common/src/main/java/dev/cel/common/internal/ProtoLiteAdapter.java @@ -42,11 +42,10 @@ import com.google.protobuf.UInt32Value; import com.google.protobuf.UInt64Value; import com.google.protobuf.Value; -import dev.cel.common.CelErrorCode; import dev.cel.common.CelOptions; import dev.cel.common.CelProtoJsonAdapter; -import dev.cel.common.CelRuntimeException; import dev.cel.common.annotations.Internal; +import dev.cel.common.exceptions.CelNumericOverflowException; import dev.cel.common.values.CelByteString; import java.time.Instant; import java.util.Map; @@ -284,14 +283,14 @@ private Message adaptValueToUint32(Object value) { try { return UInt32Value.of(unsignedIntCheckedCast((Long) value)); } catch (IllegalArgumentException e) { - throw new CelRuntimeException(e, CelErrorCode.NUMERIC_OVERFLOW); + throw new CelNumericOverflowException(e); } } if (value instanceof UnsignedLong) { try { return UInt32Value.of(unsignedIntCheckedCast(((UnsignedLong) value).longValue())); } catch (IllegalArgumentException e) { - throw new CelRuntimeException(e, CelErrorCode.NUMERIC_OVERFLOW); + throw new CelNumericOverflowException(e); } } @@ -316,7 +315,7 @@ private static int intCheckedCast(long value) { try { return Ints.checkedCast(value); } catch (IllegalArgumentException e) { - throw new CelRuntimeException(e, CelErrorCode.NUMERIC_OVERFLOW); + throw new CelNumericOverflowException(e); } } @@ -324,7 +323,7 @@ private static int unsignedIntCheckedCast(long value) { try { return UnsignedInts.checkedCast(value); } catch (IllegalArgumentException e) { - throw new CelRuntimeException(e, CelErrorCode.NUMERIC_OVERFLOW); + throw new CelNumericOverflowException(e); } } diff --git a/extensions/src/main/java/dev/cel/extensions/BUILD.bazel b/extensions/src/main/java/dev/cel/extensions/BUILD.bazel index 9b897cf84..ed2d19d6f 100644 --- a/extensions/src/main/java/dev/cel/extensions/BUILD.bazel +++ b/extensions/src/main/java/dev/cel/extensions/BUILD.bazel @@ -123,6 +123,7 @@ java_library( "//common:compiler_common", "//common:options", "//common/ast", + "//common/exceptions:numeric_overflow", "//common/internal:comparison_functions", "//common/types", "//compiler:compiler_builder", diff --git a/extensions/src/main/java/dev/cel/extensions/CelMathExtensions.java b/extensions/src/main/java/dev/cel/extensions/CelMathExtensions.java index 1e318aedc..e74177bf1 100644 --- a/extensions/src/main/java/dev/cel/extensions/CelMathExtensions.java +++ b/extensions/src/main/java/dev/cel/extensions/CelMathExtensions.java @@ -32,6 +32,7 @@ import dev.cel.common.ast.CelConstant; import dev.cel.common.ast.CelExpr; import dev.cel.common.ast.CelExpr.ExprKind.Kind; +import dev.cel.common.exceptions.CelNumericOverflowException; import dev.cel.common.internal.ComparisonFunctions; import dev.cel.common.types.ListType; import dev.cel.common.types.SimpleType; @@ -216,8 +217,7 @@ enum Function { "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)), + CelFunctionBinding.from("math_@max_list_dyn", List.class, CelMathExtensions::maxList)), ImmutableSet.of( CelFunctionBinding.from("math_@max_uint", Long.class, x -> x), CelFunctionBinding.from( @@ -640,8 +640,7 @@ enum Function { ImmutableSet.of( CelFunctionBinding.from( "math_sqrt_double", Double.class, CelMathExtensions::sqrtDouble), - CelFunctionBinding.from( - "math_sqrt_int", Long.class, CelMathExtensions::sqrtInt), + CelFunctionBinding.from("math_sqrt_int", Long.class, CelMathExtensions::sqrtInt), CelFunctionBinding.from( "math_sqrt_uint", UnsignedLong.class, CelMathExtensions::sqrtUint))); @@ -856,7 +855,7 @@ private static Comparable minPair(Comparable x, Comparable y) { private static long absExact(long x) { if (x == Long.MIN_VALUE) { // The only case where standard Math.abs overflows silently - throw new ArithmeticException("integer overflow"); + throw new CelNumericOverflowException("integer overflow"); } return Math.abs(x); } diff --git a/extensions/src/test/java/dev/cel/extensions/BUILD.bazel b/extensions/src/test/java/dev/cel/extensions/BUILD.bazel index 45d48aeca..d5155f662 100644 --- a/extensions/src/test/java/dev/cel/extensions/BUILD.bazel +++ b/extensions/src/test/java/dev/cel/extensions/BUILD.bazel @@ -14,7 +14,8 @@ java_library( "//common:compiler_common", "//common:container", "//common:options", - "//common/internal:proto_time_utils", + "//common/exceptions:divide_by_zero", + "//common/exceptions:index_out_of_bounds", "//common/types", "//common/types:type_providers", "//common/values", diff --git a/extensions/src/test/java/dev/cel/extensions/CelComprehensionsExtensionsTest.java b/extensions/src/test/java/dev/cel/extensions/CelComprehensionsExtensionsTest.java index 5318234b9..34696b688 100644 --- a/extensions/src/test/java/dev/cel/extensions/CelComprehensionsExtensionsTest.java +++ b/extensions/src/test/java/dev/cel/extensions/CelComprehensionsExtensionsTest.java @@ -24,6 +24,8 @@ import dev.cel.common.CelFunctionDecl; import dev.cel.common.CelOptions; import dev.cel.common.CelValidationException; +import dev.cel.common.exceptions.CelDivideByZeroException; +import dev.cel.common.exceptions.CelIndexOutOfBoundsException; import dev.cel.common.types.SimpleType; import dev.cel.common.types.TypeParamType; import dev.cel.compiler.CelCompiler; @@ -347,13 +349,13 @@ public void twoVarComprehension_keyCollision_runtimeError(String expr, String er } @Test - public void twoVarComprehension_arithematicException_runtimeError() throws Exception { + public void twoVarComprehension_arithmeticException_runtimeError() throws Exception { CelAbstractSyntaxTree ast = CEL_COMPILER.compile("[0].all(i, k, i/k < k)").getAst(); CelEvaluationException e = assertThrows(CelEvaluationException.class, () -> CEL_RUNTIME.createProgram(ast).eval()); - assertThat(e).hasCauseThat().isInstanceOf(ArithmeticException.class); + assertThat(e).hasCauseThat().isInstanceOf(CelDivideByZeroException.class); assertThat(e).hasCauseThat().hasMessageThat().contains("/ by zero"); } @@ -364,7 +366,7 @@ public void twoVarComprehension_outOfBounds_runtimeError() throws Exception { CelEvaluationException e = assertThrows(CelEvaluationException.class, () -> CEL_RUNTIME.createProgram(ast).eval()); - assertThat(e).hasCauseThat().isInstanceOf(IndexOutOfBoundsException.class); + assertThat(e).hasCauseThat().isInstanceOf(CelIndexOutOfBoundsException.class); assertThat(e).hasCauseThat().hasMessageThat().contains("Index out of bounds: 1"); } } diff --git a/runtime/src/main/java/dev/cel/runtime/BUILD.bazel b/runtime/src/main/java/dev/cel/runtime/BUILD.bazel index cf89d0a80..ac5599ba9 100644 --- a/runtime/src/main/java/dev/cel/runtime/BUILD.bazel +++ b/runtime/src/main/java/dev/cel/runtime/BUILD.bazel @@ -98,10 +98,9 @@ java_library( ":runtime_type_provider", "//common:cel_descriptor_util", "//common:cel_descriptors", - "//common:error_codes", "//common:options", - "//common:runtime_exception", "//common/annotations", + "//common/exceptions:attribute_not_found", "//common/internal:cel_descriptor_pools", "//common/internal:default_message_factory", "//common/internal:dynamic_proto", @@ -298,9 +297,9 @@ java_library( "//common:cel_ast", "//common:error_codes", "//common:options", - "//common:runtime_exception", "//common/annotations", "//common/ast", + "//common/exceptions:runtime_exception", "//common/types", "//common/types:type_providers", "//common/values:cel_byte_string", @@ -308,7 +307,6 @@ java_library( "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", "@maven//:com_google_protobuf_protobuf_java", - "@maven//:org_jspecify_jspecify", ], ) @@ -337,9 +335,9 @@ cel_android_library( "//common:cel_ast_android", "//common:error_codes", "//common:options", - "//common:runtime_exception", "//common/annotations", "//common/ast:ast_android", + "//common/exceptions:runtime_exception", "//common/types:type_providers_android", "//common/types:types_android", "//common/values:cel_byte_string", @@ -360,10 +358,9 @@ java_library( ], deps = [ ":runtime_helpers", - "//common:error_codes", "//common:options", - "//common:runtime_exception", "//common/annotations", + "//common/exceptions:attribute_not_found", "//common/internal:comparison_functions", "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", @@ -378,10 +375,9 @@ cel_android_library( ], deps = [ ":runtime_helpers_android", - "//common:error_codes", "//common:options", - "//common:runtime_exception", "//common/annotations", + "//common/exceptions:attribute_not_found", "//common/internal:comparison_functions_android", "@maven//:com_google_errorprone_error_prone_annotations", "@maven_android//:com_google_guava_guava", @@ -416,10 +412,11 @@ cel_android_library( ], deps = [ ":concatenated_list_view", - "//common:error_codes", "//common:options", - "//common:runtime_exception", "//common/annotations", + "//common/exceptions:divide_by_zero", + "//common/exceptions:index_out_of_bounds", + "//common/exceptions:numeric_overflow", "//common/internal:converter", "//common/values:values_android", "@maven//:com_google_errorprone_error_prone_annotations", @@ -439,10 +436,11 @@ java_library( ], deps = [ ":concatenated_list_view", - "//common:error_codes", "//common:options", - "//common:runtime_exception", "//common/annotations", + "//common/exceptions:divide_by_zero", + "//common/exceptions:index_out_of_bounds", + "//common/exceptions:numeric_overflow", "//common/internal:converter", "//common/values", "@maven//:com_google_errorprone_error_prone_annotations", @@ -558,8 +556,8 @@ java_library( ":evaluation_exception", ":metadata", "//common:error_codes", - "//common:runtime_exception", "//common/annotations", + "//common/exceptions:runtime_exception", "//common/internal:safe_string_formatter", "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:org_jspecify_jspecify", @@ -1032,9 +1030,8 @@ java_library( deps = [ ":runtime_type_provider", ":unknown_attributes", - "//common:error_codes", - "//common:runtime_exception", "//common/annotations", + "//common/exceptions:attribute_not_found", "//common/values", "//common/values:base_proto_cel_value_converter", "//common/values:base_proto_message_value_provider", @@ -1053,9 +1050,8 @@ cel_android_library( deps = [ ":runtime_type_provider_android", ":unknown_attributes_android", - "//common:error_codes", - "//common:runtime_exception", "//common/annotations", + "//common/exceptions:attribute_not_found", "//common/values:base_proto_cel_value_converter_android", "//common/values:base_proto_message_value_provider_android", "//common/values:cel_value_android", diff --git a/runtime/src/main/java/dev/cel/runtime/CelEvaluationExceptionBuilder.java b/runtime/src/main/java/dev/cel/runtime/CelEvaluationExceptionBuilder.java index 6adbcb672..986788bac 100644 --- a/runtime/src/main/java/dev/cel/runtime/CelEvaluationExceptionBuilder.java +++ b/runtime/src/main/java/dev/cel/runtime/CelEvaluationExceptionBuilder.java @@ -16,8 +16,8 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue; import dev.cel.common.CelErrorCode; -import dev.cel.common.CelRuntimeException; import dev.cel.common.annotations.Internal; +import dev.cel.common.exceptions.CelRuntimeException; import dev.cel.common.internal.SafeStringFormatter; import org.jspecify.annotations.Nullable; @@ -83,16 +83,15 @@ public static CelEvaluationExceptionBuilder newBuilder(String message, Object... */ @Internal public static CelEvaluationExceptionBuilder newBuilder(CelRuntimeException celRuntimeException) { - // TODO: Temporary until migration is complete. - Throwable cause = celRuntimeException.getCause(); + // Intercept the cause to prevent including the cause's class name in the exception message. String message = - cause == null + celRuntimeException.getCause() == null ? celRuntimeException.getMessage() : celRuntimeException.getCause().getMessage(); return new CelEvaluationExceptionBuilder(message) .setErrorCode(celRuntimeException.getErrorCode()) - .setCause(cause); + .setCause(celRuntimeException); } private CelEvaluationExceptionBuilder(String message) { diff --git a/runtime/src/main/java/dev/cel/runtime/CelValueRuntimeTypeProvider.java b/runtime/src/main/java/dev/cel/runtime/CelValueRuntimeTypeProvider.java index 989d3b7be..e071289ca 100644 --- a/runtime/src/main/java/dev/cel/runtime/CelValueRuntimeTypeProvider.java +++ b/runtime/src/main/java/dev/cel/runtime/CelValueRuntimeTypeProvider.java @@ -18,9 +18,8 @@ import com.google.errorprone.annotations.Immutable; import com.google.protobuf.MessageLite; -import dev.cel.common.CelErrorCode; -import dev.cel.common.CelRuntimeException; import dev.cel.common.annotations.Internal; +import dev.cel.common.exceptions.CelAttributeNotFoundException; import dev.cel.common.values.BaseProtoCelValueConverter; import dev.cel.common.values.BaseProtoMessageValueProvider; import dev.cel.common.values.CelValue; @@ -82,9 +81,7 @@ public Object selectField(Object message, String fieldName) { return map.get(fieldName); } - throw new CelRuntimeException( - new IllegalArgumentException(String.format("key '%s' is not present in map.", fieldName)), - CelErrorCode.ATTRIBUTE_NOT_FOUND); + throw CelAttributeNotFoundException.forMissingMapKey(fieldName); } SelectableValue selectableValue = getSelectableValueOrThrow(message, fieldName); @@ -142,13 +139,7 @@ private Object maybeUnwrapCelValue(Object object) { } private static void throwInvalidFieldSelection(String fieldName) { - throw new CelRuntimeException( - new IllegalArgumentException( - String.format( - "Error resolving field '%s'. Field selections must be performed on messages or" - + " maps.", - fieldName)), - CelErrorCode.ATTRIBUTE_NOT_FOUND); + throw CelAttributeNotFoundException.forFieldResolution(fieldName); } private CelValueRuntimeTypeProvider( diff --git a/runtime/src/main/java/dev/cel/runtime/DefaultInterpreter.java b/runtime/src/main/java/dev/cel/runtime/DefaultInterpreter.java index 47e3d3b13..ba5d05915 100644 --- a/runtime/src/main/java/dev/cel/runtime/DefaultInterpreter.java +++ b/runtime/src/main/java/dev/cel/runtime/DefaultInterpreter.java @@ -31,7 +31,6 @@ import dev.cel.common.CelAbstractSyntaxTree; import dev.cel.common.CelErrorCode; import dev.cel.common.CelOptions; -import dev.cel.common.CelRuntimeException; import dev.cel.common.ast.CelConstant; import dev.cel.common.ast.CelExpr; import dev.cel.common.ast.CelExpr.CelCall; @@ -42,6 +41,7 @@ import dev.cel.common.ast.CelExpr.CelStruct; import dev.cel.common.ast.CelExpr.ExprKind; import dev.cel.common.ast.CelReference; +import dev.cel.common.exceptions.CelRuntimeException; import dev.cel.common.types.CelKind; import dev.cel.common.types.CelType; import dev.cel.common.types.TypeType; diff --git a/runtime/src/main/java/dev/cel/runtime/DescriptorMessageProvider.java b/runtime/src/main/java/dev/cel/runtime/DescriptorMessageProvider.java index ab6934e01..f2ea85b9b 100644 --- a/runtime/src/main/java/dev/cel/runtime/DescriptorMessageProvider.java +++ b/runtime/src/main/java/dev/cel/runtime/DescriptorMessageProvider.java @@ -21,10 +21,9 @@ import com.google.protobuf.Message; import com.google.protobuf.MessageOrBuilder; import com.google.protobuf.NullValue; -import dev.cel.common.CelErrorCode; import dev.cel.common.CelOptions; -import dev.cel.common.CelRuntimeException; import dev.cel.common.annotations.Internal; +import dev.cel.common.exceptions.CelAttributeNotFoundException; import dev.cel.common.internal.DynamicProto; import dev.cel.common.internal.ProtoAdapter; import dev.cel.common.internal.ProtoMessageFactory; @@ -79,10 +78,8 @@ public DescriptorMessageProvider(ProtoMessageFactory protoMessageFactory, CelOpt .newBuilder(messageName) .orElseThrow( () -> - new CelRuntimeException( - new IllegalArgumentException( - String.format("cannot resolve '%s' as a message", messageName)), - CelErrorCode.ATTRIBUTE_NOT_FOUND)); + CelAttributeNotFoundException.of( + String.format("cannot resolve '%s' as a message", messageName))); try { Descriptor descriptor = builder.getDescriptorForType(); @@ -122,10 +119,7 @@ public DescriptorMessageProvider(ProtoMessageFactory protoMessageFactory, CelOpt if (isOptionalMessage) { return Optional.empty(); } else { - throw new CelRuntimeException( - new IllegalArgumentException( - String.format("key '%s' is not present in map.", fieldName)), - CelErrorCode.ATTRIBUTE_NOT_FOUND); + throw CelAttributeNotFoundException.forMissingMapKey(fieldName); } } @@ -197,13 +191,7 @@ private FieldDescriptor findField(Descriptor descriptor, String fieldName) { private static MessageOrBuilder assertFullProtoMessage(Object candidate, String fieldName) { if (!(candidate instanceof MessageOrBuilder)) { // This can happen when the field selection is done on dyn, and it is not a message. - throw new CelRuntimeException( - new IllegalArgumentException( - String.format( - "Error resolving field '%s'. Field selections must be performed on messages or" - + " maps.", - fieldName)), - CelErrorCode.ATTRIBUTE_NOT_FOUND); + throw CelAttributeNotFoundException.forFieldResolution(fieldName); } return (MessageOrBuilder) candidate; } diff --git a/runtime/src/main/java/dev/cel/runtime/RuntimeEquality.java b/runtime/src/main/java/dev/cel/runtime/RuntimeEquality.java index 912462e00..56a8761cd 100644 --- a/runtime/src/main/java/dev/cel/runtime/RuntimeEquality.java +++ b/runtime/src/main/java/dev/cel/runtime/RuntimeEquality.java @@ -17,10 +17,9 @@ import com.google.common.primitives.UnsignedLong; import com.google.errorprone.annotations.Immutable; import com.google.protobuf.MessageLiteOrBuilder; -import dev.cel.common.CelErrorCode; import dev.cel.common.CelOptions; -import dev.cel.common.CelRuntimeException; import dev.cel.common.annotations.Internal; +import dev.cel.common.exceptions.CelAttributeNotFoundException; import dev.cel.common.internal.ComparisonFunctions; import java.util.Iterator; import java.util.List; @@ -67,8 +66,8 @@ public B indexMap(Map map, A index) { if (value.isPresent()) { return (B) value.get(); } - throw new CelRuntimeException( - new IndexOutOfBoundsException(index.toString()), CelErrorCode.ATTRIBUTE_NOT_FOUND); + + throw CelAttributeNotFoundException.of(index.toString()); } /** Determine whether the {@code map} contains the given {@code key}. */ diff --git a/runtime/src/main/java/dev/cel/runtime/RuntimeHelpers.java b/runtime/src/main/java/dev/cel/runtime/RuntimeHelpers.java index 25f01ef59..0ee7824b7 100644 --- a/runtime/src/main/java/dev/cel/runtime/RuntimeHelpers.java +++ b/runtime/src/main/java/dev/cel/runtime/RuntimeHelpers.java @@ -23,10 +23,11 @@ import com.google.protobuf.Duration; import com.google.protobuf.MessageLiteOrBuilder; import com.google.re2j.Pattern; -import dev.cel.common.CelErrorCode; import dev.cel.common.CelOptions; -import dev.cel.common.CelRuntimeException; import dev.cel.common.annotations.Internal; +import dev.cel.common.exceptions.CelDivideByZeroException; +import dev.cel.common.exceptions.CelIndexOutOfBoundsException; +import dev.cel.common.exceptions.CelNumericOverflowException; import dev.cel.common.internal.Converter; import dev.cel.common.values.NullValue; import java.time.format.DateTimeParseException; @@ -116,17 +117,11 @@ public static A indexList(List list, Number index) { if (index instanceof Double) { return doubleToLongLossless(index.doubleValue()) .map(v -> indexList(list, v)) - .orElseThrow( - () -> - new CelRuntimeException( - new IndexOutOfBoundsException("Index out of bounds: " + index.doubleValue()), - CelErrorCode.INDEX_OUT_OF_BOUNDS)); + .orElseThrow(() -> new CelIndexOutOfBoundsException(index.doubleValue())); } int castIndex = Ints.checkedCast(index.longValue()); if (castIndex < 0 || castIndex >= list.size()) { - throw new CelRuntimeException( - new IndexOutOfBoundsException("Index out of bounds: " + castIndex), - CelErrorCode.INDEX_OUT_OF_BOUNDS); + throw new CelIndexOutOfBoundsException(castIndex); } return list.get(castIndex); } @@ -145,7 +140,7 @@ public static long int64Add(long x, long y, CelOptions celOptions) { public static long int64Divide(long x, long y, CelOptions celOptions) { if (celOptions.errorOnIntWrap() && x == Long.MIN_VALUE && y == -1) { - throw new ArithmeticException("most negative number wraps"); + throw new CelNumericOverflowException("most negative number wraps"); } return x / y; } @@ -186,13 +181,13 @@ public static long uint64Add(long x, long y, CelOptions celOptions) { if (celOptions.errorOnIntWrap()) { if (x < 0 && y < 0) { // Both numbers are in the upper half of the range, so it must overflow. - throw new ArithmeticException("range overflow on unsigned addition"); + throw new CelNumericOverflowException("range overflow on unsigned addition"); } long z = x + y; if ((x < 0 || y < 0) && z >= 0) { // Only one number is in the upper half of the range. It overflows if the result // is not in the upper half. - throw new ArithmeticException("range overflow on unsigned addition"); + throw new CelNumericOverflowException("range overflow on unsigned addition"); } return z; } @@ -201,7 +196,7 @@ public static long uint64Add(long x, long y, CelOptions celOptions) { public static UnsignedLong uint64Add(UnsignedLong x, UnsignedLong y) { if (x.compareTo(UnsignedLong.MAX_VALUE.minus(y)) > 0) { - throw new ArithmeticException("range overflow on unsigned addition"); + throw new CelNumericOverflowException("range overflow on unsigned addition"); } return x.plus(y); } @@ -228,7 +223,7 @@ public static long uint64Divide(long x, long y, CelOptions celOptions) { ? UnsignedLongs.divide(x, y) : UnsignedLong.valueOf(x).dividedBy(UnsignedLong.valueOf(y)).longValue(); } catch (ArithmeticException e) { - throw new CelRuntimeException(e, CelErrorCode.DIVIDE_BY_ZERO); + throw new CelDivideByZeroException(e); } } @@ -240,8 +235,7 @@ static long uint64Divide(long x, long y) { public static UnsignedLong uint64Divide(UnsignedLong x, UnsignedLong y) { if (y.equals(UnsignedLong.ZERO)) { - throw new CelRuntimeException( - new ArithmeticException("/ by zero"), CelErrorCode.DIVIDE_BY_ZERO); + throw new CelDivideByZeroException(); } return x.dividedBy(y); } @@ -252,14 +246,13 @@ public static long uint64Mod(long x, long y, CelOptions celOptions) { ? UnsignedLongs.remainder(x, y) : UnsignedLong.valueOf(x).mod(UnsignedLong.valueOf(y)).longValue(); } catch (ArithmeticException e) { - throw new CelRuntimeException(e, CelErrorCode.DIVIDE_BY_ZERO); + throw new CelDivideByZeroException(e); } } public static UnsignedLong uint64Mod(UnsignedLong x, UnsignedLong y) { if (y.equals(UnsignedLong.ZERO)) { - throw new CelRuntimeException( - new ArithmeticException("/ by zero"), CelErrorCode.DIVIDE_BY_ZERO); + throw new CelDivideByZeroException(); } return x.mod(y); } @@ -276,7 +269,7 @@ public static long uint64Multiply(long x, long y, CelOptions celOptions) { ? x * y : UnsignedLong.valueOf(x).times(UnsignedLong.valueOf(y)).longValue(); if (celOptions.errorOnIntWrap() && y != 0 && Long.divideUnsigned(z, y) != x) { - throw new ArithmeticException("multiply out of unsigned integer range"); + throw new CelNumericOverflowException("multiply out of unsigned integer range"); } return z; } @@ -289,7 +282,7 @@ static long uint64Multiply(long x, long y) { public static UnsignedLong uint64Multiply(UnsignedLong x, UnsignedLong y) { if (!y.equals(UnsignedLong.ZERO) && x.compareTo(UnsignedLong.MAX_VALUE.dividedBy(y)) > 0) { - throw new ArithmeticException("multiply out of unsigned integer range"); + throw new CelNumericOverflowException("multiply out of unsigned integer range"); } return x.times(y); } @@ -299,7 +292,7 @@ public static long uint64Subtract(long x, long y, CelOptions celOptions) { // Throw an overflow error if x < y, as unsigned longs. This happens if y has its high // bit set and x does not, or if they have the same high bit and x < y as signed longs. if ((x < 0 && y < 0 && x < y) || (x >= 0 && y >= 0 && x < y) || (x >= 0 && y < 0)) { - throw new ArithmeticException("unsigned subtraction underflow"); + throw new CelNumericOverflowException("unsigned subtraction underflow"); } // fallthrough } @@ -310,7 +303,7 @@ public static UnsignedLong uint64Subtract(UnsignedLong x, UnsignedLong y) { // Throw an overflow error if x < y, as unsigned longs. This happens if y has its high // bit set and x does not, or if they have the same high bit and x < y as signed longs. if (x.compareTo(y) < 0) { - throw new ArithmeticException("unsigned subtraction underflow"); + throw new CelNumericOverflowException("unsigned subtraction underflow"); } return x.minus(y); } diff --git a/runtime/src/main/java/dev/cel/runtime/planner/BUILD.bazel b/runtime/src/main/java/dev/cel/runtime/planner/BUILD.bazel index b99b41fd5..a6fe64c05 100644 --- a/runtime/src/main/java/dev/cel/runtime/planner/BUILD.bazel +++ b/runtime/src/main/java/dev/cel/runtime/planner/BUILD.bazel @@ -65,7 +65,7 @@ java_library( ":strict_error_exception", "//:auto_value", "//common:options", - "//common:runtime_exception", + "//common/exceptions:runtime_exception", "//common/values", "//runtime", "//runtime:activation", @@ -337,7 +337,7 @@ java_library( ":planned_interpretable", ":strict_error_exception", "//common:error_codes", - "//common:runtime_exception", + "//common/exceptions:runtime_exception", "//common/values", "//runtime:interpretable", ], @@ -348,7 +348,7 @@ java_library( srcs = ["StrictErrorException.java"], deps = [ "//common:error_codes", - "//common:runtime_exception", + "//common/exceptions:runtime_exception", ], ) 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 8d2805469..de034d035 100644 --- a/runtime/src/main/java/dev/cel/runtime/planner/EvalHelpers.java +++ b/runtime/src/main/java/dev/cel/runtime/planner/EvalHelpers.java @@ -15,7 +15,7 @@ package dev.cel.runtime.planner; import dev.cel.common.CelErrorCode; -import dev.cel.common.CelRuntimeException; +import dev.cel.common.exceptions.CelRuntimeException; import dev.cel.common.values.ErrorValue; import dev.cel.runtime.GlobalResolver; diff --git a/runtime/src/main/java/dev/cel/runtime/planner/PlannedProgram.java b/runtime/src/main/java/dev/cel/runtime/planner/PlannedProgram.java index 646ad6c85..bba1c394f 100644 --- a/runtime/src/main/java/dev/cel/runtime/planner/PlannedProgram.java +++ b/runtime/src/main/java/dev/cel/runtime/planner/PlannedProgram.java @@ -17,7 +17,7 @@ import com.google.auto.value.AutoValue; import com.google.errorprone.annotations.Immutable; import dev.cel.common.CelOptions; -import dev.cel.common.CelRuntimeException; +import dev.cel.common.exceptions.CelRuntimeException; import dev.cel.common.values.ErrorValue; import dev.cel.runtime.Activation; import dev.cel.runtime.CelEvaluationException; diff --git a/runtime/src/main/java/dev/cel/runtime/planner/StrictErrorException.java b/runtime/src/main/java/dev/cel/runtime/planner/StrictErrorException.java index 3acd6ff27..441a1f27c 100644 --- a/runtime/src/main/java/dev/cel/runtime/planner/StrictErrorException.java +++ b/runtime/src/main/java/dev/cel/runtime/planner/StrictErrorException.java @@ -15,7 +15,7 @@ package dev.cel.runtime.planner; import dev.cel.common.CelErrorCode; -import dev.cel.common.CelRuntimeException; +import dev.cel.common.exceptions.CelRuntimeException; /** * An exception that's raised when a strict call failed to invoke, which includes the source of diff --git a/runtime/src/main/java/dev/cel/runtime/standard/AddOperator.java b/runtime/src/main/java/dev/cel/runtime/standard/AddOperator.java index 82bb308d1..c4e0bec42 100644 --- a/runtime/src/main/java/dev/cel/runtime/standard/AddOperator.java +++ b/runtime/src/main/java/dev/cel/runtime/standard/AddOperator.java @@ -15,7 +15,6 @@ package dev.cel.runtime.standard; import static dev.cel.common.Operator.ADD; -import static dev.cel.runtime.standard.ArithmeticHelpers.getArithmeticErrorCode; import com.google.common.collect.ImmutableSet; import com.google.common.primitives.UnsignedLong; @@ -23,7 +22,7 @@ import com.google.protobuf.Duration; import com.google.protobuf.Timestamp; import dev.cel.common.CelOptions; -import dev.cel.common.CelRuntimeException; +import dev.cel.common.exceptions.CelNumericOverflowException; import dev.cel.common.internal.DateTimeHelpers; import dev.cel.common.internal.ProtoTimeUtils; import dev.cel.common.values.CelByteString; @@ -62,7 +61,7 @@ public enum AddOverload implements CelStandardOverload { try { return RuntimeHelpers.int64Add(x, y, celOptions); } catch (ArithmeticException e) { - throw new CelRuntimeException(e, getArithmeticErrorCode(e)); + throw new CelNumericOverflowException(e); } })), ADD_UINT64( @@ -76,7 +75,7 @@ public enum AddOverload implements CelStandardOverload { try { return RuntimeHelpers.uint64Add(x, y); } catch (ArithmeticException e) { - throw new CelRuntimeException(e, getArithmeticErrorCode(e)); + throw new CelNumericOverflowException(e); } }); } else { @@ -88,7 +87,7 @@ public enum AddOverload implements CelStandardOverload { try { return RuntimeHelpers.uint64Add(x, y, celOptions); } catch (ArithmeticException e) { - throw new CelRuntimeException(e, getArithmeticErrorCode(e)); + throw new CelNumericOverflowException(e); } }); } diff --git a/runtime/src/main/java/dev/cel/runtime/standard/ArithmeticHelpers.java b/runtime/src/main/java/dev/cel/runtime/standard/ArithmeticHelpers.java deleted file mode 100644 index 310e9401f..000000000 --- a/runtime/src/main/java/dev/cel/runtime/standard/ArithmeticHelpers.java +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2025 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.standard; - -import dev.cel.common.CelErrorCode; - -final class ArithmeticHelpers { - - static CelErrorCode getArithmeticErrorCode(ArithmeticException e) { - String exceptionMessage = e.getMessage(); - // The two known cases for an arithmetic exception is divide by zero and overflow. - if (exceptionMessage.equals("/ by zero")) { - return CelErrorCode.DIVIDE_BY_ZERO; - } - return CelErrorCode.NUMERIC_OVERFLOW; - } - - private ArithmeticHelpers() {} -} diff --git a/runtime/src/main/java/dev/cel/runtime/standard/BUILD.bazel b/runtime/src/main/java/dev/cel/runtime/standard/BUILD.bazel index ed189014f..5853220ae 100644 --- a/runtime/src/main/java/dev/cel/runtime/standard/BUILD.bazel +++ b/runtime/src/main/java/dev/cel/runtime/standard/BUILD.bazel @@ -45,12 +45,11 @@ java_library( tags = [ ], deps = [ - ":arithmetic_helpers", ":standard_function", ":standard_overload", "//common:operator", "//common:options", - "//common:runtime_exception", + "//common/exceptions:numeric_overflow", "//common/internal:date_time_helpers", "//common/internal:proto_time_utils", "//common/values:cel_byte_string", @@ -68,12 +67,11 @@ cel_android_library( tags = [ ], deps = [ - ":arithmetic_helpers", ":standard_function_android", ":standard_overload_android", "//common:operator_android", "//common:options", - "//common:runtime_exception", + "//common/exceptions:numeric_overflow", "//common/internal:date_time_helpers_android", "//common/internal:proto_time_utils_android", "//common/values:cel_byte_string", @@ -91,12 +89,11 @@ java_library( tags = [ ], deps = [ - ":arithmetic_helpers", ":standard_function", ":standard_overload", "//common:operator", "//common:options", - "//common:runtime_exception", + "//common/exceptions:numeric_overflow", "//common/internal:date_time_helpers", "//common/internal:proto_time_utils", "//runtime:function_binding", @@ -113,12 +110,11 @@ cel_android_library( tags = [ ], deps = [ - ":arithmetic_helpers", ":standard_function_android", ":standard_overload_android", "//common:operator_android", "//common:options", - "//common:runtime_exception", + "//common/exceptions:numeric_overflow", "//common/internal:date_time_helpers_android", "//common/internal:proto_time_utils_android", "//runtime:function_binding_android", @@ -136,9 +132,8 @@ java_library( ], deps = [ ":standard_overload", - "//common:error_codes", "//common:options", - "//common:runtime_exception", + "//common/exceptions:bad_format", "//common/internal:safe_string_formatter", "//runtime:function_binding", "//runtime:runtime_equality", @@ -155,9 +150,8 @@ cel_android_library( deps = [ ":standard_function_android", ":standard_overload_android", - "//common:error_codes", "//common:options", - "//common:runtime_exception", + "//common/exceptions:bad_format", "//common/internal:safe_string_formatter", "//runtime:function_binding_android", "//runtime:runtime_equality_android", @@ -236,9 +230,8 @@ java_library( ], deps = [ ":standard_overload", - "//common:error_codes", "//common:options", - "//common:runtime_exception", + "//common/exceptions:bad_format", "//runtime:function_binding", "//runtime:runtime_equality", "//runtime/standard:standard_function", @@ -254,9 +247,8 @@ cel_android_library( deps = [ ":standard_function_android", ":standard_overload_android", - "//common:error_codes", "//common:options", - "//common:runtime_exception", + "//common/exceptions:bad_format", "//runtime:function_binding_android", "//runtime:runtime_equality_android", "@maven_android//:com_google_guava_guava", @@ -270,9 +262,8 @@ java_library( ], deps = [ ":standard_overload", - "//common:error_codes", "//common:options", - "//common:runtime_exception", + "//common/exceptions:bad_format", "//runtime:function_binding", "//runtime:runtime_equality", "//runtime:runtime_helpers", @@ -290,9 +281,8 @@ cel_android_library( deps = [ ":standard_function_android", ":standard_overload_android", - "//common:error_codes", "//common:options", - "//common:runtime_exception", + "//common/exceptions:bad_format", "//runtime:function_binding_android", "//runtime:runtime_equality_android", "//runtime:runtime_helpers_android", @@ -898,9 +888,9 @@ java_library( ], deps = [ ":standard_overload", - "//common:error_codes", "//common:options", - "//common:runtime_exception", + "//common/exceptions:bad_format", + "//common/exceptions:numeric_overflow", "//common/internal:proto_time_utils", "//runtime:function_binding", "//runtime:runtime_equality", @@ -919,9 +909,9 @@ cel_android_library( deps = [ ":standard_function_android", ":standard_overload_android", - "//common:error_codes", "//common:options", - "//common:runtime_exception", + "//common/exceptions:bad_format", + "//common/exceptions:numeric_overflow", "//common/internal:proto_time_utils_android", "//runtime:function_binding_android", "//runtime:runtime_equality_android", @@ -1054,9 +1044,8 @@ java_library( ], deps = [ ":standard_overload", - "//common:error_codes", "//common:options", - "//common:runtime_exception", + "//common/exceptions:invalid_argument", "//runtime:function_binding", "//runtime:runtime_equality", "//runtime:runtime_helpers", @@ -1073,9 +1062,8 @@ cel_android_library( deps = [ ":standard_function_android", ":standard_overload_android", - "//common:error_codes", "//common:options", - "//common:runtime_exception", + "//common/exceptions:invalid_argument", "//runtime:function_binding_android", "//runtime:runtime_equality_android", "//runtime:runtime_helpers_android", @@ -1089,11 +1077,10 @@ java_library( tags = [ ], deps = [ - ":arithmetic_helpers", ":standard_overload", "//common:operator", "//common:options", - "//common:runtime_exception", + "//common/exceptions:divide_by_zero", "//runtime:function_binding", "//runtime:runtime_equality", "//runtime:runtime_helpers", @@ -1108,12 +1095,11 @@ cel_android_library( tags = [ ], deps = [ - ":arithmetic_helpers", ":standard_function_android", ":standard_overload_android", "//common:operator_android", "//common:options", - "//common:runtime_exception", + "//common/exceptions:divide_by_zero", "//runtime:function_binding_android", "//runtime:runtime_equality_android", "//runtime:runtime_helpers_android", @@ -1127,11 +1113,10 @@ java_library( tags = [ ], deps = [ - ":arithmetic_helpers", ":standard_overload", "//common:operator", "//common:options", - "//common:runtime_exception", + "//common/exceptions:numeric_overflow", "//runtime:function_binding", "//runtime:runtime_equality", "//runtime:runtime_helpers", @@ -1146,12 +1131,11 @@ cel_android_library( tags = [ ], deps = [ - ":arithmetic_helpers", ":standard_function_android", ":standard_overload_android", "//common:operator_android", "//common:options", - "//common:runtime_exception", + "//common/exceptions:numeric_overflow", "//runtime:function_binding_android", "//runtime:runtime_equality_android", "//runtime:runtime_helpers_android", @@ -1165,11 +1149,10 @@ java_library( tags = [ ], deps = [ - ":arithmetic_helpers", ":standard_overload", "//common:operator", "//common:options", - "//common:runtime_exception", + "//common/exceptions:divide_by_zero", "//runtime:function_binding", "//runtime:runtime_equality", "//runtime:runtime_helpers", @@ -1184,12 +1167,11 @@ cel_android_library( tags = [ ], deps = [ - ":arithmetic_helpers", ":standard_function_android", ":standard_overload_android", "//common:operator_android", "//common:options", - "//common:runtime_exception", + "//common/exceptions:divide_by_zero", "//runtime:function_binding_android", "//runtime:runtime_equality_android", "//runtime:runtime_helpers_android", @@ -1203,11 +1185,10 @@ java_library( tags = [ ], deps = [ - ":arithmetic_helpers", ":standard_overload", "//common:operator", "//common:options", - "//common:runtime_exception", + "//common/exceptions:numeric_overflow", "//runtime:function_binding", "//runtime:runtime_equality", "//runtime:runtime_helpers", @@ -1222,12 +1203,11 @@ cel_android_library( tags = [ ], deps = [ - ":arithmetic_helpers", ":standard_function_android", ":standard_overload_android", "//common:operator_android", "//common:options", - "//common:runtime_exception", + "//common/exceptions:numeric_overflow", "//runtime:function_binding_android", "//runtime:runtime_equality_android", "//runtime:runtime_helpers_android", @@ -1338,9 +1318,8 @@ java_library( ], deps = [ ":standard_overload", - "//common:error_codes", "//common:options", - "//common:runtime_exception", + "//common/exceptions:bad_format", "//common/internal:date_time_helpers", "//common/internal:proto_time_utils", "//common/values:cel_byte_string", @@ -1360,9 +1339,8 @@ cel_android_library( deps = [ ":standard_function_android", ":standard_overload_android", - "//common:error_codes", "//common:options", - "//common:runtime_exception", + "//common/exceptions:bad_format", "//common/internal:date_time_helpers_android", "//common/internal:proto_time_utils_android", "//common/values:cel_byte_string", @@ -1380,9 +1358,8 @@ java_library( ], deps = [ ":standard_overload", - "//common:error_codes", "//common:options", - "//common:runtime_exception", + "//common/exceptions:bad_format", "//common/internal:date_time_helpers", "//common/internal:proto_time_utils", "//runtime:function_binding", @@ -1401,9 +1378,8 @@ cel_android_library( deps = [ ":standard_function_android", ":standard_overload_android", - "//common:error_codes", "//common:options", - "//common:runtime_exception", + "//common/exceptions:bad_format", "//common/internal:date_time_helpers_android", "//common/internal:proto_time_utils_android", "//runtime:function_binding_android", @@ -1420,9 +1396,9 @@ java_library( ], deps = [ ":standard_overload", - "//common:error_codes", "//common:options", - "//common:runtime_exception", + "//common/exceptions:bad_format", + "//common/exceptions:numeric_overflow", "//runtime:function_binding", "//runtime:runtime_equality", "//runtime:runtime_helpers", @@ -1439,9 +1415,9 @@ cel_android_library( deps = [ ":standard_function_android", ":standard_overload_android", - "//common:error_codes", "//common:options", - "//common:runtime_exception", + "//common/exceptions:bad_format", + "//common/exceptions:numeric_overflow", "//runtime:function_binding_android", "//runtime:runtime_equality_android", "//runtime:runtime_helpers_android", @@ -1508,13 +1484,3 @@ cel_android_library( "@maven//:com_google_errorprone_error_prone_annotations", ], ) - -java_library( - name = "arithmetic_helpers", - srcs = ["ArithmeticHelpers.java"], - # used_by_android - visibility = ["//visibility:private"], - deps = [ - "//common:error_codes", - ], -) diff --git a/runtime/src/main/java/dev/cel/runtime/standard/BoolFunction.java b/runtime/src/main/java/dev/cel/runtime/standard/BoolFunction.java index 60cc8b156..668934aac 100644 --- a/runtime/src/main/java/dev/cel/runtime/standard/BoolFunction.java +++ b/runtime/src/main/java/dev/cel/runtime/standard/BoolFunction.java @@ -15,9 +15,8 @@ package dev.cel.runtime.standard; import com.google.common.collect.ImmutableSet; -import dev.cel.common.CelErrorCode; import dev.cel.common.CelOptions; -import dev.cel.common.CelRuntimeException; +import dev.cel.common.exceptions.CelBadFormatException; import dev.cel.common.internal.SafeStringFormatter; import dev.cel.runtime.CelFunctionBinding; import dev.cel.runtime.RuntimeEquality; @@ -64,11 +63,9 @@ public enum BoolOverload implements CelStandardOverload { case "0": return false; default: - throw new CelRuntimeException( - new IllegalArgumentException( - SafeStringFormatter.format( - "Type conversion error from 'string' to 'bool': [%s]", str)), - CelErrorCode.BAD_FORMAT); + throw new CelBadFormatException( + SafeStringFormatter.format( + "Type conversion error from 'string' to 'bool': [%s]", str)); } })); diff --git a/runtime/src/main/java/dev/cel/runtime/standard/DivideOperator.java b/runtime/src/main/java/dev/cel/runtime/standard/DivideOperator.java index a9c36b0ff..ddd78cef8 100644 --- a/runtime/src/main/java/dev/cel/runtime/standard/DivideOperator.java +++ b/runtime/src/main/java/dev/cel/runtime/standard/DivideOperator.java @@ -15,12 +15,11 @@ package dev.cel.runtime.standard; import static dev.cel.common.Operator.DIVIDE; -import static dev.cel.runtime.standard.ArithmeticHelpers.getArithmeticErrorCode; import com.google.common.collect.ImmutableSet; import com.google.common.primitives.UnsignedLong; import dev.cel.common.CelOptions; -import dev.cel.common.CelRuntimeException; +import dev.cel.common.exceptions.CelDivideByZeroException; import dev.cel.runtime.CelFunctionBinding; import dev.cel.runtime.RuntimeEquality; import dev.cel.runtime.RuntimeHelpers; @@ -58,7 +57,7 @@ public enum DivideOverload implements CelStandardOverload { try { return RuntimeHelpers.int64Divide(x, y, celOptions); } catch (ArithmeticException e) { - throw new CelRuntimeException(e, getArithmeticErrorCode(e)); + throw new CelDivideByZeroException(e); } })), DIVIDE_UINT64( diff --git a/runtime/src/main/java/dev/cel/runtime/standard/DoubleFunction.java b/runtime/src/main/java/dev/cel/runtime/standard/DoubleFunction.java index b541bd379..b8d4b74c0 100644 --- a/runtime/src/main/java/dev/cel/runtime/standard/DoubleFunction.java +++ b/runtime/src/main/java/dev/cel/runtime/standard/DoubleFunction.java @@ -16,9 +16,8 @@ import com.google.common.collect.ImmutableSet; import com.google.common.primitives.UnsignedLong; -import dev.cel.common.CelErrorCode; import dev.cel.common.CelOptions; -import dev.cel.common.CelRuntimeException; +import dev.cel.common.exceptions.CelBadFormatException; import dev.cel.runtime.CelFunctionBinding; import dev.cel.runtime.RuntimeEquality; import java.util.Arrays; @@ -56,7 +55,7 @@ public enum DoubleOverload implements CelStandardOverload { try { return Double.parseDouble(arg); } catch (NumberFormatException e) { - throw new CelRuntimeException(e, CelErrorCode.BAD_FORMAT); + throw new CelBadFormatException(e); } })), UINT64_TO_DOUBLE( diff --git a/runtime/src/main/java/dev/cel/runtime/standard/DurationFunction.java b/runtime/src/main/java/dev/cel/runtime/standard/DurationFunction.java index 436ffd1d4..e1f11644e 100644 --- a/runtime/src/main/java/dev/cel/runtime/standard/DurationFunction.java +++ b/runtime/src/main/java/dev/cel/runtime/standard/DurationFunction.java @@ -16,9 +16,8 @@ import com.google.common.collect.ImmutableSet; import com.google.protobuf.Duration; -import dev.cel.common.CelErrorCode; import dev.cel.common.CelOptions; -import dev.cel.common.CelRuntimeException; +import dev.cel.common.exceptions.CelBadFormatException; import dev.cel.runtime.CelFunctionBinding; import dev.cel.runtime.RuntimeEquality; import dev.cel.runtime.RuntimeHelpers; @@ -62,13 +61,13 @@ public enum DurationOverload implements CelStandardOverload { try { return RuntimeHelpers.createJavaDurationFromString(d); } catch (IllegalArgumentException e) { - throw new CelRuntimeException(e, CelErrorCode.BAD_FORMAT); + throw new CelBadFormatException(e); } } else { try { return RuntimeHelpers.createDurationFromString(d); } catch (IllegalArgumentException e) { - throw new CelRuntimeException(e, CelErrorCode.BAD_FORMAT); + throw new CelBadFormatException(e); } } })), diff --git a/runtime/src/main/java/dev/cel/runtime/standard/IntFunction.java b/runtime/src/main/java/dev/cel/runtime/standard/IntFunction.java index 248131865..63959af87 100644 --- a/runtime/src/main/java/dev/cel/runtime/standard/IntFunction.java +++ b/runtime/src/main/java/dev/cel/runtime/standard/IntFunction.java @@ -17,9 +17,9 @@ import com.google.common.collect.ImmutableSet; import com.google.common.primitives.UnsignedLong; import com.google.protobuf.Timestamp; -import dev.cel.common.CelErrorCode; import dev.cel.common.CelOptions; -import dev.cel.common.CelRuntimeException; +import dev.cel.common.exceptions.CelBadFormatException; +import dev.cel.common.exceptions.CelNumericOverflowException; import dev.cel.common.internal.ProtoTimeUtils; import dev.cel.runtime.CelFunctionBinding; import dev.cel.runtime.RuntimeEquality; @@ -56,9 +56,7 @@ public enum IntOverload implements CelStandardOverload { UnsignedLong.class, (UnsignedLong arg) -> { if (arg.compareTo(UnsignedLong.valueOf(Long.MAX_VALUE)) > 0) { - throw new CelRuntimeException( - new IllegalArgumentException("unsigned out of int range"), - CelErrorCode.NUMERIC_OVERFLOW); + throw new CelNumericOverflowException("unsigned out of int range"); } return arg.longValue(); }); @@ -68,9 +66,7 @@ public enum IntOverload implements CelStandardOverload { Long.class, (Long arg) -> { if (celOptions.errorOnIntWrap() && arg < 0) { - throw new CelRuntimeException( - new IllegalArgumentException("unsigned out of int range"), - CelErrorCode.NUMERIC_OVERFLOW); + throw new CelNumericOverflowException("unsigned out of int range"); } return arg; }); @@ -86,9 +82,7 @@ public enum IntOverload implements CelStandardOverload { return RuntimeHelpers.doubleToLongChecked(arg) .orElseThrow( () -> - new CelRuntimeException( - new IllegalArgumentException("double is out of range for int"), - CelErrorCode.NUMERIC_OVERFLOW)); + new CelNumericOverflowException("double is out of range for int")); } return arg.longValue(); })), @@ -101,7 +95,7 @@ public enum IntOverload implements CelStandardOverload { try { return Long.parseLong(arg); } catch (NumberFormatException e) { - throw new CelRuntimeException(e, CelErrorCode.BAD_FORMAT); + throw new CelBadFormatException(e); } })), TIMESTAMP_TO_INT64( diff --git a/runtime/src/main/java/dev/cel/runtime/standard/MatchesFunction.java b/runtime/src/main/java/dev/cel/runtime/standard/MatchesFunction.java index 62df04110..a82a7d439 100644 --- a/runtime/src/main/java/dev/cel/runtime/standard/MatchesFunction.java +++ b/runtime/src/main/java/dev/cel/runtime/standard/MatchesFunction.java @@ -15,9 +15,8 @@ package dev.cel.runtime.standard; import com.google.common.collect.ImmutableSet; -import dev.cel.common.CelErrorCode; import dev.cel.common.CelOptions; -import dev.cel.common.CelRuntimeException; +import dev.cel.common.exceptions.CelInvalidArgumentException; import dev.cel.runtime.CelFunctionBinding; import dev.cel.runtime.RuntimeEquality; import dev.cel.runtime.RuntimeHelpers; @@ -51,7 +50,7 @@ public enum MatchesOverload implements CelStandardOverload { try { return RuntimeHelpers.matches(string, regexp, celOptions); } catch (RuntimeException e) { - throw new CelRuntimeException(e, CelErrorCode.INVALID_ARGUMENT); + throw new CelInvalidArgumentException(e); } })), // Duplicate receiver-style matches overload. @@ -65,7 +64,7 @@ public enum MatchesOverload implements CelStandardOverload { try { return RuntimeHelpers.matches(string, regexp, celOptions); } catch (RuntimeException e) { - throw new CelRuntimeException(e, CelErrorCode.INVALID_ARGUMENT); + throw new CelInvalidArgumentException(e); } })), ; diff --git a/runtime/src/main/java/dev/cel/runtime/standard/ModuloOperator.java b/runtime/src/main/java/dev/cel/runtime/standard/ModuloOperator.java index 01e02764d..baa74fe15 100644 --- a/runtime/src/main/java/dev/cel/runtime/standard/ModuloOperator.java +++ b/runtime/src/main/java/dev/cel/runtime/standard/ModuloOperator.java @@ -15,12 +15,11 @@ package dev.cel.runtime.standard; import static dev.cel.common.Operator.MODULO; -import static dev.cel.runtime.standard.ArithmeticHelpers.getArithmeticErrorCode; import com.google.common.collect.ImmutableSet; import com.google.common.primitives.UnsignedLong; import dev.cel.common.CelOptions; -import dev.cel.common.CelRuntimeException; +import dev.cel.common.exceptions.CelDivideByZeroException; import dev.cel.runtime.CelFunctionBinding; import dev.cel.runtime.RuntimeEquality; import dev.cel.runtime.RuntimeHelpers; @@ -54,7 +53,7 @@ public enum ModuloOverload implements CelStandardOverload { try { return x % y; } catch (ArithmeticException e) { - throw new CelRuntimeException(e, getArithmeticErrorCode(e)); + throw new CelDivideByZeroException(e); } })), MODULO_UINT64( diff --git a/runtime/src/main/java/dev/cel/runtime/standard/MultiplyOperator.java b/runtime/src/main/java/dev/cel/runtime/standard/MultiplyOperator.java index c55a4c968..425723652 100644 --- a/runtime/src/main/java/dev/cel/runtime/standard/MultiplyOperator.java +++ b/runtime/src/main/java/dev/cel/runtime/standard/MultiplyOperator.java @@ -15,12 +15,11 @@ package dev.cel.runtime.standard; import static dev.cel.common.Operator.MULTIPLY; -import static dev.cel.runtime.standard.ArithmeticHelpers.getArithmeticErrorCode; import com.google.common.collect.ImmutableSet; import com.google.common.primitives.UnsignedLong; import dev.cel.common.CelOptions; -import dev.cel.common.CelRuntimeException; +import dev.cel.common.exceptions.CelNumericOverflowException; import dev.cel.runtime.CelFunctionBinding; import dev.cel.runtime.RuntimeEquality; import dev.cel.runtime.RuntimeHelpers; @@ -54,7 +53,7 @@ public enum MultiplyOverload implements CelStandardOverload { try { return RuntimeHelpers.int64Multiply(x, y, celOptions); } catch (ArithmeticException e) { - throw new CelRuntimeException(e, getArithmeticErrorCode(e)); + throw new CelNumericOverflowException(e); } })), MULTIPLY_DOUBLE( @@ -72,7 +71,7 @@ public enum MultiplyOverload implements CelStandardOverload { try { return RuntimeHelpers.uint64Multiply(x, y); } catch (ArithmeticException e) { - throw new CelRuntimeException(e, getArithmeticErrorCode(e)); + throw new CelNumericOverflowException(e); } }); } else { @@ -84,7 +83,7 @@ public enum MultiplyOverload implements CelStandardOverload { try { return RuntimeHelpers.uint64Multiply(x, y, celOptions); } catch (ArithmeticException e) { - throw new CelRuntimeException(e, getArithmeticErrorCode(e)); + throw new CelNumericOverflowException(e); } }); } diff --git a/runtime/src/main/java/dev/cel/runtime/standard/NegateOperator.java b/runtime/src/main/java/dev/cel/runtime/standard/NegateOperator.java index cc072fdec..c61c395cb 100644 --- a/runtime/src/main/java/dev/cel/runtime/standard/NegateOperator.java +++ b/runtime/src/main/java/dev/cel/runtime/standard/NegateOperator.java @@ -15,11 +15,10 @@ package dev.cel.runtime.standard; import static dev.cel.common.Operator.NEGATE; -import static dev.cel.runtime.standard.ArithmeticHelpers.getArithmeticErrorCode; import com.google.common.collect.ImmutableSet; import dev.cel.common.CelOptions; -import dev.cel.common.CelRuntimeException; +import dev.cel.common.exceptions.CelNumericOverflowException; import dev.cel.runtime.CelFunctionBinding; import dev.cel.runtime.RuntimeEquality; import dev.cel.runtime.RuntimeHelpers; @@ -52,7 +51,7 @@ public enum NegateOverload implements CelStandardOverload { try { return RuntimeHelpers.int64Negate(x, celOptions); } catch (ArithmeticException e) { - throw new CelRuntimeException(e, getArithmeticErrorCode(e)); + throw new CelNumericOverflowException(e); } })), NEGATE_DOUBLE( diff --git a/runtime/src/main/java/dev/cel/runtime/standard/StringFunction.java b/runtime/src/main/java/dev/cel/runtime/standard/StringFunction.java index 9311962ca..8fbc8add7 100644 --- a/runtime/src/main/java/dev/cel/runtime/standard/StringFunction.java +++ b/runtime/src/main/java/dev/cel/runtime/standard/StringFunction.java @@ -20,9 +20,8 @@ import com.google.protobuf.ByteString; import com.google.protobuf.Duration; import com.google.protobuf.Timestamp; -import dev.cel.common.CelErrorCode; import dev.cel.common.CelOptions; -import dev.cel.common.CelRuntimeException; +import dev.cel.common.exceptions.CelBadFormatException; import dev.cel.common.internal.DateTimeHelpers; import dev.cel.common.internal.ProtoTimeUtils; import dev.cel.common.values.CelByteString; @@ -69,10 +68,8 @@ public enum StringOverload implements CelStandardOverload { CelByteString.class, (byteStr) -> { if (!byteStr.isValidUtf8()) { - throw new CelRuntimeException( - new IllegalArgumentException( - "invalid UTF-8 in bytes, cannot convert to string"), - CelErrorCode.BAD_FORMAT); + throw new CelBadFormatException( + "invalid UTF-8 in bytes, cannot convert to string"); } return byteStr.toStringUtf8(); }); @@ -82,10 +79,8 @@ public enum StringOverload implements CelStandardOverload { ByteString.class, (byteStr) -> { if (!byteStr.isValidUtf8()) { - throw new CelRuntimeException( - new IllegalArgumentException( - "invalid UTF-8 in bytes, cannot convert to string"), - CelErrorCode.BAD_FORMAT); + throw new CelBadFormatException( + "invalid UTF-8 in bytes, cannot convert to string"); } return byteStr.toStringUtf8(); }); diff --git a/runtime/src/main/java/dev/cel/runtime/standard/SubtractOperator.java b/runtime/src/main/java/dev/cel/runtime/standard/SubtractOperator.java index 8a7595f92..784c46825 100644 --- a/runtime/src/main/java/dev/cel/runtime/standard/SubtractOperator.java +++ b/runtime/src/main/java/dev/cel/runtime/standard/SubtractOperator.java @@ -15,14 +15,13 @@ package dev.cel.runtime.standard; import static dev.cel.common.Operator.SUBTRACT; -import static dev.cel.runtime.standard.ArithmeticHelpers.getArithmeticErrorCode; import com.google.common.collect.ImmutableSet; import com.google.common.primitives.UnsignedLong; import com.google.protobuf.Duration; import com.google.protobuf.Timestamp; import dev.cel.common.CelOptions; -import dev.cel.common.CelRuntimeException; +import dev.cel.common.exceptions.CelNumericOverflowException; import dev.cel.common.internal.DateTimeHelpers; import dev.cel.common.internal.ProtoTimeUtils; import dev.cel.runtime.CelFunctionBinding; @@ -59,7 +58,7 @@ public enum SubtractOverload implements CelStandardOverload { try { return RuntimeHelpers.int64Subtract(x, y, celOptions); } catch (ArithmeticException e) { - throw new CelRuntimeException(e, getArithmeticErrorCode(e)); + throw new CelNumericOverflowException(e); } })), SUBTRACT_TIMESTAMP_TIMESTAMP( @@ -105,7 +104,7 @@ public enum SubtractOverload implements CelStandardOverload { try { return RuntimeHelpers.uint64Subtract(x, y); } catch (ArithmeticException e) { - throw new CelRuntimeException(e, getArithmeticErrorCode(e)); + throw new CelNumericOverflowException(e); } }); } else { @@ -117,7 +116,7 @@ public enum SubtractOverload implements CelStandardOverload { try { return RuntimeHelpers.uint64Subtract(x, y, celOptions); } catch (ArithmeticException e) { - throw new CelRuntimeException(e, getArithmeticErrorCode(e)); + throw new CelNumericOverflowException(e); } }); } diff --git a/runtime/src/main/java/dev/cel/runtime/standard/TimestampFunction.java b/runtime/src/main/java/dev/cel/runtime/standard/TimestampFunction.java index 27c495034..00a4ed43e 100644 --- a/runtime/src/main/java/dev/cel/runtime/standard/TimestampFunction.java +++ b/runtime/src/main/java/dev/cel/runtime/standard/TimestampFunction.java @@ -16,9 +16,8 @@ import com.google.common.collect.ImmutableSet; import com.google.protobuf.Timestamp; -import dev.cel.common.CelErrorCode; import dev.cel.common.CelOptions; -import dev.cel.common.CelRuntimeException; +import dev.cel.common.exceptions.CelBadFormatException; import dev.cel.common.internal.DateTimeHelpers; import dev.cel.common.internal.ProtoTimeUtils; import dev.cel.runtime.CelFunctionBinding; @@ -56,14 +55,14 @@ public enum TimestampOverload implements CelStandardOverload { try { return DateTimeHelpers.parse(ts); } catch (DateTimeParseException e) { - throw new CelRuntimeException(e, CelErrorCode.BAD_FORMAT); + throw new CelBadFormatException(e); } } else { try { return ProtoTimeUtils.parse(ts); } catch (ParseException e) { - throw new CelRuntimeException(e, CelErrorCode.BAD_FORMAT); + throw new CelBadFormatException(e); } } })), diff --git a/runtime/src/main/java/dev/cel/runtime/standard/UintFunction.java b/runtime/src/main/java/dev/cel/runtime/standard/UintFunction.java index d120c6b75..be2217dd9 100644 --- a/runtime/src/main/java/dev/cel/runtime/standard/UintFunction.java +++ b/runtime/src/main/java/dev/cel/runtime/standard/UintFunction.java @@ -17,9 +17,9 @@ import com.google.common.collect.ImmutableSet; import com.google.common.primitives.UnsignedLong; import com.google.common.primitives.UnsignedLongs; -import dev.cel.common.CelErrorCode; import dev.cel.common.CelOptions; -import dev.cel.common.CelRuntimeException; +import dev.cel.common.exceptions.CelBadFormatException; +import dev.cel.common.exceptions.CelNumericOverflowException; import dev.cel.runtime.CelFunctionBinding; import dev.cel.runtime.RuntimeEquality; import dev.cel.runtime.RuntimeHelpers; @@ -61,9 +61,7 @@ public enum UintOverload implements CelStandardOverload { Long.class, (Long arg) -> { if (celOptions.errorOnIntWrap() && arg < 0) { - throw new CelRuntimeException( - new IllegalArgumentException("int out of uint range"), - CelErrorCode.NUMERIC_OVERFLOW); + throw new CelNumericOverflowException("int out of uint range"); } return UnsignedLong.valueOf(arg); }); @@ -73,9 +71,7 @@ public enum UintOverload implements CelStandardOverload { Long.class, (Long arg) -> { if (celOptions.errorOnIntWrap() && arg < 0) { - throw new CelRuntimeException( - new IllegalArgumentException("int out of uint range"), - CelErrorCode.NUMERIC_OVERFLOW); + throw new CelNumericOverflowException("int out of uint range"); } return arg; }); @@ -91,10 +87,7 @@ public enum UintOverload implements CelStandardOverload { if (celOptions.errorOnIntWrap()) { return RuntimeHelpers.doubleToUnsignedChecked(arg) .orElseThrow( - () -> - new CelRuntimeException( - new IllegalArgumentException("double out of uint range"), - CelErrorCode.NUMERIC_OVERFLOW)); + () -> new CelNumericOverflowException("double out of uint range")); } return UnsignedLong.valueOf(BigDecimal.valueOf(arg).toBigInteger()); }); @@ -108,9 +101,8 @@ public enum UintOverload implements CelStandardOverload { .map(UnsignedLong::longValue) .orElseThrow( () -> - new CelRuntimeException( - new IllegalArgumentException("double out of uint range"), - CelErrorCode.NUMERIC_OVERFLOW)); + new CelNumericOverflowException( + "double out of uint range")); } return arg.longValue(); }); @@ -126,7 +118,7 @@ public enum UintOverload implements CelStandardOverload { try { return UnsignedLong.valueOf(arg); } catch (NumberFormatException e) { - throw new CelRuntimeException(e, CelErrorCode.BAD_FORMAT); + throw new CelBadFormatException(e); } }); } else { @@ -137,7 +129,7 @@ public enum UintOverload implements CelStandardOverload { try { return UnsignedLongs.parseUnsignedLong(arg); } catch (NumberFormatException e) { - throw new CelRuntimeException(e, CelErrorCode.BAD_FORMAT); + throw new CelBadFormatException(e); } }); } diff --git a/runtime/src/test/java/dev/cel/runtime/BUILD.bazel b/runtime/src/test/java/dev/cel/runtime/BUILD.bazel index eb0d652f1..ed76fdbe7 100644 --- a/runtime/src/test/java/dev/cel/runtime/BUILD.bazel +++ b/runtime/src/test/java/dev/cel/runtime/BUILD.bazel @@ -37,8 +37,11 @@ java_library( "//common:error_codes", "//common:options", "//common:proto_v1alpha1_ast", - "//common:runtime_exception", "//common/ast", + "//common/exceptions:bad_format", + "//common/exceptions:divide_by_zero", + "//common/exceptions:numeric_overflow", + "//common/exceptions:runtime_exception", "//common/internal:cel_descriptor_pools", "//common/internal:converter", "//common/internal:default_message_factory", diff --git a/runtime/src/test/java/dev/cel/runtime/CelEvaluationExceptionBuilderTest.java b/runtime/src/test/java/dev/cel/runtime/CelEvaluationExceptionBuilderTest.java index b3bc32e20..c073a8443 100644 --- a/runtime/src/test/java/dev/cel/runtime/CelEvaluationExceptionBuilderTest.java +++ b/runtime/src/test/java/dev/cel/runtime/CelEvaluationExceptionBuilderTest.java @@ -18,7 +18,8 @@ import com.google.testing.junit.testparameterinjector.TestParameterInjector; import dev.cel.common.CelErrorCode; -import dev.cel.common.CelRuntimeException; +import dev.cel.common.exceptions.CelBadFormatException; +import dev.cel.common.exceptions.CelRuntimeException; import org.junit.Test; import org.junit.runner.RunWith; @@ -87,15 +88,14 @@ public boolean hasPosition(long exprId) { @Test public void builder_fromCelRuntimeException() { IllegalStateException cause = new IllegalStateException("cause error message"); - CelRuntimeException celRuntimeException = - new CelRuntimeException(cause, CelErrorCode.BAD_FORMAT); + CelRuntimeException celRuntimeException = new CelBadFormatException(cause); CelEvaluationExceptionBuilder builder = CelEvaluationExceptionBuilder.newBuilder(celRuntimeException); CelEvaluationException e = builder.build(); assertThat(e).hasMessageThat().isEqualTo("evaluation error: cause error message"); - assertThat(e).hasCauseThat().isEqualTo(cause); + assertThat(e).hasCauseThat().isEqualTo(celRuntimeException); assertThat(e.getErrorCode()).isEqualTo(CelErrorCode.BAD_FORMAT); } } diff --git a/runtime/src/test/java/dev/cel/runtime/CelRuntimeLegacyImplTest.java b/runtime/src/test/java/dev/cel/runtime/CelRuntimeLegacyImplTest.java index c4a041f6a..fa3b5f4ae 100644 --- a/runtime/src/test/java/dev/cel/runtime/CelRuntimeLegacyImplTest.java +++ b/runtime/src/test/java/dev/cel/runtime/CelRuntimeLegacyImplTest.java @@ -18,6 +18,7 @@ import com.google.protobuf.Message; import dev.cel.common.CelException; +import dev.cel.common.exceptions.CelDivideByZeroException; import dev.cel.common.values.CelValueProvider; import dev.cel.compiler.CelCompiler; import dev.cel.compiler.CelCompilerFactory; @@ -39,7 +40,7 @@ public void evalException() throws CelException { CelRuntime runtime = CelRuntimeFactory.standardCelRuntimeBuilder().build(); CelRuntime.Program program = runtime.createProgram(compiler.compile("1/0").getAst()); CelEvaluationException e = Assert.assertThrows(CelEvaluationException.class, program::eval); - assertThat(e).hasCauseThat().isInstanceOf(ArithmeticException.class); + assertThat(e).hasCauseThat().isInstanceOf(CelDivideByZeroException.class); } @Test diff --git a/runtime/src/test/java/dev/cel/runtime/DescriptorMessageProviderTest.java b/runtime/src/test/java/dev/cel/runtime/DescriptorMessageProviderTest.java index 8866d1fa6..6ab1638b1 100644 --- a/runtime/src/test/java/dev/cel/runtime/DescriptorMessageProviderTest.java +++ b/runtime/src/test/java/dev/cel/runtime/DescriptorMessageProviderTest.java @@ -31,7 +31,7 @@ import dev.cel.common.CelDescriptors; import dev.cel.common.CelErrorCode; import dev.cel.common.CelOptions; -import dev.cel.common.CelRuntimeException; +import dev.cel.common.exceptions.CelRuntimeException; import dev.cel.common.internal.CelDescriptorPool; import dev.cel.common.internal.DefaultDescriptorPool; import dev.cel.common.internal.DefaultMessageFactory; @@ -114,8 +114,8 @@ public void createMessage_missingDescriptorError() { () -> provider.createMessage( "google.api.tools.contract.test.MissingMessageTypes", ImmutableMap.of())); - assertThat(e).hasCauseThat().isInstanceOf(IllegalArgumentException.class); assertThat(e.getErrorCode()).isEqualTo(CelErrorCode.ATTRIBUTE_NOT_FOUND); + assertThat(e).hasCauseThat().isNull(); } @Test @@ -159,8 +159,8 @@ public void selectField_mapKeyNotFound() { CelRuntimeException e = Assert.assertThrows( CelRuntimeException.class, () -> provider.selectField(ImmutableMap.of(), "hello")); - assertThat(e).hasCauseThat().isInstanceOf(IllegalArgumentException.class); assertThat(e.getErrorCode()).isEqualTo(CelErrorCode.ATTRIBUTE_NOT_FOUND); + assertThat(e).hasCauseThat().isNull(); } @Test @@ -177,8 +177,8 @@ public void selectField_nonProtoObjectError() { CelRuntimeException e = Assert.assertThrows( CelRuntimeException.class, () -> provider.selectField("hello", "not_a_field")); - assertThat(e).hasCauseThat().isInstanceOf(IllegalArgumentException.class); assertThat(e.getErrorCode()).isEqualTo(CelErrorCode.ATTRIBUTE_NOT_FOUND); + assertThat(e).hasCauseThat().isNull(); } @Test diff --git a/runtime/src/test/java/dev/cel/runtime/ProtoMessageRuntimeEqualityTest.java b/runtime/src/test/java/dev/cel/runtime/ProtoMessageRuntimeEqualityTest.java index 16806c856..dc4607e5f 100644 --- a/runtime/src/test/java/dev/cel/runtime/ProtoMessageRuntimeEqualityTest.java +++ b/runtime/src/test/java/dev/cel/runtime/ProtoMessageRuntimeEqualityTest.java @@ -42,7 +42,7 @@ import com.google.rpc.context.AttributeContext.Request; import dev.cel.common.CelDescriptorUtil; import dev.cel.common.CelOptions; -import dev.cel.common.CelRuntimeException; +import dev.cel.common.exceptions.CelRuntimeException; import dev.cel.common.internal.AdaptingTypes; import dev.cel.common.internal.BidiConverter; import dev.cel.common.internal.DefaultDescriptorPool; diff --git a/runtime/src/test/java/dev/cel/runtime/ProtoMessageRuntimeHelpersTest.java b/runtime/src/test/java/dev/cel/runtime/ProtoMessageRuntimeHelpersTest.java index f6d701741..45b050fd1 100644 --- a/runtime/src/test/java/dev/cel/runtime/ProtoMessageRuntimeHelpersTest.java +++ b/runtime/src/test/java/dev/cel/runtime/ProtoMessageRuntimeHelpersTest.java @@ -36,7 +36,8 @@ import com.google.protobuf.UInt64Value; import com.google.protobuf.Value; import dev.cel.common.CelOptions; -import dev.cel.common.CelRuntimeException; +import dev.cel.common.exceptions.CelNumericOverflowException; +import dev.cel.common.exceptions.CelRuntimeException; import dev.cel.common.internal.DefaultMessageFactory; import dev.cel.common.internal.DynamicProto; import dev.cel.common.values.CelByteString; @@ -91,7 +92,7 @@ public void int64Divide() throws Exception { assertThat(ProtoMessageRuntimeHelpers.int64Divide(Long.MIN_VALUE, -1, CelOptions.LEGACY)) .isEqualTo(Long.MIN_VALUE); assertThrows( - ArithmeticException.class, + CelNumericOverflowException.class, () -> ProtoMessageRuntimeHelpers.int64Divide(Long.MIN_VALUE, -1, CelOptions.DEFAULT)); } @@ -171,7 +172,7 @@ public void uint64Add_signedLongs() throws Exception { assertThat(ProtoMessageRuntimeHelpers.uint64Add(4, 4, CelOptions.DEFAULT)).isEqualTo(8); assertThat(ProtoMessageRuntimeHelpers.uint64Add(-1, 1, CelOptions.LEGACY)).isEqualTo(0); assertThrows( - ArithmeticException.class, + CelNumericOverflowException.class, () -> ProtoMessageRuntimeHelpers.uint64Add(-1, 1, CelOptions.DEFAULT)); } @@ -185,7 +186,7 @@ public void uint64Add_unsignedLongs() throws Exception { UnsignedLong.MAX_VALUE.minus(UnsignedLong.ONE), UnsignedLong.ONE)) .isEqualTo(UnsignedLong.MAX_VALUE); assertThrows( - ArithmeticException.class, + CelNumericOverflowException.class, () -> ProtoMessageRuntimeHelpers.uint64Add(UnsignedLong.MAX_VALUE, UnsignedLong.ONE)); } @@ -202,7 +203,7 @@ public void uint64Multiply_signedLongs() throws Exception { .build())) .isEqualTo(0); assertThrows( - ArithmeticException.class, + CelNumericOverflowException.class, () -> ProtoMessageRuntimeHelpers.uint64Multiply(Long.MIN_VALUE, 2, CelOptions.DEFAULT)); } @@ -213,7 +214,7 @@ public void uint64Multiply_unsignedLongs() throws Exception { UnsignedLong.valueOf(32), UnsignedLong.valueOf(2))) .isEqualTo(UnsignedLong.valueOf(64)); assertThrows( - ArithmeticException.class, + CelNumericOverflowException.class, () -> ProtoMessageRuntimeHelpers.uint64Multiply( UnsignedLong.MAX_VALUE, UnsignedLong.valueOf(2))); @@ -295,13 +296,13 @@ public void uint64Subtract_signedLongs() throws Exception { assertThat(ProtoMessageRuntimeHelpers.uint64Subtract(-1, 2, CelOptions.DEFAULT)).isEqualTo(-3); assertThat(ProtoMessageRuntimeHelpers.uint64Subtract(0, 1, CelOptions.LEGACY)).isEqualTo(-1); assertThrows( - ArithmeticException.class, + CelNumericOverflowException.class, () -> ProtoMessageRuntimeHelpers.uint64Subtract(0, 1, CelOptions.DEFAULT)); assertThrows( - ArithmeticException.class, + CelNumericOverflowException.class, () -> ProtoMessageRuntimeHelpers.uint64Subtract(-3, -1, CelOptions.DEFAULT)); assertThrows( - ArithmeticException.class, + CelNumericOverflowException.class, () -> ProtoMessageRuntimeHelpers.uint64Subtract(55, -40, CelOptions.DEFAULT)); } @@ -314,7 +315,7 @@ public void uint64Subtract_unsignedLongs() throws Exception { UnsignedLong.valueOf(3), UnsignedLong.valueOf(2))) .isEqualTo(UnsignedLong.ONE); assertThrows( - ArithmeticException.class, + CelNumericOverflowException.class, () -> ProtoMessageRuntimeHelpers.uint64Subtract(UnsignedLong.ONE, UnsignedLong.valueOf(2))); } diff --git a/runtime/src/test/java/dev/cel/runtime/planner/BUILD.bazel b/runtime/src/test/java/dev/cel/runtime/planner/BUILD.bazel index 01df7c9ee..2106fa5fe 100644 --- a/runtime/src/test/java/dev/cel/runtime/planner/BUILD.bazel +++ b/runtime/src/test/java/dev/cel/runtime/planner/BUILD.bazel @@ -23,6 +23,7 @@ java_library( "//common:operator", "//common:options", "//common/ast", + "//common/exceptions:divide_by_zero", "//common/internal:cel_descriptor_pools", "//common/internal:default_message_factory", "//common/internal:dynamic_proto", 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 968fdcc94..52ab5e417 100644 --- a/runtime/src/test/java/dev/cel/runtime/planner/ProgramPlannerTest.java +++ b/runtime/src/test/java/dev/cel/runtime/planner/ProgramPlannerTest.java @@ -38,6 +38,7 @@ import dev.cel.common.CelSource; import dev.cel.common.Operator; import dev.cel.common.ast.CelExpr; +import dev.cel.common.exceptions.CelDivideByZeroException; import dev.cel.common.internal.CelDescriptorPool; import dev.cel.common.internal.DefaultDescriptorPool; import dev.cel.common.internal.DefaultMessageFactory; @@ -536,7 +537,7 @@ public void plan_call_logicalOr_throws(String expression) throws Exception { CelEvaluationException e = assertThrows(CelEvaluationException.class, program::eval); assertThat(e).hasMessageThat().startsWith("evaluation error at :"); assertThat(e).hasMessageThat().endsWith("/ by zero"); - assertThat(e).hasCauseThat().isInstanceOf(ArithmeticException.class); + assertThat(e).hasCauseThat().isInstanceOf(CelDivideByZeroException.class); assertThat(e.getErrorCode()).isEqualTo(CelErrorCode.DIVIDE_BY_ZERO); } @@ -568,7 +569,7 @@ public void plan_call_logicalAnd_throws(String expression) throws Exception { CelEvaluationException e = assertThrows(CelEvaluationException.class, program::eval); assertThat(e).hasMessageThat().startsWith("evaluation error at :"); assertThat(e).hasMessageThat().endsWith("/ by zero"); - assertThat(e).hasCauseThat().isInstanceOf(ArithmeticException.class); + assertThat(e).hasCauseThat().isInstanceOf(CelDivideByZeroException.class); assertThat(e.getErrorCode()).isEqualTo(CelErrorCode.DIVIDE_BY_ZERO); } @@ -598,7 +599,7 @@ public void plan_call_conditional_throws(String expression) throws Exception { CelEvaluationException e = assertThrows(CelEvaluationException.class, program::eval); assertThat(e).hasMessageThat().startsWith("evaluation error at :"); assertThat(e).hasMessageThat().endsWith("/ by zero"); - assertThat(e).hasCauseThat().isInstanceOf(ArithmeticException.class); + assertThat(e).hasCauseThat().isInstanceOf(CelDivideByZeroException.class); assertThat(e.getErrorCode()).isEqualTo(CelErrorCode.DIVIDE_BY_ZERO); }