Skip to content

Commit 26e8a24

Browse files
committed
(fixup 2391757) SplitAny
1 parent ae109a5 commit 26e8a24

File tree

4 files changed

+113
-55
lines changed

4 files changed

+113
-55
lines changed

tests/fuzzing/TestHelper.cs

Lines changed: 44 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
using System.Diagnostics;
44
using System.Globalization;
55
using System.Text;
6-
using System.Text.RegularExpressions;
76

87
namespace SpanExtensions.Tests.Fuzzing
98
{
@@ -371,6 +370,17 @@ public static void AssertMethodResults<T>(IEnumerable<IEnumerable<T>> expected,
371370
}
372371
}
373372

373+
/// <summary>
374+
/// Creates a new span over the target array.
375+
/// </summary>
376+
/// <typeparam name="T">The array type.</typeparam>
377+
/// <param name="source">The target array.</param>
378+
/// <returns>A <see cref="ReadOnlySpan{T}"/> over <paramref name="source"/>.</returns>
379+
public static ReadOnlySpan<T> AsReadOnlySpan<T>(this T[] source)
380+
{
381+
return source.AsSpan();
382+
}
383+
374384
#if !NET8_0_OR_GREATER
375385
/// <summary>Counts the number of times the specified <paramref name="value"/> occurs in the <paramref name="span"/>.</summary>
376386
/// <typeparam name="T">The element type of the span.</typeparam>
@@ -401,17 +411,26 @@ public static int Count<T>(this Span<T> span, T value) where T : IEquatable<T>
401411
}
402412
#endif
403413

404-
/// <summary>
405-
/// Creates a new span over the target array.
406-
/// </summary>
407-
/// <typeparam name="T">The array type.</typeparam>
408-
/// <param name="source">The target array.</param>
409-
/// <returns>A <see cref="ReadOnlySpan{T}"/> over <paramref name="source"/>.</returns>
410-
public static ReadOnlySpan<T> AsReadOnlySpan<T>(this T[] source)
414+
/// <summary>Counts the number of times the specified <paramref name="value"/> occurs in the <paramref name="array"/>.</summary>
415+
/// <typeparam name="T">The element type of the array.</typeparam>
416+
/// <param name="array">The array to search.</param>
417+
/// <param name="value">The value for which to search.</param>
418+
/// <returns>The number of times <paramref name="value"/> was found in the <paramref name="array"/>.</returns>
419+
public static int Count<T>(this T[] array, T value) where T : IEquatable<T>
411420
{
412-
return source.AsSpan();
421+
return array.AsSpan().Count(value);
413422
}
414423

424+
/// <summary>Counts the number of times the specified <paramref name="value"/> occurs in the <paramref name="string"/>.</summary>
425+
/// <param name="string">The string to search.</param>
426+
/// <param name="value">The value for which to search.</param>
427+
/// <returns>The number of times <paramref name="value"/> was found in the <paramref name="string"/>.</returns>
428+
public static int Count(this string @string, char value)
429+
{
430+
return @string.AsSpan().Count(value);
431+
}
432+
433+
#if !NET8_0_OR_GREATER
415434
/// <summary>Counts the number of times any of the specified <paramref name="values"/> occur in the <paramref name="span"/>.</summary>
416435
/// <typeparam name="T">The element type of the span.</typeparam>
417436
/// <param name="span">The span to search.</param>
@@ -439,20 +458,25 @@ public static int Count<T>(this Span<T> span, ReadOnlySpan<T> values) where T :
439458
{
440459
return Count((ReadOnlySpan<T>)span, values);
441460
}
461+
#endif
442462

