From 7a1c706760e94b2509c9ae8ce112c92e948c629e Mon Sep 17 00:00:00 2001 From: Jonathan Tatum Date: Mon, 27 Jul 2026 12:57:04 -0700 Subject: [PATCH] Add support for typed has operations. PiperOrigin-RevId: 954783233 --- eval/eval/select_step.cc | 66 +++++++++- eval/tests/BUILD | 1 - eval/tests/benchmark_test.cc | 192 ++++++++++++++++++++++------ eval/tests/modern_benchmark_test.cc | 169 ++++++++++++++++++------ 4 files changed, 348 insertions(+), 80 deletions(-) diff --git a/eval/eval/select_step.cc b/eval/eval/select_step.cc index 8078f99f8..0b31c3c13 100644 --- a/eval/eval/select_step.cc +++ b/eval/eval/select_step.cc @@ -471,6 +471,62 @@ absl::Status ProtoSelectStep::EvaluateLegacyMessageGetField( &frame->value_stack().Peek()); } +class ProtoHasStep : public SelectStep { + public: + ProtoHasStep(StringValue value, int64_t expr_id, + bool enable_wrapper_type_null_unboxing, + bool enable_optional_types, const google::protobuf::Descriptor* descriptor, + const google::protobuf::FieldDescriptor* field_descriptor) + : SelectStep(std::move(value), /*test_field_presence=*/true, expr_id, + enable_wrapper_type_null_unboxing, enable_optional_types), + descriptor_(descriptor), + field_descriptor_(field_descriptor) { + ABSL_DCHECK(descriptor_ != nullptr); + ABSL_DCHECK(field_descriptor_ != nullptr); + } + + absl::Status Evaluate(ExecutionFrame* frame) const override { + if (!frame->value_stack().HasEnough(1)) { + return absl::InternalError( + "No arguments supplied for Select-type expression"); + } + + const Value& arg = frame->value_stack().Peek(); + if (auto unwrapped = arg.AsParsedMessage(); + unwrapped.has_value() && unwrapped->GetDescriptor() == descriptor_) { + return EvaluateHas(frame, *unwrapped); + } else if (const google::protobuf::Message* legacy_message = + cel::interop_internal::GetLegacyMessage(arg); + legacy_message != nullptr && + legacy_message->GetDescriptor() == descriptor_) { + cel::ParsedMessageValue parsed_message = + cel::UnsafeParsedMessageValue(legacy_message); + return EvaluateHas(frame, parsed_message); + } + // If we get an unexpected value type, fall back to the generic + // implementation. + return SelectStep::Evaluate(frame); + } + + private: + absl::Status EvaluateHas(ExecutionFrame* frame, + const cel::ParsedMessageValue& parsed_message) const; + + const google::protobuf::Descriptor* descriptor_; + const google::protobuf::FieldDescriptor* field_descriptor_; +}; + +absl::Status ProtoHasStep::EvaluateHas( + ExecutionFrame* frame, + const cel::ParsedMessageValue& parsed_message) const { + if (CheckAttributeTrail(field_, frame)) { + return absl::OkStatus(); + } + frame->value_stack().Peek() = + BoolValue{parsed_message.HasField(field_descriptor_)}; + return absl::OkStatus(); +} + } // namespace std::unique_ptr CreateDirectSelectStep( @@ -496,10 +552,10 @@ absl::StatusOr> CreateTypedSelectStep( cel::StringValue field, cel::StructType resolved_operand_type, cel::StructTypeField resolved_field, bool test_only, int64_t expr_id, bool enable_wrapper_type_null_unboxing, bool enable_optional_types) { - if (!resolved_operand_type.IsMessage() || test_only) { + if (!resolved_operand_type.IsMessage()) { // The specialization only supports messages. Fallback to the generic // implementation for other types. - // TODO(uncreated-issue/89): support has() for messages. + // TODO(uncreated-issue/89): support optional select and chaining. return CreateSelectStep(std::move(field), test_only, expr_id, enable_wrapper_type_null_unboxing, enable_optional_types); @@ -511,6 +567,12 @@ absl::StatusOr> CreateTypedSelectStep( const google::protobuf::FieldDescriptor* field_descriptor = resolved_field.GetMessage().descriptor(); + if (test_only) { + return std::make_unique( + std::move(field), expr_id, enable_wrapper_type_null_unboxing, + enable_optional_types, descriptor, field_descriptor); + } + return std::make_unique( std::move(field), expr_id, enable_wrapper_type_null_unboxing, enable_optional_types, descriptor, field_descriptor); diff --git a/eval/tests/BUILD b/eval/tests/BUILD index c5a7a7062..e4dacea3f 100644 --- a/eval/tests/BUILD +++ b/eval/tests/BUILD @@ -85,7 +85,6 @@ cc_test( "//internal:benchmark", "//internal:testing", "//internal:testing_descriptor_pool", - "//internal:testing_message_factory", "//parser", "//parser:macro_registry", "//runtime", diff --git a/eval/tests/benchmark_test.cc b/eval/tests/benchmark_test.cc index abeac608a..ff38ed2af 100644 --- a/eval/tests/benchmark_test.cc +++ b/eval/tests/benchmark_test.cc @@ -592,16 +592,34 @@ BENCHMARK(BM_HasMap); void BM_HasProto(benchmark::State& state) { google::protobuf::Arena arena; - Activation activation; - ASSERT_OK_AND_ASSIGN(ParsedExpr parsed_expr, - parser::Parse("has(request.path) && !has(request.ip)")); + ASSERT_OK_AND_ASSIGN( + auto compiler_builder, + cel::NewCompilerBuilder(google::protobuf::DescriptorPool::generated_pool())); + ASSERT_THAT(compiler_builder->AddLibrary(cel::StandardCompilerLibrary()), + IsOk()); + ASSERT_THAT( + compiler_builder->GetCheckerBuilder().AddVariable(cel::MakeVariableDecl( + "request", cel::MessageType(RequestContext::descriptor()))), + IsOk()); + ASSERT_OK_AND_ASSIGN(auto compiler, compiler_builder->Build()); + + ASSERT_OK_AND_ASSIGN( + auto validation_result, + compiler->Compile("has(request.path) && !has(request.ip)")); + ASSERT_TRUE(validation_result.IsValid()); + ASSERT_OK_AND_ASSIGN(auto ast, validation_result.ReleaseAst()); + + cel::expr::CheckedExpr checked_expr; + ASSERT_THAT(cel::AstToCheckedExpr(*ast, &checked_expr), IsOk()); + InterpreterOptions options = GetOptions(arena); auto builder = CreateCelExpressionBuilder(options); - auto reg_status = RegisterBuiltinFunctions(builder->GetRegistry(), options); + ASSERT_THAT(RegisterBuiltinFunctions(builder->GetRegistry(), options), + IsOk()); - ASSERT_OK_AND_ASSIGN(auto cel_expr, - builder->CreateExpression(&parsed_expr.expr(), nullptr)); + ASSERT_OK_AND_ASSIGN(auto cel_expr, builder->CreateExpression(&checked_expr)); + Activation activation; RequestContext request; request.set_path(kPath); request.set_token(kToken); @@ -620,17 +638,34 @@ BENCHMARK(BM_HasProto); void BM_HasProtoMap(benchmark::State& state) { google::protobuf::Arena arena; - Activation activation; - ASSERT_OK_AND_ASSIGN(ParsedExpr parsed_expr, - parser::Parse("has(request.headers.create_time) && " - "!has(request.headers.update_time)")); + ASSERT_OK_AND_ASSIGN( + auto compiler_builder, + cel::NewCompilerBuilder(google::protobuf::DescriptorPool::generated_pool())); + ASSERT_THAT(compiler_builder->AddLibrary(cel::StandardCompilerLibrary()), + IsOk()); + ASSERT_THAT( + compiler_builder->GetCheckerBuilder().AddVariable(cel::MakeVariableDecl( + "request", cel::MessageType(RequestContext::descriptor()))), + IsOk()); + ASSERT_OK_AND_ASSIGN(auto compiler, compiler_builder->Build()); + + ASSERT_OK_AND_ASSIGN(auto validation_result, + compiler->Compile("has(request.headers.create_time) && " + "!has(request.headers.update_time)")); + ASSERT_TRUE(validation_result.IsValid()); + ASSERT_OK_AND_ASSIGN(auto ast, validation_result.ReleaseAst()); + + cel::expr::CheckedExpr checked_expr; + ASSERT_THAT(cel::AstToCheckedExpr(*ast, &checked_expr), IsOk()); + InterpreterOptions options = GetOptions(arena); auto builder = CreateCelExpressionBuilder(options); - auto reg_status = RegisterBuiltinFunctions(builder->GetRegistry(), options); + ASSERT_THAT(RegisterBuiltinFunctions(builder->GetRegistry(), options), + IsOk()); - ASSERT_OK_AND_ASSIGN(auto cel_expr, - builder->CreateExpression(&parsed_expr.expr(), nullptr)); + ASSERT_OK_AND_ASSIGN(auto cel_expr, builder->CreateExpression(&checked_expr)); + Activation activation; RequestContext request; request.mutable_headers()->insert({"create_time", "2021-01-01"}); activation.InsertValue("request", @@ -648,17 +683,34 @@ BENCHMARK(BM_HasProtoMap); void BM_ReadProtoMap(benchmark::State& state) { google::protobuf::Arena arena; - Activation activation; - ASSERT_OK_AND_ASSIGN(ParsedExpr parsed_expr, parser::Parse(R"cel( + ASSERT_OK_AND_ASSIGN( + auto compiler_builder, + cel::NewCompilerBuilder(google::protobuf::DescriptorPool::generated_pool())); + ASSERT_THAT(compiler_builder->AddLibrary(cel::StandardCompilerLibrary()), + IsOk()); + ASSERT_THAT( + compiler_builder->GetCheckerBuilder().AddVariable(cel::MakeVariableDecl( + "request", cel::MessageType(RequestContext::descriptor()))), + IsOk()); + ASSERT_OK_AND_ASSIGN(auto compiler, compiler_builder->Build()); + + ASSERT_OK_AND_ASSIGN(auto validation_result, compiler->Compile(R"cel( request.headers.create_time == "2021-01-01" )cel")); + ASSERT_TRUE(validation_result.IsValid()); + ASSERT_OK_AND_ASSIGN(auto ast, validation_result.ReleaseAst()); + + cel::expr::CheckedExpr checked_expr; + ASSERT_THAT(cel::AstToCheckedExpr(*ast, &checked_expr), IsOk()); + InterpreterOptions options = GetOptions(arena); auto builder = CreateCelExpressionBuilder(options); - auto reg_status = RegisterBuiltinFunctions(builder->GetRegistry(), options); + ASSERT_THAT(RegisterBuiltinFunctions(builder->GetRegistry(), options), + IsOk()); - ASSERT_OK_AND_ASSIGN(auto cel_expr, - builder->CreateExpression(&parsed_expr.expr(), nullptr)); + ASSERT_OK_AND_ASSIGN(auto cel_expr, builder->CreateExpression(&checked_expr)); + Activation activation; RequestContext request; request.mutable_headers()->insert({"create_time", "2021-01-01"}); activation.InsertValue("request", @@ -676,17 +728,34 @@ BENCHMARK(BM_ReadProtoMap); void BM_NestedProtoFieldRead(benchmark::State& state) { google::protobuf::Arena arena; - Activation activation; - ASSERT_OK_AND_ASSIGN(ParsedExpr parsed_expr, parser::Parse(R"cel( + ASSERT_OK_AND_ASSIGN( + auto compiler_builder, + cel::NewCompilerBuilder(google::protobuf::DescriptorPool::generated_pool())); + ASSERT_THAT(compiler_builder->AddLibrary(cel::StandardCompilerLibrary()), + IsOk()); + ASSERT_THAT( + compiler_builder->GetCheckerBuilder().AddVariable(cel::MakeVariableDecl( + "request", cel::MessageType(RequestContext::descriptor()))), + IsOk()); + ASSERT_OK_AND_ASSIGN(auto compiler, compiler_builder->Build()); + + ASSERT_OK_AND_ASSIGN(auto validation_result, compiler->Compile(R"cel( !request.a.b.c.d.e )cel")); + ASSERT_TRUE(validation_result.IsValid()); + ASSERT_OK_AND_ASSIGN(auto ast, validation_result.ReleaseAst()); + + cel::expr::CheckedExpr checked_expr; + ASSERT_THAT(cel::AstToCheckedExpr(*ast, &checked_expr), IsOk()); + InterpreterOptions options = GetOptions(arena); auto builder = CreateCelExpressionBuilder(options); - auto reg_status = RegisterBuiltinFunctions(builder->GetRegistry(), options); + ASSERT_THAT(RegisterBuiltinFunctions(builder->GetRegistry(), options), + IsOk()); - ASSERT_OK_AND_ASSIGN(auto cel_expr, - builder->CreateExpression(&parsed_expr.expr(), nullptr)); + ASSERT_OK_AND_ASSIGN(auto cel_expr, builder->CreateExpression(&checked_expr)); + Activation activation; RequestContext request; request.mutable_a()->mutable_b()->mutable_c()->mutable_d()->set_e(false); activation.InsertValue("request", @@ -704,17 +773,34 @@ BENCHMARK(BM_NestedProtoFieldRead); void BM_NestedProtoFieldReadDefaults(benchmark::State& state) { google::protobuf::Arena arena; - Activation activation; - ASSERT_OK_AND_ASSIGN(ParsedExpr parsed_expr, parser::Parse(R"cel( + ASSERT_OK_AND_ASSIGN( + auto compiler_builder, + cel::NewCompilerBuilder(google::protobuf::DescriptorPool::generated_pool())); + ASSERT_THAT(compiler_builder->AddLibrary(cel::StandardCompilerLibrary()), + IsOk()); + ASSERT_THAT( + compiler_builder->GetCheckerBuilder().AddVariable(cel::MakeVariableDecl( + "request", cel::MessageType(RequestContext::descriptor()))), + IsOk()); + ASSERT_OK_AND_ASSIGN(auto compiler, compiler_builder->Build()); + + ASSERT_OK_AND_ASSIGN(auto validation_result, compiler->Compile(R"cel( !request.a.b.c.d.e )cel")); + ASSERT_TRUE(validation_result.IsValid()); + ASSERT_OK_AND_ASSIGN(auto ast, validation_result.ReleaseAst()); + + cel::expr::CheckedExpr checked_expr; + ASSERT_THAT(cel::AstToCheckedExpr(*ast, &checked_expr), IsOk()); + InterpreterOptions options = GetOptions(arena); auto builder = CreateCelExpressionBuilder(options); - auto reg_status = RegisterBuiltinFunctions(builder->GetRegistry(), options); + ASSERT_THAT(RegisterBuiltinFunctions(builder->GetRegistry(), options), + IsOk()); - ASSERT_OK_AND_ASSIGN(auto cel_expr, - builder->CreateExpression(&parsed_expr.expr(), nullptr)); + ASSERT_OK_AND_ASSIGN(auto cel_expr, builder->CreateExpression(&checked_expr)); + Activation activation; RequestContext request; activation.InsertValue("request", CelProtoWrapper::CreateMessage(&request, &arena)); @@ -731,18 +817,35 @@ BENCHMARK(BM_NestedProtoFieldReadDefaults); void BM_ProtoStructAccess(benchmark::State& state) { google::protobuf::Arena arena; - Activation activation; - ASSERT_OK_AND_ASSIGN(ParsedExpr parsed_expr, parser::Parse(R"cel( + ASSERT_OK_AND_ASSIGN( + auto compiler_builder, + cel::NewCompilerBuilder(google::protobuf::DescriptorPool::generated_pool())); + ASSERT_THAT(compiler_builder->AddLibrary(cel::StandardCompilerLibrary()), + IsOk()); + ASSERT_THAT( + compiler_builder->GetCheckerBuilder().AddVariable(cel::MakeVariableDecl( + "request", + cel::MessageType(AttributeContext::Request::descriptor()))), + IsOk()); + ASSERT_OK_AND_ASSIGN(auto compiler, compiler_builder->Build()); + + ASSERT_OK_AND_ASSIGN(auto validation_result, compiler->Compile(R"cel( has(request.auth.claims.iss) && request.auth.claims.iss == 'accounts.google.com' )cel")); + ASSERT_TRUE(validation_result.IsValid()); + ASSERT_OK_AND_ASSIGN(auto ast, validation_result.ReleaseAst()); + + cel::expr::CheckedExpr checked_expr; + ASSERT_THAT(cel::AstToCheckedExpr(*ast, &checked_expr), IsOk()); + InterpreterOptions options = GetOptions(arena); auto builder = CreateCelExpressionBuilder(options); ASSERT_THAT(RegisterBuiltinFunctions(builder->GetRegistry(), options), IsOk()); - ASSERT_OK_AND_ASSIGN(auto cel_expr, - builder->CreateExpression(&parsed_expr.expr(), nullptr)); + ASSERT_OK_AND_ASSIGN(auto cel_expr, builder->CreateExpression(&checked_expr)); + Activation activation; AttributeContext::Request request; auto* auth = request.mutable_auth(); (*auth->mutable_claims()->mutable_fields())["iss"].set_string_value( @@ -762,18 +865,35 @@ BENCHMARK(BM_ProtoStructAccess); void BM_ProtoListAccess(benchmark::State& state) { google::protobuf::Arena arena; - Activation activation; - ASSERT_OK_AND_ASSIGN(ParsedExpr parsed_expr, parser::Parse(R"cel( + ASSERT_OK_AND_ASSIGN( + auto compiler_builder, + cel::NewCompilerBuilder(google::protobuf::DescriptorPool::generated_pool())); + ASSERT_THAT(compiler_builder->AddLibrary(cel::StandardCompilerLibrary()), + IsOk()); + ASSERT_THAT( + compiler_builder->GetCheckerBuilder().AddVariable(cel::MakeVariableDecl( + "request", + cel::MessageType(AttributeContext::Request::descriptor()))), + IsOk()); + ASSERT_OK_AND_ASSIGN(auto compiler, compiler_builder->Build()); + + ASSERT_OK_AND_ASSIGN(auto validation_result, compiler->Compile(R"cel( "//.../accessLevels/MY_LEVEL_4" in request.auth.access_levels )cel")); + ASSERT_TRUE(validation_result.IsValid()); + ASSERT_OK_AND_ASSIGN(auto ast, validation_result.ReleaseAst()); + + cel::expr::CheckedExpr checked_expr; + ASSERT_THAT(cel::AstToCheckedExpr(*ast, &checked_expr), IsOk()); + InterpreterOptions options = GetOptions(arena); auto builder = CreateCelExpressionBuilder(options); ASSERT_THAT(RegisterBuiltinFunctions(builder->GetRegistry(), options), IsOk()); - ASSERT_OK_AND_ASSIGN(auto cel_expr, - builder->CreateExpression(&parsed_expr.expr(), nullptr)); + ASSERT_OK_AND_ASSIGN(auto cel_expr, builder->CreateExpression(&checked_expr)); + Activation activation; AttributeContext::Request request; auto* auth = request.mutable_auth(); auth->add_access_levels("//.../accessLevels/MY_LEVEL_0"); diff --git a/eval/tests/modern_benchmark_test.cc b/eval/tests/modern_benchmark_test.cc index 28daed981..8a41b094f 100644 --- a/eval/tests/modern_benchmark_test.cc +++ b/eval/tests/modern_benchmark_test.cc @@ -702,12 +702,25 @@ BENCHMARK(BM_HasMap); void BM_HasProto(benchmark::State& state) { RuntimeOptions options = GetOptions(); - auto runtime = StandardRuntimeOrDie(options); + auto runtime = + StandardRuntimeOrDie(options, google::protobuf::DescriptorPool::generated_pool()); - ASSERT_OK_AND_ASSIGN(ParsedExpr parsed_expr, - Parse("has(request.path) && !has(request.ip)")); - ASSERT_OK_AND_ASSIGN(auto cel_expr, ProtobufRuntimeAdapter::CreateProgram( - *runtime, parsed_expr)); + ASSERT_OK_AND_ASSIGN( + auto builder, + NewCompilerBuilder(google::protobuf::DescriptorPool::generated_pool())); + ASSERT_THAT(builder->AddLibrary(StandardCompilerLibrary()), IsOk()); + ASSERT_THAT(builder->GetCheckerBuilder().AddVariable(MakeVariableDecl( + "request", cel::MessageType(RequestContext::descriptor()))), + IsOk()); + ASSERT_OK_AND_ASSIGN(auto compiler, builder->Build()); + + ASSERT_OK_AND_ASSIGN( + ValidationResult validation_result, + compiler->Compile("has(request.path) && !has(request.ip)")); + ASSERT_TRUE(validation_result.IsValid()); + ASSERT_OK_AND_ASSIGN(auto ast, validation_result.ReleaseAst()); + + ASSERT_OK_AND_ASSIGN(auto cel_expr, runtime->CreateProgram(std::move(ast))); google::protobuf::Arena arena; Activation activation; @@ -729,13 +742,25 @@ BENCHMARK(BM_HasProto); void BM_HasProtoMap(benchmark::State& state) { RuntimeOptions options = GetOptions(); - auto runtime = StandardRuntimeOrDie(options); + auto runtime = + StandardRuntimeOrDie(options, google::protobuf::DescriptorPool::generated_pool()); - ASSERT_OK_AND_ASSIGN(ParsedExpr parsed_expr, - Parse("has(request.headers.create_time) && " - "!has(request.headers.update_time)")); - ASSERT_OK_AND_ASSIGN(auto cel_expr, ProtobufRuntimeAdapter::CreateProgram( - *runtime, parsed_expr)); + ASSERT_OK_AND_ASSIGN( + auto builder, + NewCompilerBuilder(google::protobuf::DescriptorPool::generated_pool())); + ASSERT_THAT(builder->AddLibrary(StandardCompilerLibrary()), IsOk()); + ASSERT_THAT(builder->GetCheckerBuilder().AddVariable(MakeVariableDecl( + "request", cel::MessageType(RequestContext::descriptor()))), + IsOk()); + ASSERT_OK_AND_ASSIGN(auto compiler, builder->Build()); + + ASSERT_OK_AND_ASSIGN(ValidationResult validation_result, + compiler->Compile("has(request.headers.create_time) && " + "!has(request.headers.update_time)")); + ASSERT_TRUE(validation_result.IsValid()); + ASSERT_OK_AND_ASSIGN(auto ast, validation_result.ReleaseAst()); + + ASSERT_OK_AND_ASSIGN(auto cel_expr, runtime->CreateProgram(std::move(ast))); google::protobuf::Arena arena; Activation activation; @@ -755,15 +780,27 @@ void BM_HasProtoMap(benchmark::State& state) { BENCHMARK(BM_HasProtoMap); void BM_ReadProtoMap(benchmark::State& state) { - ASSERT_OK_AND_ASSIGN(ParsedExpr parsed_expr, Parse(R"cel( + RuntimeOptions options = GetOptions(); + auto runtime = + StandardRuntimeOrDie(options, google::protobuf::DescriptorPool::generated_pool()); + + ASSERT_OK_AND_ASSIGN( + auto builder, + NewCompilerBuilder(google::protobuf::DescriptorPool::generated_pool())); + ASSERT_THAT(builder->AddLibrary(StandardCompilerLibrary()), IsOk()); + ASSERT_THAT(builder->GetCheckerBuilder().AddVariable(MakeVariableDecl( + "request", cel::MessageType(RequestContext::descriptor()))), + IsOk()); + ASSERT_OK_AND_ASSIGN(auto compiler, builder->Build()); + + ASSERT_OK_AND_ASSIGN(ValidationResult validation_result, + compiler->Compile(R"cel( request.headers.create_time == "2021-01-01" )cel")); + ASSERT_TRUE(validation_result.IsValid()); + ASSERT_OK_AND_ASSIGN(auto ast, validation_result.ReleaseAst()); - RuntimeOptions options = GetOptions(); - auto runtime = StandardRuntimeOrDie(options); - - ASSERT_OK_AND_ASSIGN(auto cel_expr, ProtobufRuntimeAdapter::CreateProgram( - *runtime, parsed_expr)); + ASSERT_OK_AND_ASSIGN(auto cel_expr, runtime->CreateProgram(std::move(ast))); google::protobuf::Arena arena; Activation activation; @@ -783,15 +820,27 @@ void BM_ReadProtoMap(benchmark::State& state) { BENCHMARK(BM_ReadProtoMap); void BM_NestedProtoFieldRead(benchmark::State& state) { - ASSERT_OK_AND_ASSIGN(ParsedExpr parsed_expr, Parse(R"cel( + RuntimeOptions options = GetOptions(); + auto runtime = + StandardRuntimeOrDie(options, google::protobuf::DescriptorPool::generated_pool()); + + ASSERT_OK_AND_ASSIGN( + auto builder, + NewCompilerBuilder(google::protobuf::DescriptorPool::generated_pool())); + ASSERT_THAT(builder->AddLibrary(StandardCompilerLibrary()), IsOk()); + ASSERT_THAT(builder->GetCheckerBuilder().AddVariable(MakeVariableDecl( + "request", cel::MessageType(RequestContext::descriptor()))), + IsOk()); + ASSERT_OK_AND_ASSIGN(auto compiler, builder->Build()); + + ASSERT_OK_AND_ASSIGN(ValidationResult validation_result, + compiler->Compile(R"cel( !request.a.b.c.d.e )cel")); + ASSERT_TRUE(validation_result.IsValid()); + ASSERT_OK_AND_ASSIGN(auto ast, validation_result.ReleaseAst()); - RuntimeOptions options = GetOptions(); - auto runtime = StandardRuntimeOrDie(options); - - ASSERT_OK_AND_ASSIGN(auto cel_expr, ProtobufRuntimeAdapter::CreateProgram( - *runtime, parsed_expr)); + ASSERT_OK_AND_ASSIGN(auto cel_expr, runtime->CreateProgram(std::move(ast))); google::protobuf::Arena arena; Activation activation; @@ -811,15 +860,27 @@ void BM_NestedProtoFieldRead(benchmark::State& state) { BENCHMARK(BM_NestedProtoFieldRead); void BM_NestedProtoFieldReadDefaults(benchmark::State& state) { - ASSERT_OK_AND_ASSIGN(ParsedExpr parsed_expr, Parse(R"cel( + RuntimeOptions options = GetOptions(); + auto runtime = + StandardRuntimeOrDie(options, google::protobuf::DescriptorPool::generated_pool()); + + ASSERT_OK_AND_ASSIGN( + auto builder, + NewCompilerBuilder(google::protobuf::DescriptorPool::generated_pool())); + ASSERT_THAT(builder->AddLibrary(StandardCompilerLibrary()), IsOk()); + ASSERT_THAT(builder->GetCheckerBuilder().AddVariable(MakeVariableDecl( + "request", cel::MessageType(RequestContext::descriptor()))), + IsOk()); + ASSERT_OK_AND_ASSIGN(auto compiler, builder->Build()); + + ASSERT_OK_AND_ASSIGN(ValidationResult validation_result, + compiler->Compile(R"cel( !request.a.b.c.d.e )cel")); + ASSERT_TRUE(validation_result.IsValid()); + ASSERT_OK_AND_ASSIGN(auto ast, validation_result.ReleaseAst()); - RuntimeOptions options = GetOptions(); - auto runtime = StandardRuntimeOrDie(options); - - ASSERT_OK_AND_ASSIGN(auto cel_expr, ProtobufRuntimeAdapter::CreateProgram( - *runtime, parsed_expr)); + ASSERT_OK_AND_ASSIGN(auto cel_expr, runtime->CreateProgram(std::move(ast))); google::protobuf::Arena arena; Activation activation; @@ -838,15 +899,28 @@ void BM_NestedProtoFieldReadDefaults(benchmark::State& state) { BENCHMARK(BM_NestedProtoFieldReadDefaults); void BM_ProtoStructAccess(benchmark::State& state) { - ASSERT_OK_AND_ASSIGN(ParsedExpr parsed_expr, Parse(R"cel( + RuntimeOptions options = GetOptions(); + auto runtime = + StandardRuntimeOrDie(options, google::protobuf::DescriptorPool::generated_pool()); + + ASSERT_OK_AND_ASSIGN( + auto builder, + NewCompilerBuilder(google::protobuf::DescriptorPool::generated_pool())); + ASSERT_THAT(builder->AddLibrary(StandardCompilerLibrary()), IsOk()); + ASSERT_THAT(builder->GetCheckerBuilder().AddVariable(MakeVariableDecl( + "request", + cel::MessageType(AttributeContext::Request::descriptor()))), + IsOk()); + ASSERT_OK_AND_ASSIGN(auto compiler, builder->Build()); + + ASSERT_OK_AND_ASSIGN(ValidationResult validation_result, + compiler->Compile(R"cel( has(request.auth.claims.iss) && request.auth.claims.iss == 'accounts.google.com' )cel")); + ASSERT_TRUE(validation_result.IsValid()); + ASSERT_OK_AND_ASSIGN(auto ast, validation_result.ReleaseAst()); - RuntimeOptions options = GetOptions(); - auto runtime = StandardRuntimeOrDie(options); - - ASSERT_OK_AND_ASSIGN(auto cel_expr, ProtobufRuntimeAdapter::CreateProgram( - *runtime, parsed_expr)); + ASSERT_OK_AND_ASSIGN(auto cel_expr, runtime->CreateProgram(std::move(ast))); google::protobuf::Arena arena; Activation activation; @@ -868,15 +942,28 @@ void BM_ProtoStructAccess(benchmark::State& state) { BENCHMARK(BM_ProtoStructAccess); void BM_ProtoListAccess(benchmark::State& state) { - ASSERT_OK_AND_ASSIGN(ParsedExpr parsed_expr, Parse(R"cel( + RuntimeOptions options = GetOptions(); + auto runtime = + StandardRuntimeOrDie(options, google::protobuf::DescriptorPool::generated_pool()); + + ASSERT_OK_AND_ASSIGN( + auto builder, + NewCompilerBuilder(google::protobuf::DescriptorPool::generated_pool())); + ASSERT_THAT(builder->AddLibrary(StandardCompilerLibrary()), IsOk()); + ASSERT_THAT(builder->GetCheckerBuilder().AddVariable(MakeVariableDecl( + "request", + cel::MessageType(AttributeContext::Request::descriptor()))), + IsOk()); + ASSERT_OK_AND_ASSIGN(auto compiler, builder->Build()); + + ASSERT_OK_AND_ASSIGN(ValidationResult validation_result, + compiler->Compile(R"cel( "//.../accessLevels/MY_LEVEL_4" in request.auth.access_levels )cel")); + ASSERT_TRUE(validation_result.IsValid()); + ASSERT_OK_AND_ASSIGN(auto ast, validation_result.ReleaseAst()); - RuntimeOptions options = GetOptions(); - auto runtime = StandardRuntimeOrDie(options); - - ASSERT_OK_AND_ASSIGN(auto cel_expr, ProtobufRuntimeAdapter::CreateProgram( - *runtime, parsed_expr)); + ASSERT_OK_AND_ASSIGN(auto cel_expr, runtime->CreateProgram(std::move(ast))); google::protobuf::Arena arena; Activation activation;