Skip to content

Commit

Permalink
Merge pull request #35 from YuHima03/feat/ref-struct-implement-interf…
Browse files Browse the repository at this point in the history
…aces

Feat: CollectionBuilder{T} implement interface
  • Loading branch information
YuHima03 authored Nov 28, 2024
2 parents e29abb7 + ab34f90 commit 46385ea
Show file tree
Hide file tree
Showing 4 changed files with 326 additions and 12 deletions.
38 changes: 38 additions & 0 deletions .github/workflows/dotnet-manual.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# This workflow will build a .NET project
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net

name: .NET Build Test (manual)

on:
workflow_dispatch:
inputs:
target_framework:
type: choice
required: true
options:
- "net6.0"
- "net7.0"
- "net8.0"
- "net9.0"

jobs:
build_and_test:
name: Build & Test (${{ github.event.inputs.target_framework }})
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: |
6.0.x
7.0.x
8.0.x
9.0.x
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build --no-restore -f ${{ github.event.inputs.target_framework }}
- name: Test
run: dotnet test --no-build --verbosity normal -f ${{ github.event.inputs.target_framework }}
142 changes: 131 additions & 11 deletions src/Yuh.Collections.Tests/CollectionBuilderTest.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
using Yuh.Collections.Tests.Helpers;
using Yuh.Collections.Tests.DataProviders;
using Yuh.Collections.Tests.Helpers;

namespace Yuh.Collections.Tests
{
public class CollectionBuilderTest()
{
public static TheoryData<int[][]> TestIntEnumerable => [
[.. Enumerable.Repeat<int[]>([], 256)],
[.. Enumerable.Range(0, 1024).Select<int, int[]>(i => [i])],
[.. Enumerable.Repeat(Enumerable.Range(0, 128).ToArray(), 512)]
];

[Theory]
[MemberData(nameof(TestIntEnumerable))]
[ClassData(typeof(SegmentedIntArrayData))]
public void AppendTest(int[][] items)
{
using CollectionBuilder<int> builder = new();
Expand All @@ -29,7 +24,7 @@ public void AppendTest(int[][] items)
}

[Theory]
[MemberData(nameof(TestIntEnumerable))]
[ClassData(typeof(SegmentedIntArrayData))]
public void AppendIEnumerableRangeTest(int[][] items)
{
using CollectionBuilder<int> builder = new();
Expand All @@ -44,7 +39,7 @@ public void AppendIEnumerableRangeTest(int[][] items)
}

[Theory]
[MemberData(nameof(TestIntEnumerable))]
[ClassData(typeof(SegmentedIntArrayData))]
public void AppendICollectionRangeTest(int[][] items)
{
using CollectionBuilder<int> builder = new();
Expand All @@ -59,7 +54,7 @@ public void AppendICollectionRangeTest(int[][] items)
}

[Theory]
[MemberData(nameof(TestIntEnumerable))]
[ClassData(typeof(SegmentedIntArrayData))]
public void AppendSpanRangeTest(int[][] items)
{
using CollectionBuilder<int> builder = new();
Expand All @@ -72,5 +67,130 @@ public void AppendSpanRangeTest(int[][] items)

Assert.Equal(expected, builder.ToArray());
}

[Theory]
[ClassData(typeof(IntArrayData))]
public void EnumeratorTest(int[] array)
{
CollectionBuilder<int> builder = new();
builder.AppendRange(array.AsSpan());

using var enumerator = builder.GetEnumerator();
for (int i = 0; i < array.Length; i++)
{
Assert.True(enumerator.MoveNext());
Assert.Equal(array[i], enumerator.Current);
}
Assert.False(enumerator.MoveNext());
}

#if NET7_0_OR_GREATER
public static TheoryData<int[]> NonEmptyIntArrayData => new(IntArrayData.DataSource.Where(Enumerable.Any));

[Theory]
[MemberData(nameof(NonEmptyIntArrayData))]
public void EnumeratorAfterCollectionChangedTest(int[] array)
{
using CollectionBuilder<int> builder = new();
builder.AppendRange(array.AsSpan());

using var enumerator = builder.GetEnumerator();
try
{
builder.AppendRange(array.AsSpan());
enumerator.MoveNext();
}
catch (InvalidOperationException)
{
return;
}
Assert.Fail($"MoveNext method of {typeof(CollectionBuilder<>.Enumerator)} structure doesn't throw {nameof(InvalidOperationException)}.");
}

[Theory]
[ClassData(typeof(IntArrayData))]
public void EnumeratorAfterDisposedTest(int[] array)
{
using CollectionBuilder<int> builder = new();
builder.AppendRange(array.AsSpan());

var exceptionThrown = false;
var enumerator = builder.GetEnumerator();
enumerator.Dispose();

try
{
enumerator.MoveNext();
}
catch (Exception)
{
exceptionThrown = true;
}
if (!exceptionThrown)
{
Assert.Fail($"MoveNext method of {typeof(CollectionBuilder<>.Enumerator)} structure doesn't throw an exception after disposed.");
}

exceptionThrown = false;
enumerator = builder.GetEnumerator();
enumerator.Dispose();
try
{
enumerator.Reset();
}
catch (Exception)
{
exceptionThrown = true;
}
if (!exceptionThrown)
{
Assert.Fail($"Reset method of {typeof(CollectionBuilder<>.Enumerator)} structure doesn't throw an exception after disposed.");
}
}
#endif

#if NET9_0_OR_GREATER
[Theory]
[ClassData(typeof(IntArrayData))]
public void IGenericEnumerableTest(int[] array)
{
CollectionBuilder<int> builder = new();
builder.AppendRange(array.AsSpan());

Test(array, builder);

static void Test<T, U>(U[] expected, T actually) where T : IEnumerable<U>, allows ref struct
{
using var enumerator = actually.GetEnumerator();
for (int i = 0; i < expected.Length; i++)
{
Assert.True(enumerator.MoveNext());
Assert.Equal(expected[i], enumerator.Current);
}
Assert.False(enumerator.MoveNext());
}
}

[Theory]
[ClassData(typeof(IntArrayData))]
public void IEnumerableTest(int[] array)
{
CollectionBuilder<int> builder = new();
builder.AppendRange(array.AsSpan());

Test(array, builder);

static void Test<T, U>(U[] expected, T actually) where T : IEnumerable<U>, allows ref struct
{
var enumerator = actually.GetEnumerator();
for (int i = 0; i < expected.Length; i++)
{
Assert.True(enumerator.MoveNext());
Assert.Equal(expected[i], enumerator.Current);
}
Assert.False(enumerator.MoveNext());
}
}
#endif
}
}
14 changes: 14 additions & 0 deletions src/Yuh.Collections.Tests/DataProviders/IntArrayData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System.Collections;
using Yuh.Collections.Tests.Helpers;

namespace Yuh.Collections.Tests.DataProviders
{
public class IntArrayData : IEnumerable<object[]>
{
public readonly static int[][] DataSource = [.. SegmentedIntArrayData.DataSource.Select(arrays => arrays.Flatten().ToArray())];

public IEnumerator<object[]> GetEnumerator() => DataSource.Select<int[], object[]>(x => [x]).GetEnumerator();

IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
}
Loading

0 comments on commit 46385ea

Please sign in to comment.