diff --git a/Ix.NET/Source/System.Linq.Async.Tests/System.Linq.Async.Tests.csproj b/Ix.NET/Source/System.Linq.Async.Tests/System.Linq.Async.Tests.csproj
index d264248e5d..dcbadd0b35 100644
--- a/Ix.NET/Source/System.Linq.Async.Tests/System.Linq.Async.Tests.csproj
+++ b/Ix.NET/Source/System.Linq.Async.Tests/System.Linq.Async.Tests.csproj
@@ -19,6 +19,11 @@
True
Average.Generated.tt
+
+ True
+ True
+ GroupBy.Generated.tt
+
True
True
@@ -51,6 +56,10 @@
TextTemplatingFileGenerator
Average.Generated.cs
+
+ TextTemplatingFileGenerator
+ GroupBy.Generated.cs
+
TextTemplatingFileGenerator
MinMax.Generated.cs
@@ -71,6 +80,11 @@
True
Average.Generated.tt
+
+ True
+ True
+ GroupBy.Generated.tt
+
True
True
diff --git a/Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/GroupBy.Generated.cs b/Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/GroupBy.Generated.cs
new file mode 100644
index 0000000000..c68f39ef23
--- /dev/null
+++ b/Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/GroupBy.Generated.cs
@@ -0,0 +1,591 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Xunit;
+
+namespace Tests
+{
+ partial class GroupBy
+ {
+ [Fact]
+ public void KeySelector_Sync_Null()
+ {
+ Assert.Throws(() => AsyncEnumerable.GroupBy(default(IAsyncEnumerable), (int x) => x));
+ Assert.Throws(() => AsyncEnumerable.GroupBy(Return42, default(Func)));
+ }
+
+ [Fact]
+ public async Task KeySelector_Sync_All()
+ {
+ var methodsS = typeof(Enumerable).GetMethods().AsEnumerable();
+ var methodsA = methodsS.ToAsyncEnumerable();
+
+ var resS = methodsS.GroupBy(m => m.Name);
+ var resA = methodsA.GroupBy(m => m.Name);
+
+ await Groups_AssertCore(resS, resA);
+ }
+
+ [Fact]
+ public void KeySelector_Sync_Comparer_Null()
+ {
+ Assert.Throws(() => AsyncEnumerable.GroupBy(default(IAsyncEnumerable), (int x) => x, EqualityComparer.Default));
+ Assert.Throws(() => AsyncEnumerable.GroupBy(Return42, default(Func), EqualityComparer.Default));
+ }
+
+ [Fact]
+ public async Task KeySelector_Sync_Comparer_All()
+ {
+ var methodsS = typeof(Enumerable).GetMethods().AsEnumerable();
+ var methodsA = methodsS.ToAsyncEnumerable();
+
+ var eq = new StringPrefixEqualityComparer(1);
+
+ var resS = methodsS.GroupBy(m => m.Name, eq);
+ var resA = methodsA.GroupBy(m => m.Name, eq);
+
+ await Groups_AssertCore(resS, resA);
+ }
+
+ [Fact]
+ public void KeySelector_ElementSelector_Sync_Null()
+ {
+ Assert.Throws(() => AsyncEnumerable.GroupBy(default(IAsyncEnumerable), (int x) => x, (int x) => x));
+ Assert.Throws(() => AsyncEnumerable.GroupBy(Return42, default(Func), (int x) => x));
+ Assert.Throws(() => AsyncEnumerable.GroupBy(Return42, (int x) => x, default(Func)));
+ }
+
+ [Fact]
+ public async Task KeySelector_ElementSelector_Sync_All()
+ {
+ var methodsS = typeof(Enumerable).GetMethods().AsEnumerable();
+ var methodsA = methodsS.ToAsyncEnumerable();
+
+ var resS = methodsS.GroupBy(m => m.Name, m => m.Name.ToUpper());
+ var resA = methodsA.GroupBy(m => m.Name, m => m.Name.ToUpper());
+
+ await Groups_AssertCore(resS, resA);
+ }
+
+ [Fact]
+ public void KeySelector_ElementSelector_Sync_Comparer_Null()
+ {
+ Assert.Throws(() => AsyncEnumerable.GroupBy(default(IAsyncEnumerable), (int x) => x, (int x) => x, EqualityComparer.Default));
+ Assert.Throws(() => AsyncEnumerable.GroupBy(Return42, default(Func), (int x) => x, EqualityComparer.Default));
+ Assert.Throws(() => AsyncEnumerable.GroupBy(default(IAsyncEnumerable), (int x) => x, default(Func), EqualityComparer.Default));
+ }
+
+ [Fact]
+ public async Task KeySelector_ElementSelector_Sync_Comparer_All()
+ {
+ var methodsS = typeof(Enumerable).GetMethods().AsEnumerable();
+ var methodsA = methodsS.ToAsyncEnumerable();
+
+ var eq = new StringPrefixEqualityComparer(1);
+
+ var resS = methodsS.GroupBy(m => m.Name, m => m.Name.ToUpper(), eq);
+ var resA = methodsA.GroupBy(m => m.Name, m => m.Name.ToUpper(), eq);
+
+ await Groups_AssertCore(resS, resA);
+ }
+
+ [Fact]
+ public void KeySelector_ResultSelector_Sync_Null()
+ {
+ Assert.Throws(() => AsyncEnumerable.GroupBy(default(IAsyncEnumerable), (int x) => x, (k, g) => 0));
+ Assert.Throws(() => AsyncEnumerable.GroupBy(Return42, default(Func), (k, g) => 0));
+ Assert.Throws(() => AsyncEnumerable.GroupBy(Return42, (int x) => x, default(Func, int>)));
+ }
+
+ [Fact]
+ public async Task KeySelector_ResultSelector_Sync_All()
+ {
+ var methodsS = typeof(Enumerable).GetMethods().AsEnumerable();
+ var methodsA = methodsS.ToAsyncEnumerable();
+
+ var resS = methodsS.GroupBy(m => m.Name, (k, g) => k + " - " + g.Count());
+ var resA = methodsA.GroupBy(m => m.Name, (k, g) => k + " - " + g.CountAsync().Result);
+
+ await Group_Result_AssertCore(resS, resA);
+ }
+
+ [Fact]
+ public void KeySelector_ResultSelector_Sync_Comparer_Null()
+ {
+ Assert.Throws(() => AsyncEnumerable.GroupBy(default(IAsyncEnumerable), (int x) => x, (k, g) => 0, EqualityComparer.Default));
+ Assert.Throws(() => AsyncEnumerable.GroupBy(Return42, default(Func), (k, g) => 0, EqualityComparer.Default));
+ Assert.Throws(() => AsyncEnumerable.GroupBy(default(IAsyncEnumerable), (int x) => x, default(Func, int>), EqualityComparer.Default));
+ }
+
+ [Fact]
+ public async Task KeySelector_ResultSelector_Sync_Comparer_All()
+ {
+ var methodsS = typeof(Enumerable).GetMethods().AsEnumerable();
+ var methodsA = methodsS.ToAsyncEnumerable();
+
+ var eq = new StringPrefixEqualityComparer(1);
+
+ var resS = methodsS.GroupBy(m => m.Name, (k, g) => k + " - " + g.Count(), eq);
+ var resA = methodsA.GroupBy(m => m.Name, (k, g) => k + " - " + g.CountAsync().Result, eq);
+
+ await Group_Result_AssertCore(resS, resA);
+ }
+
+ [Fact]
+ public void KeySelector_ElementSelector_ResultSelector_Sync_Null()
+ {
+ Assert.Throws(() => AsyncEnumerable.GroupBy(default(IAsyncEnumerable), (int x) => x, (int x) => x, (k, g) => 0));
+ Assert.Throws(() => AsyncEnumerable.GroupBy(Return42, default(Func), (int x) => x, (k, g) => 0));
+ Assert.Throws(() => AsyncEnumerable.GroupBy(Return42, (int x) => x, default(Func), (k, g) => 0));
+ Assert.Throws(() => AsyncEnumerable.GroupBy(Return42, (int x) => x, (int x) => x, default(Func, int>)));
+ }
+
+ [Fact]
+ public async Task KeySelector_ElementSelector_ResultSelector_Sync_All()
+ {
+ var methodsS = typeof(Enumerable).GetMethods().AsEnumerable();
+ var methodsA = methodsS.ToAsyncEnumerable();
+
+ var resS = methodsS.GroupBy(m => m.Name, m => m.Name.ToUpper(), (k, g) => k + " - " + g.Count());
+ var resA = methodsA.GroupBy(m => m.Name, m => m.Name.ToUpper(), (k, g) => k + " - " + g.CountAsync().Result);
+
+ await Group_Result_AssertCore(resS, resA);
+ }
+
+ [Fact]
+ public void KeySelector_ElementSelector_ResultSelector_Sync_Comparer_Null()
+ {
+ Assert.Throws(() => AsyncEnumerable.GroupBy(default(IAsyncEnumerable), (int x) => x, (int x) => x, (k, g) => 0, EqualityComparer.Default));
+ Assert.Throws(() => AsyncEnumerable.GroupBy(Return42, default(Func), (int x) => x, (k, g) => 0, EqualityComparer.Default));
+ Assert.Throws(() => AsyncEnumerable.GroupBy(default(IAsyncEnumerable), (int x) => x, default(Func), (k, g) => 0, EqualityComparer.Default));
+ Assert.Throws(() => AsyncEnumerable.GroupBy(default(IAsyncEnumerable), (int x) => x, (int x) => x, default(Func, int>), EqualityComparer.Default));
+ }
+
+ [Fact]
+ public async Task KeySelector_ElementSelector_ResultSelector_Sync_Comparer_All()
+ {
+ var methodsS = typeof(Enumerable).GetMethods().AsEnumerable();
+ var methodsA = methodsS.ToAsyncEnumerable();
+
+ var eq = new StringPrefixEqualityComparer(1);
+
+ var resS = methodsS.GroupBy(m => m.Name, m => m.Name.ToUpper(), (k, g) => k + " - " + g.Count(), eq);
+ var resA = methodsA.GroupBy(m => m.Name, m => m.Name.ToUpper(), (k, g) => k + " - " + g.CountAsync().Result, eq);
+
+ await Group_Result_AssertCore(resS, resA);
+ }
+
+ [Fact]
+ public void KeySelector_Async_Null()
+ {
+ Assert.Throws(() => AsyncEnumerable.GroupBy(default(IAsyncEnumerable), (int x) => new ValueTask(x)));
+ Assert.Throws(() => AsyncEnumerable.GroupBy(Return42, default(Func>)));
+ }
+
+ [Fact]
+ public async Task KeySelector_Async_All()
+ {
+ var methodsS = typeof(Enumerable).GetMethods().AsEnumerable();
+ var methodsA = methodsS.ToAsyncEnumerable();
+
+ var resS = methodsS.GroupBy(m => m.Name);
+ var resA = methodsA.GroupBy(m => new ValueTask(m.Name));
+
+ await Groups_AssertCore(resS, resA);
+ }
+
+ [Fact]
+ public void KeySelector_Async_Comparer_Null()
+ {
+ Assert.Throws(() => AsyncEnumerable.GroupBy(default(IAsyncEnumerable), (int x) => new ValueTask(x), EqualityComparer.Default));
+ Assert.Throws(() => AsyncEnumerable.GroupBy(Return42, default(Func>), EqualityComparer.Default));
+ }
+
+ [Fact]
+ public async Task KeySelector_Async_Comparer_All()
+ {
+ var methodsS = typeof(Enumerable).GetMethods().AsEnumerable();
+ var methodsA = methodsS.ToAsyncEnumerable();
+
+ var eq = new StringPrefixEqualityComparer(1);
+
+ var resS = methodsS.GroupBy(m => m.Name, eq);
+ var resA = methodsA.GroupBy(m => new ValueTask(m.Name), eq);
+
+ await Groups_AssertCore(resS, resA);
+ }
+
+ [Fact]
+ public void KeySelector_ElementSelector_Async_Null()
+ {
+ Assert.Throws(() => AsyncEnumerable.GroupBy(default(IAsyncEnumerable), (int x) => new ValueTask(x), (int x) => new ValueTask(x)));
+ Assert.Throws(() => AsyncEnumerable.GroupBy(Return42, default(Func>), (int x) => new ValueTask(x)));
+ Assert.Throws(() => AsyncEnumerable.GroupBy(Return42, (int x) => new ValueTask(x), default(Func>)));
+ }
+
+ [Fact]
+ public async Task KeySelector_ElementSelector_Async_All()
+ {
+ var methodsS = typeof(Enumerable).GetMethods().AsEnumerable();
+ var methodsA = methodsS.ToAsyncEnumerable();
+
+ var resS = methodsS.GroupBy(m => m.Name, m => m.Name.ToUpper());
+ var resA = methodsA.GroupBy(m => new ValueTask(m.Name), m => new ValueTask(m.Name.ToUpper()));
+
+ await Groups_AssertCore(resS, resA);
+ }
+
+ [Fact]
+ public void KeySelector_ElementSelector_Async_Comparer_Null()
+ {
+ Assert.Throws(() => AsyncEnumerable.GroupBy(default(IAsyncEnumerable), (int x) => new ValueTask(x), (int x) => new ValueTask(x), EqualityComparer.Default));
+ Assert.Throws(() => AsyncEnumerable.GroupBy(Return42, default(Func>), (int x) => new ValueTask(x), EqualityComparer.Default));
+ Assert.Throws(() => AsyncEnumerable.GroupBy(default(IAsyncEnumerable), (int x) => new ValueTask(x), default(Func>), EqualityComparer.Default));
+ }
+
+ [Fact]
+ public async Task KeySelector_ElementSelector_Async_Comparer_All()
+ {
+ var methodsS = typeof(Enumerable).GetMethods().AsEnumerable();
+ var methodsA = methodsS.ToAsyncEnumerable();
+
+ var eq = new StringPrefixEqualityComparer(1);
+
+ var resS = methodsS.GroupBy(m => m.Name, m => m.Name.ToUpper(), eq);
+ var resA = methodsA.GroupBy(m => new ValueTask(m.Name), m => new ValueTask(m.Name.ToUpper()), eq);
+
+ await Groups_AssertCore(resS, resA);
+ }
+
+ [Fact]
+ public void KeySelector_ResultSelector_Async_Null()
+ {
+ Assert.Throws(() => AsyncEnumerable.GroupBy(default(IAsyncEnumerable), (int x) => new ValueTask(x), (k, g) => new ValueTask(0)));
+ Assert.Throws(() => AsyncEnumerable.GroupBy(Return42, default(Func>), (k, g) => new ValueTask(0)));
+ Assert.Throws(() => AsyncEnumerable.GroupBy(Return42, (int x) => new ValueTask(x), default(Func, ValueTask>)));
+ }
+
+ [Fact]
+ public async Task KeySelector_ResultSelector_Async_All()
+ {
+ var methodsS = typeof(Enumerable).GetMethods().AsEnumerable();
+ var methodsA = methodsS.ToAsyncEnumerable();
+
+ var resS = methodsS.GroupBy(m => m.Name, (k, g) => k + " - " + g.Count());
+ var resA = methodsA.GroupBy(m => new ValueTask(m.Name), async (k, g) => k + " - " + await g.CountAsync()); // REVIEW: Ambiguity
+
+ await Group_Result_AssertCore(resS, resA);
+ }
+
+ [Fact]
+ public void KeySelector_ResultSelector_Async_Comparer_Null()
+ {
+ Assert.Throws(() => AsyncEnumerable.GroupBy(default(IAsyncEnumerable), (int x) => new ValueTask(x), (k, g) => new ValueTask(0), EqualityComparer.Default));
+ Assert.Throws(() => AsyncEnumerable.GroupBy(Return42, default(Func>), (k, g) => new ValueTask(0), EqualityComparer.Default));
+ Assert.Throws(() => AsyncEnumerable.GroupBy(default(IAsyncEnumerable), (int x) => new ValueTask(x), default(Func, ValueTask>), EqualityComparer.Default));
+ }
+
+ [Fact]
+ public async Task KeySelector_ResultSelector_Async_Comparer_All()
+ {
+ var methodsS = typeof(Enumerable).GetMethods().AsEnumerable();
+ var methodsA = methodsS.ToAsyncEnumerable();
+
+ var eq = new StringPrefixEqualityComparer(1);
+
+ var resS = methodsS.GroupBy(m => m.Name, (k, g) => k + " - " + g.Count(), eq);
+ var resA = methodsA.GroupBy(m => new ValueTask(m.Name), async (k, g) => k + " - " + await g.CountAsync(), eq);
+
+ await Group_Result_AssertCore(resS, resA);
+ }
+
+ [Fact]
+ public void KeySelector_ElementSelector_ResultSelector_Async_Null()
+ {
+ Assert.Throws(() => AsyncEnumerable.GroupBy(default(IAsyncEnumerable), (int x) => new ValueTask(x), (int x) => new ValueTask(x), (k, g) => new ValueTask(0)));
+ Assert.Throws(() => AsyncEnumerable.GroupBy(Return42, default(Func>), (int x) => new ValueTask(x), (k, g) => new ValueTask(0)));
+ Assert.Throws(() => AsyncEnumerable.GroupBy(Return42, (int x) => new ValueTask(x), default(Func>), (k, g) => new ValueTask(0)));
+ Assert.Throws(() => AsyncEnumerable.GroupBy(Return42, (int x) => new ValueTask(x), (int x) => new ValueTask(x), default(Func, ValueTask>)));
+ }
+
+ [Fact]
+ public async Task KeySelector_ElementSelector_ResultSelector_Async_All()
+ {
+ var methodsS = typeof(Enumerable).GetMethods().AsEnumerable();
+ var methodsA = methodsS.ToAsyncEnumerable();
+
+ var resS = methodsS.GroupBy(m => m.Name, m => m.Name.ToUpper(), (k, g) => k + " - " + g.Count());
+ var resA = methodsA.GroupBy(m => new ValueTask(m.Name), m => new ValueTask(m.Name.ToUpper()), async (k, g) => k + " - " + await g.CountAsync()); // REVIEW: Ambiguity
+
+ await Group_Result_AssertCore(resS, resA);
+ }
+
+ [Fact]
+ public void KeySelector_ElementSelector_ResultSelector_Async_Comparer_Null()
+ {
+ Assert.Throws(() => AsyncEnumerable.GroupBy(default(IAsyncEnumerable), (int x) => new ValueTask(x), (int x) => new ValueTask(x), (k, g) => new ValueTask(0), EqualityComparer.Default));
+ Assert.Throws(() => AsyncEnumerable.GroupBy(Return42, default(Func>), (int x) => new ValueTask(x), (k, g) => new ValueTask(0), EqualityComparer.Default));
+ Assert.Throws(() => AsyncEnumerable.GroupBy(default(IAsyncEnumerable), (int x) => new ValueTask(x), default(Func>), (k, g) => new ValueTask(0), EqualityComparer.Default));
+ Assert.Throws(() => AsyncEnumerable.GroupBy(default(IAsyncEnumerable), (int x) => new ValueTask(x), (int x) => new ValueTask(x), default(Func, ValueTask>), EqualityComparer.Default));
+ }
+
+ [Fact]
+ public async Task KeySelector_ElementSelector_ResultSelector_Async_Comparer_All()
+ {
+ var methodsS = typeof(Enumerable).GetMethods().AsEnumerable();
+ var methodsA = methodsS.ToAsyncEnumerable();
+
+ var eq = new StringPrefixEqualityComparer(1);
+
+ var resS = methodsS.GroupBy(m => m.Name, m => m.Name.ToUpper(), (k, g) => k + " - " + g.Count(), eq);
+ var resA = methodsA.GroupBy(m => new ValueTask(m.Name), m => new ValueTask(m.Name.ToUpper()), async (k, g) => k + " - " + await g.CountAsync(), eq);
+
+ await Group_Result_AssertCore(resS, resA);
+ }
+
+#if !NO_DEEP_CANCELLATION
+ [Fact]
+ public void KeySelector_Async_Cancel_Null()
+ {
+ Assert.Throws(() => AsyncEnumerable.GroupBy(default(IAsyncEnumerable), (int x, CancellationToken ct) => new ValueTask(x)));
+ Assert.Throws(() => AsyncEnumerable.GroupBy(Return42, default(Func>)));
+ }
+
+ [Fact]
+ public async Task KeySelector_Async_Cancel_All()
+ {
+ var methodsS = typeof(Enumerable).GetMethods().AsEnumerable();
+ var methodsA = methodsS.ToAsyncEnumerable();
+
+ var resS = methodsS.GroupBy(m => m.Name);
+ var resA = methodsA.GroupBy((m, ct) => new ValueTask(m.Name));
+
+ await Groups_AssertCore(resS, resA);
+ }
+
+ [Fact]
+ public void KeySelector_Async_Cancel_Comparer_Null()
+ {
+ Assert.Throws(() => AsyncEnumerable.GroupBy(default(IAsyncEnumerable), (int x, CancellationToken ct) => new ValueTask(x), EqualityComparer.Default));
+ Assert.Throws(() => AsyncEnumerable.GroupBy(Return42, default(Func>), EqualityComparer.Default));
+ }
+
+ [Fact]
+ public async Task KeySelector_Async_Cancel_Comparer_All()
+ {
+ var methodsS = typeof(Enumerable).GetMethods().AsEnumerable();
+ var methodsA = methodsS.ToAsyncEnumerable();
+
+ var eq = new StringPrefixEqualityComparer(1);
+
+ var resS = methodsS.GroupBy(m => m.Name, eq);
+ var resA = methodsA.GroupBy((m, ct) => new ValueTask(m.Name), eq);
+
+ await Groups_AssertCore(resS, resA);
+ }
+
+ [Fact]
+ public void KeySelector_ElementSelector_Async_Cancel_Null()
+ {
+ Assert.Throws(() => AsyncEnumerable.GroupBy(default(IAsyncEnumerable), (int x, CancellationToken ct) => new ValueTask(x), (int x, CancellationToken ct) => new ValueTask