Skip to content
Open
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
12 changes: 8 additions & 4 deletions bundle/src/test/java/dev/cel/bundle/CelImplTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@
import dev.cel.common.CelVarDecl;
import dev.cel.common.ast.CelExpr;
import dev.cel.common.ast.CelExpr.CelList;
import dev.cel.common.internal.ProtoTimeUtils;
import dev.cel.common.testing.RepeatedTestProvider;
import dev.cel.common.types.CelKind;
import dev.cel.common.types.CelProtoMessageTypes;
Expand Down Expand Up @@ -114,6 +113,7 @@
import dev.cel.runtime.CelVariableResolver;
import dev.cel.runtime.UnknownContext;
import dev.cel.testing.testdata.proto3.StandaloneGlobalEnum;
import java.time.Instant;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
Expand Down Expand Up @@ -817,27 +817,30 @@ public void program_messageConstruction() throws Exception {
public void program_duplicateTypeDescriptor() throws Exception {
Cel cel =
standardCelBuilderWithMacros()
.setOptions(CelOptions.current().evaluateCanonicalTypesToNativeValues(true).build())
.addMessageTypes(Timestamp.getDescriptor())
.addMessageTypes(ImmutableList.of(Timestamp.getDescriptor()))
.setContainer(CelContainer.ofName("google"))
.setResultType(SimpleType.TIMESTAMP)
.build();
CelRuntime.Program program =
cel.createProgram(cel.compile("protobuf.Timestamp{seconds: 12}").getAst());
assertThat(program.eval()).isEqualTo(ProtoTimeUtils.fromSecondsToTimestamp(12));

assertThat(program.eval()).isEqualTo(Instant.ofEpochSecond(12));
}

@Test
public void program_hermeticDescriptors_wellKnownProtobuf() throws Exception {
Cel cel =
standardCelBuilderWithMacros()
.setOptions(CelOptions.current().evaluateCanonicalTypesToNativeValues(true).build())
.addMessageTypes(Timestamp.getDescriptor())
.setContainer(CelContainer.ofName("google"))
.setResultType(SimpleType.TIMESTAMP)
.build();
CelRuntime.Program program =
cel.createProgram(cel.compile("protobuf.Timestamp{seconds: 12}").getAst());
assertThat(program.eval()).isEqualTo(ProtoTimeUtils.fromSecondsToTimestamp(12));
assertThat(program.eval()).isEqualTo(Instant.ofEpochSecond(12));
}

@Test
Expand Down Expand Up @@ -959,14 +962,15 @@ public void program_deepTypeResolutionDisabledForRuntime_fails() throws Exceptio
public void program_typeProvider() throws Exception {
Cel cel =
standardCelBuilderWithMacros()
.setOptions(CelOptions.current().evaluateCanonicalTypesToNativeValues(true).build())
.setTypeProvider(
new DescriptorTypeProvider(ImmutableList.of(Timestamp.getDescriptor())))
.setContainer(CelContainer.ofName("google"))
.setResultType(SimpleType.TIMESTAMP)
.build();
CelRuntime.Program program =
cel.createProgram(cel.compile("protobuf.Timestamp{seconds: 12}").getAst());
assertThat(program.eval()).isEqualTo(ProtoTimeUtils.fromSecondsToTimestamp(12));
assertThat(program.eval()).isEqualTo(Instant.ofEpochSecond(12));
}

@Test
Expand Down
4 changes: 2 additions & 2 deletions codelab/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1065,8 +1065,8 @@ public void validate_invalidTimestampLiteral_returnsError() throws Exception {
assertThat(validationResult.hasError()).isTrue();
assertThat(validationResult.getErrorString())
.isEqualTo(
"ERROR: <input>:1:11: timestamp validation failed. Reason: evaluation error: Failed to"
+ " parse timestamp: invalid timestamp \"bad\"\n"
"ERROR: <input>:1:11: timestamp validation failed. Reason: evaluation error: Text 'bad'"
+ " could not be parsed at index 0\n"
+ " | timestamp('bad')\n"
+ " | ..........^");
}
Expand Down
4 changes: 2 additions & 2 deletions codelab/src/test/codelab/Exercise8Test.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ public void validate_invalidTimestampLiteral_returnsError() throws Exception {
assertThat(validationResult.hasError()).isTrue();
assertThat(validationResult.getErrorString())
.isEqualTo(
"ERROR: <input>:1:11: timestamp validation failed. Reason: evaluation error: Failed to"
+ " parse timestamp: invalid timestamp \"bad\"\n"
"ERROR: <input>:1:11: timestamp validation failed. Reason: evaluation error: Text 'bad'"
+ " could not be parsed at index 0\n"
+ " | timestamp('bad')\n"
+ " | ..........^");
}
Expand Down
4 changes: 2 additions & 2 deletions codelab/src/test/codelab/solutions/Exercise8Test.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ public void validate_invalidTimestampLiteral_returnsError() throws Exception {
assertThat(validationResult.hasError()).isTrue();
assertThat(validationResult.getErrorString())
.isEqualTo(
"ERROR: <input>:1:11: timestamp validation failed. Reason: evaluation error: Failed to"
+ " parse timestamp: invalid timestamp \"bad\"\n"
"ERROR: <input>:1:11: timestamp validation failed. Reason: evaluation error: Text 'bad'"
+ " could not be parsed at index 0\n"
+ " | timestamp('bad')\n"
+ " | ..........^");
}
Expand Down
3 changes: 3 additions & 0 deletions common/src/main/java/dev/cel/common/CelOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ public static Builder current() {
.enableUnsignedLongs(true)
.enableRegexPartialMatch(true)
.errorOnDuplicateMapKeys(true)
.evaluateCanonicalTypesToNativeValues(true)
.errorOnIntWrap(true)
.resolveTypeDependencies(true)
.disableCelStandardEquality(false);
Expand Down Expand Up @@ -462,6 +463,8 @@ public abstract static class Builder {
* com.google.protobuf.ByteString}.
* <li>CEL null: {@code dev.cel.common.values.NullValue} instead of {@code
* com.google.protobuf.NullValue}.
* <li>Timestamp: {@code java.time.Instant} instead of {@code com.google.protobuf.Timestamp}.
* <li>Duration: {@code java.time.Duration} instead of {@code com.google.protobuf.Duration}.
* </ul>
*/
public abstract Builder evaluateCanonicalTypesToNativeValues(boolean value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import com.google.type.Expr;
import dev.cel.common.CelOptions;
import dev.cel.common.values.CelByteString;
import java.time.Instant;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
Expand Down Expand Up @@ -88,11 +89,10 @@ public static List<Object[]> data() {
{1.5D, Any.pack(DoubleValue.of(1.5D))},
{1.5D, Value.newBuilder().setNumberValue(1.5D).build()},
{
Duration.newBuilder().setSeconds(123).build(),
Duration.newBuilder().setSeconds(123).build(),
java.time.Duration.ofSeconds(123), Duration.newBuilder().setSeconds(123).build(),
},
{
Duration.newBuilder().setSeconds(123).build(),
java.time.Duration.ofSeconds(123),
Any.pack(Duration.newBuilder().setSeconds(123).build()),
},
{1L, Int64Value.of(1L)},
Expand Down Expand Up @@ -132,12 +132,10 @@ public static List<Object[]> data() {
.build(),
},
{
Timestamp.newBuilder().setSeconds(123).build(),
Timestamp.newBuilder().setSeconds(123).build(),
Instant.ofEpochSecond(123), Timestamp.newBuilder().setSeconds(123).build(),
},
{
Timestamp.newBuilder().setSeconds(123).build(),
Any.pack(Timestamp.newBuilder().setSeconds(123).build()),
Instant.ofEpochSecond(123), Any.pack(Timestamp.newBuilder().setSeconds(123).build()),
},
{UnsignedLong.valueOf(1L), UInt64Value.of(1L)},
{UnsignedLong.valueOf(1L), Any.pack(UInt64Value.of(1L))},
Expand All @@ -152,7 +150,10 @@ public static List<Object[]> data() {
@Test
public void adaptValueToProto_bidirectionalConversion() {
DynamicProto dynamicProto = DynamicProto.create(DefaultMessageFactory.INSTANCE);
ProtoAdapter protoAdapter = new ProtoAdapter(dynamicProto, CelOptions.DEFAULT);
ProtoAdapter protoAdapter =
new ProtoAdapter(
dynamicProto,
CelOptions.current().evaluateCanonicalTypesToNativeValues(true).build());
assertThat(protoAdapter.adaptValueToProto(value, proto.getDescriptorForType().getFullName()))
.isEqualTo(proto);
assertThat(protoAdapter.adaptProtoToValue(proto)).isEqualTo(value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import dev.cel.common.internal.DefaultMessageFactory;
import dev.cel.common.internal.DynamicProto;
import dev.cel.common.internal.ProtoMessageFactory;
import dev.cel.common.internal.ProtoTimeUtils;
import dev.cel.expr.conformance.proto2.TestAllTypes;
import dev.cel.expr.conformance.proto2.TestAllTypesExtensions;
import java.time.Duration;
Expand Down Expand Up @@ -66,7 +65,8 @@ public void newValue_createEmptyProtoMessage() {
@Test
public void newValue_createProtoMessage_fieldsPopulated() {
ProtoMessageValueProvider protoMessageValueProvider =
ProtoMessageValueProvider.newInstance(CelOptions.DEFAULT, DYNAMIC_PROTO);
ProtoMessageValueProvider.newInstance(
CelOptions.current().evaluateCanonicalTypesToNativeValues(true).build(), DYNAMIC_PROTO);

ProtoMessageValue protoMessageValue =
(ProtoMessageValue)
Expand All @@ -89,9 +89,9 @@ public void newValue_createProtoMessage_fieldsPopulated() {
"single_string",
"hello",
"single_timestamp",
ProtoTimeUtils.fromSecondsToTimestamp(50),
Instant.ofEpochSecond(50),
"single_duration",
ProtoTimeUtils.fromSecondsToDuration(100)))
Duration.ofSeconds(100)))
.get();

assertThat(protoMessageValue.isZeroValue()).isFalse();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

package dev.cel.validator.validators;

import com.google.protobuf.Duration;
import java.time.Duration;

/** DurationLiteralValidator ensures that duration literal arguments are valid. */
public final class DurationLiteralValidator extends LiteralValidator {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@

package dev.cel.validator.validators;

import com.google.protobuf.Timestamp;
import java.time.Instant;

/** TimestampLiteralValidator ensures that timestamp literal arguments are valid. */
public final class TimestampLiteralValidator extends LiteralValidator {
public static final TimestampLiteralValidator INSTANCE =
new TimestampLiteralValidator("timestamp", Timestamp.class);
new TimestampLiteralValidator("timestamp", Instant.class);

private TimestampLiteralValidator(String functionName, Class<?> expectedResultType) {
super(functionName, expectedResultType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import static org.junit.Assert.assertThrows;

import com.google.common.collect.ImmutableMap;
import com.google.protobuf.Duration;
import com.google.testing.junit.testparameterinjector.TestParameterInjector;
import com.google.testing.junit.testparameterinjector.TestParameters;
import dev.cel.bundle.Cel;
Expand All @@ -35,6 +34,7 @@
import dev.cel.validator.CelValidator;
import dev.cel.validator.CelValidatorFactory;
import java.text.ParseException;
import java.time.Duration;
import org.junit.Test;
import org.junit.runner.RunWith;

Expand Down Expand Up @@ -174,7 +174,7 @@ public void duration_unexpectedResultType_throws() throws Exception {
assertThat(result.getAllIssues().get(0).toDisplayString(ast.getSource()))
.isEqualTo(
"ERROR: <input>:1:10: duration validation failed. Reason: Expected"
+ " com.google.protobuf.Duration type but got java.lang.Integer instead\n"
+ " java.time.Duration type but got java.lang.Integer instead\n"
+ " | duration('1h')\n"
+ " | .........^");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import static org.junit.Assert.assertThrows;

import com.google.common.collect.ImmutableMap;
import com.google.protobuf.Timestamp;
import com.google.testing.junit.testparameterinjector.TestParameterInjector;
import com.google.testing.junit.testparameterinjector.TestParameters;
import dev.cel.bundle.Cel;
Expand All @@ -36,6 +35,7 @@
import dev.cel.validator.CelValidator;
import dev.cel.validator.CelValidatorFactory;
import java.text.ParseException;
import java.time.Instant;
import org.junit.Test;
import org.junit.runner.RunWith;

Expand Down Expand Up @@ -63,7 +63,7 @@ public void timestamp_validFormat(String source) throws Exception {

assertThat(result.hasError()).isFalse();
assertThat(result.getAllIssues()).isEmpty();
assertThat(CEL.createProgram(ast).eval()).isInstanceOf(Timestamp.class);
assertThat(CEL.createProgram(ast).eval()).isInstanceOf(Instant.class);
}

@Test
Expand Down Expand Up @@ -100,8 +100,7 @@ public void timestamp_withVariable_noOp() throws Exception {
() -> CEL.createProgram(ast).eval(ImmutableMap.of("str_var", "bad")));
assertThat(e)
.hasMessageThat()
.contains(
"evaluation error at <input>:9: Failed to parse timestamp: invalid timestamp \"bad\"");
.contains("evaluation error at <input>:9: Text 'bad' could not be parsed at index 0");
}

@Test
Expand Down Expand Up @@ -153,8 +152,8 @@ public void timestamp_invalidFormat() throws Exception {
assertThat(result.getAllIssues().get(0).getSeverity()).isEqualTo(Severity.ERROR);
assertThat(result.getAllIssues().get(0).toDisplayString(ast.getSource()))
.isEqualTo(
"ERROR: <input>:1:11: timestamp validation failed. Reason: evaluation error: Failed to"
+ " parse timestamp: invalid timestamp \"bad\"\n"
"ERROR: <input>:1:11: timestamp validation failed. Reason: evaluation error: Text 'bad'"
+ " could not be parsed at index 0\n"
+ " | timestamp('bad')\n"
+ " | ..........^");
}
Expand Down Expand Up @@ -185,7 +184,7 @@ public void timestamp_unexpectedResultType_throws() throws Exception {
assertThat(result.getAllIssues().get(0).toDisplayString(ast.getSource()))
.isEqualTo(
"ERROR: <input>:1:11: timestamp validation failed. Reason: Expected"
+ " com.google.protobuf.Timestamp type but got java.lang.Integer instead\n"
+ " java.time.Instant type but got java.lang.Integer instead\n"
+ " | timestamp(0)\n"
+ " | ..........^");
}
Expand Down