Skip to content

Commit daccace

Browse files
CEL Dev Teamcopybara-github
authored andcommitted
Custom activation factory for the C++ testrunner.
PiperOrigin-RevId: 816660123
1 parent 2b0ed60 commit daccace

File tree

4 files changed

+82
-2
lines changed

4 files changed

+82
-2
lines changed

testing/testrunner/BUILD

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,16 @@ cc_library(
1616
"//compiler",
1717
"//eval/public:cel_expression",
1818
"//runtime",
19+
"//runtime:activation",
1920
"@com_google_absl//absl/base:nullability",
2021
"@com_google_absl//absl/container:flat_hash_map",
2122
"@com_google_absl//absl/memory",
23+
"@com_google_absl//absl/status",
24+
"@com_google_absl//absl/status:statusor",
2225
"@com_google_cel_spec//proto/cel/expr:checked_cc_proto",
2326
"@com_google_cel_spec//proto/cel/expr:value_cc_proto",
27+
"@com_google_cel_spec//proto/cel/expr/conformance/test:suite_cc_proto",
28+
"@com_google_protobuf//:protobuf",
2429
],
2530
)
2631

@@ -89,6 +94,7 @@ cc_test(
8994
"//common:ast_proto",
9095
"//common:decl",
9196
"//common:type",
97+
"//common:value",
9298
"//compiler",
9399
"//compiler:compiler_factory",
94100
"//compiler:standard_library",
@@ -99,6 +105,7 @@ cc_test(
99105
"//internal:testing",
100106
"//internal:testing_descriptor_pool",
101107
"//runtime",
108+
"//runtime:activation",
102109
"//runtime:runtime_builder",
103110
"//runtime:standard_runtime_builder_factory",
104111
"@com_google_absl//absl/container:flat_hash_map",

testing/testrunner/cel_test_context.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#ifndef THIRD_PARTY_CEL_CPP_TOOLS_TESTRUNNER_CEL_TEST_CONTEXT_H_
1616
#define THIRD_PARTY_CEL_CPP_TOOLS_TESTRUNNER_CEL_TEST_CONTEXT_H_
1717

18+
#include <functional>
1819
#include <memory>
1920
#include <string>
2021
#include <utility>
@@ -24,16 +25,24 @@
2425
#include "absl/base/nullability.h"
2526
#include "absl/container/flat_hash_map.h"
2627
#include "absl/memory/memory.h"
28+
#include "absl/status/statusor.h"
2729
#include "compiler/compiler.h"
2830
#include "eval/public/cel_expression.h"
31+
#include "runtime/activation.h"
2932
#include "runtime/runtime.h"
3033
#include "testing/testrunner/cel_expression_source.h"
34+
#include "cel/expr/conformance/test/suite.pb.h"
35+
#include "google/protobuf/arena.h"
3136
namespace cel::test {
3237

3338
// The context class for a CEL test, holding configurations needed to evaluate
3439
// compiled CEL expressions.
3540
class CelTestContext {
3641
public:
42+
using CelActivationFactoryFn = std::function<absl::StatusOr<cel::Activation>(
43+
const cel::expr::conformance::test::TestCase& test_case,
44+
google::protobuf::Arena* arena)>;
45+
3746
// Creates a CelTestContext using a `CelExpressionBuilder`.
3847
//
3948
// The `CelExpressionBuilder` helps in setting up the environment for
@@ -107,6 +116,17 @@ class CelTestContext {
107116
custom_bindings_ = std::move(custom_bindings);
108117
}
109118

119+
// Allows the runner to inject a custom activation factory. If not set, an
120+
// empty activation will be used. Custom bindings and test case inputs will
121+
// be added to the activation returned by the factory.
122+
void SetActivationFactory(CelActivationFactoryFn activation_factory) {
123+
activation_factory_ = std::move(activation_factory);
124+
}
125+
126+
const CelActivationFactoryFn& activation_factory() const {
127+
return activation_factory_;
128+
}
129+
110130
private:
111131
// Delete copy and move constructors.
112132
CelTestContext(const CelTestContext&) = delete;
@@ -151,6 +171,8 @@ class CelTestContext {
151171
// needed to generate Program. Users should either provide a runtime, or the
152172
// CelExpressionBuilder.
153173
std::unique_ptr<const cel::Runtime> runtime_;
174+
175+
CelActivationFactoryFn activation_factory_;
154176
};
155177

156178
} // namespace cel::test

testing/testrunner/runner_lib.cc

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,11 +203,20 @@ absl::Status AddTestCaseBindingsToModernActivation(
203203
return absl::OkStatus();
204204
}
205205

206+
absl::StatusOr<cel::Activation> GetActivation(const CelTestContext& context,
207+
const TestCase& test_case,
208+
google::protobuf::Arena* arena) {
209+
if (context.activation_factory() != nullptr) {
210+
return context.activation_factory()(test_case, arena);
211+
}
212+
return cel::Activation();
213+
}
214+
206215
absl::StatusOr<cel::Activation> CreateModernActivationFromBindings(
207216
const TestCase& test_case, const CelTestContext& context,
208217
google::protobuf::Arena* arena) {
209-
cel::Activation activation;
210-
218+
CEL_ASSIGN_OR_RETURN(cel::Activation activation,
219+
GetActivation(context, test_case, arena));
211220
CEL_RETURN_IF_ERROR(
212221
AddCustomBindingsToModernActivation(context, activation, arena));
213222

testing/testrunner/runner_lib_test.cc

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "common/ast_proto.h"
3131
#include "common/decl.h"
3232
#include "common/type.h"
33+
#include "common/value.h"
3334
#include "compiler/compiler.h"
3435
#include "compiler/compiler_factory.h"
3536
#include "compiler/standard_library.h"
@@ -39,6 +40,7 @@
3940
#include "internal/status_macros.h"
4041
#include "internal/testing.h"
4142
#include "internal/testing_descriptor_pool.h"
43+
#include "runtime/activation.h"
4244
#include "runtime/runtime.h"
4345
#include "runtime/runtime_builder.h"
4446
#include "runtime/standard_runtime_builder_factory.h"
@@ -47,6 +49,7 @@
4749
#include "testing/testrunner/coverage_index.h"
4850
#include "cel/expr/conformance/proto3/test_all_types.pb.h"
4951
#include "cel/expr/conformance/test/suite.pb.h"
52+
#include "google/protobuf/arena.h"
5053
#include "google/protobuf/descriptor.h"
5154
#include "google/protobuf/message.h"
5255
#include "google/protobuf/text_format.h"
@@ -610,6 +613,45 @@ TEST(TestRunnerStandaloneTest, BasicTestFailsWhenExpectingErrorButGotValue) {
610613
"Expected error but got value");
611614
}
612615

616+
TEST(TestRunnerStandaloneTest, BasicTestWithActivationFactorySucceeds) {
617+
ASSERT_OK_AND_ASSIGN(cel::ValidationResult validation_result,
618+
DefaultCompiler().Compile("x + y"));
619+
CheckedExpr checked_expr;
620+
ASSERT_THAT(cel::AstToCheckedExpr(*validation_result.GetAst(), &checked_expr),
621+
absl_testing::IsOk());
622+
623+
ASSERT_OK_AND_ASSIGN(std::unique_ptr<const cel::Runtime> runtime,
624+
CreateTestRuntime());
625+
std::unique_ptr<CelTestContext> context =
626+
CelTestContext::CreateFromRuntime(std::move(runtime));
627+
context->SetActivationFactory(
628+
[](const TestCase& test_case,
629+
google::protobuf::Arena* arena) -> absl::StatusOr<cel::Activation> {
630+
cel::Activation activation;
631+
activation.InsertOrAssignValue("x", cel::IntValue(10));
632+
activation.InsertOrAssignValue("y", cel::IntValue(5));
633+
return activation;
634+
});
635+
context->SetExpressionSource(
636+
CelExpressionSource::FromCheckedExpr(std::move(checked_expr)));
637+
638+
TestCase test_case = ParseTextProtoOrDie<TestCase>(R"pb(
639+
output { result_value { int64_value: 15 } }
640+
)pb");
641+
TestRunner test_runner(std::move(context));
642+
EXPECT_NO_FATAL_FAILURE(test_runner.RunTest(test_case));
643+
644+
// Input bindings should override values set by the activation factory.
645+
test_case = ParseTextProtoOrDie<TestCase>(R"pb(
646+
input {
647+
key: "x"
648+
value { value { int64_value: 4 } }
649+
}
650+
output { result_value { int64_value: 9 } }
651+
)pb");
652+
EXPECT_NO_FATAL_FAILURE(test_runner.RunTest(test_case));
653+
}
654+
613655
TEST(CoverageTest, RuntimeCoverage) {
614656
ASSERT_OK_AND_ASSIGN(
615657
std::unique_ptr<cel::CompilerBuilder> compiler_builder,

0 commit comments

Comments
 (0)