public async Task Count_Timeout_ThrowsAfterTooLongExecution(RegexEngine engine)
        {
            if (RegexHelpers.IsNonBacktracking(engine))
            {
                // Test relies on backtracking taking a long time
                return;
            }

            const string Pattern = @"^(\w+\s?)*$";
            const string Input   = "An input string that takes a very very very very very very very very very very very long time!";

            Regex r = await RegexHelpers.GetRegexAsync(engine, Pattern, RegexOptions.None, TimeSpan.FromMilliseconds(1));

            Stopwatch sw = Stopwatch.StartNew();

            Assert.Throws <RegexMatchTimeoutException>(() => r.Count(Input));
            Assert.Throws <RegexMatchTimeoutException>(() => r.Count(Input.AsSpan()));
            Assert.InRange(sw.Elapsed.TotalSeconds, 0, 10); // arbitrary upper bound that should be well above what's needed with a 1ms timeout

            switch (engine)
            {
            case RegexEngine.Interpreter:
            case RegexEngine.Compiled:
                sw = Stopwatch.StartNew();
                Assert.Throws <RegexMatchTimeoutException>(() => Regex.Count(Input, Pattern, RegexHelpers.OptionsFromEngine(engine), TimeSpan.FromMilliseconds(1)));
                Assert.Throws <RegexMatchTimeoutException>(() => Regex.Count(Input.AsSpan(), Pattern, RegexHelpers.OptionsFromEngine(engine), TimeSpan.FromMilliseconds(1)));
                Assert.InRange(sw.Elapsed.TotalSeconds, 0, 10);     // arbitrary upper bound that should be well above what's needed with a 1ms timeout
                break;
            }
        }
Beispiel #2
0
        public async Task CharactersComparedOneByOne_Invariant(RegexEngine engine, RegexOptions options)
        {
            // Regex compares characters one by one.  If that changes, it could impact the behavior of
            // a case like this, where these characters are not the same, but the strings compare
            // as equal with the invariant culture (and some other cultures as well).
            const string S1 = "\u00D6\u200D";
            const string S2 = "\u004F\u0308";

            // Validate the chosen strings to make sure they compare the way we want to test via Regex
            Assert.False(S1[0] == S2[0]);
            Assert.False(S1[1] == S2[1]);
            Assert.StartsWith(S1, S2, StringComparison.InvariantCulture);
            Assert.True(S1.Equals(S2, StringComparison.InvariantCulture));

            // Test varying lengths of strings to validate codegen changes that kick in at longer lengths
            foreach (int multiple in new[] { 1, 10, 100 })
            {
                string pattern = string.Concat(Enumerable.Repeat(S1, multiple));
                string input   = string.Concat(Enumerable.Repeat(S2, multiple));
                Regex  r;

                // Validate when the string is at the beginning of the pattern, as it impacts prefix matching.
                r = await RegexHelpers.GetRegexAsync(engine, pattern, options);

                Assert.False(r.IsMatch(input));
                Assert.True(r.IsMatch(pattern));

                // Validate when it's not at the beginning of the pattern, as it impacts "multi" matching.
                r = await RegexHelpers.GetRegexAsync(engine, "[abc]" + pattern, options);

                Assert.False(r.IsMatch("a" + input));
                Assert.True(r.IsMatch("a" + pattern));
            }
        }
        public async Task Replace(RegexEngine engine, string pattern, string input, string replacement, RegexOptions options, int count, int start, string expected)
        {
            // A few tests exceed the 1000 limit, they reach 6003
            RegexHelpers.SetSafeSizeThreshold(6005);
            Regex r;

            try
            {
                r = await RegexHelpers.GetRegexAsync(engine, pattern, options);
            }
            finally
            {
                RegexHelpers.RestoreSafeSizeThresholdToDefault();
            }

            bool isDefaultStart = RegexHelpers.IsDefaultStart(input, options, start);
            bool isDefaultCount = RegexHelpers.IsDefaultCount(input, options, count);

            if (isDefaultStart)
            {
                if (isDefaultCount)
                {
                    Assert.Equal(expected, r.Replace(input, replacement));
                    Assert.Equal(expected, Regex.Replace(input, pattern, replacement, options));
                }

                Assert.Equal(expected, r.Replace(input, replacement, count));
            }

            Assert.Equal(expected, r.Replace(input, replacement, count, start));
        }
        public async Task Count_ReturnsExpectedCount(RegexEngine engine, string pattern, string input, RegexOptions options, int expectedCount)
        {
            Regex r = await RegexHelpers.GetRegexAsync(engine, pattern, options);

            Assert.Equal(expectedCount, r.Count(input));
            Assert.Equal(expectedCount, r.Count(input.AsSpan()));
            Assert.Equal(r.Count(input), r.Matches(input).Count);
            Assert.Equal(r.Count(input.AsSpan()), r.Matches(input).Count);

            if (options == RegexOptions.None && engine == RegexEngine.Interpreter)
            {
                Assert.Equal(expectedCount, Regex.Count(input, pattern));
                Assert.Equal(expectedCount, Regex.Count(input.AsSpan(), pattern));
            }

            switch (engine)
            {
            case RegexEngine.Interpreter:
            case RegexEngine.Compiled:
            case RegexEngine.NonBacktracking:
                RegexOptions engineOptions = RegexHelpers.OptionsFromEngine(engine);
                Assert.Equal(expectedCount, Regex.Count(input, pattern, options | engineOptions));
                Assert.Equal(expectedCount, Regex.Count(input.AsSpan(), pattern, options | engineOptions));
                Assert.Equal(expectedCount, Regex.Count(input, pattern, options | engineOptions, Regex.InfiniteMatchTimeout));
                Assert.Equal(expectedCount, Regex.Count(input.AsSpan(), pattern, options | engineOptions, Regex.InfiniteMatchTimeout));
                break;
            }
        }
        public void TurkishI_Is_Differently_LowerUpperCased_In_Turkish_Culture_NonBacktracking()
        {
            var    turkish = new CultureInfo("tr-TR");
            string input   = "I\u0131\u0130i";

            // Use the input as the regex also
            // Ignore the Compiled option here because it is a noop in combination with NonBacktracking
            Regex cultInvariantRegex = RegexHelpers.CreateRegexInCulture(input, RegexHelpers.RegexOptionNonBacktracking | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant, CultureInfo.InvariantCulture);
            Regex turkishRegex       = RegexHelpers.CreateRegexInCulture(input, RegexHelpers.RegexOptionNonBacktracking | RegexOptions.IgnoreCase, turkish);

            Assert.True(cultInvariantRegex.IsMatch(input));
            Assert.True(turkishRegex.IsMatch(input));    // <---------- This result differs from the result in the previous test!!!

            // As above and no surprises here
            // The regexes recognize different lowercase variants of different versions of i differently
            Assert.True(cultInvariantRegex.IsMatch(input.ToLowerInvariant()));
            Assert.False(cultInvariantRegex.IsMatch(input.ToLower(turkish)));

            Assert.False(turkishRegex.IsMatch(input.ToLowerInvariant()));
            Assert.True(turkishRegex.IsMatch(input.ToLower(turkish)));

            // The same holds symmetrically for ToUpper
            Assert.True(cultInvariantRegex.IsMatch(input.ToUpperInvariant()));
            Assert.False(cultInvariantRegex.IsMatch(input.ToUpper(turkish)));

            Assert.False(turkishRegex.IsMatch(input.ToUpperInvariant()));
            Assert.True(turkishRegex.IsMatch(input.ToUpper(turkish)));
        }
