Skip to content

Remove regex tests blocking on async calls #100982

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 17, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Generic;
using System.Threading.Tasks;
using Xunit;

namespace System.Text.RegularExpressions.Tests
Expand Down Expand Up @@ -41,68 +42,81 @@ public void EnumerateMatches_Ctor_Invalid()

[Theory]
[MemberData(nameof(RegexHelpers.AvailableEngines_MemberData), MemberType = typeof(RegexHelpers))]
public void EnumerateMatches_Lookahead(RegexEngine engine)
public async Task EnumerateMatches_Lookahead(RegexEngine engine)
{
if (RegexHelpers.IsNonBacktracking(engine))
{
// lookaheads not supported
return;
}

const string Pattern = @"\b(?!un)\w+\b";
const string Input = "unite one unethical ethics use untie ultimate";
Test("unite one unethical ethics use untie ultimate",
await RegexHelpers.GetRegexAsync(engine, @"\b(?!un)\w+\b", RegexOptions.IgnoreCase),
["one", "ethics", "use", "ultimate"]);

Regex r = RegexHelpers.GetRegexAsync(engine, Pattern, RegexOptions.IgnoreCase).GetAwaiter().GetResult();
int count = 0;
string[] expectedMatches = ["one", "ethics", "use", "ultimate"];
ReadOnlySpan<char> span = Input.AsSpan();
foreach (ValueMatch match in r.EnumerateMatches(span))
static void Test(string input, Regex r, string[] expectedMatches)
{
Assert.Equal(expectedMatches[count++], span.Slice(match.Index, match.Length).ToString());
ReadOnlySpan<char> span = input.AsSpan();

int count = 0;
foreach (ValueMatch match in r.EnumerateMatches(span))
{
Assert.Equal(expectedMatches[count++], span.Slice(match.Index, match.Length).ToString());
}

Assert.Equal(expectedMatches.Length, count);
}
Assert.Equal(4, count);
}

[Theory]
[MemberData(nameof(RegexHelpers.AvailableEngines_MemberData), MemberType = typeof(RegexHelpers))]
public void EnumerateMatches_Lookbehind(RegexEngine engine)
public async Task EnumerateMatches_Lookbehind(RegexEngine engine)
{
if (RegexHelpers.IsNonBacktracking(engine))
{
// lookbehinds not supported
return;
}

const string Pattern = @"(?<=\b20)\d{2}\b";
const string Input = "2010 1999 1861 2140 2009";
Test("2010 1999 1861 2140 2009",
await RegexHelpers.GetRegexAsync(engine, @"(?<=\b20)\d{2}\b", RegexOptions.IgnoreCase),
["10", "09"]);

Regex r = RegexHelpers.GetRegexAsync(engine, Pattern, RegexOptions.IgnoreCase).GetAwaiter().GetResult();
int count = 0;
string[] expectedMatches = ["10", "09"];
ReadOnlySpan<char> span = Input.AsSpan();
foreach (ValueMatch match in r.EnumerateMatches(span))
static void Test(string input, Regex r, string[] expectedMatches)
{
Assert.Equal(expectedMatches[count++], span.Slice(match.Index, match.Length).ToString());
ReadOnlySpan<char> span = input.AsSpan();

int count = 0;
foreach (ValueMatch match in r.EnumerateMatches(span))
{
Assert.Equal(expectedMatches[count++], span.Slice(match.Index, match.Length).ToString());
}

Assert.Equal(expectedMatches.Length, count);
}
Assert.Equal(2, count);
}

[Theory]
[MemberData(nameof(RegexHelpers.AvailableEngines_MemberData), MemberType = typeof(RegexHelpers))]
public void EnumerateMatches_CheckIndex(RegexEngine engine)
public async Task 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 = ["eed"];
int[] expectedIndex = [11];
ReadOnlySpan<char> span = Input.AsSpan();
foreach (ValueMatch match in r.EnumerateMatches(span))
Test("needing a reed",
await RegexHelpers.GetRegexAsync(engine, @"e{2}\w\b"),
["eed"],
[11]);

static void Test(string input, Regex r, string[] expectedMatches, int[] expectedIndex)
{
Assert.Equal(expectedMatches[count], span.Slice(match.Index, match.Length).ToString());
Assert.Equal(expectedIndex[count++], match.Index);
ReadOnlySpan<char> span = input.AsSpan();

int count = 0;
foreach (ValueMatch match in r.EnumerateMatches(span))
{
Assert.Equal(expectedMatches[count], span.Slice(match.Index, match.Length).ToString());
Assert.Equal(expectedIndex[count], match.Index);

count++;
}
}
}
}
Expand All @@ -111,91 +125,102 @@ public partial class RegexMultipleMatchTests
{
[Theory]
[MemberData(nameof(Matches_TestData))]
public void EnumerateMatches(RegexEngine engine, string pattern, string input, RegexOptions options, CaptureData[] expected)
public async Task 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))
Test(input, expected, await RegexHelpers.GetRegexAsync(engine, pattern, options));

static void Test(string input, CaptureData[] expected, Regex regexAdvanced)
{
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++;
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);
}
Assert.Equal(expected.Length, count);
}
}

public partial class RegexMatchTests
{
[Theory]
[MemberData(nameof(Match_Count_TestData))]
public void EnumerateMatches_Count(RegexEngine engine, string pattern, string input, int expectedCount)
public async Task 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))
Test(input, expectedCount, await RegexHelpers.GetRegexAsync(engine, pattern));

static void Test(string input, int expectedCount, Regex r)
{
count++;
int count = 0;
foreach (ValueMatch _ in r.EnumerateMatches(input))
{
count++;
}

Assert.Equal(expectedCount, count);
}
Assert.Equal(expectedCount, count);
}
}

public partial class RegexCountTests
{
[Theory]
[MemberData(nameof(Count_ReturnsExpectedCount_TestData))]
public void EnumerateMatches_ReturnsExpectedCount(RegexEngine engine, string pattern, string input, int startat, RegexOptions options, int expectedCount)
public async Task 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;
}
Test(engine, pattern, input, startat, options, expectedCount, await RegexHelpers.GetRegexAsync(engine, pattern, options));

if (options == RegexOptions.None && engine == RegexEngine.Interpreter)
static void Test(RegexEngine engine, string pattern, string input, int startat, RegexOptions options, int expectedCount, Regex r)
{
count = 0;
foreach (ValueMatch _ in Regex.EnumerateMatches(input, pattern))
int count = 0;
foreach (ValueMatch _ in r.EnumerateMatches(input, startat))
{
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);
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, options | engineOptions, Regex.InfiniteMatchTimeout))
foreach (ValueMatch _ in Regex.EnumerateMatches(input, pattern))
{
count++;
}
Assert.Equal(expectedCount, count);
break;
}

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;
}
}
}
}
Expand Down
Loading