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 @@ -140,9 +140,13 @@ private Object readLengthDelimitedField(
case BYTES:
return inputStream.readBytes();
case MESSAGE:
MessageLite.Builder builder =
getDefaultMessageBuilder(fieldDescriptor.getFieldProtoTypeName());

String fieldProtoTypeName = fieldDescriptor.getFieldProtoTypeName();
MessageLiteDescriptor descriptor =
descriptorPool.findDescriptor(fieldProtoTypeName).orElse(null);
if (descriptor == null) {
return RawProtoMessageLiteValue.create(inputStream.readBytes(), fieldProtoTypeName, this);
}
MessageLite.Builder builder = descriptor.newMessageBuilder();
inputStream.readMessage(builder, ExtensionRegistryLite.getEmptyRegistry());
return builder.build();
case STRING:
Expand All @@ -152,10 +156,6 @@ private Object readLengthDelimitedField(
}
}

private MessageLite.Builder getDefaultMessageBuilder(String protoTypeName) {
return descriptorPool.getDescriptorOrThrow(protoTypeName).newMessageBuilder();
}

Object getDefaultCelValue(String protoTypeName, String fieldName) {
MessageLiteDescriptor messageDescriptor = descriptorPool.getDescriptorOrThrow(protoTypeName);
return getDefaultCelValue(messageDescriptor.getByFieldNameOrThrow(fieldName));
Expand Down Expand Up @@ -200,17 +200,15 @@ private Object decodeWellKnownProto(
}

@Override
@SuppressWarnings("LiteProtoToString") // No alternative identifier to use. Debug only info is OK.
public Object toRuntimeValue(Object value) {
checkNotNull(value);
if (value instanceof MessageLite) {
MessageLite msg = (MessageLite) value;

MessageLiteDescriptor descriptor =
descriptorPool
.findDescriptor(msg)
.orElseThrow(
() -> new NoSuchElementException("Could not find a descriptor for: " + msg));
MessageLiteDescriptor descriptor = descriptorPool.findDescriptor(msg).orElse(null);
if (descriptor == null) {
return RawProtoMessageLiteValue.create(msg.toByteString(), this);
}
WellKnownProto wellKnownProto =
WellKnownProto.getByTypeName(descriptor.getProtoTypeName()).orElse(null);

Expand Down Expand Up @@ -279,11 +277,16 @@ private Object getScalarDefaultValue(FieldLiteDescriptor fieldDescriptor) {
case BYTE_STRING:
return CelByteString.EMPTY;
case MESSAGE:
if (WellKnownProto.isWrapperType(fieldDescriptor.getFieldProtoTypeName())) {
String fieldProtoTypeName = fieldDescriptor.getFieldProtoTypeName();
if (WellKnownProto.isWrapperType(fieldProtoTypeName)) {
return NullValue.NULL_VALUE;
}

return getDefaultMessageBuilder(fieldDescriptor.getFieldProtoTypeName()).build();
MessageLiteDescriptor descriptor =
descriptorPool.findDescriptor(fieldProtoTypeName).orElse(null);
if (descriptor == null) {
return RawProtoMessageLiteValue.create(ByteString.EMPTY, fieldProtoTypeName, this);
}
return descriptor.newMessageBuilder().build();
}
throw new IllegalStateException("Unexpected java type: " + type);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ public boolean isZeroValue() {
*/
@Override
public Object select(String field) {
throw CelAttributeNotFoundException.forFieldResolution(field);
throw newUnoptimizedFieldResolutionException(field);
}

/**
Expand All @@ -114,7 +114,15 @@ public Object select(String field) {
*/
@Override
public Optional<Object> find(String field) {
throw CelAttributeNotFoundException.forFieldResolution(field);
throw newUnoptimizedFieldResolutionException(field);
}

private CelAttributeNotFoundException newUnoptimizedFieldResolutionException(String field) {
return CelAttributeNotFoundException.of(
String.format(
"Error resolving field '%s' on '%s'. Field selection by name is not supported on raw"
+ " proto wire bytes; register its CelLiteDescriptor or enable SelectOptimizer.",
field, celType().name()));
}

@Override
Expand Down Expand Up @@ -514,7 +522,10 @@ public static RawProtoMessageLiteValue create(
checkNotNull(protoTypeName);
checkNotNull(protoLiteCelValueConverter);
return new AutoValue_RawProtoMessageLiteValue(
rawWireBytes, StructTypeReference.create(protoTypeName), protoLiteCelValueConverter);
rawWireBytes,
StructTypeReference.create(
protoTypeName.isEmpty() ? UNKNOWN_MESSAGE_TYPE_NAME : protoTypeName),
protoLiteCelValueConverter);
}

RawProtoMessageLiteValue() {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import dev.cel.common.internal.CelLiteDescriptorPool;
import dev.cel.common.internal.DefaultLiteDescriptorPool;
import dev.cel.common.values.ProtoLiteCelValueConverter.MessageFields;
import dev.cel.expr.conformance.proto3.NestedTestAllTypes;
import dev.cel.expr.conformance.proto3.TestAllTypes;
import dev.cel.expr.conformance.proto3.TestAllTypesCelDescriptor;
import dev.cel.protobuf.CelLiteDescriptor.FieldLiteDescriptor;
Expand Down Expand Up @@ -92,6 +93,19 @@ public MessageLiteDescriptor getDescriptorOrThrow(String protoTypeName) {
assertThat(protoMessageLiteValue.value()).isEqualTo(TestAllTypes.getDefaultInstance());
}

@Test
public void fromProtoMessageToCelValue_withoutDescriptor_returnsRawProtoMessageLiteValue() {
ProtoLiteCelValueConverter converterWithoutDescriptors =
ProtoLiteCelValueConverter.newInstance(EMPTY_DESCRIPTOR_POOL);
TestAllTypes msg = TestAllTypes.newBuilder().setSingleInt64(42L).build();

Object adaptedValue = converterWithoutDescriptors.toRuntimeValue(msg);

assertThat(adaptedValue)
.isEqualTo(
RawProtoMessageLiteValue.create(msg.toByteString(), converterWithoutDescriptors));
}

@SuppressWarnings("ImmutableEnumChecker") // Test only
private enum WellKnownProtoTestCase {
BOOL(BoolValue.of(true), true),
Expand Down Expand Up @@ -364,17 +378,46 @@ public void getDefaultCelValue_fieldDescriptor_returnsDefault() {
}

@Test
public void getDefaultCelValue_nestedMessageWithoutDescriptor_throwsNoSuchElementException() {
public void getDefaultCelValue_nestedMessageWithoutDescriptor_returnsRawProtoMessageLiteValue() {
FieldLiteDescriptor nestedMsgField =
DESCRIPTOR_POOL
.getDescriptorOrThrow("cel.expr.conformance.proto3.TestAllTypes")
.getByFieldNameOrThrow("single_nested_message");
ProtoLiteCelValueConverter converterWithoutNested =
ProtoLiteCelValueConverter.newInstance(EMPTY_DESCRIPTOR_POOL);

assertThrows(
NoSuchElementException.class,
() -> converterWithoutNested.getDefaultCelValue(nestedMsgField));
Object defaultValue = converterWithoutNested.getDefaultCelValue(nestedMsgField);

assertThat(defaultValue)
.isEqualTo(
RawProtoMessageLiteValue.create(
ByteString.EMPTY,
"cel.expr.conformance.proto3.TestAllTypes.NestedMessage",
converterWithoutNested));
}

@Test
public void readAllFields_nestedMessageWithoutDescriptor_returnsRawProtoMessageLiteValue()
throws Exception {
// DESCRIPTOR_POOL only registers TestAllTypesCelDescriptor, not NestedTestAllTypesCelDescriptor
TestAllTypes msg =
TestAllTypes.newBuilder()
.setOneofType(
NestedTestAllTypes.newBuilder()
.setPayload(TestAllTypes.newBuilder().setSingleInt64(42L)))
.build();

MessageFields fields =
PROTO_LITE_CEL_VALUE_CONVERTER.readAllFields(
msg.toByteArray(), "cel.expr.conformance.proto3.TestAllTypes");

assertThat(fields.values())
.containsExactly(
"oneof_type",
RawProtoMessageLiteValue.create(
msg.getOneofType().toByteString(),
"cel.expr.conformance.proto3.NestedTestAllTypes",
PROTO_LITE_CEL_VALUE_CONVERTER));
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,28 +71,55 @@ public void create_accessorsAndType() {
}

@Test
public void create_defaultsEmptyTypeName() {
public void create_defaultsUnknownMessageTypeName() {
ByteString bytes = ByteString.copyFromUtf8("test");

RawProtoMessageLiteValue value = RawProtoMessageLiteValue.create(bytes, EMPTY_CONVERTER);

assertThat(value.rawWireBytes()).isEqualTo(bytes);
assertThat(value.celType().name()).isEmpty();
assertThat(value.celType().name()).isEqualTo("cel.@unknownMessage");
}

@Test
public void create_emptyTypeName_normalizesToUnknownMessageTypeName() {
ByteString bytes = ByteString.copyFromUtf8("test");

RawProtoMessageLiteValue value = RawProtoMessageLiteValue.create(bytes, "", EMPTY_CONVERTER);

assertThat(value.rawWireBytes()).isEqualTo(bytes);
assertThat(value.celType().name()).isEqualTo("cel.@unknownMessage");
}

@Test
public void select_throwsCelAttributeNotFoundException() {
RawProtoMessageLiteValue value =
RawProtoMessageLiteValue.create(ByteString.EMPTY, "custom.Message", EMPTY_CONVERTER);

assertThrows(CelAttributeNotFoundException.class, () -> value.select("field"));
CelAttributeNotFoundException e =
assertThrows(CelAttributeNotFoundException.class, () -> value.select("field"));

assertThat(e)
.hasMessageThat()
.isEqualTo(
"Error resolving field 'field' on 'custom.Message'. Field selection by name is not"
+ " supported on raw proto wire bytes; register its CelLiteDescriptor or enable"
+ " SelectOptimizer.");
}

@Test
public void find_throwsCelAttributeNotFoundException() {
RawProtoMessageLiteValue value =
RawProtoMessageLiteValue.create(ByteString.EMPTY, "custom.Message", EMPTY_CONVERTER);

assertThrows(CelAttributeNotFoundException.class, () -> value.find("field"));
CelAttributeNotFoundException e =
assertThrows(CelAttributeNotFoundException.class, () -> value.find("field"));

assertThat(e)
.hasMessageThat()
.isEqualTo(
"Error resolving field 'field' on 'custom.Message'. Field selection by name is not"
+ " supported on raw proto wire bytes; register its CelLiteDescriptor or enable"
+ " SelectOptimizer.");
}

@Test
Expand Down
Loading
Loading