1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System.Collections.Generic; 6 using System.Diagnostics; 7 using System.Globalization; 8 using System.Linq; 9 using Xunit; 10 11 namespace System.Text.RegularExpressions.Tests 12 { 13 public class RegexMatchTests : RemoteExecutorTestBase 14 { Match_Basic_TestData()15 public static IEnumerable<object[]> Match_Basic_TestData() 16 { 17 // Testing octal sequence matches: "\\060(\\061)?\\061" 18 // Octal \061 is ASCII 49 ('1') 19 yield return new object[] { @"\060(\061)?\061", "011", RegexOptions.None, 0, 3, true, "011" }; 20 21 // Testing hexadecimal sequence matches: "(\\x30\\x31\\x32)" 22 // Hex \x31 is ASCII 49 ('1') 23 yield return new object[] { @"(\x30\x31\x32)", "012", RegexOptions.None, 0, 3, true, "012" }; 24 25 // Testing control character escapes???: "2", "(\u0032)" 26 yield return new object[] { "(\u0034)", "4", RegexOptions.None, 0, 1, true, "4", }; 27 28 // Using *, +, ?, {}: Actual - "a+\\.?b*\\.?c{2}" 29 yield return new object[] { @"a+\.?b*\.+c{2}", "ab.cc", RegexOptions.None, 0, 5, true, "ab.cc" }; 30 31 // Using [a-z], \s, \w: Actual - "([a-zA-Z]+)\\s(\\w+)" 32 yield return new object[] { @"([a-zA-Z]+)\s(\w+)", "David Bau", RegexOptions.None, 0, 9, true, "David Bau" }; 33 34 // \\S, \\d, \\D, \\W: Actual - "(\\S+):\\W(\\d+)\\s(\\D+)" 35 yield return new object[] { @"(\S+):\W(\d+)\s(\D+)", "Price: 5 dollars", RegexOptions.None, 0, 16, true, "Price: 5 dollars" }; 36 37 // \\S, \\d, \\D, \\W: Actual - "[^0-9]+(\\d+)" 38 yield return new object[] { @"[^0-9]+(\d+)", "Price: 30 dollars", RegexOptions.None, 0, 17, true, "Price: 30" }; 39 40 // Zero-width negative lookahead assertion: Actual - "abc(?!XXX)\\w+" 41 yield return new object[] { @"abc(?!XXX)\w+", "abcXXXdef", RegexOptions.None, 0, 9, false, string.Empty }; 42 43 // Zero-width positive lookbehind assertion: Actual - "(\\w){6}(?<=XXX)def" 44 yield return new object[] { @"(\w){6}(?<=XXX)def", "abcXXXdef", RegexOptions.None, 0, 9, true, "abcXXXdef" }; 45 46 // Zero-width negative lookbehind assertion: Actual - "(\\w){6}(?<!XXX)def" 47 yield return new object[] { @"(\w){6}(?<!XXX)def", "XXXabcdef", RegexOptions.None, 0, 9, true, "XXXabcdef" }; 48 49 // Nonbacktracking subexpression: Actual - "[^0-9]+(?>[0-9]+)3" 50 // The last 3 causes the match to fail, since the non backtracking subexpression does not give up the last digit it matched 51 // for it to be a success. For a correct match, remove the last character, '3' from the pattern 52 yield return new object[] { "[^0-9]+(?>[0-9]+)3", "abc123", RegexOptions.None, 0, 6, false, string.Empty }; 53 54 // Using beginning/end of string chars \A, \Z: Actual - "\\Aaaa\\w+zzz\\Z" 55 yield return new object[] { @"\Aaaa\w+zzz\Z", "aaaasdfajsdlfjzzz", RegexOptions.None, 0, 17, true, "aaaasdfajsdlfjzzz" }; 56 57 // Using beginning/end of string chars \A, \Z: Actual - "\\Aaaa\\w+zzz\\Z" 58 yield return new object[] { @"\Aaaa\w+zzz\Z", "aaaasdfajsdlfjzzza", RegexOptions.None, 0, 18, false, string.Empty }; 59 60 // Using beginning/end of string chars \A, \Z: Actual - "\\Aaaa\\w+zzz\\Z" 61 yield return new object[] { @"\A(line2\n)line3\Z", "line2\nline3\n", RegexOptions.Multiline, 0, 12, true, "line2\nline3" }; 62 63 // Using beginning/end of string chars ^: Actual - "^b" 64 yield return new object[] { "^b", "ab", RegexOptions.None, 0, 2, false, string.Empty }; 65 66 // Actual - "(?<char>\\w)\\<char>" 67 yield return new object[] { @"(?<char>\w)\<char>", "aa", RegexOptions.None, 0, 2, true, "aa" }; 68 69 // Actual - "(?<43>\\w)\\43" 70 yield return new object[] { @"(?<43>\w)\43", "aa", RegexOptions.None, 0, 2, true, "aa" }; 71 72 // Actual - "abc(?(1)111|222)" 73 yield return new object[] { "(abbc)(?(1)111|222)", "abbc222", RegexOptions.None, 0, 7, false, string.Empty }; 74 75 // "x" option. Removes unescaped whitespace from the pattern: Actual - " ([^/]+) ","x" 76 yield return new object[] { " ((.)+) ", "abc", RegexOptions.IgnorePatternWhitespace, 0, 3, true, "abc" }; 77 78 // "x" option. Removes unescaped whitespace from the pattern. : Actual - "\x20([^/]+)\x20","x" 79 yield return new object[] { "\x20([^/]+)\x20\x20\x20\x20\x20\x20\x20", " abc ", RegexOptions.IgnorePatternWhitespace, 0, 10, true, " abc " }; 80 81 // Turning on case insensitive option in mid-pattern : Actual - "aaa(?i:match this)bbb" 82 if ("i".ToUpper() == "I") 83 { 84 yield return new object[] { "aaa(?i:match this)bbb", "aaaMaTcH ThIsbbb", RegexOptions.None, 0, 16, true, "aaaMaTcH ThIsbbb" }; 85 } 86 87 // Turning off case insensitive option in mid-pattern : Actual - "aaa(?-i:match this)bbb", "i" 88 yield return new object[] { "aaa(?-i:match this)bbb", "AaAmatch thisBBb", RegexOptions.IgnoreCase, 0, 16, true, "AaAmatch thisBBb" }; 89 90 // Turning on/off all the options at once : Actual - "aaa(?imnsx-imnsx:match this)bbb", "i" 91 yield return new object[] { "aaa(?-i:match this)bbb", "AaAmatcH thisBBb", RegexOptions.IgnoreCase, 0, 16, false, string.Empty }; 92 93 // Actual - "aaa(?#ignore this completely)bbb" 94 yield return new object[] { "aaa(?#ignore this completely)bbb", "aaabbb", RegexOptions.None, 0, 6, true, "aaabbb" }; 95 96 // Trying empty string: Actual "[a-z0-9]+", "" 97 yield return new object[] { "[a-z0-9]+", "", RegexOptions.None, 0, 0, false, string.Empty }; 98 99 // Numbering pattern slots: "(?<1>\\d{3})(?<2>\\d{3})(?<3>\\d{4})" 100 yield return new object[] { @"(?<1>\d{3})(?<2>\d{3})(?<3>\d{4})", "8885551111", RegexOptions.None, 0, 10, true, "8885551111" }; 101 yield return new object[] { @"(?<1>\d{3})(?<2>\d{3})(?<3>\d{4})", "Invalid string", RegexOptions.None, 0, 14, false, string.Empty }; 102 103 // Not naming pattern slots at all: "^(cat|chat)" 104 yield return new object[] { "^(cat|chat)", "cats are bad", RegexOptions.None, 0, 12, true, "cat" }; 105 106 yield return new object[] { "abc", "abc", RegexOptions.None, 0, 3, true, "abc" }; 107 yield return new object[] { "abc", "aBc", RegexOptions.None, 0, 3, false, string.Empty }; 108 yield return new object[] { "abc", "aBc", RegexOptions.IgnoreCase, 0, 3, true, "aBc" }; 109 110 // Using *, +, ?, {}: Actual - "a+\\.?b*\\.?c{2}" 111 yield return new object[] { @"a+\.?b*\.+c{2}", "ab.cc", RegexOptions.None, 0, 5, true, "ab.cc" }; 112 113 // RightToLeft 114 yield return new object[] { @"\s+\d+", "sdf 12sad", RegexOptions.RightToLeft, 0, 9, true, " 12" }; 115 yield return new object[] { @"\s+\d+", " asdf12 ", RegexOptions.RightToLeft, 0, 6, false, string.Empty }; 116 yield return new object[] { "aaa", "aaabbb", RegexOptions.None, 3, 3, false, string.Empty }; 117 118 yield return new object[] { @"foo\d+", "0123456789foo4567890foo ", RegexOptions.RightToLeft, 10, 3, false, string.Empty }; 119 yield return new object[] { @"foo\d+", "0123456789foo4567890foo ", RegexOptions.RightToLeft, 11, 21, false, string.Empty }; 120 121 // IgnoreCase 122 yield return new object[] { "AAA", "aaabbb", RegexOptions.IgnoreCase, 0, 6, true, "aaa" }; 123 yield return new object[] { @"\p{Lu}", "1bc", RegexOptions.IgnoreCase, 0, 3, true, "b" }; 124 yield return new object[] { @"\p{Ll}", "1bc", RegexOptions.IgnoreCase, 0, 3, true, "b" }; 125 yield return new object[] { @"\p{Lt}", "1bc", RegexOptions.IgnoreCase, 0, 3, true, "b" }; 126 yield return new object[] { @"\p{Lo}", "1bc", RegexOptions.IgnoreCase, 0, 3, false, string.Empty }; 127 128 // "\D+" 129 yield return new object[] { @"\D+", "12321", RegexOptions.None, 0, 5, false, string.Empty }; 130 131 // Groups 132 yield return new object[] { "(?<first_name>\\S+)\\s(?<last_name>\\S+)", "David Bau", RegexOptions.None, 0, 9, true, "David Bau" }; 133 134 // "^b" 135 yield return new object[] { "^b", "abc", RegexOptions.None, 0, 3, false, string.Empty }; 136 137 // RightToLeft 138 yield return new object[] { @"foo\d+", "0123456789foo4567890foo ", RegexOptions.RightToLeft, 0, 32, true, "foo4567890" }; 139 yield return new object[] { @"foo\d+", "0123456789foo4567890foo ", RegexOptions.RightToLeft, 10, 22, true, "foo4567890" }; 140 yield return new object[] { @"foo\d+", "0123456789foo4567890foo ", RegexOptions.RightToLeft, 10, 4, true, "foo4" }; 141 142 // Trim leading and trailing whitespace 143 yield return new object[] { @"\s*(.*?)\s*$", " Hello World ", RegexOptions.None, 0, 13, true, " Hello World " }; 144 145 // < in group 146 yield return new object[] { @"(?<cat>cat)\w+(?<dog-0>dog)", "cat_Hello_World_dog", RegexOptions.None, 0, 19, false, string.Empty }; 147 148 // Atomic Zero-Width Assertions \A \Z \z \G \b \B 149 yield return new object[] { @"\A(cat)\s+(dog)", "cat \n\n\ncat dog", RegexOptions.None, 0, 20, false, string.Empty }; 150 yield return new object[] { @"\A(cat)\s+(dog)", "cat \n\n\ncat dog", RegexOptions.Multiline, 0, 20, false, string.Empty }; 151 yield return new object[] { @"\A(cat)\s+(dog)", "cat \n\n\ncat dog", RegexOptions.ECMAScript, 0, 20, false, string.Empty }; 152 153 yield return new object[] { @"(cat)\s+(dog)\Z", "cat dog\n\n\ncat", RegexOptions.None, 0, 15, false, string.Empty }; 154 yield return new object[] { @"(cat)\s+(dog)\Z", "cat dog\n\n\ncat ", RegexOptions.Multiline, 0, 20, false, string.Empty }; 155 yield return new object[] { @"(cat)\s+(dog)\Z", "cat dog\n\n\ncat ", RegexOptions.ECMAScript, 0, 20, false, string.Empty }; 156 157 yield return new object[] { @"(cat)\s+(dog)\z", "cat dog\n\n\ncat", RegexOptions.None, 0, 15, false, string.Empty }; 158 yield return new object[] { @"(cat)\s+(dog)\z", "cat dog\n\n\ncat ", RegexOptions.Multiline, 0, 20, false, string.Empty }; 159 yield return new object[] { @"(cat)\s+(dog)\z", "cat dog\n\n\ncat ", RegexOptions.ECMAScript, 0, 20, false, string.Empty }; 160 yield return new object[] { @"(cat)\s+(dog)\z", "cat \n\n\n dog\n", RegexOptions.None, 0, 16, false, string.Empty }; 161 yield return new object[] { @"(cat)\s+(dog)\z", "cat \n\n\n dog\n", RegexOptions.Multiline, 0, 16, false, string.Empty }; 162 yield return new object[] { @"(cat)\s+(dog)\z", "cat \n\n\n dog\n", RegexOptions.ECMAScript, 0, 16, false, string.Empty }; 163 164 yield return new object[] { @"\b@cat", "123START123;@catEND", RegexOptions.None, 0, 19, false, string.Empty }; 165 yield return new object[] { @"\b<cat", "123START123'<catEND", RegexOptions.None, 0, 19, false, string.Empty }; 166 yield return new object[] { @"\b,cat", "satwe,,,START',catEND", RegexOptions.None, 0, 21, false, string.Empty }; 167 yield return new object[] { @"\b\[cat", "`12START123'[catEND", RegexOptions.None, 0, 19, false, string.Empty }; 168 169 yield return new object[] { @"\B@cat", "123START123@catEND", RegexOptions.None, 0, 18, false, string.Empty }; 170 yield return new object[] { @"\B<cat", "123START123<catEND", RegexOptions.None, 0, 18, false, string.Empty }; 171 yield return new object[] { @"\B,cat", "satwe,,,START,catEND", RegexOptions.None, 0, 20, false, string.Empty }; 172 yield return new object[] { @"\B\[cat", "`12START123[catEND", RegexOptions.None, 0, 18, false, string.Empty }; 173 174 // Lazy operator Backtracking 175 yield return new object[] { @"http://([a-zA-z0-9\-]*\.?)*?(:[0-9]*)??/", "http://www.msn.com", RegexOptions.IgnoreCase, 0, 18, false, string.Empty }; 176 177 // Grouping Constructs Invalid Regular Expressions 178 yield return new object[] { "(?!)", "(?!)cat", RegexOptions.None, 0, 7, false, string.Empty }; 179 yield return new object[] { "(?<!)", "(?<!)cat", RegexOptions.None, 0, 8, false, string.Empty }; 180 181 // Alternation construct 182 yield return new object[] { "(?(cat)|dog)", "cat", RegexOptions.None, 0, 3, true, string.Empty }; 183 yield return new object[] { "(?(cat)|dog)", "catdog", RegexOptions.None, 0, 6, true, string.Empty }; 184 yield return new object[] { "(?(cat)dog1|dog2)", "catdog1", RegexOptions.None, 0, 7, false, string.Empty }; 185 yield return new object[] { "(?(cat)dog1|dog2)", "catdog2", RegexOptions.None, 0, 7, true, "dog2" }; 186 yield return new object[] { "(?(cat)dog1|dog2)", "catdog1dog2", RegexOptions.None, 0, 11, true, "dog2" }; 187 yield return new object[] { "(?(dog2))", "dog2", RegexOptions.None, 0, 4, true, string.Empty }; 188 yield return new object[] { "(?(cat)|dog)", "oof", RegexOptions.None, 0, 3, false, string.Empty }; 189 yield return new object[] { "(?(a:b))", "a", RegexOptions.None, 0, 1, true, string.Empty }; 190 yield return new object[] { "(?(a:))", "a", RegexOptions.None, 0, 1, true, string.Empty }; 191 192 // No Negation 193 yield return new object[] { "[abcd-[abcd]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 194 yield return new object[] { "[1234-[1234]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 195 196 // All Negation 197 yield return new object[] { "[^abcd-[^abcd]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 198 yield return new object[] { "[^1234-[^1234]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 199 200 // No Negation 201 yield return new object[] { "[a-z-[a-z]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 202 yield return new object[] { "[0-9-[0-9]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 203 204 // All Negation 205 yield return new object[] { "[^a-z-[^a-z]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 206 yield return new object[] { "[^0-9-[^0-9]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 207 208 // No Negation 209 yield return new object[] { @"[\w-[\w]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 210 yield return new object[] { @"[\W-[\W]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 211 yield return new object[] { @"[\s-[\s]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 212 yield return new object[] { @"[\S-[\S]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 213 yield return new object[] { @"[\d-[\d]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 214 yield return new object[] { @"[\D-[\D]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 215 216 // All Negation 217 yield return new object[] { @"[^\w-[^\w]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 218 yield return new object[] { @"[^\W-[^\W]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 219 yield return new object[] { @"[^\s-[^\s]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 220 yield return new object[] { @"[^\S-[^\S]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 221 yield return new object[] { @"[^\d-[^\d]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 222 yield return new object[] { @"[^\D-[^\D]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 223 224 // MixedNegation 225 yield return new object[] { @"[^\w-[\W]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 226 yield return new object[] { @"[\w-[^\W]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 227 yield return new object[] { @"[^\s-[\S]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 228 yield return new object[] { @"[\s-[^\S]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 229 yield return new object[] { @"[^\d-[\D]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 230 yield return new object[] { @"[\d-[^\D]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 231 232 // No Negation 233 yield return new object[] { @"[\p{Ll}-[\p{Ll}]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 234 yield return new object[] { @"[\P{Ll}-[\P{Ll}]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 235 yield return new object[] { @"[\p{Lu}-[\p{Lu}]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 236 yield return new object[] { @"[\P{Lu}-[\P{Lu}]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 237 yield return new object[] { @"[\p{Nd}-[\p{Nd}]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 238 yield return new object[] { @"[\P{Nd}-[\P{Nd}]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 239 240 // All Negation 241 yield return new object[] { @"[^\p{Ll}-[^\p{Ll}]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 242 yield return new object[] { @"[^\P{Ll}-[^\P{Ll}]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 243 yield return new object[] { @"[^\p{Lu}-[^\p{Lu}]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 244 yield return new object[] { @"[^\P{Lu}-[^\P{Lu}]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 245 yield return new object[] { @"[^\p{Nd}-[^\p{Nd}]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 246 yield return new object[] { @"[^\P{Nd}-[^\P{Nd}]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 247 248 // MixedNegation 249 yield return new object[] { @"[^\p{Ll}-[\P{Ll}]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 250 yield return new object[] { @"[\p{Ll}-[^\P{Ll}]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 251 yield return new object[] { @"[^\p{Lu}-[\P{Lu}]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 252 yield return new object[] { @"[\p{Lu}-[^\P{Lu}]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 253 yield return new object[] { @"[^\p{Nd}-[\P{Nd}]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 254 yield return new object[] { @"[\p{Nd}-[^\P{Nd}]]+", "abcxyzABCXYZ`!@#$%^&*()_-+= \t\n", RegexOptions.None, 0, 30, false, string.Empty }; 255 256 // Character Class Substraction 257 yield return new object[] { @"[ab\-\[cd-[-[]]]]", "[]]", RegexOptions.None, 0, 3, false, string.Empty }; 258 yield return new object[] { @"[ab\-\[cd-[-[]]]]", "-]]", RegexOptions.None, 0, 3, false, string.Empty }; 259 yield return new object[] { @"[ab\-\[cd-[-[]]]]", "`]]", RegexOptions.None, 0, 3, false, string.Empty }; 260 yield return new object[] { @"[ab\-\[cd-[-[]]]]", "e]]", RegexOptions.None, 0, 3, false, string.Empty }; 261 262 yield return new object[] { @"[ab\-\[cd-[[]]]]", "']]", RegexOptions.None, 0, 3, false, string.Empty }; 263 yield return new object[] { @"[ab\-\[cd-[[]]]]", "e]]", RegexOptions.None, 0, 3, false, string.Empty }; 264 265 yield return new object[] { @"[a-[a-f]]", "abcdefghijklmnopqrstuvwxyz", RegexOptions.None, 0, 26, false, string.Empty }; 266 } 267 268 [Theory] 269 [MemberData(nameof(Match_Basic_TestData))] 270 [MemberData(nameof(RegexCompilationHelper.TransformRegexOptions), nameof(Match_Basic_TestData), 2, MemberType = typeof(RegexCompilationHelper))] Match(string pattern, string input, RegexOptions options, int beginning, int length, bool expectedSuccess, string expectedValue)271 public void Match(string pattern, string input, RegexOptions options, int beginning, int length, bool expectedSuccess, string expectedValue) 272 { 273 bool isDefaultStart = RegexHelpers.IsDefaultStart(input, options, beginning); 274 bool isDefaultCount = RegexHelpers.IsDefaultCount(input, options, length); 275 if (options == RegexOptions.None) 276 { 277 if (isDefaultStart && isDefaultCount) 278 { 279 // Use Match(string) or Match(string, string) 280 VerifyMatch(new Regex(pattern).Match(input), expectedSuccess, expectedValue); 281 VerifyMatch(Regex.Match(input, pattern), expectedSuccess, expectedValue); 282 283 Assert.Equal(expectedSuccess, new Regex(pattern).IsMatch(input)); 284 Assert.Equal(expectedSuccess, Regex.IsMatch(input, pattern)); 285 } 286 if (beginning + length == input.Length) 287 { 288 // Use Match(string, int) 289 VerifyMatch(new Regex(pattern).Match(input, beginning), expectedSuccess, expectedValue); 290 291 Assert.Equal(expectedSuccess, new Regex(pattern).IsMatch(input, beginning)); 292 } 293 // Use Match(string, int, int) 294 VerifyMatch(new Regex(pattern).Match(input, beginning, length), expectedSuccess, expectedValue); 295 } 296 if (isDefaultStart && isDefaultCount) 297 { 298 // Use Match(string) or Match(string, string, RegexOptions) 299 VerifyMatch(new Regex(pattern, options).Match(input), expectedSuccess, expectedValue); 300 VerifyMatch(Regex.Match(input, pattern, options), expectedSuccess, expectedValue); 301 302 Assert.Equal(expectedSuccess, Regex.IsMatch(input, pattern, options)); 303 } 304 if (beginning + length == input.Length && (options & RegexOptions.RightToLeft) == 0) 305 { 306 // Use Match(string, int) 307 VerifyMatch(new Regex(pattern, options).Match(input, beginning), expectedSuccess, expectedValue); 308 } 309 // Use Match(string, int, int) 310 VerifyMatch(new Regex(pattern, options).Match(input, beginning, length), expectedSuccess, expectedValue); 311 } 312 VerifyMatch(Match match, bool expectedSuccess, string expectedValue)313 public static void VerifyMatch(Match match, bool expectedSuccess, string expectedValue) 314 { 315 Assert.Equal(expectedSuccess, match.Success); 316 Assert.Equal(expectedValue, match.Value); 317 318 // Groups can never be empty 319 Assert.True(match.Groups.Count >= 1); 320 Assert.Equal(expectedSuccess, match.Groups[0].Success); 321 Assert.Equal(expectedValue, match.Groups[0].Value); 322 } 323 324 [Fact] Match_Timeout()325 public void Match_Timeout() 326 { 327 Regex regex = new Regex(@"\p{Lu}", RegexOptions.IgnoreCase, TimeSpan.FromHours(1)); 328 Match match = regex.Match("abc"); 329 Assert.True(match.Success); 330 Assert.Equal("a", match.Value); 331 } 332 333 [Fact] Match_Timeout_Throws()334 public void Match_Timeout_Throws() 335 { 336 RemoteInvoke(() => 337 { 338 const string Pattern = @"^([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*@(([0-9a-zA-Z])+([-\w]*[0-9a-zA-Z])*\.)+[a-zA-Z]{2,9})$"; 339 string input = new string('a', 50) + "@a.a"; 340 341 AppDomain.CurrentDomain.SetData(RegexHelpers.DefaultMatchTimeout_ConfigKeyName, TimeSpan.FromMilliseconds(100)); 342 Assert.Throws<RegexMatchTimeoutException>(() => new Regex(Pattern).Match(input)); 343 344 return SuccessExitCode; 345 }); 346 } 347 Match_Advanced_TestData()348 public static IEnumerable<object[]> Match_Advanced_TestData() 349 { 350 // \B special character escape: ".*\\B(SUCCESS)\\B.*" 351 yield return new object[] 352 { 353 @".*\B(SUCCESS)\B.*", "adfadsfSUCCESSadsfadsf", RegexOptions.None, 0, 22, 354 new CaptureData[] 355 { 356 new CaptureData("adfadsfSUCCESSadsfadsf", 0, 22), 357 new CaptureData("SUCCESS", 7, 7) 358 } 359 }; 360 361 // Using |, (), ^, $, .: Actual - "^aaa(bb.+)(d|c)$" 362 yield return new object[] 363 { 364 "^aaa(bb.+)(d|c)$", "aaabb.cc", RegexOptions.None, 0, 8, 365 new CaptureData[] 366 { 367 new CaptureData("aaabb.cc", 0, 8), 368 new CaptureData("bb.c", 3, 4), 369 new CaptureData("c", 7, 1) 370 } 371 }; 372 373 // Using greedy quantifiers: Actual - "(a+)(b*)(c?)" 374 yield return new object[] 375 { 376 "(a+)(b*)(c?)", "aaabbbccc", RegexOptions.None, 0, 9, 377 new CaptureData[] 378 { 379 new CaptureData("aaabbbc", 0, 7), 380 new CaptureData("aaa", 0, 3), 381 new CaptureData("bbb", 3, 3), 382 new CaptureData("c", 6, 1) 383 } 384 }; 385 386 // Using lazy quantifiers: Actual - "(d+?)(e*?)(f??)" 387 // Interesting match from this pattern and input. If needed to go to the end of the string change the ? to + in the last lazy quantifier 388 yield return new object[] 389 { 390 "(d+?)(e*?)(f??)", "dddeeefff", RegexOptions.None, 0, 9, 391 new CaptureData[] 392 { 393 new CaptureData("d", 0, 1), 394 new CaptureData("d", 0, 1), 395 new CaptureData(string.Empty, 1, 0), 396 new CaptureData(string.Empty, 1, 0) 397 } 398 }; 399 400 // Noncapturing group : Actual - "(a+)(?:b*)(ccc)" 401 yield return new object[] 402 { 403 "(a+)(?:b*)(ccc)", "aaabbbccc", RegexOptions.None, 0, 9, 404 new CaptureData[] 405 { 406 new CaptureData("aaabbbccc", 0, 9), 407 new CaptureData("aaa", 0, 3), 408 new CaptureData("ccc", 6, 3), 409 } 410 }; 411 412 // Zero-width positive lookahead assertion: Actual - "abc(?=XXX)\\w+" 413 yield return new object[] 414 { 415 @"abc(?=XXX)\w+", "abcXXXdef", RegexOptions.None, 0, 9, 416 new CaptureData[] 417 { 418 new CaptureData("abcXXXdef", 0, 9) 419 } 420 }; 421 422 // Backreferences : Actual - "(\\w)\\1" 423 yield return new object[] 424 { 425 @"(\w)\1", "aa", RegexOptions.None, 0, 2, 426 new CaptureData[] 427 { 428 new CaptureData("aa", 0, 2), 429 new CaptureData("a", 0, 1), 430 } 431 }; 432 433 // Alternation constructs: Actual - "(111|aaa)" 434 yield return new object[] 435 { 436 "(111|aaa)", "aaa", RegexOptions.None, 0, 3, 437 new CaptureData[] 438 { 439 new CaptureData("aaa", 0, 3), 440 new CaptureData("aaa", 0, 3) 441 } 442 }; 443 444 // Actual - "(?<1>\\d+)abc(?(1)222|111)" 445 yield return new object[] 446 { 447 @"(?<MyDigits>\d+)abc(?(MyDigits)222|111)", "111abc222", RegexOptions.None, 0, 9, 448 new CaptureData[] 449 { 450 new CaptureData("111abc222", 0, 9), 451 new CaptureData("111", 0, 3) 452 } 453 }; 454 455 // Using "n" Regex option. Only explicitly named groups should be captured: Actual - "([0-9]*)\\s(?<s>[a-z_A-Z]+)", "n" 456 yield return new object[] 457 { 458 @"([0-9]*)\s(?<s>[a-z_A-Z]+)", "200 dollars", RegexOptions.ExplicitCapture, 0, 11, 459 new CaptureData[] 460 { 461 new CaptureData("200 dollars", 0, 11), 462 new CaptureData("dollars", 4, 7) 463 } 464 }; 465 466 // Single line mode "s". Includes new line character: Actual - "([^/]+)","s" 467 yield return new object[] 468 { 469 "(.*)", "abc\nsfc", RegexOptions.Singleline, 0, 7, 470 new CaptureData[] 471 { 472 new CaptureData("abc\nsfc", 0, 7), 473 new CaptureData("abc\nsfc", 0, 7), 474 } 475 }; 476 477 // "([0-9]+(\\.[0-9]+){3})" 478 yield return new object[] 479 { 480 @"([0-9]+(\.[0-9]+){3})", "209.25.0.111", RegexOptions.None, 0, 12, 481 new CaptureData[] 482 { 483 new CaptureData("209.25.0.111", 0, 12), 484 new CaptureData("209.25.0.111", 0, 12), 485 new CaptureData(".111", 8, 4, new CaptureData[] 486 { 487 new CaptureData(".25", 3, 3), 488 new CaptureData(".0", 6, 2), 489 new CaptureData(".111", 8, 4), 490 }), 491 } 492 }; 493 494 // Groups and captures 495 yield return new object[] 496 { 497 @"(?<A1>a*)(?<A2>b*)(?<A3>c*)", "aaabbccccccccccaaaabc", RegexOptions.None, 0, 21, 498 new CaptureData[] 499 { 500 new CaptureData("aaabbcccccccccc", 0, 15), 501 new CaptureData("aaa", 0, 3), 502 new CaptureData("bb", 3, 2), 503 new CaptureData("cccccccccc", 5, 10) 504 } 505 }; 506 507 yield return new object[] 508 { 509 @"(?<A1>A*)(?<A2>B*)(?<A3>C*)", "aaabbccccccccccaaaabc", RegexOptions.IgnoreCase, 0, 21, 510 new CaptureData[] 511 { 512 new CaptureData("aaabbcccccccccc", 0, 15), 513 new CaptureData("aaa", 0, 3), 514 new CaptureData("bb", 3, 2), 515 new CaptureData("cccccccccc", 5, 10) 516 } 517 }; 518 519 // Using |, (), ^, $, .: Actual - "^aaa(bb.+)(d|c)$" 520 yield return new object[] 521 { 522 "^aaa(bb.+)(d|c)$", "aaabb.cc", RegexOptions.None, 0, 8, 523 new CaptureData[] 524 { 525 new CaptureData("aaabb.cc", 0, 8), 526 new CaptureData("bb.c", 3, 4), 527 new CaptureData("c", 7, 1) 528 } 529 }; 530 531 // Actual - ".*\\b(\\w+)\\b" 532 yield return new object[] 533 { 534 @".*\b(\w+)\b", "XSP_TEST_FAILURE SUCCESS", RegexOptions.None, 0, 24, 535 new CaptureData[] 536 { 537 new CaptureData("XSP_TEST_FAILURE SUCCESS", 0, 24), 538 new CaptureData("SUCCESS", 17, 7) 539 } 540 }; 541 542 // Mutliline 543 yield return new object[] 544 { 545 "(line2$\n)line3", "line1\nline2\nline3\n\nline4", RegexOptions.Multiline, 0, 24, 546 new CaptureData[] 547 { 548 new CaptureData("line2\nline3", 6, 11), 549 new CaptureData("line2\n", 6, 6) 550 } 551 }; 552 553 // Mutliline 554 yield return new object[] 555 { 556 "(line2\n^)line3", "line1\nline2\nline3\n\nline4", RegexOptions.Multiline, 0, 24, 557 new CaptureData[] 558 { 559 new CaptureData("line2\nline3", 6, 11), 560 new CaptureData("line2\n", 6, 6) 561 } 562 }; 563 564 // Mutliline 565 yield return new object[] 566 { 567 "(line3\n$\n)line4", "line1\nline2\nline3\n\nline4", RegexOptions.Multiline, 0, 24, 568 new CaptureData[] 569 { 570 new CaptureData("line3\n\nline4", 12, 12), 571 new CaptureData("line3\n\n", 12, 7) 572 } 573 }; 574 575 // Mutliline 576 yield return new object[] 577 { 578 "(line3\n^\n)line4", "line1\nline2\nline3\n\nline4", RegexOptions.Multiline, 0, 24, 579 new CaptureData[] 580 { 581 new CaptureData("line3\n\nline4", 12, 12), 582 new CaptureData("line3\n\n", 12, 7) 583 } 584 }; 585 586 // Mutliline 587 yield return new object[] 588 { 589 "(line2$\n^)line3", "line1\nline2\nline3\n\nline4", RegexOptions.Multiline, 0, 24, 590 new CaptureData[] 591 { 592 new CaptureData("line2\nline3", 6, 11), 593 new CaptureData("line2\n", 6, 6) 594 } 595 }; 596 597 // RightToLeft 598 yield return new object[] 599 { 600 "aaa", "aaabbb", RegexOptions.RightToLeft, 3, 3, 601 new CaptureData[] 602 { 603 new CaptureData("aaa", 0, 3) 604 } 605 }; 606 } 607 608 [Theory] 609 [MemberData(nameof(Match_Advanced_TestData))] Match(string pattern, string input, RegexOptions options, int beginning, int length, CaptureData[] expected)610 public void Match(string pattern, string input, RegexOptions options, int beginning, int length, CaptureData[] expected) 611 { 612 bool isDefaultStart = RegexHelpers.IsDefaultStart(input, options, beginning); 613 bool isDefaultCount = RegexHelpers.IsDefaultStart(input, options, length); 614 if (options == RegexOptions.None) 615 { 616 if (isDefaultStart && isDefaultCount) 617 { 618 // Use Match(string) or Match(string, string) 619 VerifyMatch(new Regex(pattern).Match(input), true, expected); 620 VerifyMatch(Regex.Match(input, pattern), true, expected); 621 622 Assert.True(new Regex(pattern).IsMatch(input)); 623 Assert.True(Regex.IsMatch(input, pattern)); 624 } 625 if (beginning + length == input.Length) 626 { 627 // Use Match(string, int) 628 VerifyMatch(new Regex(pattern).Match(input, beginning), true, expected); 629 630 Assert.True(new Regex(pattern).IsMatch(input, beginning)); 631 } 632 else 633 { 634 // Use Match(string, int, int) 635 VerifyMatch(new Regex(pattern).Match(input, beginning, length), true, expected); 636 } 637 } 638 if (isDefaultStart && isDefaultCount) 639 { 640 // Use Match(string) or Match(string, string, RegexOptions) 641 VerifyMatch(new Regex(pattern, options).Match(input), true, expected); 642 VerifyMatch(Regex.Match(input, pattern, options), true, expected); 643 644 Assert.True(Regex.IsMatch(input, pattern, options)); 645 } 646 if (beginning + length == input.Length) 647 { 648 // Use Match(string, int) 649 VerifyMatch(new Regex(pattern, options).Match(input, beginning), true, expected); 650 } 651 if ((options & RegexOptions.RightToLeft) == 0) 652 { 653 // Use Match(string, int, int) 654 VerifyMatch(new Regex(pattern, options).Match(input, beginning, length), true, expected); 655 } 656 } 657 VerifyMatch(Match match, bool expectedSuccess, CaptureData[] expected)658 public static void VerifyMatch(Match match, bool expectedSuccess, CaptureData[] expected) 659 { 660 Assert.Equal(expectedSuccess, match.Success); 661 662 Assert.Equal(expected[0].Value, match.Value); 663 Assert.Equal(expected[0].Index, match.Index); 664 Assert.Equal(expected[0].Length, match.Length); 665 666 Assert.Equal(1, match.Captures.Count); 667 Assert.Equal(expected[0].Value, match.Captures[0].Value); 668 Assert.Equal(expected[0].Index, match.Captures[0].Index); 669 Assert.Equal(expected[0].Length, match.Captures[0].Length); 670 671 Assert.Equal(expected.Length, match.Groups.Count); 672 for (int i = 0; i < match.Groups.Count; i++) 673 { 674 Assert.Equal(expectedSuccess, match.Groups[i].Success); 675 676 Assert.Equal(expected[i].Value, match.Groups[i].Value); 677 Assert.Equal(expected[i].Index, match.Groups[i].Index); 678 Assert.Equal(expected[i].Length, match.Groups[i].Length); 679 680 Assert.Equal(expected[i].Captures.Length, match.Groups[i].Captures.Count); 681 for (int j = 0; j < match.Groups[i].Captures.Count; j++) 682 { 683 Assert.Equal(expected[i].Captures[j].Value, match.Groups[i].Captures[j].Value); 684 Assert.Equal(expected[i].Captures[j].Index, match.Groups[i].Captures[j].Index); 685 Assert.Equal(expected[i].Captures[j].Length, match.Groups[i].Captures[j].Length); 686 } 687 } 688 } 689 690 [Theory] 691 [InlineData(@"(?<1>\d{1,2})/(?<2>\d{1,2})/(?<3>\d{2,4})\s(?<time>\S+)", "08/10/99 16:00", "${time}", "16:00")] 692 [InlineData(@"(?<1>\d{1,2})/(?<2>\d{1,2})/(?<3>\d{2,4})\s(?<time>\S+)", "08/10/99 16:00", "${1}", "08")] 693 [InlineData(@"(?<1>\d{1,2})/(?<2>\d{1,2})/(?<3>\d{2,4})\s(?<time>\S+)", "08/10/99 16:00", "${2}", "10")] 694 [InlineData(@"(?<1>\d{1,2})/(?<2>\d{1,2})/(?<3>\d{2,4})\s(?<time>\S+)", "08/10/99 16:00", "${3}", "99")] 695 [InlineData("abc", "abc", "abc", "abc")] Result(string pattern, string input, string replacement, string expected)696 public void Result(string pattern, string input, string replacement, string expected) 697 { 698 Assert.Equal(expected, new Regex(pattern).Match(input).Result(replacement)); 699 } 700 701 [Fact] Result_Invalid()702 public void Result_Invalid() 703 { 704 Match match = Regex.Match("foo", "foo"); 705 AssertExtensions.Throws<ArgumentNullException>("replacement", () => match.Result(null)); 706 707 Assert.Throws<NotSupportedException>(() => RegularExpressions.Match.Empty.Result("any")); 708 } 709 710 [Fact] Match_SpecialUnicodeCharacters_enUS()711 public void Match_SpecialUnicodeCharacters_enUS() 712 { 713 RemoteInvoke(() => 714 { 715 CultureInfo.CurrentCulture = new CultureInfo("en-US"); 716 Match("\u0131", "\u0049", RegexOptions.IgnoreCase, 0, 1, false, string.Empty); 717 Match("\u0131", "\u0069", RegexOptions.IgnoreCase, 0, 1, false, string.Empty); 718 719 return SuccessExitCode; 720 }).Dispose(); 721 } 722 723 [Fact] Match_SpecialUnicodeCharacters_Invariant()724 public void Match_SpecialUnicodeCharacters_Invariant() 725 { 726 RemoteInvoke(() => 727 { 728 CultureInfo.CurrentCulture = CultureInfo.InvariantCulture; 729 Match("\u0131", "\u0049", RegexOptions.IgnoreCase, 0, 1, false, string.Empty); 730 Match("\u0131", "\u0069", RegexOptions.IgnoreCase, 0, 1, false, string.Empty); 731 Match("\u0130", "\u0049", RegexOptions.IgnoreCase, 0, 1, false, string.Empty); 732 Match("\u0130", "\u0069", RegexOptions.IgnoreCase, 0, 1, false, string.Empty); 733 734 return SuccessExitCode; 735 }).Dispose(); 736 } 737 738 [Fact] Match_Invalid()739 public void Match_Invalid() 740 { 741 // Input is null 742 AssertExtensions.Throws<ArgumentNullException>("input", () => Regex.Match(null, "pattern")); 743 AssertExtensions.Throws<ArgumentNullException>("input", () => Regex.Match(null, "pattern", RegexOptions.None)); 744 AssertExtensions.Throws<ArgumentNullException>("input", () => Regex.Match(null, "pattern", RegexOptions.None, TimeSpan.FromSeconds(1))); 745 746 AssertExtensions.Throws<ArgumentNullException>("input", () => new Regex("pattern").Match(null)); 747 AssertExtensions.Throws<ArgumentNullException>("input", () => new Regex("pattern").Match(null, 0)); 748 AssertExtensions.Throws<ArgumentNullException>("input", () => new Regex("pattern").Match(null, 0, 0)); 749 750 // Pattern is null 751 AssertExtensions.Throws<ArgumentNullException>("pattern", () => Regex.Match("input", null)); 752 AssertExtensions.Throws<ArgumentNullException>("pattern", () => Regex.Match("input", null, RegexOptions.None)); 753 AssertExtensions.Throws<ArgumentNullException>("pattern", () => Regex.Match("input", null, RegexOptions.None, TimeSpan.FromSeconds(1))); 754 755 // Start is invalid 756 Assert.Throws<ArgumentOutOfRangeException>(() => new Regex("pattern").Match("input", -1)); 757 Assert.Throws<ArgumentOutOfRangeException>(() => new Regex("pattern").Match("input", -1, 0)); 758 Assert.Throws<ArgumentOutOfRangeException>(() => new Regex("pattern").Match("input", 6)); 759 Assert.Throws<ArgumentOutOfRangeException>(() => new Regex("pattern").Match("input", 6, 0)); 760 761 // Length is invalid 762 AssertExtensions.Throws<ArgumentOutOfRangeException>("length", () => new Regex("pattern").Match("input", 0, -1)); 763 AssertExtensions.Throws<ArgumentOutOfRangeException>("length", () => new Regex("pattern").Match("input", 0, 6)); 764 } 765 766 [Theory] 767 [InlineData(")")] 768 [InlineData("())")] 769 [InlineData("[a-z-[aeiuo]")] 770 [InlineData("[a-z-[aeiuo")] 771 [InlineData("[a-z-[b]")] 772 [InlineData("[a-z-[b")] 773 [InlineData("[b-a]")] 774 [InlineData(@"[a-c]{2,1}")] 775 [InlineData(@"\d{2147483648}")] 776 [InlineData("[a-z-[b][")] 777 [InlineData(@"\")] 778 [InlineData("(?()|||||)")] Match_InvalidPattern(string pattern)779 public void Match_InvalidPattern(string pattern) 780 { 781 AssertExtensions.Throws<ArgumentException>(null, () => Regex.Match("input", pattern)); 782 } 783 784 [Fact] IsMatch_Invalid()785 public void IsMatch_Invalid() 786 { 787 // Input is null 788 AssertExtensions.Throws<ArgumentNullException>("input", () => Regex.IsMatch(null, "pattern")); 789 AssertExtensions.Throws<ArgumentNullException>("input", () => Regex.IsMatch(null, "pattern", RegexOptions.None)); 790 AssertExtensions.Throws<ArgumentNullException>("input", () => Regex.IsMatch(null, "pattern", RegexOptions.None, TimeSpan.FromSeconds(1))); 791 792 AssertExtensions.Throws<ArgumentNullException>("input", () => new Regex("pattern").IsMatch(null)); 793 AssertExtensions.Throws<ArgumentNullException>("input", () => new Regex("pattern").IsMatch(null, 0)); 794 795 // Pattern is null 796 AssertExtensions.Throws<ArgumentNullException>("pattern", () => Regex.IsMatch("input", null)); 797 AssertExtensions.Throws<ArgumentNullException>("pattern", () => Regex.IsMatch("input", null, RegexOptions.None)); 798 AssertExtensions.Throws<ArgumentNullException>("pattern", () => Regex.IsMatch("input", null, RegexOptions.None, TimeSpan.FromSeconds(1))); 799 800 // Start is invalid 801 Assert.Throws<ArgumentOutOfRangeException>(() => new Regex("pattern").IsMatch("input", -1)); 802 Assert.Throws<ArgumentOutOfRangeException>(() => new Regex("pattern").IsMatch("input", 6)); 803 } 804 } 805 } 806