443-
/// <summary>
444-
/// Counts the number of times any of the specified <paramref name="substring"/> occur in the <paramref name="string"/>.
445-
/// </summary>
463+
/// <summary>Counts the number of times any of the specified <paramref name="values"/> occur in the <paramref name="array"/>.</summary>
464+
/// <typeparam name="T">The element type of the array.</typeparam>
465+
/// <param name="array">The array to search.</param>
466+
/// <param name="values">The values for which to search.</param>
467+
/// <returns>The number of times any of the <paramref name="values"/> was found in the <paramref name="array"/>.</returns>
468+
public static int Count<T>(this T[] array, ReadOnlySpan<T> values) where T : IEquatable<T>
469+
{
470+
return array.AsSpan().Count(values);
471+
}
472+
473+
/// <summary>Counts the number of times any of the specified <paramref name="values"/> occur in the <paramref name="string"/>.</summary>
446474
/// <param name="string">The string to search.</param>
447-
/// <param name="substring">The substring for which to search.</param>
448-
/// <returns>The number of times any of the <paramref name="substring"/> was found in the <paramref name="string"/>.</returns>
449-
public static int Count(this string @string, string substring)
475+
/// <param name="values">The values for which to search.</param>
476+
/// <returns>The number of times any of the <paramref name="values"/> was found in the <paramref name="string"/>.</returns>
477+
public static int Count(this string @string, ReadOnlySpan<char> values)
450478
{
451-
#if NET7_0_OR_GREATER
452-
return Regex.Count(@string, substring);
453-
#else
454-
return Regex.Matches(@string, substring).Count;
455-
#endif
479+
return @string.AsSpan().Count(values);
456480
}
457481

458482
/// <summary>

