Skip to content

Commit 6a9d573

Browse files
jnthntatumcopybara-github
authored andcommitted
Add tests for CelValue runtime using the RegexExtension.
Note: regex.extract is not suppoted since the legacy runtime does not support option return types. PiperOrigin-RevId: 799208655
1 parent 3db277e commit 6a9d573

File tree

4 files changed

+139
-29
lines changed

4 files changed

+139
-29
lines changed

extensions/BUILD

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -712,10 +712,16 @@ cc_test(
712712
":regex_ext",
713713
"//checker:standard_library",
714714
"//checker:validation_result",
715+
"//common:kind",
715716
"//common:value",
716717
"//common:value_testing",
717718
"//compiler",
718719
"//compiler:compiler_factory",
720+
"//eval/public:activation",
721+
"//eval/public:cel_expr_builder_factory",
722+
"//eval/public:cel_expression",
723+
"//eval/public:cel_function_registry",
724+
"//eval/public:cel_options",
719725
"//extensions/protobuf:runtime_adapter",
720726
"//internal:status_macros",
721727
"//internal:testing",

extensions/regex_ext.cc

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -232,10 +232,13 @@ Value ReplaceN(const StringValue& target, const StringValue& regex,
232232
return StringValue::From(std::move(output), arena);
233233
}
234234

235-
absl::Status RegisterRegexExtensionFunctions(FunctionRegistry& registry) {
236-
CEL_RETURN_IF_ERROR(
237-
(BinaryFunctionAdapter<absl::StatusOr<Value>, StringValue, StringValue>::
238-
RegisterGlobalOverload("regex.extract", &Extract, registry)));
235+
absl::Status RegisterRegexExtensionFunctions(FunctionRegistry& registry,
236+
bool disable_extract) {
237+
if (!disable_extract) {
238+
CEL_RETURN_IF_ERROR((
239+
BinaryFunctionAdapter<absl::StatusOr<Value>, StringValue, StringValue>::
240+
RegisterGlobalOverload("regex.extract", &Extract, registry)));
241+
}
239242
CEL_RETURN_IF_ERROR(
240243
(BinaryFunctionAdapter<absl::StatusOr<Value>, StringValue, StringValue>::
241244
RegisterGlobalOverload("regex.extractAll", &ExtractAll, registry)));
@@ -306,16 +309,18 @@ absl::Status RegisterRegexExtensionFunctions(RuntimeBuilder& builder) {
306309
}
307310
if (runtime.expr_builder().options().enable_regex) {
308311
CEL_RETURN_IF_ERROR(
309-
RegisterRegexExtensionFunctions(builder.function_registry()));
312+
RegisterRegexExtensionFunctions(builder.function_registry(),
313+
/*disable_extract=*/false));
310314
}
311315
return absl::OkStatus();
312316
}
313317

314318
absl::Status RegisterRegexExtensionFunctions(
315319
google::api::expr::runtime::CelFunctionRegistry* registry,
316320
const google::api::expr::runtime::InterpreterOptions& options) {
317-
if (!options.enable_regex) {
318-
return RegisterRegexExtensionFunctions(registry->InternalGetRegistry());
321+
if (options.enable_regex) {
322+
return RegisterRegexExtensionFunctions(registry->InternalGetRegistry(),
323+
/*disable_extract=*/true);
319324
}
320325
return absl::OkStatus();
321326
}

extensions/regex_ext.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,16 @@
8484

8585
namespace cel::extensions {
8686

87-
// Register extension functions for regular expressions.
87+
// Register extension functions for regular expressions for
88+
// google::api::expr::runtime::CelValue runtime.
89+
//
90+
// Note: CelValue does not support optional types, so regex.extract is
91+
// unsupported.
8892
absl::Status RegisterRegexExtensionFunctions(
8993
google::api::expr::runtime::CelFunctionRegistry* registry,
9094
const google::api::expr::runtime::InterpreterOptions& options);
95+
96+
// Register extension functions for regular expressions.
9197
absl::Status RegisterRegexExtensionFunctions(RuntimeBuilder& builder);
9298

9399
// Type check declarations for the regex extension library.

extensions/regex_ext_test.cc

Lines changed: 114 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,16 @@
2525
#include "absl/strings/string_view.h"
2626
#include "checker/standard_library.h"
2727
#include "checker/validation_result.h"
28+
#include "common/kind.h"
2829
#include "common/value.h"
2930
#include "common/value_testing.h"
3031
#include "compiler/compiler.h"
3132
#include "compiler/compiler_factory.h"
33+
#include "eval/public/activation.h"
34+
#include "eval/public/cel_expr_builder_factory.h"
35+
#include "eval/public/cel_expression.h"
36+
#include "eval/public/cel_function_registry.h"
37+
#include "eval/public/cel_options.h"
3238
#include "extensions/protobuf/runtime_adapter.h"
3339
#include "internal/status_macros.h"
3440
#include "internal/testing.h"
@@ -49,16 +55,120 @@ namespace {
4955
using ::absl_testing::IsOk;
5056
using ::absl_testing::IsOkAndHolds;
5157
using ::absl_testing::StatusIs;
58+
using ::cel::test::BoolValueIs;
5259
using ::cel::test::ErrorValueIs;
60+
using ::cel::test::OptionalValueIs;
61+
using ::cel::test::OptionalValueIsEmpty;
62+
using ::cel::test::StringValueIs;
5363
using ::google::api::expr::parser::Parse;
54-
using test::BoolValueIs;
55-
using test::OptionalValueIs;
56-
using test::OptionalValueIsEmpty;
57-
using test::StringValueIs;
64+
using ::google::api::expr::runtime::CelExpressionBuilder;
65+
using ::google::api::expr::runtime::CelFunctionRegistry;
66+
using ::google::api::expr::runtime::CreateCelExpressionBuilder;
67+
using ::google::api::expr::runtime::InterpreterOptions;
5868
using ::testing::HasSubstr;
69+
using ::testing::IsEmpty;
70+
using ::testing::SizeIs;
5971
using ::testing::TestWithParam;
6072
using ::testing::ValuesIn;
6173

74+
using LegacyActivation = google::api::expr::runtime::Activation;
75+
76+
TEST(RegexExtTest, BuildFailsWithoutOptionalSupport) {
77+
RuntimeOptions options;
78+
options.enable_regex = true;
79+
options.enable_qualified_type_identifiers = true;
80+
81+
ASSERT_OK_AND_ASSIGN(auto builder,
82+
CreateStandardRuntimeBuilder(
83+
internal::GetTestingDescriptorPool(), options));
84+
ASSERT_THAT(
85+
EnableReferenceResolver(builder, ReferenceResolverEnabled::kAlways),
86+
IsOk());
87+
// Optional types are NOT enabled.
88+
ASSERT_THAT(RegisterRegexExtensionFunctions(builder),
89+
StatusIs(absl::StatusCode::kInvalidArgument,
90+
HasSubstr("regex extensions requires the optional types "
91+
"to be enabled")));
92+
}
93+
94+
TEST(RegexExtTest, LegacyRuntimeSmokeTest) {
95+
InterpreterOptions options;
96+
options.enable_regex = true;
97+
options.enable_qualified_type_identifiers = true;
98+
options.enable_qualified_identifier_rewrites = true;
99+
100+
std::unique_ptr<CelExpressionBuilder> builder = CreateCelExpressionBuilder(
101+
internal::GetTestingDescriptorPool(), nullptr, options);
102+
103+
// Optional types are NOT enabled.
104+
ASSERT_THAT(RegisterRegexExtensionFunctions(builder->GetRegistry(), options),
105+
IsOk());
106+
107+
ASSERT_OK_AND_ASSIGN(auto expr,
108+
Parse("regex.extractAll('hello world', 'hello (.*)')"));
109+
LegacyActivation activation;
110+
google::protobuf::Arena arena;
111+
ASSERT_OK_AND_ASSIGN(auto program, builder->CreateExpression(
112+
&expr.expr(), &expr.source_info()));
113+
ASSERT_OK_AND_ASSIGN(auto result, program->Evaluate(activation, &arena));
114+
ASSERT_TRUE(result.IsList());
115+
ASSERT_EQ(result.ListOrDie()->size(), 1);
116+
ASSERT_TRUE(result.ListOrDie()->Get(&arena, 0).IsString());
117+
EXPECT_EQ(result.ListOrDie()->Get(&arena, 0).StringOrDie().value(), "world");
118+
}
119+
120+
TEST(RegexExtTest, DoesNotRegisterExtractForLegacy) {
121+
InterpreterOptions options;
122+
options.enable_regex = true;
123+
124+
CelFunctionRegistry registry;
125+
// Optional types are not usable in legacy runtime, so extract should not be
126+
// registered.
127+
ASSERT_THAT(RegisterRegexExtensionFunctions(&registry, options), IsOk());
128+
EXPECT_THAT(
129+
registry.FindStaticOverloads("regex.extract", false,
130+
{cel::Kind::kString, cel::Kind::kString}),
131+
IsEmpty());
132+
EXPECT_THAT(
133+
registry.FindStaticOverloads("regex.extractAll", false,
134+
{cel::Kind::kString, cel::Kind::kString}),
135+
SizeIs(1));
136+
EXPECT_THAT(registry.FindStaticOverloads(
137+
"regex.replace", false,
138+
{cel::Kind::kString, cel::Kind::kString, cel::Kind::kString}),
139+
SizeIs(1));
140+
EXPECT_THAT(
141+
registry.FindStaticOverloads("regex.replace", false,
142+
{cel::Kind::kString, cel::Kind::kString,
143+
cel::Kind::kString, cel::Kind::kInt64}),
144+
SizeIs(1));
145+
}
146+
147+
TEST(RegexExtTest, FollowsRegexOption) {
148+
InterpreterOptions options;
149+
options.enable_regex = false;
150+
151+
CelFunctionRegistry registry;
152+
ASSERT_THAT(RegisterRegexExtensionFunctions(&registry, options), IsOk());
153+
EXPECT_THAT(
154+
registry.FindStaticOverloads("regex.extract", false,
155+
{cel::Kind::kString, cel::Kind::kString}),
156+
IsEmpty());
157+
EXPECT_THAT(
158+
registry.FindStaticOverloads("regex.extractAll", false,
159+
{cel::Kind::kString, cel::Kind::kString}),
160+
IsEmpty());
161+
EXPECT_THAT(registry.FindStaticOverloads(
162+
"regex.replace", false,
163+
{cel::Kind::kString, cel::Kind::kString, cel::Kind::kString}),
164+
IsEmpty());
165+
EXPECT_THAT(
166+
registry.FindStaticOverloads("regex.replace", false,
167+
{cel::Kind::kString, cel::Kind::kString,
168+
cel::Kind::kString, cel::Kind::kInt64}),
169+
IsEmpty());
170+
}
171+
62172
enum class EvaluationType {
63173
kBoolTrue,
64174
kOptionalValue,
@@ -105,23 +215,6 @@ class RegexExtTest : public TestWithParam<RegexExtTestCase> {
105215
std::unique_ptr<const Runtime> runtime_;
106216
};
107217

108-
TEST_F(RegexExtTest, BuildFailsWithoutOptionalSupport) {
109-
RuntimeOptions options;
110-
options.enable_regex = true;
111-
options.enable_qualified_type_identifiers = true;
112-
113-
ASSERT_OK_AND_ASSIGN(auto builder,
114-
CreateStandardRuntimeBuilder(
115-
internal::GetTestingDescriptorPool(), options));
116-
ASSERT_THAT(
117-
EnableReferenceResolver(builder, ReferenceResolverEnabled::kAlways),
118-
IsOk());
119-
// Optional types are NOT enabled.
120-
ASSERT_THAT(RegisterRegexExtensionFunctions(builder),
121-
StatusIs(absl::StatusCode::kInvalidArgument,
122-
HasSubstr("regex extensions requires the optional types "
123-
"to be enabled")));
124-
}
125218
std::vector<RegexExtTestCase> regexTestCases() {
126219
return {
127220
// Tests for extract Function

0 commit comments

Comments
 (0)