Beispiel #6
0
        public async Task SingleExpected(RegexEngine engine, char c)
        {
            string s   = $@"\u{(int)c:X4}";
            var    set = new HashSet <char>()
            {
                c
            };

            // One
            await ValidateSetAsync(engine, $"{s}", RegexOptions.None, set, null);
            await ValidateSetAsync(engine, $"[{s}]", RegexOptions.None, set, null);
            await ValidateSetAsync(engine, $"[^{s}]", RegexOptions.None, null, set);

            if (!RegexHelpers.IsNonBacktracking(engine))
            {
                // Positive lookahead
                await ValidateSetAsync(engine, $"(?={s}){s}", RegexOptions.None, set, null);
                await ValidateSetAsync(engine, $"(?=[^{s}])[^{s}]", RegexOptions.None, null, set);

                // Negative lookahead
                await ValidateSetAsync(engine, $"(?![^{s}]){s}", RegexOptions.None, set, null);
                await ValidateSetAsync(engine, $"(?![{s}])[^{s}]", RegexOptions.None, null, set);
            }

            // Concatenation
            await ValidateSetAsync(engine, $"[{s}{s}]", RegexOptions.None, set, null);
            await ValidateSetAsync(engine, $"[^{s}{s}{s}]", RegexOptions.None, null, set);

            // Alternation
            await ValidateSetAsync(engine, $"{s}|{s}", RegexOptions.None, set, null);
            await ValidateSetAsync(engine, $"[^{s}]|[^{s}]|[^{s}]", RegexOptions.None, null, set);
            await ValidateSetAsync(engine, $"{s}|[^{s}]", RegexOptions.None, null, new HashSet <char>());
        }
