@@ -45,6 +45,7 @@ namespace google::api::expr::runtime {
4545
4646namespace {
4747
48+ using ::absl_testing::IsOk;
4849using ::absl_testing::IsOkAndHolds;
4950using ::absl_testing::StatusIs;
5051using ::cel::Ast;
@@ -343,6 +344,60 @@ TEST(ResolveReferences, EnumConstReferenceUsedSelect) {
343344 })pb" ));
344345}
345346
347+ // foo && bar
348+ constexpr char kConstReferenceExpr [] = R"(
349+ id: 1
350+ call_expr {
351+ function: "_&&_"
352+ args {
353+ id: 2
354+ ident_expr {
355+ name: "foo"
356+ }
357+ }
358+ args {
359+ id: 5
360+ ident_expr {
361+ name: "bar"
362+ }
363+ }
364+ }
365+ )" ;
366+
367+ TEST (ResolveReferences, ConstReferenceFolded) {
368+ std::unique_ptr<Ast> expr_ast = ParseTestProto (kConstReferenceExpr );
369+ SourceInfo source_info;
370+
371+ CelFunctionRegistry func_registry;
372+ ASSERT_THAT (RegisterBuiltinFunctions (&func_registry), IsOk ());
373+ cel::TypeRegistry type_registry;
374+ Resolver registry (" " , func_registry.InternalGetRegistry (), type_registry,
375+ type_registry.GetComposedTypeProvider ());
376+ expr_ast->mutable_reference_map ()[2 ].set_name (" foo" );
377+ expr_ast->mutable_reference_map ()[2 ].mutable_value ().set_bool_value (true );
378+ expr_ast->mutable_reference_map ()[5 ].set_name (" bar" );
379+ expr_ast->mutable_reference_map ()[5 ].mutable_value ().set_bool_value (false );
380+ IssueCollector issues (RuntimeIssue::Severity::kError );
381+
382+ auto result = ResolveReferences (registry, issues, *expr_ast);
383+
384+ ASSERT_THAT (result, IsOkAndHolds (true ));
385+
386+ EXPECT_THAT (ExprToProtoOrDie (expr_ast->root_expr ()), EqualsProto (R"pb(
387+ id: 1
388+ call_expr {
389+ function: "_&&_"
390+ args {
391+ id: 2
392+ const_expr { bool_value: true }
393+ }
394+ args {
395+ id: 5
396+ const_expr { bool_value: false }
397+ }
398+ })pb" ));
399+ }
400+
346401TEST (ResolveReferences, ConstReferenceSkipped) {
347402 std::unique_ptr<Ast> expr_ast = ParseTestProto (kExpr );
348403 SourceInfo source_info;
@@ -388,6 +443,42 @@ TEST(ResolveReferences, ConstReferenceSkipped) {
388443 })pb" ));
389444}
390445
446+ constexpr char kNullValueReferenceExpr [] = R"(
447+ id: 1
448+ call_expr {
449+ function: "_+_"
450+ args {
451+ id: 2
452+ ident_expr {
453+ name: "google.protobuf.NullValue.NULL_VALUE"
454+ }
455+ }
456+ args {
457+ id: 5
458+ const_expr { int64_value: 1 }
459+ }
460+ }
461+ )" ;
462+
463+ TEST (ResolveReferences, NullValueReferenceSkipped) {
464+ std::unique_ptr<Ast> expr_ast = ParseTestProto (kNullValueReferenceExpr );
465+ SourceInfo source_info;
466+
467+ CelFunctionRegistry func_registry;
468+ ASSERT_THAT (RegisterBuiltinFunctions (&func_registry), IsOk ());
469+ cel::TypeRegistry type_registry;
470+ Resolver registry (" " , func_registry.InternalGetRegistry (), type_registry,
471+ type_registry.GetComposedTypeProvider ());
472+ expr_ast->mutable_reference_map ()[2 ].set_name (
473+ " google.protobuf.NullValue.NULL_VALUE" );
474+ expr_ast->mutable_reference_map ()[2 ].mutable_value ().set_null_value (nullptr );
475+ IssueCollector issues (RuntimeIssue::Severity::kError );
476+
477+ auto result = ResolveReferences (registry, issues, *expr_ast);
478+
479+ ASSERT_THAT (result, IsOkAndHolds (/* was_rewritten=*/ false ));
480+ }
481+
391482constexpr char kExtensionAndExpr [] = R"(
392483id: 1
393484call_expr {
0 commit comments