2626import com .google .testing .junit .testparameterinjector .TestParameterInjector ;
2727import com .google .testing .junit .testparameterinjector .TestParameters ;
2828import dev .cel .bundle .Cel ;
29- import dev .cel .bundle .CelFactory ;
3029import dev .cel .common .CelAbstractSyntaxTree ;
3130import dev .cel .common .CelContainer ;
3231import dev .cel .common .CelFunctionDecl ;
3534import dev .cel .common .CelValidationException ;
3635import dev .cel .common .types .SimpleType ;
3736import dev .cel .common .types .StructTypeReference ;
38- import dev .cel .compiler .CelCompiler ;
39- import dev .cel .compiler .CelCompilerFactory ;
4037import dev .cel .expr .conformance .proto2 .Proto2ExtensionScopedMessage ;
4138import dev .cel .expr .conformance .proto2 .TestAllTypes ;
4239import dev .cel .expr .conformance .proto2 .TestAllTypes .NestedEnum ;
4340import dev .cel .expr .conformance .proto2 .TestAllTypesExtensions ;
4441import dev .cel .parser .CelMacro ;
4542import dev .cel .parser .CelStandardMacro ;
4643import dev .cel .runtime .CelFunctionBinding ;
47- import dev .cel .runtime .CelRuntime ;
48- import dev .cel .runtime .CelRuntimeFactory ;
44+ import dev .cel .testing .CelRuntimeFlavor ;
45+ import java .util .Map ;
46+ import org .junit .Assume ;
47+ import org .junit .Before ;
4948import org .junit .Test ;
5049import org .junit .runner .RunWith ;
5150
5251@ RunWith (TestParameterInjector .class )
5352public final class CelProtoExtensionsTest {
5453
55- private static final CelCompiler CEL_COMPILER =
56- CelCompilerFactory .standardCelCompilerBuilder ()
57- .addLibraries (CelExtensions .protos ())
58- .setStandardMacros (CelStandardMacro .STANDARD_MACROS )
59- .addFileTypes (TestAllTypesExtensions .getDescriptor ())
60- .addVar ("msg" , StructTypeReference .create ("cel.expr.conformance.proto2.TestAllTypes" ))
61- .setContainer (CelContainer .ofName ("cel.expr.conformance.proto2" ))
62- .build ();
54+ @ TestParameter public CelRuntimeFlavor runtimeFlavor ;
55+ @ TestParameter public boolean isParseOnly ;
6356
64- private static final CelRuntime CEL_RUNTIME =
65- CelRuntimeFactory .standardCelRuntimeBuilder ()
66- .addFileTypes (TestAllTypesExtensions .getDescriptor ())
67- .build ();
57+ private Cel cel ;
58+
59+ @ Before
60+ public void setUp () {
61+ // Legacy runtime does not support parsed-only evaluation mode.
62+ Assume .assumeFalse (runtimeFlavor .equals (CelRuntimeFlavor .LEGACY ) && isParseOnly );
63+ this .cel =
64+ runtimeFlavor
65+ .builder ()
66+ .addCompilerLibraries (CelExtensions .protos ())
67+ .setStandardMacros (CelStandardMacro .STANDARD_MACROS )
68+ .addFileTypes (TestAllTypesExtensions .getDescriptor ())
69+ .addVar ("msg" , StructTypeReference .create ("cel.expr.conformance.proto2.TestAllTypes" ))
70+ .setContainer (CelContainer .ofName ("cel.expr.conformance.proto2" ))
71+ .build ();
72+ }
6873
6974 private static final TestAllTypes PACKAGE_SCOPED_EXT_MSG =
7075 TestAllTypes .newBuilder ()
@@ -106,10 +111,7 @@ public void library() {
106111 "{expr: 'proto.hasExt(msg, cel.expr.conformance.proto2.repeated_test_all_types)'}" )
107112 @ TestParameters ("{expr: '!proto.hasExt(msg, cel.expr.conformance.proto2.test_all_types_ext)'}" )
108113 public void hasExt_packageScoped_success (String expr ) throws Exception {
109- CelAbstractSyntaxTree ast = CEL_COMPILER .compile (expr ).getAst ();
110- boolean result =
111- (boolean )
112- CEL_RUNTIME .createProgram (ast ).eval (ImmutableMap .of ("msg" , PACKAGE_SCOPED_EXT_MSG ));
114+ boolean result = (boolean ) eval (expr , ImmutableMap .of ("msg" , PACKAGE_SCOPED_EXT_MSG ));
113115
114116 assertThat (result ).isTrue ();
115117 }
@@ -128,10 +130,7 @@ public void hasExt_packageScoped_success(String expr) throws Exception {
128130 "{expr: '!proto.hasExt(msg,"
129131 + " cel.expr.conformance.proto2.Proto2ExtensionScopedMessage.nested_enum_ext)'}" )
130132 public void hasExt_messageScoped_success (String expr ) throws Exception {
131- CelAbstractSyntaxTree ast = CEL_COMPILER .compile (expr ).getAst ();
132- boolean result =
133- (boolean )
134- CEL_RUNTIME .createProgram (ast ).eval (ImmutableMap .of ("msg" , MESSAGE_SCOPED_EXT_MSG ));
133+ boolean result = (boolean ) eval (expr , ImmutableMap .of ("msg" , MESSAGE_SCOPED_EXT_MSG ));
135134
136135 assertThat (result ).isTrue ();
137136 }
@@ -142,9 +141,10 @@ public void hasExt_messageScoped_success(String expr) throws Exception {
142141 public void hasExt_nonProtoNamespace_success (String expr ) throws Exception {
143142 StructTypeReference proto2MessageTypeReference =
144143 StructTypeReference .create ("cel.expr.conformance.proto2.TestAllTypes" );
145- CelCompiler celCompiler =
146- CelCompilerFactory .standardCelCompilerBuilder ()
147- .addLibraries (CelExtensions .protos ())
144+ Cel customCel =
145+ runtimeFlavor
146+ .builder ()
147+ .addCompilerLibraries (CelExtensions .protos ())
148148 .addVar ("msg" , proto2MessageTypeReference )
149149 .addFunctionDeclarations (
150150 CelFunctionDecl .newFunctionDeclaration (
@@ -154,37 +154,35 @@ public void hasExt_nonProtoNamespace_success(String expr) throws Exception {
154154 SimpleType .BOOL ,
155155 ImmutableList .of (
156156 proto2MessageTypeReference , SimpleType .STRING , SimpleType .INT ))))
157- .build ();
158- CelRuntime celRuntime =
159- CelRuntimeFactory .standardCelRuntimeBuilder ()
160157 .addFunctionBindings (
161- CelFunctionBinding .from (
162- "msg_hasExt" ,
163- ImmutableList .of (TestAllTypes .class , String .class , Long .class ),
164- (arg ) -> {
165- TestAllTypes msg = (TestAllTypes ) arg [0 ];
166- String extensionField = (String ) arg [1 ];
167- return msg .getAllFields ().keySet ().stream ()
168- .anyMatch (fd -> fd .getFullName ().equals (extensionField ));
169- }))
158+ CelFunctionBinding .fromOverloads (
159+ "hasExt" ,
160+ CelFunctionBinding .from (
161+ "msg_hasExt" ,
162+ ImmutableList .of (TestAllTypes .class , String .class , Long .class ),
163+ (arg ) -> {
164+ TestAllTypes msg = (TestAllTypes ) arg [0 ];
165+ String extensionField = (String ) arg [1 ];
166+ return msg .getAllFields ().keySet ().stream ()
167+ .anyMatch (fd -> fd .getFullName ().equals (extensionField ));
168+ })))
170169 .build ();
171170
172- CelAbstractSyntaxTree ast = celCompiler .compile (expr ).getAst ();
173171 boolean result =
174- (boolean )
175- celRuntime .createProgram (ast ).eval (ImmutableMap .of ("msg" , PACKAGE_SCOPED_EXT_MSG ));
172+ (boolean ) eval (customCel , expr , ImmutableMap .of ("msg" , PACKAGE_SCOPED_EXT_MSG ));
176173
177174 assertThat (result ).isTrue ();
178175 }
179176
180177 @ Test
181178 public void hasExt_undefinedField_throwsException () {
179+ // This is a type-checking failure
180+ Assume .assumeFalse (isParseOnly );
182181 CelValidationException exception =
183182 assertThrows (
184183 CelValidationException .class ,
185184 () ->
186- CEL_COMPILER
187- .compile ("!proto.hasExt(msg, cel.expr.conformance.proto2.undefined_field)" )
185+ cel .compile ("!proto.hasExt(msg, cel.expr.conformance.proto2.undefined_field)" )
188186 .getAst ());
189187
190188 assertThat (exception )
@@ -204,10 +202,7 @@ public void hasExt_undefinedField_throwsException() {
204202 "{expr: 'proto.getExt(msg, cel.expr.conformance.proto2.repeated_test_all_types) =="
205203 + " [TestAllTypes{single_string: ''A''}, TestAllTypes{single_string: ''B''}]'}" )
206204 public void getExt_packageScoped_success (String expr ) throws Exception {
207- CelAbstractSyntaxTree ast = CEL_COMPILER .compile (expr ).getAst ();
208- boolean result =
209- (boolean )
210- CEL_RUNTIME .createProgram (ast ).eval (ImmutableMap .of ("msg" , PACKAGE_SCOPED_EXT_MSG ));
205+ boolean result = (boolean ) eval (expr , ImmutableMap .of ("msg" , PACKAGE_SCOPED_EXT_MSG ));
211206
212207 assertThat (result ).isTrue ();
213208 }
@@ -221,22 +216,20 @@ public void getExt_packageScoped_success(String expr) throws Exception {
221216 "{expr: 'proto.getExt(msg,"
222217 + " cel.expr.conformance.proto2.Proto2ExtensionScopedMessage.int64_ext) == 1'}" )
223218 public void getExt_messageScopedSuccess (String expr ) throws Exception {
224- CelAbstractSyntaxTree ast = CEL_COMPILER .compile (expr ).getAst ();
225- boolean result =
226- (boolean )
227- CEL_RUNTIME .createProgram (ast ).eval (ImmutableMap .of ("msg" , MESSAGE_SCOPED_EXT_MSG ));
219+ boolean result = (boolean ) eval (expr , ImmutableMap .of ("msg" , MESSAGE_SCOPED_EXT_MSG ));
228220
229221 assertThat (result ).isTrue ();
230222 }
231223
232224 @ Test
233225 public void getExt_undefinedField_throwsException () {
226+ // This is a type-checking failure
227+ Assume .assumeFalse (isParseOnly );
234228 CelValidationException exception =
235229 assertThrows (
236230 CelValidationException .class ,
237231 () ->
238- CEL_COMPILER
239- .compile ("!proto.getExt(msg, cel.expr.conformance.proto2.undefined_field)" )
232+ cel .compile ("!proto.getExt(msg, cel.expr.conformance.proto2.undefined_field)" )
240233 .getAst ());
241234
242235 assertThat (exception )
@@ -250,9 +243,10 @@ public void getExt_undefinedField_throwsException() {
250243 public void getExt_nonProtoNamespace_success (String expr ) throws Exception {
251244 StructTypeReference proto2MessageTypeReference =
252245 StructTypeReference .create ("cel.expr.conformance.proto2.TestAllTypes" );
253- CelCompiler celCompiler =
254- CelCompilerFactory .standardCelCompilerBuilder ()
255- .addLibraries (CelExtensions .protos ())
246+ Cel customCel =
247+ runtimeFlavor
248+ .builder ()
249+ .addCompilerLibraries (CelExtensions .protos ())
256250 .addVar ("msg" , proto2MessageTypeReference )
257251 .addFunctionDeclarations (
258252 CelFunctionDecl .newFunctionDeclaration (
@@ -262,29 +256,26 @@ public void getExt_nonProtoNamespace_success(String expr) throws Exception {
262256 SimpleType .DYN ,
263257 ImmutableList .of (
264258 proto2MessageTypeReference , SimpleType .STRING , SimpleType .INT ))))
265- .build ();
266- CelRuntime celRuntime =
267- CelRuntimeFactory .standardCelRuntimeBuilder ()
268259 .addFunctionBindings (
269- CelFunctionBinding .from (
270- "msg_getExt" ,
271- ImmutableList .of (TestAllTypes .class , String .class , Long .class ),
272- (arg ) -> {
273- TestAllTypes msg = (TestAllTypes ) arg [0 ];
274- String extensionField = (String ) arg [1 ];
275- FieldDescriptor extensionDescriptor =
276- msg .getAllFields ().keySet ().stream ()
277- .filter (fd -> fd .getFullName ().equals (extensionField ))
278- .findAny ()
279- .get ();
280- return msg .getField (extensionDescriptor );
281- }))
260+ CelFunctionBinding .fromOverloads (
261+ "getExt" ,
262+ CelFunctionBinding .from (
263+ "msg_getExt" ,
264+ ImmutableList .of (TestAllTypes .class , String .class , Long .class ),
265+ (arg ) -> {
266+ TestAllTypes msg = (TestAllTypes ) arg [0 ];
267+ String extensionField = (String ) arg [1 ];
268+ FieldDescriptor extensionDescriptor =
269+ msg .getAllFields ().keySet ().stream ()
270+ .filter (fd -> fd .getFullName ().equals (extensionField ))
271+ .findAny ()
272+ .get ();
273+ return msg .getField (extensionDescriptor );
274+ })))
282275 .build ();
283276
284- CelAbstractSyntaxTree ast = celCompiler .compile (expr ).getAst ();
285277 boolean result =
286- (boolean )
287- celRuntime .createProgram (ast ).eval (ImmutableMap .of ("msg" , PACKAGE_SCOPED_EXT_MSG ));
278+ (boolean ) eval (customCel , expr , ImmutableMap .of ("msg" , PACKAGE_SCOPED_EXT_MSG ));
288279
289280 assertThat (result ).isTrue ();
290281 }
@@ -293,21 +284,24 @@ public void getExt_nonProtoNamespace_success(String expr) throws Exception {
293284 public void getExt_onAnyPackedExtensionField_success () throws Exception {
294285 ExtensionRegistry extensionRegistry = ExtensionRegistry .newInstance ();
295286 TestAllTypesExtensions .registerAllExtensions (extensionRegistry );
296- Cel cel =
297- CelFactory .standardCelBuilder ()
287+ Cel customCel =
288+ runtimeFlavor
289+ .builder ()
298290 // CEL-Internal-2
299291 .addCompilerLibraries (CelExtensions .protos ())
300292 .addFileTypes (TestAllTypesExtensions .getDescriptor ())
301293 .setExtensionRegistry (extensionRegistry )
302294 .addVar ("msg" , StructTypeReference .create ("cel.expr.conformance.proto2.TestAllTypes" ))
303295 .build ();
304- CelAbstractSyntaxTree ast =
305- cel .compile ("proto.getExt(msg, cel.expr.conformance.proto2.int32_ext)" ).getAst ();
306296 Any anyMsg =
307297 Any .pack (
308298 TestAllTypes .newBuilder ().setExtension (TestAllTypesExtensions .int32Ext , 1 ).build ());
309-
310- Long result = (Long ) cel .createProgram (ast ).eval (ImmutableMap .of ("msg" , anyMsg ));
299+ Long result =
300+ (Long )
301+ eval (
302+ customCel ,
303+ "proto.getExt(msg, cel.expr.conformance.proto2.int32_ext)" ,
304+ ImmutableMap .of ("msg" , anyMsg ));
311305
312306 assertThat (result ).isEqualTo (1 );
313307 }
@@ -343,9 +337,18 @@ private enum ParseErrorTestCase {
343337 @ Test
344338 public void parseErrors (@ TestParameter ParseErrorTestCase testcase ) {
345339 CelValidationException e =
346- assertThrows (
347- CelValidationException .class , () -> CEL_COMPILER .compile (testcase .expr ).getAst ());
340+ assertThrows (CelValidationException .class , () -> cel .parse (testcase .expr ).getAst ());
348341
349342 assertThat (e ).hasMessageThat ().isEqualTo (testcase .error );
350343 }
344+
345+ private Object eval (String expression , Map <String , ?> variables ) throws Exception {
346+ return eval (this .cel , expression , variables );
347+ }
348+
349+ private Object eval (Cel cel , String expression , Map <String , ?> variables ) throws Exception {
350+ CelAbstractSyntaxTree ast =
351+ this .isParseOnly ? cel .parse (expression ).getAst () : cel .compile (expression ).getAst ();
352+ return cel .createProgram (ast ).eval (variables );
353+ }
351354}
0 commit comments