Beispiel #7
0
        public async Task Matches(RegexEngine engine, string pattern, string input, RegexOptions options, CaptureData[] expected)
        {
            Regex regexAdvanced = await RegexHelpers.GetRegexAsync(engine, pattern, options);

            VerifyMatches(regexAdvanced.Matches(input), expected);
            VerifyMatches(regexAdvanced.Match(input), expected);
        }
        public void Match_In_Different_Cultures_CriticalCases(string pattern, RegexOptions options, CultureInfo culture, string input, string match_expected)
        {
            Regex r     = RegexHelpers.CreateRegexInCulture(pattern, options, culture);
            Match match = r.Match(input);

            Assert.Equal(match_expected, match.Value);
        }
Beispiel #9
0
        public void Replace(string pattern, string input, MatchEvaluator evaluator, RegexOptions options, int count, int start, string expected)
        {
            bool isDefaultStart = RegexHelpers.IsDefaultStart(input, options, start);
            bool isDefaultCount = RegexHelpers.IsDefaultCount(input, options, count);

            if (options == RegexOptions.None)
            {
                if (isDefaultStart && isDefaultCount)
                {
                    // Use Replace(string, MatchEvaluator) or Replace(string, string, MatchEvaluator)
                    Assert.Equal(expected, new Regex(pattern).Replace(input, evaluator));
                    Assert.Equal(expected, Regex.Replace(input, pattern, evaluator));
                }
                if (isDefaultStart)
                {
                    // Use Replace(string, MatchEvaluator, string, int)
                    Assert.Equal(expected, new Regex(pattern).Replace(input, evaluator, count));
                }
                // Use Replace(string, MatchEvaluator, int, int)
                Assert.Equal(expected, new Regex(pattern).Replace(input, evaluator, count, start));
            }
            if (isDefaultStart && isDefaultCount)
            {
                // Use Replace(string, MatchEvaluator) or Replace(string, MatchEvaluator, RegexOptions)
                Assert.Equal(expected, new Regex(pattern, options).Replace(input, evaluator));
                Assert.Equal(expected, Regex.Replace(input, pattern, evaluator, options));
            }
            if (isDefaultStart)
            {
                // Use Replace(string, MatchEvaluator, string, int)
                Assert.Equal(expected, new Regex(pattern, options).Replace(input, evaluator, count));
            }
            // Use Replace(string, MatchEvaluator, int, int)
            Assert.Equal(expected, new Regex(pattern, options).Replace(input, evaluator, count, start));
        }
        public void Split(string pattern, string input, RegexOptions options, int count, int start, string[] expected)
        {
            bool isDefaultStart = RegexHelpers.IsDefaultStart(input, options, start);
            bool isDefaultCount = RegexHelpers.IsDefaultStart(input, options, count);

            if (options == RegexOptions.None)
            {
                // Use Split(string), Split(string, string), Split(string, int) or Split(string, int, int)
                if (isDefaultStart && isDefaultCount)
                {
                    // Use Split(string) or Split(string, string)
                    Assert.Equal(expected, new Regex(pattern).Split(input));
                    Assert.Equal(expected, Regex.Split(input, pattern));
                }
                if (isDefaultStart)
                {
                    // Use Split(string, int)
                    Assert.Equal(expected, new Regex(pattern).Split(input, count));
                }
                // Use Split(string, int, int)
                Assert.Equal(expected, new Regex(pattern).Split(input, count, start));
            }
            if (isDefaultStart && isDefaultCount)
            {
                // Use Split(string, string, RegexOptions)
                Assert.Equal(expected, Regex.Split(input, pattern, options));
            }
            if (isDefaultStart)
            {
                // Use Split(string, int)
                Assert.Equal(expected, new Regex(pattern, options).Split(input, count));
            }
            // Use Split(string, int, int, int)
            Assert.Equal(expected, new Regex(pattern, options).Split(input, count, start));
        }
Beispiel #11
0
        public async Task Match_In_Different_Cultures_CriticalCases(string pattern, RegexOptions options, RegexEngine engine, CultureInfo culture, string input, string match_expected)
        {
            Regex r = await RegexHelpers.GetRegexAsync(engine, pattern, options, culture);

            Match match = r.Match(input);

            Assert.Equal(match_expected, match.Value);
        }
