tools/pcre/pcrecpp_unittest.cc
changeset 2762 d2d467bf1b5a
child 3831 babd0eee3c5e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/tools/pcre/pcrecpp_unittest.cc	Tue Jul 28 17:51:34 2009 -0400
     1.3 @@ -0,0 +1,1276 @@
     1.4 +// -*- coding: utf-8 -*-
     1.5 +//
     1.6 +// Copyright (c) 2005 - 2006, Google Inc.
     1.7 +// All rights reserved.
     1.8 +//
     1.9 +// Redistribution and use in source and binary forms, with or without
    1.10 +// modification, are permitted provided that the following conditions are
    1.11 +// met:
    1.12 +//
    1.13 +//     * Redistributions of source code must retain the above copyright
    1.14 +// notice, this list of conditions and the following disclaimer.
    1.15 +//     * Redistributions in binary form must reproduce the above
    1.16 +// copyright notice, this list of conditions and the following disclaimer
    1.17 +// in the documentation and/or other materials provided with the
    1.18 +// distribution.
    1.19 +//     * Neither the name of Google Inc. nor the names of its
    1.20 +// contributors may be used to endorse or promote products derived from
    1.21 +// this software without specific prior written permission.
    1.22 +//
    1.23 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    1.24 +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    1.25 +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    1.26 +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    1.27 +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    1.28 +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    1.29 +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    1.30 +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    1.31 +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    1.32 +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    1.33 +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    1.34 +//
    1.35 +// Author: Sanjay Ghemawat
    1.36 +//
    1.37 +// TODO: Test extractions for PartialMatch/Consume
    1.38 +
    1.39 +#ifdef HAVE_CONFIG_H
    1.40 +#include "config.h"
    1.41 +#endif
    1.42 +
    1.43 +#include <stdio.h>
    1.44 +#include <cassert>
    1.45 +#include <vector>
    1.46 +#include "pcrecpp.h"
    1.47 +
    1.48 +using pcrecpp::StringPiece;
    1.49 +using pcrecpp::RE;
    1.50 +using pcrecpp::RE_Options;
    1.51 +using pcrecpp::Hex;
    1.52 +using pcrecpp::Octal;
    1.53 +using pcrecpp::CRadix;
    1.54 +
    1.55 +static bool VERBOSE_TEST  = false;
    1.56 +
    1.57 +// CHECK dies with a fatal error if condition is not true.  It is *not*
    1.58 +// controlled by NDEBUG, so the check will be executed regardless of
    1.59 +// compilation mode.  Therefore, it is safe to do things like:
    1.60 +//    CHECK_EQ(fp->Write(x), 4)
    1.61 +#define CHECK(condition) do {                           \
    1.62 +  if (!(condition)) {                                   \
    1.63 +    fprintf(stderr, "%s:%d: Check failed: %s\n",        \
    1.64 +            __FILE__, __LINE__, #condition);            \
    1.65 +    exit(1);                                            \
    1.66 +  }                                                     \
    1.67 +} while (0)
    1.68 +
    1.69 +#define CHECK_EQ(a, b)   CHECK(a == b)
    1.70 +
    1.71 +static void Timing1(int num_iters) {
    1.72 +  // Same pattern lots of times
    1.73 +  RE pattern("ruby:\\d+");
    1.74 +  StringPiece p("ruby:1234");
    1.75 +  for (int j = num_iters; j > 0; j--) {
    1.76 +    CHECK(pattern.FullMatch(p));
    1.77 +  }
    1.78 +}
    1.79 +
    1.80 +static void Timing2(int num_iters) {
    1.81 +  // Same pattern lots of times
    1.82 +  RE pattern("ruby:(\\d+)");
    1.83 +  int i;
    1.84 +  for (int j = num_iters; j > 0; j--) {
    1.85 +    CHECK(pattern.FullMatch("ruby:1234", &i));
    1.86 +    CHECK_EQ(i, 1234);
    1.87 +  }
    1.88 +}
    1.89 +
    1.90 +static void Timing3(int num_iters) {
    1.91 +  string text_string;
    1.92 +  for (int j = num_iters; j > 0; j--) {
    1.93 +    text_string += "this is another line\n";
    1.94 +  }
    1.95 +
    1.96 +  RE line_matcher(".*\n");
    1.97 +  string line;
    1.98 +  StringPiece text(text_string);
    1.99 +  int counter = 0;
   1.100 +  while (line_matcher.Consume(&text)) {
   1.101 +    counter++;
   1.102 +  }
   1.103 +  printf("Matched %d lines\n", counter);
   1.104 +}
   1.105 +
   1.106 +#if 0  // uncomment this if you have a way of defining VirtualProcessSize()
   1.107 +
   1.108 +static void LeakTest() {
   1.109 +  // Check for memory leaks
   1.110 +  unsigned long long initial_size = 0;
   1.111 +  for (int i = 0; i < 100000; i++) {
   1.112 +    if (i == 50000) {
   1.113 +      initial_size = VirtualProcessSize();
   1.114 +      printf("Size after 50000: %llu\n", initial_size);
   1.115 +    }
   1.116 +    char buf[100];  // definitely big enough
   1.117 +    sprintf(buf, "pat%09d", i);
   1.118 +    RE newre(buf);
   1.119 +  }
   1.120 +  uint64 final_size = VirtualProcessSize();
   1.121 +  printf("Size after 100000: %llu\n", final_size);
   1.122 +  const double growth = double(final_size - initial_size) / final_size;
   1.123 +  printf("Growth: %0.2f%%", growth * 100);
   1.124 +  CHECK(growth < 0.02);       // Allow < 2% growth
   1.125 +}
   1.126 +
   1.127 +#endif
   1.128 +
   1.129 +static void RadixTests() {
   1.130 +  printf("Testing hex\n");
   1.131 +
   1.132 +#define CHECK_HEX(type, value) \
   1.133 +  do { \
   1.134 +    type v; \
   1.135 +    CHECK(RE("([0-9a-fA-F]+)[uUlL]*").FullMatch(#value, Hex(&v))); \
   1.136 +    CHECK_EQ(v, 0x ## value); \
   1.137 +    CHECK(RE("([0-9a-fA-FxX]+)[uUlL]*").FullMatch("0x" #value, CRadix(&v))); \
   1.138 +    CHECK_EQ(v, 0x ## value); \
   1.139 +  } while(0)
   1.140 +
   1.141 +  CHECK_HEX(short,              2bad);
   1.142 +  CHECK_HEX(unsigned short,     2badU);
   1.143 +  CHECK_HEX(int,                dead);
   1.144 +  CHECK_HEX(unsigned int,       deadU);
   1.145 +  CHECK_HEX(long,               7eadbeefL);
   1.146 +  CHECK_HEX(unsigned long,      deadbeefUL);
   1.147 +#ifdef HAVE_LONG_LONG
   1.148 +  CHECK_HEX(long long,          12345678deadbeefLL);
   1.149 +#endif
   1.150 +#ifdef HAVE_UNSIGNED_LONG_LONG
   1.151 +  CHECK_HEX(unsigned long long, cafebabedeadbeefULL);
   1.152 +#endif
   1.153 +
   1.154 +#undef CHECK_HEX
   1.155 +
   1.156 +  printf("Testing octal\n");
   1.157 +
   1.158 +#define CHECK_OCTAL(type, value) \
   1.159 +  do { \
   1.160 +    type v; \
   1.161 +    CHECK(RE("([0-7]+)[uUlL]*").FullMatch(#value, Octal(&v))); \
   1.162 +    CHECK_EQ(v, 0 ## value); \
   1.163 +    CHECK(RE("([0-9a-fA-FxX]+)[uUlL]*").FullMatch("0" #value, CRadix(&v))); \
   1.164 +    CHECK_EQ(v, 0 ## value); \
   1.165 +  } while(0)
   1.166 +
   1.167 +  CHECK_OCTAL(short,              77777);
   1.168 +  CHECK_OCTAL(unsigned short,     177777U);
   1.169 +  CHECK_OCTAL(int,                17777777777);
   1.170 +  CHECK_OCTAL(unsigned int,       37777777777U);
   1.171 +  CHECK_OCTAL(long,               17777777777L);
   1.172 +  CHECK_OCTAL(unsigned long,      37777777777UL);
   1.173 +#ifdef HAVE_LONG_LONG
   1.174 +  CHECK_OCTAL(long long,          777777777777777777777LL);
   1.175 +#endif
   1.176 +#ifdef HAVE_UNSIGNED_LONG_LONG
   1.177 +  CHECK_OCTAL(unsigned long long, 1777777777777777777777ULL);
   1.178 +#endif
   1.179 +
   1.180 +#undef CHECK_OCTAL
   1.181 +
   1.182 +  printf("Testing decimal\n");
   1.183 +
   1.184 +#define CHECK_DECIMAL(type, value) \
   1.185 +  do { \
   1.186 +    type v; \
   1.187 +    CHECK(RE("(-?[0-9]+)[uUlL]*").FullMatch(#value, &v)); \
   1.188 +    CHECK_EQ(v, value); \
   1.189 +    CHECK(RE("(-?[0-9a-fA-FxX]+)[uUlL]*").FullMatch(#value, CRadix(&v))); \
   1.190 +    CHECK_EQ(v, value); \
   1.191 +  } while(0)
   1.192 +
   1.193 +  CHECK_DECIMAL(short,              -1);
   1.194 +  CHECK_DECIMAL(unsigned short,     9999);
   1.195 +  CHECK_DECIMAL(int,                -1000);
   1.196 +  CHECK_DECIMAL(unsigned int,       12345U);
   1.197 +  CHECK_DECIMAL(long,               -10000000L);
   1.198 +  CHECK_DECIMAL(unsigned long,      3083324652U);
   1.199 +#ifdef HAVE_LONG_LONG
   1.200 +  CHECK_DECIMAL(long long,          -100000000000000LL);
   1.201 +#endif
   1.202 +#ifdef HAVE_UNSIGNED_LONG_LONG
   1.203 +  CHECK_DECIMAL(unsigned long long, 1234567890987654321ULL);
   1.204 +#endif
   1.205 +
   1.206 +#undef CHECK_DECIMAL
   1.207 +
   1.208 +}
   1.209 +
   1.210 +static void TestReplace() {
   1.211 +  printf("Testing Replace\n");
   1.212 +
   1.213 +  struct ReplaceTest {
   1.214 +    const char *regexp;
   1.215 +    const char *rewrite;
   1.216 +    const char *original;
   1.217 +    const char *single;
   1.218 +    const char *global;
   1.219 +    int global_count;         // the expected return value from ReplaceAll
   1.220 +  };
   1.221 +  static const ReplaceTest tests[] = {
   1.222 +    { "(qu|[b-df-hj-np-tv-z]*)([a-z]+)",
   1.223 +      "\\2\\1ay",
   1.224 +      "the quick brown fox jumps over the lazy dogs.",
   1.225 +      "ethay quick brown fox jumps over the lazy dogs.",
   1.226 +      "ethay ickquay ownbray oxfay umpsjay overay ethay azylay ogsday.",
   1.227 +      9 },
   1.228 +    { "\\w+",
   1.229 +      "\\0-NOSPAM",
   1.230 +      "[email protected]",
   1.231 +      "[email protected]",
   1.232 +      "[email protected]",
   1.233 +      4 },
   1.234 +    { "^",
   1.235 +      "(START)",
   1.236 +      "foo",
   1.237 +      "(START)foo",
   1.238 +      "(START)foo",
   1.239 +      1 },
   1.240 +    { "^",
   1.241 +      "(START)",
   1.242 +      "",
   1.243 +      "(START)",
   1.244 +      "(START)",
   1.245 +      1 },
   1.246 +    { "$",
   1.247 +      "(END)",
   1.248 +      "",
   1.249 +      "(END)",
   1.250 +      "(END)",
   1.251 +      1 },
   1.252 +    { "b",
   1.253 +      "bb",
   1.254 +      "ababababab",
   1.255 +      "abbabababab",
   1.256 +      "abbabbabbabbabb",
   1.257 +       5 },
   1.258 +    { "b",
   1.259 +      "bb",
   1.260 +      "bbbbbb",
   1.261 +      "bbbbbbb",
   1.262 +      "bbbbbbbbbbbb",
   1.263 +      6 },
   1.264 +    { "b+",
   1.265 +      "bb",
   1.266 +      "bbbbbb",
   1.267 +      "bb",
   1.268 +      "bb",
   1.269 +      1 },
   1.270 +    { "b*",
   1.271 +      "bb",
   1.272 +      "bbbbbb",
   1.273 +      "bb",
   1.274 +      "bb",
   1.275 +      1 },
   1.276 +    { "b*",
   1.277 +      "bb",
   1.278 +      "aaaaa",
   1.279 +      "bbaaaaa",
   1.280 +      "bbabbabbabbabbabb",
   1.281 +      6 },
   1.282 +    { "b*",
   1.283 +      "bb",
   1.284 +      "aa\naa\n",
   1.285 +      "bbaa\naa\n",
   1.286 +      "bbabbabb\nbbabbabb\nbb",
   1.287 +      7 },
   1.288 +    { "b*",
   1.289 +      "bb",
   1.290 +      "aa\raa\r",
   1.291 +      "bbaa\raa\r",
   1.292 +      "bbabbabb\rbbabbabb\rbb",
   1.293 +      7 },
   1.294 +    { "b*",
   1.295 +      "bb",
   1.296 +      "aa\r\naa\r\n",
   1.297 +      "bbaa\r\naa\r\n",
   1.298 +      "bbabbabb\r\nbbabbabb\r\nbb",
   1.299 +      7 },
   1.300 +#ifdef SUPPORT_UTF8
   1.301 +    { "b*",
   1.302 +      "bb",
   1.303 +      "\xE3\x83\x9B\xE3\x83\xBC\xE3\x83\xA0\xE3\x81\xB8",   // utf8
   1.304 +      "bb\xE3\x83\x9B\xE3\x83\xBC\xE3\x83\xA0\xE3\x81\xB8",
   1.305 +      "bb\xE3\x83\x9B""bb""\xE3\x83\xBC""bb""\xE3\x83\xA0""bb""\xE3\x81\xB8""bb",
   1.306 +      5 },
   1.307 +    { "b*",
   1.308 +      "bb",
   1.309 +      "\xE3\x83\x9B\r\n\xE3\x83\xBC\r\xE3\x83\xA0\n\xE3\x81\xB8\r\n",   // utf8
   1.310 +      "bb\xE3\x83\x9B\r\n\xE3\x83\xBC\r\xE3\x83\xA0\n\xE3\x81\xB8\r\n",
   1.311 +      ("bb\xE3\x83\x9B""bb\r\nbb""\xE3\x83\xBC""bb\rbb""\xE3\x83\xA0"
   1.312 +       "bb\nbb""\xE3\x81\xB8""bb\r\nbb"),
   1.313 +      9 },
   1.314 +#endif
   1.315 +    { "", NULL, NULL, NULL, NULL, 0 }
   1.316 +  };
   1.317 +
   1.318 +#ifdef SUPPORT_UTF8
   1.319 +  const bool support_utf8 = true;
   1.320 +#else
   1.321 +  const bool support_utf8 = false;
   1.322 +#endif
   1.323 +
   1.324 +  for (const ReplaceTest *t = tests; t->original != NULL; ++t) {
   1.325 +    RE re(t->regexp, RE_Options(PCRE_NEWLINE_CRLF).set_utf8(support_utf8));
   1.326 +    assert(re.error().empty());
   1.327 +    string one(t->original);
   1.328 +    CHECK(re.Replace(t->rewrite, &one));
   1.329 +    CHECK_EQ(one, t->single);
   1.330 +    string all(t->original);
   1.331 +    const int replace_count = re.GlobalReplace(t->rewrite, &all);
   1.332 +    CHECK_EQ(all, t->global);
   1.333 +    CHECK_EQ(replace_count, t->global_count);
   1.334 +  }
   1.335 +
   1.336 +  // One final test: test \r\n replacement when we're not in CRLF mode
   1.337 +  {
   1.338 +    RE re("b*", RE_Options(PCRE_NEWLINE_CR).set_utf8(support_utf8));
   1.339 +    assert(re.error().empty());
   1.340 +    string all("aa\r\naa\r\n");
   1.341 +    CHECK_EQ(re.GlobalReplace("bb", &all), 9);
   1.342 +    CHECK_EQ(all, string("bbabbabb\rbb\nbbabbabb\rbb\nbb"));
   1.343 +  }
   1.344 +  {
   1.345 +    RE re("b*", RE_Options(PCRE_NEWLINE_LF).set_utf8(support_utf8));
   1.346 +    assert(re.error().empty());
   1.347 +    string all("aa\r\naa\r\n");
   1.348 +    CHECK_EQ(re.GlobalReplace("bb", &all), 9);
   1.349 +    CHECK_EQ(all, string("bbabbabb\rbb\nbbabbabb\rbb\nbb"));
   1.350 +  }
   1.351 +  // TODO: test what happens when no PCRE_NEWLINE_* flag is set.
   1.352 +  //       Alas, the answer depends on how pcre was compiled.
   1.353 +}
   1.354 +
   1.355 +static void TestExtract() {
   1.356 +  printf("Testing Extract\n");
   1.357 +
   1.358 +  string s;
   1.359 +
   1.360 +  CHECK(RE("(.*)@([^.]*)").Extract("\\2!\\1", "[email protected]", &s));
   1.361 +  CHECK_EQ(s, "kremvax!boris");
   1.362 +
   1.363 +  // check the RE interface as well
   1.364 +  CHECK(RE(".*").Extract("'\\0'", "foo", &s));
   1.365 +  CHECK_EQ(s, "'foo'");
   1.366 +  CHECK(!RE("bar").Extract("'\\0'", "baz", &s));
   1.367 +  CHECK_EQ(s, "'foo'");
   1.368 +}
   1.369 +
   1.370 +static void TestConsume() {
   1.371 +  printf("Testing Consume\n");
   1.372 +
   1.373 +  string word;
   1.374 +
   1.375 +  string s("   aaa b!@#$@#$cccc");
   1.376 +  StringPiece input(s);
   1.377 +
   1.378 +  RE r("\\s*(\\w+)");    // matches a word, possibly proceeded by whitespace
   1.379 +  CHECK(r.Consume(&input, &word));
   1.380 +  CHECK_EQ(word, "aaa");
   1.381 +  CHECK(r.Consume(&input, &word));
   1.382 +  CHECK_EQ(word, "b");
   1.383 +  CHECK(! r.Consume(&input, &word));
   1.384 +}
   1.385 +
   1.386 +static void TestFindAndConsume() {
   1.387 +  printf("Testing FindAndConsume\n");
   1.388 +
   1.389 +  string word;
   1.390 +
   1.391 +  string s("   aaa b!@#$@#$cccc");
   1.392 +  StringPiece input(s);
   1.393 +
   1.394 +  RE r("(\\w+)");      // matches a word
   1.395 +  CHECK(r.FindAndConsume(&input, &word));
   1.396 +  CHECK_EQ(word, "aaa");
   1.397 +  CHECK(r.FindAndConsume(&input, &word));
   1.398 +  CHECK_EQ(word, "b");
   1.399 +  CHECK(r.FindAndConsume(&input, &word));
   1.400 +  CHECK_EQ(word, "cccc");
   1.401 +  CHECK(! r.FindAndConsume(&input, &word));
   1.402 +}
   1.403 +
   1.404 +static void TestMatchNumberPeculiarity() {
   1.405 +  printf("Testing match-number peculiaraity\n");
   1.406 +
   1.407 +  string word1;
   1.408 +  string word2;
   1.409 +  string word3;
   1.410 +
   1.411 +  RE r("(foo)|(bar)|(baz)");
   1.412 +  CHECK(r.PartialMatch("foo", &word1, &word2, &word3));
   1.413 +  CHECK_EQ(word1, "foo");
   1.414 +  CHECK_EQ(word2, "");
   1.415 +  CHECK_EQ(word3, "");
   1.416 +  CHECK(r.PartialMatch("bar", &word1, &word2, &word3));
   1.417 +  CHECK_EQ(word1, "");
   1.418 +  CHECK_EQ(word2, "bar");
   1.419 +  CHECK_EQ(word3, "");
   1.420 +  CHECK(r.PartialMatch("baz", &word1, &word2, &word3));
   1.421 +  CHECK_EQ(word1, "");
   1.422 +  CHECK_EQ(word2, "");
   1.423 +  CHECK_EQ(word3, "baz");
   1.424 +  CHECK(!r.PartialMatch("f", &word1, &word2, &word3));
   1.425 +
   1.426 +  string a;
   1.427 +  CHECK(RE("(foo)|hello").FullMatch("hello", &a));
   1.428 +  CHECK_EQ(a, "");
   1.429 +}
   1.430 +
   1.431 +static void TestRecursion() {
   1.432 +  printf("Testing recursion\n");
   1.433 +
   1.434 +  // Get one string that passes (sometimes), one that never does.
   1.435 +  string text_good("abcdefghijk");
   1.436 +  string text_bad("acdefghijkl");
   1.437 +
   1.438 +  // According to pcretest, matching text_good against (\w+)*b
   1.439 +  // requires match_limit of at least 8192, and match_recursion_limit
   1.440 +  // of at least 37.
   1.441 +
   1.442 +  RE_Options options_ml;
   1.443 +  options_ml.set_match_limit(8192);
   1.444 +  RE re("(\\w+)*b", options_ml);
   1.445 +  CHECK(re.PartialMatch(text_good) == true);
   1.446 +  CHECK(re.PartialMatch(text_bad) == false);
   1.447 +  CHECK(re.FullMatch(text_good) == false);
   1.448 +  CHECK(re.FullMatch(text_bad) == false);
   1.449 +
   1.450 +  options_ml.set_match_limit(1024);
   1.451 +  RE re2("(\\w+)*b", options_ml);
   1.452 +  CHECK(re2.PartialMatch(text_good) == false);   // because of match_limit
   1.453 +  CHECK(re2.PartialMatch(text_bad) == false);
   1.454 +  CHECK(re2.FullMatch(text_good) == false);
   1.455 +  CHECK(re2.FullMatch(text_bad) == false);
   1.456 +
   1.457 +  RE_Options options_mlr;
   1.458 +  options_mlr.set_match_limit_recursion(50);
   1.459 +  RE re3("(\\w+)*b", options_mlr);
   1.460 +  CHECK(re3.PartialMatch(text_good) == true);
   1.461 +  CHECK(re3.PartialMatch(text_bad) == false);
   1.462 +  CHECK(re3.FullMatch(text_good) == false);
   1.463 +  CHECK(re3.FullMatch(text_bad) == false);
   1.464 +
   1.465 +  options_mlr.set_match_limit_recursion(10);
   1.466 +  RE re4("(\\w+)*b", options_mlr);
   1.467 +  CHECK(re4.PartialMatch(text_good) == false);
   1.468 +  CHECK(re4.PartialMatch(text_bad) == false);
   1.469 +  CHECK(re4.FullMatch(text_good) == false);
   1.470 +  CHECK(re4.FullMatch(text_bad) == false);
   1.471 +}
   1.472 +
   1.473 +// A meta-quoted string, interpreted as a pattern, should always match
   1.474 +// the original unquoted string.
   1.475 +static void TestQuoteMeta(string unquoted, RE_Options options = RE_Options()) {
   1.476 +  string quoted = RE::QuoteMeta(unquoted);
   1.477 +  RE re(quoted, options);
   1.478 +  CHECK(re.FullMatch(unquoted));
   1.479 +}
   1.480 +
   1.481 +// A string containing meaningful regexp characters, which is then meta-
   1.482 +// quoted, should not generally match a string the unquoted string does.
   1.483 +static void NegativeTestQuoteMeta(string unquoted, string should_not_match,
   1.484 +                                  RE_Options options = RE_Options()) {
   1.485 +  string quoted = RE::QuoteMeta(unquoted);
   1.486 +  RE re(quoted, options);
   1.487 +  CHECK(!re.FullMatch(should_not_match));
   1.488 +}
   1.489 +
   1.490 +// Tests that quoted meta characters match their original strings,
   1.491 +// and that a few things that shouldn't match indeed do not.
   1.492 +static void TestQuotaMetaSimple() {
   1.493 +  TestQuoteMeta("foo");
   1.494 +  TestQuoteMeta("foo.bar");
   1.495 +  TestQuoteMeta("foo\\.bar");
   1.496 +  TestQuoteMeta("[1-9]");
   1.497 +  TestQuoteMeta("1.5-2.0?");
   1.498 +  TestQuoteMeta("\\d");
   1.499 +  TestQuoteMeta("Who doesn't like ice cream?");
   1.500 +  TestQuoteMeta("((a|b)c?d*e+[f-h]i)");
   1.501 +  TestQuoteMeta("((?!)xxx).*yyy");
   1.502 +  TestQuoteMeta("([");
   1.503 +  TestQuoteMeta(string("foo\0bar", 7));
   1.504 +}
   1.505 +
   1.506 +static void TestQuoteMetaSimpleNegative() {
   1.507 +  NegativeTestQuoteMeta("foo", "bar");
   1.508 +  NegativeTestQuoteMeta("...", "bar");
   1.509 +  NegativeTestQuoteMeta("\\.", ".");
   1.510 +  NegativeTestQuoteMeta("\\.", "..");
   1.511 +  NegativeTestQuoteMeta("(a)", "a");
   1.512 +  NegativeTestQuoteMeta("(a|b)", "a");
   1.513 +  NegativeTestQuoteMeta("(a|b)", "(a)");
   1.514 +  NegativeTestQuoteMeta("(a|b)", "a|b");
   1.515 +  NegativeTestQuoteMeta("[0-9]", "0");
   1.516 +  NegativeTestQuoteMeta("[0-9]", "0-9");
   1.517 +  NegativeTestQuoteMeta("[0-9]", "[9]");
   1.518 +  NegativeTestQuoteMeta("((?!)xxx)", "xxx");
   1.519 +}
   1.520 +
   1.521 +static void TestQuoteMetaLatin1() {
   1.522 +  TestQuoteMeta("3\xb2 = 9");
   1.523 +}
   1.524 +
   1.525 +static void TestQuoteMetaUtf8() {
   1.526 +#ifdef SUPPORT_UTF8
   1.527 +  TestQuoteMeta("Pl\xc3\xa1\x63ido Domingo", pcrecpp::UTF8());
   1.528 +  TestQuoteMeta("xyz", pcrecpp::UTF8());            // No fancy utf8
   1.529 +  TestQuoteMeta("\xc2\xb0", pcrecpp::UTF8());       // 2-byte utf8 (degree symbol)
   1.530 +  TestQuoteMeta("27\xc2\xb0 degrees", pcrecpp::UTF8());  // As a middle character
   1.531 +  TestQuoteMeta("\xe2\x80\xb3", pcrecpp::UTF8());   // 3-byte utf8 (double prime)
   1.532 +  TestQuoteMeta("\xf0\x9d\x85\x9f", pcrecpp::UTF8()); // 4-byte utf8 (music note)
   1.533 +  TestQuoteMeta("27\xc2\xb0"); // Interpreted as Latin-1, but should still work
   1.534 +  NegativeTestQuoteMeta("27\xc2\xb0",               // 2-byte utf (degree symbol)
   1.535 +                        "27\\\xc2\\\xb0",
   1.536 +                        pcrecpp::UTF8());
   1.537 +#endif
   1.538 +}
   1.539 +
   1.540 +static void TestQuoteMetaAll() {
   1.541 +  printf("Testing QuoteMeta\n");
   1.542 +  TestQuotaMetaSimple();
   1.543 +  TestQuoteMetaSimpleNegative();
   1.544 +  TestQuoteMetaLatin1();
   1.545 +  TestQuoteMetaUtf8();
   1.546 +}
   1.547 +
   1.548 +//
   1.549 +// Options tests contributed by
   1.550 +// Giuseppe Maxia, CTO, Stardata s.r.l.
   1.551 +// July 2005
   1.552 +//
   1.553 +static void GetOneOptionResult(
   1.554 +                const char *option_name,
   1.555 +                const char *regex,
   1.556 +                const char *str,
   1.557 +                RE_Options options,
   1.558 +                bool full,
   1.559 +                string expected) {
   1.560 +
   1.561 +  printf("Testing Option <%s>\n", option_name);
   1.562 +  if(VERBOSE_TEST)
   1.563 +    printf("/%s/ finds \"%s\" within \"%s\" \n",
   1.564 +                    regex,
   1.565 +                    expected.c_str(),
   1.566 +                    str);
   1.567 +  string captured("");
   1.568 +  if (full)
   1.569 +    RE(regex,options).FullMatch(str, &captured);
   1.570 +  else
   1.571 +    RE(regex,options).PartialMatch(str, &captured);
   1.572 +  CHECK_EQ(captured, expected);
   1.573 +}
   1.574 +
   1.575 +static void TestOneOption(
   1.576 +                const char *option_name,
   1.577 +                const char *regex,
   1.578 +                const char *str,
   1.579 +                RE_Options options,
   1.580 +                bool full,
   1.581 +                bool assertive = true) {
   1.582 +
   1.583 +  printf("Testing Option <%s>\n", option_name);
   1.584 +  if (VERBOSE_TEST)
   1.585 +    printf("'%s' %s /%s/ \n",
   1.586 +                  str,
   1.587 +                  (assertive? "matches" : "doesn't match"),
   1.588 +                  regex);
   1.589 +  if (assertive) {
   1.590 +    if (full)
   1.591 +      CHECK(RE(regex,options).FullMatch(str));
   1.592 +    else
   1.593 +      CHECK(RE(regex,options).PartialMatch(str));
   1.594 +  } else {
   1.595 +    if (full)
   1.596 +      CHECK(!RE(regex,options).FullMatch(str));
   1.597 +    else
   1.598 +      CHECK(!RE(regex,options).PartialMatch(str));
   1.599 +  }
   1.600 +}
   1.601 +
   1.602 +static void Test_CASELESS() {
   1.603 +  RE_Options options;
   1.604 +  RE_Options options2;
   1.605 +
   1.606 +  options.set_caseless(true);
   1.607 +  TestOneOption("CASELESS (class)",  "HELLO",    "hello", options, false);
   1.608 +  TestOneOption("CASELESS (class2)", "HELLO",    "hello", options2.set_caseless(true), false);
   1.609 +  TestOneOption("CASELESS (class)",  "^[A-Z]+$", "Hello", options, false);
   1.610 +
   1.611 +  TestOneOption("CASELESS (function)", "HELLO",    "hello", pcrecpp::CASELESS(), false);
   1.612 +  TestOneOption("CASELESS (function)", "^[A-Z]+$", "Hello", pcrecpp::CASELESS(), false);
   1.613 +  options.set_caseless(false);
   1.614 +  TestOneOption("no CASELESS", "HELLO",    "hello", options, false, false);
   1.615 +}
   1.616 +
   1.617 +static void Test_MULTILINE() {
   1.618 +  RE_Options options;
   1.619 +  RE_Options options2;
   1.620 +  const char *str = "HELLO\n" "cruel\n" "world\n";
   1.621 +
   1.622 +  options.set_multiline(true);
   1.623 +  TestOneOption("MULTILINE (class)",    "^cruel$", str, options, false);
   1.624 +  TestOneOption("MULTILINE (class2)",   "^cruel$", str, options2.set_multiline(true), false);
   1.625 +  TestOneOption("MULTILINE (function)", "^cruel$", str, pcrecpp::MULTILINE(), false);
   1.626 +  options.set_multiline(false);
   1.627 +  TestOneOption("no MULTILINE", "^cruel$", str, options, false, false);
   1.628 +}
   1.629 +
   1.630 +static void Test_DOTALL() {
   1.631 +  RE_Options options;
   1.632 +  RE_Options options2;
   1.633 +  const char *str = "HELLO\n" "cruel\n" "world";
   1.634 +
   1.635 +  options.set_dotall(true);
   1.636 +  TestOneOption("DOTALL (class)",    "HELLO.*world", str, options, true);
   1.637 +  TestOneOption("DOTALL (class2)",   "HELLO.*world", str, options2.set_dotall(true), true);
   1.638 +  TestOneOption("DOTALL (function)",    "HELLO.*world", str, pcrecpp::DOTALL(), true);
   1.639 +  options.set_dotall(false);
   1.640 +  TestOneOption("no DOTALL", "HELLO.*world", str, options, true, false);
   1.641 +}
   1.642 +
   1.643 +static void Test_DOLLAR_ENDONLY() {
   1.644 +  RE_Options options;
   1.645 +  RE_Options options2;
   1.646 +  const char *str = "HELLO world\n";
   1.647 +
   1.648 +  TestOneOption("no DOLLAR_ENDONLY", "world$", str, options, false);
   1.649 +  options.set_dollar_endonly(true);
   1.650 +  TestOneOption("DOLLAR_ENDONLY 1",    "world$", str, options, false, false);
   1.651 +  TestOneOption("DOLLAR_ENDONLY 2",    "world$", str, options2.set_dollar_endonly(true), false, false);
   1.652 +}
   1.653 +
   1.654 +static void Test_EXTRA() {
   1.655 +  RE_Options options;
   1.656 +  const char *str = "HELLO";
   1.657 +
   1.658 +  options.set_extra(true);
   1.659 +  TestOneOption("EXTRA 1", "\\HELL\\O", str, options, true, false );
   1.660 +  TestOneOption("EXTRA 2", "\\HELL\\O", str, RE_Options().set_extra(true), true, false );
   1.661 +  options.set_extra(false);
   1.662 +  TestOneOption("no EXTRA", "\\HELL\\O", str, options, true );
   1.663 +}
   1.664 +
   1.665 +static void Test_EXTENDED() {
   1.666 +  RE_Options options;
   1.667 +  RE_Options options2;
   1.668 +  const char *str = "HELLO world";
   1.669 +
   1.670 +  options.set_extended(true);
   1.671 +  TestOneOption("EXTENDED (class)",    "HELLO world", str, options, false, false);
   1.672 +  TestOneOption("EXTENDED (class2)",   "HELLO world", str, options2.set_extended(true), false, false);
   1.673 +  TestOneOption("EXTENDED (class)",
   1.674 +                    "^ HE L{2} O "
   1.675 +                    "\\s+        "
   1.676 +                    "\\w+ $      ",
   1.677 +                    str,
   1.678 +                    options,
   1.679 +                    false);
   1.680 +
   1.681 +  TestOneOption("EXTENDED (function)",    "HELLO world", str, pcrecpp::EXTENDED(), false, false);
   1.682 +  TestOneOption("EXTENDED (function)",
   1.683 +                    "^ HE L{2} O "
   1.684 +                    "\\s+        "
   1.685 +                    "\\w+ $      ",
   1.686 +                    str,
   1.687 +                    pcrecpp::EXTENDED(),
   1.688 +                    false);
   1.689 +
   1.690 +  options.set_extended(false);
   1.691 +  TestOneOption("no EXTENDED", "HELLO world", str, options, false);
   1.692 +}
   1.693 +
   1.694 +static void Test_NO_AUTO_CAPTURE() {
   1.695 +  RE_Options options;
   1.696 +  const char *str = "HELLO world";
   1.697 +  string captured;
   1.698 +
   1.699 +  printf("Testing Option <no NO_AUTO_CAPTURE>\n");
   1.700 +  if (VERBOSE_TEST)
   1.701 +    printf("parentheses capture text\n");
   1.702 +  RE re("(world|universe)$", options);
   1.703 +  CHECK(re.Extract("\\1", str , &captured));
   1.704 +  CHECK_EQ(captured, "world");
   1.705 +  options.set_no_auto_capture(true);
   1.706 +  printf("testing Option <NO_AUTO_CAPTURE>\n");
   1.707 +  if (VERBOSE_TEST)
   1.708 +    printf("parentheses do not capture text\n");
   1.709 +  re.Extract("\\1",str, &captured );
   1.710 +  CHECK_EQ(captured, "world");
   1.711 +}
   1.712 +
   1.713 +static void Test_UNGREEDY() {
   1.714 +  RE_Options options;
   1.715 +  const char *str = "HELLO, 'this' is the 'world'";
   1.716 +
   1.717 +  options.set_ungreedy(true);
   1.718 +  GetOneOptionResult("UNGREEDY 1", "('.*')", str, options, false, "'this'" );
   1.719 +  GetOneOptionResult("UNGREEDY 2", "('.*')", str, RE_Options().set_ungreedy(true), false, "'this'" );
   1.720 +  GetOneOptionResult("UNGREEDY", "('.*?')", str, options, false, "'this' is the 'world'" );
   1.721 +
   1.722 +  options.set_ungreedy(false);
   1.723 +  GetOneOptionResult("no UNGREEDY", "('.*')", str, options, false, "'this' is the 'world'" );
   1.724 +  GetOneOptionResult("no UNGREEDY", "('.*?')", str, options, false, "'this'" );
   1.725 +}
   1.726 +
   1.727 +static void Test_all_options() {
   1.728 +  const char *str = "HELLO\n" "cruel\n" "world";
   1.729 +  RE_Options options;
   1.730 +  options.set_all_options(PCRE_CASELESS | PCRE_DOTALL);
   1.731 +
   1.732 +  TestOneOption("all_options (CASELESS|DOTALL)", "^hello.*WORLD", str , options, false);
   1.733 +  options.set_all_options(0);
   1.734 +  TestOneOption("all_options (0)", "^hello.*WORLD", str , options, false, false);
   1.735 +  options.set_all_options(PCRE_MULTILINE | PCRE_EXTENDED);
   1.736 +
   1.737 +  TestOneOption("all_options (MULTILINE|EXTENDED)", " ^ c r u e l $ ", str, options, false);
   1.738 +  TestOneOption("all_options (MULTILINE|EXTENDED) with constructor",
   1.739 +                  " ^ c r u e l $ ",
   1.740 +                  str,
   1.741 +                  RE_Options(PCRE_MULTILINE | PCRE_EXTENDED),
   1.742 +                  false);
   1.743 +
   1.744 +  TestOneOption("all_options (MULTILINE|EXTENDED) with concatenation",
   1.745 +                  " ^ c r u e l $ ",
   1.746 +                  str,
   1.747 +                  RE_Options()
   1.748 +                       .set_multiline(true)
   1.749 +                       .set_extended(true),
   1.750 +                  false);
   1.751 +
   1.752 +  options.set_all_options(0);
   1.753 +  TestOneOption("all_options (0)", "^ c r u e l $", str, options, false, false);
   1.754 +
   1.755 +}
   1.756 +
   1.757 +static void TestOptions() {
   1.758 +  printf("Testing Options\n");
   1.759 +  Test_CASELESS();
   1.760 +  Test_MULTILINE();
   1.761 +  Test_DOTALL();
   1.762 +  Test_DOLLAR_ENDONLY();
   1.763 +  Test_EXTENDED();
   1.764 +  Test_NO_AUTO_CAPTURE();
   1.765 +  Test_UNGREEDY();
   1.766 +  Test_EXTRA();
   1.767 +  Test_all_options();
   1.768 +}
   1.769 +
   1.770 +static void TestConstructors() {
   1.771 +  printf("Testing constructors\n");
   1.772 +
   1.773 +  RE_Options options;
   1.774 +  options.set_dotall(true);
   1.775 +  const char *str = "HELLO\n" "cruel\n" "world";
   1.776 +
   1.777 +  RE orig("HELLO.*world", options);
   1.778 +  CHECK(orig.FullMatch(str));
   1.779 +
   1.780 +  RE copy1(orig);
   1.781 +  CHECK(copy1.FullMatch(str));
   1.782 +
   1.783 +  RE copy2("not a match");
   1.784 +  CHECK(!copy2.FullMatch(str));
   1.785 +  copy2 = copy1;
   1.786 +  CHECK(copy2.FullMatch(str));
   1.787 +  copy2 = orig;
   1.788 +  CHECK(copy2.FullMatch(str));
   1.789 +
   1.790 +  // Make sure when we assign to ourselves, nothing bad happens
   1.791 +  orig = orig;
   1.792 +  copy1 = copy1;
   1.793 +  copy2 = copy2;
   1.794 +  CHECK(orig.FullMatch(str));
   1.795 +  CHECK(copy1.FullMatch(str));
   1.796 +  CHECK(copy2.FullMatch(str));
   1.797 +}
   1.798 +
   1.799 +int main(int argc, char** argv) {
   1.800 +  // Treat any flag as --help
   1.801 +  if (argc > 1 && argv[1][0] == '-') {
   1.802 +    printf("Usage: %s [timing1|timing2|timing3 num-iters]\n"
   1.803 +           "       If 'timingX ###' is specified, run the given timing test\n"
   1.804 +           "       with the given number of iterations, rather than running\n"
   1.805 +           "       the default corectness test.\n", argv[0]);
   1.806 +    return 0;
   1.807 +  }
   1.808 +
   1.809 +  if (argc > 1) {
   1.810 +    if ( argc == 2 || atoi(argv[2]) == 0) {
   1.811 +      printf("timing mode needs a num-iters argument\n");
   1.812 +      return 1;
   1.813 +    }
   1.814 +    if (!strcmp(argv[1], "timing1"))
   1.815 +      Timing1(atoi(argv[2]));
   1.816 +    else if (!strcmp(argv[1], "timing2"))
   1.817 +      Timing2(atoi(argv[2]));
   1.818 +    else if (!strcmp(argv[1], "timing3"))
   1.819 +      Timing3(atoi(argv[2]));
   1.820 +    else
   1.821 +      printf("Unknown argument '%s'\n", argv[1]);
   1.822 +    return 0;
   1.823 +  }
   1.824 +
   1.825 +  printf("Testing FullMatch\n");
   1.826 +
   1.827 +  int i;
   1.828 +  string s;
   1.829 +
   1.830 +  /***** FullMatch with no args *****/
   1.831 +
   1.832 +  CHECK(RE("h.*o").FullMatch("hello"));
   1.833 +  CHECK(!RE("h.*o").FullMatch("othello"));     // Must be anchored at front
   1.834 +  CHECK(!RE("h.*o").FullMatch("hello!"));      // Must be anchored at end
   1.835 +  CHECK(RE("a*").FullMatch("aaaa"));           // Fullmatch with normal op
   1.836 +  CHECK(RE("a*?").FullMatch("aaaa"));          // Fullmatch with nongreedy op
   1.837 +  CHECK(RE("a*?\\z").FullMatch("aaaa"));       // Two unusual ops
   1.838 +
   1.839 +  /***** FullMatch with args *****/
   1.840 +
   1.841 +  // Zero-arg
   1.842 +  CHECK(RE("\\d+").FullMatch("1001"));
   1.843 +
   1.844 +  // Single-arg
   1.845 +  CHECK(RE("(\\d+)").FullMatch("1001",   &i));
   1.846 +  CHECK_EQ(i, 1001);
   1.847 +  CHECK(RE("(-?\\d+)").FullMatch("-123", &i));
   1.848 +  CHECK_EQ(i, -123);
   1.849 +  CHECK(!RE("()\\d+").FullMatch("10", &i));
   1.850 +  CHECK(!RE("(\\d+)").FullMatch("1234567890123456789012345678901234567890",
   1.851 +                                &i));
   1.852 +
   1.853 +  // Digits surrounding integer-arg
   1.854 +  CHECK(RE("1(\\d*)4").FullMatch("1234", &i));
   1.855 +  CHECK_EQ(i, 23);
   1.856 +  CHECK(RE("(\\d)\\d+").FullMatch("1234", &i));
   1.857 +  CHECK_EQ(i, 1);
   1.858 +  CHECK(RE("(-\\d)\\d+").FullMatch("-1234", &i));
   1.859 +  CHECK_EQ(i, -1);
   1.860 +  CHECK(RE("(\\d)").PartialMatch("1234", &i));
   1.861 +  CHECK_EQ(i, 1);
   1.862 +  CHECK(RE("(-\\d)").PartialMatch("-1234", &i));
   1.863 +  CHECK_EQ(i, -1);
   1.864 +
   1.865 +  // String-arg
   1.866 +  CHECK(RE("h(.*)o").FullMatch("hello", &s));
   1.867 +  CHECK_EQ(s, string("ell"));
   1.868 +
   1.869 +  // StringPiece-arg
   1.870 +  StringPiece sp;
   1.871 +  CHECK(RE("(\\w+):(\\d+)").FullMatch("ruby:1234", &sp, &i));
   1.872 +  CHECK_EQ(sp.size(), 4);
   1.873 +  CHECK(memcmp(sp.data(), "ruby", 4) == 0);
   1.874 +  CHECK_EQ(i, 1234);
   1.875 +
   1.876 +  // Multi-arg
   1.877 +  CHECK(RE("(\\w+):(\\d+)").FullMatch("ruby:1234", &s, &i));
   1.878 +  CHECK_EQ(s, string("ruby"));
   1.879 +  CHECK_EQ(i, 1234);
   1.880 +
   1.881 +  // Ignore non-void* NULL arg
   1.882 +  CHECK(RE("he(.*)lo").FullMatch("hello", (char*)NULL));
   1.883 +  CHECK(RE("h(.*)o").FullMatch("hello", (string*)NULL));
   1.884 +  CHECK(RE("h(.*)o").FullMatch("hello", (StringPiece*)NULL));
   1.885 +  CHECK(RE("(.*)").FullMatch("1234", (int*)NULL));
   1.886 +#ifdef HAVE_LONG_LONG
   1.887 +  CHECK(RE("(.*)").FullMatch("1234567890123456", (long long*)NULL));
   1.888 +#endif
   1.889 +  CHECK(RE("(.*)").FullMatch("123.4567890123456", (double*)NULL));
   1.890 +  CHECK(RE("(.*)").FullMatch("123.4567890123456", (float*)NULL));
   1.891 +
   1.892 +  // Fail on non-void* NULL arg if the match doesn't parse for the given type.
   1.893 +  CHECK(!RE("h(.*)lo").FullMatch("hello", &s, (char*)NULL));
   1.894 +  CHECK(!RE("(.*)").FullMatch("hello", (int*)NULL));
   1.895 +  CHECK(!RE("(.*)").FullMatch("1234567890123456", (int*)NULL));
   1.896 +  CHECK(!RE("(.*)").FullMatch("hello", (double*)NULL));
   1.897 +  CHECK(!RE("(.*)").FullMatch("hello", (float*)NULL));
   1.898 +
   1.899 +  // Ignored arg
   1.900 +  CHECK(RE("(\\w+)(:)(\\d+)").FullMatch("ruby:1234", &s, (void*)NULL, &i));
   1.901 +  CHECK_EQ(s, string("ruby"));
   1.902 +  CHECK_EQ(i, 1234);
   1.903 +
   1.904 +  // Type tests
   1.905 +  {
   1.906 +    char c;
   1.907 +    CHECK(RE("(H)ello").FullMatch("Hello", &c));
   1.908 +    CHECK_EQ(c, 'H');
   1.909 +  }
   1.910 +  {
   1.911 +    unsigned char c;
   1.912 +    CHECK(RE("(H)ello").FullMatch("Hello", &c));
   1.913 +    CHECK_EQ(c, static_cast<unsigned char>('H'));
   1.914 +  }
   1.915 +  {
   1.916 +    short v;
   1.917 +    CHECK(RE("(-?\\d+)").FullMatch("100",     &v));    CHECK_EQ(v, 100);
   1.918 +    CHECK(RE("(-?\\d+)").FullMatch("-100",    &v));    CHECK_EQ(v, -100);
   1.919 +    CHECK(RE("(-?\\d+)").FullMatch("32767",   &v));    CHECK_EQ(v, 32767);
   1.920 +    CHECK(RE("(-?\\d+)").FullMatch("-32768",  &v));    CHECK_EQ(v, -32768);
   1.921 +    CHECK(!RE("(-?\\d+)").FullMatch("-32769", &v));
   1.922 +    CHECK(!RE("(-?\\d+)").FullMatch("32768",  &v));
   1.923 +  }
   1.924 +  {
   1.925 +    unsigned short v;
   1.926 +    CHECK(RE("(\\d+)").FullMatch("100",     &v));    CHECK_EQ(v, 100);
   1.927 +    CHECK(RE("(\\d+)").FullMatch("32767",   &v));    CHECK_EQ(v, 32767);
   1.928 +    CHECK(RE("(\\d+)").FullMatch("65535",   &v));    CHECK_EQ(v, 65535);
   1.929 +    CHECK(!RE("(\\d+)").FullMatch("65536",  &v));
   1.930 +  }
   1.931 +  {
   1.932 +    int v;
   1.933 +    static const int max_value = 0x7fffffff;
   1.934 +    static const int min_value = -max_value - 1;
   1.935 +    CHECK(RE("(-?\\d+)").FullMatch("100",         &v)); CHECK_EQ(v, 100);
   1.936 +    CHECK(RE("(-?\\d+)").FullMatch("-100",        &v)); CHECK_EQ(v, -100);
   1.937 +    CHECK(RE("(-?\\d+)").FullMatch("2147483647",  &v)); CHECK_EQ(v, max_value);
   1.938 +    CHECK(RE("(-?\\d+)").FullMatch("-2147483648", &v)); CHECK_EQ(v, min_value);
   1.939 +    CHECK(!RE("(-?\\d+)").FullMatch("-2147483649", &v));
   1.940 +    CHECK(!RE("(-?\\d+)").FullMatch("2147483648",  &v));
   1.941 +  }
   1.942 +  {
   1.943 +    unsigned int v;
   1.944 +    static const unsigned int max_value = 0xfffffffful;
   1.945 +    CHECK(RE("(\\d+)").FullMatch("100",         &v)); CHECK_EQ(v, 100);
   1.946 +    CHECK(RE("(\\d+)").FullMatch("4294967295",  &v)); CHECK_EQ(v, max_value);
   1.947 +    CHECK(!RE("(\\d+)").FullMatch("4294967296", &v));
   1.948 +  }
   1.949 +#ifdef HAVE_LONG_LONG
   1.950 +# if defined(__MINGW__) || defined(__MINGW32__)
   1.951 +#   define LLD "%I64d"
   1.952 +#   define LLU "%I64u"
   1.953 +# else
   1.954 +#   define LLD "%lld"
   1.955 +#   define LLU "%llu"
   1.956 +# endif
   1.957 +  {
   1.958 +    long long v;
   1.959 +    static const long long max_value = 0x7fffffffffffffffLL;
   1.960 +    static const long long min_value = -max_value - 1;
   1.961 +    char buf[32];  // definitely big enough for a long long
   1.962 +
   1.963 +    CHECK(RE("(-?\\d+)").FullMatch("100", &v)); CHECK_EQ(v, 100);
   1.964 +    CHECK(RE("(-?\\d+)").FullMatch("-100",&v)); CHECK_EQ(v, -100);
   1.965 +
   1.966 +    sprintf(buf, LLD, max_value);
   1.967 +    CHECK(RE("(-?\\d+)").FullMatch(buf,&v)); CHECK_EQ(v, max_value);
   1.968 +
   1.969 +    sprintf(buf, LLD, min_value);
   1.970 +    CHECK(RE("(-?\\d+)").FullMatch(buf,&v)); CHECK_EQ(v, min_value);
   1.971 +
   1.972 +    sprintf(buf, LLD, max_value);
   1.973 +    assert(buf[strlen(buf)-1] != '9');
   1.974 +    buf[strlen(buf)-1]++;
   1.975 +    CHECK(!RE("(-?\\d+)").FullMatch(buf, &v));
   1.976 +
   1.977 +    sprintf(buf, LLD, min_value);
   1.978 +    assert(buf[strlen(buf)-1] != '9');
   1.979 +    buf[strlen(buf)-1]++;
   1.980 +    CHECK(!RE("(-?\\d+)").FullMatch(buf, &v));
   1.981 +  }
   1.982 +#endif
   1.983 +#if defined HAVE_UNSIGNED_LONG_LONG && defined HAVE_LONG_LONG
   1.984 +  {
   1.985 +    unsigned long long v;
   1.986 +    long long v2;
   1.987 +    static const unsigned long long max_value = 0xffffffffffffffffULL;
   1.988 +    char buf[32];  // definitely big enough for a unsigned long long
   1.989 +
   1.990 +    CHECK(RE("(-?\\d+)").FullMatch("100",&v)); CHECK_EQ(v, 100);
   1.991 +    CHECK(RE("(-?\\d+)").FullMatch("-100",&v2)); CHECK_EQ(v2, -100);
   1.992 +
   1.993 +    sprintf(buf, LLU, max_value);
   1.994 +    CHECK(RE("(-?\\d+)").FullMatch(buf,&v)); CHECK_EQ(v, max_value);
   1.995 +
   1.996 +    assert(buf[strlen(buf)-1] != '9');
   1.997 +    buf[strlen(buf)-1]++;
   1.998 +    CHECK(!RE("(-?\\d+)").FullMatch(buf, &v));
   1.999 +  }
  1.1000 +#endif
  1.1001 +  {
  1.1002 +    float v;
  1.1003 +    CHECK(RE("(.*)").FullMatch("100", &v));
  1.1004 +    CHECK(RE("(.*)").FullMatch("-100.", &v));
  1.1005 +    CHECK(RE("(.*)").FullMatch("1e23", &v));
  1.1006 +  }
  1.1007 +  {
  1.1008 +    double v;
  1.1009 +    CHECK(RE("(.*)").FullMatch("100", &v));
  1.1010 +    CHECK(RE("(.*)").FullMatch("-100.", &v));
  1.1011 +    CHECK(RE("(.*)").FullMatch("1e23", &v));
  1.1012 +  }
  1.1013 +
  1.1014 +  // Check that matching is fully anchored
  1.1015 +  CHECK(!RE("(\\d+)").FullMatch("x1001",  &i));
  1.1016 +  CHECK(!RE("(\\d+)").FullMatch("1001x",  &i));
  1.1017 +  CHECK(RE("x(\\d+)").FullMatch("x1001", &i)); CHECK_EQ(i, 1001);
  1.1018 +  CHECK(RE("(\\d+)x").FullMatch("1001x", &i)); CHECK_EQ(i, 1001);
  1.1019 +
  1.1020 +  // Braces
  1.1021 +  CHECK(RE("[0-9a-f+.-]{5,}").FullMatch("0abcd"));
  1.1022 +  CHECK(RE("[0-9a-f+.-]{5,}").FullMatch("0abcde"));
  1.1023 +  CHECK(!RE("[0-9a-f+.-]{5,}").FullMatch("0abc"));
  1.1024 +
  1.1025 +  // Complicated RE
  1.1026 +  CHECK(RE("foo|bar|[A-Z]").FullMatch("foo"));
  1.1027 +  CHECK(RE("foo|bar|[A-Z]").FullMatch("bar"));
  1.1028 +  CHECK(RE("foo|bar|[A-Z]").FullMatch("X"));
  1.1029 +  CHECK(!RE("foo|bar|[A-Z]").FullMatch("XY"));
  1.1030 +
  1.1031 +  // Check full-match handling (needs '$' tacked on internally)
  1.1032 +  CHECK(RE("fo|foo").FullMatch("fo"));
  1.1033 +  CHECK(RE("fo|foo").FullMatch("foo"));
  1.1034 +  CHECK(RE("fo|foo$").FullMatch("fo"));
  1.1035 +  CHECK(RE("fo|foo$").FullMatch("foo"));
  1.1036 +  CHECK(RE("foo$").FullMatch("foo"));
  1.1037 +  CHECK(!RE("foo\\$").FullMatch("foo$bar"));
  1.1038 +  CHECK(!RE("fo|bar").FullMatch("fox"));
  1.1039 +
  1.1040 +  // Uncomment the following if we change the handling of '$' to
  1.1041 +  // prevent it from matching a trailing newline
  1.1042 +  if (false) {
  1.1043 +    // Check that we don't get bitten by pcre's special handling of a
  1.1044 +    // '\n' at the end of the string matching '$'
  1.1045 +    CHECK(!RE("foo$").PartialMatch("foo\n"));
  1.1046 +  }
  1.1047 +
  1.1048 +  // Number of args
  1.1049 +  int a[16];
  1.1050 +  CHECK(RE("").FullMatch(""));
  1.1051 +
  1.1052 +  memset(a, 0, sizeof(0));
  1.1053 +  CHECK(RE("(\\d){1}").FullMatch("1",
  1.1054 +                                 &a[0]));
  1.1055 +  CHECK_EQ(a[0], 1);
  1.1056 +
  1.1057 +  memset(a, 0, sizeof(0));
  1.1058 +  CHECK(RE("(\\d)(\\d)").FullMatch("12",
  1.1059 +                                   &a[0],  &a[1]));
  1.1060 +  CHECK_EQ(a[0], 1);
  1.1061 +  CHECK_EQ(a[1], 2);
  1.1062 +
  1.1063 +  memset(a, 0, sizeof(0));
  1.1064 +  CHECK(RE("(\\d)(\\d)(\\d)").FullMatch("123",
  1.1065 +                                        &a[0],  &a[1],  &a[2]));
  1.1066 +  CHECK_EQ(a[0], 1);
  1.1067 +  CHECK_EQ(a[1], 2);
  1.1068 +  CHECK_EQ(a[2], 3);
  1.1069 +
  1.1070 +  memset(a, 0, sizeof(0));
  1.1071 +  CHECK(RE("(\\d)(\\d)(\\d)(\\d)").FullMatch("1234",
  1.1072 +                                             &a[0],  &a[1],  &a[2],  &a[3]));
  1.1073 +  CHECK_EQ(a[0], 1);
  1.1074 +  CHECK_EQ(a[1], 2);
  1.1075 +  CHECK_EQ(a[2], 3);
  1.1076 +  CHECK_EQ(a[3], 4);
  1.1077 +
  1.1078 +  memset(a, 0, sizeof(0));
  1.1079 +  CHECK(RE("(\\d)(\\d)(\\d)(\\d)(\\d)").FullMatch("12345",
  1.1080 +                                                  &a[0],  &a[1],  &a[2],
  1.1081 +                                                  &a[3],  &a[4]));
  1.1082 +  CHECK_EQ(a[0], 1);
  1.1083 +  CHECK_EQ(a[1], 2);
  1.1084 +  CHECK_EQ(a[2], 3);
  1.1085 +  CHECK_EQ(a[3], 4);
  1.1086 +  CHECK_EQ(a[4], 5);
  1.1087 +
  1.1088 +  memset(a, 0, sizeof(0));
  1.1089 +  CHECK(RE("(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)").FullMatch("123456",
  1.1090 +                                                       &a[0],  &a[1],  &a[2],
  1.1091 +                                                       &a[3],  &a[4],  &a[5]));
  1.1092 +  CHECK_EQ(a[0], 1);
  1.1093 +  CHECK_EQ(a[1], 2);
  1.1094 +  CHECK_EQ(a[2], 3);
  1.1095 +  CHECK_EQ(a[3], 4);
  1.1096 +  CHECK_EQ(a[4], 5);
  1.1097 +  CHECK_EQ(a[5], 6);
  1.1098 +
  1.1099 +  memset(a, 0, sizeof(0));
  1.1100 +  CHECK(RE("(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)").FullMatch("1234567",
  1.1101 +                                                            &a[0],  &a[1],  &a[2],  &a[3],
  1.1102 +                                                            &a[4],  &a[5],  &a[6]));
  1.1103 +  CHECK_EQ(a[0], 1);
  1.1104 +  CHECK_EQ(a[1], 2);
  1.1105 +  CHECK_EQ(a[2], 3);
  1.1106 +  CHECK_EQ(a[3], 4);
  1.1107 +  CHECK_EQ(a[4], 5);
  1.1108 +  CHECK_EQ(a[5], 6);
  1.1109 +  CHECK_EQ(a[6], 7);
  1.1110 +
  1.1111 +  memset(a, 0, sizeof(0));
  1.1112 +  CHECK(RE("(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)"
  1.1113 +           "(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)").FullMatch(
  1.1114 +               "1234567890123456",
  1.1115 +               &a[0],  &a[1],  &a[2],  &a[3],
  1.1116 +               &a[4],  &a[5],  &a[6],  &a[7],
  1.1117 +               &a[8],  &a[9],  &a[10], &a[11],
  1.1118 +               &a[12], &a[13], &a[14], &a[15]));
  1.1119 +  CHECK_EQ(a[0], 1);
  1.1120 +  CHECK_EQ(a[1], 2);
  1.1121 +  CHECK_EQ(a[2], 3);
  1.1122 +  CHECK_EQ(a[3], 4);
  1.1123 +  CHECK_EQ(a[4], 5);
  1.1124 +  CHECK_EQ(a[5], 6);
  1.1125 +  CHECK_EQ(a[6], 7);
  1.1126 +  CHECK_EQ(a[7], 8);
  1.1127 +  CHECK_EQ(a[8], 9);
  1.1128 +  CHECK_EQ(a[9], 0);
  1.1129 +  CHECK_EQ(a[10], 1);
  1.1130 +  CHECK_EQ(a[11], 2);
  1.1131 +  CHECK_EQ(a[12], 3);
  1.1132 +  CHECK_EQ(a[13], 4);
  1.1133 +  CHECK_EQ(a[14], 5);
  1.1134 +  CHECK_EQ(a[15], 6);
  1.1135 +
  1.1136 +  /***** PartialMatch *****/
  1.1137 +
  1.1138 +  printf("Testing PartialMatch\n");
  1.1139 +
  1.1140 +  CHECK(RE("h.*o").PartialMatch("hello"));
  1.1141 +  CHECK(RE("h.*o").PartialMatch("othello"));
  1.1142 +  CHECK(RE("h.*o").PartialMatch("hello!"));
  1.1143 +  CHECK(RE("((((((((((((((((((((x))))))))))))))))))))").PartialMatch("x"));
  1.1144 +
  1.1145 +  /***** other tests *****/
  1.1146 +
  1.1147 +  RadixTests();
  1.1148 +  TestReplace();
  1.1149 +  TestExtract();
  1.1150 +  TestConsume();
  1.1151 +  TestFindAndConsume();
  1.1152 +  TestQuoteMetaAll();
  1.1153 +  TestMatchNumberPeculiarity();
  1.1154 +
  1.1155 +  // Check the pattern() accessor
  1.1156 +  {
  1.1157 +    const string kPattern = "http://([^/]+)/.*";
  1.1158 +    const RE re(kPattern);
  1.1159 +    CHECK_EQ(kPattern, re.pattern());
  1.1160 +  }
  1.1161 +
  1.1162 +  // Check RE error field.
  1.1163 +  {
  1.1164 +    RE re("foo");
  1.1165 +    CHECK(re.error().empty());  // Must have no error
  1.1166 +  }
  1.1167 +
  1.1168 +#ifdef SUPPORT_UTF8
  1.1169 +  // Check UTF-8 handling
  1.1170 +  {
  1.1171 +    printf("Testing UTF-8 handling\n");
  1.1172 +
  1.1173 +    // Three Japanese characters (nihongo)
  1.1174 +    const unsigned char utf8_string[] = {
  1.1175 +         0xe6, 0x97, 0xa5, // 65e5
  1.1176 +         0xe6, 0x9c, 0xac, // 627c
  1.1177 +         0xe8, 0xaa, 0x9e, // 8a9e
  1.1178 +         0
  1.1179 +    };
  1.1180 +    const unsigned char utf8_pattern[] = {
  1.1181 +         '.',
  1.1182 +         0xe6, 0x9c, 0xac, // 627c
  1.1183 +         '.',
  1.1184 +         0
  1.1185 +    };
  1.1186 +
  1.1187 +    // Both should match in either mode, bytes or UTF-8
  1.1188 +    RE re_test1(".........");
  1.1189 +    CHECK(re_test1.FullMatch(utf8_string));
  1.1190 +    RE re_test2("...", pcrecpp::UTF8());
  1.1191 +    CHECK(re_test2.FullMatch(utf8_string));
  1.1192 +
  1.1193 +    // Check that '.' matches one byte or UTF-8 character
  1.1194 +    // according to the mode.
  1.1195 +    string ss;
  1.1196 +    RE re_test3("(.)");
  1.1197 +    CHECK(re_test3.PartialMatch(utf8_string, &ss));
  1.1198 +    CHECK_EQ(ss, string("\xe6"));
  1.1199 +    RE re_test4("(.)", pcrecpp::UTF8());
  1.1200 +    CHECK(re_test4.PartialMatch(utf8_string, &ss));
  1.1201 +    CHECK_EQ(ss, string("\xe6\x97\xa5"));
  1.1202 +
  1.1203 +    // Check that string matches itself in either mode
  1.1204 +    RE re_test5(utf8_string);
  1.1205 +    CHECK(re_test5.FullMatch(utf8_string));
  1.1206 +    RE re_test6(utf8_string, pcrecpp::UTF8());
  1.1207 +    CHECK(re_test6.FullMatch(utf8_string));
  1.1208 +
  1.1209 +    // Check that pattern matches string only in UTF8 mode
  1.1210 +    RE re_test7(utf8_pattern);
  1.1211 +    CHECK(!re_test7.FullMatch(utf8_string));
  1.1212 +    RE re_test8(utf8_pattern, pcrecpp::UTF8());
  1.1213 +    CHECK(re_test8.FullMatch(utf8_string));
  1.1214 +  }
  1.1215 +
  1.1216 +  // Check that ungreedy, UTF8 regular expressions don't match when they
  1.1217 +  // oughtn't -- see bug 82246.
  1.1218 +  {
  1.1219 +    // This code always worked.
  1.1220 +    const char* pattern = "\\w+X";
  1.1221 +    const string target = "a aX";
  1.1222 +    RE match_sentence(pattern);
  1.1223 +    RE match_sentence_re(pattern, pcrecpp::UTF8());
  1.1224 +
  1.1225 +    CHECK(!match_sentence.FullMatch(target));
  1.1226 +    CHECK(!match_sentence_re.FullMatch(target));
  1.1227 +  }
  1.1228 +
  1.1229 +  {
  1.1230 +    const char* pattern = "(?U)\\w+X";
  1.1231 +    const string target = "a aX";
  1.1232 +    RE match_sentence(pattern);
  1.1233 +    RE match_sentence_re(pattern, pcrecpp::UTF8());
  1.1234 +
  1.1235 +    CHECK(!match_sentence.FullMatch(target));
  1.1236 +    CHECK(!match_sentence_re.FullMatch(target));
  1.1237 +  }
  1.1238 +#endif  /* def SUPPORT_UTF8 */
  1.1239 +
  1.1240 +  printf("Testing error reporting\n");
  1.1241 +
  1.1242 +  { RE re("a\\1"); CHECK(!re.error().empty()); }
  1.1243 +  {
  1.1244 +    RE re("a[x");
  1.1245 +    CHECK(!re.error().empty());
  1.1246 +  }
  1.1247 +  {
  1.1248 +    RE re("a[z-a]");
  1.1249 +    CHECK(!re.error().empty());
  1.1250 +  }
  1.1251 +  {
  1.1252 +    RE re("a[[:foobar:]]");
  1.1253 +    CHECK(!re.error().empty());
  1.1254 +  }
  1.1255 +  {
  1.1256 +    RE re("a(b");
  1.1257 +    CHECK(!re.error().empty());
  1.1258 +  }
  1.1259 +  {
  1.1260 +    RE re("a\\");
  1.1261 +    CHECK(!re.error().empty());
  1.1262 +  }
  1.1263 +
  1.1264 +  // Test that recursion is stopped
  1.1265 +  TestRecursion();
  1.1266 +
  1.1267 +  // Test Options
  1.1268 +  if (getenv("VERBOSE_TEST") != NULL)
  1.1269 +    VERBOSE_TEST  = true;
  1.1270 +  TestOptions();
  1.1271 +
  1.1272 +  // Test the constructors
  1.1273 +  TestConstructors();
  1.1274 +
  1.1275 +  // Done
  1.1276 +  printf("OK\n");
  1.1277 +
  1.1278 +  return 0;
  1.1279 +}