tests/fuzzing/Tests/ReadOnlySpan/Split/Split.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ static void AssertOptions<T>(T[] array, T delimiter, int count, CountExceedingBe
7878
{
7979
int[] integerArray = GenerateRandomIntegers(length, minValue, maxValue).ToArray();
8080
int integerDelimiter = integerArray.RandomElementOrDefault(0);
81-
int countDelimiters = integerArray.AsSpan().Count(integerDelimiter);
81+
int countDelimiters = integerArray.Count(integerDelimiter);
8282
foreach(CountExceedingBehaviour countExceedingBehaviour in countExceedingBehaviours)
8383
{
8484
AssertOptions(integerArray, integerDelimiter, 0, countExceedingBehaviour);
@@ -94,7 +94,7 @@ static void AssertOptions<T>(T[] array, T delimiter, int count, CountExceedingBe
9494
char[] charArray = GenerateRandomString(length).ToCharArray();
9595
char charDelimiter = charArray.RandomElementOrDefault('0');
9696
const char charMissingDelimiter = 'ა';
97-
countDelimiters = charArray.AsSpan().Count(charDelimiter);
97+
countDelimiters = charArray.Count(charDelimiter);
9898
foreach(CountExceedingBehaviour countExceedingBehaviour in countExceedingBehaviours)
9999
{
100100
AssertOptions(charArray, charDelimiter, 0, countExceedingBehaviour);
@@ -184,10 +184,12 @@ static void AssertOptions<T>(T[] array, T[] delimiter, int count, CountExceeding
184184
);
185185
}
186186

187+
int[] randomIntDelimiterArray = GenerateRandomIntegers(delimiterLength, minValue, maxValue).ToArray();
188+
char[] randomcharDelimiterArray = GenerateRandomString(delimiterLength).ToCharArray();
187189
for(int iteration = 0; iteration < iterations; iteration++)
188190
{
189191
int[] integerArray = GenerateRandomIntegers(length, minValue, maxValue).ToArray();
190-
int[] integerSequenceDelimiter = integerArray.RandomSubsequenceOrDefault(delimiterLength, GenerateRandomIntegers(delimiterLength, minValue, maxValue).ToArray());
192+
int[] integerSequenceDelimiter = integerArray.RandomSubsequenceOrDefault(delimiterLength, randomIntDelimiterArray);
191193
int[] integerSequenceMissingDelimiter = integerSequenceDelimiter.ReplaceRandomElement(maxValue);
192194
int countDelimiters = integerArray.CountSubsequence(integerSequenceDelimiter);
193195
foreach(CountExceedingBehaviour countExceedingBehaviour in countExceedingBehaviours)
@@ -203,7 +205,7 @@ static void AssertOptions<T>(T[] array, T[] delimiter, int count, CountExceeding
203205
}
204206

205207
char[] charArray = GenerateRandomString(length).ToCharArray();
206-
char[] charSequenceDelimiter = charArray.RandomSubsequenceOrDefault(delimiterLength, GenerateRandomString(delimiterLength).ToCharArray());
208+
char[] charSequenceDelimiter = charArray.RandomSubsequenceOrDefault(delimiterLength, randomcharDelimiterArray);
207209
char[] charSequenceMissingDelimiter = charSequenceDelimiter.ReplaceRandomElement('ა');
208210
countDelimiters = charArray.CountSubsequence(charSequenceDelimiter);
209211
foreach(CountExceedingBehaviour countExceedingBehaviour in countExceedingBehaviours)

tests/fuzzing/Tests/ReadOnlySpan/Split/SplitAny.cs

Lines changed: 62 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,29 @@ public static partial class ReadOnlySpanSplitTests
66
{
77
public sealed class SplitAny
88
{
9-
[Fact]
10-
public void FuzzSplitAny()
9+
public static TheoryData<int, int, int, int, int, float> SplitAnyData()
10+
{
11+
const int iterations = 10000;
12+
13+
TheoryData<int, int, int, int, int, float> data = new();
14+
15+
foreach(int length in new MultiplierRange(1, 1000, 10).And([0]))
16+
{
17+
foreach(int delimitersLength in ((IEnumerable<int>)[0, 1, 5, 25, 50]).Where(x => x <= length * 3))
18+
{
19+
foreach(float delimitersOccurencePart in (IEnumerable<float>)(delimitersLength > 1 ? [0f, 0.5f, 1f] : [0f, 1f]))
20+
{
21+
data.Add(iterations, length, minValue, maxValue, delimitersLength, delimitersOccurencePart);
22+
}
23+
}
24+
}
25+
26+
return data;
27+
}
28+
29+
[Theory]
30+
[MemberData(nameof(SplitAnyData))]
31+
public void FuzzSplitAny(int iterations, int length, int minValue, int maxValue, int delimitersLength, float delimitersOccurencePart)
1132
{
1233
static void AssertOptions<T>(T[] array, T[] delimiters) where T : IEquatable<T>
1334
{
@@ -20,21 +41,27 @@ static void AssertOptions<T>(T[] array, T[] delimiters) where T : IEquatable<T>
2041
);
2142
}
2243

23-
int[] integerArray = GenerateRandomIntegers(count, minValue, maxValue).ToArray();
24-
int[] integerDelimiters = Enumerable.Range(0, 5).Select(_ => integerArray[random.Next(integerArray.Length)]).ToArray();
25-
int[] integerMissingDelimiters = Enumerable.Range(0, 5).Select(i => maxValue + i).ToArray();
26-
AssertOptions(integerArray, integerDelimiters);
27-
AssertOptions(integerArray, integerMissingDelimiters);
44+
for(int iteration = 0; iteration < iterations; iteration++)
45+
{
46+
int[] integerArray = GenerateRandomIntegers(length, minValue, maxValue).ToArray();
47+
int[] integerDelimiters = Enumerable.Range(0, delimitersLength).Select(i =>
48+
i < delimitersLength * delimitersOccurencePart ? integerArray.RandomElementOrDefault()
49+
: maxValue + i
50+
).ToArray();
51+
AssertOptions(integerArray, integerDelimiters);
2852

29-
char[] charArray = GenerateRandomString(length).ToCharArray();
30-
char[] charDelimiters = Enumerable.Range(0, 5).Select(_ => charArray[random.Next(charArray.Length)]).ToArray();
31-
char[] charMissingDelimiters = Enumerable.Range(0, 5).Select(i => (char)('ა' + i)).ToArray();
32-
AssertOptions(charArray, charDelimiters);
33-
AssertOptions(charArray, charMissingDelimiters);
53+
char[] charArray = GenerateRandomString(length).ToCharArray();
54+
char[] charDelimiters = Enumerable.Range(0, delimitersLength).Select(i =>
55+
i < delimitersLength * delimitersOccurencePart ? charArray.RandomElementOrDefault()
56+
: (char)('ა' + i)
57+
).ToArray();
58+
AssertOptions(charArray, charDelimiters);
59+
}
3460
}
3561

36-
[Fact]
37-
public void FuzzSplitAnyWithCount()
62+
[Theory]
63+
[MemberData(nameof(SplitAnyData))]
64+
public void FuzzSplitAnyWithCount(int iterations, int length, int minValue, int maxValue, int delimitersLength, float delimitersOccurencePart)
3865
{
3966
static void AssertOptions<T>(T[] array, T[] delimiters, int count, CountExceedingBehaviour countExceedingBehaviour) where T : IEquatable<T>
4067
{
@@ -47,24 +74,29 @@ static void AssertOptions<T>(T[] array, T[] delimiters, int count, CountExceedin
4774
);
4875
}
4976

50-
int[] integerArray = GenerateRandomIntegers(count, minValue, maxValue).ToArray();
51-
int[] integerDelimiters = Enumerable.Range(0, 5).Select(_ => integerArray[random.Next(integerArray.Length)]).ToArray();
52-
int[] integerMissingDelimiters = Enumerable.Range(0, 5).Select(i => maxValue + i).ToArray();
53-
int countDelimiters = integerArray.AsSpan().Count(integerDelimiters);
54-
foreach(CountExceedingBehaviour countExceedingBehaviour in countExceedingBehaviours)
77+
for(int iteration = 0; iteration < iterations; iteration++)
5578
{
56-
AssertOptions(integerArray, integerDelimiters, countDelimiters, countExceedingBehaviour);
57-
AssertOptions(integerArray, integerMissingDelimiters, countDelimiters, countExceedingBehaviour);
58-
}
79+
int[] integerArray = GenerateRandomIntegers(count, minValue, maxValue).ToArray();
80+
int[] integerDelimiters = Enumerable.Range(0, delimitersLength).Select(i =>
81+
i < delimitersLength * delimitersOccurencePart ? integerArray.RandomElementOrDefault()
82+
: maxValue + i
83+
).ToArray();
84+
int countDelimiters = integerArray.Count(integerDelimiters);
85+
foreach(CountExceedingBehaviour countExceedingBehaviour in countExceedingBehaviours)
86+
{
87+
AssertOptions(integerArray, integerDelimiters, countDelimiters, countExceedingBehaviour);
88+
}
5989

60-
char[] charArray = GenerateRandomString(length).ToCharArray();
61-
char[] charDelimiters = Enumerable.Range(0, 5).Select(_ => charArray[random.Next(charArray.Length)]).ToArray();
62-
char[] cahrMissingDelimiters = Enumerable.Range(0, 5).Select(i => (char)('ა' + i)).ToArray();
63-
countDelimiters = charArray.AsSpan().Count(charDelimiters);
64-
foreach(CountExceedingBehaviour countExceedingBehaviour in countExceedingBehaviours)
65-
{
66-
AssertOptions(charArray, charDelimiters, countDelimiters, countExceedingBehaviour);
67-
AssertOptions(charArray, cahrMissingDelimiters, countDelimiters, countExceedingBehaviour);
90+
char[] charArray = GenerateRandomString(length).ToCharArray();
91+
char[] charDelimiters = Enumerable.Range(0, delimitersLength).Select(i =>
92+
i < delimitersLength * delimitersOccurencePart ? charArray.RandomElementOrDefault()
93+
: (char)('ა' + i)
94+
).ToArray();
95+
countDelimiters = charArray.Count(charDelimiters);
96+
foreach(CountExceedingBehaviour countExceedingBehaviour in countExceedingBehaviours)
97+
{
98+
AssertOptions(charArray, charDelimiters, countDelimiters, countExceedingBehaviour);
99+
}
68100
}
69101
}
70102
}

tests/fuzzing/Tests/ReadOnlySpan/Split/SplitString.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ static void AssertOptions(string @string, char delimiter, int count, StringSplit
6767
{
6868
string @string = GenerateRandomString(length);
6969
char charDelimiter = @string.RandomElementOrDefault('0');
70-
int countDelimiters = @string.AsSpan().Count(charDelimiter);
70+
int countDelimiters = @string.Count(charDelimiter);
7171
foreach(StringSplitOptions options in stringSplitOptions)
7272
{
7373
foreach(CountExceedingBehaviour countExceedingBehaviour in countExceedingBehaviours)

0 commit comments

Comments
 (0)