Beispiel #12
0
        public async Task Test(RegexEngine engine, RegexOptions options, string pattern, string input, string captures, string nonBacktrackingCaptures = null)
        {
            if (input == "NULL")
            {
                input = "";
            }

            bool   nonBacktracking = engine == RegexEngine.NonBacktracking;
            string expected        = nonBacktracking && nonBacktrackingCaptures != null ?
                                     nonBacktrackingCaptures : // nonBacktrackingCaptures value overrides the expected result in NonBacktracking mode
                                     captures;

            if (expected == "BADBR")
            {
                await Assert.ThrowsAnyAsync <ArgumentException>(async() => await RegexHelpers.GetRegexAsync(engine, pattern, options));

                return;
            }

            if (nonBacktracking && nonBacktrackingCaptures == "NONBACKTRACKINGINCOMPATIBLE")
            {
                // In particular: backreferences are not supported in NonBacktracking mode
                await Assert.ThrowsAnyAsync <NotSupportedException>(() => RegexHelpers.GetRegexAsync(engine, pattern, options));

                return;
            }

            Regex r = await RegexHelpers.GetRegexAsync(engine, pattern, options);

            if (expected == "NOMATCH")
            {
                Assert.False(r.IsMatch(input));
                return;
            }

            Match match = r.Match(input);

            Assert.True(match.Success);

            var expectedSet = new HashSet <(int start, int end)>(
                expected
                .Split(new[] { '(', ')' }, StringSplitOptions.RemoveEmptyEntries)
                .Select(s => s.Split(','))
                .Select(s => (start: int.Parse(s[0]), end: int.Parse(s[1]))));

            var actualSet = new HashSet <(int start, int end)>(
                match.Groups
                .Cast <Group>()
                .Select(g => (start: g.Index, end: g.Index + g.Length)));

            // NonBacktracking mode only provides the top-level match.
            // The .NET implementation sometimes has extra captures beyond what the original data specifies, so we assert a subset.
            if (nonBacktracking ? !actualSet.IsSubsetOf(expectedSet) : !expectedSet.IsSubsetOf(actualSet))
            {
                throw new Xunit.Sdk.XunitException($"Actual: {string.Join(", ", actualSet)}{Environment.NewLine}Expected: {string.Join(", ", expected)}");
            }
        }
Beispiel #13
0
        public async Task TurkishCulture_MatchesWordChar(RegexEngine engine, string input, RegexOptions options, string expectedResult)
        {
            using (new ThreadCultureChange(new CultureInfo("tr-TR")))
            {
                Regex regex = await RegexHelpers.GetRegexAsync(engine, @"\w*", options);

                Assert.Equal(expectedResult, regex.Match(input).Value);
            }
        }
Beispiel #14
0
        public static IEnumerable <object[]> Count_ReturnsExpectedCount_TestData()
        {
            foreach (RegexEngine engine in RegexHelpers.AvailableEngines)
            {
                yield return(new object[] { engine, @"", "", 0, RegexOptions.None, 1 });

                yield return(new object[] { engine, @"", "a", 0, RegexOptions.None, 2 });

                yield return(new object[] { engine, @"", "ab", 0, RegexOptions.None, 3 });

                yield return(new object[] { engine, @"", "ab", 1, RegexOptions.None, 2 });

                yield return(new object[] { engine, @"\w", "", 0, RegexOptions.None, 0 });

                yield return(new object[] { engine, @"\w", "a", 0, RegexOptions.None, 1 });

                yield return(new object[] { engine, @"\w", "ab", 0, RegexOptions.None, 2 });

                yield return(new object[] { engine, @"\w", "ab", 1, RegexOptions.None, 1 });

                yield return(new object[] { engine, @"\w", "ab", 2, RegexOptions.None, 0 });

                yield return(new object[] { engine, @"\b\w+\b", "abc def ghi jkl", 0, RegexOptions.None, 4 });

                yield return(new object[] { engine, @"\b\w+\b", "abc def ghi jkl", 7, RegexOptions.None, 2 });

                yield return(new object[] { engine, @"A", "", 0, RegexOptions.IgnoreCase, 0 });

                yield return(new object[] { engine, @"A", "a", 0, RegexOptions.IgnoreCase, 1 });

                yield return(new object[] { engine, @"A", "aAaA", 0, RegexOptions.IgnoreCase, 4 });

                yield return(new object[] { engine, @".", "\n\n\n", 0, RegexOptions.None, 0 });

                yield return(new object[] { engine, @".", "\n\n\n", 0, RegexOptions.Singleline, 3 });

                yield return(new object[] { engine, @"[а-я-[аeиоуыэюя]]", "спокойной ночи", 0, RegexOptions.None, 8 });

                if (!RegexHelpers.IsNonBacktracking(engine))
                {
                    // Lookbehinds
                    yield return(new object[] { engine, @"(?<=abc)\w", "abcxabcy", 7, RegexOptions.None, 1 });

                    // Starting anchors
                    yield return(new object[] { engine, @"\Gdef", "abcdef", 0, RegexOptions.None, 0 });

                    yield return(new object[] { engine, @"\Gdef", "abcdef", 3, RegexOptions.None, 1 });

                    // RightToLeft
                    yield return(new object[] { engine, @"\b\w+\b", "abc def ghi jkl", 15, RegexOptions.RightToLeft, 4 });

                    yield return(new object[] { RegexEngine.Interpreter, @"(?<=abc)\w", "abcxabcy", 8, RegexOptions.RightToLeft, 2 });

                    yield return(new object[] { engine, @"(?<=abc)\w", "abcxabcy", 7, RegexOptions.RightToLeft, 1 });
                }
            }
        }
 public async Task CharactersLowercasedOneByOne(RegexEngine engine)
 {
     using (new ThreadCultureChange("en-US"))
     {
         Assert.True((await RegexHelpers.GetRegexAsync(engine, "\uD801\uDC00", RegexOptions.IgnoreCase)).IsMatch("\uD801\uDC00"));
         Assert.True((await RegexHelpers.GetRegexAsync(engine, "\uD801\uDC00", RegexOptions.IgnoreCase)).IsMatch("abcdefg\uD801\uDC00"));
         Assert.True((await RegexHelpers.GetRegexAsync(engine, "\uD801", RegexOptions.IgnoreCase)).IsMatch("\uD801\uDC00"));
         Assert.True((await RegexHelpers.GetRegexAsync(engine, "\uDC00", RegexOptions.IgnoreCase)).IsMatch("\uD801\uDC00"));
     }
 }
