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
1 change: 1 addition & 0 deletions common/src/main/java/dev/cel/common/values/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ java_library(
":base_proto_cel_value_converter",
":values",
"//:auto_value",
"//common:options",
"//common/annotations",
"//common/internal:cel_descriptor_pools",
"//common/internal:dynamic_proto",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import com.google.protobuf.Message;
import com.google.protobuf.MessageLiteOrBuilder;
import com.google.protobuf.MessageOrBuilder;
import dev.cel.common.CelOptions;
import dev.cel.common.annotations.Internal;
import dev.cel.common.internal.CelDescriptorPool;
import dev.cel.common.internal.DynamicProto;
Expand All @@ -49,11 +50,12 @@
public final class ProtoCelValueConverter extends BaseProtoCelValueConverter {
private final CelDescriptorPool celDescriptorPool;
private final DynamicProto dynamicProto;
private final CelOptions celOptions;

/** Constructs a new instance of ProtoCelValueConverter. */
public static ProtoCelValueConverter newInstance(
CelDescriptorPool celDescriptorPool, DynamicProto dynamicProto) {
return new ProtoCelValueConverter(celDescriptorPool, dynamicProto);
CelDescriptorPool celDescriptorPool, DynamicProto dynamicProto, CelOptions celOptions) {
return new ProtoCelValueConverter(celDescriptorPool, dynamicProto, celOptions);
}

@Override
Expand Down Expand Up @@ -97,7 +99,8 @@ public Object toRuntimeValue(Object value) {
WellKnownProto wellKnownProto =
WellKnownProto.getByTypeName(message.getDescriptorForType().getFullName()).orElse(null);
if (wellKnownProto == null) {
return ProtoMessageValue.create((Message) message, celDescriptorPool, this);
return ProtoMessageValue.create(
message, celDescriptorPool, this, celOptions.enableJsonFieldNames());
}

return fromWellKnownProto(message, wellKnownProto);
Expand Down Expand Up @@ -167,10 +170,13 @@ public Object fromProtoMessageFieldToCelValue(Message message, FieldDescriptor f
return toRuntimeValue(result);
}

private ProtoCelValueConverter(CelDescriptorPool celDescriptorPool, DynamicProto dynamicProto) {
private ProtoCelValueConverter(
CelDescriptorPool celDescriptorPool, DynamicProto dynamicProto, CelOptions celOptions) {
Preconditions.checkNotNull(celDescriptorPool);
Preconditions.checkNotNull(dynamicProto);
Preconditions.checkNotNull(celOptions);
this.celDescriptorPool = celDescriptorPool;
this.dynamicProto = dynamicProto;
this.celOptions = celOptions;
}
}
16 changes: 14 additions & 2 deletions common/src/main/java/dev/cel/common/values/ProtoMessageValue.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ public abstract class ProtoMessageValue extends StructValue<String> {

abstract ProtoCelValueConverter protoCelValueConverter();

abstract boolean enableJsonFieldNames();

@Override
public boolean isZeroValue() {
return value().getDefaultInstanceForType().equals(value());
Expand Down Expand Up @@ -75,15 +77,17 @@ public Optional<Object> find(String field) {
public static ProtoMessageValue create(
Message value,
CelDescriptorPool celDescriptorPool,
ProtoCelValueConverter protoCelValueConverter) {
ProtoCelValueConverter protoCelValueConverter,
boolean enableJsonFieldNames) {
Preconditions.checkNotNull(value);
Preconditions.checkNotNull(celDescriptorPool);
Preconditions.checkNotNull(protoCelValueConverter);
return new AutoValue_ProtoMessageValue(
value,
StructTypeReference.create(value.getDescriptorForType().getFullName()),
celDescriptorPool,
protoCelValueConverter);
protoCelValueConverter,
enableJsonFieldNames);
}

private FieldDescriptor findField(
Expand All @@ -93,6 +97,14 @@ private FieldDescriptor findField(
return fieldDescriptor;
}

if (enableJsonFieldNames()) {
for (FieldDescriptor fd : descriptor.getFields()) {
if (fd.getJsonName().equals(fieldName)) {
return fd;
}
}
}

return celDescriptorPool
.findExtensionDescriptor(descriptor, fieldName)
.orElseThrow(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public class ProtoMessageValueProvider implements CelValueProvider {
private final ProtoAdapter protoAdapter;
private final ProtoMessageFactory protoMessageFactory;
private final ProtoCelValueConverter protoCelValueConverter;
private final CelOptions celOptions;

@Override
public CelValueConverter celValueConverter() {
Expand Down Expand Up @@ -72,6 +73,14 @@ private FieldDescriptor findField(Descriptor descriptor, String fieldName) {
return fieldDescriptor;
}

if (celOptions.enableJsonFieldNames()) {
for (FieldDescriptor fd : descriptor.getFields()) {
if (fd.getJsonName().equals(fieldName)) {
return fd;
}
}
}

return protoMessageFactory
.getDescriptorPool()
.findExtensionDescriptor(descriptor, fieldName)
Expand All @@ -91,7 +100,9 @@ public static ProtoMessageValueProvider newInstance(
private ProtoMessageValueProvider(CelOptions celOptions, DynamicProto dynamicProto) {
this.protoMessageFactory = dynamicProto.getProtoMessageFactory();
this.protoCelValueConverter =
ProtoCelValueConverter.newInstance(protoMessageFactory.getDescriptorPool(), dynamicProto);
ProtoCelValueConverter.newInstance(
protoMessageFactory.getDescriptorPool(), dynamicProto, celOptions);
this.protoAdapter = new ProtoAdapter(dynamicProto, celOptions);
this.celOptions = celOptions;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import static com.google.common.truth.Truth.assertThat;

import dev.cel.common.CelOptions;
import dev.cel.common.internal.DefaultDescriptorPool;
import dev.cel.common.internal.DefaultMessageFactory;
import dev.cel.common.internal.DynamicProto;
Expand All @@ -28,7 +29,9 @@ public class ProtoCelValueConverterTest {

private static final ProtoCelValueConverter PROTO_CEL_VALUE_CONVERTER =
ProtoCelValueConverter.newInstance(
DefaultDescriptorPool.INSTANCE, DynamicProto.create(DefaultMessageFactory.INSTANCE));
DefaultDescriptorPool.INSTANCE,
DynamicProto.create(DefaultMessageFactory.INSTANCE),
CelOptions.DEFAULT);

@Test
public void unwrap_nullValue() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import com.google.testing.junit.testparameterinjector.TestParameterInjector;
import com.google.testing.junit.testparameterinjector.TestParameters;
import dev.cel.common.CelDescriptorUtil;
import dev.cel.common.CelOptions;
import dev.cel.common.internal.CelDescriptorPool;
import dev.cel.common.internal.DefaultDescriptorPool;
import dev.cel.common.internal.DefaultMessageFactory;
Expand All @@ -54,15 +55,18 @@ public final class ProtoMessageValueTest {

private static final ProtoCelValueConverter PROTO_CEL_VALUE_CONVERTER =
ProtoCelValueConverter.newInstance(
DefaultDescriptorPool.INSTANCE, DynamicProto.create(DefaultMessageFactory.INSTANCE));
DefaultDescriptorPool.INSTANCE,
DynamicProto.create(DefaultMessageFactory.INSTANCE),
CelOptions.DEFAULT);

@Test
public void emptyProtoMessage() {
ProtoMessageValue protoMessageValue =
ProtoMessageValue.create(
TestAllTypes.getDefaultInstance(),
DefaultDescriptorPool.INSTANCE,
PROTO_CEL_VALUE_CONVERTER);
PROTO_CEL_VALUE_CONVERTER,
/* enableJsonFieldNames= */ false);

assertThat(protoMessageValue.value()).isEqualTo(TestAllTypes.getDefaultInstance());
assertThat(protoMessageValue.isZeroValue()).isTrue();
Expand All @@ -74,7 +78,7 @@ public void constructProtoMessage() {
TestAllTypes.newBuilder().setSingleBool(true).setSingleInt64(5L).build();
ProtoMessageValue protoMessageValue =
ProtoMessageValue.create(
testAllTypes, DefaultDescriptorPool.INSTANCE, PROTO_CEL_VALUE_CONVERTER);
testAllTypes, DefaultDescriptorPool.INSTANCE, PROTO_CEL_VALUE_CONVERTER, false);

assertThat(protoMessageValue.value()).isEqualTo(testAllTypes);
assertThat(protoMessageValue.isZeroValue()).isFalse();
Expand All @@ -90,7 +94,7 @@ public void findField_fieldIsSet_fieldExists() {
.build();
ProtoMessageValue protoMessageValue =
ProtoMessageValue.create(
testAllTypes, DefaultDescriptorPool.INSTANCE, PROTO_CEL_VALUE_CONVERTER);
testAllTypes, DefaultDescriptorPool.INSTANCE, PROTO_CEL_VALUE_CONVERTER, false);

assertThat(protoMessageValue.find("single_bool")).isPresent();
assertThat(protoMessageValue.find("single_int64")).isPresent();
Expand All @@ -103,7 +107,8 @@ public void findField_fieldIsUnset_fieldDoesNotExist() {
ProtoMessageValue.create(
TestAllTypes.getDefaultInstance(),
DefaultDescriptorPool.INSTANCE,
PROTO_CEL_VALUE_CONVERTER);
PROTO_CEL_VALUE_CONVERTER,
/* enableJsonFieldNames= */ false);

assertThat(protoMessageValue.find("single_int32")).isEmpty();
assertThat(protoMessageValue.find("single_uint64")).isEmpty();
Expand All @@ -116,7 +121,8 @@ public void findField_fieldIsUndeclared_throwsException() {
ProtoMessageValue.create(
TestAllTypes.getDefaultInstance(),
DefaultDescriptorPool.INSTANCE,
PROTO_CEL_VALUE_CONVERTER);
PROTO_CEL_VALUE_CONVERTER,
/* enableJsonFieldNames= */ false);

IllegalArgumentException exception =
assertThrows(IllegalArgumentException.class, () -> protoMessageValue.select("bogus"));
Expand All @@ -137,7 +143,7 @@ public void findField_extensionField_success() {
TestAllTypes.newBuilder().setExtension(TestAllTypesExtensions.int32Ext, 1).build();

ProtoMessageValue protoMessageValue =
ProtoMessageValue.create(proto2Message, descriptorPool, PROTO_CEL_VALUE_CONVERTER);
ProtoMessageValue.create(proto2Message, descriptorPool, PROTO_CEL_VALUE_CONVERTER, false);

assertThat(protoMessageValue.find("cel.expr.conformance.proto2.int32_ext")).isPresent();
}
Expand All @@ -149,7 +155,7 @@ public void findField_extensionField_throwsWhenDescriptorMissing() {

ProtoMessageValue protoMessageValue =
ProtoMessageValue.create(
proto2Message, DefaultDescriptorPool.INSTANCE, PROTO_CEL_VALUE_CONVERTER);
proto2Message, DefaultDescriptorPool.INSTANCE, PROTO_CEL_VALUE_CONVERTER, false);

IllegalArgumentException exception =
assertThrows(
Expand Down Expand Up @@ -193,7 +199,8 @@ private enum SelectFieldTestCase {
ProtoMessageValue.create(
NestedMessage.getDefaultInstance(),
DefaultDescriptorPool.INSTANCE,
PROTO_CEL_VALUE_CONVERTER)),
PROTO_CEL_VALUE_CONVERTER,
/* enableJsonFieldNames= */ false)),
NESTED_ENUM("standalone_enum", 1L);

private final String fieldName;
Expand Down Expand Up @@ -239,7 +246,7 @@ public void selectField_success(@TestParameter SelectFieldTestCase testCase) {

ProtoMessageValue protoMessageValue =
ProtoMessageValue.create(
testAllTypes, DefaultDescriptorPool.INSTANCE, PROTO_CEL_VALUE_CONVERTER);
testAllTypes, DefaultDescriptorPool.INSTANCE, PROTO_CEL_VALUE_CONVERTER, false);

assertThat(protoMessageValue.select(testCase.fieldName)).isEqualTo(testCase.value);
}
Expand All @@ -253,7 +260,8 @@ public void selectField_dynamicMessage_success() {
ProtoMessageValue.create(
DynamicMessage.newBuilder(testAllTypes).build(),
DefaultDescriptorPool.INSTANCE,
PROTO_CEL_VALUE_CONVERTER);
PROTO_CEL_VALUE_CONVERTER,
/* enableJsonFieldNames= */ false);

assertThat(protoMessageValue.select("single_int32_wrapper")).isEqualTo(5);
}
Expand All @@ -269,7 +277,7 @@ public void selectField_timestampNanosOutOfRange_success(int nanos) {

ProtoMessageValue protoMessageValue =
ProtoMessageValue.create(
testAllTypes, DefaultDescriptorPool.INSTANCE, PROTO_CEL_VALUE_CONVERTER);
testAllTypes, DefaultDescriptorPool.INSTANCE, PROTO_CEL_VALUE_CONVERTER, false);

assertThat(protoMessageValue.select("single_timestamp"))
.isEqualTo(Instant.ofEpochSecond(0, nanos));
Expand All @@ -289,7 +297,7 @@ public void selectField_durationOutOfRange_success(int seconds, int nanos) {

ProtoMessageValue protoMessageValue =
ProtoMessageValue.create(
testAllTypes, DefaultDescriptorPool.INSTANCE, PROTO_CEL_VALUE_CONVERTER);
testAllTypes, DefaultDescriptorPool.INSTANCE, PROTO_CEL_VALUE_CONVERTER, false);

assertThat(protoMessageValue.select("single_duration"))
.isEqualTo(Duration.ofSeconds(seconds, nanos));
Expand Down Expand Up @@ -334,7 +342,7 @@ public void selectField_jsonValue(@TestParameter SelectFieldJsonValueTestCase te

ProtoMessageValue protoMessageValue =
ProtoMessageValue.create(
testAllTypes, DefaultDescriptorPool.INSTANCE, PROTO_CEL_VALUE_CONVERTER);
testAllTypes, DefaultDescriptorPool.INSTANCE, PROTO_CEL_VALUE_CONVERTER, false);

assertThat(protoMessageValue.select("single_value")).isEqualTo(testCase.value);
}
Expand All @@ -351,7 +359,7 @@ public void selectField_jsonStruct() {

ProtoMessageValue protoMessageValue =
ProtoMessageValue.create(
testAllTypes, DefaultDescriptorPool.INSTANCE, PROTO_CEL_VALUE_CONVERTER);
testAllTypes, DefaultDescriptorPool.INSTANCE, PROTO_CEL_VALUE_CONVERTER, false);

assertThat(protoMessageValue.select("single_struct")).isEqualTo(ImmutableMap.of("a", false));
}
Expand All @@ -368,7 +376,7 @@ public void selectField_jsonList() {

ProtoMessageValue protoMessageValue =
ProtoMessageValue.create(
testAllTypes, DefaultDescriptorPool.INSTANCE, PROTO_CEL_VALUE_CONVERTER);
testAllTypes, DefaultDescriptorPool.INSTANCE, PROTO_CEL_VALUE_CONVERTER, false);

assertThat(protoMessageValue.select("list_value")).isEqualTo(ImmutableList.of(false));
}
Expand All @@ -379,7 +387,8 @@ public void selectField_wrapperFieldUnset_returnsNull() {
ProtoMessageValue.create(
TestAllTypes.getDefaultInstance(),
DefaultDescriptorPool.INSTANCE,
PROTO_CEL_VALUE_CONVERTER);
PROTO_CEL_VALUE_CONVERTER,
/* enableJsonFieldNames= */ false);

assertThat(protoMessageValue.select("single_int64_wrapper")).isEqualTo(NullValue.NULL_VALUE);
}
Expand All @@ -390,9 +399,21 @@ public void celTypeTest() {
ProtoMessageValue.create(
TestAllTypes.getDefaultInstance(),
DefaultDescriptorPool.INSTANCE,
PROTO_CEL_VALUE_CONVERTER);
PROTO_CEL_VALUE_CONVERTER,
/* enableJsonFieldNames= */ false);

assertThat(protoMessageValue.celType())
.isEqualTo(StructTypeReference.create(TestAllTypes.getDescriptor().getFullName()));
}

@Test
public void findField_jsonName_success() {
TestAllTypes testAllTypes = TestAllTypes.newBuilder().setSingleInt32(42).build();

ProtoMessageValue protoMessageValue =
ProtoMessageValue.create(
testAllTypes, DefaultDescriptorPool.INSTANCE, PROTO_CEL_VALUE_CONVERTER, true);

assertThat(protoMessageValue.find("singleInt32")).isPresent();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,18 @@ private CelEvaluationException newCelEvaluationException(long exprId, Exception
// Use the localized expr ID (most specific error location)
LocalizedEvaluationException localized = (LocalizedEvaluationException) e;
exprId = localized.exprId();
builder =
CelEvaluationExceptionBuilder.newBuilder((CelRuntimeException) localized.getCause());
Throwable cause = localized.getCause();
if (cause instanceof CelRuntimeException) {
builder =
CelEvaluationExceptionBuilder.newBuilder((CelRuntimeException) localized.getCause());
} else {
builder = CelEvaluationExceptionBuilder.newBuilder(cause.getMessage()).setCause(cause);
}
} else if (e instanceof CelRuntimeException) {
builder = CelEvaluationExceptionBuilder.newBuilder((CelRuntimeException) e);
} else {
// Unhandled function dispatch failures wraps the original exception with a descriptive message
// Unhandled function dispatch failures wraps the original exception with a descriptive
// message
// (e.g: "Function foo failed with...")
// We need to unwrap the cause here to preserve the original exception message and its cause.
Throwable cause = e.getCause() != null ? e.getCause() : e;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,4 @@ public void unknownResultSet() {
// TODO: Unknown support not implemented yet
skipBaselineVerification();
}

@Override
public void jsonFieldNames() throws Exception {
// TODO: Support JSON field names for planner
skipBaselineVerification();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public final class ProgramPlannerTest {
private static final CelValueProvider VALUE_PROVIDER =
ProtoMessageValueProvider.newInstance(CEL_OPTIONS, DYNAMIC_PROTO);
private static final CelValueConverter CEL_VALUE_CONVERTER =
ProtoCelValueConverter.newInstance(DESCRIPTOR_POOL, DYNAMIC_PROTO);
ProtoCelValueConverter.newInstance(DESCRIPTOR_POOL, DYNAMIC_PROTO, CelOptions.DEFAULT);
private static final CelContainer CEL_CONTAINER =
CelContainer.newBuilder()
.setName("cel.expr.conformance.proto3")
Expand Down
Loading