bloaty/third_party/re2/re2/testing/exhaustive_tester.cc
Go to the documentation of this file.
1 // Copyright 2008 The RE2 Authors. All Rights Reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4 
5 // Exhaustive testing of regular expression matching.
6 
7 // Each test picks an alphabet (e.g., "abc"), a maximum string length,
8 // a maximum regular expression length, and a maximum number of letters
9 // that can appear in the regular expression. Given these parameters,
10 // it tries every possible regular expression and string, verifying that
11 // the NFA, DFA, and a trivial backtracking implementation agree about
12 // the location of the match.
13 
14 #include <stdio.h>
15 
16 #include "util/test.h"
17 #include "util/logging.h"
18 #include "util/strutil.h"
19 #include "re2/testing/exhaustive_tester.h"
20 #include "re2/testing/tester.h"
21 
22 // For target `log' in the Makefile.
23 #ifndef LOGGING
24 #define LOGGING 0
25 #endif
26 
27 DEFINE_bool(show_regexps, false, "show regexps during testing");
28 
29 DEFINE_int32(max_bad_regexp_inputs, 1,
30  "Stop testing a regular expression after finding this many "
31  "strings that break it.");
32 
33 namespace re2 {
34 
35 static char* escape(const StringPiece& sp) {
36  static char buf[512];
37  char* p = buf;
38  *p++ = '\"';
39  for (size_t i = 0; i < sp.size(); i++) {
40  if(p+5 >= buf+sizeof buf)
41  LOG(FATAL) << "ExhaustiveTester escape: too long";
42  if(sp[i] == '\\' || sp[i] == '\"') {
43  *p++ = '\\';
44  *p++ = sp[i];
45  } else if(sp[i] == '\n') {
46  *p++ = '\\';
47  *p++ = 'n';
48  } else {
49  *p++ = sp[i];
50  }
51  }
52  *p++ = '\"';
53  *p = '\0';
54  return buf;
55 }
56 
57 static void PrintResult(const RE2& re, const StringPiece& input, RE2::Anchor anchor, StringPiece *m, int n) {
58  if (!re.Match(input, 0, input.size(), anchor, m, n)) {
59  printf("-");
60  return;
61  }
62  for (int i = 0; i < n; i++) {
63  if (i > 0)
64  printf(" ");
65  if (m[i].data() == NULL)
66  printf("-");
67  else
68  printf("%td-%td",
69  m[i].begin() - input.begin(), m[i].end() - input.begin());
70  }
71 }
72 
73 // Processes a single generated regexp.
74 // Compiles it using Regexp interface and PCRE, and then
75 // checks that NFA, DFA, and PCRE all return the same results.
76 void ExhaustiveTester::HandleRegexp(const std::string& const_regexp) {
77  regexps_++;
78  std::string regexp = const_regexp;
79  if (!topwrapper_.empty())
80  regexp = StringPrintf(topwrapper_.c_str(), regexp.c_str());
81 
82  if (FLAGS_show_regexps) {
83  printf("\r%s", regexp.c_str());
84  fflush(stdout);
85  }
86 
87  if (LOGGING) {
88  // Write out test cases and answers for use in testing
89  // other implementations, such as Go's regexp package.
90  if (randomstrings_)
91  LOG(ERROR) << "Cannot log with random strings.";
92  if (regexps_ == 1) { // first
93  printf("strings\n");
94  strgen_.Reset();
95  while (strgen_.HasNext())
96  printf("%s\n", escape(strgen_.Next()));
97  printf("regexps\n");
98  }
99  printf("%s\n", escape(regexp));
100 
101  RE2 re(regexp);
102  RE2::Options longest;
103  longest.set_longest_match(true);
104  RE2 relongest(regexp, longest);
105  int ngroup = re.NumberOfCapturingGroups()+1;
106  StringPiece* group = new StringPiece[ngroup];
107 
108  strgen_.Reset();
109  while (strgen_.HasNext()) {
111  PrintResult(re, input, RE2::ANCHOR_BOTH, group, ngroup);
112  printf(";");
113  PrintResult(re, input, RE2::UNANCHORED, group, ngroup);
114  printf(";");
115  PrintResult(relongest, input, RE2::ANCHOR_BOTH, group, ngroup);
116  printf(";");
117  PrintResult(relongest, input, RE2::UNANCHORED, group, ngroup);
118  printf("\n");
119  }
120  delete[] group;
121  return;
122  }
123 
124  Tester tester(regexp);
125  if (tester.error())
126  return;
127 
128  strgen_.Reset();
130  if (randomstrings_)
132  int bad_inputs = 0;
133  while (strgen_.HasNext()) {
134  tests_++;
135  if (!tester.TestInput(strgen_.Next())) {
136  failures_++;
137  if (++bad_inputs >= FLAGS_max_bad_regexp_inputs)
138  break;
139  }
140  }
141 }
142 
143 // Runs an exhaustive test on the given parameters.
144 void ExhaustiveTest(int maxatoms, int maxops,
145  const std::vector<std::string>& alphabet,
146  const std::vector<std::string>& ops,
147  int maxstrlen,
148  const std::vector<std::string>& stralphabet,
149  const std::string& wrapper,
150  const std::string& topwrapper) {
151  if (RE2_DEBUG_MODE) {
152  if (maxatoms > 1)
153  maxatoms--;
154  if (maxops > 1)
155  maxops--;
156  if (maxstrlen > 1)
157  maxstrlen--;
158  }
159  ExhaustiveTester t(maxatoms, maxops, alphabet, ops,
160  maxstrlen, stralphabet, wrapper,
161  topwrapper);
162  t.Generate();
163  if (!LOGGING) {
164  printf("%d regexps, %d tests, %d failures [%d/%d str]\n",
165  t.regexps(), t.tests(), t.failures(), maxstrlen, (int)stralphabet.size());
166  }
167  EXPECT_EQ(0, t.failures());
168 }
169 
170 // Runs an exhaustive test using the given parameters and
171 // the basic egrep operators.
172 void EgrepTest(int maxatoms, int maxops, const std::string& alphabet,
173  int maxstrlen, const std::string& stralphabet,
174  const std::string& wrapper) {
175  const char* tops[] = { "", "^(?:%s)", "(?:%s)$", "^(?:%s)$" };
176 
177  for (size_t i = 0; i < arraysize(tops); i++) {
178  ExhaustiveTest(maxatoms, maxops,
179  Split("", alphabet),
181  maxstrlen,
182  Split("", stralphabet),
183  wrapper,
184  tops[i]);
185  }
186 }
187 
188 } // namespace re2
re2::ExhaustiveTester::tests_
int tests_
Definition: bloaty/third_party/re2/re2/testing/exhaustive_tester.h:77
re2::StringGenerator::GenerateNULL
void GenerateNULL()
Definition: bloaty/third_party/re2/re2/testing/string_generator.cc:109
re2::ExhaustiveTester::strgen_
StringGenerator strgen_
Definition: bloaty/third_party/re2/re2/testing/exhaustive_tester.h:73
demumble_test.stdout
stdout
Definition: demumble_test.py:38
begin
char * begin
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1007
LOGGING
#define LOGGING
Definition: bloaty/third_party/re2/re2/testing/exhaustive_tester.cc:24
re2::Split
std::vector< std::string > Split(const StringPiece &sep, const StringPiece &s)
Definition: bloaty/third_party/re2/re2/testing/regexp_generator.cc:256
re2::StringPiece::size
size_type size() const
Definition: bloaty/third_party/re2/re2/stringpiece.h:80
buf
voidpf void * buf
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
printf
_Use_decl_annotations_ int __cdecl printf(const char *_Format,...)
Definition: cs_driver.c:91
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
re2::ExhaustiveTester::stringseed_
int32_t stringseed_
Definition: bloaty/third_party/re2/re2/testing/exhaustive_tester.h:81
re2::RE2::ANCHOR_BOTH
@ ANCHOR_BOTH
Definition: bloaty/third_party/re2/re2/re2.h:475
re2::ExhaustiveTest
void ExhaustiveTest(int maxatoms, int maxops, const std::vector< std::string > &alphabet, const std::vector< std::string > &ops, int maxstrlen, const std::vector< std::string > &stralphabet, const std::string &wrapper, const std::string &topwrapper)
Definition: bloaty/third_party/re2/re2/testing/exhaustive_tester.cc:144
re2::RE2::UNANCHORED
@ UNANCHORED
Definition: bloaty/third_party/re2/re2/re2.h:473
re2
Definition: bloaty/third_party/re2/re2/bitmap256.h:17
alphabet
static const char alphabet[]
Definition: bin_encoder.cc:30
DEFINE_bool
DEFINE_bool(show_regexps, false, "show regexps during testing")
re2::PrintResult
static void PrintResult(const RE2 &re, const StringPiece &input, RE2::Anchor anchor, StringPiece *m, int n)
Definition: bloaty/third_party/re2/re2/testing/exhaustive_tester.cc:57
re2::StringGenerator::HasNext
bool HasNext()
Definition: bloaty/third_party/re2/re2/testing/string_generator.h:28
EXPECT_EQ
#define EXPECT_EQ(a, b)
Definition: iomgr/time_averaged_stats_test.cc:27
DEFINE_int32
DEFINE_int32(max_bad_regexp_inputs, 1, "Stop testing a regular expression after finding this many " "strings that break it.")
re2::Tester::TestInput
bool TestInput(const StringPiece &text)
Definition: bloaty/third_party/re2/re2/testing/tester.cc:641
re2::Tester
Definition: bloaty/third_party/re2/re2/testing/tester.h:92
LOG
#define LOG(severity)
Definition: bloaty/third_party/re2/util/logging.h:53
re2::ExhaustiveTester::regexps_
int regexps_
Definition: bloaty/third_party/re2/re2/testing/exhaustive_tester.h:76
re2::StringPrintf
std::string StringPrintf(const char *format,...)
Definition: bloaty/third_party/re2/util/strutil.cc:140
re2::StringGenerator::Reset
void Reset()
Definition: bloaty/third_party/re2/re2/testing/string_generator.cc:35
re2::StringGenerator::Random
void Random(int32_t seed, int n)
Definition: bloaty/third_party/re2/re2/testing/string_generator.cc:101
re2::EgrepTest
void EgrepTest(int maxatoms, int maxops, const std::string &alphabet, int maxstrlen, const std::string &stralphabet, const std::string &wrapper)
Definition: bloaty/third_party/re2/re2/testing/exhaustive_tester.cc:172
data
char data[kBufferLength]
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1006
wrapper
grpc_channel_wrapper * wrapper
Definition: src/php/ext/grpc/channel.h:48
re2::RE2
Definition: bloaty/third_party/re2/re2/re2.h:211
re2::Tester::error
bool error()
Definition: bloaty/third_party/re2/re2/testing/tester.h:97
n
int n
Definition: abseil-cpp/absl/container/btree_test.cc:1080
google::protobuf::ERROR
static const LogLevel ERROR
Definition: bloaty/third_party/protobuf/src/google/protobuf/testing/googletest.h:70
arraysize
#define arraysize(array)
Definition: benchmark/src/arraysize.h:28
re2::RE2::Match
bool Match(const StringPiece &text, size_t startpos, size_t endpos, Anchor re_anchor, StringPiece *submatch, int nsubmatch) const
Definition: bloaty/third_party/re2/re2/re2.cc:572
FATAL
#define FATAL(msg)
Definition: task.h:88
re2::RegexpGenerator::EgrepOps
static const std::vector< std::string > & EgrepOps()
Definition: bloaty/third_party/re2/re2/testing/regexp_generator.cc:41
re2::RE2::Options
Definition: bloaty/third_party/re2/re2/re2.h:548
upload.group
group
Definition: bloaty/third_party/googletest/googlemock/scripts/upload.py:397
re2::RE2_DEBUG_MODE
const bool RE2_DEBUG_MODE
Definition: bloaty/third_party/re2/re2/testing/exhaustive_tester.h:25
re2::ExhaustiveTester::HandleRegexp
void HandleRegexp(const std::string &regexp)
Definition: bloaty/third_party/re2/re2/testing/exhaustive_tester.cc:76
re2::RE2::Options::set_longest_match
void set_longest_match(bool b)
Definition: bloaty/third_party/re2/re2/re2.h:644
re2::ExhaustiveTester
Definition: bloaty/third_party/re2/re2/testing/exhaustive_tester.h:41
re2::ExhaustiveTester::stringcount_
int stringcount_
Definition: bloaty/third_party/re2/re2/testing/exhaustive_tester.h:82
input
std::string input
Definition: bloaty/third_party/protobuf/src/google/protobuf/io/tokenizer_unittest.cc:197
re2::escape
static char * escape(const StringPiece &sp)
Definition: bloaty/third_party/re2/re2/testing/exhaustive_tester.cc:35
re2::RE2::Anchor
Anchor
Definition: bloaty/third_party/re2/re2/re2.h:472
re2::StringGenerator::Next
const StringPiece & Next()
Definition: bloaty/third_party/re2/re2/testing/string_generator.cc:84
re2::RE2::NumberOfCapturingGroups
int NumberOfCapturingGroups() const
Definition: bloaty/third_party/re2/re2/re2.h:481
regress.m
m
Definition: regress/regress.py:25
re2::ExhaustiveTester::randomstrings_
bool randomstrings_
Definition: bloaty/third_party/re2/re2/testing/exhaustive_tester.h:80
re2::StringPiece
Definition: bloaty/third_party/re2/re2/stringpiece.h:39
ops
static grpc_op ops[6]
Definition: test/core/fling/client.cc:39
re2::ExhaustiveTester::topwrapper_
std::string topwrapper_
Definition: bloaty/third_party/re2/re2/testing/exhaustive_tester.h:75
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
re2::ExhaustiveTester::failures_
int failures_
Definition: bloaty/third_party/re2/re2/testing/exhaustive_tester.h:78


grpc
Author(s):
autogenerated on Fri May 16 2025 02:58:20