Beispiel #16
0
        public void EnumerateMatches_Count(RegexEngine engine, string pattern, string input, int expectedCount)
        {
            Regex r     = RegexHelpers.GetRegexAsync(engine, pattern).GetAwaiter().GetResult();
            int   count = 0;

            foreach (ValueMatch _ in r.EnumerateMatches(input))
            {
                count++;
            }
            Assert.Equal(expectedCount, count);
        }
        public void TurkishCulture_Handling_Of_IgnoreCase_NonBacktracking()
        {
            var    turkish = new CultureInfo("tr-TR");
            string input   = "I\u0131\u0130i";
            string pattern = "[H-J][\u0131-\u0140][\u0120-\u0130][h-j]";

            Regex regex = RegexHelpers.CreateRegexInCulture(pattern, RegexOptions.IgnoreCase | RegexHelpers.RegexOptionNonBacktracking, turkish);

            // The pattern must trivially match the input because all of the letters fall in the given intervals
            // Ignoring case can only add more letters here -- not REMOVE letters
            Assert.True(regex.IsMatch(input));
        }
Beispiel #18
0
        public async Task TurkishCulture_Handling_Of_IgnoreCase(RegexEngine engine)
        {
            var    turkish = new CultureInfo("tr-TR");
            string input   = "I\u0131\u0130i";
            string pattern = "[H-J][\u0131-\u0140][\u0120-\u0130][h-j]";

            Regex regex = await RegexHelpers.GetRegexAsync(engine, pattern, RegexOptions.IgnoreCase, turkish);

            // The pattern must trivially match the input because all of the letters fall in the given intervals
            // Ignoring case can only add more letters here -- not REMOVE letters
            Assert.True(regex.IsMatch(input));
        }
Beispiel #19
0
        public async Task CharactersComparedOneByOne_AnchoredPattern(RegexEngine engine, string pattern, string input, string culture, RegexOptions options, bool expected)
        {
            // Regex compares characters one by one.  If that changes, it could impact the behavior of
            // a case like this, where these characters are not the same, but the strings compare
            // as equal with the invariant culture (and some other cultures as well).
            using (new ThreadCultureChange(culture))
            {
                Regex r = await RegexHelpers.GetRegexAsync(engine, pattern, options);

                Assert.Equal(expected, r.IsMatch(input));
            }
        }
Beispiel #20
0
        public void EnumerateMatches_ReturnsExpectedCount(RegexEngine engine, string pattern, string input, int startat, RegexOptions options, int expectedCount)
        {
            Regex r = RegexHelpers.GetRegexAsync(engine, pattern, options).GetAwaiter().GetResult();

            int count;

            count = 0;
            foreach (ValueMatch _ in r.EnumerateMatches(input, startat))
            {
                count++;
            }
            Assert.Equal(expectedCount, count);

            bool isDefaultStartAt = startat == ((options & RegexOptions.RightToLeft) != 0 ? input.Length : 0);

            if (!isDefaultStartAt)
            {
                return;
            }

            if (options == RegexOptions.None && engine == RegexEngine.Interpreter)
            {
                count = 0;
                foreach (ValueMatch _ in Regex.EnumerateMatches(input, pattern))
                {
                    count++;
                }
                Assert.Equal(expectedCount, count);
            }

            switch (engine)
            {
            case RegexEngine.Interpreter:
            case RegexEngine.Compiled:
            case RegexEngine.NonBacktracking:
                RegexOptions engineOptions = RegexHelpers.OptionsFromEngine(engine);
                count = 0;
                foreach (ValueMatch _ in Regex.EnumerateMatches(input, pattern, options | engineOptions))
                {
                    count++;
                }
                Assert.Equal(expectedCount, count);

                count = 0;
                foreach (ValueMatch _ in Regex.EnumerateMatches(input, pattern, options | engineOptions, Regex.InfiniteMatchTimeout))
                {
                    count++;
                }
                Assert.Equal(expectedCount, count);
                break;
            }
        }
