2222#include " absl/status/status.h"
2323#include " absl/status/status_matchers.h"
2424#include " absl/status/statusor.h"
25+ #include " absl/strings/string_view.h"
26+ #include " checker/standard_library.h"
27+ #include " checker/validation_result.h"
2528#include " common/value.h"
2629#include " common/value_testing.h"
30+ #include " compiler/compiler.h"
31+ #include " compiler/compiler_factory.h"
2732#include " extensions/protobuf/runtime_adapter.h"
2833#include " internal/status_macros.h"
2934#include " internal/testing.h"
3338#include " runtime/optional_types.h"
3439#include " runtime/reference_resolver.h"
3540#include " runtime/runtime.h"
36- #include " runtime/runtime_builder.h"
3741#include " runtime/runtime_options.h"
3842#include " runtime/standard_runtime_builder_factory.h"
3943#include " google/protobuf/arena.h"
@@ -84,9 +88,7 @@ class RegexExtTest : public TestWithParam<RegexExtTestCase> {
8488 EnableReferenceResolver (builder, ReferenceResolverEnabled::kAlways ),
8589 IsOk ());
8690 ASSERT_THAT (EnableOptionalTypes (builder), IsOk ());
87- ASSERT_THAT (
88- RegisterRegexExtensionFunctions (builder.function_registry (), options),
89- IsOk ());
91+ ASSERT_THAT (RegisterRegexExtensionFunctions (builder), IsOk ());
9092 ASSERT_OK_AND_ASSIGN (runtime_, std::move (builder).Build ());
9193 }
9294
@@ -103,6 +105,23 @@ class RegexExtTest : public TestWithParam<RegexExtTestCase> {
103105 std::unique_ptr<const Runtime> runtime_;
104106};
105107
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+ }
106125std::vector<RegexExtTestCase> regexTestCases () {
107126 return {
108127 // Tests for extract Function
@@ -121,6 +140,11 @@ std::vector<RegexExtTestCase> regexTestCases() {
121140 " regex.extract('hello world', 'goodbye (.*)')" },
122141 {EvaluationType::kOptionalNone , " regex.extract('HELLO', 'hello')" },
123142 {EvaluationType::kOptionalNone , R"( regex.extract('', r'\w+'))" },
143+ {EvaluationType::kBoolTrue ,
144+ " regex.extract('4122345432', '22').orValue('777') == '22'" },
145+ {EvaluationType::kBoolTrue ,
146+ " regex.extract('4122345432', '22').or(optional.of('777')) == "
147+ " optional.of('22')" },
124148
125149 // Tests for extractAll Function
126150 {EvaluationType::kBoolTrue ,
@@ -328,5 +352,57 @@ TEST_P(RegexExtTest, RegexExtTests) {
328352
329353INSTANTIATE_TEST_SUITE_P (RegexExtTest, RegexExtTest,
330354 ValuesIn (regexTestCases()));
355+
356+ struct RegexCheckerTestCase {
357+ std::string expr_string;
358+ std::string error_substr;
359+ };
360+
361+ class RegexExtCheckerLibraryTest : public TestWithParam <RegexCheckerTestCase> {
362+ public:
363+ void SetUp () override {
364+ // Arrange: Configure the compiler.
365+ // Add the regex checker library to the compiler builder.
366+ ASSERT_OK_AND_ASSIGN (std::unique_ptr<CompilerBuilder> compiler_builder,
367+ NewCompilerBuilder (descriptor_pool_));
368+ ASSERT_THAT (compiler_builder->AddLibrary (StandardCheckerLibrary ()), IsOk ());
369+ ASSERT_THAT (compiler_builder->AddLibrary (RegexExtCompilerLibrary ()),
370+ IsOk ());
371+ ASSERT_OK_AND_ASSIGN (compiler_, std::move (*compiler_builder).Build ());
372+ }
373+
374+ const google::protobuf::DescriptorPool* descriptor_pool_ =
375+ internal::GetTestingDescriptorPool ();
376+ std::unique_ptr<Compiler> compiler_;
377+ };
378+
379+ TEST_P (RegexExtCheckerLibraryTest, RegexExtTypeCheckerTests) {
380+ // Act & Assert: Compile the expression and validate the result.
381+ ASSERT_OK_AND_ASSIGN (ValidationResult result,
382+ compiler_->Compile (GetParam ().expr_string ));
383+ absl::string_view error_substr = GetParam ().error_substr ;
384+ EXPECT_EQ (result.IsValid (), error_substr.empty ());
385+
386+ if (!error_substr.empty ()) {
387+ EXPECT_THAT (result.FormatError (), HasSubstr (error_substr));
388+ }
389+ }
390+
391+ std::vector<RegexCheckerTestCase> createRegexCheckerParams () {
392+ return {
393+ {" regex.replace('abc', 'a', 's') == 'sbc'" },
394+ {" regex.replace('abc', 'a', 's') == 121" ,
395+ " found no matching overload for '_==_' applied to '(string, int)" },
396+ {" regex.replace('abc', 'j', '1', 2) == 9.0" ,
397+ " found no matching overload for '_==_' applied to '(string, double)" },
398+ {" regex.extractAll('banananana', '(ana)') == ['ana', 'ana']" },
399+ {" regex.extract('foo bar', 'f') == 121" ,
400+ " found no matching overload for '_==_' applied to "
401+ " '(optional_type(string), int)'" },
402+ };
403+ }
404+
405+ INSTANTIATE_TEST_SUITE_P (RegexExtCheckerLibraryTest, RegexExtCheckerLibraryTest,
406+ ValuesIn (createRegexCheckerParams()));
331407} // namespace
332408} // namespace cel::extensions
0 commit comments