Skip to content

Commit b3e69ec

Browse files
committed
merged into review-tests
1 parent a77b171 commit b3e69ec

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+6222
-2
lines changed

.github/workflows/dotnet.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,4 @@ jobs:
2626
- name: Build
2727
run: dotnet build --no-restore
2828
- name: Test
29-
run: dotnet test --no-build --verbosity normal
29+
run: dotnet test --no-build --verbosity normal --filter FullyQualifiedName!~SpanExtensions.Tests.Fuzzing

SpanExtensions.sln

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ VisualStudioVersion = 17.5.33627.172
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SpanExtensions", "src\SpanExtensions.csproj", "{75DE5AFD-663E-415D-9B95-6BC513BD4A07}"
77
EndProject
8+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTests", "tests\unit-tests\UnitTests.csproj", "{B48A0293-A7FF-4E39-8F8D-57B6F824D70F}"
9+
EndProject
10+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FuzzingTests", "tests\fuzzing\FuzzingTests.csproj", "{63CA0F05-0019-4ED3-AD94-45A5CE4D338F}"
11+
EndProject
812
Global
913
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1014
Debug|Any CPU = Debug|Any CPU
@@ -15,6 +19,14 @@ Global
1519
{75DE5AFD-663E-415D-9B95-6BC513BD4A07}.Debug|Any CPU.Build.0 = Debug|Any CPU
1620
{75DE5AFD-663E-415D-9B95-6BC513BD4A07}.Release|Any CPU.ActiveCfg = Release|Any CPU
1721
{75DE5AFD-663E-415D-9B95-6BC513BD4A07}.Release|Any CPU.Build.0 = Release|Any CPU
22+
{B48A0293-A7FF-4E39-8F8D-57B6F824D70F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
23+
{B48A0293-A7FF-4E39-8F8D-57B6F824D70F}.Debug|Any CPU.Build.0 = Debug|Any CPU
24+
{B48A0293-A7FF-4E39-8F8D-57B6F824D70F}.Release|Any CPU.ActiveCfg = Release|Any CPU
25+
{B48A0293-A7FF-4E39-8F8D-57B6F824D70F}.Release|Any CPU.Build.0 = Release|Any CPU
26+
{63CA0F05-0019-4ED3-AD94-45A5CE4D338F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27+
{63CA0F05-0019-4ED3-AD94-45A5CE4D338F}.Debug|Any CPU.Build.0 = Debug|Any CPU
28+
{63CA0F05-0019-4ED3-AD94-45A5CE4D338F}.Release|Any CPU.ActiveCfg = Release|Any CPU
29+
{63CA0F05-0019-4ED3-AD94-45A5CE4D338F}.Release|Any CPU.Build.0 = Release|Any CPU
1830
EndGlobalSection
1931
GlobalSection(SolutionProperties) = preSolution
2032
HideSolutionNode = FALSE

src/SpanExtensions.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<PropertyGroup>
44
<TargetFrameworks>net8.0;net7.0;net6.0;net5.0;netstandard2.1</TargetFrameworks>
5-
<ImplicitUsings>disable</ImplicitUsings>
5+
<ImplicitUsings>disable</ImplicitUsings>
66
<Nullable>enable</Nullable>
77
<GenerateDocumentationFile>True</GenerateDocumentationFile>
88
<Platforms>AnyCPU</Platforms>

tests/fuzzing/FuzzingTests.csproj

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFrameworks>net8.0;net7.0;net6.0;net5.0</TargetFrameworks>
5+
<LangVersion>latest</LangVersion>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
9+
<IsPackable>false</IsPackable>
10+
<IsTestProject>true</IsTestProject>
11+
12+
<RootNamespace>SpanExtensions.Tests.Fuzzing</RootNamespace>
13+
</PropertyGroup>
14+
15+
<ItemGroup>
16+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
17+
<PackageReference Include="xunit" Version="2.7.0" />
18+
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
19+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
20+
<PrivateAssets>all</PrivateAssets>
21+
</PackageReference>
22+
<PackageReference Include="coverlet.collector" Version="6.0.1">
23+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
24+
<PrivateAssets>all</PrivateAssets>
25+
</PackageReference>
26+
</ItemGroup>
27+
28+
<ItemGroup>
29+
<ProjectReference Include="..\..\src\SpanExtensions.csproj" />
30+
</ItemGroup>
31+
32+
</Project>

tests/fuzzing/GlobalUsings.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
global using Xunit;

tests/fuzzing/TestHelper.cs

Lines changed: 812 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using static SpanExtensions.Tests.Fuzzing.TestHelper;
2+
3+
namespace SpanExtensions.Tests.Fuzzing
4+
{
5+
public static partial class ReadOnlySpanLinqTests
6+
{
7+
public sealed class Sum
8+
{
9+
// todo
10+
}
11+
}
12+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using static SpanExtensions.Tests.Fuzzing.TestHelper;
2+
3+
namespace SpanExtensions.Tests.Fuzzing
4+
{
5+
public static partial class ReadOnlySpanSplitTests
6+
{
7+
static readonly IEnumerable<StringSplitOptions> stringSplitOptions = GetAllStringSplitOptions();
8+
static readonly CountExceedingBehaviour[] countExceedingBehaviours = (CountExceedingBehaviour[])Enum.GetValues(typeof(CountExceedingBehaviour));
9+
}
10+
}
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
using static SpanExtensions.Tests.Fuzzing.TestHelper;
2+
3+
namespace SpanExtensions.Tests.Fuzzing
4+
{
5+
public static partial class ReadOnlySpanSplitTests
6+
{
7+
public static class Split
8+
{
9+
public static TheoryData<int, int, int, int> SplitData(int iterations)
10+
{
11+
const int minValue = 0;
12+
const int maxValue = 100;
13+
14+
TheoryData<int, int, int, int> data = new();
15+
16+
foreach(int length in new MultiplierRange(1, 1000, 10).And([0]))
17+
{
18+
data.Add(iterations, length, minValue, maxValue);
19+
}
20+
21+
return data;
22+
}
23+
24+
public sealed class SplitWithoutParameters
25+
{
26+
public static readonly TheoryData<int, int, int, int> _SplitData = SplitData(250000);
27+
28+
[Theory]
29+
[MemberData(nameof(_SplitData))]
30+
public void Fuzz(int iterations, int length, int minValue, int maxValue)
31+
{
32+
static void AssertOptions<T>(T[] array, T delimiter) where T : IEquatable<T>
33+
{
34+
AssertMethodResults(
35+
expected: Split(array, delimiter),
36+
actual: array.AsReadOnlySpan().Split(delimiter).ToSystemEnumerable(),
37+
source: array,
38+
method: nameof(ReadOnlySpanExtensions.Split),
39+
args: ("delimiter", delimiter)
40+
);
41+
}
42+
43+
for(int iteration = 0; iteration < iterations; iteration++)
44+
{
45+
int[] integerArray = GenerateRandomIntegers(length, minValue, maxValue).ToArray();
46+
int integerDelimiter = integerArray.RandomElementOrDefault(0);
47+
AssertOptions(integerArray, integerDelimiter);
48+
AssertOptions(integerArray, maxValue);
49+
50+
char[] charArray = GenerateRandomString(length).ToCharArray();
51+
char charDelimiter = charArray.RandomElementOrDefault('0');
52+
const char charMissingDelimiter = 'ა';
53+
AssertOptions(charArray, charDelimiter);
54+
AssertOptions(charArray, charMissingDelimiter);
55+
}
56+
}
57+
}
58+
59+
public sealed class SplitWithCount
60+
{
61+
public static readonly TheoryData<int, int, int, int> _SplitData = SplitData(25000);
62+
63+
[Theory]
64+
[MemberData(nameof(_SplitData))]
65+
public void Fuzz(int iterations, int length, int minValue, int maxValue)
66+
{
67+
static void AssertOptions<T>(T[] array, T delimiter, int count, CountExceedingBehaviour countExceedingBehaviour) where T : IEquatable<T>
68+
{
69+
AssertMethodResults(
70+
expected: Split(array, delimiter, count, countExceedingBehaviour),
71+
actual: array.AsReadOnlySpan().Split(delimiter, count, countExceedingBehaviour).ToSystemEnumerable(),
72+
source: array,
73+
method: nameof(ReadOnlySpanExtensions.Split),
74+
args: [("delimiter", delimiter), ("count", count), ("countExceedingBehaviour", countExceedingBehaviour)]
75+
);
76+
}
77+
78+
for(int iteration = 0; iteration < iterations; iteration++)
79+
{
80+
int[] integerArray = GenerateRandomIntegers(length, minValue, maxValue).ToArray();
81+
int integerDelimiter = integerArray.RandomElementOrDefault(0);
82+
int countDelimiters = integerArray.Count(integerDelimiter);
83+
foreach(CountExceedingBehaviour countExceedingBehaviour in countExceedingBehaviours)
84+
{
85+
AssertOptions(integerArray, integerDelimiter, 0, countExceedingBehaviour);
86+
AssertOptions(integerArray, integerDelimiter, 1, countExceedingBehaviour);
87+
if(countDelimiters - 1 > 1) AssertOptions(integerArray, integerDelimiter, countDelimiters - 1, countExceedingBehaviour);
88+
if(countDelimiters > 1) AssertOptions(integerArray, integerDelimiter, countDelimiters, countExceedingBehaviour);
89+
AssertOptions(integerArray, integerDelimiter, countDelimiters + 2, countExceedingBehaviour);
90+
AssertOptions(integerArray, maxValue, 0, countExceedingBehaviour);
91+
AssertOptions(integerArray, maxValue, 1, countExceedingBehaviour);
92+
AssertOptions(integerArray, maxValue, 2, countExceedingBehaviour);
93+
}
94+
95+
char[] charArray = GenerateRandomString(length).ToCharArray();
96+
char charDelimiter = charArray.RandomElementOrDefault('0');
97+
const char charMissingDelimiter = 'ა';
98+
countDelimiters = charArray.Count(charDelimiter);
99+
foreach(CountExceedingBehaviour countExceedingBehaviour in countExceedingBehaviours)
100+
{
101+
AssertOptions(charArray, charDelimiter, 0, countExceedingBehaviour);
102+
AssertOptions(charArray, charDelimiter, 1, countExceedingBehaviour);
103+
if(countDelimiters - 1 > 1) AssertOptions(charArray, charDelimiter, countDelimiters - 1, countExceedingBehaviour);
104+
if(countDelimiters > 1) AssertOptions(charArray, charDelimiter, countDelimiters, countExceedingBehaviour);
105+
AssertOptions(charArray, charDelimiter, countDelimiters + 2, countExceedingBehaviour);
106+
AssertOptions(charArray, charMissingDelimiter, 0, countExceedingBehaviour);
107+
AssertOptions(charArray, charMissingDelimiter, 1, countExceedingBehaviour);
108+
AssertOptions(charArray, charMissingDelimiter, 2, countExceedingBehaviour);
109+
}
110+
}
111+
}
112+
}
113+
}
114+
}
115+
}
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
using static SpanExtensions.Tests.Fuzzing.TestHelper;
2+
3+
namespace SpanExtensions.Tests.Fuzzing
4+
{
5+
public static partial class ReadOnlySpanSplitTests
6+
{
7+
public static class SplitAny
8+
{
9+
public static TheoryData<int, int, int, int, int, float> SplitAnyData(int iterations)
10+
{
11+
const int minValue = 0;
12+
const int maxValue = 100;
13+
14+
TheoryData<int, int, int, int, int, float> data = new();
15+
16+
foreach(int length in new MultiplierRange(1, 1000, 10).And([0]))
17+
{
18+
foreach(int delimitersLength in ((IEnumerable<int>)[0, 1, 5, 25, 50]).Where(x => x <= length * 3))
19+
{
20+
foreach(float delimitersOccurencePart in GetParts(delimitersLength))
21+
{
22+
data.Add(iterations, length, minValue, maxValue, delimitersLength, delimitersOccurencePart);
23+
}
24+
}
25+
}
26+
27+
return data;
28+
29+
static IEnumerable<float> GetParts(int delimitersLength)
30+
{
31+
return delimitersLength switch
32+
{
33+
0 => [0f],
34+
1 => [0f, 1f],
35+
_ => [0f, 0.5f, 1f]
36+
};
37+
}
38+
}
39+
40+
public sealed class SplitAnyWithoutParameters
41+
{
42+
public static readonly TheoryData<int, int, int, int, int, float> _SplitAnyData = SplitAnyData(11000);
43+
44+
[Theory]
45+
[MemberData(nameof(_SplitAnyData))]
46+
public void Fuzz(int iterations, int length, int minValue, int maxValue, int delimitersLength, float delimitersOccurencePart)
47+
{
48+
static void AssertOptions<T>(T[] array, T[] delimiters) where T : IEquatable<T>
49+
{
50+
AssertMethodResults(
51+
expected: SplitAny(array, delimiters),
52+
actual: array.AsReadOnlySpan().SplitAny(delimiters).ToSystemEnumerable(),
53+
source: array,
54+
method: nameof(ReadOnlySpanExtensions.SplitAny),
55+
args: ("delimiters", delimiters)
56+
);
57+
}
58+
59+
for(int iteration = 0; iteration < iterations; iteration++)
60+
{
61+
int[] integerArray = GenerateRandomIntegers(length, minValue, maxValue).ToArray();
62+
int[] integerDelimiters = Enumerable.Range(0, delimitersLength).Select(i =>
63+
i < delimitersLength * delimitersOccurencePart ? integerArray.RandomElementOrDefault()
64+
: maxValue + i
65+
).ToArray();
66+
AssertOptions(integerArray, integerDelimiters);
67+
68+
char[] charArray = GenerateRandomString(length).ToCharArray();
69+
char[] charDelimiters = Enumerable.Range(0, delimitersLength).Select(i =>
70+
i < delimitersLength * delimitersOccurencePart ? charArray.RandomElementOrDefault()
71+
: (char)('ა' + i)
72+
).ToArray();
73+
AssertOptions(charArray, charDelimiters);
74+
}
75+
}
76+
}
77+
78+
public sealed class SplitAnyWithCount
79+
{
80+
public static readonly TheoryData<int, int, int, int, int, float> _SplitAnyData = SplitAnyData(2000);
81+
82+
[Theory]
83+
[MemberData(nameof(_SplitAnyData))]
84+
public void Fuzz(int iterations, int length, int minValue, int maxValue, int delimitersLength, float delimitersOccurencePart)
85+
{
86+
static void AssertOptions<T>(T[] array, T[] delimiters, int count, CountExceedingBehaviour countExceedingBehaviour) where T : IEquatable<T>
87+
{
88+
AssertMethodResults(
89+
expected: SplitAny(array, delimiters, count, countExceedingBehaviour),
90+
actual: array.AsReadOnlySpan().SplitAny(delimiters, count, countExceedingBehaviour).ToSystemEnumerable(),
91+
source: array,
92+
method: nameof(ReadOnlySpanExtensions.SplitAny),
93+
args: [("delimiters", delimiters), ("count", count), ("countExceedingBehaviour", countExceedingBehaviour)]
94+
);
95+
}
96+
97+
for(int iteration = 0; iteration < iterations; iteration++)
98+
{
99+
int[] integerArray = GenerateRandomIntegers(length, minValue, maxValue).ToArray();
100+
int[] integerDelimiters = Enumerable.Range(0, delimitersLength).Select(i =>
101+
i < delimitersLength * delimitersOccurencePart ? integerArray.RandomElementOrDefault()
102+
: maxValue + i
103+
).ToArray();
104+
int countDelimiters = integerArray.Count(integerDelimiters);
105+
foreach(CountExceedingBehaviour countExceedingBehaviour in countExceedingBehaviours)
106+
{
107+
AssertOptions(integerArray, integerDelimiters, 0, countExceedingBehaviour);
108+
AssertOptions(integerArray, integerDelimiters, 1, countExceedingBehaviour);
109+
if(countDelimiters - 1 > 1) AssertOptions(integerArray, integerDelimiters, countDelimiters, countExceedingBehaviour);
110+
if(countDelimiters > 1) AssertOptions(integerArray, integerDelimiters, countDelimiters, countExceedingBehaviour);
111+
AssertOptions(integerArray, integerDelimiters, countDelimiters + 2, countExceedingBehaviour);
112+
}
113+
114+
char[] charArray = GenerateRandomString(length).ToCharArray();
115+
char[] charDelimiters = Enumerable.Range(0, delimitersLength).Select(i =>
116+
i < delimitersLength * delimitersOccurencePart ? charArray.RandomElementOrDefault()
117+
: (char)('ა' + i)
118+
).ToArray();
119+
countDelimiters = charArray.Count(charDelimiters);
120+
foreach(CountExceedingBehaviour countExceedingBehaviour in countExceedingBehaviours)
121+
{
122+
AssertOptions(charArray, charDelimiters, 0, countExceedingBehaviour);
123+
AssertOptions(charArray, charDelimiters, 0, countExceedingBehaviour);
124+
if(countDelimiters - 1 > 1) AssertOptions(charArray, charDelimiters, countDelimiters - 1, countExceedingBehaviour);
125+
if(countDelimiters > 1) AssertOptions(charArray, charDelimiters, countDelimiters, countExceedingBehaviour);
126+
AssertOptions(charArray, charDelimiters, countDelimiters + 2, countExceedingBehaviour);
127+
}
128+
}
129+
}
130+
}
131+
}
132+
}
133+
}

0 commit comments

Comments
 (0)