Beispiel #21
0
        public async Task Test(string pattern, string input, string captures)
        {
            if (input == "NULL")
            {
                input = "";
            }

            foreach (RegexEngine engine in RegexHelpers.AvailableEngines)
            {
                if (captures == "BADBR")
                {
                    await Assert.ThrowsAnyAsync <ArgumentException>(async() => (await RegexHelpers.GetRegexAsync(engine, pattern)).IsMatch(input));

                    return;
                }

                Regex r = await RegexHelpers.GetRegexAsync(engine, pattern);

                if (captures == "NOMATCH")
                {
                    Assert.False(r.IsMatch(input));
                    return;
                }

                Match match = r.Match(input);
                Assert.True(match.Success);

                var expected = new HashSet <(int start, int end)>(
                    captures
                    .Split(new[] { '(', ')' }, StringSplitOptions.RemoveEmptyEntries)
                    .Select(s => s.Split(','))
                    .Select(s => (start: int.Parse(s[0]), end: int.Parse(s[1])))
                    .Distinct()
                    .OrderBy(c => c.start)
                    .ThenBy(c => c.end));

                var actual = new HashSet <(int start, int end)>(
                    match.Groups
                    .Cast <Group>()
                    .Select(g => (start: g.Index, end: g.Index + g.Length))
                    .Distinct()
                    .OrderBy(g => g.start)
                    .ThenBy(g => g.end));

                // The .NET implementation sometimes has extra captures beyond what the original data specifies, so we assert a subset.
                if (!expected.IsSubsetOf(actual))
                {
                    throw new Xunit.Sdk.XunitException($"Actual: {string.Join(", ", actual)}{Environment.NewLine}Expected: {string.Join(", ", expected)}");
                }
            }
        }
        public static IEnumerable <object[]> TurkishCulture_MatchesWordChar_MemberData()
        {
            foreach (RegexEngine engine in RegexHelpers.AvailableEngines)
            {
                yield return(new object[] { engine, "I\u0131\u0130i", RegexOptions.None, "I\u0131\u0130i" });

                yield return(new object[] { engine, "I\u0131\u0130i", RegexOptions.IgnoreCase, "I\u0131\u0130i" });

                if (!RegexHelpers.IsNonBacktracking(engine))
                {
                    yield return(new object[] { engine, "I\u0131\u0130i", RegexOptions.IgnoreCase | RegexOptions.ECMAScript, "" });
                }
            }
        }
        public static IEnumerable <object[]> Replace_MatchEvaluator_TestData()
        {
            foreach (RegexEngine engine in RegexHelpers.AvailableEngines)
            {
                yield return(new object[] { engine, "a", "bbbb", new MatchEvaluator(match => "uhoh"), RegexOptions.None, 4, 0, "bbbb" });

                yield return(new object[] { engine, "(Big|Small)", "Big mountain", new MatchEvaluator(MatchEvaluator1), RegexOptions.None, 12, 0, "Huge mountain" });

                yield return(new object[] { engine, "(Big|Small)", "Small village", new MatchEvaluator(MatchEvaluator1), RegexOptions.None, 13, 0, "Tiny village" });

                if ("i".ToUpper() == "I")
                {
                    yield return(new object[] { engine, "(Big|Small)", "bIG horse", new MatchEvaluator(MatchEvaluator1), RegexOptions.IgnoreCase, 9, 0, "Huge horse" });
                }

                yield return(new object[] { engine, "(Big|Small)", "sMaLl dog", new MatchEvaluator(MatchEvaluator1), RegexOptions.IgnoreCase, 9, 0, "Tiny dog" });

                yield return(new object[] { engine, ".+", "XSP_TEST_FAILURE", new MatchEvaluator(MatchEvaluator2), RegexOptions.None, 16, 0, "SUCCESS" });

                yield return(new object[] { engine, "[abcabc]", "abcabc", new MatchEvaluator(MatchEvaluator3), RegexOptions.None, 6, 0, "ABCABC" });

                yield return(new object[] { engine, "[abcabc]", "abcabc", new MatchEvaluator(MatchEvaluator3), RegexOptions.None, 3, 0, "ABCabc" });

                yield return(new object[] { engine, "[abcabc]", "abcabc", new MatchEvaluator(MatchEvaluator3), RegexOptions.None, 3, 2, "abCABc" });

                if (!RegexHelpers.IsNonBacktracking(engine))
                {
                    // Regression test:
                    // Regex treating Devanagari matra characters as matching "\b"
                    // Unicode characters in the "Mark, NonSpacing" Category, U+0902=Devanagari sign anusvara, U+0947=Devanagri vowel sign E
                    string boldInput    = "\u092f\u0939 \u0915\u0930 \u0935\u0939 \u0915\u0930\u0947\u0902 \u0939\u0948\u0964";
                    string boldExpected = "\u092f\u0939 <b>\u0915\u0930</b> \u0935\u0939 <b>\u0915\u0930\u0947\u0902</b> \u0939\u0948\u0964";
                    yield return(new object[] { engine, @"\u0915\u0930.*?\b", boldInput, new MatchEvaluator(MatchEvaluatorBold), RegexOptions.CultureInvariant | RegexOptions.Singleline, boldInput.Length, 0, boldExpected });

                    // RighToLeft
                    yield return(new object[] { engine, "a", "bbbb", new MatchEvaluator(match => "uhoh"), RegexOptions.RightToLeft, 4, 3, "bbbb" });

                    yield return(new object[] { engine, @"foo\s+", "0123456789foo4567890foo         ", new MatchEvaluator(MatchEvaluatorBar), RegexOptions.RightToLeft, 32, 32, "0123456789foo4567890bar" });

                    yield return(new object[] { engine, @"\d", "0123456789foo4567890foo         ", new MatchEvaluator(MatchEvaluatorPoundSign), RegexOptions.RightToLeft, 17, 32, "##########foo#######foo         " });

                    yield return(new object[] { engine, @"\d", "0123456789foo4567890foo         ", new MatchEvaluator(MatchEvaluatorPoundSign), RegexOptions.RightToLeft, 7, 32, "0123456789foo#######foo         " });

                    yield return(new object[] { engine, @"\d", "0123456789foo4567890foo         ", new MatchEvaluator(MatchEvaluatorPoundSign), RegexOptions.RightToLeft, 0, 32, "0123456789foo4567890foo         " });

                    yield return(new object[] { engine, @"\d", "0123456789foo4567890foo         ", new MatchEvaluator(MatchEvaluatorPoundSign), RegexOptions.RightToLeft, -1, 32, "##########foo#######foo         " });
                }
            }
        }
