Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions testing/testrunner/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,16 @@ cc_library(
"//compiler",
"//eval/public:cel_expression",
"//runtime",
"//runtime:activation",
"@com_google_absl//absl/base:nullability",
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/memory",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_cel_spec//proto/cel/expr:checked_cc_proto",
"@com_google_cel_spec//proto/cel/expr:value_cc_proto",
"@com_google_cel_spec//proto/cel/expr/conformance/test:suite_cc_proto",
"@com_google_protobuf//:protobuf",
],
)

Expand Down Expand Up @@ -89,6 +94,7 @@ cc_test(
"//common:ast_proto",
"//common:decl",
"//common:type",
"//common:value",
"//compiler",
"//compiler:compiler_factory",
"//compiler:standard_library",
Expand All @@ -99,6 +105,7 @@ cc_test(
"//internal:testing",
"//internal:testing_descriptor_pool",
"//runtime",
"//runtime:activation",
"//runtime:runtime_builder",
"//runtime:standard_runtime_builder_factory",
"@com_google_absl//absl/container:flat_hash_map",
Expand Down
22 changes: 22 additions & 0 deletions testing/testrunner/cel_test_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#ifndef THIRD_PARTY_CEL_CPP_TOOLS_TESTRUNNER_CEL_TEST_CONTEXT_H_
#define THIRD_PARTY_CEL_CPP_TOOLS_TESTRUNNER_CEL_TEST_CONTEXT_H_

#include <functional>
#include <memory>
#include <string>
#include <utility>
Expand All @@ -24,16 +25,24 @@
#include "absl/base/nullability.h"
#include "absl/container/flat_hash_map.h"
#include "absl/memory/memory.h"
#include "absl/status/statusor.h"
#include "compiler/compiler.h"
#include "eval/public/cel_expression.h"
#include "runtime/activation.h"
#include "runtime/runtime.h"
#include "testing/testrunner/cel_expression_source.h"
#include "cel/expr/conformance/test/suite.pb.h"
#include "google/protobuf/arena.h"
namespace cel::test {

// The context class for a CEL test, holding configurations needed to evaluate
// compiled CEL expressions.
class CelTestContext {
public:
using CelActivationFactoryFn = std::function<absl::StatusOr<cel::Activation>(
const cel::expr::conformance::test::TestCase& test_case,
google::protobuf::Arena* arena)>;

// Creates a CelTestContext using a `CelExpressionBuilder`.
//
// The `CelExpressionBuilder` helps in setting up the environment for
Expand Down Expand Up @@ -107,6 +116,17 @@ class CelTestContext {
custom_bindings_ = std::move(custom_bindings);
}

// Allows the runner to inject a custom activation factory. If not set, an
// empty activation will be used. Custom bindings and test case inputs will
// be added to the activation returned by the factory.
void SetActivationFactory(CelActivationFactoryFn activation_factory) {
activation_factory_ = std::move(activation_factory);
}

const CelActivationFactoryFn& activation_factory() const {
return activation_factory_;
}

private:
// Delete copy and move constructors.
CelTestContext(const CelTestContext&) = delete;
Expand Down Expand Up @@ -151,6 +171,8 @@ class CelTestContext {
// needed to generate Program. Users should either provide a runtime, or the
// CelExpressionBuilder.
std::unique_ptr<const cel::Runtime> runtime_;

CelActivationFactoryFn activation_factory_;
};

} // namespace cel::test
Expand Down
13 changes: 11 additions & 2 deletions testing/testrunner/runner_lib.cc
Original file line number Diff line number Diff line change
Expand Up @@ -203,11 +203,20 @@ absl::Status AddTestCaseBindingsToModernActivation(
return absl::OkStatus();
}

absl::StatusOr<cel::Activation> GetActivation(const CelTestContext& context,
const TestCase& test_case,
google::protobuf::Arena* arena) {
if (context.activation_factory() != nullptr) {
return context.activation_factory()(test_case, arena);
}
return cel::Activation();
}

absl::StatusOr<cel::Activation> CreateModernActivationFromBindings(
const TestCase& test_case, const CelTestContext& context,
google::protobuf::Arena* arena) {
cel::Activation activation;

CEL_ASSIGN_OR_RETURN(cel::Activation activation,
GetActivation(context, test_case, arena));
CEL_RETURN_IF_ERROR(
AddCustomBindingsToModernActivation(context, activation, arena));

Expand Down
42 changes: 42 additions & 0 deletions testing/testrunner/runner_lib_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "common/ast_proto.h"
#include "common/decl.h"
#include "common/type.h"
#include "common/value.h"
#include "compiler/compiler.h"
#include "compiler/compiler_factory.h"
#include "compiler/standard_library.h"
Expand All @@ -39,6 +40,7 @@
#include "internal/status_macros.h"
#include "internal/testing.h"
#include "internal/testing_descriptor_pool.h"
#include "runtime/activation.h"
#include "runtime/runtime.h"
#include "runtime/runtime_builder.h"
#include "runtime/standard_runtime_builder_factory.h"
Expand All @@ -47,6 +49,7 @@
#include "testing/testrunner/coverage_index.h"
#include "cel/expr/conformance/proto3/test_all_types.pb.h"
#include "cel/expr/conformance/test/suite.pb.h"
#include "google/protobuf/arena.h"
#include "google/protobuf/descriptor.h"
#include "google/protobuf/message.h"
#include "google/protobuf/text_format.h"
Expand Down Expand Up @@ -610,6 +613,45 @@ TEST(TestRunnerStandaloneTest, BasicTestFailsWhenExpectingErrorButGotValue) {
"Expected error but got value");
}

TEST(TestRunnerStandaloneTest, BasicTestWithActivationFactorySucceeds) {
ASSERT_OK_AND_ASSIGN(cel::ValidationResult validation_result,
DefaultCompiler().Compile("x + y"));
CheckedExpr checked_expr;
ASSERT_THAT(cel::AstToCheckedExpr(*validation_result.GetAst(), &checked_expr),
absl_testing::IsOk());

ASSERT_OK_AND_ASSIGN(std::unique_ptr<const cel::Runtime> runtime,
CreateTestRuntime());
std::unique_ptr<CelTestContext> context =
CelTestContext::CreateFromRuntime(std::move(runtime));
context->SetActivationFactory(
[](const TestCase& test_case,
google::protobuf::Arena* arena) -> absl::StatusOr<cel::Activation> {
cel::Activation activation;
activation.InsertOrAssignValue("x", cel::IntValue(10));
activation.InsertOrAssignValue("y", cel::IntValue(5));
return activation;
});
context->SetExpressionSource(
CelExpressionSource::FromCheckedExpr(std::move(checked_expr)));

TestCase test_case = ParseTextProtoOrDie<TestCase>(R"pb(
output { result_value { int64_value: 15 } }
)pb");
TestRunner test_runner(std::move(context));
EXPECT_NO_FATAL_FAILURE(test_runner.RunTest(test_case));

// Input bindings should override values set by the activation factory.
test_case = ParseTextProtoOrDie<TestCase>(R"pb(
input {
key: "x"
value { value { int64_value: 4 } }
}
output { result_value { int64_value: 9 } }
)pb");
EXPECT_NO_FATAL_FAILURE(test_runner.RunTest(test_case));
}

TEST(CoverageTest, RuntimeCoverage) {
ASSERT_OK_AND_ASSIGN(
std::unique_ptr<cel::CompilerBuilder> compiler_builder,
Expand Down