diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index ac6982b1..6b7463f5 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -43,17 +43,10 @@ jobs:
with:
cache-read-only: ${{ github.event_name != 'push' || github.ref != 'refs/heads/main' }}
- - name: Spotless Check
- # Spotless must run in a different invocation, because
- # it has some weird Gradle configuration/variant issue
- if: ${{ matrix.java-version == '21' }}
- run: ./gradlew spotlessCheck --scan
-
- name: Build
run: >
./gradlew --rerun-tasks ${{ env.ADDITIONAL_GRADLE_OPTS }}
assemble check publishToMavenLocal
- -x jmh -x spotlessCheck -x testNative
--scan
- name: Quarkus native smoke
@@ -65,9 +58,6 @@ jobs:
# because these tasks intentionally do not depend on the publishToMavenLocal tasks.
run: ./gradlew buildToolIntegrations
- - name: Microbenchmarks
- run: ./gradlew jmh
-
- name: Capture test results
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
if: failure()
diff --git a/README.md b/README.md
index fee5f965..fbb49c0f 100644
--- a/README.md
+++ b/README.md
@@ -22,6 +22,7 @@ The CEL specification can be found [here](https://github.com/google/cel-spec).
- [Motivation](#motivation)
- [Arbitrary Java classes](#arbitrary-java-classes)
- [Unsigned 64-bit `uint`](#unsigned-64-bit-uint)
+ - [Protobuf enum semantics](#protobuf-enum-semantics)
- [Native image and package verification](#native-image-and-package-verification)
- [Not yet implemented](#not-yet-implemented)
- [Unclear double-to-int rounding behavior](#unclear-double-to-int-rounding-behavior)
@@ -394,6 +395,24 @@ but `123u == 123u` and `123 == 123` are.
If you have a `uint32` or `uint64` in protobuf objects, or use `uint`s in CEL expressions, wrap those
values with `org.projectnessie.cel.common.ULong`.
+### Protobuf enum semantics
+
+CEL-Java follows the CEL-Spec v0.25.2 language definition for protobuf enum values: protobuf enum
+constants and enum fields are represented as CEL `int` values.
+
+The upstream CEL-Spec conformance testdata also contains strong-enum cases where enum values
+preserve their enum type. CEL-Java does not currently enable those strong-enum conformance cases.
+They are not part of the v0.25.2 language-definition baseline and are mutually incompatible with the
+legacy enum-as-int conformance sections in a single-mode runtime.
+
+Use numeric enum values directly, or use `int(...)` when writing expressions that should remain clear
+if strong enum support is added in the future:
+
+```cel
+TestAllTypes.NestedEnum.BAR == 1
+int(TestAllTypes.NestedEnum.BAR) == 1
+```
+
### Native image and package verification
Native-image and package behavior must be verified in the consuming application's exact build.
@@ -401,7 +420,7 @@ Native-image and package behavior must be verified in the consuming application'
prove Quarkus native-image or package compatibility for every application.
Before using CEL conditions in release-critical authorization paths, run JVM condition tests, the
-consuming project's normal build, dependency tree review for protobuf/ANTLR/Jackson conflicts, and
+consuming project's normal build, dependency tree review for protobuf/Jackson conflicts, and
package/native-image verification if native execution is part of the release path.
### Not yet implemented
diff --git a/SECURITY.md b/SECURITY.md
index ca587034..1f57adff 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -1,10 +1,10 @@
# Security Policy
-The project is in a very early stage.
-
## Supported Versions
-None, yet.
+Only the latest published release receives security fixes. Older releases are not supported.
+
+Reports affecting older releases are still welcome, but any fix will target the latest release.
## Reporting a Vulnerability
diff --git a/benchmarks/build.gradle.kts b/benchmarks/build.gradle.kts
new file mode 100644
index 00000000..3f1e4ef5
--- /dev/null
+++ b/benchmarks/build.gradle.kts
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2026 The Authors of CEL-Java
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+plugins {
+ `java-library`
+ alias(libs.plugins.jmh)
+ id("cel-conventions")
+}
+
+configurations.all {
+ exclude(group = "org.projectnessie.cel", module = "cel-generated-pb")
+}
+
+dependencies {
+ implementation(project(":cel-core"))
+ implementation(project(":cel-jackson3"))
+ implementation(project(":cel-generated-pb3"))
+ implementation(testFixtures(project(":cel-generated-pb3")))
+ implementation(libs.protobuf.java3)
+
+ testImplementation(platform(libs.junit.bom))
+ testImplementation(libs.bundles.junit.testing)
+ testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
+ testRuntimeOnly("org.junit.platform:junit-platform-launcher")
+
+ jmhImplementation(libs.jmh.core)
+ jmhAnnotationProcessor(libs.jmh.generator.annprocess)
+ jmhImplementation(libs.cel.expr.java)
+}
+
+jmh { jmhVersion.set(libs.versions.jmh.get()) }
+
+tasks.named("assemble") { dependsOn(tasks.named("jmhJar")) }
diff --git a/benchmarks/src/jmh/java/org/projectnessie/cel/DevCelRealWorldComparisonBench.java b/benchmarks/src/jmh/java/org/projectnessie/cel/DevCelRealWorldComparisonBench.java
new file mode 100644
index 00000000..bf37d966
--- /dev/null
+++ b/benchmarks/src/jmh/java/org/projectnessie/cel/DevCelRealWorldComparisonBench.java
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2026 The Authors of CEL-Java
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.projectnessie.cel;
+
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.DAPR_IMPORTANT_HIT;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.DRA_UNRELATED_32;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.FLUX_READY_ALL_32;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.GATEWAY_HOSTNAME_16;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.GATEWAY_UNIQUE_16;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.IAM_PREFIX_HIT;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.NESSIE_DEFAULT_ALLOW;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.NESSIE_ROLES_MISS;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.ORG_BINDINGS_ALL_8_X_8;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.ORG_MEMBERS_ALL_32;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.POLARIS_CUTOFF_STOP;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.PROTOVALIDATE_NOTIFICATION_NONE;
+
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Message;
+import dev.cel.common.CelValidationException;
+import dev.cel.common.types.CelType;
+import dev.cel.common.types.ListType;
+import dev.cel.common.types.SimpleType;
+import dev.cel.common.types.StructTypeReference;
+import dev.cel.compiler.CelCompiler;
+import dev.cel.compiler.CelCompilerBuilder;
+import dev.cel.compiler.CelCompilerFactory;
+import dev.cel.parser.CelStandardMacro;
+import dev.cel.runtime.CelEvaluationException;
+import dev.cel.runtime.CelRuntime;
+import dev.cel.runtime.CelRuntimeFactory;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Threads;
+import org.openjdk.jmh.annotations.Warmup;
+import org.projectnessie.cel.benchmark.PreparedFixture;
+import org.projectnessie.cel.benchmark.RealWorldHostFixtures;
+import org.projectnessie.cel.benchmark.RealWorldProtoFixtures;
+import org.projectnessie.cel.benchmark.RealWorldWorkloads;
+import org.projectnessie.cel.benchmark.RealWorldWorkloads.Family;
+import org.projectnessie.cel.benchmark.RealWorldWorkloads.Representation;
+import org.projectnessie.cel.benchmark.RealWorldWorkloads.Scenario;
+
+/**
+ * Compares Projectnessie CEL-Java with the independent {@code dev.cel} Java implementation.
+ *
+ *
The {@code dev.cel} implementation is maintained in the {@code cel-expr/cel-java} repository, formerly
+ * {@code google/cel-java}. It is not an upstream project from which Projectnessie CEL-Java is
+ * derived. Its exact release is pinned by the {@code celExprJava} entry in the Gradle version
+ * catalog.
+ *
+ *
Measured boundary
+ *
+ *
This benchmark measures warm, single-threaded, complete-program evaluation. Each state
+ * constructs, checks, and plans its programs once during trial setup. Each benchmark invocation
+ * then:
+ *
+ *
+ *
evaluates the same CEL source expression or ordered expression sequence,
+ *
uses the same activation and, for Protobuf scenarios, the same generated message instance,
+ *
short-circuits an expression sequence after the first {@code true} result, and
+ *
materializes the result as a Java {@link Boolean}.
+ *
+ *
+ *
Checking, planning, environment construction, JVM startup, concurrency scaling, and
+ * application tail latency are outside the measured boundary.
+ *
+ *
Compared configurations
+ *
+ *
Projectnessie is represented by two configurations. Both use {@link EvalOption#OptOptimize}.
+ * The {@code projectnessieExactNative*} methods additionally use exact input adapters and native
+ * planning. This is an opt-in fast path whose availability depends on the registered input types
+ * and expression shape. The {@code projectnessieGeneral*} methods use the general value-adaptation
+ * path and are included to make the contribution and scope of exact/native evaluation visible.
+ *
+ *
The {@code devCel*} methods use {@link CelCompilerFactory#standardCelCompilerBuilder()} with
+ * the standard macros and {@link CelRuntimeFactory#plannerRuntimeBuilder()}. No separate {@code
+ * dev.cel} AST optimization pass is applied. This represents the documented compiler and planner
+ * runtime path, not every configuration or feature offered by that implementation.
+ *
+ *
Workload and dependency limitations
+ *
+ *
The scenarios are a deliberately bounded common subset of {@link RealWorldWorkloads}. They
+ * cover scalar and list host values, a dynamic map, constant regular expressions, and generated
+ * Protobuf fields, maps, repeated messages, presence, and nested comprehensions. Jackson scenarios
+ * are excluded because there is no equivalent {@code dev.cel} Jackson integration in this harness.
+ * The subset must not be treated as a general ranking across all CEL features, input systems,
+ * diagnostics, extensions, or application workloads.
+ *
+ *
Both implementations run in one JMH classpath and therefore use the Protobuf runtime version
+ * pinned by this project. This keeps the generated messages and runtime representation identical,
+ * but it does not reproduce the exact transitive dependency graph declared by the selected {@code
+ * dev.cel} release.
+ *
+ *
Correctness and interpretation
+ *
+ *
Trial setup evaluates every compared configuration and rejects a scenario unless all results
+ * match its expected value. This is a semantic guard for the selected inputs, not a conformance
+ * test. Benchmark results should always identify the two library revisions, JDK, hardware, JMH
+ * configuration, selected scenarios, and compared modes. Results from this class establish only the
+ * relative cost of the documented warm-evaluation boundary.
+ */
+@Warmup(iterations = 3, time = 500, timeUnit = TimeUnit.MILLISECONDS)
+@Measurement(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS)
+@Fork(3)
+@Threads(1)
+@BenchmarkMode(Mode.AverageTime)
+@OutputTimeUnit(TimeUnit.NANOSECONDS)
+public class DevCelRealWorldComparisonBench {
+ @State(Scope.Benchmark)
+ public static class HostState {
+ @Param({POLARIS_CUTOFF_STOP, NESSIE_DEFAULT_ALLOW, NESSIE_ROLES_MISS, DAPR_IMPORTANT_HIT})
+ public String scenarioId;
+
+ RealWorldProgramSet projectnessie;
+ DevCelPrograms devCel;
+
+ @Setup
+ public void setup() throws CelValidationException, CelEvaluationException {
+ Scenario scenario = RealWorldWorkloads.scenario(scenarioId);
+ PreparedFixture fixture = RealWorldHostFixtures.prepare(scenario);
+ projectnessie = RealWorldProgramSet.host(scenario, fixture);
+ devCel = DevCelPrograms.host(scenario, fixture);
+ verify(scenario, projectnessie.exactNative(), projectnessie.general(), devCel.evaluate());
+ }
+ }
+
+ @State(Scope.Benchmark)
+ public static class ProtoState {
+ @Param({
+ IAM_PREFIX_HIT,
+ DRA_UNRELATED_32,
+ ORG_MEMBERS_ALL_32,
+ ORG_BINDINGS_ALL_8_X_8,
+ GATEWAY_HOSTNAME_16,
+ GATEWAY_UNIQUE_16,
+ FLUX_READY_ALL_32,
+ PROTOVALIDATE_NOTIFICATION_NONE
+ })
+ public String scenarioId;
+
+ RealWorldProgramSet projectnessie;
+ DevCelPrograms devCel;
+
+ @Setup
+ public void setup() throws CelValidationException, CelEvaluationException {
+ Scenario scenario = RealWorldWorkloads.scenario(scenarioId);
+ PreparedFixture fixture = RealWorldProtoFixtures.prepare(scenario);
+ Message[] messageTypes = RealWorldProtoFixtures.registeredTypes(scenario.family());
+ projectnessie = RealWorldProgramSet.protobuf(scenario, fixture, messageTypes);
+ devCel = DevCelPrograms.protobuf(scenario, fixture, messageTypes);
+ verify(scenario, projectnessie.exactNative(), projectnessie.general(), devCel.evaluate());
+ }
+ }
+
+ @Benchmark
+ public Boolean projectnessieExactNativeHost(HostState state) {
+ return state.projectnessie.exactNative();
+ }
+
+ @Benchmark
+ public Boolean projectnessieGeneralHost(HostState state) {
+ return state.projectnessie.general();
+ }
+
+ @Benchmark
+ public Boolean devCelHost(HostState state) throws CelEvaluationException {
+ return state.devCel.evaluate();
+ }
+
+ @Benchmark
+ public Boolean projectnessieExactNativeProto(ProtoState state) {
+ return state.projectnessie.exactNative();
+ }
+
+ @Benchmark
+ public Boolean projectnessieGeneralProto(ProtoState state) {
+ return state.projectnessie.general();
+ }
+
+ @Benchmark
+ public Boolean devCelProto(ProtoState state) throws CelEvaluationException {
+ return state.devCel.evaluate();
+ }
+
+ private static void verify(
+ Scenario scenario,
+ Boolean projectnessieExactNative,
+ Boolean projectnessieGeneral,
+ Boolean devCel) {
+ if (projectnessieExactNative != scenario.expected()
+ || projectnessieGeneral != scenario.expected()
+ || devCel != scenario.expected()) {
+ throw new IllegalStateException(
+ scenario.id()
+ + ": expected="
+ + scenario.expected()
+ + ", projectnessieExactNative="
+ + projectnessieExactNative
+ + ", projectnessieGeneral="
+ + projectnessieGeneral
+ + ", devCel="
+ + devCel);
+ }
+ }
+
+ private record DevCelPrograms(List programs, Map activation) {
+ private DevCelPrograms(List programs, Map activation) {
+ this.programs = List.copyOf(programs);
+ this.activation = activation;
+ }
+
+ static DevCelPrograms host(Scenario scenario, PreparedFixture fixture)
+ throws CelValidationException, CelEvaluationException {
+ CelCompilerBuilder compiler = standardCompiler();
+ addHostVariables(compiler, scenario.family());
+ return create(
+ compiler.build(),
+ CelRuntimeFactory.plannerRuntimeBuilder().build(),
+ scenario.expressions(Representation.HOST),
+ fixture.activation());
+ }
+
+ static DevCelPrograms protobuf(
+ Scenario scenario, PreparedFixture fixture, Message[] messageTypes)
+ throws CelValidationException, CelEvaluationException {
+ List descriptors =
+ Arrays.stream(messageTypes).map(Message::getDescriptorForType).toList();
+ Descriptor rootDescriptor = messageTypes[0].getDescriptorForType();
+ CelType rootType = StructTypeReference.create(rootDescriptor.getFullName());
+ CelCompilerBuilder compiler =
+ standardCompiler()
+ .addMessageTypes(descriptors)
+ .addVar(variableName(scenario.family()), variableType(scenario.family(), rootType));
+ CelRuntime runtime =
+ CelRuntimeFactory.plannerRuntimeBuilder().addMessageTypes(descriptors).build();
+ return create(
+ compiler.build(),
+ runtime,
+ scenario.expressions(Representation.PROTOBUF),
+ fixture.activation());
+ }
+
+ private static CelCompilerBuilder standardCompiler() {
+ return CelCompilerFactory.standardCelCompilerBuilder()
+ .setStandardMacros(CelStandardMacro.STANDARD_MACROS);
+ }
+
+ private static DevCelPrograms create(
+ CelCompiler compiler,
+ CelRuntime runtime,
+ List expressions,
+ Map activation)
+ throws CelValidationException, CelEvaluationException {
+ List programs = new ArrayList<>(expressions.size());
+ for (String expression : expressions) {
+ programs.add(runtime.createProgram(compiler.compile(expression).getAst()));
+ }
+ return new DevCelPrograms(programs, activation);
+ }
+
+ Boolean evaluate() throws CelEvaluationException {
+ for (CelRuntime.Program program : programs) {
+ if ((Boolean) program.eval(activation)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static void addHostVariables(CelCompilerBuilder compiler, Family family) {
+ switch (family) {
+ case POLARIS ->
+ compiler
+ .addVar("ref", SimpleType.STRING)
+ .addVar("commits", SimpleType.INT)
+ .addVar("ageMinutes", SimpleType.INT)
+ .addVar("ageHours", SimpleType.INT)
+ .addVar("ageDays", SimpleType.INT);
+ case NESSIE ->
+ compiler
+ .addVar("op", SimpleType.STRING)
+ .addVar("role", SimpleType.STRING)
+ .addVar("roles", ListType.create(SimpleType.STRING))
+ .addVar("ref", SimpleType.STRING)
+ .addVar("path", SimpleType.STRING)
+ .addVar("contentType", SimpleType.STRING);
+ case DAPR_HOST -> compiler.addVar("event", SimpleType.DYN);
+ default -> throw new IllegalArgumentException("Unsupported host family " + family);
+ }
+ }
+
+ private static String variableName(Family family) {
+ return switch (family) {
+ case IAM, ORGANIZATION, FLUX -> "resource";
+ case GATEWAY -> "self";
+ case DRA -> "device";
+ case DAPR_TYPED -> "event";
+ case PROTOVALIDATE_BOOKING, PROTOVALIDATE_INTERVAL, PROTOVALIDATE_NOTIFICATION -> "this";
+ default -> throw new IllegalArgumentException("Unsupported protobuf family " + family);
+ };
+ }
+
+ private static CelType variableType(Family family, CelType rootType) {
+ return family == Family.GATEWAY ? ListType.create(rootType) : rootType;
+ }
+ }
+}
diff --git a/benchmarks/src/jmh/java/org/projectnessie/cel/RealWorldHostWorkloadBench.java b/benchmarks/src/jmh/java/org/projectnessie/cel/RealWorldHostWorkloadBench.java
new file mode 100644
index 00000000..64195a09
--- /dev/null
+++ b/benchmarks/src/jmh/java/org/projectnessie/cel/RealWorldHostWorkloadBench.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2026 The Authors of CEL-Java
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.projectnessie.cel;
+
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.DAPR_DEPOSIT_BOUNDARY;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.DAPR_DEPOSIT_HIT;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.DAPR_IMPORTANT_ABSENT;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.DAPR_IMPORTANT_HIT;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.DAPR_TYPE_HIT;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.DAPR_TYPE_MISS;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.NESSIE_DEFAULT_ALLOW;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.NESSIE_DEFAULT_DENY;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.NESSIE_ROLES_HIT_LATE;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.NESSIE_ROLES_MISS;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.NESSIE_RULES_DENY;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.NESSIE_RULES_FIRST;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.NESSIE_RULES_LATE;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.NESSIE_RULES_MIDDLE;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.OPENFGA_AFTER;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.OPENFGA_BEFORE;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.OPENFGA_EQUAL;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.POLARIS_CONSTANT_FALSE;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.POLARIS_CUTOFF_LEFT;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.POLARIS_CUTOFF_RIGHT;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.POLARIS_CUTOFF_STOP;
+
+import java.util.concurrent.TimeUnit;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Threads;
+import org.openjdk.jmh.annotations.Warmup;
+import org.projectnessie.cel.benchmark.RealWorldHostFixtures;
+import org.projectnessie.cel.benchmark.RealWorldWorkloads;
+
+/** Complete-program source-host workloads derived from Polaris, Nessie, OpenFGA, and Dapr. */
+@Warmup(iterations = 3, time = 500, timeUnit = TimeUnit.MILLISECONDS)
+@Measurement(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS)
+@Fork(3)
+@Threads(1)
+@BenchmarkMode(Mode.AverageTime)
+@OutputTimeUnit(TimeUnit.NANOSECONDS)
+public class RealWorldHostWorkloadBench {
+ @State(Scope.Benchmark)
+ public static class WorkloadState {
+ @Param({
+ POLARIS_CONSTANT_FALSE,
+ POLARIS_CUTOFF_LEFT,
+ POLARIS_CUTOFF_RIGHT,
+ POLARIS_CUTOFF_STOP,
+ NESSIE_DEFAULT_ALLOW,
+ NESSIE_DEFAULT_DENY,
+ NESSIE_ROLES_HIT_LATE,
+ NESSIE_ROLES_MISS,
+ NESSIE_RULES_FIRST,
+ NESSIE_RULES_MIDDLE,
+ NESSIE_RULES_LATE,
+ NESSIE_RULES_DENY,
+ OPENFGA_BEFORE,
+ OPENFGA_EQUAL,
+ OPENFGA_AFTER,
+ DAPR_TYPE_HIT,
+ DAPR_TYPE_MISS,
+ DAPR_IMPORTANT_HIT,
+ DAPR_IMPORTANT_ABSENT,
+ DAPR_DEPOSIT_HIT,
+ DAPR_DEPOSIT_BOUNDARY
+ })
+ public String scenarioId;
+
+ RealWorldProgramSet programs;
+
+ @Setup
+ public void setup() {
+ var scenario = RealWorldWorkloads.scenario(scenarioId);
+ programs = RealWorldProgramSet.host(scenario, RealWorldHostFixtures.prepare(scenario));
+ }
+ }
+
+ @Benchmark
+ public Boolean exactNative(WorkloadState state) {
+ return state.programs.exactNative();
+ }
+
+ @Benchmark
+ public Boolean exactDisabled(WorkloadState state) {
+ return state.programs.exactDisabled();
+ }
+
+ @Benchmark
+ public Boolean general(WorkloadState state) {
+ return state.programs.general();
+ }
+
+ @Benchmark
+ public Boolean direct(WorkloadState state) {
+ return state.programs.direct();
+ }
+}
diff --git a/benchmarks/src/jmh/java/org/projectnessie/cel/RealWorldJackson3WorkloadBench.java b/benchmarks/src/jmh/java/org/projectnessie/cel/RealWorldJackson3WorkloadBench.java
new file mode 100644
index 00000000..c527f04d
--- /dev/null
+++ b/benchmarks/src/jmh/java/org/projectnessie/cel/RealWorldJackson3WorkloadBench.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2026 The Authors of CEL-Java
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.projectnessie.cel;
+
+import java.util.concurrent.TimeUnit;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Threads;
+import org.openjdk.jmh.annotations.Warmup;
+import org.projectnessie.cel.benchmark.RealWorldPojoFixtures;
+import org.projectnessie.cel.benchmark.RealWorldWorkloads;
+
+/** Complete-program Jackson 3 POJO representation workloads. */
+@Warmup(iterations = 3, time = 500, timeUnit = TimeUnit.MILLISECONDS)
+@Measurement(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS)
+@Fork(3)
+@Threads(1)
+@BenchmarkMode(Mode.AverageTime)
+@OutputTimeUnit(TimeUnit.NANOSECONDS)
+public class RealWorldJackson3WorkloadBench {
+ @State(Scope.Benchmark)
+ public static class WorkloadState extends RealWorldPairedWorkloadState {
+ @Setup
+ public void setup() {
+ var scenario = RealWorldWorkloads.scenario(scenarioId);
+ programs =
+ RealWorldProgramSet.jackson3(
+ scenario,
+ RealWorldPojoFixtures.prepare(scenario),
+ RealWorldPojoFixtures.registeredTypes(scenario.family()));
+ }
+ }
+
+ @Benchmark
+ public Boolean exactNative(WorkloadState state) {
+ return state.programs.exactNative();
+ }
+
+ @Benchmark
+ public Boolean exactDisabled(WorkloadState state) {
+ return state.programs.exactDisabled();
+ }
+
+ @Benchmark
+ public Boolean general(WorkloadState state) {
+ return state.programs.general();
+ }
+
+ @Benchmark
+ public Boolean direct(WorkloadState state) {
+ return state.programs.direct();
+ }
+}
diff --git a/benchmarks/src/jmh/java/org/projectnessie/cel/RealWorldLifecycleBench.java b/benchmarks/src/jmh/java/org/projectnessie/cel/RealWorldLifecycleBench.java
new file mode 100644
index 00000000..f9eebb43
--- /dev/null
+++ b/benchmarks/src/jmh/java/org/projectnessie/cel/RealWorldLifecycleBench.java
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2026 The Authors of CEL-Java
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.projectnessie.cel;
+
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.DAPR_DEPOSIT_HIT;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.DAPR_IMPORTANT_HIT;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.DAPR_TYPED_DEPOSIT;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.DAPR_TYPED_IMPORTANT;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.DAPR_TYPE_HIT;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.DRA_MATCH;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.FLUX_READY_ALL_32;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.GATEWAY_UNIQUE_16;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.IAM_PREFIX_HIT;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.NESSIE_DEFAULT_ALLOW;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.NESSIE_ROLES_HIT_LATE;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.NESSIE_RULES_DENY;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.OPENFGA_BEFORE;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.ORG_BINDINGS_ALL_8_X_8;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.POLARIS_CUTOFF_LEFT;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.PROTOVALIDATE_BOOKING_REGION;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.PROTOVALIDATE_INTERVAL_ORDERED;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.PROTOVALIDATE_NOTIFICATION_WEBHOOK;
+
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Threads;
+import org.openjdk.jmh.annotations.Warmup;
+import org.projectnessie.cel.RealWorldProgramSet.Lifecycle;
+import org.projectnessie.cel.benchmark.RealWorldHostFixtures;
+import org.projectnessie.cel.benchmark.RealWorldPojoFixtures;
+import org.projectnessie.cel.benchmark.RealWorldProtoFixtures;
+import org.projectnessie.cel.benchmark.RealWorldWorkloads;
+
+/**
+ * Measures compilation, planning, and the first evaluation of a fresh program for representative
+ * real-world expression shapes.
+ *
+ *
The compilation methods include parsing and checking. Compilation and planning retain a
+ * configured environment. The {@code cold*} methods include environment and registry construction,
+ * parsing, checking, program construction, and one complete evaluation, but not whole-JVM startup.
+ */
+@Warmup(iterations = 3, time = 500, timeUnit = TimeUnit.MILLISECONDS)
+@Measurement(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS)
+@Fork(3)
+@Threads(1)
+@BenchmarkMode(Mode.AverageTime)
+@OutputTimeUnit(TimeUnit.NANOSECONDS)
+public class RealWorldLifecycleBench {
+ @State(Scope.Benchmark)
+ public static class HostState {
+ @Param({
+ POLARIS_CUTOFF_LEFT,
+ NESSIE_DEFAULT_ALLOW,
+ NESSIE_ROLES_HIT_LATE,
+ NESSIE_RULES_DENY,
+ OPENFGA_BEFORE,
+ DAPR_TYPE_HIT,
+ DAPR_IMPORTANT_HIT,
+ DAPR_DEPOSIT_HIT
+ })
+ public String scenarioId;
+
+ Lifecycle lifecycle;
+
+ @Setup
+ public void setup() {
+ var scenario = RealWorldWorkloads.scenario(scenarioId);
+ lifecycle =
+ RealWorldProgramSet.hostLifecycle(scenario, RealWorldHostFixtures.prepare(scenario));
+ }
+ }
+
+ @State(Scope.Benchmark)
+ public abstract static class PairedState {
+ @Param({
+ IAM_PREFIX_HIT,
+ ORG_BINDINGS_ALL_8_X_8,
+ GATEWAY_UNIQUE_16,
+ DRA_MATCH,
+ FLUX_READY_ALL_32,
+ DAPR_TYPED_IMPORTANT,
+ DAPR_TYPED_DEPOSIT,
+ PROTOVALIDATE_BOOKING_REGION,
+ PROTOVALIDATE_INTERVAL_ORDERED,
+ PROTOVALIDATE_NOTIFICATION_WEBHOOK
+ })
+ public String scenarioId;
+
+ Lifecycle lifecycle;
+ }
+
+ @State(Scope.Benchmark)
+ public static class ProtoState extends PairedState {
+ @Setup
+ public void setup() {
+ var scenario = RealWorldWorkloads.scenario(scenarioId);
+ lifecycle =
+ RealWorldProgramSet.protobufLifecycle(
+ scenario,
+ RealWorldProtoFixtures.prepare(scenario),
+ RealWorldProtoFixtures.registeredTypes(scenario.family()));
+ }
+ }
+
+ @State(Scope.Benchmark)
+ public static class Jackson3State extends PairedState {
+ @Setup
+ public void setup() {
+ var scenario = RealWorldWorkloads.scenario(scenarioId);
+ lifecycle =
+ RealWorldProgramSet.jackson3Lifecycle(
+ scenario,
+ RealWorldPojoFixtures.prepare(scenario),
+ RealWorldPojoFixtures.registeredTypes(scenario.family()));
+ }
+ }
+
+ @Benchmark
+ public List hostCompileExact(HostState state) {
+ return state.lifecycle.compileExact();
+ }
+
+ @Benchmark
+ public List hostCompileGeneral(HostState state) {
+ return state.lifecycle.compileGeneral();
+ }
+
+ @Benchmark
+ public List hostPlanExactNative(HostState state) {
+ return state.lifecycle.planExactNative();
+ }
+
+ @Benchmark
+ public List hostPlanExactDisabled(HostState state) {
+ return state.lifecycle.planExactDisabled();
+ }
+
+ @Benchmark
+ public List hostPlanGeneral(HostState state) {
+ return state.lifecycle.planGeneral();
+ }
+
+ @Benchmark
+ public Boolean hostColdExactNative(HostState state) {
+ return state.lifecycle.coldExactNative();
+ }
+
+ @Benchmark
+ public Boolean hostColdExactDisabled(HostState state) {
+ return state.lifecycle.coldExactDisabled();
+ }
+
+ @Benchmark
+ public Boolean hostColdGeneral(HostState state) {
+ return state.lifecycle.coldGeneral();
+ }
+
+ @Benchmark
+ public List protoCompileExact(ProtoState state) {
+ return state.lifecycle.compileExact();
+ }
+
+ @Benchmark
+ public List protoCompileGeneral(ProtoState state) {
+ return state.lifecycle.compileGeneral();
+ }
+
+ @Benchmark
+ public List protoPlanExactNative(ProtoState state) {
+ return state.lifecycle.planExactNative();
+ }
+
+ @Benchmark
+ public List protoPlanExactDisabled(ProtoState state) {
+ return state.lifecycle.planExactDisabled();
+ }
+
+ @Benchmark
+ public List protoPlanGeneral(ProtoState state) {
+ return state.lifecycle.planGeneral();
+ }
+
+ @Benchmark
+ public Boolean protoColdExactNative(ProtoState state) {
+ return state.lifecycle.coldExactNative();
+ }
+
+ @Benchmark
+ public Boolean protoColdExactDisabled(ProtoState state) {
+ return state.lifecycle.coldExactDisabled();
+ }
+
+ @Benchmark
+ public Boolean protoColdGeneral(ProtoState state) {
+ return state.lifecycle.coldGeneral();
+ }
+
+ @Benchmark
+ public List jackson3CompileExact(Jackson3State state) {
+ return state.lifecycle.compileExact();
+ }
+
+ @Benchmark
+ public List jackson3CompileGeneral(Jackson3State state) {
+ return state.lifecycle.compileGeneral();
+ }
+
+ @Benchmark
+ public List jackson3PlanExactNative(Jackson3State state) {
+ return state.lifecycle.planExactNative();
+ }
+
+ @Benchmark
+ public List jackson3PlanExactDisabled(Jackson3State state) {
+ return state.lifecycle.planExactDisabled();
+ }
+
+ @Benchmark
+ public List jackson3PlanGeneral(Jackson3State state) {
+ return state.lifecycle.planGeneral();
+ }
+
+ @Benchmark
+ public Boolean jackson3ColdExactNative(Jackson3State state) {
+ return state.lifecycle.coldExactNative();
+ }
+
+ @Benchmark
+ public Boolean jackson3ColdExactDisabled(Jackson3State state) {
+ return state.lifecycle.coldExactDisabled();
+ }
+
+ @Benchmark
+ public Boolean jackson3ColdGeneral(Jackson3State state) {
+ return state.lifecycle.coldGeneral();
+ }
+}
diff --git a/benchmarks/src/jmh/java/org/projectnessie/cel/RealWorldPairedWorkloadState.java b/benchmarks/src/jmh/java/org/projectnessie/cel/RealWorldPairedWorkloadState.java
new file mode 100644
index 00000000..85f33d9b
--- /dev/null
+++ b/benchmarks/src/jmh/java/org/projectnessie/cel/RealWorldPairedWorkloadState.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2026 The Authors of CEL-Java
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.projectnessie.cel;
+
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.DAPR_TYPED_ABSENT;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.DAPR_TYPED_DEPOSIT;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.DAPR_TYPED_IMPORTANT;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.DRA_COLOR_MISS;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.DRA_MATCH;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.DRA_SIZE_MISS;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.DRA_UNRELATED_32;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.FLUX_FAIL_FIRST_32;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.FLUX_FAIL_LAST_32;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.FLUX_NO_CONDITIONS;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.FLUX_NO_READY_8;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.FLUX_READY_ALL_32;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.FLUX_READY_ONE;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.GATEWAY_DUPLICATE_FIRST_16;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.GATEWAY_DUPLICATE_LAST_16;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.GATEWAY_EMPTY;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.GATEWAY_HOSTNAME_16;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.GATEWAY_ONE;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.GATEWAY_UNIQUE_16;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.GATEWAY_UNIQUE_8;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.IAM_PREFIX_HIT;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.IAM_PREFIX_NAME_MISS;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.IAM_PREFIX_TYPE_MISS;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.ORG_BINDINGS_ALL_8_X_8;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.ORG_BINDINGS_FAIL_LAST_8_X_8;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.ORG_MEMBERS_ALL_32;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.ORG_MEMBERS_EMPTY;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.ORG_MEMBERS_FAIL_FIRST_8;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.ORG_MEMBERS_FAIL_LAST_8;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.ORG_MEMBERS_ONE;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.PROTOVALIDATE_BOOKING_HYBRID;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.PROTOVALIDATE_BOOKING_MISSING;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.PROTOVALIDATE_BOOKING_REGION;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.PROTOVALIDATE_INTERVAL_ABSENT;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.PROTOVALIDATE_INTERVAL_ORDERED;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.PROTOVALIDATE_INTERVAL_REVERSED;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.PROTOVALIDATE_NOTIFICATION_EMAIL;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.PROTOVALIDATE_NOTIFICATION_NONE;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.PROTOVALIDATE_NOTIFICATION_WEBHOOK;
+
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.State;
+
+/** Shared complete scenario parameter for the two paired representations. */
+@State(Scope.Benchmark)
+public abstract class RealWorldPairedWorkloadState {
+ @Param({
+ IAM_PREFIX_HIT,
+ IAM_PREFIX_TYPE_MISS,
+ IAM_PREFIX_NAME_MISS,
+ ORG_MEMBERS_EMPTY,
+ ORG_MEMBERS_ONE,
+ ORG_MEMBERS_FAIL_FIRST_8,
+ ORG_MEMBERS_FAIL_LAST_8,
+ ORG_MEMBERS_ALL_32,
+ ORG_BINDINGS_ALL_8_X_8,
+ ORG_BINDINGS_FAIL_LAST_8_X_8,
+ GATEWAY_EMPTY,
+ GATEWAY_ONE,
+ GATEWAY_UNIQUE_8,
+ GATEWAY_UNIQUE_16,
+ GATEWAY_DUPLICATE_FIRST_16,
+ GATEWAY_DUPLICATE_LAST_16,
+ GATEWAY_HOSTNAME_16,
+ DRA_MATCH,
+ DRA_COLOR_MISS,
+ DRA_SIZE_MISS,
+ DRA_UNRELATED_32,
+ FLUX_NO_CONDITIONS,
+ FLUX_NO_READY_8,
+ FLUX_READY_ONE,
+ FLUX_READY_ALL_32,
+ FLUX_FAIL_FIRST_32,
+ FLUX_FAIL_LAST_32,
+ DAPR_TYPED_IMPORTANT,
+ DAPR_TYPED_ABSENT,
+ DAPR_TYPED_DEPOSIT,
+ PROTOVALIDATE_BOOKING_HYBRID,
+ PROTOVALIDATE_BOOKING_REGION,
+ PROTOVALIDATE_BOOKING_MISSING,
+ PROTOVALIDATE_INTERVAL_ABSENT,
+ PROTOVALIDATE_INTERVAL_ORDERED,
+ PROTOVALIDATE_INTERVAL_REVERSED,
+ PROTOVALIDATE_NOTIFICATION_WEBHOOK,
+ PROTOVALIDATE_NOTIFICATION_EMAIL,
+ PROTOVALIDATE_NOTIFICATION_NONE
+ })
+ public String scenarioId;
+
+ RealWorldProgramSet programs;
+}
diff --git a/benchmarks/src/jmh/java/org/projectnessie/cel/RealWorldProtoWorkloadBench.java b/benchmarks/src/jmh/java/org/projectnessie/cel/RealWorldProtoWorkloadBench.java
new file mode 100644
index 00000000..65aed687
--- /dev/null
+++ b/benchmarks/src/jmh/java/org/projectnessie/cel/RealWorldProtoWorkloadBench.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2026 The Authors of CEL-Java
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.projectnessie.cel;
+
+import java.util.concurrent.TimeUnit;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Threads;
+import org.openjdk.jmh.annotations.Warmup;
+import org.projectnessie.cel.benchmark.RealWorldProtoFixtures;
+import org.projectnessie.cel.benchmark.RealWorldWorkloads;
+
+/** Complete-program generated-pb3 representation workloads. */
+@Warmup(iterations = 3, time = 500, timeUnit = TimeUnit.MILLISECONDS)
+@Measurement(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS)
+@Fork(3)
+@Threads(1)
+@BenchmarkMode(Mode.AverageTime)
+@OutputTimeUnit(TimeUnit.NANOSECONDS)
+public class RealWorldProtoWorkloadBench {
+ @State(Scope.Benchmark)
+ public static class WorkloadState extends RealWorldPairedWorkloadState {
+ @Setup
+ public void setup() {
+ var scenario = RealWorldWorkloads.scenario(scenarioId);
+ programs =
+ RealWorldProgramSet.protobuf(
+ scenario,
+ RealWorldProtoFixtures.prepare(scenario),
+ RealWorldProtoFixtures.registeredTypes(scenario.family()));
+ }
+ }
+
+ @Benchmark
+ public Boolean exactNative(WorkloadState state) {
+ return state.programs.exactNative();
+ }
+
+ @Benchmark
+ public Boolean exactDisabled(WorkloadState state) {
+ return state.programs.exactDisabled();
+ }
+
+ @Benchmark
+ public Boolean general(WorkloadState state) {
+ return state.programs.general();
+ }
+
+ @Benchmark
+ public Boolean direct(WorkloadState state) {
+ return state.programs.direct();
+ }
+}
diff --git a/benchmarks/src/main/java/org/projectnessie/cel/RealWorldProgramSet.java b/benchmarks/src/main/java/org/projectnessie/cel/RealWorldProgramSet.java
new file mode 100644
index 00000000..e72d30c4
--- /dev/null
+++ b/benchmarks/src/main/java/org/projectnessie/cel/RealWorldProgramSet.java
@@ -0,0 +1,599 @@
+/*
+ * Copyright (C) 2026 The Authors of CEL-Java
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.projectnessie.cel;
+
+import static org.projectnessie.cel.Env.newCustomEnv;
+import static org.projectnessie.cel.Env.newEnv;
+import static org.projectnessie.cel.EnvOption.customTypeAdapter;
+import static org.projectnessie.cel.EnvOption.customTypeProvider;
+import static org.projectnessie.cel.EnvOption.declarations;
+import static org.projectnessie.cel.EnvOption.types;
+import static org.projectnessie.cel.EvalOption.OptDisableNativeEval;
+import static org.projectnessie.cel.EvalOption.OptOptimize;
+import static org.projectnessie.cel.ProgramOption.evalOptions;
+
+import com.google.protobuf.Message;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.function.BooleanSupplier;
+import java.util.function.Supplier;
+import org.projectnessie.cel.benchmark.PreparedFixture;
+import org.projectnessie.cel.benchmark.RealWorldPojoFixtures.Booking;
+import org.projectnessie.cel.benchmark.RealWorldPojoFixtures.CloudEvent;
+import org.projectnessie.cel.benchmark.RealWorldPojoFixtures.Device;
+import org.projectnessie.cel.benchmark.RealWorldPojoFixtures.GatewayAddress;
+import org.projectnessie.cel.benchmark.RealWorldPojoFixtures.KubernetesResource;
+import org.projectnessie.cel.benchmark.RealWorldPojoFixtures.Notification;
+import org.projectnessie.cel.benchmark.RealWorldPojoFixtures.OrganizationResource;
+import org.projectnessie.cel.benchmark.RealWorldPojoFixtures.PolicyResource;
+import org.projectnessie.cel.benchmark.RealWorldPojoFixtures.TraceInterval;
+import org.projectnessie.cel.benchmark.RealWorldWorkloads.Family;
+import org.projectnessie.cel.benchmark.RealWorldWorkloads.Representation;
+import org.projectnessie.cel.benchmark.RealWorldWorkloads.Scenario;
+import org.projectnessie.cel.checker.Decls;
+import org.projectnessie.cel.common.types.pb.DefaultTypeAdapter;
+import org.projectnessie.cel.common.types.pb.ProtoTypeRegistry;
+import org.projectnessie.cel.common.types.ref.ExactAggregateTypeAdapter;
+import org.projectnessie.cel.common.types.ref.StandardScalarTypeAdapter;
+import org.projectnessie.cel.common.types.ref.TypeRegistry;
+import org.projectnessie.cel.common.types.ref.Val;
+import org.projectnessie.cel.types.jackson3.Jackson3Registry;
+
+/** The three reusable CEL program modes and direct control for one Boolean scenario. */
+public final class RealWorldProgramSet {
+ public record ProgramModes(Program exactNative, Program exactDisabled, Program general) {}
+
+ /**
+ * Reusable environment and fixture for measuring compilation, planning, and the first evaluation
+ * of a newly constructed program.
+ *
+ *
The compilation methods include parsing and checking. Compilation and planning retain an
+ * environment because applications normally compile multiple expressions against one configured
+ * environment. The {@code cold*()} methods create a fresh environment, checked AST, and program
+ * before evaluating it once; they do not represent whole-JVM startup.
+ */
+ public static final class Lifecycle {
+ private final Supplier exactEnvFactory;
+ private final Supplier generalEnvFactory;
+ private final Env exactEnv;
+ private final Env generalEnv;
+ private final List expressions;
+ private final List exactAsts;
+ private final List generalAsts;
+ private final Map activation;
+ private final Class> resultClass;
+ private final boolean expected;
+ private final String scenarioId;
+
+ private Lifecycle(
+ Supplier exactEnvFactory,
+ Supplier generalEnvFactory,
+ List expressions,
+ PreparedFixture fixture,
+ boolean expected,
+ String scenarioId) {
+ this.exactEnvFactory = exactEnvFactory;
+ this.generalEnvFactory = generalEnvFactory;
+ this.exactEnv = exactEnvFactory.get();
+ this.generalEnv = generalEnvFactory.get();
+ this.expressions = expressions;
+ this.exactAsts = compile(exactEnv, expressions);
+ this.generalAsts = compile(generalEnv, expressions);
+ this.activation = fixture.activation();
+ this.resultClass = fixture.resultClass();
+ this.expected = expected;
+ this.scenarioId = scenarioId;
+ verify();
+ }
+
+ public List compileExact() {
+ return compile(exactEnv, expressions);
+ }
+
+ public List compileGeneral() {
+ return compile(generalEnv, expressions);
+ }
+
+ public List planExactNative() {
+ return plan(exactEnv, exactAsts, OptOptimize);
+ }
+
+ public List planExactDisabled() {
+ return plan(exactEnv, exactAsts, OptOptimize, OptDisableNativeEval);
+ }
+
+ public List planGeneral() {
+ return plan(generalEnv, generalAsts, OptOptimize);
+ }
+
+ public Boolean coldExactNative() {
+ return compilePlanEvaluate(
+ exactEnvFactory.get(), expressions, activation, resultClass, OptOptimize);
+ }
+
+ public Boolean coldExactDisabled() {
+ return compilePlanEvaluate(
+ exactEnvFactory.get(),
+ expressions,
+ activation,
+ resultClass,
+ OptOptimize,
+ OptDisableNativeEval);
+ }
+
+ public Boolean coldGeneral() {
+ return compilePlanEvaluate(
+ generalEnvFactory.get(), expressions, activation, resultClass, OptOptimize);
+ }
+
+ private void verify() {
+ Boolean nativeResult = coldExactNative();
+ Boolean disabledResult = coldExactDisabled();
+ Boolean generalResult = coldGeneral();
+ if (nativeResult != expected || disabledResult != expected || generalResult != expected) {
+ throw new IllegalStateException(
+ "Lifecycle scenario "
+ + scenarioId
+ + " mismatch: expected="
+ + expected
+ + ", exactNative="
+ + nativeResult
+ + ", exactDisabled="
+ + disabledResult
+ + ", general="
+ + generalResult);
+ }
+ }
+ }
+
+ private final List exactNative;
+ private final List exactDisabled;
+ private final List general;
+ private final Map activation;
+ private final BooleanSupplier direct;
+ private final boolean expected;
+ private final Class> resultClass;
+ private final String scenarioId;
+
+ private RealWorldProgramSet(
+ List exactNative,
+ List exactDisabled,
+ List general,
+ PreparedFixture fixture,
+ boolean expected,
+ String scenarioId) {
+ this.exactNative = List.copyOf(exactNative);
+ this.exactDisabled = List.copyOf(exactDisabled);
+ this.general = List.copyOf(general);
+ this.activation = fixture.activation();
+ this.direct = fixture.direct();
+ this.expected = expected;
+ this.resultClass = fixture.resultClass();
+ this.scenarioId = scenarioId;
+ verify();
+ }
+
+ public static RealWorldProgramSet host(Scenario scenario, PreparedFixture fixture) {
+ if (!scenario.representations().contains(Representation.HOST)) {
+ throw new IllegalArgumentException("Not a host scenario " + scenario.id());
+ }
+ requireResultClass(scenario, fixture);
+ Env exactEnv = hostExactEnv(scenario.family());
+ Env generalEnv = hostGeneralEnv(scenario.family());
+ List exactNative = new ArrayList<>();
+ List exactDisabled = new ArrayList<>();
+ List general = new ArrayList<>();
+ for (String expression : scenario.expressions(Representation.HOST)) {
+ Ast exactAst = compile(exactEnv, expression);
+ exactNative.add(exactEnv.program(exactAst, evalOptions(OptOptimize)));
+ exactDisabled.add(exactEnv.program(exactAst, evalOptions(OptOptimize, OptDisableNativeEval)));
+ Ast generalAst = compile(generalEnv, expression);
+ general.add(generalEnv.program(generalAst, evalOptions(OptOptimize)));
+ }
+ return new RealWorldProgramSet(
+ exactNative, exactDisabled, general, fixture, scenario.expected(), scenario.id());
+ }
+
+ public static ProgramModes hostPrograms(Family family, String expression) {
+ Env exactEnv = hostExactEnv(family);
+ Ast exactAst = compile(exactEnv, expression);
+ Program exactNative = exactEnv.program(exactAst, evalOptions(OptOptimize));
+ Program exactDisabled =
+ exactEnv.program(exactAst, evalOptions(OptOptimize, OptDisableNativeEval));
+ Env generalEnv = hostGeneralEnv(family);
+ Program general = generalEnv.program(compile(generalEnv, expression), evalOptions(OptOptimize));
+ return new ProgramModes(exactNative, exactDisabled, general);
+ }
+
+ public static Lifecycle hostLifecycle(Scenario scenario, PreparedFixture fixture) {
+ if (!scenario.representations().contains(Representation.HOST)) {
+ throw new IllegalArgumentException("Not a host scenario " + scenario.id());
+ }
+ requireResultClass(scenario, fixture);
+ Supplier exactEnvFactory = () -> hostExactEnv(scenario.family());
+ Supplier generalEnvFactory = () -> hostGeneralEnv(scenario.family());
+ return new Lifecycle(
+ exactEnvFactory,
+ generalEnvFactory,
+ scenario.expressions(Representation.HOST),
+ fixture,
+ scenario.expected(),
+ scenario.id());
+ }
+
+ public static RealWorldProgramSet protobuf(
+ Scenario scenario, PreparedFixture fixture, Message... registeredTypes) {
+ Env exactEnv = protobufEnv(scenario, true, registeredTypes);
+ Env generalEnv = protobufEnv(scenario, false, registeredTypes);
+ return structured(scenario, fixture, Representation.PROTOBUF, exactEnv, generalEnv);
+ }
+
+ public static ProgramModes protobufPrograms(Scenario scenario, Message... registeredTypes) {
+ Env exactEnv = protobufEnv(scenario, true, registeredTypes);
+ Env generalEnv = protobufEnv(scenario, false, registeredTypes);
+ return programModes(scenario.expressions(Representation.PROTOBUF).get(0), exactEnv, generalEnv);
+ }
+
+ public static Lifecycle protobufLifecycle(
+ Scenario scenario, PreparedFixture fixture, Message... registeredTypes) {
+ requireResultClass(scenario, fixture);
+ Supplier exactEnvFactory = () -> protobufEnv(scenario, true, registeredTypes);
+ Supplier generalEnvFactory = () -> protobufEnv(scenario, false, registeredTypes);
+ return new Lifecycle(
+ exactEnvFactory,
+ generalEnvFactory,
+ scenario.expressions(Representation.PROTOBUF),
+ fixture,
+ scenario.expected(),
+ scenario.id());
+ }
+
+ public static RealWorldProgramSet jackson3(
+ Scenario scenario, PreparedFixture fixture, Class>... registeredTypes) {
+ Env exactEnv = jackson3Env(scenario, true, registeredTypes);
+ Env generalEnv = jackson3Env(scenario, false, registeredTypes);
+ return structured(scenario, fixture, Representation.JACKSON3, exactEnv, generalEnv);
+ }
+
+ public static ProgramModes jackson3Programs(Scenario scenario, Class>... registeredTypes) {
+ Env exactEnv = jackson3Env(scenario, true, registeredTypes);
+ Env generalEnv = jackson3Env(scenario, false, registeredTypes);
+ return programModes(scenario.expressions(Representation.JACKSON3).get(0), exactEnv, generalEnv);
+ }
+
+ public static Lifecycle jackson3Lifecycle(
+ Scenario scenario, PreparedFixture fixture, Class>... registeredTypes) {
+ requireResultClass(scenario, fixture);
+ Supplier exactEnvFactory = () -> jackson3Env(scenario, true, registeredTypes);
+ Supplier generalEnvFactory = () -> jackson3Env(scenario, false, registeredTypes);
+ return new Lifecycle(
+ exactEnvFactory,
+ generalEnvFactory,
+ scenario.expressions(Representation.JACKSON3),
+ fixture,
+ scenario.expected(),
+ scenario.id());
+ }
+
+ public Boolean exactNative() {
+ return evaluate(exactNative, activation, resultClass);
+ }
+
+ public Boolean exactDisabled() {
+ return evaluate(exactDisabled, activation, resultClass);
+ }
+
+ public Boolean general() {
+ return evaluate(general, activation, resultClass);
+ }
+
+ public Boolean direct() {
+ return direct.getAsBoolean();
+ }
+
+ public boolean expected() {
+ return expected;
+ }
+
+ public static Boolean evaluate(Program program, Map activation) {
+ return evaluate(program, activation, Boolean.class);
+ }
+
+ private static Boolean evaluate(
+ Program program, Map activation, Class> resultClass) {
+ Program.EvalResult result = program.eval(activation);
+ return (Boolean) ((Prog) program).e.adapter.valueToNative(result.getVal(), resultClass);
+ }
+
+ private static Boolean evaluate(
+ List programs, Map activation, Class> resultClass) {
+ if (programs.size() == 1) {
+ return evaluate(programs.get(0), activation, resultClass);
+ }
+ for (Program program : programs) {
+ if (evaluate(program, activation, resultClass)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void verify() {
+ Boolean nativeResult = exactNative();
+ Boolean disabledResult = exactDisabled();
+ Boolean generalResult = general();
+ Boolean directResult = direct();
+ if (nativeResult != expected
+ || disabledResult != expected
+ || generalResult != expected
+ || directResult != expected) {
+ throw new IllegalStateException(
+ "Scenario "
+ + scenarioId
+ + " mismatch: expected="
+ + expected
+ + ", exactNative="
+ + nativeResult
+ + ", exactDisabled="
+ + disabledResult
+ + ", general="
+ + generalResult
+ + ", direct="
+ + directResult);
+ }
+ }
+
+ private static RealWorldProgramSet structured(
+ Scenario scenario,
+ PreparedFixture fixture,
+ Representation representation,
+ Env exactEnv,
+ Env generalEnv) {
+ requireResultClass(scenario, fixture);
+ List exactNative = new ArrayList<>();
+ List exactDisabled = new ArrayList<>();
+ List general = new ArrayList<>();
+ for (String expression : scenario.expressions(representation)) {
+ Ast exactAst = compile(exactEnv, expression);
+ exactNative.add(exactEnv.program(exactAst, evalOptions(OptOptimize)));
+ exactDisabled.add(exactEnv.program(exactAst, evalOptions(OptOptimize, OptDisableNativeEval)));
+ general.add(generalEnv.program(compile(generalEnv, expression), evalOptions(OptOptimize)));
+ }
+ return new RealWorldProgramSet(
+ exactNative, exactDisabled, general, fixture, scenario.expected(), scenario.id());
+ }
+
+ private static ProgramModes programModes(String expression, Env exactEnv, Env generalEnv) {
+ Ast exactAst = compile(exactEnv, expression);
+ return new ProgramModes(
+ exactEnv.program(exactAst, evalOptions(OptOptimize)),
+ exactEnv.program(exactAst, evalOptions(OptOptimize, OptDisableNativeEval)),
+ generalEnv.program(compile(generalEnv, expression), evalOptions(OptOptimize)));
+ }
+
+ private static List compile(Env env, List expressions) {
+ List asts = new ArrayList<>(expressions.size());
+ for (String expression : expressions) {
+ asts.add(compile(env, expression));
+ }
+ return asts;
+ }
+
+ private static List plan(Env env, List asts, EvalOption... options) {
+ List programs = new ArrayList<>(asts.size());
+ for (Ast ast : asts) {
+ programs.add(env.program(ast, evalOptions(options)));
+ }
+ return programs;
+ }
+
+ private static Boolean compilePlanEvaluate(
+ Env env,
+ List expressions,
+ Map activation,
+ Class> resultClass,
+ EvalOption... options) {
+ return evaluate(plan(env, compile(env, expressions), options), activation, resultClass);
+ }
+
+ private static Env hostExactEnv(Family family) {
+ return newEnv(
+ customTypeAdapter(new ExactHostAdapter()), declarations(hostDeclarations(family)));
+ }
+
+ private static Env hostGeneralEnv(Family family) {
+ return newEnv(
+ customTypeAdapter(DefaultTypeAdapter.Instance), declarations(hostDeclarations(family)));
+ }
+
+ private static Env protobufEnv(Scenario scenario, boolean exact, Message... registeredTypes) {
+ TypeRegistry registry =
+ exact
+ ? ProtoTypeRegistry.newExactAggregateRegistry(registeredTypes)
+ : ProtoTypeRegistry.newRegistry(registeredTypes);
+ return newCustomEnv(
+ registry,
+ List.of(
+ Library.StdLib(),
+ declarations(structuredDeclarations(scenario.family(), Representation.PROTOBUF))));
+ }
+
+ private static Env jackson3Env(Scenario scenario, boolean exact, Class>... registeredTypes) {
+ TypeRegistry registry =
+ exact ? Jackson3Registry.newExactAggregateRegistry() : Jackson3Registry.newRegistry();
+ return newEnv(
+ customTypeAdapter(registry),
+ customTypeProvider(registry),
+ types((Object[]) registeredTypes),
+ declarations(structuredDeclarations(scenario.family(), Representation.JACKSON3)));
+ }
+
+ private static void requireResultClass(Scenario scenario, PreparedFixture fixture) {
+ if (!scenario.resultClass().equals(fixture.resultClass())) {
+ throw new IllegalArgumentException(
+ "Scenario "
+ + scenario.id()
+ + " declares "
+ + scenario.resultClass().getName()
+ + " but fixture declares "
+ + fixture.resultClass().getName());
+ }
+ }
+
+ private static com.google.api.expr.v1alpha1.Decl[] hostDeclarations(Family family) {
+ return switch (family) {
+ case POLARIS ->
+ new com.google.api.expr.v1alpha1.Decl[] {
+ Decls.newVar("ref", Decls.String),
+ Decls.newVar("commits", Decls.Int),
+ Decls.newVar("ageMinutes", Decls.Int),
+ Decls.newVar("ageHours", Decls.Int),
+ Decls.newVar("ageDays", Decls.Int)
+ };
+ case NESSIE ->
+ new com.google.api.expr.v1alpha1.Decl[] {
+ Decls.newVar("op", Decls.String),
+ Decls.newVar("role", Decls.String),
+ Decls.newVar("roles", Decls.newListType(Decls.String)),
+ Decls.newVar("ref", Decls.String),
+ Decls.newVar("path", Decls.String),
+ Decls.newVar("contentType", Decls.String)
+ };
+ case OPENFGA ->
+ new com.google.api.expr.v1alpha1.Decl[] {
+ Decls.newVar("current_time", Decls.Timestamp),
+ Decls.newVar("grant_time", Decls.Timestamp),
+ Decls.newVar("grant_duration", Decls.Duration)
+ };
+ case DAPR_HOST -> new com.google.api.expr.v1alpha1.Decl[] {Decls.newVar("event", Decls.Dyn)};
+ default -> throw new IllegalArgumentException("Not a host family " + family);
+ };
+ }
+
+ private static com.google.api.expr.v1alpha1.Decl[] structuredDeclarations(
+ Family family, Representation representation) {
+ return switch (family) {
+ case IAM ->
+ new com.google.api.expr.v1alpha1.Decl[] {
+ Decls.newVar(
+ "resource",
+ Decls.newObjectType(
+ representation == Representation.PROTOBUF
+ ? org.projectnessie.cel.benchmark.proto.PolicyResource.getDescriptor()
+ .getFullName()
+ : PolicyResource.class.getName()))
+ };
+ case DRA ->
+ new com.google.api.expr.v1alpha1.Decl[] {
+ Decls.newVar(
+ "device",
+ Decls.newObjectType(
+ representation == Representation.PROTOBUF
+ ? org.projectnessie.cel.benchmark.proto.Device.getDescriptor().getFullName()
+ : Device.class.getName()))
+ };
+ case ORGANIZATION ->
+ new com.google.api.expr.v1alpha1.Decl[] {
+ Decls.newVar(
+ "resource",
+ Decls.newObjectType(
+ representation == Representation.PROTOBUF
+ ? org.projectnessie.cel.benchmark.proto.OrganizationResource.getDescriptor()
+ .getFullName()
+ : OrganizationResource.class.getName()))
+ };
+ case GATEWAY ->
+ new com.google.api.expr.v1alpha1.Decl[] {
+ Decls.newVar(
+ "self",
+ Decls.newListType(
+ Decls.newObjectType(
+ representation == Representation.PROTOBUF
+ ? org.projectnessie.cel.benchmark.proto.GatewayAddress.getDescriptor()
+ .getFullName()
+ : GatewayAddress.class.getName())))
+ };
+ case FLUX ->
+ new com.google.api.expr.v1alpha1.Decl[] {
+ Decls.newVar(
+ "resource",
+ Decls.newObjectType(
+ representation == Representation.PROTOBUF
+ ? org.projectnessie.cel.benchmark.proto.KubernetesResource.getDescriptor()
+ .getFullName()
+ : KubernetesResource.class.getName()))
+ };
+ case DAPR_TYPED ->
+ new com.google.api.expr.v1alpha1.Decl[] {
+ Decls.newVar(
+ "event",
+ Decls.newObjectType(
+ representation == Representation.PROTOBUF
+ ? org.projectnessie.cel.benchmark.proto.CloudEvent.getDescriptor()
+ .getFullName()
+ : CloudEvent.class.getName()))
+ };
+ case PROTOVALIDATE_BOOKING ->
+ new com.google.api.expr.v1alpha1.Decl[] {
+ Decls.newVar(
+ "this",
+ Decls.newObjectType(
+ representation == Representation.PROTOBUF
+ ? org.projectnessie.cel.benchmark.proto.Booking.getDescriptor()
+ .getFullName()
+ : Booking.class.getName()))
+ };
+ case PROTOVALIDATE_INTERVAL ->
+ new com.google.api.expr.v1alpha1.Decl[] {
+ Decls.newVar(
+ "this",
+ Decls.newObjectType(
+ representation == Representation.PROTOBUF
+ ? org.projectnessie.cel.benchmark.proto.TraceInterval.getDescriptor()
+ .getFullName()
+ : TraceInterval.class.getName()))
+ };
+ case PROTOVALIDATE_NOTIFICATION ->
+ new com.google.api.expr.v1alpha1.Decl[] {
+ Decls.newVar(
+ "this",
+ Decls.newObjectType(
+ representation == Representation.PROTOBUF
+ ? org.projectnessie.cel.benchmark.proto.Notification.getDescriptor()
+ .getFullName()
+ : Notification.class.getName()))
+ };
+ default -> throw new IllegalArgumentException("Not yet a structured family " + family);
+ };
+ }
+
+ private static Ast compile(Env env, String expression) {
+ Env.AstIssuesTuple result = env.compile(expression);
+ if (result.hasIssues()) {
+ throw new IllegalStateException(expression + ": " + result.getIssues());
+ }
+ return result.getAst();
+ }
+
+ private static final class ExactHostAdapter
+ implements ExactAggregateTypeAdapter, StandardScalarTypeAdapter {
+ @Override
+ public Val nativeToValue(Object value) {
+ return DefaultTypeAdapter.Instance.nativeToValue(value);
+ }
+ }
+}
diff --git a/benchmarks/src/main/java/org/projectnessie/cel/benchmark/PreparedFixture.java b/benchmarks/src/main/java/org/projectnessie/cel/benchmark/PreparedFixture.java
new file mode 100644
index 00000000..1f1af78a
--- /dev/null
+++ b/benchmarks/src/main/java/org/projectnessie/cel/benchmark/PreparedFixture.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2026 The Authors of CEL-Java
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.projectnessie.cel.benchmark;
+
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.function.BooleanSupplier;
+
+/** Already-constructed activation and direct-Java decision for one scenario. */
+public record PreparedFixture(
+ Map activation, Class> resultClass, BooleanSupplier direct) {
+ public PreparedFixture(Map activation, BooleanSupplier direct) {
+ this(activation, Boolean.class, direct);
+ }
+
+ public PreparedFixture {
+ activation = Collections.unmodifiableMap(new LinkedHashMap<>(activation));
+ }
+}
diff --git a/benchmarks/src/main/java/org/projectnessie/cel/benchmark/RealWorldHostFixtures.java b/benchmarks/src/main/java/org/projectnessie/cel/benchmark/RealWorldHostFixtures.java
new file mode 100644
index 00000000..7cf2dfd6
--- /dev/null
+++ b/benchmarks/src/main/java/org/projectnessie/cel/benchmark/RealWorldHostFixtures.java
@@ -0,0 +1,347 @@
+/*
+ * Copyright (C) 2026 The Authors of CEL-Java
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.projectnessie.cel.benchmark;
+
+import com.google.protobuf.Duration;
+import com.google.protobuf.Timestamp;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.BooleanSupplier;
+import java.util.regex.Pattern;
+import org.projectnessie.cel.benchmark.RealWorldWorkloads.Scenario;
+
+/** Builds source-host activation fixtures and their direct-Java semantic controls. */
+public final class RealWorldHostFixtures {
+ private static final Pattern MATCH_ALL = Pattern.compile(".*");
+ private static final Set NESSIE_ADMIN_OPERATIONS =
+ Set.of(
+ "VIEW_REFERENCE",
+ "CREATE_REFERENCE",
+ "DELETE_REFERENCE",
+ "VIEW_REFLOG",
+ "LIST_COMMITLOG",
+ "READ_ENTRIES",
+ "READ_CONTENT_KEY",
+ "LIST_COMMIT_LOG",
+ "COMMIT_CHANGE_AGAINST_REFERENCE",
+ "ASSIGN_REFERENCE_TO_HASH",
+ "CREATE_ENTITY",
+ "UPDATE_ENTITY",
+ "READ_ENTITY_VALUE",
+ "DELETE_ENTITY");
+ private static final Set NESSIE_BRANCH_OPERATIONS =
+ Set.of(
+ "CREATE_REFERENCE",
+ "DELETE_REFERENCE",
+ "LIST_COMMIT_LOG",
+ "READ_ENTRIES",
+ "READ_CONTENT_KEY",
+ "ASSIGN_REFERENCE_TO_HASH");
+ private static final Set NESSIE_USER1_OPERATIONS =
+ Set.of(
+ "VIEW_REFERENCE",
+ "ASSIGN_REFERENCE_TO_HASH",
+ "COMMIT_CHANGE_AGAINST_REFERENCE",
+ "DELETE_REFERENCE");
+ private static final Set NESSIE_USER2_OPERATIONS =
+ Set.of("VIEW_REFERENCE", "CREATE_ENTITY", "UPDATE_ENTITY");
+ private static final Set NESSIE_USER3_OPERATIONS =
+ Set.of("VIEW_REFERENCE", "DELETE_ENTITY_VALUE", "CREATE_ENTITY", "UPDATE_ENTITY");
+ private static final Set NESSIE_USER4_OPERATIONS =
+ Set.of("VIEW_REFERENCE", "READ_ENTITY_VALUE", "DELETE_ENTITY");
+ private static final Set NESSIE_DELETE_BRANCH_OPERATIONS =
+ Set.of("VIEW_REFERENCE", "CREATE_REFERENCE");
+ private static final Set NESSIE_DELETE_BRANCH_REFS =
+ Set.of("testDeleteBranchDisallowed", "main");
+
+ private RealWorldHostFixtures() {}
+
+ public static PreparedFixture prepare(Scenario scenario) {
+ return switch (scenario.family()) {
+ case POLARIS -> polaris(scenario);
+ case NESSIE -> nessie(scenario);
+ case OPENFGA -> openFga(scenario);
+ case DAPR_HOST -> dapr(scenario);
+ default -> throw new IllegalArgumentException("Not a host scenario " + scenario.id());
+ };
+ }
+
+ private static PreparedFixture polaris(Scenario scenario) {
+ long commits;
+ long ageDays;
+ switch (scenario.id()) {
+ case "polaris.constant.false" -> {
+ commits = 1L;
+ ageDays = 0L;
+ }
+ case "polaris.cutoff.left" -> {
+ commits = 12L;
+ ageDays = 29L;
+ }
+ case "polaris.cutoff.right" -> {
+ commits = 10L;
+ ageDays = 30L;
+ }
+ case "polaris.cutoff.stop" -> {
+ commits = 11L;
+ ageDays = 30L;
+ }
+ default -> throw new IllegalArgumentException(scenario.id());
+ }
+ Map activation =
+ Map.of(
+ "ref",
+ "principals",
+ "commits",
+ commits,
+ "ageMinutes",
+ ageDays * 24L * 60L,
+ "ageHours",
+ ageDays * 24L,
+ "ageDays",
+ ageDays);
+ BooleanSupplier direct =
+ scenario.id().equals("polaris.constant.false")
+ ? () -> false
+ : () -> ageDays < 30L || commits <= 10L;
+ return new PreparedFixture(activation, direct);
+ }
+
+ private static PreparedFixture nessie(Scenario scenario) {
+ String op = "";
+ String role = "";
+ List roles = List.of();
+ String ref = "";
+ String path = "";
+ switch (scenario.id()) {
+ case "nessie.default.allow" -> {
+ op = "VIEW_REFERENCE";
+ ref = "main";
+ }
+ case "nessie.default.deny" -> {
+ op = "CREATE_REFERENCE";
+ ref = "main";
+ }
+ case "nessie.roles.hitLate" -> {
+ List values = new ArrayList<>(32);
+ for (int i = 0; i < 31; i++) {
+ values.add("role-" + i);
+ }
+ values.add("bar");
+ roles = List.copyOf(values);
+ }
+ case "nessie.roles.miss" -> {
+ List values = new ArrayList<>(32);
+ for (int i = 0; i < 32; i++) {
+ values.add("role-" + i);
+ }
+ roles = List.copyOf(values);
+ }
+ case "nessie.rules.first" -> {
+ op = "VIEW_REFERENCE";
+ role = "admin_user";
+ ref = "main";
+ }
+ case "nessie.rules.middle" -> {
+ op = "CREATE_ENTITY";
+ role = "test_user3";
+ ref = "allowedBranch-middle";
+ path = "allowed-content";
+ }
+ case "nessie.rules.late" -> {
+ op = "VIEW_REFERENCE";
+ role = "user1";
+ ref = "main";
+ }
+ case "nessie.rules.deny" -> {
+ op = "DELETE_REFERENCE";
+ role = "unmatched";
+ ref = "deniedBranch";
+ }
+ default -> throw new IllegalArgumentException(scenario.id());
+ }
+
+ Map activation =
+ Map.of(
+ "op", op,
+ "role", role,
+ "roles", roles,
+ "ref", ref,
+ "path", path,
+ "contentType", "");
+ BooleanSupplier direct =
+ switch (scenario.id()) {
+ case "nessie.default.allow", "nessie.default.deny" ->
+ () ->
+ ((String) activation.get("op")).equals("VIEW_REFERENCE")
+ && MATCH_ALL.matcher((String) activation.get("ref")).find();
+ case "nessie.roles.hitLate", "nessie.roles.miss" ->
+ () -> ((List>) activation.get("roles")).contains("bar");
+ default -> () -> nessieRules(activation);
+ };
+ return new PreparedFixture(activation, direct);
+ }
+
+ private static boolean nessieRules(Map activation) {
+ String op = (String) activation.get("op");
+ String role = (String) activation.get("role");
+ String ref = (String) activation.get("ref");
+ String path = (String) activation.get("path");
+ if (NESSIE_ADMIN_OPERATIONS.contains(op) && role.equals("admin_user")) {
+ return true;
+ }
+ if (op.equals("VIEW_REFERENCE")
+ && role.startsWith("test_user")
+ && MATCH_ALL.matcher(ref).find()) {
+ return true;
+ }
+ if (NESSIE_BRANCH_OPERATIONS.contains(op)
+ && role.startsWith("test_user")
+ && ref.startsWith("allowedBranch")) {
+ return true;
+ }
+ if (op.equals("COMMIT_CHANGE_AGAINST_REFERENCE")
+ && role.startsWith("test_user")
+ && ref.startsWith("allowedBranch")) {
+ return true;
+ }
+ if (NESSIE_USER2_OPERATIONS.contains(op)
+ && role.equals("test_user2")
+ && path.startsWith("allowed-")
+ && ref.startsWith("allowedBranch")) {
+ return true;
+ }
+ if (NESSIE_USER3_OPERATIONS.contains(op)
+ && role.equals("test_user3")
+ && path.startsWith("allowed-")
+ && ref.startsWith("allowedBranch")) {
+ return true;
+ }
+ if (NESSIE_USER4_OPERATIONS.contains(op)
+ && role.equals("test_user4")
+ && path.startsWith("allowed-")
+ && ref.startsWith("allowedBranch")) {
+ return true;
+ }
+ if (op.equals("COMMIT_CHANGE_AGAINST_REFERENCE")
+ && role.equals("test_user2")
+ && ref.startsWith("allowedBranch")) {
+ return true;
+ }
+ if (op.equals("CREATE_REFERENCE") && role.equals("user1") && MATCH_ALL.matcher(ref).find()) {
+ return true;
+ }
+ if (NESSIE_USER1_OPERATIONS.contains(op)
+ && role.equals("user1")
+ && (ref.startsWith("allowedBranch") || ref.equals("main"))) {
+ return true;
+ }
+ return NESSIE_DELETE_BRANCH_OPERATIONS.contains(op)
+ && role.equals("delete_branch_disallowed_user")
+ && NESSIE_DELETE_BRANCH_REFS.contains(ref);
+ }
+
+ private static PreparedFixture openFga(Scenario scenario) {
+ Instant grant = Instant.parse("2026-01-01T00:00:00Z");
+ java.time.Duration duration = java.time.Duration.ofHours(1L);
+ Instant cutoff = grant.plus(duration);
+ Instant current =
+ switch (scenario.id()) {
+ case "openfga.before" -> cutoff.minusNanos(1L);
+ case "openfga.equal" -> cutoff;
+ case "openfga.after" -> cutoff.plusNanos(1L);
+ default -> throw new IllegalArgumentException(scenario.id());
+ };
+ Map activation =
+ Map.of(
+ "current_time",
+ timestamp(current),
+ "grant_time",
+ timestamp(grant),
+ "grant_duration",
+ duration(duration));
+ return new PreparedFixture(activation, () -> current.isBefore(grant.plus(duration)));
+ }
+
+ private static PreparedFixture dapr(Scenario scenario) {
+ String type;
+ Map data;
+ switch (scenario.id()) {
+ case "dapr.type.hit" -> {
+ type = "widget";
+ data = Map.of();
+ }
+ case "dapr.type.miss" -> {
+ type = "other";
+ data = Map.of();
+ }
+ case "dapr.important.hit" -> {
+ type = "other";
+ data = Map.of("important", true);
+ }
+ case "dapr.important.absent" -> {
+ type = "other";
+ data = Map.of();
+ }
+ case "dapr.deposit.hit" -> {
+ type = "deposit";
+ data = Map.of("amount", "10001");
+ }
+ case "dapr.deposit.boundary" -> {
+ type = "deposit";
+ data = Map.of("amount", "10000");
+ }
+ default -> throw new IllegalArgumentException(scenario.id());
+ }
+ Map event = Map.of("type", type, "data", data);
+ Map activation = Map.of("event", event);
+ BooleanSupplier direct =
+ switch (scenario.id()) {
+ case "dapr.type.hit", "dapr.type.miss" ->
+ () -> ((String) event.get("type")).equals("widget");
+ case "dapr.important.hit", "dapr.important.absent" ->
+ () -> {
+ Map, ?> directData = (Map, ?>) event.get("data");
+ return directData.containsKey("important")
+ && Boolean.TRUE.equals(directData.get("important"));
+ };
+ case "dapr.deposit.hit", "dapr.deposit.boundary" ->
+ () ->
+ ((String) event.get("type")).equals("deposit")
+ && Long.parseLong((String) ((Map, ?>) event.get("data")).get("amount"))
+ > 10_000L;
+ default -> throw new IllegalArgumentException(scenario.id());
+ };
+ return new PreparedFixture(activation, direct);
+ }
+
+ private static Timestamp timestamp(Instant instant) {
+ return Timestamp.newBuilder()
+ .setSeconds(instant.getEpochSecond())
+ .setNanos(instant.getNano())
+ .build();
+ }
+
+ private static Duration duration(java.time.Duration duration) {
+ return Duration.newBuilder()
+ .setSeconds(duration.getSeconds())
+ .setNanos(duration.getNano())
+ .build();
+ }
+}
diff --git a/benchmarks/src/main/java/org/projectnessie/cel/benchmark/RealWorldPojoFixtures.java b/benchmarks/src/main/java/org/projectnessie/cel/benchmark/RealWorldPojoFixtures.java
new file mode 100644
index 00000000..cb00f8cb
--- /dev/null
+++ b/benchmarks/src/main/java/org/projectnessie/cel/benchmark/RealWorldPojoFixtures.java
@@ -0,0 +1,569 @@
+/*
+ * Copyright (C) 2026 The Authors of CEL-Java
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.projectnessie.cel.benchmark;
+
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/** Immutable JavaBean-style types used by the Jackson 3 workload representation. */
+public final class RealWorldPojoFixtures {
+ private static final String OBJECT_TYPE = "storage.googleapis.com/Object";
+ private static final String NAME_PREFIX = "projects/_/buckets/exampleco-site-assets/";
+ private static final String DRIVER = "resource-driver.example.com";
+ private static final String SERVICE_ACCOUNT = "iam.googleapis.com/ServiceAccount";
+ private static final String USER = "iam.googleapis.com/User";
+ private static final Instant INTERVAL_INSTANT = Instant.parse("2026-01-01T00:00:00.123456789Z");
+
+ private RealWorldPojoFixtures() {}
+
+ public static PreparedFixture prepare(RealWorldWorkloads.Scenario scenario) {
+ return switch (scenario.family()) {
+ case IAM -> iam(scenario);
+ case ORGANIZATION -> organization(scenario);
+ case GATEWAY -> gateway(scenario);
+ case DRA -> dra(scenario);
+ case FLUX -> flux(scenario);
+ case DAPR_TYPED -> dapr(scenario);
+ case PROTOVALIDATE_BOOKING -> booking(scenario);
+ case PROTOVALIDATE_INTERVAL -> interval(scenario);
+ case PROTOVALIDATE_NOTIFICATION -> notification(scenario);
+ default ->
+ throw new IllegalArgumentException("Unsupported Jackson scenario " + scenario.id());
+ };
+ }
+
+ public static Class>[] registeredTypes(RealWorldWorkloads.Family family) {
+ return switch (family) {
+ case IAM -> new Class>[] {PolicyResource.class};
+ case ORGANIZATION -> new Class>[] {OrganizationResource.class, Binding.class, Member.class};
+ case GATEWAY -> new Class>[] {GatewayAddress.class};
+ case DRA -> new Class>[] {Device.class, DeviceAttributes.class};
+ case FLUX -> new Class>[] {KubernetesResource.class, ResourceStatus.class, Condition.class};
+ case DAPR_TYPED -> new Class>[] {CloudEvent.class, EventData.class};
+ case PROTOVALIDATE_BOOKING -> new Class>[] {Booking.class};
+ case PROTOVALIDATE_INTERVAL -> new Class>[] {TraceInterval.class};
+ case PROTOVALIDATE_NOTIFICATION -> new Class>[] {Notification.class};
+ default -> throw new IllegalArgumentException("Unsupported Jackson family " + family);
+ };
+ }
+
+ private static PreparedFixture iam(RealWorldWorkloads.Scenario scenario) {
+ PolicyResource resource =
+ switch (scenario.id()) {
+ case "iam.prefix.hit" -> new PolicyResource(OBJECT_TYPE, NAME_PREFIX + "asset.js");
+ case "iam.prefix.typeMiss" ->
+ new PolicyResource("storage.googleapis.com/Bucket", NAME_PREFIX + "asset.js");
+ case "iam.prefix.nameMiss" ->
+ new PolicyResource(OBJECT_TYPE, "projects/_/buckets/unrelated/asset.js");
+ default -> throw new IllegalArgumentException(scenario.id());
+ };
+ return new PreparedFixture(
+ Map.of("resource", resource),
+ () -> resource.getType().equals(OBJECT_TYPE) && resource.getName().startsWith(NAME_PREFIX));
+ }
+
+ private static PreparedFixture dra(RealWorldWorkloads.Scenario scenario) {
+ Map attributes = new LinkedHashMap<>();
+ if (scenario.id().equals("dra.unrelated32")) {
+ for (int i = 0; i < 32; i++) {
+ attributes.put("unrelated.example.com/" + i, new DeviceAttributes("blue", "small"));
+ }
+ }
+ DeviceAttributes target =
+ switch (scenario.id()) {
+ case "dra.match", "dra.unrelated32" -> new DeviceAttributes("black", "large");
+ case "dra.colorMiss" -> new DeviceAttributes("white", "large");
+ case "dra.sizeMiss" -> new DeviceAttributes("black", "small");
+ default -> throw new IllegalArgumentException(scenario.id());
+ };
+ attributes.put(DRIVER, target);
+ Device device = new Device(attributes);
+ return new PreparedFixture(
+ Map.of("device", device),
+ () ->
+ device.getAttributes().get(DRIVER).getColor().equals("black")
+ && device.getAttributes().get(DRIVER).getSize().equals("large"));
+ }
+
+ private static PreparedFixture organization(RealWorldWorkloads.Scenario scenario) {
+ int bindings;
+ int members;
+ int failingBinding = -1;
+ int failingMember = -1;
+ switch (scenario.id()) {
+ case "org.members.empty" -> {
+ bindings = 1;
+ members = 0;
+ }
+ case "org.members.one" -> {
+ bindings = 1;
+ members = 1;
+ }
+ case "org.members.failFirst8" -> {
+ bindings = 1;
+ members = 8;
+ failingBinding = 0;
+ failingMember = 0;
+ }
+ case "org.members.failLast8" -> {
+ bindings = 1;
+ members = 8;
+ failingBinding = 0;
+ failingMember = 7;
+ }
+ case "org.members.all32" -> {
+ bindings = 1;
+ members = 32;
+ }
+ case "org.bindings.all8x8" -> {
+ bindings = 8;
+ members = 8;
+ }
+ case "org.bindings.failLast8x8" -> {
+ bindings = 8;
+ members = 8;
+ failingBinding = 7;
+ failingMember = 7;
+ }
+ default -> throw new IllegalArgumentException(scenario.id());
+ }
+ List bindingValues = new ArrayList<>(bindings);
+ for (int bindingIndex = 0; bindingIndex < bindings; bindingIndex++) {
+ List memberValues = new ArrayList<>(members);
+ for (int memberIndex = 0; memberIndex < members; memberIndex++) {
+ String type =
+ bindingIndex == failingBinding && memberIndex == failingMember ? USER : SERVICE_ACCOUNT;
+ memberValues.add(new Member(type, "principal-" + memberIndex));
+ }
+ bindingValues.add(new Binding("roles/viewer", memberValues));
+ }
+ OrganizationResource resource = new OrganizationResource(bindingValues);
+ return new PreparedFixture(Map.of("resource", resource), () -> organizationDirect(resource));
+ }
+
+ private static boolean organizationDirect(OrganizationResource resource) {
+ for (Binding binding : resource.getBindings()) {
+ for (Member member : binding.getMembers()) {
+ if (!member.getType().equals(SERVICE_ACCOUNT)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private static PreparedFixture gateway(RealWorldWorkloads.Scenario scenario) {
+ int size =
+ switch (scenario.id()) {
+ case "gateway.empty" -> 0;
+ case "gateway.one" -> 1;
+ case "gateway.unique8" -> 8;
+ default -> 16;
+ };
+ List addresses = new ArrayList<>(size);
+ for (int i = 0; i < size; i++) {
+ String type = scenario.id().equals("gateway.hostname16") ? "Hostname" : "IPAddress";
+ String value = type.equals("Hostname") ? "host-" + i + ".example.com" : "192.0.2." + i;
+ if (scenario.id().equals("gateway.duplicateFirst16") && i == 1) {
+ value = "192.0.2.0";
+ } else if (scenario.id().equals("gateway.duplicateLast16") && i == 15) {
+ value = "192.0.2.14";
+ }
+ addresses.add(new GatewayAddress(type, value));
+ }
+ List value = List.copyOf(addresses);
+ return new PreparedFixture(Map.of("self", value), () -> gatewayDirect(value));
+ }
+
+ private static boolean gatewayDirect(List addresses) {
+ for (GatewayAddress first : addresses) {
+ if (first.getType().equals("IPAddress") && first.getValue() != null) {
+ int matches = 0;
+ for (GatewayAddress second : addresses) {
+ if (second.getType().equals(first.getType())
+ && second.getValue() != null
+ && second.getValue().equals(first.getValue())) {
+ matches++;
+ }
+ }
+ if (matches != 1) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private static PreparedFixture flux(RealWorldWorkloads.Scenario scenario) {
+ int size =
+ switch (scenario.id()) {
+ case "flux.noConditions" -> 0;
+ case "flux.readyOne" -> 1;
+ case "flux.noReady8" -> 8;
+ default -> 32;
+ };
+ List conditions = new ArrayList<>(size);
+ for (int i = 0; i < size; i++) {
+ String type = scenario.id().equals("flux.noReady8") ? "Healthy" : "Ready";
+ String status = "True";
+ if ((scenario.id().equals("flux.failFirst32") && i == 0)
+ || (scenario.id().equals("flux.failLast32") && i == 31)) {
+ status = "False";
+ }
+ conditions.add(new Condition(type, status));
+ }
+ KubernetesResource resource = new KubernetesResource(new ResourceStatus(conditions));
+ return new PreparedFixture(Map.of("resource", resource), () -> fluxDirect(resource));
+ }
+
+ private static boolean fluxDirect(KubernetesResource resource) {
+ List ready = new ArrayList<>(resource.getStatus().getConditions().size());
+ for (Condition condition : resource.getStatus().getConditions()) {
+ if (condition.getType().equals("Ready")) {
+ ready.add(condition);
+ }
+ }
+ for (Condition condition : ready) {
+ if (!condition.getStatus().equals("True")) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static PreparedFixture dapr(RealWorldWorkloads.Scenario scenario) {
+ CloudEvent event =
+ switch (scenario.id()) {
+ case "dapr.typed.important" -> new CloudEvent("other", new EventData(true, ""));
+ case "dapr.typed.absent" -> new CloudEvent("other", new EventData(null, ""));
+ case "dapr.typed.deposit" -> new CloudEvent("deposit", new EventData(null, "10001"));
+ default -> throw new IllegalArgumentException(scenario.id());
+ };
+ return new PreparedFixture(
+ Map.of("event", event),
+ scenario.id().equals("dapr.typed.deposit")
+ ? () ->
+ event.getType().equals("deposit")
+ && Long.parseLong(event.getData().getAmount()) > 10_000L
+ : () -> event.getData().getImportant() != null && event.getData().getImportant());
+ }
+
+ private static PreparedFixture booking(RealWorldWorkloads.Scenario scenario) {
+ Booking booking =
+ switch (scenario.id()) {
+ case "protovalidate.booking.hybrid" -> new Booking("hybrid", null);
+ case "protovalidate.booking.region" -> new Booking("aws", "us-east-1");
+ case "protovalidate.booking.missing" -> new Booking("aws", null);
+ default -> throw new IllegalArgumentException(scenario.id());
+ };
+ return new PreparedFixture(
+ Map.of("this", booking),
+ () ->
+ booking.getCloudProviderId().equals("hybrid")
+ || booking.getCloudProviderRegionId() != null);
+ }
+
+ private static PreparedFixture interval(RealWorldWorkloads.Scenario scenario) {
+ TraceInterval interval =
+ switch (scenario.id()) {
+ case "protovalidate.interval.absent" -> new TraceInterval(null, null);
+ case "protovalidate.interval.ordered" ->
+ new TraceInterval(INTERVAL_INSTANT, INTERVAL_INSTANT);
+ case "protovalidate.interval.reversed" ->
+ new TraceInterval(INTERVAL_INSTANT, INTERVAL_INSTANT.minusNanos(1L));
+ default -> throw new IllegalArgumentException(scenario.id());
+ };
+ return new PreparedFixture(Map.of("this", interval), () -> intervalDirect(interval));
+ }
+
+ private static boolean intervalDirect(TraceInterval interval) {
+ if (interval.getStartTime() == null) {
+ return true;
+ }
+ if (interval.getEndTime() == null) {
+ return true;
+ }
+ return interval.getEndTime().compareTo(interval.getStartTime()) >= 0;
+ }
+
+ private static PreparedFixture notification(RealWorldWorkloads.Scenario scenario) {
+ Notification notification =
+ switch (scenario.id()) {
+ case "protovalidate.notification.webhook" ->
+ new Notification("https://example.com/hook", null);
+ case "protovalidate.notification.email" -> new Notification(null, "alerts@example.com");
+ case "protovalidate.notification.none" -> new Notification(null, null);
+ default -> throw new IllegalArgumentException(scenario.id());
+ };
+ return new PreparedFixture(
+ Map.of("this", notification),
+ () -> notification.getWebhook() != null || notification.getEmail() != null);
+ }
+
+ public static final class PolicyResource {
+ private final String type;
+ private final String name;
+
+ public PolicyResource(String type, String name) {
+ this.type = type;
+ this.name = name;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public String getName() {
+ return name;
+ }
+ }
+
+ public static final class Member {
+ private final String type;
+ private final String value;
+
+ public Member(String type, String value) {
+ this.type = type;
+ this.value = value;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public String getValue() {
+ return value;
+ }
+ }
+
+ public static final class Binding {
+ private final String role;
+ private final List members;
+
+ public Binding(String role, List members) {
+ this.role = role;
+ this.members = List.copyOf(members);
+ }
+
+ public String getRole() {
+ return role;
+ }
+
+ public List getMembers() {
+ return members;
+ }
+ }
+
+ public static final class OrganizationResource {
+ private final List bindings;
+
+ public OrganizationResource(List bindings) {
+ this.bindings = List.copyOf(bindings);
+ }
+
+ public List getBindings() {
+ return bindings;
+ }
+ }
+
+ public static final class GatewayAddress {
+ private final String type;
+ private final String value;
+
+ public GatewayAddress(String type, String value) {
+ this.type = type;
+ this.value = value;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public String getValue() {
+ return value;
+ }
+ }
+
+ public static final class DeviceAttributes {
+ private final String color;
+ private final String size;
+
+ public DeviceAttributes(String color, String size) {
+ this.color = color;
+ this.size = size;
+ }
+
+ public String getColor() {
+ return color;
+ }
+
+ public String getSize() {
+ return size;
+ }
+ }
+
+ public static final class Device {
+ private final Map attributes;
+
+ public Device(Map attributes) {
+ this.attributes = immutableLinkedMap(attributes);
+ }
+
+ public Map getAttributes() {
+ return attributes;
+ }
+ }
+
+ public static final class Condition {
+ private final String type;
+ private final String status;
+
+ public Condition(String type, String status) {
+ this.type = type;
+ this.status = status;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public String getStatus() {
+ return status;
+ }
+ }
+
+ public static final class ResourceStatus {
+ private final List conditions;
+
+ public ResourceStatus(List conditions) {
+ this.conditions = List.copyOf(conditions);
+ }
+
+ public List getConditions() {
+ return conditions;
+ }
+ }
+
+ public static final class KubernetesResource {
+ private final ResourceStatus status;
+
+ public KubernetesResource(ResourceStatus status) {
+ this.status = status;
+ }
+
+ public ResourceStatus getStatus() {
+ return status;
+ }
+ }
+
+ public static final class EventData {
+ private final Boolean important;
+ private final String amount;
+
+ public EventData(Boolean important, String amount) {
+ this.important = important;
+ this.amount = amount;
+ }
+
+ public Boolean getImportant() {
+ return important;
+ }
+
+ public String getAmount() {
+ return amount;
+ }
+ }
+
+ public static final class CloudEvent {
+ private final String type;
+ private final EventData data;
+
+ public CloudEvent(String type, EventData data) {
+ this.type = type;
+ this.data = data;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public EventData getData() {
+ return data;
+ }
+ }
+
+ public static final class Booking {
+ private final String cloudProviderId;
+ private final String cloudProviderRegionId;
+
+ public Booking(String cloudProviderId, String cloudProviderRegionId) {
+ this.cloudProviderId = cloudProviderId;
+ this.cloudProviderRegionId = cloudProviderRegionId;
+ }
+
+ public String getCloudProviderId() {
+ return cloudProviderId;
+ }
+
+ public String getCloudProviderRegionId() {
+ return cloudProviderRegionId;
+ }
+ }
+
+ public static final class TraceInterval {
+ private final Instant startTime;
+ private final Instant endTime;
+
+ public TraceInterval(Instant startTime, Instant endTime) {
+ this.startTime = startTime;
+ this.endTime = endTime;
+ }
+
+ public Instant getStartTime() {
+ return startTime;
+ }
+
+ public Instant getEndTime() {
+ return endTime;
+ }
+ }
+
+ public static final class Notification {
+ private final String webhook;
+ private final String email;
+
+ public Notification(String webhook, String email) {
+ this.webhook = webhook;
+ this.email = email;
+ }
+
+ public String getWebhook() {
+ return webhook;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+ }
+
+ private static Map immutableLinkedMap(Map source) {
+ return Collections.unmodifiableMap(new LinkedHashMap<>(source));
+ }
+}
diff --git a/benchmarks/src/main/java/org/projectnessie/cel/benchmark/RealWorldProtoFixtures.java b/benchmarks/src/main/java/org/projectnessie/cel/benchmark/RealWorldProtoFixtures.java
new file mode 100644
index 00000000..b71da4a2
--- /dev/null
+++ b/benchmarks/src/main/java/org/projectnessie/cel/benchmark/RealWorldProtoFixtures.java
@@ -0,0 +1,397 @@
+/*
+ * Copyright (C) 2026 The Authors of CEL-Java
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.projectnessie.cel.benchmark;
+
+import com.google.protobuf.Message;
+import com.google.protobuf.Timestamp;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import org.projectnessie.cel.benchmark.RealWorldWorkloads.Family;
+import org.projectnessie.cel.benchmark.RealWorldWorkloads.Scenario;
+import org.projectnessie.cel.benchmark.proto.Binding;
+import org.projectnessie.cel.benchmark.proto.Booking;
+import org.projectnessie.cel.benchmark.proto.CloudEvent;
+import org.projectnessie.cel.benchmark.proto.Condition;
+import org.projectnessie.cel.benchmark.proto.Device;
+import org.projectnessie.cel.benchmark.proto.DeviceAttributes;
+import org.projectnessie.cel.benchmark.proto.EventData;
+import org.projectnessie.cel.benchmark.proto.GatewayAddress;
+import org.projectnessie.cel.benchmark.proto.KubernetesResource;
+import org.projectnessie.cel.benchmark.proto.Member;
+import org.projectnessie.cel.benchmark.proto.Notification;
+import org.projectnessie.cel.benchmark.proto.OrganizationResource;
+import org.projectnessie.cel.benchmark.proto.PolicyResource;
+import org.projectnessie.cel.benchmark.proto.ResourceStatus;
+import org.projectnessie.cel.benchmark.proto.TraceInterval;
+
+/** Builds generated-pb3 fixtures and direct controls for paired workloads. */
+public final class RealWorldProtoFixtures {
+ private static final String OBJECT_TYPE = "storage.googleapis.com/Object";
+ private static final String NAME_PREFIX = "projects/_/buckets/exampleco-site-assets/";
+ private static final String DRIVER = "resource-driver.example.com";
+ private static final String SERVICE_ACCOUNT = "iam.googleapis.com/ServiceAccount";
+ private static final String USER = "iam.googleapis.com/User";
+ private static final Instant INTERVAL_INSTANT = Instant.parse("2026-01-01T00:00:00.123456789Z");
+
+ private RealWorldProtoFixtures() {}
+
+ public static PreparedFixture prepare(Scenario scenario) {
+ return switch (scenario.family()) {
+ case IAM -> iam(scenario);
+ case ORGANIZATION -> organization(scenario);
+ case GATEWAY -> gateway(scenario);
+ case DRA -> dra(scenario);
+ case FLUX -> flux(scenario);
+ case DAPR_TYPED -> dapr(scenario);
+ case PROTOVALIDATE_BOOKING -> booking(scenario);
+ case PROTOVALIDATE_INTERVAL -> interval(scenario);
+ case PROTOVALIDATE_NOTIFICATION -> notification(scenario);
+ default ->
+ throw new IllegalArgumentException("Unsupported protobuf scenario " + scenario.id());
+ };
+ }
+
+ public static Message[] registeredTypes(Family family) {
+ return switch (family) {
+ case IAM -> new Message[] {PolicyResource.getDefaultInstance()};
+ case ORGANIZATION ->
+ new Message[] {
+ OrganizationResource.getDefaultInstance(),
+ Binding.getDefaultInstance(),
+ Member.getDefaultInstance()
+ };
+ case GATEWAY -> new Message[] {GatewayAddress.getDefaultInstance()};
+ case DRA ->
+ new Message[] {Device.getDefaultInstance(), DeviceAttributes.getDefaultInstance()};
+ case FLUX ->
+ new Message[] {
+ KubernetesResource.getDefaultInstance(),
+ ResourceStatus.getDefaultInstance(),
+ Condition.getDefaultInstance()
+ };
+ case DAPR_TYPED ->
+ new Message[] {CloudEvent.getDefaultInstance(), EventData.getDefaultInstance()};
+ case PROTOVALIDATE_BOOKING -> new Message[] {Booking.getDefaultInstance()};
+ case PROTOVALIDATE_INTERVAL -> new Message[] {TraceInterval.getDefaultInstance()};
+ case PROTOVALIDATE_NOTIFICATION -> new Message[] {Notification.getDefaultInstance()};
+ default -> throw new IllegalArgumentException("Unsupported protobuf family " + family);
+ };
+ }
+
+ private static PreparedFixture iam(Scenario scenario) {
+ PolicyResource resource =
+ switch (scenario.id()) {
+ case "iam.prefix.hit" ->
+ PolicyResource.newBuilder()
+ .setType(OBJECT_TYPE)
+ .setName(NAME_PREFIX + "asset.js")
+ .build();
+ case "iam.prefix.typeMiss" ->
+ PolicyResource.newBuilder()
+ .setType("storage.googleapis.com/Bucket")
+ .setName(NAME_PREFIX + "asset.js")
+ .build();
+ case "iam.prefix.nameMiss" ->
+ PolicyResource.newBuilder()
+ .setType(OBJECT_TYPE)
+ .setName("projects/_/buckets/unrelated/asset.js")
+ .build();
+ default -> throw new IllegalArgumentException(scenario.id());
+ };
+ return new PreparedFixture(
+ Map.of("resource", resource),
+ () -> resource.getType().equals(OBJECT_TYPE) && resource.getName().startsWith(NAME_PREFIX));
+ }
+
+ private static PreparedFixture dra(Scenario scenario) {
+ Device.Builder builder = Device.newBuilder();
+ if (scenario.id().equals("dra.unrelated32")) {
+ for (int i = 0; i < 32; i++) {
+ builder.putAttributes(
+ "unrelated.example.com/" + i,
+ DeviceAttributes.newBuilder().setColor("blue").setSize("small").build());
+ }
+ }
+ DeviceAttributes target =
+ switch (scenario.id()) {
+ case "dra.match", "dra.unrelated32" ->
+ DeviceAttributes.newBuilder().setColor("black").setSize("large").build();
+ case "dra.colorMiss" ->
+ DeviceAttributes.newBuilder().setColor("white").setSize("large").build();
+ case "dra.sizeMiss" ->
+ DeviceAttributes.newBuilder().setColor("black").setSize("small").build();
+ default -> throw new IllegalArgumentException(scenario.id());
+ };
+ Device device = builder.putAttributes(DRIVER, target).build();
+ return new PreparedFixture(
+ Map.of("device", device),
+ () ->
+ device.getAttributesMap().get(DRIVER).getColor().equals("black")
+ && device.getAttributesMap().get(DRIVER).getSize().equals("large"));
+ }
+
+ private static PreparedFixture organization(Scenario scenario) {
+ int bindings;
+ int members;
+ int failingBinding = -1;
+ int failingMember = -1;
+ switch (scenario.id()) {
+ case "org.members.empty" -> {
+ bindings = 1;
+ members = 0;
+ }
+ case "org.members.one" -> {
+ bindings = 1;
+ members = 1;
+ }
+ case "org.members.failFirst8" -> {
+ bindings = 1;
+ members = 8;
+ failingBinding = 0;
+ failingMember = 0;
+ }
+ case "org.members.failLast8" -> {
+ bindings = 1;
+ members = 8;
+ failingBinding = 0;
+ failingMember = 7;
+ }
+ case "org.members.all32" -> {
+ bindings = 1;
+ members = 32;
+ }
+ case "org.bindings.all8x8" -> {
+ bindings = 8;
+ members = 8;
+ }
+ case "org.bindings.failLast8x8" -> {
+ bindings = 8;
+ members = 8;
+ failingBinding = 7;
+ failingMember = 7;
+ }
+ default -> throw new IllegalArgumentException(scenario.id());
+ }
+ OrganizationResource.Builder resource = OrganizationResource.newBuilder();
+ for (int bindingIndex = 0; bindingIndex < bindings; bindingIndex++) {
+ Binding.Builder binding = Binding.newBuilder().setRole("roles/viewer");
+ for (int memberIndex = 0; memberIndex < members; memberIndex++) {
+ String type =
+ bindingIndex == failingBinding && memberIndex == failingMember ? USER : SERVICE_ACCOUNT;
+ binding.addMembers(
+ Member.newBuilder().setType(type).setValue("principal-" + memberIndex).build());
+ }
+ resource.addBindings(binding.build());
+ }
+ OrganizationResource value = resource.build();
+ return new PreparedFixture(Map.of("resource", value), () -> organizationDirect(value));
+ }
+
+ private static boolean organizationDirect(OrganizationResource resource) {
+ for (Binding binding : resource.getBindingsList()) {
+ for (Member member : binding.getMembersList()) {
+ if (!member.getType().equals(SERVICE_ACCOUNT)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private static PreparedFixture gateway(Scenario scenario) {
+ int size =
+ switch (scenario.id()) {
+ case "gateway.empty" -> 0;
+ case "gateway.one" -> 1;
+ case "gateway.unique8" -> 8;
+ default -> 16;
+ };
+ List addresses = new ArrayList<>(size);
+ for (int i = 0; i < size; i++) {
+ String type = scenario.id().equals("gateway.hostname16") ? "Hostname" : "IPAddress";
+ String value = type.equals("Hostname") ? "host-" + i + ".example.com" : "192.0.2." + i;
+ if (scenario.id().equals("gateway.duplicateFirst16") && i == 1) {
+ value = "192.0.2.0";
+ } else if (scenario.id().equals("gateway.duplicateLast16") && i == 15) {
+ value = "192.0.2.14";
+ }
+ addresses.add(GatewayAddress.newBuilder().setType(type).setValue(value).build());
+ }
+ List value = List.copyOf(addresses);
+ return new PreparedFixture(Map.of("self", value), () -> gatewayDirect(value));
+ }
+
+ private static boolean gatewayDirect(List addresses) {
+ for (GatewayAddress first : addresses) {
+ if (first.getType().equals("IPAddress") && first.hasValue()) {
+ int matches = 0;
+ for (GatewayAddress second : addresses) {
+ if (second.getType().equals(first.getType())
+ && second.hasValue()
+ && second.getValue().equals(first.getValue())) {
+ matches++;
+ }
+ }
+ if (matches != 1) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private static PreparedFixture flux(Scenario scenario) {
+ int size =
+ switch (scenario.id()) {
+ case "flux.noConditions" -> 0;
+ case "flux.readyOne" -> 1;
+ case "flux.noReady8" -> 8;
+ default -> 32;
+ };
+ ResourceStatus.Builder status = ResourceStatus.newBuilder();
+ for (int i = 0; i < size; i++) {
+ String type = scenario.id().equals("flux.noReady8") ? "Healthy" : "Ready";
+ String conditionStatus = "True";
+ if ((scenario.id().equals("flux.failFirst32") && i == 0)
+ || (scenario.id().equals("flux.failLast32") && i == 31)) {
+ conditionStatus = "False";
+ }
+ status.addConditions(Condition.newBuilder().setType(type).setStatus(conditionStatus).build());
+ }
+ KubernetesResource resource = KubernetesResource.newBuilder().setStatus(status.build()).build();
+ return new PreparedFixture(Map.of("resource", resource), () -> fluxDirect(resource));
+ }
+
+ private static boolean fluxDirect(KubernetesResource resource) {
+ List ready = new ArrayList<>(resource.getStatus().getConditionsCount());
+ for (Condition condition : resource.getStatus().getConditionsList()) {
+ if (condition.getType().equals("Ready")) {
+ ready.add(condition);
+ }
+ }
+ for (Condition condition : ready) {
+ if (!condition.getStatus().equals("True")) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static PreparedFixture dapr(Scenario scenario) {
+ CloudEvent event =
+ switch (scenario.id()) {
+ case "dapr.typed.important" ->
+ CloudEvent.newBuilder()
+ .setType("other")
+ .setData(EventData.newBuilder().setImportant(true).build())
+ .build();
+ case "dapr.typed.absent" ->
+ CloudEvent.newBuilder()
+ .setType("other")
+ .setData(EventData.getDefaultInstance())
+ .build();
+ case "dapr.typed.deposit" ->
+ CloudEvent.newBuilder()
+ .setType("deposit")
+ .setData(EventData.newBuilder().setAmount("10001").build())
+ .build();
+ default -> throw new IllegalArgumentException(scenario.id());
+ };
+ return new PreparedFixture(
+ Map.of("event", event),
+ scenario.id().equals("dapr.typed.deposit")
+ ? () ->
+ event.getType().equals("deposit")
+ && Long.parseLong(event.getData().getAmount()) > 10_000L
+ : () -> event.getData().hasImportant() && event.getData().getImportant());
+ }
+
+ private static PreparedFixture booking(Scenario scenario) {
+ Booking booking =
+ switch (scenario.id()) {
+ case "protovalidate.booking.hybrid" ->
+ Booking.newBuilder().setCloudProviderId("hybrid").build();
+ case "protovalidate.booking.region" ->
+ Booking.newBuilder()
+ .setCloudProviderId("aws")
+ .setCloudProviderRegionId("us-east-1")
+ .build();
+ case "protovalidate.booking.missing" ->
+ Booking.newBuilder().setCloudProviderId("aws").build();
+ default -> throw new IllegalArgumentException(scenario.id());
+ };
+ return new PreparedFixture(
+ Map.of("this", booking),
+ () -> booking.getCloudProviderId().equals("hybrid") || booking.hasCloudProviderRegionId());
+ }
+
+ private static PreparedFixture interval(Scenario scenario) {
+ TraceInterval interval =
+ switch (scenario.id()) {
+ case "protovalidate.interval.absent" -> TraceInterval.getDefaultInstance();
+ case "protovalidate.interval.ordered" ->
+ TraceInterval.newBuilder()
+ .setStartTime(timestamp(INTERVAL_INSTANT))
+ .setEndTime(timestamp(INTERVAL_INSTANT))
+ .build();
+ case "protovalidate.interval.reversed" ->
+ TraceInterval.newBuilder()
+ .setStartTime(timestamp(INTERVAL_INSTANT))
+ .setEndTime(timestamp(INTERVAL_INSTANT.minusNanos(1L)))
+ .build();
+ default -> throw new IllegalArgumentException(scenario.id());
+ };
+ return new PreparedFixture(Map.of("this", interval), () -> intervalDirect(interval));
+ }
+
+ private static boolean intervalDirect(TraceInterval interval) {
+ if (!interval.hasStartTime()) {
+ return true;
+ }
+ if (!interval.hasEndTime()) {
+ return true;
+ }
+ return compare(interval.getEndTime(), interval.getStartTime()) >= 0;
+ }
+
+ private static PreparedFixture notification(Scenario scenario) {
+ Notification notification =
+ switch (scenario.id()) {
+ case "protovalidate.notification.webhook" ->
+ Notification.newBuilder().setWebhook("https://example.com/hook").build();
+ case "protovalidate.notification.email" ->
+ Notification.newBuilder().setEmail("alerts@example.com").build();
+ case "protovalidate.notification.none" -> Notification.getDefaultInstance();
+ default -> throw new IllegalArgumentException(scenario.id());
+ };
+ return new PreparedFixture(
+ Map.of("this", notification), () -> notification.hasWebhook() || notification.hasEmail());
+ }
+
+ private static Timestamp timestamp(Instant instant) {
+ return Timestamp.newBuilder()
+ .setSeconds(instant.getEpochSecond())
+ .setNanos(instant.getNano())
+ .build();
+ }
+
+ private static int compare(Timestamp left, Timestamp right) {
+ int seconds = Long.compare(left.getSeconds(), right.getSeconds());
+ return seconds != 0 ? seconds : Integer.compare(left.getNanos(), right.getNanos());
+ }
+}
diff --git a/benchmarks/src/main/java/org/projectnessie/cel/benchmark/RealWorldWorkloads.java b/benchmarks/src/main/java/org/projectnessie/cel/benchmark/RealWorldWorkloads.java
new file mode 100644
index 00000000..542e8f48
--- /dev/null
+++ b/benchmarks/src/main/java/org/projectnessie/cel/benchmark/RealWorldWorkloads.java
@@ -0,0 +1,547 @@
+/*
+ * Copyright (C) 2026 The Authors of CEL-Java
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.projectnessie.cel.benchmark;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.ArrayList;
+import java.util.EnumMap;
+import java.util.EnumSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/** Immutable manifest for the retained real-world workload scenarios. */
+public final class RealWorldWorkloads {
+ public enum Representation {
+ HOST,
+ PROTOBUF,
+ JACKSON3
+ }
+
+ public enum Family {
+ POLARIS,
+ NESSIE,
+ OPENFGA,
+ DAPR_HOST,
+ IAM,
+ ORGANIZATION,
+ GATEWAY,
+ DRA,
+ FLUX,
+ DAPR_TYPED,
+ PROTOVALIDATE_BOOKING,
+ PROTOVALIDATE_INTERVAL,
+ PROTOVALIDATE_NOTIFICATION
+ }
+
+ public record Scenario(
+ String id,
+ Family family,
+ List sourceExpressions,
+ Map> benchmarkExpressions,
+ boolean expected,
+ Class> resultClass,
+ Set representations,
+ String adaptationNote,
+ String provenanceUrl) {
+ public Scenario {
+ requireNonNull(id, "id");
+ requireNonNull(family, "family");
+ sourceExpressions = List.copyOf(sourceExpressions);
+ EnumMap> expressions = new EnumMap<>(Representation.class);
+ benchmarkExpressions.forEach(
+ (representation, sources) -> expressions.put(representation, List.copyOf(sources)));
+ benchmarkExpressions = Map.copyOf(expressions);
+ requireNonNull(resultClass, "resultClass");
+ representations = Set.copyOf(representations);
+ requireNonNull(adaptationNote, "adaptationNote");
+ requireNonNull(provenanceUrl, "provenanceUrl");
+ if (!benchmarkExpressions.keySet().containsAll(representations)) {
+ throw new IllegalArgumentException("Missing benchmark expression for " + id);
+ }
+ }
+
+ public List expressions(Representation representation) {
+ List expressions = benchmarkExpressions.get(representation);
+ if (expressions == null) {
+ throw new IllegalArgumentException(id + " does not support " + representation);
+ }
+ return expressions;
+ }
+ }
+
+ public static final String POLARIS_URL =
+ "https://github.com/apache/polaris/blob/"
+ + "8989f1f1a446f6e3d5da57a25892f5a89d040cd2/"
+ + "persistence/nosql/persistence/maintenance/retain-cel/src/main/java/"
+ + "org/apache/polaris/maintenance/cel/CelReferenceContinuePredicate.java";
+ public static final String NESSIE_URL =
+ "https://github.com/projectnessie/nessie/blob/"
+ + "a8ab90154cf3ecc3da156e45c3a52014cfc1d148/"
+ + "servers/quarkus-server/src/testFixtures/java/org/projectnessie/server/authz/"
+ + "NessieAuthorizationTestProfile.java";
+ public static final String OPENFGA_URL = "https://openfga.dev/docs/modeling/conditions";
+ public static final String DAPR_URL =
+ "https://docs.dapr.io/developing-applications/building-blocks/pubsub/"
+ + "howto-route-messages/";
+ public static final String IAM_URL = "https://docs.cloud.google.com/iam/docs/conditions-overview";
+ public static final String ORGANIZATION_URL =
+ "https://docs.cloud.google.com/iam/docs/org-policy-custom-constraints";
+ public static final String GATEWAY_URL =
+ "https://github.com/kubernetes-sigs/gateway-api/blob/"
+ + "5e0983451ea056a1ecb2fb49910d4ccdf44ba141/config/crd/standard/"
+ + "gateway.networking.k8s.io_gateways.yaml";
+ public static final String DRA_URL =
+ "https://kubernetes.io/docs/concepts/scheduling-eviction/" + "dynamic-resource-allocation/";
+ public static final String FLUX_URL = "https://fluxcd.io/flux/cheatsheets/cel-healthchecks/";
+ public static final String QDRANT_BOOKING_URL =
+ "https://github.com/qdrant/qdrant-cloud-public-api/blob/"
+ + "8645e6737ec43bdd32b49131b8579ad02821b36b/"
+ + "proto/qdrant/cloud/booking/v1/booking.proto";
+ public static final String REDPANDA_TRACING_URL =
+ "https://github.com/redpanda-data/console/blob/"
+ + "1018f5f71eb949cf8566734d32167cb2ea47a61f/"
+ + "proto/redpanda/api/dataplane/v1alpha3/tracing.proto";
+ public static final String FLYTE_NOTIFICATION_URL =
+ "https://github.com/flyteorg/flyte/blob/"
+ + "081e22c668f72d07cdc601c15170f3200c4105f9/"
+ + "flyteidl2/notification/definition.proto";
+
+ public static final String POLARIS_CUTOFF = "ageDays < 30 || commits <= 10";
+ public static final String NESSIE_DEFAULT = "op == 'VIEW_REFERENCE' && ref.matches('.*')";
+ public static final String NESSIE_ROLES = "'bar' in roles";
+ public static final List NESSIE_RULES =
+ List.of(
+ "op in ['VIEW_REFERENCE','CREATE_REFERENCE','DELETE_REFERENCE','VIEW_REFLOG',"
+ + "'LIST_COMMITLOG','READ_ENTRIES','READ_CONTENT_KEY','LIST_COMMIT_LOG',"
+ + "'COMMIT_CHANGE_AGAINST_REFERENCE','ASSIGN_REFERENCE_TO_HASH',"
+ + "'CREATE_ENTITY','UPDATE_ENTITY','READ_ENTITY_VALUE','DELETE_ENTITY']"
+ + " && role == 'admin_user'",
+ "op == 'VIEW_REFERENCE' && role.startsWith('test_user') && ref.matches('.*')",
+ "op in ['CREATE_REFERENCE','DELETE_REFERENCE','LIST_COMMIT_LOG','READ_ENTRIES',"
+ + "'READ_CONTENT_KEY','ASSIGN_REFERENCE_TO_HASH']"
+ + " && role.startsWith('test_user') && ref.startsWith('allowedBranch')",
+ "op == 'COMMIT_CHANGE_AGAINST_REFERENCE'"
+ + " && role.startsWith('test_user') && ref.startsWith('allowedBranch')",
+ "op in ['VIEW_REFERENCE','CREATE_ENTITY','UPDATE_ENTITY']"
+ + " && role == 'test_user2' && path.startsWith('allowed-')"
+ + " && ref.startsWith('allowedBranch')",
+ "op in ['VIEW_REFERENCE','DELETE_ENTITY_VALUE','CREATE_ENTITY','UPDATE_ENTITY']"
+ + " && role == 'test_user3' && path.startsWith('allowed-')"
+ + " && ref.startsWith('allowedBranch')",
+ "op in ['VIEW_REFERENCE','READ_ENTITY_VALUE','DELETE_ENTITY']"
+ + " && role == 'test_user4' && path.startsWith('allowed-')"
+ + " && ref.startsWith('allowedBranch')",
+ "op == 'COMMIT_CHANGE_AGAINST_REFERENCE'"
+ + " && role == 'test_user2' && ref.startsWith('allowedBranch')",
+ "op == 'CREATE_REFERENCE' && role == 'user1' && ref.matches('.*')",
+ "op in ['VIEW_REFERENCE','ASSIGN_REFERENCE_TO_HASH',"
+ + "'COMMIT_CHANGE_AGAINST_REFERENCE','DELETE_REFERENCE']"
+ + " && role == 'user1'"
+ + " && (ref.startsWith('allowedBranch') || ref == 'main')",
+ "op in ['VIEW_REFERENCE','CREATE_REFERENCE']"
+ + " && role == 'delete_branch_disallowed_user'"
+ + " && ref in ['testDeleteBranchDisallowed','main']");
+ public static final String OPENFGA_TIME = "current_time < grant_time + grant_duration";
+ public static final String DAPR_TYPE = "event.type == 'widget'";
+ public static final String DAPR_IMPORTANT =
+ "has(event.data.important) && event.data.important == true";
+ public static final String DAPR_DEPOSIT =
+ "event.type == 'deposit' && int(event.data.amount) > 10000";
+ public static final String IAM_PREFIX =
+ "resource.type == 'storage.googleapis.com/Object'"
+ + " && resource.name.startsWith("
+ + "'projects/_/buckets/exampleco-site-assets/')";
+ public static final String ORGANIZATION_SOURCE =
+ "resource.bindings.all(binding, binding.members.all(member,"
+ + " MemberTypeMatches(member, ['iam.googleapis.com/ServiceAccount'])))";
+ public static final String ORGANIZATION_BENCHMARK =
+ "resource.bindings.all(binding, binding.members.all(member,"
+ + " member.type == 'iam.googleapis.com/ServiceAccount'))";
+ public static final String GATEWAY_UNIQUENESS =
+ "self.all(a1, a1.type == 'IPAddress' && has(a1.value)"
+ + " ? self.exists_one(a2, a2.type == a1.type"
+ + " && has(a2.value) && a2.value == a1.value) : true)";
+ public static final String DRA_ATTRIBUTES =
+ "device.attributes['resource-driver.example.com'].color == 'black'"
+ + " && device.attributes['resource-driver.example.com'].size == 'large'";
+ public static final String FLUX_SOURCE =
+ "status.conditions.filter(e, e.type == 'Ready').all(e, e.status == 'True')";
+ public static final String FLUX_BENCHMARK =
+ "resource.status.conditions" + ".filter(e, e.type == 'Ready').all(e, e.status == 'True')";
+ public static final String BOOKING_PROTO =
+ "this.cloud_provider_id == 'hybrid' || has(this.cloud_provider_region_id)";
+ public static final String BOOKING_JACKSON =
+ "this.cloudProviderId == 'hybrid' || has(this.cloudProviderRegionId)";
+ public static final String INTERVAL_PROTO =
+ "!has(this.start_time) || !has(this.end_time) || this.end_time >= this.start_time";
+ public static final String INTERVAL_JACKSON =
+ "!has(this.startTime) || !has(this.endTime) || this.endTime >= this.startTime";
+ public static final String NOTIFICATION = "has(this.webhook) || has(this.email)";
+
+ public static final String POLARIS_CONSTANT_FALSE = "polaris.constant.false";
+ public static final String POLARIS_CUTOFF_LEFT = "polaris.cutoff.left";
+ public static final String POLARIS_CUTOFF_RIGHT = "polaris.cutoff.right";
+ public static final String POLARIS_CUTOFF_STOP = "polaris.cutoff.stop";
+ public static final String NESSIE_DEFAULT_ALLOW = "nessie.default.allow";
+ public static final String NESSIE_DEFAULT_DENY = "nessie.default.deny";
+ public static final String NESSIE_ROLES_HIT_LATE = "nessie.roles.hitLate";
+ public static final String NESSIE_ROLES_MISS = "nessie.roles.miss";
+ public static final String NESSIE_RULES_FIRST = "nessie.rules.first";
+ public static final String NESSIE_RULES_MIDDLE = "nessie.rules.middle";
+ public static final String NESSIE_RULES_LATE = "nessie.rules.late";
+ public static final String NESSIE_RULES_DENY = "nessie.rules.deny";
+ public static final String OPENFGA_BEFORE = "openfga.before";
+ public static final String OPENFGA_EQUAL = "openfga.equal";
+ public static final String OPENFGA_AFTER = "openfga.after";
+ public static final String DAPR_TYPE_HIT = "dapr.type.hit";
+ public static final String DAPR_TYPE_MISS = "dapr.type.miss";
+ public static final String DAPR_IMPORTANT_HIT = "dapr.important.hit";
+ public static final String DAPR_IMPORTANT_ABSENT = "dapr.important.absent";
+ public static final String DAPR_DEPOSIT_HIT = "dapr.deposit.hit";
+ public static final String DAPR_DEPOSIT_BOUNDARY = "dapr.deposit.boundary";
+ public static final String IAM_PREFIX_HIT = "iam.prefix.hit";
+ public static final String IAM_PREFIX_TYPE_MISS = "iam.prefix.typeMiss";
+ public static final String IAM_PREFIX_NAME_MISS = "iam.prefix.nameMiss";
+ public static final String DRA_MATCH = "dra.match";
+ public static final String DRA_COLOR_MISS = "dra.colorMiss";
+ public static final String DRA_SIZE_MISS = "dra.sizeMiss";
+ public static final String DRA_UNRELATED_32 = "dra.unrelated32";
+ public static final String ORG_MEMBERS_EMPTY = "org.members.empty";
+ public static final String ORG_MEMBERS_ONE = "org.members.one";
+ public static final String ORG_MEMBERS_FAIL_FIRST_8 = "org.members.failFirst8";
+ public static final String ORG_MEMBERS_FAIL_LAST_8 = "org.members.failLast8";
+ public static final String ORG_MEMBERS_ALL_32 = "org.members.all32";
+ public static final String ORG_BINDINGS_ALL_8_X_8 = "org.bindings.all8x8";
+ public static final String ORG_BINDINGS_FAIL_LAST_8_X_8 = "org.bindings.failLast8x8";
+ public static final String GATEWAY_EMPTY = "gateway.empty";
+ public static final String GATEWAY_ONE = "gateway.one";
+ public static final String GATEWAY_UNIQUE_8 = "gateway.unique8";
+ public static final String GATEWAY_UNIQUE_16 = "gateway.unique16";
+ public static final String GATEWAY_DUPLICATE_FIRST_16 = "gateway.duplicateFirst16";
+ public static final String GATEWAY_DUPLICATE_LAST_16 = "gateway.duplicateLast16";
+ public static final String GATEWAY_HOSTNAME_16 = "gateway.hostname16";
+ public static final String FLUX_NO_CONDITIONS = "flux.noConditions";
+ public static final String FLUX_NO_READY_8 = "flux.noReady8";
+ public static final String FLUX_READY_ONE = "flux.readyOne";
+ public static final String FLUX_READY_ALL_32 = "flux.readyAll32";
+ public static final String FLUX_FAIL_FIRST_32 = "flux.failFirst32";
+ public static final String FLUX_FAIL_LAST_32 = "flux.failLast32";
+ public static final String DAPR_TYPED_IMPORTANT = "dapr.typed.important";
+ public static final String DAPR_TYPED_ABSENT = "dapr.typed.absent";
+ public static final String DAPR_TYPED_DEPOSIT = "dapr.typed.deposit";
+ public static final String PROTOVALIDATE_BOOKING_HYBRID = "protovalidate.booking.hybrid";
+ public static final String PROTOVALIDATE_BOOKING_REGION = "protovalidate.booking.region";
+ public static final String PROTOVALIDATE_BOOKING_MISSING = "protovalidate.booking.missing";
+ public static final String PROTOVALIDATE_INTERVAL_ABSENT = "protovalidate.interval.absent";
+ public static final String PROTOVALIDATE_INTERVAL_ORDERED = "protovalidate.interval.ordered";
+ public static final String PROTOVALIDATE_INTERVAL_REVERSED = "protovalidate.interval.reversed";
+ public static final String PROTOVALIDATE_NOTIFICATION_WEBHOOK =
+ "protovalidate.notification.webhook";
+ public static final String PROTOVALIDATE_NOTIFICATION_EMAIL = "protovalidate.notification.email";
+ public static final String PROTOVALIDATE_NOTIFICATION_NONE = "protovalidate.notification.none";
+
+ private static final List HOST_SCENARIOS = createHostScenarios();
+ private static final List PAIRED_SCENARIOS = createPairedScenarios();
+ private static final Map BY_ID = index();
+
+ private RealWorldWorkloads() {}
+
+ public static List hostScenarios() {
+ return HOST_SCENARIOS;
+ }
+
+ public static List pairedScenarios() {
+ return PAIRED_SCENARIOS;
+ }
+
+ public static Scenario scenario(String id) {
+ Scenario scenario = BY_ID.get(id);
+ if (scenario == null) {
+ throw new IllegalArgumentException("Unknown scenario " + id);
+ }
+ return scenario;
+ }
+
+ public static String[] hostScenarioIds() {
+ return HOST_SCENARIOS.stream().map(Scenario::id).toArray(String[]::new);
+ }
+
+ public static String[] pairedScenarioIds() {
+ return PAIRED_SCENARIOS.stream().map(Scenario::id).toArray(String[]::new);
+ }
+
+ private static List createHostScenarios() {
+ List scenarios = new ArrayList<>();
+ scenarios.add(host(POLARIS_CONSTANT_FALSE, Family.POLARIS, "false", false, POLARIS_URL));
+ scenarios.add(host(POLARIS_CUTOFF_LEFT, Family.POLARIS, POLARIS_CUTOFF, true, POLARIS_URL));
+ scenarios.add(host(POLARIS_CUTOFF_RIGHT, Family.POLARIS, POLARIS_CUTOFF, true, POLARIS_URL));
+ scenarios.add(host(POLARIS_CUTOFF_STOP, Family.POLARIS, POLARIS_CUTOFF, false, POLARIS_URL));
+ scenarios.add(host(NESSIE_DEFAULT_ALLOW, Family.NESSIE, NESSIE_DEFAULT, true, NESSIE_URL));
+ scenarios.add(host(NESSIE_DEFAULT_DENY, Family.NESSIE, NESSIE_DEFAULT, false, NESSIE_URL));
+ scenarios.add(host(NESSIE_ROLES_HIT_LATE, Family.NESSIE, NESSIE_ROLES, true, NESSIE_URL));
+ scenarios.add(host(NESSIE_ROLES_MISS, Family.NESSIE, NESSIE_ROLES, false, NESSIE_URL));
+ scenarios.add(hostRules(NESSIE_RULES_FIRST, true));
+ scenarios.add(hostRules(NESSIE_RULES_MIDDLE, true));
+ scenarios.add(hostRules(NESSIE_RULES_LATE, true));
+ scenarios.add(hostRules(NESSIE_RULES_DENY, false));
+ scenarios.add(host(OPENFGA_BEFORE, Family.OPENFGA, OPENFGA_TIME, true, OPENFGA_URL));
+ scenarios.add(host(OPENFGA_EQUAL, Family.OPENFGA, OPENFGA_TIME, false, OPENFGA_URL));
+ scenarios.add(host(OPENFGA_AFTER, Family.OPENFGA, OPENFGA_TIME, false, OPENFGA_URL));
+ scenarios.add(host(DAPR_TYPE_HIT, Family.DAPR_HOST, DAPR_TYPE, true, DAPR_URL));
+ scenarios.add(host(DAPR_TYPE_MISS, Family.DAPR_HOST, DAPR_TYPE, false, DAPR_URL));
+ scenarios.add(host(DAPR_IMPORTANT_HIT, Family.DAPR_HOST, DAPR_IMPORTANT, true, DAPR_URL));
+ scenarios.add(host(DAPR_IMPORTANT_ABSENT, Family.DAPR_HOST, DAPR_IMPORTANT, false, DAPR_URL));
+ scenarios.add(host(DAPR_DEPOSIT_HIT, Family.DAPR_HOST, DAPR_DEPOSIT, true, DAPR_URL));
+ scenarios.add(host(DAPR_DEPOSIT_BOUNDARY, Family.DAPR_HOST, DAPR_DEPOSIT, false, DAPR_URL));
+ return List.copyOf(scenarios);
+ }
+
+ private static List createPairedScenarios() {
+ List scenarios = new ArrayList<>();
+ scenarios.add(pair(IAM_PREFIX_HIT, Family.IAM, IAM_PREFIX, true, IAM_URL));
+ scenarios.add(pair(IAM_PREFIX_TYPE_MISS, Family.IAM, IAM_PREFIX, false, IAM_URL));
+ scenarios.add(pair(IAM_PREFIX_NAME_MISS, Family.IAM, IAM_PREFIX, false, IAM_URL));
+
+ scenarios.add(
+ adaptedPair(
+ ORG_MEMBERS_EMPTY,
+ Family.ORGANIZATION,
+ ORGANIZATION_SOURCE,
+ ORGANIZATION_BENCHMARK,
+ true,
+ "MemberTypeMatches is mirrored by a preclassified member.type field.",
+ ORGANIZATION_URL));
+ scenarios.add(pairFromPrevious(scenarios, ORG_MEMBERS_ONE, true));
+ scenarios.add(pairFromPrevious(scenarios, ORG_MEMBERS_FAIL_FIRST_8, false));
+ scenarios.add(pairFromPrevious(scenarios, ORG_MEMBERS_FAIL_LAST_8, false));
+ scenarios.add(pairFromPrevious(scenarios, ORG_MEMBERS_ALL_32, true));
+ scenarios.add(pairFromPrevious(scenarios, ORG_BINDINGS_ALL_8_X_8, true));
+ scenarios.add(pairFromPrevious(scenarios, ORG_BINDINGS_FAIL_LAST_8_X_8, false));
+
+ scenarios.add(pair(GATEWAY_EMPTY, Family.GATEWAY, GATEWAY_UNIQUENESS, true, GATEWAY_URL));
+ scenarios.add(pairFromPrevious(scenarios, GATEWAY_ONE, true));
+ scenarios.add(pairFromPrevious(scenarios, GATEWAY_UNIQUE_8, true));
+ scenarios.add(pairFromPrevious(scenarios, GATEWAY_UNIQUE_16, true));
+ scenarios.add(pairFromPrevious(scenarios, GATEWAY_DUPLICATE_FIRST_16, false));
+ scenarios.add(pairFromPrevious(scenarios, GATEWAY_DUPLICATE_LAST_16, false));
+ scenarios.add(pairFromPrevious(scenarios, GATEWAY_HOSTNAME_16, true));
+
+ scenarios.add(pair(DRA_MATCH, Family.DRA, DRA_ATTRIBUTES, true, DRA_URL));
+ scenarios.add(pairFromPrevious(scenarios, DRA_COLOR_MISS, false));
+ scenarios.add(pairFromPrevious(scenarios, DRA_SIZE_MISS, false));
+ scenarios.add(pairFromPrevious(scenarios, DRA_UNRELATED_32, true));
+
+ scenarios.add(
+ adaptedPair(
+ FLUX_NO_CONDITIONS,
+ Family.FLUX,
+ FLUX_SOURCE,
+ FLUX_BENCHMARK,
+ true,
+ "The source host exposes resource fields implicitly; the benchmark uses resource.",
+ FLUX_URL));
+ scenarios.add(pairFromPrevious(scenarios, FLUX_NO_READY_8, true));
+ scenarios.add(pairFromPrevious(scenarios, FLUX_READY_ONE, true));
+ scenarios.add(pairFromPrevious(scenarios, FLUX_READY_ALL_32, true));
+ scenarios.add(pairFromPrevious(scenarios, FLUX_FAIL_FIRST_32, false));
+ scenarios.add(pairFromPrevious(scenarios, FLUX_FAIL_LAST_32, false));
+
+ scenarios.add(pair(DAPR_TYPED_IMPORTANT, Family.DAPR_TYPED, DAPR_IMPORTANT, true, DAPR_URL));
+ scenarios.add(pairFromPrevious(scenarios, DAPR_TYPED_ABSENT, false));
+ scenarios.add(pair(DAPR_TYPED_DEPOSIT, Family.DAPR_TYPED, DAPR_DEPOSIT, true, DAPR_URL));
+
+ scenarios.add(
+ representationPair(
+ PROTOVALIDATE_BOOKING_HYBRID,
+ Family.PROTOVALIDATE_BOOKING,
+ BOOKING_PROTO,
+ BOOKING_PROTO,
+ BOOKING_JACKSON,
+ true,
+ "Jackson uses Java property names; protobuf retains schema field names.",
+ QDRANT_BOOKING_URL));
+ scenarios.add(pairFromPrevious(scenarios, PROTOVALIDATE_BOOKING_REGION, true));
+ scenarios.add(pairFromPrevious(scenarios, PROTOVALIDATE_BOOKING_MISSING, false));
+
+ scenarios.add(
+ representationPair(
+ PROTOVALIDATE_INTERVAL_ABSENT,
+ Family.PROTOVALIDATE_INTERVAL,
+ INTERVAL_PROTO,
+ INTERVAL_PROTO,
+ INTERVAL_JACKSON,
+ true,
+ "Jackson uses Java property names and nullable Instant fields.",
+ REDPANDA_TRACING_URL));
+ scenarios.add(pairFromPrevious(scenarios, PROTOVALIDATE_INTERVAL_ORDERED, true));
+ scenarios.add(pairFromPrevious(scenarios, PROTOVALIDATE_INTERVAL_REVERSED, false));
+
+ scenarios.add(
+ pair(
+ PROTOVALIDATE_NOTIFICATION_WEBHOOK,
+ Family.PROTOVALIDATE_NOTIFICATION,
+ NOTIFICATION,
+ true,
+ FLYTE_NOTIFICATION_URL));
+ scenarios.add(pairFromPrevious(scenarios, PROTOVALIDATE_NOTIFICATION_EMAIL, true));
+ scenarios.add(pairFromPrevious(scenarios, PROTOVALIDATE_NOTIFICATION_NONE, false));
+ return List.copyOf(scenarios);
+ }
+
+ private static Scenario host(
+ String id, Family family, String expression, boolean expected, String provenanceUrl) {
+ return scenario(
+ id,
+ family,
+ List.of(expression),
+ Map.of(Representation.HOST, List.of(expression)),
+ expected,
+ EnumSet.of(Representation.HOST),
+ "Source expression is used without adaptation.",
+ provenanceUrl);
+ }
+
+ private static Scenario hostRules(String id, boolean expected) {
+ return scenario(
+ id,
+ Family.NESSIE,
+ NESSIE_RULES,
+ Map.of(Representation.HOST, NESSIE_RULES),
+ expected,
+ EnumSet.of(Representation.HOST),
+ "The HashMap-backed host policy is made source ordered for a deterministic position case.",
+ NESSIE_URL);
+ }
+
+ private static Scenario pair(
+ String id, Family family, String expression, boolean expected, String provenanceUrl) {
+ return scenario(
+ id,
+ family,
+ List.of(expression),
+ Map.of(
+ Representation.PROTOBUF,
+ List.of(expression),
+ Representation.JACKSON3,
+ List.of(expression)),
+ expected,
+ EnumSet.of(Representation.PROTOBUF, Representation.JACKSON3),
+ "Source expression is used without adaptation.",
+ provenanceUrl);
+ }
+
+ private static Scenario adaptedPair(
+ String id,
+ Family family,
+ String sourceExpression,
+ String benchmarkExpression,
+ boolean expected,
+ String note,
+ String provenanceUrl) {
+ return scenario(
+ id,
+ family,
+ List.of(sourceExpression),
+ Map.of(
+ Representation.PROTOBUF,
+ List.of(benchmarkExpression),
+ Representation.JACKSON3,
+ List.of(benchmarkExpression)),
+ expected,
+ EnumSet.of(Representation.PROTOBUF, Representation.JACKSON3),
+ note,
+ provenanceUrl);
+ }
+
+ private static Scenario representationPair(
+ String id,
+ Family family,
+ String sourceExpression,
+ String protoExpression,
+ String jacksonExpression,
+ boolean expected,
+ String note,
+ String provenanceUrl) {
+ return scenario(
+ id,
+ family,
+ List.of(sourceExpression),
+ Map.of(
+ Representation.PROTOBUF,
+ List.of(protoExpression),
+ Representation.JACKSON3,
+ List.of(jacksonExpression)),
+ expected,
+ EnumSet.of(Representation.PROTOBUF, Representation.JACKSON3),
+ note,
+ provenanceUrl);
+ }
+
+ private static Scenario pairFromPrevious(List scenarios, String id, boolean expected) {
+ if (scenarios.isEmpty()) {
+ throw new IllegalStateException("No prior paired scenario");
+ }
+ Scenario previous = scenarios.get(scenarios.size() - 1);
+ return scenario(
+ id,
+ previous.family(),
+ previous.sourceExpressions(),
+ previous.benchmarkExpressions(),
+ expected,
+ previous.representations(),
+ previous.adaptationNote(),
+ previous.provenanceUrl());
+ }
+
+ private static Scenario scenario(
+ String id,
+ Family family,
+ List sourceExpressions,
+ Map> benchmarkExpressions,
+ boolean expected,
+ Set representations,
+ String adaptationNote,
+ String provenanceUrl) {
+ return new Scenario(
+ id,
+ family,
+ sourceExpressions,
+ benchmarkExpressions,
+ expected,
+ Boolean.class,
+ representations,
+ adaptationNote,
+ provenanceUrl);
+ }
+
+ private static Map index() {
+ Map index = new LinkedHashMap<>();
+ for (Scenario scenario : HOST_SCENARIOS) {
+ if (index.put(scenario.id(), scenario) != null) {
+ throw new IllegalStateException("Duplicate scenario " + scenario.id());
+ }
+ }
+ for (Scenario scenario : PAIRED_SCENARIOS) {
+ if (index.put(scenario.id(), scenario) != null) {
+ throw new IllegalStateException("Duplicate scenario " + scenario.id());
+ }
+ }
+ return Map.copyOf(index);
+ }
+}
diff --git a/benchmarks/src/test/java/org/projectnessie/cel/RealWorldHostWorkloadTest.java b/benchmarks/src/test/java/org/projectnessie/cel/RealWorldHostWorkloadTest.java
new file mode 100644
index 00000000..a9320c92
--- /dev/null
+++ b/benchmarks/src/test/java/org/projectnessie/cel/RealWorldHostWorkloadTest.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2026 The Authors of CEL-Java
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.projectnessie.cel;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.catchThrowable;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.DAPR_DEPOSIT;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.DAPR_TYPE;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.Family.DAPR_HOST;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.Family.NESSIE;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Stream;
+import org.junit.jupiter.api.DynamicTest;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestFactory;
+import org.projectnessie.cel.RealWorldProgramSet.ProgramModes;
+import org.projectnessie.cel.benchmark.PreparedFixture;
+import org.projectnessie.cel.benchmark.RealWorldHostFixtures;
+import org.projectnessie.cel.benchmark.RealWorldWorkloads;
+import org.projectnessie.cel.common.types.Err;
+import org.projectnessie.cel.common.types.StringT;
+
+class RealWorldHostWorkloadTest {
+ @TestFactory
+ Stream retainedHostScenarios() {
+ return RealWorldWorkloads.hostScenarios().stream()
+ .map(
+ scenario ->
+ DynamicTest.dynamicTest(
+ scenario.id(),
+ () -> {
+ PreparedFixture fixture = RealWorldHostFixtures.prepare(scenario);
+ RealWorldProgramSet programs = RealWorldProgramSet.host(scenario, fixture);
+ assertThat(programs.exactNative())
+ .isInstanceOf(Boolean.class)
+ .isEqualTo(scenario.expected());
+ assertThat(programs.exactDisabled()).isEqualTo(scenario.expected());
+ assertThat(programs.general()).isEqualTo(scenario.expected());
+ assertThat(programs.direct()).isEqualTo(scenario.expected());
+ }));
+ }
+
+ @Test
+ void invalidDaprAmountIsCelErrorInEveryMode() {
+ ProgramModes modes = RealWorldProgramSet.hostPrograms(DAPR_HOST, DAPR_DEPOSIT);
+ Map activation =
+ Map.of("event", Map.of("type", "deposit", "data", Map.of("amount", "not-a-number")));
+ assertCelErrors(modes, activation);
+ }
+
+ @Test
+ void missingTopLevelVariableIsCelErrorInEveryMode() {
+ ProgramModes modes = RealWorldProgramSet.hostPrograms(DAPR_HOST, DAPR_TYPE);
+ assertCelErrors(modes, Map.of());
+ }
+
+ @Test
+ void nonBooleanResultFailsNativeConversionInEveryMode() {
+ ProgramModes modes = RealWorldProgramSet.hostPrograms(NESSIE, "'not-a-boolean'");
+ Map activation =
+ Map.of(
+ "op", "",
+ "role", "",
+ "roles", List.of(),
+ "ref", "",
+ "path", "",
+ "contentType", "");
+ List> failureClasses = new ArrayList<>();
+ for (Program program : List.of(modes.exactNative(), modes.exactDisabled(), modes.general())) {
+ assertThat(program.eval(activation).getVal()).isEqualTo(StringT.stringOf("not-a-boolean"));
+ Throwable failure = catchThrowable(() -> RealWorldProgramSet.evaluate(program, activation));
+ assertThat(failure).isInstanceOf(RuntimeException.class);
+ failureClasses.add(failure.getClass());
+ }
+ assertThat(failureClasses).containsOnly(failureClasses.get(0));
+ }
+
+ private static void assertCelErrors(ProgramModes modes, Map activation) {
+ for (Program program : List.of(modes.exactNative(), modes.exactDisabled(), modes.general())) {
+ assertThat(Err.isError(program.eval(activation).getVal())).isTrue();
+ }
+ }
+}
diff --git a/benchmarks/src/test/java/org/projectnessie/cel/RealWorldJackson3WorkloadTest.java b/benchmarks/src/test/java/org/projectnessie/cel/RealWorldJackson3WorkloadTest.java
new file mode 100644
index 00000000..34fee8ac
--- /dev/null
+++ b/benchmarks/src/test/java/org/projectnessie/cel/RealWorldJackson3WorkloadTest.java
@@ -0,0 +1,287 @@
+/*
+ * Copyright (C) 2026 The Authors of CEL-Java
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.projectnessie.cel;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.DAPR_TYPED_DEPOSIT;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.DRA_COLOR_MISS;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.DRA_MATCH;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.DRA_SIZE_MISS;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.DRA_UNRELATED_32;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.FLUX_FAIL_FIRST_32;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.FLUX_FAIL_LAST_32;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.FLUX_NO_CONDITIONS;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.FLUX_NO_READY_8;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.FLUX_READY_ALL_32;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.FLUX_READY_ONE;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.GATEWAY_DUPLICATE_FIRST_16;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.GATEWAY_DUPLICATE_LAST_16;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.GATEWAY_EMPTY;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.GATEWAY_HOSTNAME_16;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.GATEWAY_ONE;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.GATEWAY_UNIQUE_16;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.GATEWAY_UNIQUE_8;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.IAM_PREFIX_NAME_MISS;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.IAM_PREFIX_TYPE_MISS;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.ORG_BINDINGS_ALL_8_X_8;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.ORG_BINDINGS_FAIL_LAST_8_X_8;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.ORG_MEMBERS_ALL_32;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.ORG_MEMBERS_EMPTY;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.ORG_MEMBERS_FAIL_FIRST_8;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.ORG_MEMBERS_FAIL_LAST_8;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.ORG_MEMBERS_ONE;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.PROTOVALIDATE_BOOKING_MISSING;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.PROTOVALIDATE_INTERVAL_REVERSED;
+import static org.projectnessie.cel.common.types.Err.isError;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Stream;
+import org.junit.jupiter.api.DynamicTest;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestFactory;
+import org.projectnessie.cel.RealWorldProgramSet.ProgramModes;
+import org.projectnessie.cel.benchmark.PreparedFixture;
+import org.projectnessie.cel.benchmark.RealWorldPojoFixtures;
+import org.projectnessie.cel.benchmark.RealWorldPojoFixtures.CloudEvent;
+import org.projectnessie.cel.benchmark.RealWorldPojoFixtures.Device;
+import org.projectnessie.cel.benchmark.RealWorldPojoFixtures.EventData;
+import org.projectnessie.cel.benchmark.RealWorldPojoFixtures.GatewayAddress;
+import org.projectnessie.cel.benchmark.RealWorldPojoFixtures.KubernetesResource;
+import org.projectnessie.cel.benchmark.RealWorldPojoFixtures.OrganizationResource;
+import org.projectnessie.cel.benchmark.RealWorldPojoFixtures.PolicyResource;
+import org.projectnessie.cel.benchmark.RealWorldPojoFixtures.TraceInterval;
+import org.projectnessie.cel.benchmark.RealWorldProtoFixtures;
+import org.projectnessie.cel.benchmark.RealWorldWorkloads;
+import org.projectnessie.cel.benchmark.RealWorldWorkloads.Family;
+import org.projectnessie.cel.benchmark.RealWorldWorkloads.Scenario;
+
+class RealWorldJackson3WorkloadTest {
+ @TestFactory
+ Stream retainedJacksonScenarios() {
+ return RealWorldProtoWorkloadTest.implementedScenarios()
+ .map(
+ scenario ->
+ DynamicTest.dynamicTest(
+ scenario.id(),
+ () -> {
+ PreparedFixture fixture = RealWorldPojoFixtures.prepare(scenario);
+ RealWorldProgramSet programs =
+ RealWorldProgramSet.jackson3(
+ scenario,
+ fixture,
+ RealWorldPojoFixtures.registeredTypes(scenario.family()));
+ assertThat(programs.exactNative()).isEqualTo(scenario.expected());
+ assertThat(programs.exactDisabled()).isEqualTo(scenario.expected());
+ assertThat(programs.general()).isEqualTo(scenario.expected());
+ assertThat(programs.direct()).isEqualTo(scenario.expected());
+ }));
+ }
+
+ @TestFactory
+ Stream protobufAndJacksonAgree() {
+ return RealWorldProtoWorkloadTest.implementedScenarios()
+ .map(
+ scenario ->
+ DynamicTest.dynamicTest(
+ scenario.id(),
+ () -> {
+ RealWorldProgramSet protobuf =
+ RealWorldProgramSet.protobuf(
+ scenario,
+ RealWorldProtoFixtures.prepare(scenario),
+ RealWorldProtoFixtures.registeredTypes(scenario.family()));
+ RealWorldProgramSet jackson =
+ RealWorldProgramSet.jackson3(
+ scenario,
+ RealWorldPojoFixtures.prepare(scenario),
+ RealWorldPojoFixtures.registeredTypes(scenario.family()));
+ assertThat(jackson.exactNative()).isEqualTo(protobuf.exactNative());
+ assertThat(jackson.exactDisabled()).isEqualTo(protobuf.exactDisabled());
+ assertThat(jackson.general()).isEqualTo(protobuf.general());
+ }));
+ }
+
+ @Test
+ void missingDraDriverIsCelErrorInEveryMode() {
+ Scenario scenario = RealWorldWorkloads.scenario(DRA_MATCH);
+ ProgramModes modes =
+ RealWorldProgramSet.jackson3Programs(
+ scenario, RealWorldPojoFixtures.registeredTypes(Family.DRA));
+ Device device = new Device(new LinkedHashMap<>());
+ Map activation = Map.of("device", device);
+ for (Program program : List.of(modes.exactNative(), modes.exactDisabled(), modes.general())) {
+ assertThat(isError(program.eval(activation).getVal())).isTrue();
+ }
+ }
+
+ @Test
+ void fixtureDimensionsRemainDistinct() {
+ PolicyResource typeMiss =
+ (PolicyResource)
+ RealWorldPojoFixtures.prepare(RealWorldWorkloads.scenario(IAM_PREFIX_TYPE_MISS))
+ .activation()
+ .get("resource");
+ assertThat(typeMiss.getName()).startsWith("projects/_/buckets/exampleco-site-assets/");
+
+ PolicyResource nameMiss =
+ (PolicyResource)
+ RealWorldPojoFixtures.prepare(RealWorldWorkloads.scenario(IAM_PREFIX_NAME_MISS))
+ .activation()
+ .get("resource");
+ assertThat(nameMiss.getType()).isEqualTo("storage.googleapis.com/Object");
+
+ Device colorMiss = pojoDevice(DRA_COLOR_MISS);
+ assertThat(colorMiss.getAttributes().get("resource-driver.example.com").getSize())
+ .isEqualTo("large");
+ Device sizeMiss = pojoDevice(DRA_SIZE_MISS);
+ assertThat(sizeMiss.getAttributes().get("resource-driver.example.com").getColor())
+ .isEqualTo("black");
+ assertThat(pojoDevice(DRA_UNRELATED_32).getAttributes()).hasSize(33);
+
+ assertOrganizationShapes();
+ assertGatewayShapes();
+ assertFluxShapes();
+
+ assertThat(
+ ((RealWorldPojoFixtures.Booking) pojoRoot(PROTOVALIDATE_BOOKING_MISSING, "this"))
+ .getCloudProviderRegionId())
+ .isNull();
+ TraceInterval interval = (TraceInterval) pojoRoot(PROTOVALIDATE_INTERVAL_REVERSED, "this");
+ assertThat(interval.getStartTime().getNano() - interval.getEndTime().getNano()).isEqualTo(1);
+ }
+
+ private static Device pojoDevice(String scenarioId) {
+ return (Device) pojoRoot(scenarioId, "device");
+ }
+
+ private static void assertOrganizationShapes() {
+ Map.of(
+ ORG_MEMBERS_EMPTY, 0,
+ ORG_MEMBERS_ONE, 1,
+ ORG_MEMBERS_FAIL_FIRST_8, 8,
+ ORG_MEMBERS_FAIL_LAST_8, 8,
+ ORG_MEMBERS_ALL_32, 32)
+ .forEach(
+ (scenarioId, members) -> {
+ OrganizationResource resource =
+ (OrganizationResource) pojoRoot(scenarioId, "resource");
+ assertThat(resource.getBindings()).as(scenarioId).hasSize(1);
+ assertThat(resource.getBindings().get(0).getMembers())
+ .as(scenarioId)
+ .hasSize(members);
+ });
+ OrganizationResource failFirst =
+ (OrganizationResource) pojoRoot(ORG_MEMBERS_FAIL_FIRST_8, "resource");
+ assertThat(failFirst.getBindings().get(0).getMembers().get(0).getType())
+ .isEqualTo("iam.googleapis.com/User");
+ assertThat(failFirst.getBindings().get(0).getMembers().get(7).getType())
+ .isEqualTo("iam.googleapis.com/ServiceAccount");
+ OrganizationResource failLast =
+ (OrganizationResource) pojoRoot(ORG_MEMBERS_FAIL_LAST_8, "resource");
+ assertThat(failLast.getBindings().get(0).getMembers().get(0).getType())
+ .isEqualTo("iam.googleapis.com/ServiceAccount");
+ assertThat(failLast.getBindings().get(0).getMembers().get(7).getType())
+ .isEqualTo("iam.googleapis.com/User");
+
+ for (String scenarioId : List.of(ORG_BINDINGS_ALL_8_X_8, ORG_BINDINGS_FAIL_LAST_8_X_8)) {
+ OrganizationResource resource = (OrganizationResource) pojoRoot(scenarioId, "resource");
+ assertThat(resource.getBindings()).as(scenarioId).hasSize(8);
+ assertThat(resource.getBindings())
+ .as(scenarioId)
+ .allSatisfy(binding -> assertThat(binding.getMembers()).hasSize(8));
+ }
+ OrganizationResource failLastBinding =
+ (OrganizationResource) pojoRoot(ORG_BINDINGS_FAIL_LAST_8_X_8, "resource");
+ assertThat(failLastBinding.getBindings().get(7).getMembers().get(7).getType())
+ .isEqualTo("iam.googleapis.com/User");
+ }
+
+ private static void assertGatewayShapes() {
+ Map.of(
+ GATEWAY_EMPTY, 0,
+ GATEWAY_ONE, 1,
+ GATEWAY_UNIQUE_8, 8,
+ GATEWAY_UNIQUE_16, 16,
+ GATEWAY_DUPLICATE_FIRST_16, 16,
+ GATEWAY_DUPLICATE_LAST_16, 16,
+ GATEWAY_HOSTNAME_16, 16)
+ .forEach(
+ (scenarioId, size) -> assertThat(pojoGateway(scenarioId)).as(scenarioId).hasSize(size));
+ assertThat(pojoGateway(GATEWAY_DUPLICATE_FIRST_16).get(1).getValue())
+ .isEqualTo(pojoGateway(GATEWAY_DUPLICATE_FIRST_16).get(0).getValue());
+ assertThat(pojoGateway(GATEWAY_DUPLICATE_LAST_16).get(15).getValue())
+ .isEqualTo(pojoGateway(GATEWAY_DUPLICATE_LAST_16).get(14).getValue());
+ assertThat(pojoGateway(GATEWAY_HOSTNAME_16))
+ .allSatisfy(address -> assertThat(address.getType()).isEqualTo("Hostname"));
+ }
+
+ private static void assertFluxShapes() {
+ Map.of(
+ FLUX_NO_CONDITIONS, 0,
+ FLUX_NO_READY_8, 8,
+ FLUX_READY_ONE, 1,
+ FLUX_READY_ALL_32, 32,
+ FLUX_FAIL_FIRST_32, 32,
+ FLUX_FAIL_LAST_32, 32)
+ .forEach(
+ (scenarioId, size) ->
+ assertThat(pojoFlux(scenarioId).getStatus().getConditions())
+ .as(scenarioId)
+ .hasSize(size));
+ assertThat(pojoFlux(FLUX_NO_READY_8).getStatus().getConditions())
+ .allSatisfy(condition -> assertThat(condition.getType()).isEqualTo("Healthy"));
+ assertThat(pojoFlux(FLUX_READY_ALL_32).getStatus().getConditions())
+ .allSatisfy(condition -> assertThat(condition.getStatus()).isEqualTo("True"));
+ assertThat(pojoFlux(FLUX_FAIL_FIRST_32).getStatus().getConditions().get(0).getStatus())
+ .isEqualTo("False");
+ assertThat(pojoFlux(FLUX_FAIL_FIRST_32).getStatus().getConditions().get(31).getStatus())
+ .isEqualTo("True");
+ assertThat(pojoFlux(FLUX_FAIL_LAST_32).getStatus().getConditions().get(0).getStatus())
+ .isEqualTo("True");
+ assertThat(pojoFlux(FLUX_FAIL_LAST_32).getStatus().getConditions().get(31).getStatus())
+ .isEqualTo("False");
+ }
+
+ @SuppressWarnings("unchecked")
+ private static List pojoGateway(String scenarioId) {
+ return (List) pojoRoot(scenarioId, "self");
+ }
+
+ private static KubernetesResource pojoFlux(String scenarioId) {
+ return (KubernetesResource) pojoRoot(scenarioId, "resource");
+ }
+
+ private static Object pojoRoot(String scenarioId, String variable) {
+ return RealWorldPojoFixtures.prepare(RealWorldWorkloads.scenario(scenarioId))
+ .activation()
+ .get(variable);
+ }
+
+ @Test
+ void invalidTypedDaprAmountIsCelErrorInEveryMode() {
+ Scenario scenario = RealWorldWorkloads.scenario(DAPR_TYPED_DEPOSIT);
+ ProgramModes modes =
+ RealWorldProgramSet.jackson3Programs(
+ scenario, RealWorldPojoFixtures.registeredTypes(Family.DAPR_TYPED));
+ CloudEvent event = new CloudEvent("deposit", new EventData(null, "not-a-number"));
+ Map activation = Map.of("event", event);
+ for (Program program : List.of(modes.exactNative(), modes.exactDisabled(), modes.general())) {
+ assertThat(isError(program.eval(activation).getVal())).isTrue();
+ }
+ }
+}
diff --git a/benchmarks/src/test/java/org/projectnessie/cel/RealWorldManifestTest.java b/benchmarks/src/test/java/org/projectnessie/cel/RealWorldManifestTest.java
new file mode 100644
index 00000000..a5eeb397
--- /dev/null
+++ b/benchmarks/src/test/java/org/projectnessie/cel/RealWorldManifestTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2026 The Authors of CEL-Java
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.projectnessie.cel;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.Representation.HOST;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.Representation.JACKSON3;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.Representation.PROTOBUF;
+
+import java.util.stream.Stream;
+import org.junit.jupiter.api.Test;
+import org.projectnessie.cel.benchmark.RealWorldWorkloads;
+import org.projectnessie.cel.benchmark.RealWorldWorkloads.Scenario;
+
+class RealWorldManifestTest {
+ @Test
+ void retainedCardinalityAndUniqueIds() {
+ assertThat(RealWorldWorkloads.hostScenarios()).hasSize(21);
+ assertThat(RealWorldWorkloads.pairedScenarios()).hasSize(39);
+ assertThat(
+ Stream.concat(
+ RealWorldWorkloads.hostScenarios().stream(),
+ RealWorldWorkloads.pairedScenarios().stream())
+ .map(Scenario::id))
+ .doesNotHaveDuplicates();
+ }
+
+ @Test
+ void representationContractsAreComplete() {
+ assertThat(RealWorldWorkloads.hostScenarios())
+ .allSatisfy(
+ scenario -> {
+ assertThat(scenario.representations()).containsExactly(HOST);
+ assertThat(scenario.expressions(HOST)).isNotEmpty();
+ });
+ assertThat(RealWorldWorkloads.pairedScenarios())
+ .allSatisfy(
+ scenario -> {
+ assertThat(scenario.representations()).containsExactlyInAnyOrder(PROTOBUF, JACKSON3);
+ assertThat(scenario.expressions(PROTOBUF)).isNotEmpty();
+ assertThat(scenario.expressions(JACKSON3)).isNotEmpty();
+ });
+ }
+
+ @Test
+ void metadataRequiredForReproductionIsPresent() {
+ assertThat(
+ Stream.concat(
+ RealWorldWorkloads.hostScenarios().stream(),
+ RealWorldWorkloads.pairedScenarios().stream()))
+ .allSatisfy(
+ scenario -> {
+ assertThat(scenario.sourceExpressions()).isNotEmpty();
+ assertThat(scenario.resultClass()).isEqualTo(Boolean.class);
+ assertThat(scenario.adaptationNote()).isNotBlank();
+ assertThat(scenario.provenanceUrl()).startsWith("https://");
+ });
+ }
+}
diff --git a/benchmarks/src/test/java/org/projectnessie/cel/RealWorldProgramLifecycleTest.java b/benchmarks/src/test/java/org/projectnessie/cel/RealWorldProgramLifecycleTest.java
new file mode 100644
index 00000000..21f46773
--- /dev/null
+++ b/benchmarks/src/test/java/org/projectnessie/cel/RealWorldProgramLifecycleTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2026 The Authors of CEL-Java
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.projectnessie.cel;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.NESSIE_RULES_DENY;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.ORG_BINDINGS_ALL_8_X_8;
+
+import org.junit.jupiter.api.Test;
+import org.projectnessie.cel.RealWorldProgramSet.Lifecycle;
+import org.projectnessie.cel.benchmark.RealWorldHostFixtures;
+import org.projectnessie.cel.benchmark.RealWorldPojoFixtures;
+import org.projectnessie.cel.benchmark.RealWorldProtoFixtures;
+import org.projectnessie.cel.benchmark.RealWorldWorkloads;
+
+class RealWorldProgramLifecycleTest {
+ @Test
+ void hostLifecycleRetainsMultiProgramRuleSet() {
+ var scenario = RealWorldWorkloads.scenario(NESSIE_RULES_DENY);
+ Lifecycle lifecycle =
+ RealWorldProgramSet.hostLifecycle(scenario, RealWorldHostFixtures.prepare(scenario));
+
+ assertThat(lifecycle.compileExact()).hasSize(11);
+ assertThat(lifecycle.compileGeneral()).hasSize(11);
+ assertThat(lifecycle.planExactNative()).hasSize(11);
+ assertThat(lifecycle.planExactDisabled()).hasSize(11);
+ assertThat(lifecycle.planGeneral()).hasSize(11);
+ assertThat(lifecycle.coldExactNative()).isFalse();
+ assertThat(lifecycle.coldExactDisabled()).isFalse();
+ assertThat(lifecycle.coldGeneral()).isFalse();
+ }
+
+ @Test
+ void protobufLifecycleProducesEquivalentResult() {
+ var scenario = RealWorldWorkloads.scenario(ORG_BINDINGS_ALL_8_X_8);
+ Lifecycle lifecycle =
+ RealWorldProgramSet.protobufLifecycle(
+ scenario,
+ RealWorldProtoFixtures.prepare(scenario),
+ RealWorldProtoFixtures.registeredTypes(scenario.family()));
+
+ assertThat(lifecycle.coldExactNative()).isTrue();
+ assertThat(lifecycle.coldExactDisabled()).isTrue();
+ assertThat(lifecycle.coldGeneral()).isTrue();
+ }
+
+ @Test
+ void jackson3LifecycleProducesEquivalentResult() {
+ var scenario = RealWorldWorkloads.scenario(ORG_BINDINGS_ALL_8_X_8);
+ Lifecycle lifecycle =
+ RealWorldProgramSet.jackson3Lifecycle(
+ scenario,
+ RealWorldPojoFixtures.prepare(scenario),
+ RealWorldPojoFixtures.registeredTypes(scenario.family()));
+
+ assertThat(lifecycle.coldExactNative()).isTrue();
+ assertThat(lifecycle.coldExactDisabled()).isTrue();
+ assertThat(lifecycle.coldGeneral()).isTrue();
+ }
+}
diff --git a/benchmarks/src/test/java/org/projectnessie/cel/RealWorldProtoWorkloadTest.java b/benchmarks/src/test/java/org/projectnessie/cel/RealWorldProtoWorkloadTest.java
new file mode 100644
index 00000000..b95328a3
--- /dev/null
+++ b/benchmarks/src/test/java/org/projectnessie/cel/RealWorldProtoWorkloadTest.java
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 2026 The Authors of CEL-Java
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.projectnessie.cel;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.DAPR_TYPED_DEPOSIT;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.DRA_COLOR_MISS;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.DRA_MATCH;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.DRA_SIZE_MISS;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.DRA_UNRELATED_32;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.FLUX_FAIL_FIRST_32;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.FLUX_FAIL_LAST_32;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.FLUX_NO_CONDITIONS;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.FLUX_NO_READY_8;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.FLUX_READY_ALL_32;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.FLUX_READY_ONE;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.GATEWAY_DUPLICATE_FIRST_16;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.GATEWAY_DUPLICATE_LAST_16;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.GATEWAY_EMPTY;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.GATEWAY_HOSTNAME_16;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.GATEWAY_ONE;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.GATEWAY_UNIQUE_16;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.GATEWAY_UNIQUE_8;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.IAM_PREFIX_NAME_MISS;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.IAM_PREFIX_TYPE_MISS;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.ORG_BINDINGS_ALL_8_X_8;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.ORG_BINDINGS_FAIL_LAST_8_X_8;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.ORG_MEMBERS_ALL_32;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.ORG_MEMBERS_EMPTY;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.ORG_MEMBERS_FAIL_FIRST_8;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.ORG_MEMBERS_FAIL_LAST_8;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.ORG_MEMBERS_ONE;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.PROTOVALIDATE_BOOKING_MISSING;
+import static org.projectnessie.cel.benchmark.RealWorldWorkloads.PROTOVALIDATE_INTERVAL_REVERSED;
+import static org.projectnessie.cel.common.types.Err.isError;
+
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Stream;
+import org.junit.jupiter.api.DynamicTest;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestFactory;
+import org.projectnessie.cel.RealWorldProgramSet.ProgramModes;
+import org.projectnessie.cel.benchmark.PreparedFixture;
+import org.projectnessie.cel.benchmark.RealWorldProtoFixtures;
+import org.projectnessie.cel.benchmark.RealWorldWorkloads;
+import org.projectnessie.cel.benchmark.RealWorldWorkloads.Family;
+import org.projectnessie.cel.benchmark.RealWorldWorkloads.Scenario;
+import org.projectnessie.cel.benchmark.proto.Booking;
+import org.projectnessie.cel.benchmark.proto.CloudEvent;
+import org.projectnessie.cel.benchmark.proto.Device;
+import org.projectnessie.cel.benchmark.proto.EventData;
+import org.projectnessie.cel.benchmark.proto.GatewayAddress;
+import org.projectnessie.cel.benchmark.proto.KubernetesResource;
+import org.projectnessie.cel.benchmark.proto.OrganizationResource;
+import org.projectnessie.cel.benchmark.proto.PolicyResource;
+import org.projectnessie.cel.benchmark.proto.TraceInterval;
+
+class RealWorldProtoWorkloadTest {
+ @TestFactory
+ Stream retainedProtobufScenarios() {
+ return implementedScenarios()
+ .map(
+ scenario ->
+ DynamicTest.dynamicTest(
+ scenario.id(),
+ () -> {
+ PreparedFixture fixture = RealWorldProtoFixtures.prepare(scenario);
+ RealWorldProgramSet programs =
+ RealWorldProgramSet.protobuf(
+ scenario,
+ fixture,
+ RealWorldProtoFixtures.registeredTypes(scenario.family()));
+ assertThat(programs.exactNative()).isEqualTo(scenario.expected());
+ assertThat(programs.exactDisabled()).isEqualTo(scenario.expected());
+ assertThat(programs.general()).isEqualTo(scenario.expected());
+ assertThat(programs.direct()).isEqualTo(scenario.expected());
+ }));
+ }
+
+ @Test
+ void missingDraDriverIsCelErrorInEveryMode() {
+ Scenario scenario = RealWorldWorkloads.scenario(DRA_MATCH);
+ ProgramModes modes =
+ RealWorldProgramSet.protobufPrograms(
+ scenario, RealWorldProtoFixtures.registeredTypes(Family.DRA));
+ Map activation = Map.of("device", Device.getDefaultInstance());
+ for (Program program : List.of(modes.exactNative(), modes.exactDisabled(), modes.general())) {
+ assertThat(isError(program.eval(activation).getVal())).isTrue();
+ }
+ }
+
+ @Test
+ void fixtureDimensionsRemainDistinct() {
+ PolicyResource typeMiss =
+ (PolicyResource)
+ RealWorldProtoFixtures.prepare(RealWorldWorkloads.scenario(IAM_PREFIX_TYPE_MISS))
+ .activation()
+ .get("resource");
+ assertThat(typeMiss.getName()).startsWith("projects/_/buckets/exampleco-site-assets/");
+
+ PolicyResource nameMiss =
+ (PolicyResource)
+ RealWorldProtoFixtures.prepare(RealWorldWorkloads.scenario(IAM_PREFIX_NAME_MISS))
+ .activation()
+ .get("resource");
+ assertThat(nameMiss.getType()).isEqualTo("storage.googleapis.com/Object");
+
+ Device colorMiss = protoDevice(DRA_COLOR_MISS);
+ assertThat(colorMiss.getAttributesOrThrow("resource-driver.example.com").getSize())
+ .isEqualTo("large");
+ Device sizeMiss = protoDevice(DRA_SIZE_MISS);
+ assertThat(sizeMiss.getAttributesOrThrow("resource-driver.example.com").getColor())
+ .isEqualTo("black");
+ assertThat(protoDevice(DRA_UNRELATED_32).getAttributesCount()).isEqualTo(33);
+
+ assertOrganizationShapes();
+ assertGatewayShapes();
+ assertFluxShapes();
+
+ Booking booking = (Booking) protoRoot(PROTOVALIDATE_BOOKING_MISSING, "this");
+ assertThat(booking.hasCloudProviderRegionId()).isFalse();
+ TraceInterval interval = (TraceInterval) protoRoot(PROTOVALIDATE_INTERVAL_REVERSED, "this");
+ assertThat(interval.getStartTime().getNanos() - interval.getEndTime().getNanos()).isEqualTo(1);
+ }
+
+ @Test
+ void invalidTypedDaprAmountIsCelErrorInEveryMode() {
+ Scenario scenario = RealWorldWorkloads.scenario(DAPR_TYPED_DEPOSIT);
+ ProgramModes modes =
+ RealWorldProgramSet.protobufPrograms(
+ scenario, RealWorldProtoFixtures.registeredTypes(Family.DAPR_TYPED));
+ CloudEvent event =
+ CloudEvent.newBuilder()
+ .setType("deposit")
+ .setData(EventData.newBuilder().setAmount("not-a-number").build())
+ .build();
+ Map activation = Map.of("event", event);
+ for (Program program : List.of(modes.exactNative(), modes.exactDisabled(), modes.general())) {
+ assertThat(isError(program.eval(activation).getVal())).isTrue();
+ }
+ }
+
+ static Stream implementedScenarios() {
+ return RealWorldWorkloads.pairedScenarios().stream();
+ }
+
+ private static Device protoDevice(String scenarioId) {
+ return (Device) protoRoot(scenarioId, "device");
+ }
+
+ private static void assertOrganizationShapes() {
+ Map.of(
+ ORG_MEMBERS_EMPTY, 0,
+ ORG_MEMBERS_ONE, 1,
+ ORG_MEMBERS_FAIL_FIRST_8, 8,
+ ORG_MEMBERS_FAIL_LAST_8, 8,
+ ORG_MEMBERS_ALL_32, 32)
+ .forEach(
+ (scenarioId, members) -> {
+ OrganizationResource resource =
+ (OrganizationResource) protoRoot(scenarioId, "resource");
+ assertThat(resource.getBindingsCount()).as(scenarioId).isEqualTo(1);
+ assertThat(resource.getBindings(0).getMembersCount())
+ .as(scenarioId)
+ .isEqualTo(members);
+ });
+ OrganizationResource failFirst =
+ (OrganizationResource) protoRoot(ORG_MEMBERS_FAIL_FIRST_8, "resource");
+ assertThat(failFirst.getBindings(0).getMembers(0).getType())
+ .isEqualTo("iam.googleapis.com/User");
+ assertThat(failFirst.getBindings(0).getMembers(7).getType())
+ .isEqualTo("iam.googleapis.com/ServiceAccount");
+ OrganizationResource failLast =
+ (OrganizationResource) protoRoot(ORG_MEMBERS_FAIL_LAST_8, "resource");
+ assertThat(failLast.getBindings(0).getMembers(0).getType())
+ .isEqualTo("iam.googleapis.com/ServiceAccount");
+ assertThat(failLast.getBindings(0).getMembers(7).getType())
+ .isEqualTo("iam.googleapis.com/User");
+
+ for (String scenarioId : List.of(ORG_BINDINGS_ALL_8_X_8, ORG_BINDINGS_FAIL_LAST_8_X_8)) {
+ OrganizationResource resource = (OrganizationResource) protoRoot(scenarioId, "resource");
+ assertThat(resource.getBindingsCount()).as(scenarioId).isEqualTo(8);
+ assertThat(resource.getBindingsList())
+ .as(scenarioId)
+ .allSatisfy(binding -> assertThat(binding.getMembersCount()).isEqualTo(8));
+ }
+ OrganizationResource failLastBinding =
+ (OrganizationResource) protoRoot(ORG_BINDINGS_FAIL_LAST_8_X_8, "resource");
+ assertThat(failLastBinding.getBindings(7).getMembers(7).getType())
+ .isEqualTo("iam.googleapis.com/User");
+ }
+
+ private static void assertGatewayShapes() {
+ Map.of(
+ GATEWAY_EMPTY, 0,
+ GATEWAY_ONE, 1,
+ GATEWAY_UNIQUE_8, 8,
+ GATEWAY_UNIQUE_16, 16,
+ GATEWAY_DUPLICATE_FIRST_16, 16,
+ GATEWAY_DUPLICATE_LAST_16, 16,
+ GATEWAY_HOSTNAME_16, 16)
+ .forEach(
+ (scenarioId, size) ->
+ assertThat(protoGateway(scenarioId)).as(scenarioId).hasSize(size));
+ assertThat(protoGateway(GATEWAY_DUPLICATE_FIRST_16).get(1).getValue())
+ .isEqualTo(protoGateway(GATEWAY_DUPLICATE_FIRST_16).get(0).getValue());
+ assertThat(protoGateway(GATEWAY_DUPLICATE_LAST_16).get(15).getValue())
+ .isEqualTo(protoGateway(GATEWAY_DUPLICATE_LAST_16).get(14).getValue());
+ assertThat(protoGateway(GATEWAY_HOSTNAME_16))
+ .allSatisfy(address -> assertThat(address.getType()).isEqualTo("Hostname"));
+ }
+
+ private static void assertFluxShapes() {
+ Map.of(
+ FLUX_NO_CONDITIONS, 0,
+ FLUX_NO_READY_8, 8,
+ FLUX_READY_ONE, 1,
+ FLUX_READY_ALL_32, 32,
+ FLUX_FAIL_FIRST_32, 32,
+ FLUX_FAIL_LAST_32, 32)
+ .forEach(
+ (scenarioId, size) ->
+ assertThat(protoFlux(scenarioId).getStatus().getConditionsCount())
+ .as(scenarioId)
+ .isEqualTo(size));
+ assertThat(protoFlux(FLUX_NO_READY_8).getStatus().getConditionsList())
+ .allSatisfy(condition -> assertThat(condition.getType()).isEqualTo("Healthy"));
+ assertThat(protoFlux(FLUX_READY_ALL_32).getStatus().getConditionsList())
+ .allSatisfy(condition -> assertThat(condition.getStatus()).isEqualTo("True"));
+ assertThat(protoFlux(FLUX_FAIL_FIRST_32).getStatus().getConditions(0).getStatus())
+ .isEqualTo("False");
+ assertThat(protoFlux(FLUX_FAIL_FIRST_32).getStatus().getConditions(31).getStatus())
+ .isEqualTo("True");
+ assertThat(protoFlux(FLUX_FAIL_LAST_32).getStatus().getConditions(0).getStatus())
+ .isEqualTo("True");
+ assertThat(protoFlux(FLUX_FAIL_LAST_32).getStatus().getConditions(31).getStatus())
+ .isEqualTo("False");
+ }
+
+ @SuppressWarnings("unchecked")
+ private static List protoGateway(String scenarioId) {
+ return (List) protoRoot(scenarioId, "self");
+ }
+
+ private static KubernetesResource protoFlux(String scenarioId) {
+ return (KubernetesResource) protoRoot(scenarioId, "resource");
+ }
+
+ private static Object protoRoot(String scenarioId, String variable) {
+ return RealWorldProtoFixtures.prepare(RealWorldWorkloads.scenario(scenarioId))
+ .activation()
+ .get(variable);
+ }
+}
diff --git a/bom/build.gradle.kts b/bom/build.gradle.kts
index b50161b0..3e09d37d 100644
--- a/bom/build.gradle.kts
+++ b/bom/build.gradle.kts
@@ -24,10 +24,8 @@ plugins {
dependencies {
constraints {
api(project(":cel-core"))
- api(project(":cel-generated-antlr"))
api(project(":cel-generated-pb"))
api(project(":cel-generated-pb3"))
- api(project(":cel-conformance"))
api(project(":cel-jackson"))
api(project(":cel-jackson3"))
api(project(":cel-tools"))
diff --git a/build-logic/src/main/kotlin/CodeCoverage.kt b/build-logic/src/main/kotlin/CodeCoverage.kt
index 04373d87..cd47cb30 100644
--- a/build-logic/src/main/kotlin/CodeCoverage.kt
+++ b/build-logic/src/main/kotlin/CodeCoverage.kt
@@ -49,8 +49,6 @@ class CelCodeCoveragePlugin : Plugin {
excludeClassLoaders =
listOf("*QuarkusClassLoader") + (if (excluded != null) excluded else emptyList())
}
- systemProperty("quarkus.jacoco.report", "false")
- systemProperty("quarkus.jacoco.reuse-data-file", "true")
}
}
}
diff --git a/build-logic/src/main/kotlin/PublishingHelperPlugin.kt b/build-logic/src/main/kotlin/PublishingHelperPlugin.kt
index e67351a2..57c83fef 100644
--- a/build-logic/src/main/kotlin/PublishingHelperPlugin.kt
+++ b/build-logic/src/main/kotlin/PublishingHelperPlugin.kt
@@ -139,6 +139,7 @@ constructor(private val softwareComponentFactory: SoftwareComponentFactory) : Pl
project.name
}
val pomDescription = project.description
+ val projectVersion = project.version.toString()
val developersFile = layout.settingsDirectory.file("gradle/developers.csv")
val contributorsFile = layout.settingsDirectory.file("gradle/contributors.csv")
@@ -186,10 +187,16 @@ constructor(private val softwareComponentFactory: SoftwareComponentFactory) : Pl
}
}
scm {
+ val tagName =
+ if (projectVersion.endsWith("-SNAPSHOT")) {
+ "main"
+ } else {
+ "v$projectVersion"
+ }
connection.set(scmUrl)
developerConnection.set(scmUrl)
- url.set(repoUrl.map { "$it/tree/main" })
- tag.set("main")
+ url.set(repoUrl.map { "$it/tree/$tagName" })
+ tag.set(tagName)
}
issueManagement {
system.set("Github")
diff --git a/build-logic/src/main/kotlin/cel-conventions.gradle.kts b/build-logic/src/main/kotlin/cel-conventions.gradle.kts
index 8a66f9c5..599e1aa6 100644
--- a/build-logic/src/main/kotlin/cel-conventions.gradle.kts
+++ b/build-logic/src/main/kotlin/cel-conventions.gradle.kts
@@ -20,6 +20,7 @@ nessieConfigureJava()
val nonPublishedProjects =
setOf(
+ "cel-benchmarks",
"cel-conformance",
"cel-quarkus-smoke-standalone",
"cel-quarkus-smoke-core-pb3-jackson3",
diff --git a/build.gradle.kts b/build.gradle.kts
index df3713e0..62a9c29a 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -102,7 +102,6 @@ idea.project.settings {
afterSync(
":cel-generated-pb:jar",
":cel-generated-pb:testJar",
- ":cel-generated-antlr:shadowJar",
)
}
}
diff --git a/conformance/build.gradle.kts b/conformance/build.gradle.kts
index 8f4e2769..4af8fc99 100644
--- a/conformance/build.gradle.kts
+++ b/conformance/build.gradle.kts
@@ -67,7 +67,7 @@ dependencies {
implementation(project(":cel-generated-pb3"))
implementation(testFixtures(project(":cel-generated-pb3")))
- implementation(libs.protobuf.java) { version { strictly(libs.versions.protobuf3.get()) } }
+ implementation(libs.protobuf.java3)
testImplementation(testFixtures(project(":cel-core")))
@@ -82,7 +82,8 @@ configure {
// Configure the protoc executable
protoc {
// Download from repositories
- artifact = "com.google.protobuf:protoc:${libs.versions.protobuf3.get()}"
+ artifact =
+ "com.google.protobuf:protoc:${libs.protobuf.java3.get().versionConstraint.preferredVersion}"
}
}
diff --git a/conformance/src/test/java/org/projectnessie/cel/conformance/SimpleConformanceTest.java b/conformance/src/test/java/org/projectnessie/cel/conformance/SimpleConformanceTest.java
index b71ec3f1..2115b652 100644
--- a/conformance/src/test/java/org/projectnessie/cel/conformance/SimpleConformanceTest.java
+++ b/conformance/src/test/java/org/projectnessie/cel/conformance/SimpleConformanceTest.java
@@ -29,8 +29,11 @@
import static org.projectnessie.cel.EnvOption.clearMacros;
import static org.projectnessie.cel.EnvOption.container;
import static org.projectnessie.cel.EnvOption.declarations;
+import static org.projectnessie.cel.EnvOption.macros;
import static org.projectnessie.cel.EnvOption.types;
+import static org.projectnessie.cel.EvalOption.OptDisableNativeEval;
import static org.projectnessie.cel.Library.StdLib;
+import static org.projectnessie.cel.ProgramOption.evalOptions;
import static org.projectnessie.cel.common.types.BoolT.True;
import static org.projectnessie.cel.common.types.BytesT.bytesOf;
import static org.projectnessie.cel.common.types.DoubleT.doubleOf;
@@ -43,6 +46,12 @@
import static org.projectnessie.cel.common.types.UintT.uintOf;
import static org.projectnessie.cel.common.types.UnknownT.isUnknown;
import static org.projectnessie.cel.common.types.UnknownT.unknownOf;
+import static org.projectnessie.cel.extension.EncodersLib.encoders;
+import static org.projectnessie.cel.extension.MathLib.math;
+import static org.projectnessie.cel.extension.NetworkLib.network;
+import static org.projectnessie.cel.extension.OptionalLib.optionals;
+import static org.projectnessie.cel.extension.ProtoLib.proto;
+import static org.projectnessie.cel.extension.StringsLib.strings;
import com.google.api.expr.v1alpha1.CheckedExpr;
import com.google.api.expr.v1alpha1.Decl;
@@ -80,6 +89,8 @@
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import java.util.stream.Stream;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.DynamicNode;
@@ -99,19 +110,25 @@
import org.projectnessie.cel.common.types.ref.Val;
import org.projectnessie.cel.common.types.traits.Lister;
import org.projectnessie.cel.common.types.traits.Mapper;
+import org.projectnessie.cel.parser.Macro;
class SimpleConformanceTest {
private static final Path TESTDATA_DIR = testdataDir();
- private static final TextFormat.Printer TEXT_PRINTER =
- TextFormat.printer().emittingSingleLine(true);
+ private static final Pattern PROTO3_NUMERIC_ENUM_ANY =
+ Pattern.compile(
+ "\\[type\\.googleapis\\.com/cel\\.expr\\.conformance\\.proto3\\.TestAllTypes\\]"
+ + "\\s*\\{\\s*standalone_enum:\\s*(-?\\d+)\\s*\\}");
private static final List TEST_FILES =
List.of(
"basic.textproto",
+ "bindings_ext.textproto",
+ "block_ext.textproto",
"comparisons.textproto",
"conversions.textproto",
"dynamic.textproto",
+ "encoders_ext.textproto",
"enums.textproto",
"fields.textproto",
"fp_math.textproto",
@@ -119,75 +136,89 @@ class SimpleConformanceTest {
"lists.textproto",
"logic.textproto",
"macros.textproto",
+ "macros2.textproto",
+ "math_ext.textproto",
"namespace.textproto",
+ "network_ext.textproto",
+ "optionals.textproto",
"parse.textproto",
"plumbing.textproto",
"proto2.textproto",
+ "proto2_ext.textproto",
"proto3.textproto",
"string.textproto",
+ "string_ext.textproto",
"timestamps.textproto",
+ "type_deduction.textproto",
"unknowns.textproto",
"wrappers.textproto");
private static final Set SKIP_TESTS =
SkipList.parse(
- // Without the checker, verifying whether an assignment is allowed by the CEL spec is
- // difficult, especially from a map to a struct. The checker catches this case, while the
- // evaluator currently converts int(1) to string("1").
- "dynamic/struct/field_assign_proto2_bad",
- "dynamic/struct/field_assign_proto3_bad",
- // The test expects -0.0d, but in Java -0.0d == 0.0d, so -0.0d is evaluated as not set.
- "dynamic/float/field_assign_proto3_round_to_zero",
- // Malicious too-deep protobuf structure.
- "parse/nest/message_literal",
- // Proto equality specialties do not seem to be in effect for Java.
- "comparisons/eq_wrapper/eq_proto_nan_equal",
- "comparisons/ne_literal/ne_proto_nan_not_equal",
- // TODO Actual known issue: protobuf Any returned by this test is wrapped twice.
- "dynamic/any/var",
- // New CEL-Spec v0.25.2 expectations that need follow-up parser/runtime changes.
- "conversions/bool/string_1,string_t,string_0,string_f,string_true_badcase,string_false_badcase",
- "fields/quoted_map_fields/field_access_slash,field_access_dash,field_access_dot,has_field_slash,has_field_dash,has_field_dot",
- "namespace/namespace_shadowing/comprehension_shadowing,comprehension_shadowing_disambiguation,comprehension_shadowing_parse_only,comprehension_shadowing_selector,comprehension_shadowing_selector_parse_only,comprehension_shadowing_namespaced_selector,comprehension_shadowing_namespaced_selector_parse_only,comprehension_shadowing_nesting",
- "proto2/set_null/single_message,single_duration,single_timestamp,repeated_field_timestamp_null_pruned,repeated_field_duration_null_pruned,repeated_field_wrapper_null_pruned,map_timestamp_null_pruned,map_duration_null_pruned,map_wrapper_null_pruned,map_anytype_null_retained,single_scalar,repeated,map,list_value,single_struct",
- "proto2/quoted_fields/set_field_with_quoted_name,get_field_with_quoted_name",
- "proto2/extensions_has/package_scoped_int32,package_scoped_nested_ext,package_scoped_test_all_types_ext,package_scoped_test_all_types_nested_enum_ext,package_scoped_repeated_test_all_types,message_scoped_int64,message_scoped_nested_ext,message_scoped_nested_enum_ext,message_scoped_repeated_test_all_types",
- "proto2/extensions_get/package_scoped_int32,package_scoped_nested_ext,package_scoped_test_all_types_ext,package_scoped_test_all_types_nested_enum_ext,package_scoped_repeated_test_all_types,message_scoped_int64,message_scoped_nested_ext,message_scoped_nested_enum_ext,message_scoped_repeated_test_all_types",
- "proto3/set_null/single_message,single_duration,single_timestamp,repeated_field_timestamp_null_pruned,repeated_field_duration_null_pruned,repeated_field_wrapper_null_pruned,map_timestamp_null_pruned,map_duration_null_pruned,map_wrapper_null_pruned,map_anytype_null_retained,single_scalar,repeated,map,list_value,single_struct",
- "proto3/quoted_fields/set_field,get_field",
- "timestamps/timestamp_conversions/type_comparison",
- "timestamps/duration_conversions/type_comparison",
- "wrappers/bool/to_null",
- "wrappers/int32/to_null",
- "wrappers/int64/to_null",
- "wrappers/uint32/to_null",
- "wrappers/uint64/to_null",
- "wrappers/float/to_null",
- "wrappers/double/to_null",
- "wrappers/bytes/to_null",
- "wrappers/string/to_null",
- "dynamic/int32/field_assign_proto2_range,field_assign_proto3_range",
- "dynamic/uint32/field_assign_proto2_range,field_assign_proto3_range",
- "dynamic/float/field_assign_proto2_range,field_assign_proto3_range",
- "enums/legacy_proto2/assign_standalone_int_too_big,assign_standalone_int_too_neg",
- "enums/legacy_proto3/assign_standalone_int_too_big,assign_standalone_int_too_neg",
- "enums/strong_proto2",
- "enums/strong_proto3",
- "fields/qualified_identifier_resolution/map_key_float",
- "wrappers/uint64/to_json_string",
- "wrappers/field_mask/to_json",
- "wrappers/timestamp/to_json",
- "wrappers/empty/to_json");
+ // Strong enum semantics require typed enum values rather than treating enum literals as
+ // ints.
+ "enums/strong_proto2/literal_global",
+ "enums/strong_proto2/literal_nested",
+ "enums/strong_proto2/literal_zero",
+ "enums/strong_proto2/type_global",
+ "enums/strong_proto2/type_nested",
+ "enums/strong_proto2/select_default",
+ "enums/strong_proto2/field_type",
+ "enums/strong_proto2/assign_standalone_int",
+ "enums/strong_proto2/convert_int_inrange",
+ "enums/strong_proto2/convert_int_big",
+ "enums/strong_proto2/convert_int_neg",
+ "enums/strong_proto2/convert_int_too_big",
+ "enums/strong_proto2/convert_int_too_neg",
+ "enums/strong_proto2/convert_string",
+ "enums/strong_proto2/convert_string_bad",
+ "enums/strong_proto3/literal_global",
+ "enums/strong_proto3/literal_nested",
+ "enums/strong_proto3/literal_zero",
+ "enums/strong_proto3/type_global",
+ "enums/strong_proto3/type_nested",
+ "enums/strong_proto3/select_default",
+ "enums/strong_proto3/select",
+ "enums/strong_proto3/select_big",
+ "enums/strong_proto3/select_neg",
+ "enums/strong_proto3/field_type",
+ "enums/strong_proto3/assign_standalone_int",
+ "enums/strong_proto3/assign_standalone_int_big",
+ "enums/strong_proto3/assign_standalone_int_neg",
+ "enums/strong_proto3/convert_int_inrange",
+ "enums/strong_proto3/convert_int_big",
+ "enums/strong_proto3/convert_int_neg",
+ "enums/strong_proto3/convert_int_too_big",
+ "enums/strong_proto3/convert_int_too_neg",
+ "enums/strong_proto3/convert_string",
+ "enums/strong_proto3/convert_string_bad");
private static final Set matchedSkips = new LinkedHashSet<>();
private static final AtomicInteger total = new AtomicInteger();
private static final AtomicInteger passed = new AtomicInteger();
private static final AtomicInteger skipped = new AtomicInteger();
+ private enum EvaluationMode {
+ NATIVE_ENABLED("native evaluation enabled"),
+ NATIVE_DISABLED("native evaluation disabled");
+
+ private final String displayName;
+
+ EvaluationMode(String displayName) {
+ this.displayName = displayName;
+ }
+ }
+
@TestFactory
Stream simpleConformance() {
List files = new ArrayList<>();
- TEST_FILES.forEach(fileName -> files.add(dynamicContainer(fileName, fileTests(fileName))));
+ for (EvaluationMode mode : EvaluationMode.values()) {
+ files.add(
+ dynamicContainer(
+ mode.displayName,
+ TEST_FILES.stream()
+ .map(fileName -> dynamicContainer(fileName, fileTests(fileName, mode)))));
+ }
files.add(dynamicTest("skip list matches testdata", this::assertAllSkipsMatched));
return files.stream();
}
@@ -195,11 +226,11 @@ Stream simpleConformance() {
@AfterAll
static void printSummary() {
System.out.printf(
- "Conformance tests: %d total, %d passed, %d skipped%n",
+ "Conformance test executions: %d total, %d passed, %d skipped%n",
total.get(), passed.get(), skipped.get());
}
- private Stream fileTests(String fileName) {
+ private Stream fileTests(String fileName, EvaluationMode mode) {
SimpleTestFile file;
try {
file = parseSimpleFile(TESTDATA_DIR.resolve(fileName));
@@ -208,15 +239,17 @@ private Stream fileTests(String fileName) {
}
return file.getSectionList().stream()
- .map(
- section ->
- dynamicContainer(
- section.getName(),
- section.getTestList().stream()
- .map(test -> dynamicTest(test.getName(), () -> run(file, section, test)))));
+ .map(section -> dynamicContainer(section.getName(), sectionTests(file, section, mode)));
}
- private void run(SimpleTestFile file, SimpleTestSection section, SimpleTest test)
+ private Stream sectionTests(
+ SimpleTestFile file, SimpleTestSection section, EvaluationMode mode) {
+ return section.getTestList().stream()
+ .map(test -> dynamicTest(test.getName(), () -> run(file, section, test, mode)));
+ }
+
+ private void run(
+ SimpleTestFile file, SimpleTestSection section, SimpleTest test, EvaluationMode mode)
throws InvalidProtocolBufferException {
total.incrementAndGet();
String sectionPath = file.getName() + "/" + section.getName();
@@ -232,7 +265,7 @@ private void run(SimpleTestFile file, SimpleTestSection section, SimpleTest test
abort("Skipped conformance test " + testPath);
}
- ConformanceCaseRunner.run(testPath, test);
+ ConformanceCaseRunner.run(mode, testPath, test);
passed.incrementAndGet();
}
@@ -261,10 +294,37 @@ private static SimpleTestFile parseSimpleFile(Path testFile) throws IOException
TextFormat.Parser.newBuilder()
.setTypeRegistry(typeRegistry)
.build()
- .merge(Files.readString(testFile, StandardCharsets.UTF_8), extensionRegistry, builder);
+ .merge(
+ encodeProto3NumericEnumAnyValues(Files.readString(testFile, StandardCharsets.UTF_8)),
+ extensionRegistry,
+ builder);
return builder.build();
}
+ private static String encodeProto3NumericEnumAnyValues(String testData) {
+ // Protobuf 3's text-format parser rejects unknown numeric proto3 enum values, although its
+ // generated builders and binary format preserve them. Rewrite these narrowly shaped expanded
+ // Any literals to the equivalent raw Any representation so the conformance cases remain intact.
+ Matcher matcher = PROTO3_NUMERIC_ENUM_ANY.matcher(testData);
+ StringBuilder encoded = new StringBuilder(testData.length());
+ while (matcher.find()) {
+ int enumValue = Integer.parseInt(matcher.group(1));
+ Any any =
+ Any.pack(
+ dev.cel.expr.conformance.proto3.TestAllTypes.newBuilder()
+ .setStandaloneEnumValue(enumValue)
+ .build());
+ String replacement =
+ "type_url: \""
+ + any.getTypeUrl()
+ + "\" value: \""
+ + TextFormat.escapeBytes(any.getValue())
+ + "\"";
+ matcher.appendReplacement(encoded, Matcher.quoteReplacement(replacement));
+ }
+ return matcher.appendTail(encoded).toString();
+ }
+
private static Path testdataDir() {
Path rootRelative = Path.of("submodules/cel-spec/tests/simple/testdata");
if (Files.isDirectory(rootRelative)) {
@@ -282,7 +342,7 @@ private static Path testdataDir() {
private static final class ConformanceCaseRunner {
private ConformanceCaseRunner() {}
- private static void run(String testPath, SimpleTest test)
+ private static void run(EvaluationMode mode, String testPath, SimpleTest test)
throws InvalidProtocolBufferException {
if (test.getName().isEmpty()) {
throw new IllegalArgumentException("simple test has no name");
@@ -315,9 +375,10 @@ private static void run(String testPath, SimpleTest test)
return;
}
- match(testPath, test, ConformanceEvaluator.evalParsed(test, parsedExpr));
+ String evaluationPath = mode.displayName + "/" + testPath;
+ match(evaluationPath, test, ConformanceEvaluator.evalParsed(mode, test, parsedExpr));
if (checkedExpr != null) {
- match(testPath, test, ConformanceEvaluator.evalChecked(test, checkedExpr));
+ match(evaluationPath, test, ConformanceEvaluator.evalChecked(mode, test, checkedExpr));
}
}
}
@@ -335,6 +396,12 @@ private static ParsedExpr parse(SimpleTest test) {
if (test.getDisableMacros()) {
parseOptions.add(clearMacros());
}
+ if (usesTestOnlyBlockMacros(test.getExpr())) {
+ parseOptions.add(macros(Macro.TestOnlyBlockMacros));
+ }
+ if (usesOptionals(test.getExpr())) {
+ parseOptions.add(optionals());
+ }
Env env = newEnv(parseOptions.toArray(new EnvOption[0]));
AstIssuesTuple astIss = env.parse(sourceText);
@@ -353,12 +420,8 @@ private static CheckedExpr check(SimpleTest test, ParsedExpr parsedExpr)
Env env =
newCustomEnv(
- StdLib(),
- container(test.getContainer()),
- declarations(typeEnv),
- types(
- dev.cel.expr.conformance.proto2.TestAllTypes.getDefaultInstance(),
- dev.cel.expr.conformance.proto3.TestAllTypes.getDefaultInstance()));
+ conformanceEnvOptions(test, StdLib(), declarations(typeEnv))
+ .toArray(new EnvOption[0]));
AstIssuesTuple astIss = env.check(parsedExprToAst(parsedExpr));
if (astIss.hasIssues()) {
@@ -367,23 +430,23 @@ private static CheckedExpr check(SimpleTest test, ParsedExpr parsedExpr)
return astToCheckedExpr(astIss.getAst());
}
- private static ExprValue evalParsed(SimpleTest test, ParsedExpr parsedExpr) {
- return eval(test, parsedExprToAst(parsedExpr));
+ private static ExprValue evalParsed(
+ EvaluationMode mode, SimpleTest test, ParsedExpr parsedExpr) {
+ return eval(mode, test, parsedExprToAst(parsedExpr));
}
- private static ExprValue evalChecked(SimpleTest test, CheckedExpr checkedExpr) {
- return eval(test, checkedExprToAst(checkedExpr));
+ private static ExprValue evalChecked(
+ EvaluationMode mode, SimpleTest test, CheckedExpr checkedExpr) {
+ return eval(mode, test, checkedExprToAst(checkedExpr));
}
- private static ExprValue eval(SimpleTest test, Ast ast) {
- Env env =
- newEnv(
- container(test.getContainer()),
- types(
- dev.cel.expr.conformance.proto2.TestAllTypes.getDefaultInstance(),
- dev.cel.expr.conformance.proto3.TestAllTypes.getDefaultInstance()));
+ private static ExprValue eval(EvaluationMode mode, SimpleTest test, Ast ast) {
+ Env env = newEnv(conformanceEnvOptions(test).toArray(new EnvOption[0]));
- Program program = env.program(ast);
+ Program program =
+ mode == EvaluationMode.NATIVE_ENABLED
+ ? env.program(ast)
+ : env.program(ast, evalOptions(OptDisableNativeEval));
Map args = new HashMap<>();
test.getBindingsMap()
.forEach(
@@ -392,7 +455,7 @@ private static ExprValue eval(SimpleTest test, Ast ast) {
EvalResult res = program.eval(args);
if (!isError(res.getVal())) {
- return refValueToExprValue(res.getVal());
+ return refValueToExprValue(env.getTypeAdapter(), res.getVal());
}
Err err = (Err) res.getVal();
@@ -400,6 +463,76 @@ private static ExprValue eval(SimpleTest test, Ast ast) {
.setError(ErrorSet.newBuilder().addErrors(Status.newBuilder().setMessage(err.toString())))
.build();
}
+
+ private static List conformanceEnvOptions(SimpleTest test, EnvOption... options) {
+ List envOptions = new ArrayList<>();
+ envOptions.add(container(test.getContainer()));
+ envOptions.add(
+ types(
+ dev.cel.expr.conformance.proto2.TestAllTypes.getDefaultInstance(),
+ dev.cel.expr.conformance.proto2.Proto2ExtensionScopedMessage.getDefaultInstance(),
+ dev.cel.expr.conformance.proto3.TestAllTypes.getDefaultInstance()));
+ if (test.getExpr().startsWith("proto.hasExt(")
+ || test.getExpr().startsWith("proto.getExt(")) {
+ envOptions.add(proto());
+ }
+ if (usesStringExtensions(test.getExpr())) {
+ envOptions.add(strings());
+ }
+ if (test.getExpr().contains("base64.")) {
+ envOptions.add(encoders());
+ }
+ if (test.getExpr().contains("math.")) {
+ envOptions.add(math());
+ }
+ if (usesNetworkExtensions(test.getExpr())) {
+ envOptions.add(network());
+ }
+ if (usesOptionals(test.getExpr())) {
+ envOptions.add(optionals());
+ }
+ envOptions.addAll(List.of(options));
+ return envOptions;
+ }
+
+ private static boolean usesStringExtensions(String expression) {
+ return expression.contains(".charAt(")
+ || expression.contains(".indexOf(")
+ || expression.contains(".lastIndexOf(")
+ || expression.contains(".lowerAscii(")
+ || expression.contains(".upperAscii(")
+ || expression.contains(".replace(")
+ || expression.contains(".split(")
+ || expression.contains(".substring(")
+ || expression.contains(".trim(")
+ || expression.contains(".join(")
+ || expression.contains("strings.quote(")
+ || expression.contains(".format(")
+ || expression.contains(".reverse(");
+ }
+
+ private static boolean usesOptionals(String expression) {
+ return expression.contains("optional.")
+ || expression.contains(".?")
+ || expression.contains("[?")
+ || expression.contains("{?");
+ }
+
+ private static boolean usesNetworkExtensions(String expression) {
+ return expression.contains("ip(")
+ || expression.contains("cidr(")
+ || expression.contains("isIP(")
+ || expression.contains("ip.isCanonical(")
+ || expression.contains("net.IP")
+ || expression.contains("net.CIDR");
+ }
+
+ private static boolean usesTestOnlyBlockMacros(String expression) {
+ return expression.contains("cel.block(")
+ || expression.contains("cel.index(")
+ || expression.contains("cel.iterVar(")
+ || expression.contains("cel.accuVar(");
+ }
}
private static void match(String testPath, SimpleTest test, ExprValue actual)
@@ -524,16 +657,12 @@ private static Val exprValueToRefValue(TypeAdapter adapter, dev.cel.expr.ExprVal
}
private static Val exprValueToRefValue(TypeAdapter adapter, ExprValue ev) {
- switch (ev.getKindCase()) {
- case VALUE:
- return valueToRefValue(adapter, ev.getValue());
- case ERROR:
- return newErr("XXX add details later");
- case UNKNOWN:
- return unknownOf(ev.getUnknown().getExprs(0));
- default:
- throw new IllegalArgumentException("unknown ExprValue kind " + ev.getKindCase());
- }
+ return switch (ev.getKindCase()) {
+ case VALUE -> valueToRefValue(adapter, ev.getValue());
+ case ERROR -> newErr("XXX add details later");
+ case UNKNOWN -> unknownOf(ev.getUnknown().getExprs(0));
+ default -> throw new IllegalArgumentException("unknown ExprValue kind " + ev.getKindCase());
+ };
}
private static Val valueToRefValue(TypeAdapter adapter, Value v) {
@@ -574,28 +703,32 @@ private static Val valueToRefValue(TypeAdapter adapter, Value v) {
return type;
}
return newObjectTypeValue(typeName);
+ case ENUM_VALUE:
+ return intOf(v.getEnumValue().getValue());
default:
throw new IllegalArgumentException("unknown value " + v.getKindCase());
}
}
- private static ExprValue refValueToExprValue(Val res) {
+ private static ExprValue refValueToExprValue(TypeAdapter adapter, Val res) {
if (isUnknown(res)) {
return ExprValue.newBuilder()
.setUnknown(UnknownSet.newBuilder().addExprs(res.intValue()))
.build();
}
- return ExprValue.newBuilder().setValue(refValueToValue(res)).build();
+ return ExprValue.newBuilder().setValue(refValueToValue(adapter, res)).build();
}
- private static Value refValueToValue(Val res) {
+ private static Value refValueToValue(TypeAdapter adapter, Val res) {
switch (res.type().typeEnum()) {
case Bool:
return Value.newBuilder().setBoolValue(res.booleanValue()).build();
case Bytes:
- return Value.newBuilder().setBytesValue(res.convertToNative(ByteString.class)).build();
+ return Value.newBuilder()
+ .setBytesValue(adapter.valueToNative(res, ByteString.class))
+ .build();
case Double:
- return Value.newBuilder().setDoubleValue(res.convertToNative(Double.class)).build();
+ return Value.newBuilder().setDoubleValue(adapter.valueToDouble(res)).build();
case Int:
return Value.newBuilder().setInt64Value(res.intValue()).build();
case Null:
@@ -608,17 +741,17 @@ private static Value refValueToValue(Val res) {
return Value.newBuilder().setUint64Value(res.intValue()).build();
case Duration:
return Value.newBuilder()
- .setObjectValue(Any.pack(res.convertToNative(Duration.class)))
+ .setObjectValue(Any.pack(adapter.valueToNative(res, Duration.class)))
.build();
case Timestamp:
return Value.newBuilder()
- .setObjectValue(Any.pack(res.convertToNative(Timestamp.class)))
+ .setObjectValue(Any.pack(adapter.valueToNative(res, Timestamp.class)))
.build();
case List:
Lister lister = (Lister) res;
ListValue.Builder elements = ListValue.newBuilder();
for (IteratorT i = lister.iterator(); i.hasNext() == True; ) {
- elements.addValues(refValueToValue(i.next()));
+ elements.addValues(refValueToValue(adapter, i.next()));
}
return Value.newBuilder().setListValue(elements).build();
case Map:
@@ -628,14 +761,16 @@ private static Value refValueToValue(Val res) {
Val key = i.next();
entries
.addEntriesBuilder()
- .setKey(refValueToValue(key))
- .setValue(refValueToValue(mapper.get(key)));
+ .setKey(refValueToValue(adapter, key))
+ .setValue(refValueToValue(adapter, mapper.get(key)));
}
return Value.newBuilder().setMapValue(entries).build();
case Object:
Message pb = (Message) res.value();
Value.Builder value = Value.newBuilder();
- if (pb instanceof ListValue) {
+ if (pb instanceof Any) {
+ value.setObjectValue(unwrapNestedAny((Any) pb));
+ } else if (pb instanceof ListValue) {
value.setListValue((ListValue) pb);
} else if (pb instanceof MapValue) {
value.setMapValue((MapValue) pb);
@@ -648,6 +783,22 @@ private static Value refValueToValue(Val res) {
}
}
+ private static Any unwrapNestedAny(Any any) {
+ Any current = any;
+ while (current.is(Any.class)) {
+ try {
+ Any next = current.unpack(Any.class);
+ if (next.equals(current)) {
+ return current;
+ }
+ current = next;
+ } catch (InvalidProtocolBufferException e) {
+ return current;
+ }
+ }
+ return current;
+ }
+
private static T convert(Message message, Class targetType)
throws InvalidProtocolBufferException {
try {
@@ -665,7 +816,7 @@ private static T convert(Message message, Class targetTyp
}
private static String print(Message message) {
- return TEXT_PRINTER.printToString(message);
+ return TextFormat.shortDebugString(message);
}
private static final class SkipList {
diff --git a/core/build.gradle.kts b/core/build.gradle.kts
index 67a2b529..63a9ec7e 100644
--- a/core/build.gradle.kts
+++ b/core/build.gradle.kts
@@ -24,13 +24,17 @@ plugins {
`java-test-fixtures`
}
+val congocc = configurations.create("congocc")
+
configurations.named("jmhImplementation") { extendsFrom(configurations.testFixturesApi.get()) }
dependencies {
- implementation(project(":cel-generated-antlr"))
compileOnly(project(":cel-generated-pb"))
implementation(libs.agrona)
+ implementation(libs.re2j)
+
+ congocc(libs.congocc)
testImplementation(project(":cel-generated-pb"))
testFixturesApi(platform(libs.junit.bom))
@@ -46,13 +50,57 @@ dependencies {
jmhAnnotationProcessor(libs.jmh.generator.annprocess)
}
+abstract class Generate : JavaExec() {
+ init {
+ outputs.cacheIf { true }
+ }
+
+ @get:InputDirectory
+ @get:PathSensitive(PathSensitivity.RELATIVE)
+ abstract val sourceDir: DirectoryProperty
+
+ @get:OutputDirectory abstract val outputDir: DirectoryProperty
+}
+
+val generateCelGrammar =
+ tasks.register("generateCelGrammar") {
+ val generatedDir = layout.buildDirectory.dir("generated/sources/congocc/cel")
+ val projectDir = layout.projectDirectory
+
+ sourceDir = projectDir.dir("src/main/congocc/cel")
+ outputDir = generatedDir
+
+ classpath(congocc)
+ mainClass = "org.congocc.app.Main"
+ workingDir(projectDir)
+
+ doFirst { generatedDir.get().asFile.deleteRecursively() }
+
+ argumentProviders.add(
+ CommandLineArgumentProvider {
+ val sourceFile = sourceDir.file("cel-java.ccc").get().asFile.relativeTo(projectDir.asFile)
+ val base =
+ listOf(
+ "-d",
+ generatedDir.get().asFile.toString(),
+ "-jdk17",
+ "-n",
+ sourceFile.toString(),
+ )
+ if (logger.isInfoEnabled) base else base + "-q"
+ }
+ )
+ }
+
jmh { jmhVersion.set(libs.versions.jmh.get()) }
+sourceSets.main { java.srcDir(generateCelGrammar) }
+
sourceSets.test {
java.srcDir(layout.buildDirectory.dir("generated/source/proto/test/java"))
java.destinationDirectory.set(layout.buildDirectory.dir("classes/java/generatedTest"))
}
-tasks.named("check") { dependsOn(tasks.named("jmh")) }
+tasks.named("compileJava") { dependsOn(generateCelGrammar) }
tasks.named("assemble") { dependsOn(tasks.named("jmhJar")) }
diff --git a/core/src/jmh/java/org/projectnessie/cel/CompileBuildBench.java b/core/src/jmh/java/org/projectnessie/cel/CompileBuildBench.java
index 76bb13ab..8fe49da5 100644
--- a/core/src/jmh/java/org/projectnessie/cel/CompileBuildBench.java
+++ b/core/src/jmh/java/org/projectnessie/cel/CompileBuildBench.java
@@ -51,17 +51,17 @@ public static class CompileState {
public String expression;
String source() {
- switch (expression) {
- case "simplePredicate":
- return "resource == 'projects/p1' && user == 'alice'";
- case "deepSelectors":
- return "request.auth.claims.email.endsWith('@example.com')"
- + " && request.resource.labels['env'] == 'prod'";
- case "macroPipeline":
- return "items.filter(i, i.score > 10).map(i, i.name).exists(n, n.startsWith('a'))";
- default:
- throw new IllegalArgumentException("Unknown compile benchmark expression: " + expression);
- }
+ return switch (expression) {
+ case "simplePredicate" -> "resource == 'projects/p1' && user == 'alice'";
+ case "deepSelectors" ->
+ "request.auth.claims.email.endsWith('@example.com')"
+ + " && request.resource.labels['env'] == 'prod'";
+ case "macroPipeline" ->
+ "items.filter(i, i.score > 10).map(i, i.name).exists(n, n.startsWith('a'))";
+ default ->
+ throw new IllegalArgumentException(
+ "Unknown compile benchmark expression: " + expression);
+ };
}
}
diff --git a/core/src/jmh/java/org/projectnessie/cel/EvaluatorBaselineBench.java b/core/src/jmh/java/org/projectnessie/cel/EvaluatorBaselineBench.java
new file mode 100644
index 00000000..35025ca1
--- /dev/null
+++ b/core/src/jmh/java/org/projectnessie/cel/EvaluatorBaselineBench.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2021 The Authors of CEL-Java
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.projectnessie.cel;
+
+import static org.projectnessie.cel.Env.newEnv;
+import static org.projectnessie.cel.EnvOption.declarations;
+import static org.projectnessie.cel.EnvOption.types;
+import static org.projectnessie.cel.EvalOption.OptOptimize;
+import static org.projectnessie.cel.ProgramOption.evalOptions;
+import static org.projectnessie.cel.interpreter.Activation.newActivation;
+
+import dev.cel.expr.conformance.proto3.TestAllTypes;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Supplier;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Threads;
+import org.openjdk.jmh.annotations.Warmup;
+import org.projectnessie.cel.Env.AstIssuesTuple;
+import org.projectnessie.cel.checker.Decls;
+import org.projectnessie.cel.interpreter.Activation;
+
+/** Attributes evaluator cost at the raw, public-program, and native-result boundaries. */
+@Warmup(iterations = 3, time = 500, timeUnit = TimeUnit.MILLISECONDS)
+@Measurement(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS)
+@Fork(1)
+@Threads(1)
+@BenchmarkMode(Mode.AverageTime)
+@OutputTimeUnit(TimeUnit.NANOSECONDS)
+public class EvaluatorBaselineBench {
+
+ @State(Scope.Benchmark)
+ public static class EvaluationState {
+ @Param({
+ "identityInt",
+ "addInt",
+ "chainInt",
+ "chainDouble",
+ "chainString",
+ "shortCircuit",
+ "mapSelection",
+ "protoSelection"
+ })
+ public String expression;
+
+ Program program;
+ Prog internalProgram;
+ Map variables;
+ Activation activation;
+ Class> nativeResultType;
+ Supplier