Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,13 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.primitives.UnsignedLong;
import com.google.protobuf.Any;
import com.google.protobuf.Descriptors.Descriptor;
import com.google.protobuf.Descriptors.FileDescriptor;
import com.google.protobuf.Int64Value;
import com.google.protobuf.Struct;
import com.google.protobuf.TextFormat;
import com.google.protobuf.Value;
import com.google.testing.junit.testparameterinjector.TestParameter;
import com.google.testing.junit.testparameterinjector.TestParameterInjector;
import dev.cel.bundle.Cel;
Expand Down Expand Up @@ -592,6 +596,38 @@ private enum NativeSelectEvaluationTestCase {
"msg.single_timestamp",
ImmutableMap.of("msg", TestAllTypes.getDefaultInstance()),
Instant.EPOCH),
PROTO3_MAP_OF_ANY_UNPACKS_VALUE(
"msg.map_string_any['k']",
ImmutableMap.of(
"msg",
TestAllTypes.newBuilder().putMapStringAny("k", Any.pack(Int64Value.of(5))).build()),
5L),
PROTO3_MAP_OF_WRAPPER_UNWRAPS_MAP_VALUES(
"msg.map_string_int64_wrapper",
ImmutableMap.of(
"msg",
TestAllTypes.newBuilder().putMapStringInt64Wrapper("k", Int64Value.of(5)).build()),
ImmutableMap.of("k", 5L)),
PROTO3_MAP_OF_VALUE_CONVERTS_TO_JSON(
"msg.map_string_value['k']",
ImmutableMap.of(
"msg",
TestAllTypes.newBuilder()
.putMapStringValue("k", Value.newBuilder().setNumberValue(1.5).build())
.build()),
1.5),
PROTO3_MAP_OF_STRUCT_CONVERTS_TO_MAP(
"msg.map_string_struct['k'].a",
ImmutableMap.of(
"msg",
TestAllTypes.newBuilder()
.putMapStringStruct(
"k",
Struct.newBuilder()
.putFields("a", Value.newBuilder().setNumberValue(1.5).build())
.build())
.build()),
1.5),
DEEPLY_NESTED_PROTO2_MESSAGE_POPULATED(
"nested_msg.child.payload.single_int64",
ImmutableMap.of("nested_msg", newNestedTestAllTypes(999L)),
Expand Down
2 changes: 2 additions & 0 deletions runtime/src/main/java/dev/cel/runtime/planner/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,7 @@ java_library(
":planner_helpers",
"//common/ast",
"//common/types",
"//common/types:cel_types",
"//common/types:type_providers",
"//common/values",
"//common/values:cel_byte_string",
Expand Down Expand Up @@ -1178,6 +1179,7 @@ cel_android_library(
":planned_interpretable_android",
":planner_helpers_android",
"//common/ast:ast_android",
"//common/types:cel_types_android",
"//common/types:type_providers_android",
"//common/types:types_android",
"//common/values:cel_byte_string",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@

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.errorprone.annotations.Immutable;
import dev.cel.common.ast.CelConstant;
import dev.cel.common.ast.CelExpr;
import dev.cel.common.ast.CelExpr.CelCall;
import dev.cel.common.ast.CelExpr.ExprKind.Kind;
import dev.cel.common.types.CelType;
import dev.cel.common.types.CelTypes;
import dev.cel.common.types.SimpleType;
import dev.cel.common.values.CelByteString;
import dev.cel.common.values.CelValueConverter;
Expand Down Expand Up @@ -56,6 +58,18 @@ final class OptimizedSelectPlanner {
private static final String DURATION_TYPE_IDENT = SimpleType.DURATION.name();
private static final String TIMESTAMP_TYPE_IDENT = SimpleType.TIMESTAMP.name();

/**
* Well-known message types whose CEL semantics (Any unpacking, JSON value conversion) are not
* implemented by the optimized traversal. Wrapper types are rejected via {@link
* CelTypes#isWrapperType}.
*/
private static final ImmutableSet<String> UNSUPPORTED_WELL_KNOWN_TYPE_IDENTS =
ImmutableSet.of(
CelTypes.ANY_MESSAGE,
CelTypes.STRUCT_MESSAGE,
CelTypes.VALUE_MESSAGE,
CelTypes.LIST_VALUE_MESSAGE);

private final AttributeFactory attributeFactory;
private final CelValueConverter celValueConverter;

Expand Down Expand Up @@ -228,6 +242,11 @@ private static void validateLeafTypeIdent(
!ScalarType.isScalarTypeIdent(typeIdent),
"Leaf MESSAGE type code (11) is incompatible with scalar typeIdent '%s'",
typeIdent);
checkArgument(
!CelTypes.isWrapperType(typeIdent)
&& !UNSUPPORTED_WELL_KNOWN_TYPE_IDENTS.contains(typeIdent),
"Leaf well-known type '%s' is not supported by the select-optimized runtime",
typeIdent);
if (typeIdent.equals(DURATION_TYPE_IDENT)) {
checkArgument(
Objects.equals(defaultValue, Duration.ZERO),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,38 @@ public void plan_invalidAst_messageTypeCodeWithScalarTypeIdent_throwsEvaluationE
.contains("Leaf MESSAGE type code (11) is incompatible with scalar typeIdent 'int'");
}

@Test
public void plan_invalidAst_unsupportedWellKnownType_throwsEvaluationException() {
CelAbstractSyntaxTree ast =
CelAbstractSyntaxTree.newParsedAst(
CelExpr.ofCall(
1L,
OptimizedSelectPlanner.CEL_ATTRIBUTE_FUNCTION_NAME,
ImmutableList.of(
CelExpr.ofIdent(2L, "msg"),
CelExpr.ofList(
3L,
ImmutableList.of(
CelExpr.ofList(
4L,
ImmutableList.of(
CelExpr.ofConstant(5L, CelConstant.ofValue(105L)),
CelExpr.ofConstant(
6L, CelConstant.ofValue("single_int64_wrapper")),
CelExpr.ofConstant(7L, CelConstant.ofValue(11L))),
ImmutableList.of())),
ImmutableList.of()),
CelExpr.ofIdent(8L, "google.protobuf.Int64Value"))),
CelSource.newBuilder().build());

CelEvaluationException e = assertThrows(CelEvaluationException.class, () -> PLANNER.plan(ast));

assertThat(e).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
assertThat(e)
.hasMessageThat()
.contains("Leaf well-known type 'google.protobuf.Int64Value' is not supported");
}

private static CelAbstractSyntaxTree optimizeSelectAst(String expression) throws Exception {
CelAbstractSyntaxTree ast = CEL.compile(expression).getAst();
CelAbstractSyntaxTree optimizedAst = SELECT_OPTIMIZER.optimize(ast);
Expand Down
Loading