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 @@ -135,9 +135,13 @@ public void setRuntimeOptions(CelRuntimeBuilder runtimeBuilder) {
functions.forEach(
function -> {
if (celOptions.evaluateCanonicalTypesToNativeValues()) {
runtimeBuilder.addFunctionBindings(function.nativeBytesFunctionBinding);
runtimeBuilder.addFunctionBindings(
CelFunctionBinding.fromOverloads(
function.getFunction(), function.nativeBytesFunctionBinding));
} else {
runtimeBuilder.addFunctionBindings(function.protoBytesFunctionBinding);
runtimeBuilder.addFunctionBindings(
CelFunctionBinding.fromOverloads(
function.getFunction(), function.protoBytesFunctionBinding));
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,36 +19,45 @@
import static org.junit.Assert.assertThrows;

import com.google.common.collect.ImmutableMap;
import com.google.testing.junit.testparameterinjector.TestParameter;
import com.google.testing.junit.testparameterinjector.TestParameterInjector;
import dev.cel.bundle.Cel;
import dev.cel.common.CelAbstractSyntaxTree;
import dev.cel.common.CelFunctionDecl;
import dev.cel.common.CelOptions;
import dev.cel.common.CelValidationException;
import dev.cel.common.types.SimpleType;
import dev.cel.common.values.CelByteString;
import dev.cel.compiler.CelCompiler;
import dev.cel.compiler.CelCompilerFactory;
import dev.cel.runtime.CelEvaluationException;
import dev.cel.runtime.CelRuntime;
import dev.cel.runtime.CelRuntimeFactory;
import dev.cel.testing.CelRuntimeFlavor;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(TestParameterInjector.class)
public class CelEncoderExtensionsTest {
private static final CelOptions CEL_OPTIONS =
CelOptions.current().build();

private static final CelCompiler CEL_COMPILER =
CelCompilerFactory.standardCelCompilerBuilder()
.addVar("stringVar", SimpleType.STRING)
.addLibraries(CelExtensions.encoders(CEL_OPTIONS))
.build();
private static final CelRuntime CEL_RUNTIME =
CelRuntimeFactory.standardCelRuntimeBuilder()
.setOptions(CEL_OPTIONS)
.addLibraries(CelExtensions.encoders(CEL_OPTIONS))
.build();
CelOptions.current().enableHeterogeneousNumericComparisons(true).build();

@TestParameter public CelRuntimeFlavor runtimeFlavor;
@TestParameter public boolean isParseOnly;

private Cel cel;

@Before
public void setUp() {
// Legacy runtime does not support parsed-only evaluation mode.
Assume.assumeFalse(runtimeFlavor.equals(CelRuntimeFlavor.LEGACY) && isParseOnly);
this.cel =
runtimeFlavor
.builder()
.setOptions(CEL_OPTIONS)
.addCompilerLibraries(CelExtensions.encoders(CEL_OPTIONS))
.addRuntimeLibraries(CelExtensions.encoders(CEL_OPTIONS))
.addVar("stringVar", SimpleType.STRING)
.build();
}

@Test
public void library() {
Expand All @@ -63,86 +72,72 @@ public void library() {

@Test
public void encode_success() throws Exception {
String encodedBytes =
(String)
CEL_RUNTIME
.createProgram(CEL_COMPILER.compile("base64.encode(b'hello')").getAst())
.eval();
String encodedBytes = (String) eval("base64.encode(b'hello')");

assertThat(encodedBytes).isEqualTo("aGVsbG8=");
}

@Test
public void decode_success() throws Exception {
CelByteString decodedBytes =
(CelByteString)
CEL_RUNTIME
.createProgram(CEL_COMPILER.compile("base64.decode('aGVsbG8=')").getAst())
.eval();
CelByteString decodedBytes = (CelByteString) eval("base64.decode('aGVsbG8=')");

assertThat(decodedBytes.size()).isEqualTo(5);
assertThat(new String(decodedBytes.toByteArray(), ISO_8859_1)).isEqualTo("hello");
}

@Test
public void decode_withoutPadding_success() throws Exception {
CelByteString decodedBytes =
(CelByteString)
CEL_RUNTIME
// RFC2045 6.8, padding can be ignored.
.createProgram(CEL_COMPILER.compile("base64.decode('aGVsbG8')").getAst())
.eval();
CelByteString decodedBytes = (CelByteString) eval("base64.decode('aGVsbG8')");

assertThat(decodedBytes.size()).isEqualTo(5);
assertThat(new String(decodedBytes.toByteArray(), ISO_8859_1)).isEqualTo("hello");
}

@Test
public void roundTrip_success() throws Exception {
String encodedString =
(String)
CEL_RUNTIME
.createProgram(CEL_COMPILER.compile("base64.encode(b'Hello World!')").getAst())
.eval();
String encodedString = (String) eval("base64.encode(b'Hello World!')");
CelByteString decodedBytes =
(CelByteString)
CEL_RUNTIME
.createProgram(CEL_COMPILER.compile("base64.decode(stringVar)").getAst())
.eval(ImmutableMap.of("stringVar", encodedString));
eval("base64.decode(stringVar)", ImmutableMap.of("stringVar", encodedString));

assertThat(new String(decodedBytes.toByteArray(), ISO_8859_1)).isEqualTo("Hello World!");
}

@Test
public void encode_invalidParam_throwsCompilationException() {
Assume.assumeFalse(isParseOnly);
CelValidationException e =
assertThrows(
CelValidationException.class,
() -> CEL_COMPILER.compile("base64.encode('hello')").getAst());
CelValidationException.class, () -> cel.compile("base64.encode('hello')").getAst());

assertThat(e).hasMessageThat().contains("found no matching overload for 'base64.encode'");
}

@Test
public void decode_invalidParam_throwsCompilationException() {
Assume.assumeFalse(isParseOnly);
CelValidationException e =
assertThrows(
CelValidationException.class,
() -> CEL_COMPILER.compile("base64.decode(b'aGVsbG8=')").getAst());
CelValidationException.class, () -> cel.compile("base64.decode(b'aGVsbG8=')").getAst());

assertThat(e).hasMessageThat().contains("found no matching overload for 'base64.decode'");
}

@Test
public void decode_malformedBase64Char_throwsEvaluationException() throws Exception {
CelAbstractSyntaxTree ast = CEL_COMPILER.compile("base64.decode('z!')").getAst();

CelEvaluationException e =
assertThrows(CelEvaluationException.class, () -> CEL_RUNTIME.createProgram(ast).eval());
assertThrows(CelEvaluationException.class, () -> eval("base64.decode('z!')"));

assertThat(e)
.hasMessageThat()
.contains("Function 'base64_decode_string' failed with arg(s) 'z!'");
assertThat(e).hasMessageThat().contains("failed with arg(s) 'z!'");
assertThat(e).hasCauseThat().hasMessageThat().contains("Illegal base64 character");
}

private Object eval(String expr) throws Exception {
return eval(expr, ImmutableMap.of());
}

private Object eval(String expr, ImmutableMap<String, Object> vars) throws Exception {
CelAbstractSyntaxTree ast = isParseOnly ? cel.parse(expr).getAst() : cel.compile(expr).getAst();
return cel.createProgram(ast).eval(vars);
}
}
Loading