Beispiel #24
0
        public void EnumerateMatches(RegexEngine engine, string pattern, string input, RegexOptions options, CaptureData[] expected)
        {
            Regex regexAdvanced      = RegexHelpers.GetRegexAsync(engine, pattern, options).GetAwaiter().GetResult();
            int   count              = 0;
            ReadOnlySpan <char> span = input.AsSpan();

            foreach (ValueMatch match in regexAdvanced.EnumerateMatches(span))
            {
                Assert.Equal(expected[count].Index, match.Index);
                Assert.Equal(expected[count].Length, match.Length);
                Assert.Equal(expected[count].Value, span.Slice(match.Index, match.Length).ToString());
                count++;
            }
            Assert.Equal(expected.Length, count);
        }
        public void Match(string pattern, string input, RegexOptions options, int beginning, int length, CaptureData[] expected)
        {
            bool isDefaultStart = RegexHelpers.IsDefaultStart(input, options, beginning);
            bool isDefaultCount = RegexHelpers.IsDefaultStart(input, options, length);

            if (options == RegexOptions.None)
            {
                if (isDefaultStart && isDefaultCount)
                {
                    // Use Match(string) or Match(string, string)
                    VerifyMatch(new Regex(pattern).Match(input), true, expected);
                    VerifyMatch(Regex.Match(input, pattern), true, expected);

                    Assert.True(new Regex(pattern).IsMatch(input));
                    Assert.True(Regex.IsMatch(input, pattern));
                }
                if (beginning + length == input.Length)
                {
                    // Use Match(string, int)
                    VerifyMatch(new Regex(pattern).Match(input, beginning), true, expected);

                    Assert.True(new Regex(pattern).IsMatch(input, beginning));
                }
                else
                {
                    // Use Match(string, int, int)
                    VerifyMatch(new Regex(pattern).Match(input, beginning, length), true, expected);
                }
            }
            if (isDefaultStart && isDefaultCount)
            {
                // Use Match(string) or Match(string, string, RegexOptions)
                VerifyMatch(new Regex(pattern, options).Match(input), true, expected);
                VerifyMatch(Regex.Match(input, pattern, options), true, expected);

                Assert.True(Regex.IsMatch(input, pattern, options));
            }
            if (beginning + length == input.Length)
            {
                // Use Match(string, int)
                VerifyMatch(new Regex(pattern, options).Match(input, beginning), true, expected);
            }
            if ((options & RegexOptions.RightToLeft) == 0)
            {
                // Use Match(string, int, int)
                VerifyMatch(new Regex(pattern, options).Match(input, beginning, length), true, expected);
            }
        }
