diff --git a/bundle/src/test/java/dev/cel/bundle/CelImplTest.java b/bundle/src/test/java/dev/cel/bundle/CelImplTest.java index a3ad60d40..fbacb242a 100644 --- a/bundle/src/test/java/dev/cel/bundle/CelImplTest.java +++ b/bundle/src/test/java/dev/cel/bundle/CelImplTest.java @@ -59,7 +59,6 @@ import com.google.rpc.context.AttributeContext; import com.google.testing.junit.testparameterinjector.TestParameter; import com.google.testing.junit.testparameterinjector.TestParameterInjector; -import com.google.testing.junit.testparameterinjector.TestParameters; import dev.cel.checker.CelCheckerLegacyImpl; import dev.cel.checker.DescriptorTypeProvider; import dev.cel.checker.ProtoTypeMask; @@ -232,9 +231,7 @@ public void check() throws Exception { } @Test - @TestParameters("{useProtoResultType: false}") - @TestParameters("{useProtoResultType: true}") - public void compile(boolean useProtoResultType) throws Exception { + public void compile(@TestParameter boolean useProtoResultType) throws Exception { CelBuilder celBuilder = standardCelBuilderWithMacros(); if (useProtoResultType) { celBuilder.setProtoResultType(CelProtoTypes.BOOL); @@ -246,9 +243,7 @@ public void compile(boolean useProtoResultType) throws Exception { } @Test - @TestParameters("{useProtoResultType: false}") - @TestParameters("{useProtoResultType: true}") - public void compile_resultTypeCheckFailure(boolean useProtoResultType) { + public void compile_resultTypeCheckFailure(@TestParameter boolean useProtoResultType) { CelBuilder celBuilder = standardCelBuilderWithMacros(); if (useProtoResultType) { celBuilder.setProtoResultType(CelProtoTypes.STRING); @@ -563,23 +558,6 @@ public void program_withVars() throws Exception { assertThat(program.eval(ImmutableMap.of("variable", "hello"))).isEqualTo(true); } - @Test - public void program_withCelValue() throws Exception { - Cel cel = - standardCelBuilderWithMacros() - .setOptions(CelOptions.current().enableCelValue(true).build()) - .addDeclarations( - Decl.newBuilder() - .setName("variable") - .setIdent(IdentDecl.newBuilder().setType(CelProtoTypes.STRING)) - .build()) - .setResultType(SimpleType.BOOL) - .build(); - - CelRuntime.Program program = cel.createProgram(cel.compile("variable == 'hello'").getAst()); - - assertThat(program.eval(ImmutableMap.of("variable", "hello"))).isEqualTo(true); - } @Test public void program_withProtoVars() throws Exception { @@ -1006,9 +984,8 @@ public void program_protoActivation() throws Exception { } @Test - @TestParameters("{resolveTypeDependencies: false}") - @TestParameters("{resolveTypeDependencies: true}") - public void program_enumTypeDirectResolution(boolean resolveTypeDependencies) throws Exception { + public void program_enumTypeDirectResolution(@TestParameter boolean resolveTypeDependencies) + throws Exception { Cel cel = standardCelBuilderWithMacros() .addFileTypes(StandaloneGlobalEnum.getDescriptor().getFile()) @@ -1029,9 +1006,7 @@ public void program_enumTypeDirectResolution(boolean resolveTypeDependencies) th } @Test - @TestParameters("{resolveTypeDependencies: false}") - @TestParameters("{resolveTypeDependencies: true}") - public void program_enumTypeReferenceResolution(boolean resolveTypeDependencies) + public void program_enumTypeReferenceResolution(@TestParameter boolean resolveTypeDependencies) throws Exception { Cel cel = standardCelBuilderWithMacros() @@ -1429,25 +1404,6 @@ public void programAdvanceEvaluation_nestedSelect() throws Exception { .isEqualTo(CelUnknownSet.create(CelAttribute.fromQualifiedIdentifier("com.google.a"))); } - @Test - public void programAdvanceEvaluation_nestedSelect_withCelValue() throws Exception { - Cel cel = - standardCelBuilderWithMacros() - .setOptions( - CelOptions.current().enableUnknownTracking(true).enableCelValue(true).build()) - .addVar("com", MapType.create(SimpleType.STRING, SimpleType.DYN)) - .addFunctionBindings() - .setResultType(SimpleType.BOOL) - .build(); - CelRuntime.Program program = cel.createProgram(cel.compile("com.google.a || false").getAst()); - - assertThat( - program.advanceEvaluation( - UnknownContext.create( - fromMap(ImmutableMap.of()), - ImmutableList.of(CelAttributePattern.fromQualifiedIdentifier("com.google.a"))))) - .isEqualTo(CelUnknownSet.create(CelAttribute.fromQualifiedIdentifier("com.google.a"))); - } @Test public void programAdvanceEvaluation_argumentMergeErrorPriority() throws Exception { diff --git a/common/BUILD.bazel b/common/BUILD.bazel index 4e0d7485c..b67069de7 100644 --- a/common/BUILD.bazel +++ b/common/BUILD.bazel @@ -22,6 +22,11 @@ java_library( exports = ["//common/src/main/java/dev/cel/common:container"], ) +cel_android_library( + name = "container_android", + exports = ["//common/src/main/java/dev/cel/common:container_android"], +) + java_library( name = "proto_ast", exports = ["//common/src/main/java/dev/cel/common:proto_ast"], diff --git a/common/ast/BUILD.bazel b/common/ast/BUILD.bazel index 302abfc79..1361ad76b 100644 --- a/common/ast/BUILD.bazel +++ b/common/ast/BUILD.bazel @@ -17,6 +17,12 @@ java_library( exports = ["//common/src/main/java/dev/cel/common/ast:cel_block"], ) +cel_android_library( + name = "cel_block_android", + visibility = ["//:internal"], + exports = ["//common/src/main/java/dev/cel/common/ast:cel_block_android"], +) + cel_android_library( name = "ast_android", exports = ["//common/src/main/java/dev/cel/common/ast:ast_android"], diff --git a/common/navigation/BUILD.bazel b/common/navigation/BUILD.bazel index 1dba25b8e..0c03596f9 100644 --- a/common/navigation/BUILD.bazel +++ b/common/navigation/BUILD.bazel @@ -1,4 +1,5 @@ load("@rules_java//java:defs.bzl", "java_library") +load("//:cel_android_rules.bzl", "cel_android_library") package( default_applicable_licenses = ["//:license"], @@ -15,6 +16,11 @@ java_library( exports = ["//common/src/main/java/dev/cel/common/navigation"], ) +cel_android_library( + name = "navigation_android", + exports = ["//common/src/main/java/dev/cel/common/navigation:navigation_android"], +) + java_library( name = "mutable_navigation", exports = ["//common/src/main/java/dev/cel/common/navigation:mutable_navigation"], diff --git a/common/src/main/java/dev/cel/common/BUILD.bazel b/common/src/main/java/dev/cel/common/BUILD.bazel index 38548744c..11b762220 100644 --- a/common/src/main/java/dev/cel/common/BUILD.bazel +++ b/common/src/main/java/dev/cel/common/BUILD.bazel @@ -365,6 +365,18 @@ java_library( ], ) +cel_android_library( + name = "container_android", + srcs = ["CelContainer.java"], + tags = [ + ], + deps = [ + "//:auto_value", + "@maven//:com_google_errorprone_error_prone_annotations", + "@maven_android//:com_google_guava_guava", + ], +) + java_library( name = "operator", srcs = ["Operator.java"], diff --git a/common/src/main/java/dev/cel/common/ast/BUILD.bazel b/common/src/main/java/dev/cel/common/ast/BUILD.bazel index 46c235d1f..c72857080 100644 --- a/common/src/main/java/dev/cel/common/ast/BUILD.bazel +++ b/common/src/main/java/dev/cel/common/ast/BUILD.bazel @@ -71,6 +71,20 @@ java_library( ], ) +cel_android_library( + name = "cel_block_android", + srcs = ["CelBlock.java"], + tags = [ + ], + deps = [ + ":ast_android", + "//common:cel_ast_android", + "//common/annotations", + "//common/navigation:navigation_android", + "@maven_android//:com_google_guava_guava", + ], +) + java_library( name = "expr_converter", srcs = EXPR_CONVERTER_SOURCES, diff --git a/common/src/main/java/dev/cel/common/navigation/BUILD.bazel b/common/src/main/java/dev/cel/common/navigation/BUILD.bazel index b43f3c289..3c2eaad62 100644 --- a/common/src/main/java/dev/cel/common/navigation/BUILD.bazel +++ b/common/src/main/java/dev/cel/common/navigation/BUILD.bazel @@ -1,4 +1,5 @@ load("@rules_java//java:defs.bzl", "java_library") +load("//:cel_android_rules.bzl", "cel_android_library") package( default_applicable_licenses = [ @@ -28,6 +29,25 @@ java_library( ], ) +cel_android_library( + name = "common_android", + srcs = [ + "BaseNavigableExpr.java", + "CelNavigableExprVisitor.java", + "ExprPropertyCalculator.java", + "TraversalOrder.java", + ], + tags = [ + ], + deps = [ + "//:auto_value", + "//common/ast:ast_android", + "@maven//:com_google_errorprone_error_prone_annotations", + "@maven//:org_jspecify_jspecify", + "@maven_android//:com_google_guava_guava", + ], +) + java_library( name = "navigation", srcs = [ @@ -47,6 +67,25 @@ java_library( ], ) +cel_android_library( + name = "navigation_android", + srcs = [ + "CelNavigableAst.java", + "CelNavigableExpr.java", + ], + tags = [ + ], + deps = [ + ":common_android", + "//:auto_value", + "//common:cel_ast_android", + "//common/ast:ast_android", + "@maven//:com_google_errorprone_error_prone_annotations", + "@maven//:org_jspecify_jspecify", + "@maven_android//:com_google_guava_guava", + ], +) + java_library( name = "mutable_navigation", srcs = [ diff --git a/common/src/main/java/dev/cel/common/values/BUILD.bazel b/common/src/main/java/dev/cel/common/values/BUILD.bazel index 5ccc498fd..433dcd477 100644 --- a/common/src/main/java/dev/cel/common/values/BUILD.bazel +++ b/common/src/main/java/dev/cel/common/values/BUILD.bazel @@ -408,6 +408,7 @@ java_library( ], deps = [ "//common/annotations", + "//common/values", "//common/values:base_proto_cel_value_converter", "//common/values:cel_value_provider", "@maven//:com_google_errorprone_error_prone_annotations", @@ -423,6 +424,7 @@ cel_android_library( "//common/annotations", "//common/values:base_proto_cel_value_converter_android", "//common/values:cel_value_provider_android", + "//common/values:values_android", "@maven//:com_google_errorprone_error_prone_annotations", ], ) diff --git a/common/src/main/java/dev/cel/common/values/BaseProtoMessageValueProvider.java b/common/src/main/java/dev/cel/common/values/BaseProtoMessageValueProvider.java index f42a16179..51bb0a497 100644 --- a/common/src/main/java/dev/cel/common/values/BaseProtoMessageValueProvider.java +++ b/common/src/main/java/dev/cel/common/values/BaseProtoMessageValueProvider.java @@ -28,4 +28,9 @@ public abstract class BaseProtoMessageValueProvider implements CelValueProvider { public abstract BaseProtoCelValueConverter protoCelValueConverter(); + + @Override + public CelValueConverter celValueConverter() { + return protoCelValueConverter(); + } } diff --git a/runtime/BUILD.bazel b/runtime/BUILD.bazel index d1cb99b64..c87fadca9 100644 --- a/runtime/BUILD.bazel +++ b/runtime/BUILD.bazel @@ -226,11 +226,21 @@ java_library( exports = ["//runtime/src/main/java/dev/cel/runtime:interpreter_util"], ) +cel_android_library( + name = "interpreter_util_android", + exports = ["//runtime/src/main/java/dev/cel/runtime:interpreter_util_android"], +) + java_library( name = "evaluation_listener", exports = ["//runtime/src/main/java/dev/cel/runtime:evaluation_listener"], ) +cel_android_library( + name = "evaluation_listener_android", + exports = ["//runtime/src/main/java/dev/cel/runtime:evaluation_listener_android"], +) + cel_android_library( name = "standard_functions_android", exports = [ @@ -352,7 +362,20 @@ java_library( ], ) +cel_android_library( + name = "accumulated_unknowns_android", + visibility = ["//:internal"], + exports = [ + "//runtime/src/main/java/dev/cel/runtime:accumulated_unknowns_android", + ], +) + java_library( name = "partial_vars", exports = ["//runtime/src/main/java/dev/cel/runtime:partial_vars"], ) + +cel_android_library( + name = "partial_vars_android", + exports = ["//runtime/src/main/java/dev/cel/runtime:partial_vars_android"], +) diff --git a/runtime/planner/BUILD.bazel b/runtime/planner/BUILD.bazel index 9b5dbee6a..860d413a0 100644 --- a/runtime/planner/BUILD.bazel +++ b/runtime/planner/BUILD.bazel @@ -1,4 +1,5 @@ load("@rules_java//java:defs.bzl", "java_library") +load("//:cel_android_rules.bzl", "cel_android_library") package( default_applicable_licenses = ["//:license"], @@ -10,6 +11,11 @@ java_library( exports = ["//runtime/src/main/java/dev/cel/runtime/planner:program_planner"], ) +cel_android_library( + name = "program_planner_android", + exports = ["//runtime/src/main/java/dev/cel/runtime/planner:program_planner_android"], +) + java_library( name = "planned_program", visibility = ["//:internal"], diff --git a/runtime/src/main/java/dev/cel/runtime/BUILD.bazel b/runtime/src/main/java/dev/cel/runtime/BUILD.bazel index 933758c04..489bb64d8 100644 --- a/runtime/src/main/java/dev/cel/runtime/BUILD.bazel +++ b/runtime/src/main/java/dev/cel/runtime/BUILD.bazel @@ -44,11 +44,6 @@ LITE_RUNTIME_IMPL_SOURCES = [ "LiteRuntimeImpl.java", ] -# keep sorted -LITE_PROGRAM_IMPL_SOURCES = [ - "LiteProgramImpl.java", -] - # keep sorted FUNCTION_BINDING_SOURCES = [ "CelFunctionBinding.java", @@ -416,7 +411,6 @@ java_library( "//common/internal:dynamic_proto", "//common/internal:proto_equality", "@maven//:com_google_errorprone_error_prone_annotations", - "@maven//:com_google_guava_guava", "@maven//:com_google_protobuf_protobuf_java", ], ) @@ -508,7 +502,6 @@ java_library( ":function_binding", ":function_resolver", ":resolved_overload", - "//:auto_value", "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", ], @@ -525,7 +518,6 @@ cel_android_library( ":function_binding_android", ":function_resolver_android", ":resolved_overload_android", - "//:auto_value", "@maven//:com_google_errorprone_error_prone_annotations", "@maven_android//:com_google_guava_guava", ], @@ -732,7 +724,6 @@ cel_android_library( "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", "@maven_android//:com_google_guava_guava", - "@maven_android//:com_google_protobuf_protobuf_javalite", ], ) @@ -876,7 +867,6 @@ java_library( tags = [ ], deps = [ - ":cel_value_runtime_type_provider", ":descriptor_message_provider", ":descriptor_type_resolver", ":dispatcher", @@ -901,7 +891,6 @@ java_library( "//common/types:type_providers", "//common/values", "//common/values:cel_value_provider", - "//common/values:proto_message_value_provider", "//runtime/standard:int", "//runtime/standard:timestamp", "@maven//:com_google_code_findbugs_annotations", @@ -969,15 +958,15 @@ java_library( ":evaluation_exception", ":function_binding", ":program", - "//:auto_value", "//common:cel_ast", + "//common:container", "//common:options", "//common/annotations", + "//common/types:type_providers", "//common/values:cel_value_provider", "//runtime/standard:standard_function", "@maven//:com_google_code_findbugs_annotations", "@maven//:com_google_errorprone_error_prone_annotations", - "@maven//:com_google_guava_guava", ], ) @@ -987,55 +976,25 @@ java_library( tags = [ ], deps = [ - ":cel_value_runtime_type_provider", ":dispatcher", ":function_binding", - ":interpreter", - ":lite_program_impl", ":lite_runtime", ":program", ":runtime_equality", ":runtime_helpers", - ":type_resolver", - "//:auto_value", "//common:cel_ast", + "//common:container", "//common:options", + "//common/types:default_type_provider", + "//common/types:type_providers", + "//common/values", "//common/values:cel_value_provider", + "//runtime:evaluation_exception", + "//runtime/planner:program_planner", "//runtime/standard:standard_function", "@maven//:com_google_code_findbugs_annotations", - "@maven//:com_google_guava_guava", - ], -) - -java_library( - name = "lite_program_impl", - srcs = LITE_PROGRAM_IMPL_SOURCES, - deps = [ - ":activation", - ":evaluation_exception", - ":function_resolver", - ":interpretable", - ":partial_vars", - ":program", - ":variable_resolver", - "//:auto_value", - "@maven//:com_google_errorprone_error_prone_annotations", - ], -) - -cel_android_library( - name = "lite_program_impl_android", - srcs = LITE_PROGRAM_IMPL_SOURCES, - deps = [ - ":activation_android", - ":evaluation_exception", - ":function_resolver_android", - ":interpretable_android", - ":partial_vars_android", - ":program_android", - ":variable_resolver", - "//:auto_value", "@maven//:com_google_errorprone_error_prone_annotations", + "@maven//:com_google_guava_guava", ], ) @@ -1045,20 +1004,21 @@ cel_android_library( tags = [ ], deps = [ - ":cel_value_runtime_type_provider_android", ":dispatcher_android", ":function_binding_android", - ":interpreter_android", - ":lite_program_impl_android", ":lite_runtime_android", ":program_android", ":runtime_equality_android", ":runtime_helpers_android", - ":type_resolver_android", - "//:auto_value", "//common:cel_ast_android", + "//common:container_android", "//common:options", + "//common/types:default_type_provider_android", + "//common/types:type_providers_android", "//common/values:cel_value_provider_android", + "//common/values:values_android", + "//runtime:evaluation_exception", + "//runtime/planner:program_planner_android", "//runtime/standard:standard_function_android", "@maven//:com_google_code_findbugs_annotations", "@maven//:com_google_errorprone_error_prone_annotations", @@ -1151,46 +1111,6 @@ cel_android_library( ], ) -java_library( - name = "cel_value_runtime_type_provider", - srcs = ["CelValueRuntimeTypeProvider.java"], - deps = [ - ":runtime_type_provider", - ":unknown_attributes", - "//common/annotations", - "//common/exceptions:attribute_not_found", - "//common/values", - "//common/values:base_proto_cel_value_converter", - "//common/values:base_proto_message_value_provider", - "//common/values:cel_value", - "//common/values:cel_value_provider", - "//common/values:combined_cel_value_provider", - "@maven//:com_google_errorprone_error_prone_annotations", - "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", - ], -) - -cel_android_library( - name = "cel_value_runtime_type_provider_android", - srcs = ["CelValueRuntimeTypeProvider.java"], - deps = [ - ":runtime_type_provider_android", - ":unknown_attributes_android", - "//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", - "//common/values:cel_value_provider_android", - "//common/values:combined_cel_value_provider_android", - "//common/values:values_android", - "@maven//:com_google_errorprone_error_prone_annotations", - "@maven_android//:com_google_guava_guava", - "@maven_android//:com_google_protobuf_protobuf_javalite", - ], -) - java_library( name = "interpreter_util", srcs = ["InterpreterUtil.java"], @@ -1210,7 +1130,6 @@ java_library( cel_android_library( name = "interpreter_util_android", srcs = ["InterpreterUtil.java"], - visibility = ["//visibility:private"], deps = [ ":accumulated_unknowns_android", ":evaluation_exception", @@ -1237,7 +1156,6 @@ java_library( cel_android_library( name = "evaluation_listener_android", srcs = ["CelEvaluationListener.java"], - visibility = ["//visibility:private"], deps = [ "//common/ast:ast_android", "@maven//:com_google_code_findbugs_annotations", @@ -1254,15 +1172,15 @@ cel_android_library( ":evaluation_exception", ":function_binding_android", ":program_android", - "//:auto_value", "//common:cel_ast_android", + "//common:container_android", "//common:options", "//common/annotations", + "//common/types:type_providers_android", "//common/values:cel_value_provider_android", "//runtime/standard:standard_function_android", "@maven//:com_google_code_findbugs_annotations", "@maven//:com_google_errorprone_error_prone_annotations", - "@maven_android//:com_google_guava_guava", ], ) @@ -1291,7 +1209,6 @@ java_library( cel_android_library( name = "accumulated_unknowns_android", srcs = ["AccumulatedUnknowns.java"], - visibility = ["//visibility:private"], deps = [ ":unknown_attributes_android", "//common/annotations", @@ -1343,7 +1260,6 @@ java_library( ":variable_resolver", "//:auto_value", "//runtime:unknown_attributes", - "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", ], ) @@ -1357,7 +1273,6 @@ cel_android_library( ":variable_resolver", "//:auto_value", "//runtime:unknown_attributes_android", - "@maven//:com_google_errorprone_error_prone_annotations", "@maven_android//:com_google_guava_guava", ], ) diff --git a/runtime/src/main/java/dev/cel/runtime/CelLiteRuntimeBuilder.java b/runtime/src/main/java/dev/cel/runtime/CelLiteRuntimeBuilder.java index 48b51274d..f2f27da27 100644 --- a/runtime/src/main/java/dev/cel/runtime/CelLiteRuntimeBuilder.java +++ b/runtime/src/main/java/dev/cel/runtime/CelLiteRuntimeBuilder.java @@ -16,7 +16,9 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.errorprone.annotations.CheckReturnValue; +import dev.cel.common.CelContainer; import dev.cel.common.CelOptions; +import dev.cel.common.types.CelTypeProvider; import dev.cel.common.values.CelValueProvider; import dev.cel.runtime.standard.CelStandardFunction; @@ -62,6 +64,28 @@ CelLiteRuntimeBuilder setStandardFunctions( @CanIgnoreReturnValue CelLiteRuntimeBuilder addLibraries(Iterable libraries); + /** + * Sets the {@link CelTypeProvider} for resolving CEL types during evaluation, such as a fully + * qualified type name to a struct or an enum value. + */ + @CanIgnoreReturnValue + CelLiteRuntimeBuilder setTypeProvider(CelTypeProvider celTypeProvider); + + /** + * Set the {@link CelContainer} to use as the namespace for resolving CEL expression variables and + * functions. + */ + @CanIgnoreReturnValue + CelLiteRuntimeBuilder setContainer(CelContainer container); + + /** Adds bindings for functions that are allowed to be late-bound (resolved at execution time). */ + @CanIgnoreReturnValue + CelLiteRuntimeBuilder addLateBoundFunctions(String... lateBoundFunctionNames); + + /** Adds bindings for functions that are allowed to be late-bound (resolved at execution time). */ + @CanIgnoreReturnValue + CelLiteRuntimeBuilder addLateBoundFunctions(Iterable lateBoundFunctionNames); + @CheckReturnValue CelLiteRuntime build(); } diff --git a/runtime/src/main/java/dev/cel/runtime/CelRuntimeLegacyImpl.java b/runtime/src/main/java/dev/cel/runtime/CelRuntimeLegacyImpl.java index b9ce022cf..c5e06d013 100644 --- a/runtime/src/main/java/dev/cel/runtime/CelRuntimeLegacyImpl.java +++ b/runtime/src/main/java/dev/cel/runtime/CelRuntimeLegacyImpl.java @@ -44,7 +44,6 @@ import dev.cel.common.types.CelTypes; import dev.cel.common.values.CelValueConverter; import dev.cel.common.values.CelValueProvider; -import dev.cel.common.values.ProtoMessageValueProvider; import dev.cel.runtime.standard.IntFunction.IntOverload; import dev.cel.runtime.standard.TimestampFunction.TimestampOverload; import java.util.Arrays; @@ -78,7 +77,6 @@ public final class CelRuntimeLegacyImpl implements CelRuntime { private final Function customTypeFactory; private final CelStandardFunctions overriddenStandardFunctions; - private final CelValueProvider celValueProvider; private final ImmutableSet fileDescriptors; // This does not affect the evaluation behavior in any manner. @@ -113,9 +111,6 @@ public CelRuntimeBuilder toRuntimeBuilder() { builder.setStandardFunctions(overriddenStandardFunctions); } - if (celValueProvider != null) { - builder.setValueProvider(celValueProvider); - } return builder; } @@ -136,7 +131,6 @@ public static final class Builder implements CelRuntimeBuilder { @VisibleForTesting final ImmutableSet.Builder celRuntimeLibraries; @VisibleForTesting Function customTypeFactory; - @VisibleForTesting CelValueProvider celValueProvider; @VisibleForTesting CelStandardFunctions overriddenStandardFunctions; private CelOptions options; @@ -209,8 +203,8 @@ public CelRuntimeBuilder setTypeProvider(CelTypeProvider celTypeProvider) { @Override public CelRuntimeBuilder setValueProvider(CelValueProvider celValueProvider) { - this.celValueProvider = celValueProvider; - return this; + throw new UnsupportedOperationException( + "setValueProvider is not supported for legacy runtime"); } @Override @@ -335,19 +329,10 @@ public CelRuntimeLegacyImpl build() { RuntimeTypeProvider runtimeTypeProvider; if (options.enableCelValue()) { - CelValueProvider messageValueProvider = celValueProvider; - - if (messageValueProvider == null) { - messageValueProvider = ProtoMessageValueProvider.newInstance(options, dynamicProto); - } - - runtimeTypeProvider = CelValueRuntimeTypeProvider.newInstance(messageValueProvider); - celValueConverter = messageValueProvider.celValueConverter(); + throw new UnsupportedOperationException( + "enableCelValue is not supported for legacy runtime"); } else { runtimeTypeProvider = new DescriptorMessageProvider(runtimeTypeFactory, options); - if (celValueProvider != null) { - celValueConverter = celValueProvider.celValueConverter(); - } } DefaultInterpreter interpreter = @@ -364,7 +349,6 @@ public CelRuntimeLegacyImpl build() { extensionRegistry, customTypeFactory, overriddenStandardFunctions, - celValueProvider, fileDescriptors, runtimeLibraries, ImmutableList.copyOf(customFunctionBindings.values())); @@ -452,7 +436,6 @@ private CelRuntimeLegacyImpl( ExtensionRegistry extensionRegistry, @Nullable Function customTypeFactory, @Nullable CelStandardFunctions overriddenStandardFunctions, - @Nullable CelValueProvider celValueProvider, ImmutableSet fileDescriptors, ImmutableSet celRuntimeLibraries, ImmutableList celFunctionBindings) { @@ -462,7 +445,6 @@ private CelRuntimeLegacyImpl( this.extensionRegistry = extensionRegistry; this.customTypeFactory = customTypeFactory; this.overriddenStandardFunctions = overriddenStandardFunctions; - this.celValueProvider = celValueProvider; this.fileDescriptors = fileDescriptors; this.celRuntimeLibraries = celRuntimeLibraries; this.celFunctionBindings = celFunctionBindings; diff --git a/runtime/src/main/java/dev/cel/runtime/CelValueRuntimeTypeProvider.java b/runtime/src/main/java/dev/cel/runtime/CelValueRuntimeTypeProvider.java deleted file mode 100644 index 38365127c..000000000 --- a/runtime/src/main/java/dev/cel/runtime/CelValueRuntimeTypeProvider.java +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright 2023 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 static com.google.common.base.Preconditions.checkNotNull; - -import com.google.errorprone.annotations.Immutable; -import com.google.protobuf.MessageLite; -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.CelValueProvider; -import dev.cel.common.values.CombinedCelValueProvider; -import dev.cel.common.values.SelectableValue; -import java.util.Map; -import java.util.NoSuchElementException; - -/** Bridge between the old RuntimeTypeProvider and CelValueProvider APIs. */ -@Internal -@Immutable -final class CelValueRuntimeTypeProvider implements RuntimeTypeProvider { - - private final CelValueProvider valueProvider; - private final BaseProtoCelValueConverter protoCelValueConverter; - private static final BaseProtoCelValueConverter DEFAULT_CEL_VALUE_CONVERTER = - new BaseProtoCelValueConverter() {}; - - static CelValueRuntimeTypeProvider newInstance(CelValueProvider valueProvider) { - BaseProtoCelValueConverter converter = DEFAULT_CEL_VALUE_CONVERTER; - - // Find the underlying ProtoCelValueConverter. - // This is required because DefaultInterpreter works with a resolved protobuf messages directly - // in evaluation flow. - // A new runtime should not directly depend on protobuf, thus this will not be needed in the - // future. - if (valueProvider instanceof BaseProtoMessageValueProvider) { - converter = ((BaseProtoMessageValueProvider) valueProvider).protoCelValueConverter(); - } else if (valueProvider instanceof CombinedCelValueProvider) { - converter = - ((CombinedCelValueProvider) valueProvider) - .valueProviders().stream() - .filter(p -> p instanceof BaseProtoMessageValueProvider) - .map(p -> ((BaseProtoMessageValueProvider) p).protoCelValueConverter()) - .findFirst() - .orElse(DEFAULT_CEL_VALUE_CONVERTER); - } - - return new CelValueRuntimeTypeProvider(valueProvider, converter); - } - - @Override - public Object createMessage(String messageName, Map values) { - return protoCelValueConverter.maybeUnwrap( - valueProvider - .newValue(messageName, values) - .orElseThrow( - () -> - new NoSuchElementException( - String.format("cannot resolve '%s' as a message", messageName)))); - } - - @Override - public Object selectField(Object message, String fieldName) { - if (message instanceof Map) { - Map map = (Map) message; - if (map.containsKey(fieldName)) { - return map.get(fieldName); - } - - throw CelAttributeNotFoundException.forMissingMapKey(fieldName); - } - - SelectableValue selectableValue = getSelectableValueOrThrow(message, fieldName); - Object value = selectableValue.select(fieldName); - - return protoCelValueConverter.maybeUnwrap(value); - } - - @Override - public Object hasField(Object message, String fieldName) { - SelectableValue selectableValue = getSelectableValueOrThrow(message, fieldName); - - return selectableValue.find(fieldName).isPresent(); - } - - @SuppressWarnings("unchecked") - private SelectableValue getSelectableValueOrThrow(Object obj, String fieldName) { - Object convertedCelValue = protoCelValueConverter.toRuntimeValue(obj); - - if (!(convertedCelValue instanceof SelectableValue)) { - throwInvalidFieldSelection(fieldName); - } - - return (SelectableValue) convertedCelValue; - } - - @Override - public Object adapt(String messageName, Object message) { - if (message instanceof CelUnknownSet) { - return message; // CelUnknownSet is handled specially for iterative evaluation. No need to - // adapt to CelValue. - } - - if (message instanceof MessageLite.Builder) { - message = ((MessageLite.Builder) message).build(); - } - - if (message instanceof MessageLite) { - return protoCelValueConverter.maybeUnwrap(protoCelValueConverter.toRuntimeValue(message)); - } - - return message; - } - - private static void throwInvalidFieldSelection(String fieldName) { - throw CelAttributeNotFoundException.forFieldResolution(fieldName); - } - - private CelValueRuntimeTypeProvider( - CelValueProvider valueProvider, BaseProtoCelValueConverter protoCelValueConverter) { - this.valueProvider = checkNotNull(valueProvider); - this.protoCelValueConverter = checkNotNull(protoCelValueConverter); - } -} diff --git a/runtime/src/main/java/dev/cel/runtime/LiteProgramImpl.java b/runtime/src/main/java/dev/cel/runtime/LiteProgramImpl.java deleted file mode 100644 index af8c1a6d0..000000000 --- a/runtime/src/main/java/dev/cel/runtime/LiteProgramImpl.java +++ /dev/null @@ -1,64 +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; - -import com.google.auto.value.AutoValue; -import com.google.errorprone.annotations.Immutable; -import java.util.Map; - -@Immutable -@AutoValue -abstract class LiteProgramImpl implements Program { - - abstract Interpretable interpretable(); - - @Override - public Object eval() throws CelEvaluationException { - return interpretable().eval(GlobalResolver.EMPTY); - } - - @Override - public Object eval(Map mapValue) throws CelEvaluationException { - return interpretable().eval(Activation.copyOf(mapValue)); - } - - @Override - public Object eval(Map mapValue, CelFunctionResolver lateBoundFunctionResolver) - throws CelEvaluationException { - return interpretable().eval(Activation.copyOf(mapValue), lateBoundFunctionResolver); - } - - @Override - public Object eval(CelVariableResolver resolver, CelFunctionResolver lateBoundFunctionResolver) { - // TODO: Wire in program planner - throw new UnsupportedOperationException("To be implemented"); - } - - @Override - public Object eval(CelVariableResolver resolver) throws CelEvaluationException { - // TODO: Wire in program planner - throw new UnsupportedOperationException("To be implemented"); - } - - @Override - public Object eval(PartialVars partialVars) throws CelEvaluationException { - // TODO: Wire in program planner - throw new UnsupportedOperationException("To be implemented"); - } - - static Program plan(Interpretable interpretable) { - return new AutoValue_LiteProgramImpl(interpretable); - } -} diff --git a/runtime/src/main/java/dev/cel/runtime/LiteRuntimeImpl.java b/runtime/src/main/java/dev/cel/runtime/LiteRuntimeImpl.java index 8ce2d7733..6572621a6 100644 --- a/runtime/src/main/java/dev/cel/runtime/LiteRuntimeImpl.java +++ b/runtime/src/main/java/dev/cel/runtime/LiteRuntimeImpl.java @@ -15,37 +15,43 @@ package dev.cel.runtime; import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Preconditions.checkState; import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import javax.annotation.concurrent.ThreadSafe; import dev.cel.common.CelAbstractSyntaxTree; +import dev.cel.common.CelContainer; import dev.cel.common.CelOptions; +import dev.cel.common.types.CelTypeProvider; +import dev.cel.common.types.DefaultTypeProvider; +import dev.cel.common.values.CelValueConverter; import dev.cel.common.values.CelValueProvider; +import dev.cel.runtime.planner.ProgramPlanner; import dev.cel.runtime.standard.CelStandardFunction; import java.util.Arrays; import java.util.HashMap; +import java.util.Map; import java.util.Optional; @ThreadSafe final class LiteRuntimeImpl implements CelLiteRuntime { - private final Interpreter interpreter; + private final ProgramPlanner planner; private final CelOptions celOptions; private final ImmutableList customFunctionBindings; private final ImmutableSet celStandardFunctions; private final CelValueProvider celValueProvider; + private final CelTypeProvider celTypeProvider; + private final CelContainer celContainer; - // This does not affect the evaluation behavior in any manner. // CEL-Internal-4 private final ImmutableSet runtimeLibraries; @Override - public Program createProgram(CelAbstractSyntaxTree ast) { - checkState(ast.isChecked(), "programs must be created from checked expressions"); - return LiteProgramImpl.plan(interpreter.createInterpretable(ast)); + public Program createProgram(CelAbstractSyntaxTree ast) throws CelEvaluationException { + return planner.plan(ast); } @Override @@ -55,12 +61,17 @@ public CelLiteRuntimeBuilder toRuntimeBuilder() { .setOptions(celOptions) .setStandardFunctions(celStandardFunctions) .addFunctionBindings(customFunctionBindings) - .addLibraries(runtimeLibraries); + .addLibraries(runtimeLibraries) + .setContainer(celContainer); if (celValueProvider != null) { builder.setValueProvider(celValueProvider); } + if (celTypeProvider != null) { + builder.setTypeProvider(celTypeProvider); + } + return builder; } @@ -72,9 +83,18 @@ static final class Builder implements CelLiteRuntimeBuilder { @VisibleForTesting final ImmutableSet.Builder runtimeLibrariesBuilder; @VisibleForTesting final ImmutableSet.Builder standardFunctionBuilder; @VisibleForTesting CelValueProvider celValueProvider; + private CelContainer container; + @VisibleForTesting final ImmutableSet.Builder lateBoundFunctionNamesBuilder; + @VisibleForTesting CelTypeProvider celTypeProvider; @Override public CelLiteRuntimeBuilder setOptions(CelOptions celOptions) { + Preconditions.checkArgument( + celOptions.enableUnsignedLongs(), + "CelLiteRuntime requires CelOptions.enableUnsignedLongs(true)."); + Preconditions.checkArgument( + celOptions.unwrapWellKnownTypesOnFunctionDispatch(), + "CelLiteRuntime requires CelOptions.unwrapWellKnownTypesOnFunctionDispatch(true)."); this.celOptions = celOptions; return this; } @@ -119,12 +139,32 @@ public CelLiteRuntimeBuilder addLibraries(Iterable lateBoundFunctionNames) { + lateBoundFunctionNamesBuilder.addAll(lateBoundFunctionNames); + return this; + } + + @Override + public CelLiteRuntimeBuilder setTypeProvider(CelTypeProvider celTypeProvider) { + this.celTypeProvider = celTypeProvider; + return this; + } + + @Override + public CelLiteRuntimeBuilder setContainer(CelContainer container) { + this.container = checkNotNull(container); + return this; + } + /** Throws if an unsupported flag in CelOptions is toggled. */ private static void assertAllowedCelOptions(CelOptions celOptions) { String prefix = "Misconfigured CelOptions: "; - if (!celOptions.enableCelValue()) { - throw new IllegalArgumentException(prefix + "enableCelValue must be enabled."); - } if (!celOptions.enableUnsignedLongs()) { throw new IllegalArgumentException(prefix + "enableUnsignedLongs cannot be disabled."); } @@ -175,28 +215,52 @@ public CelLiteRuntime build() { func.getDefinition()); }); - Interpreter interpreter = - new DefaultInterpreter( - TypeResolver.create(celValueProvider.celValueConverter()), - CelValueRuntimeTypeProvider.newInstance(celValueProvider), + CelTypeProvider celTypeProvider = DefaultTypeProvider.getInstance(); + if (this.celTypeProvider != null) { + celTypeProvider = + new CelTypeProvider.CombinedCelTypeProvider(celTypeProvider, this.celTypeProvider); + } + + ProgramPlanner planner = + ProgramPlanner.newPlanner( + celTypeProvider, + celValueProvider, dispatcherBuilder.build(), - celOptions); + celValueProvider.celValueConverter(), + container, + celOptions, + lateBoundFunctionNamesBuilder.build()); return new LiteRuntimeImpl( - interpreter, + planner, celOptions, customFunctionBindings.values(), standardFunctions, runtimeLibs, - celValueProvider); + celValueProvider, + celTypeProvider, + container); } private Builder() { - this.celOptions = CelOptions.current().enableCelValue(true).build(); - this.celValueProvider = (structType, fields) -> Optional.empty(); + this.celOptions = CelOptions.DEFAULT; + this.celValueProvider = + new CelValueProvider() { + @Override + public Optional newValue(String structType, Map fields) { + return Optional.empty(); + } + + @Override + public CelValueConverter celValueConverter() { + return CelValueConverter.getDefaultInstance(); + } + }; this.customFunctionBindings = new HashMap<>(); this.standardFunctionBuilder = ImmutableSet.builder(); this.runtimeLibrariesBuilder = ImmutableSet.builder(); + this.lateBoundFunctionNamesBuilder = ImmutableSet.builder(); + this.container = CelContainer.newBuilder().build(); } } @@ -205,17 +269,21 @@ static CelLiteRuntimeBuilder newBuilder() { } private LiteRuntimeImpl( - Interpreter interpreter, + ProgramPlanner planner, CelOptions celOptions, Iterable customFunctionBindings, ImmutableSet celStandardFunctions, ImmutableSet runtimeLibraries, - CelValueProvider celValueProvider) { - this.interpreter = interpreter; + CelValueProvider celValueProvider, + CelTypeProvider celTypeProvider, + CelContainer celContainer) { + this.planner = planner; this.celOptions = celOptions; this.customFunctionBindings = ImmutableList.copyOf(customFunctionBindings); this.celStandardFunctions = celStandardFunctions; this.runtimeLibraries = runtimeLibraries; this.celValueProvider = celValueProvider; + this.celTypeProvider = celTypeProvider; + this.celContainer = celContainer; } } 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 e82f77c67..67a06ffb5 100644 --- a/runtime/src/main/java/dev/cel/runtime/planner/BUILD.bazel +++ b/runtime/src/main/java/dev/cel/runtime/planner/BUILD.bazel @@ -1,4 +1,5 @@ load("@rules_java//java:defs.bzl", "java_library") +load("//:cel_android_rules.bzl", "cel_android_library") package( default_applicable_licenses = ["//:license"], @@ -37,11 +38,8 @@ java_library( ":eval_unary", ":eval_var_args_call", ":eval_zero_arity", - ":interpretable_attribute", ":planned_interpretable", ":planned_program", - ":qualifier", - ":string_qualifier", "//:auto_value", "//common:cel_ast", "//common:container", @@ -108,33 +106,26 @@ java_library( ], ) -java_library( - name = "interpretable_attribute", - srcs = ["InterpretableAttribute.java"], - deps = [ - ":planned_interpretable", - ":qualifier", - "//common/ast", - "@maven//:com_google_errorprone_error_prone_annotations", - ], -) - java_library( name = "attribute", srcs = [ "Attribute.java", "AttributeFactory.java", + "InterpretableAttribute.java", "MaybeAttribute.java", "MissingAttribute.java", "NamespacedAttribute.java", + "PresenceTestQualifier.java", + "Qualifier.java", "RelativeAttribute.java", + "StringQualifier.java", ], deps = [ ":activation_wrapper", ":eval_helpers", ":planned_interpretable", - ":qualifier", "//common:container", + "//common/ast", "//common/exceptions:attribute_not_found", "//common/types", "//common/types:type_providers", @@ -151,125 +142,210 @@ java_library( ) java_library( - name = "activation_wrapper", - srcs = ["ActivationWrapper.java"], + name = "eval_attribute", + srcs = ["EvalAttribute.java"], deps = [ + ":attribute", + ":planned_interpretable", + "//common/ast", "//runtime:interpretable", + "@maven//:com_google_errorprone_error_prone_annotations", ], ) java_library( - name = "qualifier", - srcs = ["Qualifier.java"], + name = "eval_create_list", + srcs = ["EvalCreateList.java"], deps = [ + ":eval_helpers", + ":planned_interpretable", + "//common/ast", + "//runtime:accumulated_unknowns", + "//runtime:interpretable", "@maven//:com_google_errorprone_error_prone_annotations", + "@maven//:com_google_guava_guava", ], ) java_library( - name = "presence_test_qualifier", - srcs = ["PresenceTestQualifier.java"], + name = "eval_create_map", + srcs = ["EvalCreateMap.java"], deps = [ - ":attribute", - ":qualifier", + ":eval_helpers", + ":localized_evaluation_exception", + ":planned_interpretable", + "//common/ast", + "//common/exceptions:duplicate_key", + "//common/exceptions:invalid_argument", + "//runtime:accumulated_unknowns", + "//runtime:evaluation_exception", + "//runtime:interpretable", + "@maven//:com_google_errorprone_error_prone_annotations", + "@maven//:com_google_guava_guava", + ], +) + +java_library( + name = "activation_wrapper", + srcs = ["ActivationWrapper.java"], + deps = ["//runtime:interpretable"], +) + +java_library( + name = "error_metadata", + srcs = ["ErrorMetadata.java"], + deps = [ + "//runtime:metadata", + "@maven//:com_google_errorprone_error_prone_annotations", + "@maven//:com_google_guava_guava", + ], +) + +java_library( + name = "eval_and", + srcs = ["EvalAnd.java"], + deps = [ + ":eval_helpers", + ":planned_interpretable", + "//common/ast", "//common/values", + "//runtime:accumulated_unknowns", + "//runtime:interpretable", + "@maven//:com_google_guava_guava", ], ) java_library( - name = "string_qualifier", - srcs = ["StringQualifier.java"], + name = "eval_binary", + srcs = ["EvalBinary.java"], deps = [ - ":qualifier", - "//common/exceptions:attribute_not_found", + ":eval_helpers", + ":planned_interpretable", + "//common/ast", "//common/values", + "//runtime:accumulated_unknowns", + "//runtime:evaluation_exception", + "//runtime:interpretable", + "//runtime:resolved_overload", ], ) java_library( - name = "eval_attribute", - srcs = ["EvalAttribute.java"], + name = "eval_block", + srcs = ["EvalBlock.java"], deps = [ - ":attribute", - ":interpretable_attribute", ":planned_interpretable", - ":qualifier", "//common/ast", + "//runtime:evaluation_exception", "//runtime:interpretable", "@maven//:com_google_errorprone_error_prone_annotations", ], ) java_library( - name = "eval_test_only", - srcs = ["EvalTestOnly.java"], + name = "eval_conditional", + srcs = ["EvalConditional.java"], deps = [ - ":interpretable_attribute", ":planned_interpretable", - ":presence_test_qualifier", - ":qualifier", "//common/ast", + "//runtime:accumulated_unknowns", "//runtime:evaluation_exception", "//runtime:interpretable", - "@maven//:com_google_errorprone_error_prone_annotations", + "@maven//:com_google_guava_guava", ], ) java_library( - name = "eval_zero_arity", - srcs = ["EvalZeroArity.java"], + name = "eval_create_struct", + srcs = ["EvalCreateStruct.java"], deps = [ ":eval_helpers", ":planned_interpretable", "//common/ast", + "//common/types:type_providers", "//common/values", - "//runtime:evaluation_exception", + "//common/values:cel_value_provider", + "//runtime:accumulated_unknowns", "//runtime:interpretable", - "//runtime:resolved_overload", + "@maven//:com_google_errorprone_error_prone_annotations", + "@maven//:com_google_guava_guava", ], ) java_library( - name = "eval_unary", - srcs = ["EvalUnary.java"], + name = "eval_exhaustive_and", + srcs = ["EvalExhaustiveAnd.java"], deps = [ ":eval_helpers", ":planned_interpretable", "//common/ast", "//common/values", - "//runtime:evaluation_exception", + "//runtime:accumulated_unknowns", "//runtime:interpretable", - "//runtime:resolved_overload", + "@maven//:com_google_errorprone_error_prone_annotations", ], ) java_library( - name = "eval_binary", - srcs = ["EvalBinary.java"], + name = "eval_exhaustive_conditional", + srcs = ["EvalExhaustiveConditional.java"], deps = [ ":eval_helpers", ":planned_interpretable", "//common/ast", - "//common/values", "//runtime:accumulated_unknowns", "//runtime:evaluation_exception", "//runtime:interpretable", - "//runtime:resolved_overload", + "@maven//:com_google_errorprone_error_prone_annotations", ], ) java_library( - name = "eval_var_args_call", - srcs = ["EvalVarArgsCall.java"], + name = "eval_exhaustive_or", + srcs = ["EvalExhaustiveOr.java"], deps = [ ":eval_helpers", ":planned_interpretable", "//common/ast", "//common/values", "//runtime:accumulated_unknowns", + "//runtime:interpretable", + "@maven//:com_google_errorprone_error_prone_annotations", + ], +) + +java_library( + name = "eval_fold", + srcs = ["EvalFold.java"], + deps = [ + ":activation_wrapper", + ":planned_interpretable", + "//common/ast", + "//common/exceptions:runtime_exception", + "//common/values:mutable_map_value", + "//runtime:accumulated_unknowns", + "//runtime:concatenated_list_view", + "//runtime:evaluation_exception", + "//runtime:interpretable", + "@maven//:com_google_errorprone_error_prone_annotations", + "@maven//:com_google_guava_guava", + "@maven//:org_jspecify_jspecify", + ], +) + +java_library( + name = "eval_helpers", + srcs = ["EvalHelpers.java"], + deps = [ + ":localized_evaluation_exception", + ":planned_interpretable", + "//common:error_codes", + "//common/exceptions:runtime_exception", + "//common/values", "//runtime:evaluation_exception", "//runtime:interpretable", "//runtime:resolved_overload", + "@maven//:com_google_guava_guava", ], ) @@ -291,130 +367,125 @@ java_library( ) java_library( - name = "eval_or", - srcs = ["EvalOr.java"], + name = "eval_optional_or", + srcs = ["EvalOptionalOr.java"], deps = [ ":eval_helpers", ":planned_interpretable", "//common/ast", - "//common/values", + "//common/exceptions:overload_not_found", "//runtime:accumulated_unknowns", "//runtime:interpretable", + "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", ], ) java_library( - name = "eval_and", - srcs = ["EvalAnd.java"], + name = "eval_optional_or_value", + srcs = ["EvalOptionalOrValue.java"], deps = [ ":eval_helpers", ":planned_interpretable", "//common/ast", - "//common/values", + "//common/exceptions:overload_not_found", "//runtime:accumulated_unknowns", "//runtime:interpretable", + "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", ], ) java_library( - name = "eval_conditional", - srcs = ["EvalConditional.java"], + name = "eval_optional_select_field", + srcs = ["EvalOptionalSelectField.java"], deps = [ + ":eval_helpers", ":planned_interpretable", "//common/ast", + "//common/values", "//runtime:accumulated_unknowns", - "//runtime:evaluation_exception", "//runtime:interpretable", + "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", ], ) java_library( - name = "eval_create_struct", - srcs = ["EvalCreateStruct.java"], + name = "eval_or", + srcs = ["EvalOr.java"], deps = [ ":eval_helpers", ":planned_interpretable", "//common/ast", - "//common/types:type_providers", "//common/values", - "//common/values:cel_value_provider", "//runtime:accumulated_unknowns", "//runtime:interpretable", - "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:com_google_guava_guava", ], ) java_library( - name = "eval_create_list", - srcs = ["EvalCreateList.java"], + name = "eval_test_only", + srcs = ["EvalTestOnly.java"], deps = [ - ":eval_helpers", + ":attribute", ":planned_interpretable", "//common/ast", - "//runtime:accumulated_unknowns", + "//runtime:evaluation_exception", "//runtime:interpretable", "@maven//:com_google_errorprone_error_prone_annotations", - "@maven//:com_google_guava_guava", ], ) java_library( - name = "eval_create_map", - srcs = ["EvalCreateMap.java"], + name = "eval_unary", + srcs = ["EvalUnary.java"], deps = [ ":eval_helpers", - ":localized_evaluation_exception", ":planned_interpretable", "//common/ast", - "//common/exceptions:duplicate_key", - "//common/exceptions:invalid_argument", - "//runtime:accumulated_unknowns", + "//common/values", "//runtime:evaluation_exception", "//runtime:interpretable", - "@maven//:com_google_errorprone_error_prone_annotations", - "@maven//:com_google_guava_guava", + "//runtime:resolved_overload", ], ) java_library( - name = "eval_fold", - srcs = ["EvalFold.java"], + name = "eval_var_args_call", + srcs = ["EvalVarArgsCall.java"], deps = [ - ":activation_wrapper", + ":eval_helpers", ":planned_interpretable", "//common/ast", - "//common/exceptions:runtime_exception", - "//common/values:mutable_map_value", + "//common/values", "//runtime:accumulated_unknowns", - "//runtime:concatenated_list_view", "//runtime:evaluation_exception", "//runtime:interpretable", - "@maven//:com_google_errorprone_error_prone_annotations", - "@maven//:com_google_guava_guava", - "@maven//:org_jspecify_jspecify", + "//runtime:resolved_overload", ], ) java_library( - name = "eval_helpers", - srcs = ["EvalHelpers.java"], + name = "eval_zero_arity", + srcs = ["EvalZeroArity.java"], deps = [ - ":localized_evaluation_exception", + ":eval_helpers", ":planned_interpretable", - "//common:error_codes", - "//common/exceptions:runtime_exception", + "//common/ast", "//common/values", "//runtime:evaluation_exception", "//runtime:interpretable", "//runtime:resolved_overload", - "@maven//:com_google_guava_guava", ], ) +alias( + name = "interpretable_attribute", + actual = ":attribute", +) + java_library( name = "localized_evaluation_exception", srcs = ["LocalizedEvaluationException.java"], @@ -424,16 +495,6 @@ java_library( ], ) -java_library( - name = "error_metadata", - srcs = ["ErrorMetadata.java"], - deps = [ - "//runtime:metadata", - "@maven//:com_google_errorprone_error_prone_annotations", - "@maven//:com_google_guava_guava", - ], -) - java_library( name = "planned_interpretable", srcs = [ @@ -458,101 +519,505 @@ java_library( ], ) -java_library( - name = "eval_optional_or", - srcs = ["EvalOptionalOr.java"], +cel_android_library( + name = "program_planner_android", + srcs = ["ProgramPlanner.java"], + tags = [ + ], deps = [ - ":eval_helpers", - ":planned_interpretable", - "//common/ast", + ":attribute_android", + ":error_metadata_android", + ":eval_and_android", + ":eval_attribute_android", + ":eval_binary_android", + ":eval_block_android", + ":eval_conditional_android", + ":eval_const_android", + ":eval_create_list_android", + ":eval_create_map_android", + ":eval_create_struct_android", + ":eval_exhaustive_and_android", + ":eval_exhaustive_conditional_android", + ":eval_exhaustive_or_android", + ":eval_fold_android", + ":eval_late_bound_call_android", + ":eval_optional_or_android", + ":eval_optional_or_value_android", + ":eval_optional_select_field_android", + ":eval_or_android", + ":eval_test_only_android", + ":eval_unary_android", + ":eval_var_args_call_android", + ":eval_zero_arity_android", + ":planned_interpretable_android", + ":planned_program_android", + "//:auto_value", + "//common:cel_ast_android", + "//common:container_android", + "//common:operator_android", + "//common:options", + "//common/annotations", + "//common/ast:ast_android", + "//common/ast:cel_block_android", "//common/exceptions:overload_not_found", - "//runtime:accumulated_unknowns", - "//runtime:interpretable", + "//common/types:type_providers_android", + "//common/types:types_android", + "//common/values:cel_value_provider_android", + "//common/values:values_android", + "//runtime:dispatcher_android", + "//runtime:evaluation_exception", + "//runtime:evaluation_exception_builder", + "//runtime:resolved_overload_android", + "//runtime/src/main/java/dev/cel/runtime:program_android", "@maven//:com_google_errorprone_error_prone_annotations", - "@maven//:com_google_guava_guava", + "@maven//:org_jspecify_jspecify", + "@maven_android//:com_google_guava_guava", ], ) -java_library( - name = "eval_optional_or_value", - srcs = ["EvalOptionalOrValue.java"], +cel_android_library( + name = "planned_program_android", + srcs = ["PlannedProgram.java"], deps = [ - ":eval_helpers", - ":planned_interpretable", - "//common/ast", - "//common/exceptions:overload_not_found", - "//runtime:accumulated_unknowns", - "//runtime:interpretable", + ":error_metadata_android", + ":localized_evaluation_exception_android", + ":planned_interpretable_android", + "//:auto_value", + "//common:options", + "//common/annotations", + "//common/exceptions:runtime_exception", + "//common/values:values_android", + "//runtime:activation_android", + "//runtime:evaluation_exception", + "//runtime:evaluation_exception_builder", + "//runtime:interpretable_android", + "//runtime:resolved_overload_android", + "//runtime:variable_resolver", + "//runtime/src/main/java/dev/cel/runtime:evaluation_listener_android", + "//runtime/src/main/java/dev/cel/runtime:function_resolver_android", + "//runtime/src/main/java/dev/cel/runtime:interpreter_util_android", + "//runtime/src/main/java/dev/cel/runtime:partial_vars_android", + "//runtime/src/main/java/dev/cel/runtime:program_android", "@maven//:com_google_errorprone_error_prone_annotations", - "@maven//:com_google_guava_guava", + "@maven//:org_jspecify_jspecify", ], ) -java_library( - name = "eval_optional_select_field", - srcs = ["EvalOptionalSelectField.java"], +cel_android_library( + name = "eval_const_android", + srcs = ["EvalConstant.java"], deps = [ - ":eval_helpers", - ":planned_interpretable", - "//common/ast", - "//common/values", - "//runtime:accumulated_unknowns", - "//runtime:interpretable", + ":planned_interpretable_android", + "//common/ast:ast_android", + "//runtime:interpretable_android", "@maven//:com_google_errorprone_error_prone_annotations", - "@maven//:com_google_guava_guava", ], ) -java_library( - name = "eval_exhaustive_and", +cel_android_library( + name = "attribute_android", + srcs = [ + "Attribute.java", + "AttributeFactory.java", + "InterpretableAttribute.java", + "MaybeAttribute.java", + "MissingAttribute.java", + "NamespacedAttribute.java", + "PresenceTestQualifier.java", + "Qualifier.java", + "RelativeAttribute.java", + "StringQualifier.java", + ], + deps = [ + ":activation_wrapper_android", + ":eval_helpers_android", + ":planned_interpretable_android", + "//common:container_android", + "//common/ast:ast_android", + "//common/exceptions:attribute_not_found", + "//common/types:type_providers_android", + "//common/types:types_android", + "//common/values:values_android", + "//runtime:interpretable_android", + "//runtime:unknown_attributes_android", + "//runtime/src/main/java/dev/cel/runtime:accumulated_unknowns_android", + "//runtime/src/main/java/dev/cel/runtime:interpreter_util_android", + "//runtime/src/main/java/dev/cel/runtime:partial_vars_android", + "@maven//:com_google_errorprone_error_prone_annotations", + "@maven//:org_jspecify_jspecify", + "@maven_android//:com_google_guava_guava", + ], +) + +cel_android_library( + name = "eval_attribute_android", + srcs = ["EvalAttribute.java"], + deps = [ + ":attribute_android", + ":planned_interpretable_android", + "//common/ast:ast_android", + "//runtime:interpretable_android", + "@maven//:com_google_errorprone_error_prone_annotations", + ], +) + +cel_android_library( + name = "eval_create_list_android", + srcs = ["EvalCreateList.java"], + deps = [ + ":eval_helpers_android", + ":planned_interpretable_android", + "//common/ast:ast_android", + "//runtime:interpretable_android", + "//runtime/src/main/java/dev/cel/runtime:accumulated_unknowns_android", + "@maven//:com_google_errorprone_error_prone_annotations", + "@maven_android//:com_google_guava_guava", + ], +) + +cel_android_library( + name = "eval_create_map_android", + srcs = ["EvalCreateMap.java"], + deps = [ + ":eval_helpers_android", + ":localized_evaluation_exception_android", + ":planned_interpretable_android", + "//common/ast:ast_android", + "//common/exceptions:duplicate_key", + "//common/exceptions:invalid_argument", + "//runtime:evaluation_exception", + "//runtime:interpretable_android", + "//runtime/src/main/java/dev/cel/runtime:accumulated_unknowns_android", + "@maven//:com_google_errorprone_error_prone_annotations", + "@maven_android//:com_google_guava_guava", + ], +) + +cel_android_library( + name = "activation_wrapper_android", + srcs = ["ActivationWrapper.java"], + deps = ["//runtime:interpretable_android"], +) + +cel_android_library( + name = "error_metadata_android", + srcs = ["ErrorMetadata.java"], + deps = [ + "//runtime:metadata", + "@maven//:com_google_errorprone_error_prone_annotations", + "@maven_android//:com_google_guava_guava", + ], +) + +cel_android_library( + name = "eval_and_android", + srcs = ["EvalAnd.java"], + deps = [ + ":eval_helpers_android", + ":planned_interpretable_android", + "//common/ast:ast_android", + "//common/values:values_android", + "//runtime:interpretable_android", + "//runtime/src/main/java/dev/cel/runtime:accumulated_unknowns_android", + "@maven_android//:com_google_guava_guava", + ], +) + +cel_android_library( + name = "eval_binary_android", + srcs = ["EvalBinary.java"], + deps = [ + ":eval_helpers_android", + ":planned_interpretable_android", + "//common/ast:ast_android", + "//common/values:values_android", + "//runtime:evaluation_exception", + "//runtime:interpretable_android", + "//runtime:resolved_overload_android", + "//runtime/src/main/java/dev/cel/runtime:accumulated_unknowns_android", + ], +) + +cel_android_library( + name = "eval_block_android", + srcs = ["EvalBlock.java"], + deps = [ + ":planned_interpretable_android", + "//common/ast:ast_android", + "//runtime:evaluation_exception", + "//runtime:interpretable_android", + "@maven//:com_google_errorprone_error_prone_annotations", + ], +) + +cel_android_library( + name = "eval_conditional_android", + srcs = ["EvalConditional.java"], + deps = [ + ":planned_interpretable_android", + "//common/ast:ast_android", + "//runtime:evaluation_exception", + "//runtime:interpretable_android", + "//runtime/src/main/java/dev/cel/runtime:accumulated_unknowns_android", + "@maven_android//:com_google_guava_guava", + ], +) + +cel_android_library( + name = "eval_create_struct_android", + srcs = ["EvalCreateStruct.java"], + deps = [ + ":eval_helpers_android", + ":planned_interpretable_android", + "//common/ast:ast_android", + "//common/types:type_providers_android", + "//common/values:cel_value_provider_android", + "//common/values:values_android", + "//runtime:interpretable_android", + "//runtime/src/main/java/dev/cel/runtime:accumulated_unknowns_android", + "@maven//:com_google_errorprone_error_prone_annotations", + "@maven_android//:com_google_guava_guava", + ], +) + +cel_android_library( + name = "eval_exhaustive_and_android", srcs = ["EvalExhaustiveAnd.java"], deps = [ - ":eval_helpers", - ":planned_interpretable", - "//common/ast", - "//common/values", - "//runtime:accumulated_unknowns", - "//runtime:interpretable", + ":eval_helpers_android", + ":planned_interpretable_android", + "//common/ast:ast_android", + "//common/values:values_android", + "//runtime:interpretable_android", + "//runtime/src/main/java/dev/cel/runtime:accumulated_unknowns_android", "@maven//:com_google_errorprone_error_prone_annotations", ], ) -java_library( - name = "eval_exhaustive_or", +cel_android_library( + name = "eval_exhaustive_conditional_android", + srcs = ["EvalExhaustiveConditional.java"], + deps = [ + ":eval_helpers_android", + ":planned_interpretable_android", + "//common/ast:ast_android", + "//runtime:evaluation_exception", + "//runtime:interpretable_android", + "//runtime/src/main/java/dev/cel/runtime:accumulated_unknowns_android", + "@maven//:com_google_errorprone_error_prone_annotations", + ], +) + +cel_android_library( + name = "eval_exhaustive_or_android", srcs = ["EvalExhaustiveOr.java"], deps = [ - ":eval_helpers", - ":planned_interpretable", - "//common/ast", - "//common/values", - "//runtime:accumulated_unknowns", - "//runtime:interpretable", + ":eval_helpers_android", + ":planned_interpretable_android", + "//common/ast:ast_android", + "//common/values:values_android", + "//runtime:interpretable_android", + "//runtime/src/main/java/dev/cel/runtime:accumulated_unknowns_android", "@maven//:com_google_errorprone_error_prone_annotations", ], ) -java_library( - name = "eval_exhaustive_conditional", - srcs = ["EvalExhaustiveConditional.java"], +cel_android_library( + name = "eval_fold_android", + srcs = ["EvalFold.java"], deps = [ - ":eval_helpers", - ":planned_interpretable", - "//common/ast", - "//runtime:accumulated_unknowns", + ":activation_wrapper_android", + ":planned_interpretable_android", + "//common/ast:ast_android", + "//common/exceptions:runtime_exception", + "//common/values:mutable_map_value_android", + "//runtime:concatenated_list_view", "//runtime:evaluation_exception", - "//runtime:interpretable", + "//runtime:interpretable_android", + "//runtime/src/main/java/dev/cel/runtime:accumulated_unknowns_android", "@maven//:com_google_errorprone_error_prone_annotations", + "@maven//:org_jspecify_jspecify", + "@maven_android//:com_google_guava_guava", ], ) -java_library( - name = "eval_block", - srcs = ["EvalBlock.java"], +cel_android_library( + name = "eval_helpers_android", + srcs = ["EvalHelpers.java"], deps = [ - ":planned_interpretable", - "//common/ast", + ":localized_evaluation_exception_android", + ":planned_interpretable_android", + "//common:error_codes", + "//common/exceptions:runtime_exception", + "//common/values:values_android", "//runtime:evaluation_exception", - "//runtime:interpretable", + "//runtime:interpretable_android", + "//runtime:resolved_overload_android", + "@maven_android//:com_google_guava_guava", + ], +) + +cel_android_library( + name = "eval_late_bound_call_android", + srcs = ["EvalLateBoundCall.java"], + deps = [ + ":eval_helpers_android", + ":planned_interpretable_android", + "//common/ast:ast_android", + "//common/exceptions:overload_not_found", + "//common/values:values_android", + "//runtime:evaluation_exception", + "//runtime:interpretable_android", + "//runtime:resolved_overload_android", + "//runtime/src/main/java/dev/cel/runtime:accumulated_unknowns_android", + "@maven_android//:com_google_guava_guava", + ], +) + +cel_android_library( + name = "eval_optional_or_android", + srcs = ["EvalOptionalOr.java"], + deps = [ + ":eval_helpers_android", + ":planned_interpretable_android", + "//common/ast:ast_android", + "//common/exceptions:overload_not_found", + "//runtime:interpretable_android", + "//runtime/src/main/java/dev/cel/runtime:accumulated_unknowns_android", "@maven//:com_google_errorprone_error_prone_annotations", + "@maven_android//:com_google_guava_guava", + ], +) + +cel_android_library( + name = "eval_optional_or_value_android", + srcs = ["EvalOptionalOrValue.java"], + deps = [ + ":eval_helpers_android", + ":planned_interpretable_android", + "//common/ast:ast_android", + "//common/exceptions:overload_not_found", + "//runtime:interpretable_android", + "//runtime/src/main/java/dev/cel/runtime:accumulated_unknowns_android", + "@maven//:com_google_errorprone_error_prone_annotations", + "@maven_android//:com_google_guava_guava", + ], +) + +cel_android_library( + name = "eval_optional_select_field_android", + srcs = ["EvalOptionalSelectField.java"], + deps = [ + ":eval_helpers_android", + ":planned_interpretable_android", + "//common/ast:ast_android", + "//common/values:values_android", + "//runtime:interpretable_android", + "//runtime/src/main/java/dev/cel/runtime:accumulated_unknowns_android", + "@maven//:com_google_errorprone_error_prone_annotations", + "@maven_android//:com_google_guava_guava", + ], +) + +cel_android_library( + name = "eval_or_android", + srcs = ["EvalOr.java"], + deps = [ + ":eval_helpers_android", + ":planned_interpretable_android", + "//common/ast:ast_android", + "//common/values:values_android", + "//runtime:interpretable_android", + "//runtime/src/main/java/dev/cel/runtime:accumulated_unknowns_android", + "@maven_android//:com_google_guava_guava", + ], +) + +cel_android_library( + name = "eval_test_only_android", + srcs = ["EvalTestOnly.java"], + deps = [ + ":attribute_android", + ":planned_interpretable_android", + "//common/ast:ast_android", + "//runtime:evaluation_exception", + "//runtime:interpretable_android", + "@maven//:com_google_errorprone_error_prone_annotations", + ], +) + +cel_android_library( + name = "eval_unary_android", + srcs = ["EvalUnary.java"], + deps = [ + ":eval_helpers_android", + ":planned_interpretable_android", + "//common/ast:ast_android", + "//common/values:values_android", + "//runtime:evaluation_exception", + "//runtime:interpretable_android", + "//runtime:resolved_overload_android", + ], +) + +cel_android_library( + name = "eval_var_args_call_android", + srcs = ["EvalVarArgsCall.java"], + deps = [ + ":eval_helpers_android", + ":planned_interpretable_android", + "//common/ast:ast_android", + "//common/values:values_android", + "//runtime:evaluation_exception", + "//runtime:interpretable_android", + "//runtime:resolved_overload_android", + "//runtime/src/main/java/dev/cel/runtime:accumulated_unknowns_android", + ], +) + +cel_android_library( + name = "eval_zero_arity_android", + srcs = ["EvalZeroArity.java"], + deps = [ + ":eval_helpers_android", + ":planned_interpretable_android", + "//common/ast:ast_android", + "//common/values:values_android", + "//runtime:evaluation_exception", + "//runtime:interpretable_android", + "//runtime:resolved_overload_android", + ], +) + +cel_android_library( + name = "localized_evaluation_exception_android", + srcs = ["LocalizedEvaluationException.java"], + deps = [ + "//common:error_codes", + "//common/exceptions:runtime_exception", + ], +) + +cel_android_library( + name = "planned_interpretable_android", + srcs = [ + "BlockMemoizer.java", + "ExecutionFrame.java", + "PlannedInterpretable.java", + ], + deps = [ + ":localized_evaluation_exception_android", + "//common:options", + "//common/ast:ast_android", + "//common/exceptions:iteration_budget_exceeded", + "//runtime:evaluation_exception", + "//runtime:evaluation_listener_android", + "//runtime:interpretable_android", + "//runtime:interpreter_util_android", + "//runtime:resolved_overload_android", + "//runtime/src/main/java/dev/cel/runtime:function_resolver_android", + "//runtime/src/main/java/dev/cel/runtime:partial_vars_android", + "@maven//:com_google_errorprone_error_prone_annotations", + "@maven//:org_jspecify_jspecify", ], ) diff --git a/runtime/src/main/java/dev/cel/runtime/planner/MissingAttribute.java b/runtime/src/main/java/dev/cel/runtime/planner/MissingAttribute.java index b7fb8ad72..46af3c701 100644 --- a/runtime/src/main/java/dev/cel/runtime/planner/MissingAttribute.java +++ b/runtime/src/main/java/dev/cel/runtime/planner/MissingAttribute.java @@ -15,10 +15,12 @@ package dev.cel.runtime.planner; import com.google.common.collect.ImmutableSet; +import com.google.errorprone.annotations.Immutable; import dev.cel.common.exceptions.CelAttributeNotFoundException; import dev.cel.runtime.GlobalResolver; /** Represents a missing attribute that is surfaced while resolving a struct field or a map key. */ +@Immutable final class MissingAttribute implements Attribute { private final ImmutableSet missingAttributes; diff --git a/runtime/src/main/java/dev/cel/runtime/planner/PresenceTestQualifier.java b/runtime/src/main/java/dev/cel/runtime/planner/PresenceTestQualifier.java index 5c2cba1ed..a93ec74b7 100644 --- a/runtime/src/main/java/dev/cel/runtime/planner/PresenceTestQualifier.java +++ b/runtime/src/main/java/dev/cel/runtime/planner/PresenceTestQualifier.java @@ -16,10 +16,12 @@ import static dev.cel.runtime.planner.MissingAttribute.newMissingField; +import com.google.errorprone.annotations.Immutable; import dev.cel.common.values.SelectableValue; import java.util.Map; /** A qualifier for presence testing a field or a map key. */ +@Immutable final class PresenceTestQualifier implements Qualifier { @SuppressWarnings("Immutable") diff --git a/runtime/src/main/java/dev/cel/runtime/planner/StringQualifier.java b/runtime/src/main/java/dev/cel/runtime/planner/StringQualifier.java index 293ca5c7d..21a4b6721 100644 --- a/runtime/src/main/java/dev/cel/runtime/planner/StringQualifier.java +++ b/runtime/src/main/java/dev/cel/runtime/planner/StringQualifier.java @@ -14,12 +14,14 @@ package dev.cel.runtime.planner; +import com.google.errorprone.annotations.Immutable; import dev.cel.common.exceptions.CelAttributeNotFoundException; import dev.cel.common.values.OptionalValue; import dev.cel.common.values.SelectableValue; import java.util.Map; /** A qualifier that accesses fields or map keys using a string identifier. */ +@Immutable final class StringQualifier implements Qualifier { private final String value; diff --git a/runtime/src/test/java/dev/cel/runtime/AbstractPlannerInterpreterTest.java b/runtime/src/test/java/dev/cel/runtime/AbstractPlannerInterpreterTest.java new file mode 100644 index 000000000..8910511ae --- /dev/null +++ b/runtime/src/test/java/dev/cel/runtime/AbstractPlannerInterpreterTest.java @@ -0,0 +1,280 @@ +// 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; + +import com.google.common.collect.ImmutableMap; +import com.google.protobuf.Timestamp; +import dev.cel.common.CelContainer; +import dev.cel.common.CelOptions; +import dev.cel.common.types.ListType; +import dev.cel.common.types.SimpleType; +import dev.cel.common.types.StructTypeReference; +import dev.cel.expr.conformance.proto3.TestAllTypes; +import dev.cel.testing.BaseInterpreterTest; +import java.util.Arrays; +import java.util.Objects; +import org.junit.Test; + +public abstract class AbstractPlannerInterpreterTest extends BaseInterpreterTest { + + @Override + public void optional_errors() { + // Exercised in planner_optional_errors instead + skipBaselineVerification(); + } + + @Test + public void planner_optional_errors() { + source = "optional.unwrap([dyn(1)])"; + runTest(ImmutableMap.of()); + } + + @Override + public void unknownField() { + // Exercised in planner_unknownFieldSelection instead + skipBaselineVerification(); + } + + @Override + public void unknownResultSet() { + // Exercised in planner_unknownResultSet_success instead + skipBaselineVerification(); + } + + @Test + public void planner_unknownFieldSelection() { + setContainer(CelContainer.ofName(TestAllTypes.getDescriptor().getFile().getPackage())); + declareVariable("x", StructTypeReference.create(TestAllTypes.getDescriptor().getFullName())); + + CelAttributePattern patternX = CelAttributePattern.fromQualifiedIdentifier("x"); + + source = "x"; + // We have the full message, but we're claiming that the attribute is unknown. + runTest(ImmutableMap.of("x", TestAllTypes.getDefaultInstance()), patternX); + // A "partially known message". The result is still an unknown. + runTest( + ImmutableMap.of("x", TestAllTypes.getDefaultInstance()), + CelAttributePattern.fromQualifiedIdentifier("x.single_int32")); + + source = "x.single_int32"; + runTest(ImmutableMap.of(), patternX); + runTest(ImmutableMap.of(), CelAttributePattern.fromQualifiedIdentifier("x.single_int32")); + + source = "x.map_int32_int64[22]"; + runTest(ImmutableMap.of(), patternX); + runTest(ImmutableMap.of(), CelAttributePattern.fromQualifiedIdentifier("x.map_int32_int64")); + + source = "x.repeated_nested_message[1]"; + runTest(ImmutableMap.of(), patternX); + runTest( + ImmutableMap.of(), + CelAttributePattern.fromQualifiedIdentifier("x.repeated_nested_message")); + + source = "x.single_nested_message.bb"; + runTest(ImmutableMap.of(), patternX); + runTest( + ImmutableMap.of(), + CelAttributePattern.fromQualifiedIdentifier("x.single_nested_message.bb")); + + source = "{1: x.single_int32}"; + runTest(ImmutableMap.of(), patternX); + runTest(ImmutableMap.of(), CelAttributePattern.fromQualifiedIdentifier("x.single_int32")); + + source = "[1, x.single_int32]"; + runTest(ImmutableMap.of(), patternX); + runTest(ImmutableMap.of(), CelAttributePattern.fromQualifiedIdentifier("x.single_int32")); + } + + @Test + public void planner_unknownResultSet_success() { + setContainer(CelContainer.ofName(TestAllTypes.getDescriptor().getFile().getPackage())); + declareVariable("x", StructTypeReference.create(TestAllTypes.getDescriptor().getFullName())); + TestAllTypes message = + TestAllTypes.newBuilder() + .setSingleString("test") + .setSingleTimestamp(Timestamp.newBuilder().setSeconds(15)) + .build(); + ImmutableMap variables = ImmutableMap.of("x", message); + CelAttributePattern unknownInt32 = + CelAttributePattern.fromQualifiedIdentifier("x.single_int32"); + CelAttributePattern unknownInt64 = + CelAttributePattern.fromQualifiedIdentifier("x.single_int64"); + + source = "x.single_int32 == 1 && true"; + runTest(variables, unknownInt32); + + source = "x.single_int32 == 1 && false"; + runTest(variables, unknownInt32); + + source = "x.single_int32 == 1 && x.single_int64 == 1"; + runTest(variables, unknownInt32, unknownInt64); + + source = "true && x.single_int32 == 1"; + runTest(variables, unknownInt32); + + source = "false && x.single_int32 == 1"; + runTest(variables, unknownInt32); + + source = "x.single_int32 == 1 || x.single_string == \"test\""; + runTest(variables, unknownInt32); + + source = "x.single_int32 == 1 || x.single_string != \"test\""; + runTest(variables, unknownInt32); + + source = "x.single_int32 == 1 || x.single_int64 == 1"; + runTest(variables, unknownInt32, unknownInt64); + + source = "true || x.single_int32 == 1"; + runTest(variables, unknownInt32); + + source = "false || x.single_int32 == 1"; + runTest(variables, unknownInt32); + + // dispatch test + declareFunction( + "f", memberOverload("f", Arrays.asList(SimpleType.INT, SimpleType.INT), SimpleType.BOOL)); + celRuntime = + newBaseRuntimeBuilder( + CelOptions.current() + .enableHeterogeneousNumericComparisons(true) + .enableOptionalSyntax(true) + .comprehensionMaxIterations(1_000) + .build()) + .addFunctionBindings( + CelFunctionBinding.from("f", Integer.class, Integer.class, Objects::equals)) + .setContainer(CelContainer.ofName(TestAllTypes.getDescriptor().getFile().getPackage())) + .build(); + + source = "x.single_int32.f(1)"; + runTest(variables, unknownInt32); + + source = "1.f(x.single_int32)"; + runTest(variables, unknownInt32); + + source = "x.single_int64.f(x.single_int32)"; + runTest(variables, unknownInt32, unknownInt64); + + source = "[0, 2, 4].exists(z, z == 2 || z == x.single_int32)"; + runTest(variables, unknownInt32); + + source = "[0, 2, 4].exists(z, z == x.single_int32)"; + runTest(variables, unknownInt32); + + source = + "[0, 2, 4].exists_one(z, z == 0 || (z == 2 && z == x.single_int32) " + + "|| (z == 4 && z == x.single_int64))"; + runTest(variables, unknownInt32, unknownInt64); + + source = "[0, 2].all(z, z == 2 || z == x.single_int32)"; + runTest(variables, unknownInt32); + + source = + "[0, 2, 4].filter(z, z == 0 || (z == 2 && z == x.single_int32) " + + "|| (z == 4 && z == x.single_int64))"; + runTest(variables, unknownInt32, unknownInt64); + + source = + "[0, 2, 4].map(z, z == 0 || (z == 2 && z == x.single_int32) " + + "|| (z == 4 && z == x.single_int64))"; + runTest(variables, unknownInt32, unknownInt64); + + source = "x.single_int32 == 1 ? 1 : 2"; + runTest(variables, unknownInt32); + + source = "true ? x.single_int32 : 2"; + runTest(variables, unknownInt32); + + source = "true ? 1 : x.single_int32"; + runTest(variables, unknownInt32); + + source = "false ? x.single_int32 : 2"; + runTest(variables, unknownInt32); + + source = "false ? 1 : x.single_int32"; + runTest(variables, unknownInt32); + + source = "x.single_int64 == 1 ? x.single_int32 : x.single_int32"; + runTest(variables, unknownInt32, unknownInt64); + + source = "{x.single_int32: 2, 3: 4}"; + runTest(variables, unknownInt32); + + source = "{1: x.single_int32, 3: 4}"; + runTest(variables, unknownInt32); + + source = "{1: x.single_int32, x.single_int64: 4}"; + runTest(variables, unknownInt32, unknownInt64); + + source = "[1, x.single_int32, 3, 4]"; + runTest(variables, unknownInt32); + + source = "[1, x.single_int32, x.single_int64, 4]"; + runTest(variables, unknownInt32, unknownInt64); + + source = "TestAllTypes{single_int32: x.single_int32}.single_int32 == 2"; + runTest(variables, unknownInt32); + + source = "TestAllTypes{single_int32: x.single_int32, single_int64: x.single_int64}"; + runTest(variables, unknownInt32, unknownInt64); + + clearAllDeclarations(); + declareVariable("unknown_list", ListType.create(SimpleType.INT)); + source = "unknown_list.map(x, x)"; + runTest(variables, CelAttributePattern.fromQualifiedIdentifier("unknown_list")); + + clearAllDeclarations(); + declareVariable("x", StructTypeReference.create(TestAllTypes.getDescriptor().getFullName())); + source = "cel.bind(x, [1, 2, 3], 1 in x)"; + runTest(variables, CelAttributePattern.fromQualifiedIdentifier("x")); + } + + @Test + public void planner_unknownResultSet_errors() { + declareVariable("x", StructTypeReference.create(TestAllTypes.getDescriptor().getFullName())); + TestAllTypes message = + TestAllTypes.newBuilder() + .setSingleString("test") + .setSingleTimestamp(Timestamp.newBuilder().setSeconds(15)) + .build(); + ImmutableMap variables = ImmutableMap.of("x", message); + CelAttributePattern unknownInt32 = + CelAttributePattern.fromQualifiedIdentifier("x.single_int32"); + + source = "x.single_int32 == 1 && x.single_timestamp <= timestamp(\"bad timestamp string\")"; + runTest(variables, unknownInt32); + + source = "x.single_timestamp <= timestamp(\"bad timestamp string\") && x.single_int32 == 1"; + runTest(variables, unknownInt32); + + source = + "x.single_timestamp <= timestamp(\"bad timestamp string\") " + + "&& x.single_timestamp > timestamp(\"another bad timestamp string\")"; + runTest(variables, unknownInt32); + + source = "x.single_int32 == 1 || x.single_timestamp <= timestamp(\"bad timestamp string\")"; + runTest(variables, unknownInt32); + + source = "x.single_timestamp <= timestamp(\"bad timestamp string\") || x.single_int32 == 1"; + runTest(variables, unknownInt32); + + source = + "x.single_timestamp <= timestamp(\"bad timestamp string\") " + + "|| x.single_timestamp > timestamp(\"another bad timestamp string\")"; + runTest(variables, unknownInt32); + + source = "x"; + runTest(ImmutableMap.of(), CelAttributePattern.fromQualifiedIdentifier("x")); + } +} diff --git a/runtime/src/test/java/dev/cel/runtime/BUILD.bazel b/runtime/src/test/java/dev/cel/runtime/BUILD.bazel index e886c3d8a..a2e44223a 100644 --- a/runtime/src/test/java/dev/cel/runtime/BUILD.bazel +++ b/runtime/src/test/java/dev/cel/runtime/BUILD.bazel @@ -19,6 +19,7 @@ java_library( ["*.java"], # keep sorted exclude = [ + "AbstractPlannerInterpreterTest.java", "CelLiteInterpreterTest.java", "InterpreterTest.java", "PlannerInterpreterTest.java", @@ -55,7 +56,6 @@ java_library( "//common/types:message_type_provider", "//common/values", "//common/values:cel_byte_string", - "//common/values:cel_value_provider", "//common/values:proto_message_lite_value_provider", "//compiler", "//compiler:compiler_builder", @@ -127,6 +127,24 @@ java_library( ], ) +java_library( + name = "abstract_planner_interpreter_test", + testonly = 1, + srcs = ["AbstractPlannerInterpreterTest.java"], + deps = [ + "//common:container", + "//common:options", + "//common/types", + "//runtime:function_binding", + "//runtime:unknown_attributes", + "//testing:base_interpreter_test", + "@cel_spec//proto/cel/expr/conformance/proto3:test_all_types_java_proto", + "@maven//:com_google_guava_guava", + "@maven//:com_google_protobuf_protobuf_java", + "@maven//:junit_junit", + ], +) + java_library( name = "planner_interpreter_test", testonly = 1, @@ -137,20 +155,15 @@ java_library( "//runtime/testdata", ], deps = [ + ":abstract_planner_interpreter_test", "//common:cel_ast", "//common:compiler_common", "//common:container", "//common:options", - "//common/types", "//common/types:type_providers", "//extensions", "//runtime", - "//runtime:function_binding", - "//runtime:unknown_attributes", - "//testing:base_interpreter_test", "@cel_spec//proto/cel/expr/conformance/proto3:test_all_types_java_proto", - "@maven//:com_google_guava_guava", - "@maven//:com_google_protobuf_protobuf_java", "@maven//:com_google_testparameterinjector_test_parameter_injector", "@maven//:junit_junit", ], @@ -176,6 +189,7 @@ cel_android_local_test( "//runtime:lite_runtime_android", "//runtime:lite_runtime_factory_android", "//runtime:lite_runtime_impl_android", + "//runtime:partial_vars_android", "//runtime:standard_functions_android", "//runtime:unknown_attributes_android", "//runtime/src/main/java/dev/cel/runtime:program_android", @@ -199,7 +213,11 @@ java_library( srcs = [ "CelLiteInterpreterTest.java", ], + resources = [ + "//runtime/testdata", + ], deps = [ + ":abstract_planner_interpreter_test", "//common:options", "//common/values:proto_message_lite_value_provider", "//extensions:optional_library", diff --git a/runtime/src/test/java/dev/cel/runtime/CelLiteInterpreterTest.java b/runtime/src/test/java/dev/cel/runtime/CelLiteInterpreterTest.java index 1d1a316c0..bc0fde200 100644 --- a/runtime/src/test/java/dev/cel/runtime/CelLiteInterpreterTest.java +++ b/runtime/src/test/java/dev/cel/runtime/CelLiteInterpreterTest.java @@ -27,16 +27,18 @@ * ProtoMessageLiteValueProvider} and full version of protobuf messages. */ @RunWith(TestParameterInjector.class) -public class CelLiteInterpreterTest extends BaseInterpreterTest { +public class CelLiteInterpreterTest extends AbstractPlannerInterpreterTest { @Override protected CelRuntimeBuilder newBaseRuntimeBuilder(CelOptions celOptions) { - return CelRuntimeFactory.standardCelRuntimeBuilder() + return CelRuntimeFactory.plannerRuntimeBuilder() .setValueProvider( ProtoMessageLiteValueProvider.newInstance( dev.cel.expr.conformance.proto2.TestAllTypesCelDescriptor.getDescriptor(), TestAllTypesCelDescriptor.getDescriptor())) .addLibraries(CelOptionalLibrary.INSTANCE) + .addFileTypes(TEST_FILE_DESCRIPTORS) + .addLateBoundFunctions("record") .setOptions(celOptions.toBuilder().enableCelValue(true).build()); } diff --git a/runtime/src/test/java/dev/cel/runtime/CelLiteRuntimeAndroidTest.java b/runtime/src/test/java/dev/cel/runtime/CelLiteRuntimeAndroidTest.java index 73492d126..6c54ce486 100644 --- a/runtime/src/test/java/dev/cel/runtime/CelLiteRuntimeAndroidTest.java +++ b/runtime/src/test/java/dev/cel/runtime/CelLiteRuntimeAndroidTest.java @@ -192,7 +192,10 @@ public void eval_add() throws Exception { @Test public void eval_stringLiteral() throws Exception { - CelLiteRuntime runtime = CelLiteRuntimeFactory.newLiteRuntimeBuilder().build(); + CelLiteRuntime runtime = + CelLiteRuntimeFactory.newLiteRuntimeBuilder() + .setStandardFunctions(CelStandardFunctions.ALL_STANDARD_FUNCTIONS) + .build(); // Expr: 'hello world' CelAbstractSyntaxTree ast = readCheckedExpr("compiled_hello_world"); Program program = runtime.createProgram(ast); @@ -205,7 +208,10 @@ public void eval_stringLiteral() throws Exception { @Test @SuppressWarnings("unchecked") public void eval_listLiteral() throws Exception { - CelLiteRuntime runtime = CelLiteRuntimeFactory.newLiteRuntimeBuilder().build(); + CelLiteRuntime runtime = + CelLiteRuntimeFactory.newLiteRuntimeBuilder() + .setStandardFunctions(CelStandardFunctions.ALL_STANDARD_FUNCTIONS) + .build(); // Expr: ['a', 1, 2u, 3.5] CelAbstractSyntaxTree ast = readCheckedExpr("compiled_list_literal"); Program program = runtime.createProgram(ast); @@ -286,6 +292,7 @@ public void eval_customFunctions_asLateBoundFunctions() throws Exception { CelLiteRuntime runtime = CelLiteRuntimeFactory.newLiteRuntimeBuilder() .addFunctionBindings(CelFunctionBinding.from("list_isEmpty", List.class, List::isEmpty)) + .addLateBoundFunctions("isEmpty") .setStandardFunctions(CelStandardFunctions.ALL_STANDARD_FUNCTIONS) .build(); // Expr: ''.isEmpty() && [].isEmpty() @@ -307,11 +314,18 @@ public void eval_customFunctions_asLateBoundFunctions() throws Exception { @TestParameters("{checkedExpr: 'compiled_proto2_select_primitives'}") @TestParameters("{checkedExpr: 'compiled_proto3_select_primitives'}") public void eval_protoMessage_unknowns(String checkedExpr) throws Exception { - CelLiteRuntime runtime = CelLiteRuntimeFactory.newLiteRuntimeBuilder().build(); + CelLiteRuntime runtime = + CelLiteRuntimeFactory.newLiteRuntimeBuilder() + .setStandardFunctions(CelStandardFunctions.ALL_STANDARD_FUNCTIONS) + .build(); CelAbstractSyntaxTree ast = readCheckedExpr(checkedExpr); Program program = runtime.createProgram(ast); - CelUnknownSet result = (CelUnknownSet) program.eval(); + CelUnknownSet result = + (CelUnknownSet) + program.eval( + PartialVars.of( + CelAttributePattern.create("proto2"), CelAttributePattern.create("proto3"))); assertThat(result.unknownExprIds()).hasSize(15); } @@ -516,7 +530,8 @@ public void eval_protoMessage_deepTraversalReturnsRepeatedStrings(String checked .setPayload( dev.cel.expr.conformance.proto2.TestAllTypes.newBuilder() .addAllRepeatedString(data) - .build())), + .build())) + .build(), "proto3", TestAllTypes.newBuilder() .setOneofType( @@ -524,7 +539,8 @@ public void eval_protoMessage_deepTraversalReturnsRepeatedStrings(String checked .setPayload( TestAllTypes.newBuilder() .addAllRepeatedString(data) - .build())))); + .build())) + .build())); assertThat(result).isEqualTo(data); } @@ -713,7 +729,6 @@ public void eval_protoMessage_mapFields(String checkedExpr) throws Exception { } private enum CelOptionsTestCase { - CEL_VALUE_DISABLED(newBaseTestOptions().enableCelValue(false).build()), UNSIGNED_LONG_DISABLED(newBaseTestOptions().enableUnsignedLongs(false).build()), UNWRAP_WKT_DISABLED(newBaseTestOptions().unwrapWellKnownTypesOnFunctionDispatch(false).build()), ; diff --git a/runtime/src/test/java/dev/cel/runtime/CelLiteRuntimeTest.java b/runtime/src/test/java/dev/cel/runtime/CelLiteRuntimeTest.java index 0ce7bd184..56a944d8b 100644 --- a/runtime/src/test/java/dev/cel/runtime/CelLiteRuntimeTest.java +++ b/runtime/src/test/java/dev/cel/runtime/CelLiteRuntimeTest.java @@ -20,6 +20,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; import com.google.common.primitives.UnsignedLong; import com.google.protobuf.BoolValue; import com.google.protobuf.ByteString; @@ -42,6 +43,7 @@ import dev.cel.common.CelFunctionDecl; import dev.cel.common.CelOverloadDecl; import dev.cel.common.internal.ProtoTimeUtils; +import dev.cel.common.types.ProtoMessageTypeProvider; import dev.cel.common.types.SimpleType; import dev.cel.common.types.StructTypeReference; import dev.cel.common.values.CelByteString; @@ -74,22 +76,33 @@ /** Exercises tests for CelLiteRuntime using full version of protobuf messages. */ @RunWith(TestParameterInjector.class) public class CelLiteRuntimeTest { + private static final CelContainer CEL_CONTAINER = + CelContainer.ofName("cel.expr.conformance.proto3"); + private static final CelCompiler CEL_COMPILER = CelCompilerFactory.standardCelCompilerBuilder() .setStandardMacros(CelStandardMacro.STANDARD_MACROS) .addVar("msg", StructTypeReference.create(TestAllTypes.getDescriptor().getFullName())) .addVar("content", SimpleType.DYN) .addMessageTypes(TestAllTypes.getDescriptor()) - .setContainer(CelContainer.ofName("cel.expr.conformance.proto3")) + .setContainer(CEL_CONTAINER) .build(); private static final CelLiteRuntime CEL_RUNTIME = CelLiteRuntimeFactory.newLiteRuntimeBuilder() .setStandardFunctions(CelStandardFunctions.ALL_STANDARD_FUNCTIONS) + .setTypeProvider( + ProtoMessageTypeProvider.newBuilder() + .addDescriptors( + ImmutableSet.of( + dev.cel.expr.conformance.proto2.TestAllTypes.getDescriptor(), + TestAllTypes.getDescriptor())) + .build()) .setValueProvider( ProtoMessageLiteValueProvider.newInstance( dev.cel.expr.conformance.proto2.TestAllTypesCelDescriptor.getDescriptor(), TestAllTypesCelDescriptor.getDescriptor())) + .setContainer(CEL_CONTAINER) .build(); @Test @@ -596,6 +609,11 @@ public void nestedMessage_fromImportedProto() throws Exception { ProtoMessageLiteValueProvider.newInstance( SingleFileCelDescriptor.getDescriptor(), MultiFileCelDescriptor.getDescriptor())) + .setTypeProvider( + ProtoMessageTypeProvider.newBuilder() + .addDescriptors( + ImmutableList.of(SingleFile.getDescriptor(), MultiFile.getDescriptor())) + .build()) .build(); CelAbstractSyntaxTree ast = celCompiler.compile("multiFile.nested_single_file.name").getAst(); @@ -608,7 +626,8 @@ public void nestedMessage_fromImportedProto() throws Exception { ImmutableMap.of( "multiFile", MultiFile.newBuilder() - .setNestedSingleFile(SingleFile.newBuilder().setName("foo").build()))); + .setNestedSingleFile(SingleFile.newBuilder().setName("foo").build()) + .build())); assertThat(result).isEqualTo("foo"); } @@ -623,7 +642,10 @@ public void eval_withLateBoundFunction() throws Exception { CelOverloadDecl.newGlobalOverload( "lateBoundFunc_string", SimpleType.STRING, SimpleType.STRING))) .build(); - CelLiteRuntime celRuntime = CelLiteRuntimeFactory.newLiteRuntimeBuilder().build(); + CelLiteRuntime celRuntime = + CelLiteRuntimeFactory.newLiteRuntimeBuilder() + .addLateBoundFunctions("lateBoundFunc") + .build(); CelAbstractSyntaxTree ast = celCompiler.compile("lateBoundFunc('hello')").getAst(); String result = @@ -680,6 +702,10 @@ public void eval_withEnumField() throws Exception { .setValueProvider( ProtoMessageLiteValueProvider.newInstance( MessageWithEnumCelDescriptor.getDescriptor())) + .setTypeProvider( + ProtoMessageTypeProvider.newBuilder() + .addFileDescriptors(ImmutableList.of(MessageWithEnum.getDescriptor().getFile())) + .build()) .build(); CelAbstractSyntaxTree ast = celCompiler.compile("msg.simple_enum").getAst(); @@ -689,7 +715,7 @@ public void eval_withEnumField() throws Exception { .createProgram(ast) .eval( ImmutableMap.of( - "msg", MessageWithEnum.newBuilder().setSimpleEnum(SimpleEnum.BAR))); + "msg", MessageWithEnum.newBuilder().setSimpleEnum(SimpleEnum.BAR).build())); assertThat(result).isEqualTo(SimpleEnum.BAR.getNumber()); } diff --git a/runtime/src/test/java/dev/cel/runtime/CelRuntimeLegacyImplTest.java b/runtime/src/test/java/dev/cel/runtime/CelRuntimeLegacyImplTest.java index fa3b5f4ae..fec5fab41 100644 --- a/runtime/src/test/java/dev/cel/runtime/CelRuntimeLegacyImplTest.java +++ b/runtime/src/test/java/dev/cel/runtime/CelRuntimeLegacyImplTest.java @@ -19,12 +19,10 @@ 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; import dev.cel.expr.conformance.proto3.TestAllTypes; import dev.cel.runtime.CelStandardFunctions.StandardFunction; -import java.util.Optional; import java.util.function.Function; import org.junit.Assert; import org.junit.Test; @@ -108,13 +106,11 @@ public void toRuntimeBuilder_optionalProperties() { Function customTypeFactory = (typeName) -> TestAllTypes.newBuilder(); CelStandardFunctions overriddenStandardFunctions = CelStandardFunctions.newBuilder().includeFunctions(StandardFunction.ADD).build(); - CelValueProvider noOpValueProvider = (structType, fields) -> Optional.empty(); CelRuntimeBuilder celRuntimeBuilder = CelRuntimeFactory.standardCelRuntimeBuilder() .setStandardEnvironmentEnabled(false) .setTypeFactory(customTypeFactory) - .setStandardFunctions(overriddenStandardFunctions) - .setValueProvider(noOpValueProvider); + .setStandardFunctions(overriddenStandardFunctions); CelRuntime celRuntime = celRuntimeBuilder.build(); CelRuntimeLegacyImpl.Builder newRuntimeBuilder = @@ -123,6 +119,5 @@ public void toRuntimeBuilder_optionalProperties() { assertThat(newRuntimeBuilder.customTypeFactory).isEqualTo(customTypeFactory); assertThat(newRuntimeBuilder.overriddenStandardFunctions) .isEqualTo(overriddenStandardFunctions); - assertThat(newRuntimeBuilder.celValueProvider).isEqualTo(noOpValueProvider); } } diff --git a/runtime/src/test/java/dev/cel/runtime/PlannerInterpreterTest.java b/runtime/src/test/java/dev/cel/runtime/PlannerInterpreterTest.java index 9ae8590d5..4d93c6e07 100644 --- a/runtime/src/test/java/dev/cel/runtime/PlannerInterpreterTest.java +++ b/runtime/src/test/java/dev/cel/runtime/PlannerInterpreterTest.java @@ -14,8 +14,6 @@ package dev.cel.runtime; -import com.google.common.collect.ImmutableMap; -import com.google.protobuf.Timestamp; import com.google.testing.junit.testparameterinjector.TestParameter; import com.google.testing.junit.testparameterinjector.TestParameterInjector; import dev.cel.common.CelAbstractSyntaxTree; @@ -23,20 +21,13 @@ import dev.cel.common.CelOptions; import dev.cel.common.CelValidationException; import dev.cel.common.types.CelTypeProvider; -import dev.cel.common.types.ListType; -import dev.cel.common.types.SimpleType; -import dev.cel.common.types.StructTypeReference; import dev.cel.expr.conformance.proto3.TestAllTypes; import dev.cel.extensions.CelExtensions; -import dev.cel.testing.BaseInterpreterTest; -import java.util.Arrays; -import java.util.Objects; -import org.junit.Test; import org.junit.runner.RunWith; /** Interpreter tests using ProgramPlanner */ @RunWith(TestParameterInjector.class) -public class PlannerInterpreterTest extends BaseInterpreterTest { +public class PlannerInterpreterTest extends AbstractPlannerInterpreterTest { @TestParameter boolean isParseOnly; @@ -79,253 +70,4 @@ protected CelAbstractSyntaxTree prepareTest(CelTypeProvider typeProvider) { return null; } } - - @Override - public void optional_errors() { - // Exercised in planner_optional_errors instead - skipBaselineVerification(); - } - - @Test - public void planner_optional_errors() { - source = "optional.unwrap([dyn(1)])"; - runTest(ImmutableMap.of()); - } - - @Override - public void unknownField() { - // Exercised in planner_unknownFieldAccess instead - skipBaselineVerification(); - } - - @Override - public void unknownResultSet() { - // Exercised in planner_unknownResultSet_success instead - skipBaselineVerification(); - } - - @Test - public void planner_unknownFieldSelection() { - setContainer(CelContainer.ofName(TestAllTypes.getDescriptor().getFile().getPackage())); - declareVariable("x", StructTypeReference.create(TestAllTypes.getDescriptor().getFullName())); - - CelAttributePattern patternX = CelAttributePattern.fromQualifiedIdentifier("x"); - - source = "x"; - // We have the full message, but we're claiming that the attribute is unknown. - runTest(ImmutableMap.of("x", TestAllTypes.getDefaultInstance()), patternX); - // A "partially known message". The result is still an unknown. - runTest( - ImmutableMap.of("x", TestAllTypes.getDefaultInstance()), - CelAttributePattern.fromQualifiedIdentifier("x.single_int32")); - - source = "x.single_int32"; - runTest(ImmutableMap.of(), patternX); - runTest(ImmutableMap.of(), CelAttributePattern.fromQualifiedIdentifier("x.single_int32")); - - source = "x.map_int32_int64[22]"; - runTest(ImmutableMap.of(), patternX); - runTest(ImmutableMap.of(), CelAttributePattern.fromQualifiedIdentifier("x.map_int32_int64")); - - source = "x.repeated_nested_message[1]"; - runTest(ImmutableMap.of(), patternX); - runTest( - ImmutableMap.of(), - CelAttributePattern.fromQualifiedIdentifier("x.repeated_nested_message")); - - source = "x.single_nested_message.bb"; - runTest(ImmutableMap.of(), patternX); - runTest( - ImmutableMap.of(), - CelAttributePattern.fromQualifiedIdentifier("x.single_nested_message.bb")); - - source = "{1: x.single_int32}"; - runTest(ImmutableMap.of(), patternX); - runTest(ImmutableMap.of(), CelAttributePattern.fromQualifiedIdentifier("x.single_int32")); - - source = "[1, x.single_int32]"; - runTest(ImmutableMap.of(), patternX); - runTest(ImmutableMap.of(), CelAttributePattern.fromQualifiedIdentifier("x.single_int32")); - } - - @Test - public void planner_unknownResultSet_success() { - setContainer(CelContainer.ofName(TestAllTypes.getDescriptor().getFile().getPackage())); - declareVariable("x", StructTypeReference.create(TestAllTypes.getDescriptor().getFullName())); - TestAllTypes message = - TestAllTypes.newBuilder() - .setSingleString("test") - .setSingleTimestamp(Timestamp.newBuilder().setSeconds(15)) - .build(); - ImmutableMap variables = ImmutableMap.of("x", message); - CelAttributePattern unknownInt32 = - CelAttributePattern.fromQualifiedIdentifier("x.single_int32"); - CelAttributePattern unknownInt64 = - CelAttributePattern.fromQualifiedIdentifier("x.single_int64"); - - source = "x.single_int32 == 1 && true"; - runTest(variables, unknownInt32); - - source = "x.single_int32 == 1 && false"; - runTest(variables, unknownInt32); - - source = "x.single_int32 == 1 && x.single_int64 == 1"; - runTest(variables, unknownInt32, unknownInt64); - - source = "true && x.single_int32 == 1"; - runTest(variables, unknownInt32); - - source = "false && x.single_int32 == 1"; - runTest(variables, unknownInt32); - - source = "x.single_int32 == 1 || x.single_string == \"test\""; - runTest(variables, unknownInt32); - - source = "x.single_int32 == 1 || x.single_string != \"test\""; - runTest(variables, unknownInt32); - - source = "x.single_int32 == 1 || x.single_int64 == 1"; - runTest(variables, unknownInt32, unknownInt64); - - source = "true || x.single_int32 == 1"; - runTest(variables, unknownInt32); - - source = "false || x.single_int32 == 1"; - runTest(variables, unknownInt32); - - // dispatch test - declareFunction( - "f", memberOverload("f", Arrays.asList(SimpleType.INT, SimpleType.INT), SimpleType.BOOL)); - celRuntime = - newBaseRuntimeBuilder( - CelOptions.current() - .enableHeterogeneousNumericComparisons(true) - .enableOptionalSyntax(true) - .comprehensionMaxIterations(1_000) - .build()) - .addFunctionBindings( - CelFunctionBinding.from("f", Integer.class, Integer.class, Objects::equals)) - .setContainer(CelContainer.ofName(TestAllTypes.getDescriptor().getFile().getPackage())) - .build(); - - source = "x.single_int32.f(1)"; - runTest(variables, unknownInt32); - - source = "1.f(x.single_int32)"; - runTest(variables, unknownInt32); - - source = "x.single_int64.f(x.single_int32)"; - runTest(variables, unknownInt32, unknownInt64); - - source = "[0, 2, 4].exists(z, z == 2 || z == x.single_int32)"; - runTest(variables, unknownInt32); - - source = "[0, 2, 4].exists(z, z == x.single_int32)"; - runTest(variables, unknownInt32); - - source = - "[0, 2, 4].exists_one(z, z == 0 || (z == 2 && z == x.single_int32) " - + "|| (z == 4 && z == x.single_int64))"; - runTest(variables, unknownInt32, unknownInt64); - - source = "[0, 2].all(z, z == 2 || z == x.single_int32)"; - runTest(variables, unknownInt32); - - source = - "[0, 2, 4].filter(z, z == 0 || (z == 2 && z == x.single_int32) " - + "|| (z == 4 && z == x.single_int64))"; - runTest(variables, unknownInt32, unknownInt64); - - source = - "[0, 2, 4].map(z, z == 0 || (z == 2 && z == x.single_int32) " - + "|| (z == 4 && z == x.single_int64))"; - runTest(variables, unknownInt32, unknownInt64); - - source = "x.single_int32 == 1 ? 1 : 2"; - runTest(variables, unknownInt32); - - source = "true ? x.single_int32 : 2"; - runTest(variables, unknownInt32); - - source = "true ? 1 : x.single_int32"; - runTest(variables, unknownInt32); - - source = "false ? x.single_int32 : 2"; - runTest(variables, unknownInt32); - - source = "false ? 1 : x.single_int32"; - runTest(variables, unknownInt32); - - source = "x.single_int64 == 1 ? x.single_int32 : x.single_int32"; - runTest(variables, unknownInt32, unknownInt64); - - source = "{x.single_int32: 2, 3: 4}"; - runTest(variables, unknownInt32); - - source = "{1: x.single_int32, 3: 4}"; - runTest(variables, unknownInt32); - - source = "{1: x.single_int32, x.single_int64: 4}"; - runTest(variables, unknownInt32, unknownInt64); - - source = "[1, x.single_int32, 3, 4]"; - runTest(variables, unknownInt32); - - source = "[1, x.single_int32, x.single_int64, 4]"; - runTest(variables, unknownInt32, unknownInt64); - - source = "TestAllTypes{single_int32: x.single_int32}.single_int32 == 2"; - runTest(variables, unknownInt32); - - source = "TestAllTypes{single_int32: x.single_int32, single_int64: x.single_int64}"; - runTest(variables, unknownInt32, unknownInt64); - - clearAllDeclarations(); - declareVariable("unknown_list", ListType.create(SimpleType.INT)); - source = "unknown_list.map(x, x)"; - runTest(variables, CelAttributePattern.fromQualifiedIdentifier("unknown_list")); - - clearAllDeclarations(); - declareVariable("x", StructTypeReference.create(TestAllTypes.getDescriptor().getFullName())); - source = "cel.bind(x, [1, 2, 3], 1 in x)"; - runTest(variables, CelAttributePattern.fromQualifiedIdentifier("x")); - } - - @Test - public void planner_unknownResultSet_errors() { - declareVariable("x", StructTypeReference.create(TestAllTypes.getDescriptor().getFullName())); - TestAllTypes message = - TestAllTypes.newBuilder() - .setSingleString("test") - .setSingleTimestamp(Timestamp.newBuilder().setSeconds(15)) - .build(); - ImmutableMap variables = ImmutableMap.of("x", message); - CelAttributePattern unknownInt32 = - CelAttributePattern.fromQualifiedIdentifier("x.single_int32"); - - source = "x.single_int32 == 1 && x.single_timestamp <= timestamp(\"bad timestamp string\")"; - runTest(variables, unknownInt32); - - source = "x.single_timestamp <= timestamp(\"bad timestamp string\") && x.single_int32 == 1"; - runTest(variables, unknownInt32); - - source = - "x.single_timestamp <= timestamp(\"bad timestamp string\") " - + "&& x.single_timestamp > timestamp(\"another bad timestamp string\")"; - runTest(variables, unknownInt32); - - source = "x.single_int32 == 1 || x.single_timestamp <= timestamp(\"bad timestamp string\")"; - runTest(variables, unknownInt32); - - source = "x.single_timestamp <= timestamp(\"bad timestamp string\") || x.single_int32 == 1"; - runTest(variables, unknownInt32); - - source = - "x.single_timestamp <= timestamp(\"bad timestamp string\") " - + "|| x.single_timestamp > timestamp(\"another bad timestamp string\")"; - runTest(variables, unknownInt32); - - source = "x"; - runTest(ImmutableMap.of(), CelAttributePattern.fromQualifiedIdentifier("x")); - } } diff --git a/testing.bzl b/testing.bzl index 5425f7719..636ea83c5 100644 --- a/testing.bzl +++ b/testing.bzl @@ -75,7 +75,10 @@ def junit4_test_suites( test_files = srcs or native.glob( ["**/*Test.java"], # TODO: Inspect built JAR and derive the included test files from classpath instead (provided from java_library deps). - exclude = ["**/*AndroidTest.java"], + exclude = [ + "**/*AndroidTest.java", + "**/AbstractPlannerInterpreterTest.java", + ], ) test_classes = [] for src in test_files: