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 +}