Beispiel #26
0
        public async Task UnicodeCategoriesInclusionsExpected(RegexEngine engine, string generalCategory, UnicodeCategory unicodeCategory)
        {
            Regex r;

            char[] allChars              = Enumerable.Range(0, char.MaxValue + 1).Select(i => (char)i).ToArray();
            int    expectedInCategory    = allChars.Count(c => char.GetUnicodeCategory(c) == unicodeCategory);
            int    expectedNotInCategory = allChars.Length - expectedInCategory;

            r = await RegexHelpers.GetRegexAsync(engine, @$ "\p{{{generalCategory}}}");

            Assert.Equal(expectedInCategory, r.Matches(string.Concat(allChars)).Count);

            r = await RegexHelpers.GetRegexAsync(engine, (@$ "\P{{{generalCategory}}}"));

            Assert.Equal(expectedNotInCategory, r.Matches(string.Concat(allChars)).Count);
        }
Beispiel #27
0
        private static async Task ValidateSetAsync(string regex, RegexOptions options, HashSet <char> included, HashSet <char> excluded, bool validateEveryChar = false)
        {
            Assert.True((included != null) ^ (excluded != null));

            foreach (RegexEngine engine in RegexHelpers.AvailableEngines)
            {
                Regex r = await RegexHelpers.GetRegexAsync(engine, regex, options);

                if (validateEveryChar)
                {
                    for (int i = 0; i <= char.MaxValue; i++)
                    {
                        bool actual   = r.IsMatch(((char)i).ToString());
                        bool expected = included != null?included.Contains((char)i) : !excluded.Contains((char)i);

                        if (actual != expected)
                        {
                            Fail(i);
                        }
                    }
                }
                else if (included != null)
                {
                    foreach (char c in included)
                    {
                        if (!r.IsMatch(c.ToString()))
                        {
                            Fail(c);
                        }
                    }
                }
                else
                {
                    foreach (char c in excluded)
                    {
                        if (r.IsMatch(c.ToString()))
                        {
                            Fail(c);
                        }
                    }
                }
            }

            void Fail(int c) => throw new XunitException($"Set=\"{regex}\", Options=\"{options}\", {c:X4} => '{(char)c}'");
        }
Beispiel #28
0
        public void EnumerateMatches_CheckIndex(RegexEngine engine)
        {
            const string Pattern = @"e{2}\w\b";
            const string Input   = "needing a reed";

            Regex r     = RegexHelpers.GetRegexAsync(engine, Pattern).GetAwaiter().GetResult();
            int   count = 0;

            string[]            expectedMatches = new[] { "eed" };
            int[]               expectedIndex   = new[] { 11 };
            ReadOnlySpan <char> span            = Input.AsSpan();

            foreach (ValueMatch match in r.EnumerateMatches(span))
            {
                Assert.Equal(expectedMatches[count], span.Slice(match.Index, match.Length).ToString());
                Assert.Equal(expectedIndex[count++], match.Index);
            }
        }
        public async Task Replace_MatchEvaluator_Test(RegexEngine engine, string pattern, string input, MatchEvaluator evaluator, RegexOptions options, int count, int start, string expected)
        {
            bool isDefaultStart = RegexHelpers.IsDefaultStart(input, options, start);
            bool isDefaultCount = RegexHelpers.IsDefaultCount(input, options, count);

            Regex r = await RegexHelpers.GetRegexAsync(engine, pattern, options);

            if (isDefaultStart && isDefaultCount)
            {
                Assert.Equal(expected, r.Replace(input, evaluator));
            }

            if (isDefaultStart)
            {
                Assert.Equal(expected, r.Replace(input, evaluator, count));
            }

            Assert.Equal(expected, r.Replace(input, evaluator, count, start));
        }
Beispiel #30
0
        public async Task Split(RegexEngine engine, string pattern, string input, RegexOptions options, int count, int start, string[] expected)
        {
            bool isDefaultStart = RegexHelpers.IsDefaultStart(input, options, start);
            bool isDefaultCount = RegexHelpers.IsDefaultCount(input, options, count);

            Regex r = await RegexHelpers.GetRegexAsync(engine, pattern, options);

            if (isDefaultStart && isDefaultCount)
            {
                Assert.Equal(expected, r.Split(input));
            }

            if (isDefaultStart)
            {
                Assert.Equal(expected, r.Split(input, count));
            }

            Assert.Equal(expected, r.Split(input, count, start));
        }