blob: c310bcf98fcce0679f69e02e8a5a6d4a5b08ed3d [file] [log] [blame]
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
/// @assertion Returns whether the regular expression has a match in the string
/// [str].
/// @description Tests this method with various patterns, flags and input strings.
/// @author rodionov
/// @Issue 1297
import "../../../Utils/expect.dart";
main() {
// Disjunction
check("a|ab", "abc");
check(r"\d{3}|[a-z]{4}", "2, 12 and of course repeat 12");
checkNeg(r"\d{3}|[a-z]{4}", "2, 12 and 23 AND 0.00.1");
check("ab|cd|ef", "AEKFCD", ignoreCase: true);
checkNeg("ab|cd|ef", "AEKFCD");
check("11111|111", "1111111111111111");
check("xyz|...", "abc");
check("(ab|cd)+|ef", "AEKFCD", ignoreCase: true);
check("(ab|cd)+|ef", "AEKFCDab", ignoreCase: true);
check("(ab|cd)+|ef", "AEKeFCDab", ignoreCase: true);
check("(.)..|abc", "abc");
check(".+: gr(a|e)y", "color: grey");
check("(Rob)|(Bob)|(Robert)|(Bobby)", "Hi Bob");
check("()|", "");
check("|()", "");
check("((a)|(ab))((c)|(bc))", "abc");
// Term
check("a[a-z]{2,4}", "abcdefghi");
check("a[a-z]{2,4}?", "abcdefghi");
check("(aa|aabaac|ba|b|c)*", "aabaac");
check(r"^(a+)\1*,\1+$", "aaaaaaaaa,aaaaaa");
check(r"^(a+)\1*,\1+$", "aaaaaa,aaaaaaaaa");
check(r"^(a+?)\1*,\1+$", "aaaaaaaaa,aaaaaa");
check(r"^(a+?)\1*,\1+$", "aaaaaa,aaaaaaaaa");
check("(z)((a+)?(b+)?(c))*", "zaacbbbcac");
check("(z)((a+)?(b+)?(c))*", "zaacbbbc");
check(r"(a*)b\1+", "baaaac");
check("(a*)*", "b");
// Assertion
checkNeg("^m", "pairs\nmakes\tdouble");
check("^m", "pairs\nmakes\tdouble", multiLine: true);
check(r"^\d+", "abc\n123xyz", multiLine: true);
check("^p[a-z]", "pairs\nmakes\tdouble\npesos");
checkNeg("^p[b-z]", "pairs\nmakes\tdouble\npesos");
check("^p[b-z]", "pairs\nmakes\tdouble\npesos", multiLine: true);
check("^[^p]", "pairs\nmakes\tdouble\npesos", multiLine: true);
check("^ab", "abcde");
checkNeg("^..^e", "ab\ncde");
checkNeg("^xxx", "yyyyy");
check(r"^\^+", "^^^x");
checkNeg(r"s$", "pairs\nmakes\tdouble");
check(r"e$", "pairs\nmakes\tdouble");
check(r"s$", "pairs\nmakes\tdouble", multiLine: true);
check(r"[^e]$", "pairs\nmakes\tdouble", multiLine: true);
check(r"es$", "pairs\nmakes\tdoubl\u0065s", multiLine: true);
check(r"\bp", "pilot\nsoviet robot\topenoffice");
check(r"ot\b", "pilot\nsoviet robot\topenoffice");
checkNeg(r"\bot", "pilot\nsoviet robot\topenoffice");
check(r"\bso", "pilot\nsoviet robot\topenoffice");
checkNeg(r"so\b", "pilot\nsoviet robot\topenoffice");
check(r"[^o]t\b", "pilOt\nsoviet robot\topenoffice");
check(r"[^o]t\b", "pilOt\nsoviet robot\topenoffice", ignoreCase:true);
check(r"\bro", "pilot\nsoviet robot\topenoffice");
checkNeg(r"r\b", "pilot\nsoviet robot\topenoffice");
check(r"\brobot\b", "pilot\nsoviet robot\topenoffice");
check(r"\b\w{5}\b", "pilot\nsoviet robot\topenoffice");
check(r"\bop", "pilot\nsoviet robot\topenoffice");
checkNeg(r"op\b", "pilot\nsoviet robot\topenoffice");
check(r"e\b", "pilot\nsoviet robot\topenoffic\u0065");
checkNeg(r"\be", "pilot\nsoviet robot\topenoffic\u0065");
check(r"\Bevil\B", "devils arise\tfor\nevil");
check(r"[f-z]e\B", "devils arise\tfor\nrevil");
check(r"\Bo\B", "devils arise\tfOr\nrevil", ignoreCase:true);
check(r"\B\w\B", "devils arise\tfor\nrevil");
check(r"\w\B", "devils arise\tfor\nrevil");
check(r"\B\w", "devils arise\tfor\nrevil");
checkNeg(r"\B[a-yA-Y]{4}\B", "devil arise\tforzzx\nevils");
check(r"\B\w{4}\B", "devil arise\tforzzx\nevils");
check(r"^^^^^^^\b\b\b\bro\B\B\B\Bbot\b\b\b\b\b$$$$", "robot");
// Quantifier
check("[^\"]*", "\"beast\"-nickname");
check("[^\"]*", "alice said: \"don\'t\"");
check("[^\"]*", "before\'i\'start");
check("[^\"]*", "alice \"sweep\": \"don\'t\"");
check("[^\"]*", "alice \u0022sweep\u0022: \"don\'t\"");
check("[\"\'][^\"\']*[\"\']", "alice \u0022sweep\u0022: \"don\'t\"");
check("[\"\'][^\"\']*[\"\']", "alice cries out: \'don\'t\'");
checkNeg("[\"\'][^\"\']*[\"\']", "alice cries out: don\'t");
check("[\"\'][^\"\']*[\"\']", "alice cries out: \"\"");
check("d*", "abcddddefg");
check("cd*", "abcddddefg");
check("cx*d", "abcddddefg");
check("(x*)(x+)", "xxxxxxx");
check(r"(\d*)(\d+)", "0123456789");
check(r"(\d*)\d(\d+)", "0123456789");
check("(x+)(x*)", "xxxxxxx");
check(r"x*y+$", "xxxxxxyyyyyy");
check(r"[\d]*[\s]*bc.", "abcdef");
check(r"bc..[\d]*[\s]*", "abcdef");
check(".*", "a1b2c3");
checkNeg("[xyz]*1", "a0.b2.c3");
check(r"\s+java\s+", "language java\n");
check(r"\s+java\s+", "\t java object");
checkNeg(r"\s+java\s+", "\t javax package");
checkNeg(r"\s+java\s+", "java\n\nobject");
check(r"[a-z]+\d+", "x 2 ff 55 x2 as1 z12 abc12.0");
check(r"[a-z]+\d+", "__abc123.0");
check(r"[a-z]+(\d+)", "x 2 ff 55 x2 as1 z12 abc12.0");
check(r"[a-z]+(\d+)", "__abc123.0");
check("d+", "abcdddddefg");
checkNeg("o+", "abcdddddefg");
check("d+", "abcdefg");
check("(b+)(b+)(b+)", "abbbbbbbc");
check("(b+)(b*)", "abbbbbbbc");
check("b*b+", "abbbbbbbc");
check("java(script)?", "state: javascript is an extension of ecma script");
check("java(script)?", "state: java and javascript are vastly different");
checkNeg("java(script)?",
"state: both Java and JavaScript used in web development");
check("cd?e", "abcdef");
check("cdx?e", "abcdef");
check("o?pqrst", "pqrstuvw");
check("x?y?z?", "abcdef");
check("x?ay?bz?c", "abcdef");
check("b?b?b?b", "abbbbc");
check("ab?c?d?x?y?z", "123az789");
check(r"\??\??\??\??\??", "?????");
check(".?.?.?.?.?.?.?", "test");
check(r"[a-zA-Z]{3}\d{2}", "xa124dfdg08");
check(r"b{2}c", "aaabbbbcccddeeeefffff");
checkNeg(r"b{8}", "aaabbbbcccddeeeefffff");
check(r"b{2,}c", "aaabbbbcccddeeeefffff");
checkNeg(r"b{8,}c", "aaabbbbcccddeeeefffff");
check(r"\d{1,}", "wqe456646dsff");
check(r"(123){1,}", "123123");
check(r"(123){1,}?", "123123");
check(r"(123){1,}x\1", "123123x123");
check(r"x{1,2}x{1,}", "xxxxxxx");
check(r"\d{2,4}", "the answer is 42");
checkNeg(r"\d{2,4}", "the 7 movie");
check(r"\d{2,4}", "the 20000 Leagues Under the Sea book");
check(r"\d{2,4}", "the Fahrenheit 451 book");
check(r"\d{2,4}", "the 1984 novel");
check(r"\d{2,4}", "0a0\u0031\u0031b");
check(r"\d{2,4}", "0a0\u0031\u003122b");
check(r"b{2,3}c", "aaabbbbcccddeeeefffff");
checkNeg(r"b{42,93}c", "aaabbbbcccddeeeefffff");
check(r"b{0,93}c", "aaabbbbcccddeeeefffff");
check(r"bx{0,93}c", "aaabbbbcccddeeeefffff");
check(r".{0,93}", "weirwerdf");
// Atom
check(r"(?=(a+))", "baaabac");
check(r"(?=(a+))a*b\1", "baaabac");
check(r"[Jj]ava([Ss]cript)?(?=\:)", "just Javascript: the way af jedi");
check(r"[Jj]ava([Ss]cript)?(?=\:)", "taste of java: the cookbook");
checkNeg(r"[Jj]ava([Ss]cript)?(?=\:)", "rhino is JavaScript engine");
check(r"Java(?!Script)([A-Z]\w*)", "using of JavaBeans technology");
checkNeg(r"Java(?!Script)([A-Z]\w*)", "using of Java language");
checkNeg(r"Java(?!Script)([A-Z]\w*)", "I\"m a JavaScripter");
check(r"Java(?!Script)([A-Z]\w*)", "JavaScr oops ipt ");
check(r"(\.(?!com|org)|/)", "ah.info");
check(r"(\.(?!com|org)|/)", "ah/info");
checkNeg(r"(\.(?!com|org)|/)", "ah.com");
check(r"(?!a|b)|c", "");
check(r"(?!a|b)|c", "bc");
check(r"(?!a|b)|c", "d");
check(r"(.*?)a(?!(a+)b\2c)\2(.*)", "baaabaac");
check(r"([Jj]ava([Ss]cript)?)\sis\s(fun\w*)",
"Learning javaScript is funny, really");
check(r"([Jj]ava([Ss]cript)?)\sis\s(fun\w*)",
"Developing with Java is fun, try it");
checkNeg(r"([Jj]ava([Ss]cript)?)\sis\s(fun\w*)",
"Developing with JavaScript is dangerous, do not try it without assistance");
check(r"(abc)", "abc");
check(r"a(bc)d(ef)g", "abcdefg");
check(r"(.{3})(.{4})", "abcdefgh");
check(r"(aa)bcd\1", "aabcdaabcd");
check(r"(aa).+\1", "aabcdaabcd");
check(r"(.{2}).+\1", "aabcdaabcd");
check(r"(\d{3})(\d{3})\1\2", "123456123456");
check(r"a(..(..)..)", "abcdefgh");
check(r"(a(b(c)))(d(e(f)))", "xabcdefg");
check(r"(a(b(c)))(d(e(f)))\2\5", "xabcdefbcefg");
check(r"a(.?)b\1c\1d\1", "abcd");
check(r"([\S]+([ \t]+[\S]+)*)[ \t]*=[ \t]*[\S]+", "Course_Creator = Test");
check(r"^(A)?(A.*)$", "AAA");
check(r"^(A)?(A.*)$", "AA");
check(r"^(A)?(A.*)$", "A");
check(r"(A)?(A.*)", "zxcasd;fl\\ ^AAAaaAAaaaf;lrlrzs");
check(r"(A)?(A.*)", "zxcasd;fl\\ ^AAaaAAaaaf;lrlrzs");
check(r"(A)?(A.*)", "zxcasd;fl\\ ^AaaAAaaaf;lrlrzs");
check(r"(a)?a", "a");
check(r"a|(b)", "a");
check(r"(a)?(a)", "a");
check(r"^([a-z]+)*[a-z]$", "a");
check(r"^([a-z]+)*[a-z]$", "ab");
check(r"^([a-z]+)*[a-z]$", "abc");
check(r"^(([a-z]+)*[a-z]\.)+[a-z]{2,}$", "www.netscape.com");
check(r"^(([a-z]+)*([a-z])\.)+[a-z]{2,}$", "www.netscape.com");
check(r"ab.de", "abcde");
check(r".+", "line 1\nline 2");
check(r".*a.*", "this is a test");
check(r".+", r"this is a *&^%$# test");
check(r".+", "....");
check(r".+", "abcdefghijklmnopqrstuvwxyz");
check(r".+", "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
check(r".+", r"`1234567890-=~!@#$%^&*()_+");
check(r".+", r"""|\[{]};:"',<>.?/""");
check(r"[a-z]+", "ABC def ghi", ignoreCase:true);
check(r"[a-z]+", "ABC def ghi");
checkNeg(r"[A-Z]+", "Гџ", ignoreCase: true);
checkNeg(r"[A-Z]+", "\u0131", ignoreCase: true);
checkNeg(r"[A-Z]+", "\u017F", ignoreCase: true);
// AtomEscape
check(r"\b(\w+) \1\b", "do you listen the the band");
check(r"([xu]\d{2}([A-H]{2})?)\1", "x09x12x01x01u00FFu00FFx04x04x23");
check(r"([xu]\d{2}([A-H]{2})?)\1", "x09x12x01x05u00FFu00FFx04x04x23");
check(r"(a*)b\1+", "baaac");
// CharacterEscape
check(r"\t", "\u0009");
check(r"\t\t", "\u0009\u0009asf");
check(r"\n", "\u000A");
check(r"\n\n", "\u000A\u000Aasf");
check(r"\v", "\u000B");
check(r"\v\v", "\u000B\u000Basf");
check(r"\f", "\u000C");
check(r"\f\f", "\u000C\u000Casf");
check(r"\r", "\u000D");
check(r"\r\r", "\u000D\u000Dasf");
// DecimalEscape
check(r"\0", "\u0000");
check(r"\0\0", "\u0000\u0000asf");
checkNeg(r"\00", "");
checkNeg(r"\011", "");
checkNeg(r"\1", "");
checkNeg(r"\2", "");
checkNeg(r"\3", "");
checkNeg(r"\4", "");
checkNeg(r"\10", "");
checkNeg(r"\100", "");
checkNeg(r"(A)\2", "AA");
check(r"(A)\1", "AA");
check(r"\1(A)", "AA");
check(r"(A)\1(B)\2", "AABB");
check(r"\1(A)(B)\2", "ABB");
check(r"((((((((((A))))))))))\1\2\3\4\5\6\7\8\9\10", "AAAAAAAAAAA");
check(r"((((((((((A))))))))))\10\9\8\7\6\5\4\3\2\1", "AAAAAAAAAAA");
// CharacterClassEscape
check(r"\d\d\d", "150");
checkNeg(r"\d", r"adgo[oFSOPE$%^!@#$");
checkNeg(r"\D", "150");
check(r"\D\D\D\D\D\D\D\D\D\D\D\D\D\D\D", r"adgo[oFSOPE$%^!@#4");
check(r"\s\s\s\s", "\n\r\t ");
checkNeg(r"\s", r"`1234567890-=+_)(*&^%$#@!~asjkfh;afGHJWGEFRG");
checkNeg(r"\S", "\n\r\t ");
check(r"\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S", r"`1234567890-=+_)(*&^%$#@!~asjkfh;afGHJWGEFRG");
// CharacterClass
check("q[ax-zb](?=\\s+)", "qYqy ");
check("q[ax-zb](?=\\s+)", "tqaqy ");
check("q[ax-zb](?=\\s+)", "tqa\t qy ");
check("ab[ercst]de", "abcde");
check("[d-h]+", "abcdefghijkl");
check("[1234567].{2}", "abc6defghijkl");
check("[a-c\\d]+", "\n\nabc324234\n");
check("ab[.]?c", "abc");
check("a[b]c", "abc");
check("[a-z][^1-9][a-z]", "a1b b2c c3d def f4g");
check(r"[\*&$]{3}", r"123*&$abc");
check(r"[\d][\n][^\d]", "line1\nline2");
check(r"[\+--]", ",");
check("[--0]", "/");
check("[---]", "-");
check("[a-cA-C]", "bB");
check(r"[\u0061-\u007A]", "f");
checkNeg("[]", "a[b\n[]\tc]d");
checkNeg("[]a", "\0a\0a");
checkNeg("a[]", "\0a\0a");
checkNeg("ab[erst]de", "abcde");
check("[^]a", "a\naba");
check("a[^]", " a\t\n");
check(r"a[^b-z]\s+", "ab an az aY n");
check("a[^1-9]c", "abc");
checkNeg("a[^b]c", "abc");
check("[^a-z]{4}", r"abc#$%def%&*@ghi");
check("[^]", r"abc#$%def%&*@ghi");
check(r"[^\b]+", "easy\bto\u0008ride");
// check(r"[\d][\0012-\0014]{1,}[^\d]", "line1\n\n\n\n\nline2"); // issue 1297
}
void check(String pattern, String str, {bool multiLine: false,
bool ignoreCase: false}) {
RegExp re = new RegExp(pattern, multiLine: multiLine,
caseSensitive: !ignoreCase);
Expect.isTrue(re.hasMatch(str), "'/$pattern/' !~ '$str'");
}
void checkNeg(String pattern, String str, {bool multiLine: false,
bool ignoreCase: false}) {
RegExp re = new RegExp(pattern, multiLine: multiLine,
caseSensitive: !ignoreCase);
Expect.isFalse(re.hasMatch(str), "'/$pattern/' ~ '$str'");
}