Procházet zdrojové kódy

Moving GroupBy tests.

Bart De Smet před 8 roky
rodič
revize
cb92b5af3f

+ 0 - 879
Ix.NET/Source/System.Interactive.Async.Tests/AsyncTests.Single.cs

@@ -291,885 +291,6 @@ namespace Tests
             AssertThrows<Exception>(() => xs.ForEachAsync((x, i) => { throw ex; }).Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
         }
 
-        [Fact]
-        public void GroupBy_Null()
-        {
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int>(null, x => x));
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int>(AsyncEnumerable.Return(42), default(Func<int, int>)));
-
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int>(null, x => x, EqualityComparer<int>.Default));
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int>(AsyncEnumerable.Return(42), default(Func<int, int>), EqualityComparer<int>.Default));
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int>(AsyncEnumerable.Return(42), x => x, default(IEqualityComparer<int>)));
-
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(null, x => x, x => x));
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(AsyncEnumerable.Return(42), default(Func<int, int>), x => x));
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(AsyncEnumerable.Return(42), x => x, default(Func<int, int>)));
-
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(null, x => x, x => x, EqualityComparer<int>.Default));
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(AsyncEnumerable.Return(42), default(Func<int, int>), x => x, EqualityComparer<int>.Default));
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(AsyncEnumerable.Return(42), x => x, default(Func<int, int>), EqualityComparer<int>.Default));
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(AsyncEnumerable.Return(42), x => x, x => x, default(IEqualityComparer<int>)));
-
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(null, x => x, (x, ys) => x));
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(AsyncEnumerable.Return(42), default(Func<int, int>), (x, ys) => x));
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(AsyncEnumerable.Return(42), x => x, default(Func<int, IAsyncEnumerable<int>, int>)));
-
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(null, x => x, (x, ys) => x, EqualityComparer<int>.Default));
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(AsyncEnumerable.Return(42), default(Func<int, int>), (x, ys) => x, EqualityComparer<int>.Default));
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(AsyncEnumerable.Return(42), x => x, default(Func<int, IAsyncEnumerable<int>, int>), EqualityComparer<int>.Default));
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(AsyncEnumerable.Return(42), x => x, (x, ys) => x, default(IEqualityComparer<int>)));
-
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int, int>(null, x => x, x => x, (x, ys) => x));
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int, int>(AsyncEnumerable.Return(42), default(Func<int, int>), x => x, (x, ys) => x));
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int, int>(AsyncEnumerable.Return(42), x => x, default(Func<int, int>), (x, ys) => x));
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int, int>(AsyncEnumerable.Return(42), x => x, x => x, default(Func<int, IAsyncEnumerable<int>, int>)));
-
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int, int>(null, x => x, x => x, (x, ys) => x, EqualityComparer<int>.Default));
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int, int>(AsyncEnumerable.Return(42), default(Func<int, int>), x => x, (x, ys) => x, EqualityComparer<int>.Default));
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int, int>(AsyncEnumerable.Return(42), x => x, default(Func<int, int>), (x, ys) => x, EqualityComparer<int>.Default));
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int, int>(AsyncEnumerable.Return(42), x => x, x => x, default(Func<int, IAsyncEnumerable<int>, int>), EqualityComparer<int>.Default));
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int, int>(AsyncEnumerable.Return(42), x => x, x => x, (x, ys) => x, default(IEqualityComparer<int>)));
-        }
-
-        [Fact]
-        public void GroupBy1()
-        {
-            var xs = new[] {
-                new { Name = "Bart", Age = 27 },
-                new { Name = "John", Age = 62 },
-                new { Name = "Eric", Age = 27 },
-                new { Name = "Lisa", Age = 14 },
-                new { Name = "Brad", Age = 27 },
-                new { Name = "Lisa", Age = 23 },
-                new { Name = "Eric", Age = 42 },
-            };
-
-            var ys = xs.ToAsyncEnumerable();
-
-            var res = ys.GroupBy(x => x.Age / 10);
-
-            var e = res.GetAsyncEnumerator();
-
-            Assert.True(e.MoveNextAsync().Result);
-            Assert.Equal(2, e.Current.Key);
-            var g1 = e.Current.GetAsyncEnumerator();
-            HasNext(g1, xs[0]);
-            HasNext(g1, xs[2]);
-            HasNext(g1, xs[4]);
-            HasNext(g1, xs[5]);
-            NoNext(g1);
-
-            Assert.True(e.MoveNextAsync().Result);
-            Assert.Equal(6, e.Current.Key);
-            var g2 = e.Current.GetAsyncEnumerator();
-            HasNext(g2, xs[1]);
-            NoNext(g2);
-
-            Assert.True(e.MoveNextAsync().Result);
-            Assert.Equal(1, e.Current.Key);
-            var g3 = e.Current.GetAsyncEnumerator();
-            HasNext(g3, xs[3]);
-            NoNext(g3);
-
-            Assert.True(e.MoveNextAsync().Result);
-            Assert.Equal(4, e.Current.Key);
-            var g4 = e.Current.GetAsyncEnumerator();
-            HasNext(g4, xs[6]);
-            NoNext(g4);
-
-            NoNext(e);
-        }
-
-        [Fact]
-        public void GroupBy2()
-        {
-            var xs = new[] {
-                new { Name = "Bart", Age = 27 },
-                new { Name = "John", Age = 62 },
-                new { Name = "Eric", Age = 27 },
-                new { Name = "Lisa", Age = 14 },
-                new { Name = "Brad", Age = 27 },
-                new { Name = "Lisa", Age = 23 },
-                new { Name = "Eric", Age = 42 },
-            };
-
-            var ys = xs.ToAsyncEnumerable();
-
-            var res = ys.GroupBy(x => x.Age / 10);
-
-            var e = res.GetAsyncEnumerator();
-
-            Assert.True(e.MoveNextAsync().Result);
-            var g1 = e.Current;
-            Assert.Equal(2, g1.Key);
-
-            Assert.True(e.MoveNextAsync().Result);
-            var g2 = e.Current;
-            Assert.Equal(6, g2.Key);
-
-            Assert.True(e.MoveNextAsync().Result);
-            var g3 = e.Current;
-            Assert.Equal(1, g3.Key);
-
-            Assert.True(e.MoveNextAsync().Result);
-            var g4 = e.Current;
-            Assert.Equal(4, g4.Key);
-
-            NoNext(e);
-
-            var g1e = g1.GetAsyncEnumerator();
-            HasNext(g1e, xs[0]);
-            HasNext(g1e, xs[2]);
-            HasNext(g1e, xs[4]);
-            HasNext(g1e, xs[5]);
-            NoNext(g1e);
-
-            var g2e = g2.GetAsyncEnumerator();
-            HasNext(g2e, xs[1]);
-            NoNext(g2e);
-
-            var g3e = g3.GetAsyncEnumerator();
-            HasNext(g3e, xs[3]);
-            NoNext(g3e);
-
-            var g4e = g4.GetAsyncEnumerator();
-            HasNext(g4e, xs[6]);
-            NoNext(g4e);
-        }
-
-        [Fact]
-        public void GroupBy3()
-        {
-            var xs = AsyncEnumerable.Empty<int>();
-            var ys = xs.GroupBy(x => x);
-
-            var e = ys.GetAsyncEnumerator();
-            NoNext(e);
-        }
-
-        [Fact]
-        public void GroupBy4()
-        {
-            var ex = new Exception("Bang!");
-            var xs = AsyncEnumerable.Throw<int>(ex);
-            var ys = xs.GroupBy(x => x);
-
-            var e = ys.GetAsyncEnumerator();
-            AssertThrows(() => e.MoveNextAsync().Wait(WaitTimeoutMs), (Exception ex_) => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
-        }
-
-        [Fact]
-        public void GroupBy5()
-        {
-            var xs = GetXs().ToAsyncEnumerable();
-            var ys = xs.GroupBy(x => x);
-
-            var e = ys.GetAsyncEnumerator();
-
-            AssertThrows(() => e.MoveNextAsync().Wait(WaitTimeoutMs), (Exception ex_) => ((AggregateException)ex_).Flatten().InnerExceptions.Single().Message == "Bang!");
-
-            //Assert.True(e.MoveNext().Result);
-            //var g1 = e.Current;
-            //Assert.Equal(g1.Key, 42);
-            //var g1e = g1.GetEnumerator();
-            //HasNext(g1e, 42);
-
-            //Assert.True(e.MoveNext().Result);
-            //var g2 = e.Current;
-            //Assert.Equal(g2.Key, 43);
-            //var g2e = g2.GetEnumerator();
-            //HasNext(g2e, 43);
-
-
-            //AssertThrows<Exception>(() => g1e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single().Message == "Bang!");
-            //AssertThrows<Exception>(() => g2e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single().Message == "Bang!");
-        }
-
-        [Fact]
-        public void GroupBy6()
-        {
-            var xs = GetXs().ToAsyncEnumerable();
-            var ys = xs.GroupBy(x => x);
-
-            var e = ys.GetAsyncEnumerator();
-
-            AssertThrows(() => e.MoveNextAsync().Wait(WaitTimeoutMs), (Exception ex_) => ((AggregateException)ex_).Flatten().InnerExceptions.Single().Message == "Bang!");
-
-            //Assert.True(e.MoveNext().Result);
-            //var g1 = e.Current;
-            //Assert.Equal(g1.Key, 42);
-            //var g1e = g1.GetEnumerator();
-            //HasNext(g1e, 42);
-            //AssertThrows<Exception>(() => g1e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single().Message == "Bang!");
-
-
-        }
-
-        static IEnumerable<int> GetXs()
-        {
-            yield return 42;
-            yield return 43;
-            throw new Exception("Bang!");
-        }
-
-        [Fact]
-        public void GroupBy7()
-        {
-            var ex = new Exception("Bang!");
-            var xs = AsyncEnumerable.Return(42);
-            var ys = xs.GroupBy<int, int>(new Func<int, int>(x => { throw ex; }));
-
-            var e = ys.GetAsyncEnumerator();
-            AssertThrows(() => e.MoveNextAsync().Wait(WaitTimeoutMs), (Exception ex_) => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
-        }
-
-        [Fact]
-        public void GroupBy8()
-        {
-            var ex = new Exception("Bang!");
-            var xs = new[] { 1, 2, 3 }.ToAsyncEnumerable();
-            var ys = xs.GroupBy<int, int>(x => { if (x == 3) throw ex; return x; });
-
-            var e = ys.GetAsyncEnumerator();
-
-            AssertThrows(() => e.MoveNextAsync().Wait(WaitTimeoutMs), (Exception ex_) => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
-
-            //Assert.True(e.MoveNext().Result);
-            //var g1 = e.Current;
-            //Assert.Equal(g1.Key, 1);
-            //var g1e = g1.GetEnumerator();
-            //HasNext(g1e, 1);
-
-            //Assert.True(e.MoveNext().Result);
-            //var g2 = e.Current;
-            //Assert.Equal(g2.Key, 2);
-            //var g2e = g2.GetEnumerator();
-            //HasNext(g2e, 2);
-
-
-            //AssertThrows<Exception>(() => g1e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
-            //AssertThrows<Exception>(() => g2e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
-        }
-
-        [Fact]
-        public void GroupBy9()
-        {
-            var xs = AsyncEnumerable.Range(0, 10);
-            var ys = xs.GroupBy(x => x % 3, x => (char)('a' + x));
-
-            var e = ys.GetAsyncEnumerator();
-
-            Assert.True(e.MoveNextAsync().Result);
-            var g1 = e.Current;
-            Assert.Equal(0, g1.Key);
-            var g1e = g1.GetAsyncEnumerator();
-            HasNext(g1e, 'a');
-            HasNext(g1e, 'd');
-            HasNext(g1e, 'g');
-            HasNext(g1e, 'j');
-            NoNext(g1e);
-
-            Assert.True(e.MoveNextAsync().Result);
-            var g2 = e.Current;
-            Assert.Equal(1, g2.Key);
-            var g2e = g2.GetAsyncEnumerator();
-            HasNext(g2e, 'b');
-            HasNext(g2e, 'e');
-            HasNext(g2e, 'h');
-            NoNext(g2e);
-
-            Assert.True(e.MoveNextAsync().Result);
-            var g3 = e.Current;
-            Assert.Equal(2, g3.Key);
-            var g3e = g3.GetAsyncEnumerator();
-            HasNext(g3e, 'c');
-            HasNext(g3e, 'f');
-            HasNext(g3e, 'i');
-            NoNext(g3e);
-
-            NoNext(e);
-        }
-
-        [Fact]
-        public void GroupBy10()
-        {
-            var xs = AsyncEnumerable.Range(0, 10);
-            var ys = xs.GroupBy(x => x % 3, x => (char)('a' + x), (k, cs) => k + " - " + cs.Aggregate("", (a, c) => a + c).Result);
-
-            var e = ys.GetAsyncEnumerator();
-            HasNext(e, "0 - adgj");
-            HasNext(e, "1 - beh");
-            HasNext(e, "2 - cfi");
-            NoNext(e);
-        }
-
-        [Fact]
-        public void GroupBy11()
-        {
-            var xs = AsyncEnumerable.Range(0, 10);
-            var ys = xs.GroupBy(x => x % 3, (k, cs) => k + " - " + cs.Aggregate("", (a, c) => a + c).Result);
-
-            var e = ys.GetAsyncEnumerator();
-            HasNext(e, "0 - 0369");
-            HasNext(e, "1 - 147");
-            HasNext(e, "2 - 258");
-            NoNext(e);
-        }
-
-        [Fact]
-        public void GroupBy12()
-        {
-            var xs = AsyncEnumerable.Range(0, 10);
-            var ys = xs.GroupBy(x => x, new EqMod(3));
-
-            var e = ys.GetAsyncEnumerator();
-
-            Assert.True(e.MoveNextAsync().Result);
-            var g1 = e.Current;
-            Assert.Equal(0, g1.Key);
-            var g1e = g1.GetAsyncEnumerator();
-            HasNext(g1e, 0);
-            HasNext(g1e, 3);
-            HasNext(g1e, 6);
-            HasNext(g1e, 9);
-            NoNext(g1e);
-
-            Assert.True(e.MoveNextAsync().Result);
-            var g2 = e.Current;
-            Assert.Equal(1, g2.Key);
-            var g2e = g2.GetAsyncEnumerator();
-            HasNext(g2e, 1);
-            HasNext(g2e, 4);
-            HasNext(g2e, 7);
-            NoNext(g2e);
-
-            Assert.True(e.MoveNextAsync().Result);
-            var g3 = e.Current;
-            Assert.Equal(2, g3.Key);
-            var g3e = g3.GetAsyncEnumerator();
-            HasNext(g3e, 2);
-            HasNext(g3e, 5);
-            HasNext(g3e, 8);
-            NoNext(g3e);
-
-            NoNext(e);
-        }
-
-        [Fact]
-        public void GroupBy13()
-        {
-            var xs = AsyncEnumerable.Range(0, 10);
-            var ys = xs.GroupBy(x => x, x => (char)('a' + x), new EqMod(3));
-
-            var e = ys.GetAsyncEnumerator();
-
-            Assert.True(e.MoveNextAsync().Result);
-            var g1 = e.Current;
-            Assert.Equal(0, g1.Key);
-            var g1e = g1.GetAsyncEnumerator();
-            HasNext(g1e, 'a');
-            HasNext(g1e, 'd');
-            HasNext(g1e, 'g');
-            HasNext(g1e, 'j');
-            NoNext(g1e);
-
-            Assert.True(e.MoveNextAsync().Result);
-            var g2 = e.Current;
-            Assert.Equal(1, g2.Key);
-            var g2e = g2.GetAsyncEnumerator();
-            HasNext(g2e, 'b');
-            HasNext(g2e, 'e');
-            HasNext(g2e, 'h');
-            NoNext(g2e);
-
-            Assert.True(e.MoveNextAsync().Result);
-            var g3 = e.Current;
-            Assert.Equal(2, g3.Key);
-            var g3e = g3.GetAsyncEnumerator();
-            HasNext(g3e, 'c');
-            HasNext(g3e, 'f');
-            HasNext(g3e, 'i');
-            NoNext(g3e);
-
-            NoNext(e);
-        }
-
-        [Fact]
-        public void GroupBy14()
-        {
-            var xs = AsyncEnumerable.Range(0, 10);
-            var ys = xs.GroupBy(x => x, x => (char)('a' + x), (k, cs) => k + " - " + cs.Aggregate("", (a, c) => a + c).Result, new EqMod(3));
-
-            var e = ys.GetAsyncEnumerator();
-            HasNext(e, "0 - adgj");
-            HasNext(e, "1 - beh");
-            HasNext(e, "2 - cfi");
-            NoNext(e);
-        }
-
-        [Fact]
-        public void GroupBy15()
-        {
-            var xs = AsyncEnumerable.Range(0, 10);
-            var ys = xs.GroupBy(x => x, (k, cs) => k + " - " + cs.Aggregate("", (a, c) => a + c).Result, new EqMod(3));
-
-            var e = ys.GetAsyncEnumerator();
-            HasNext(e, "0 - 0369");
-            HasNext(e, "1 - 147");
-            HasNext(e, "2 - 258");
-            NoNext(e);
-        }
-
-        [Fact]
-        public async Task GroupBy16()
-        {
-            var xs = AsyncEnumerable.Range(0, 10);
-            var ys = xs.GroupBy(x => x, x => (char)('a' + x), new EqMod(3));
-
-            var e = ys.GetAsyncEnumerator();
-
-            Assert.True(e.MoveNextAsync().Result);
-            var g1 = e.Current;
-            Assert.Equal(0, g1.Key);
-            var g1e = g1.GetAsyncEnumerator();
-            HasNext(g1e, 'a');
-            HasNext(g1e, 'd');
-            HasNext(g1e, 'g');
-            HasNext(g1e, 'j');
-            NoNext(g1e);
-            await g1e.DisposeAsync();
-
-            Assert.True(e.MoveNextAsync().Result);
-            var g2 = e.Current;
-            Assert.Equal(1, g2.Key);
-            var g2e = g2.GetAsyncEnumerator();
-            HasNext(g2e, 'b');
-            HasNext(g2e, 'e');
-            HasNext(g2e, 'h');
-            NoNext(g2e);
-            await g2e.DisposeAsync();
-
-            Assert.True(e.MoveNextAsync().Result);
-            var g3 = e.Current;
-            Assert.Equal(2, g3.Key);
-            var g3e = g3.GetAsyncEnumerator();
-            HasNext(g3e, 'c');
-            HasNext(g3e, 'f');
-            HasNext(g3e, 'i');
-            NoNext(g3e);
-            await g3e.DisposeAsync();
-
-            NoNext(e);
-
-            await e.DisposeAsync();
-        }
-
-        [Fact]
-        public async Task GroupBy17()
-        {
-            var xs = AsyncEnumerable.Range(0, 10);
-            var ys = xs.GroupBy(x => x, x => (char)('a' + x), new EqMod(3));
-
-            var e = ys.GetAsyncEnumerator();
-            await e.DisposeAsync();
-
-            Assert.False(e.MoveNextAsync().Result);
-        }
-
-        [Fact]
-        public async Task GroupBy18()
-        {
-            var xs = AsyncEnumerable.Range(0, 10);
-            var ys = xs.GroupBy(x => x, x => (char)('a' + x), new EqMod(3));
-
-            var e = ys.GetAsyncEnumerator();
-
-            Assert.True(e.MoveNextAsync().Result);
-            var g1 = e.Current;
-            Assert.Equal(0, g1.Key);
-            var g1e = g1.GetAsyncEnumerator();
-            HasNext(g1e, 'a');
-
-            await e.DisposeAsync();
-
-            HasNext(g1e, 'd');
-            HasNext(g1e, 'g');
-            HasNext(g1e, 'j');
-            NoNext(g1e);
-            await g1e.DisposeAsync();
-
-            Assert.False(e.MoveNextAsync().Result);
-        }
-
-        [Fact]
-        public async Task GroupBy19()
-        {
-            // We're using Kvp here because the types will eval as equal for this test
-            var xs = new[]
-            {
-                new Kvp("Bart", 27),
-                new Kvp("John", 62),
-                new Kvp("Eric", 27),
-                new Kvp("Lisa", 14),
-                new Kvp("Brad", 27),
-                new Kvp("Lisa", 23),
-                new Kvp("Eric", 42)
-            };
-
-            var ys = xs.ToAsyncEnumerable();
-
-            var res = ys.GroupBy(x => x.Item / 10);
-
-            await SequenceIdentity(res);
-        }
-
-
-        [Fact]
-        public async Task GroupBy20()
-        {
-            var xs = AsyncEnumerable.Range(0, 10);
-            var ys = xs.GroupBy(x => x % 3, x => (char)('a' + x), (k, cs) => k + " - " + cs.Aggregate("", (a, c) => a + c).Result);
-
-            var arr = new[] { "0 - adgj", "1 - beh", "2 - cfi" };
-
-            Assert.Equal(arr, await ys.ToArray());
-        }
-
-        [Fact]
-        public async Task GroupBy21()
-        {
-            var xs = AsyncEnumerable.Range(0, 10);
-            var ys = xs.GroupBy(x => x % 3, x => (char)('a' + x), (k, cs) => k + " - " + cs.Aggregate("", (a, c) => a + c).Result);
-
-            var arr = new List<string> { "0 - adgj", "1 - beh", "2 - cfi" };
-
-            Assert.Equal(arr, await ys.ToList());
-        }
-
-        [Fact]
-        public async Task GroupBy22()
-        {
-            var xs = AsyncEnumerable.Range(0, 10);
-            var ys = xs.GroupBy(x => x % 3, x => (char)('a' + x), (k, cs) => k + " - " + cs.Aggregate("", (a, c) => a + c).Result);
-
-            Assert.Equal(3, await ys.Count());
-        }
-
-        [Fact]
-        public async Task GroupBy23()
-        {
-            var xs = AsyncEnumerable.Range(0, 10);
-            var ys = xs.GroupBy(x => x % 3, x => (char)('a' + x), (k, cs) => k + " - " + cs.Aggregate("", (a, c) => a + c).Result);
-
-            await SequenceIdentity(ys);
-        }
-
-        [Fact]
-        public async Task GroupBy24()
-        {
-            var xs = AsyncEnumerable.Range(0, 10);
-            var ys = xs.GroupBy(x => x % 3, x => (char)('a' + x));
-
-            var g1a = new[] { 'a', 'd', 'g', 'j' };
-            var g2a = new[] { 'b', 'e', 'h' };
-            var g3a = new[] { 'c', 'f', 'i' };
-
-            var gar = await ys.ToArray();
-
-            Assert.Equal(3, gar.Length);
-
-            var gg1 = gar[0];
-            var gg1a = await gg1.ToArray();
-
-            Assert.Equal(g1a, gg1a);
-
-            var gg2 = gar[1];
-            var gg2a = await gg2.ToArray();
-
-            Assert.Equal(g2a, gg2a);
-
-            var gg3 = gar[2];
-            var gg3a = await gg3.ToArray();
-            Assert.Equal(g3a, gg3a);
-        }
-
-        [Fact]
-        public async Task GroupBy25()
-        {
-            var xs = AsyncEnumerable.Range(0, 10);
-            var ys = xs.GroupBy(x => x % 3, x => (char)('a' + x));
-
-            var g1a = new List<char> { 'a', 'd', 'g', 'j' };
-            var g2a = new List<char> { 'b', 'e', 'h' };
-            var g3a = new List<char> { 'c', 'f', 'i' };
-
-            var gar = await ys.ToList();
-
-            Assert.Equal(3, gar.Count);
-
-            var gg1 = gar[0];
-            var gg1a = await gg1.ToList();
-            Assert.Equal(g1a, gg1a);
-
-            var gg2 = gar[1];
-            var gg2a = await gg2.ToList();
-            Assert.Equal(g2a, gg2a);
-
-            var gg3 = gar[2];
-            var gg3a = await gg3.ToList();
-            Assert.Equal(g3a, gg3a);
-        }
-
-        [Fact]
-        public async Task GroupBy26()
-        {
-            var xs = AsyncEnumerable.Range(0, 10);
-            var ys = xs.GroupBy(x => x % 3, x => (char)('a' + x));
-
-            var gar = await ys.ToList();
-
-            Assert.Equal(3, gar.Count);
-
-            var gg1 = gar[0];
-            var gg1a = await gg1.Count();
-            Assert.Equal(4, gg1a);
-
-            var gg2 = gar[1];
-            var gg2a = await gg2.Count();
-            Assert.Equal(3, gg2a);
-
-            var gg3 = gar[2];
-            var gg3a = await gg3.Count();
-            Assert.Equal(3, gg3a);
-        }
-
-        [Fact]
-        public async Task GroupBy27()
-        {
-            var xs = AsyncEnumerable.Range(0, 10);
-            var ys = xs.GroupBy(x => x % 3, x => (char)('a' + x));
-
-            var gar = await ys.Count();
-
-            Assert.Equal(3, gar);
-        }
-
-        [Fact]
-        public async Task GroupBy28()
-        {
-            var xs = AsyncEnumerable.Range(0, 10);
-            var ys = xs.GroupBy(x => x % 3, x => (char)('a' + x));
-
-            await SequenceIdentity(ys);
-        }
-
-        [Fact]
-        public async Task GroupBy29()
-        {
-            var xs = AsyncEnumerable.Range(0, 10);
-            var ys = xs.GroupBy(x => x, new EqMod(3));
-
-            var g1a = new List<int> { 0, 3, 6, 9 };
-            var g2a = new List<int> { 1, 4, 7 };
-            var g3a = new List<int> { 2, 5, 8 };
-
-            var gar = await ys.ToList();
-
-            Assert.Equal(3, gar.Count);
-
-            var gg1 = gar[0];
-            var gg1a = await gg1.ToList();
-            Assert.Equal(g1a, gg1a);
-
-            var gg2 = gar[1];
-            var gg2a = await gg2.ToList();
-            Assert.Equal(g2a, gg2a);
-
-            var gg3 = gar[2];
-            var gg3a = await gg3.ToList();
-            Assert.Equal(g3a, gg3a);
-        }
-
-        [Fact]
-        public async Task GroupBy30()
-        {
-            var xs = AsyncEnumerable.Range(0, 10);
-            var ys = xs.GroupBy(x => x, new EqMod(3));
-
-
-            var gar = await ys.ToList();
-
-            Assert.Equal(3, gar.Count);
-
-            var gg1 = gar[0];
-            var gg1a = await gg1.Count();
-            Assert.Equal(4, gg1a);
-
-            var gg2 = gar[1];
-            var gg2a = await gg2.Count();
-            Assert.Equal(3, gg2a);
-
-            var gg3 = gar[2];
-            var gg3a = await gg3.Count();
-            Assert.Equal(3, gg3a);
-        }
-
-        [Fact]
-        public async Task GroupBy31()
-        {
-            var xs = AsyncEnumerable.Range(0, 10);
-            var ys = xs.GroupBy(x => x, new EqMod(3));
-
-            var g1a = new[] { 0, 3, 6, 9 };
-            var g2a = new[] { 1, 4, 7 };
-            var g3a = new[] { 2, 5, 8 };
-
-            var gar = await ys.ToArray();
-
-            Assert.Equal(3, gar.Length);
-
-            var gg1 = gar[0];
-            var gg1a = await gg1.ToArray();
-
-            Assert.Equal(g1a, gg1a);
-
-            var gg2 = gar[1];
-            var gg2a = await gg2.ToArray();
-
-            Assert.Equal(g2a, gg2a);
-
-            var gg3 = gar[2];
-            var gg3a = await gg3.ToArray();
-            Assert.Equal(g3a, gg3a);
-        }
-
-        [Fact]
-        public async Task GroupBy32()
-        {
-            var xs = AsyncEnumerable.Range(0, 10);
-            var ys = xs.GroupBy(x => x, new EqMod(3));
-
-            var gar = await ys.Count();
-
-            Assert.Equal(3, gar);
-        }
-
-        [Fact]
-        public async Task GroupBy33()
-        {
-            var xs = AsyncEnumerable.Range(0, 10);
-            var ys = xs.GroupBy(x => x, new EqMod(3));
-
-            await SequenceIdentity(ys);
-        }
-
-        [Fact]
-        public async Task GroupBy34()
-        {
-            var xs = AsyncEnumerable.Range(0, 10);
-            var ys = xs.GroupBy(x => x, (k, cs) => k + " - " + cs.Aggregate("", (a, c) => a + c).Result, new EqMod(3));
-
-            var arr = new[] { "0 - 0369", "1 - 147", "2 - 258" };
-
-            Assert.Equal(arr, await ys.ToArray());
-        }
-
-        [Fact]
-        public async Task GroupBy35()
-        {
-            var xs = AsyncEnumerable.Range(0, 10);
-            var ys = xs.GroupBy(x => x, (k, cs) => k + " - " + cs.Aggregate("", (a, c) => a + c).Result, new EqMod(3));
-
-            var arr = new List<string> { "0 - 0369", "1 - 147", "2 - 258" };
-
-            Assert.Equal(arr, await ys.ToList());
-        }
-
-        [Fact]
-        public async Task GroupBy36()
-        {
-            var xs = AsyncEnumerable.Range(0, 10);
-            var ys = xs.GroupBy(x => x, (k, cs) => k + " - " + cs.Aggregate("", (a, c) => a + c).Result, new EqMod(3));
-
-            Assert.Equal(3, await ys.Count());
-        }
-
-        [Fact]
-        public async Task GroupBy37()
-        {
-            var xs = AsyncEnumerable.Range(0, 10);
-            var ys = xs.GroupBy(x => x, (k, cs) => k + " - " + cs.Aggregate("", (a, c) => a + c).Result, new EqMod(3));
-
-            await SequenceIdentity(ys);
-        }
-
-        class Kvp : IEquatable<Kvp>
-        {
-            public bool Equals(Kvp other)
-            {
-                if (ReferenceEquals(null, other)) return false;
-                if (ReferenceEquals(this, other)) return true;
-                return string.Equals(Key, other.Key) && Item == other.Item;
-            }
-
-            public override bool Equals(object obj)
-            {
-                if (ReferenceEquals(null, obj)) return false;
-                if (ReferenceEquals(this, obj)) return true;
-                if (obj.GetType() != GetType()) return false;
-                return Equals((Kvp)obj);
-            }
-
-            public override int GetHashCode()
-            {
-                unchecked
-                {
-                    return ((Key != null ? Key.GetHashCode() : 0) * 397) ^ Item;
-                }
-            }
-
-            public static bool operator ==(Kvp left, Kvp right)
-            {
-                return Equals(left, right);
-            }
-
-            public static bool operator !=(Kvp left, Kvp right)
-            {
-                return !Equals(left, right);
-            }
-
-
-            public string Key { get; }
-            public int Item { get; }
-
-            public Kvp(string key, int item)
-            {
-                Key = key;
-                Item = item;
-            }
-        }
-
-
-        class EqMod : IEqualityComparer<int>
-        {
-            private readonly int _d;
-
-            public EqMod(int d)
-            {
-                _d = d;
-            }
-
-            public bool Equals(int x, int y)
-            {
-                return EqualityComparer<int>.Default.Equals(x % _d, y % _d);
-            }
-
-            public int GetHashCode(int obj)
-            {
-                return EqualityComparer<int>.Default.GetHashCode(obj % _d);
-            }
-        }
-
         [Fact]
         public void AsAsyncEnumerable_Null()
         {

+ 893 - 0
Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/GroupBy.cs

@@ -0,0 +1,893 @@
+// 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
+{
+    public class GroupBy : AsyncEnumerableTests
+    {
+        [Fact]
+        public void GroupBy_Null()
+        {
+            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int>(null, x => x));
+            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int>(AsyncEnumerable.Return(42), default(Func<int, int>)));
+
+            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int>(null, x => x, EqualityComparer<int>.Default));
+            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int>(AsyncEnumerable.Return(42), default(Func<int, int>), EqualityComparer<int>.Default));
+            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int>(AsyncEnumerable.Return(42), x => x, default(IEqualityComparer<int>)));
+
+            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(null, x => x, x => x));
+            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(AsyncEnumerable.Return(42), default(Func<int, int>), x => x));
+            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(AsyncEnumerable.Return(42), x => x, default(Func<int, int>)));
+
+            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(null, x => x, x => x, EqualityComparer<int>.Default));
+            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(AsyncEnumerable.Return(42), default(Func<int, int>), x => x, EqualityComparer<int>.Default));
+            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(AsyncEnumerable.Return(42), x => x, default(Func<int, int>), EqualityComparer<int>.Default));
+            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(AsyncEnumerable.Return(42), x => x, x => x, default(IEqualityComparer<int>)));
+
+            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(null, x => x, (x, ys) => x));
+            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(AsyncEnumerable.Return(42), default(Func<int, int>), (x, ys) => x));
+            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(AsyncEnumerable.Return(42), x => x, default(Func<int, IAsyncEnumerable<int>, int>)));
+
+            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(null, x => x, (x, ys) => x, EqualityComparer<int>.Default));
+            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(AsyncEnumerable.Return(42), default(Func<int, int>), (x, ys) => x, EqualityComparer<int>.Default));
+            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(AsyncEnumerable.Return(42), x => x, default(Func<int, IAsyncEnumerable<int>, int>), EqualityComparer<int>.Default));
+            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(AsyncEnumerable.Return(42), x => x, (x, ys) => x, default(IEqualityComparer<int>)));
+
+            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int, int>(null, x => x, x => x, (x, ys) => x));
+            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int, int>(AsyncEnumerable.Return(42), default(Func<int, int>), x => x, (x, ys) => x));
+            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int, int>(AsyncEnumerable.Return(42), x => x, default(Func<int, int>), (x, ys) => x));
+            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int, int>(AsyncEnumerable.Return(42), x => x, x => x, default(Func<int, IAsyncEnumerable<int>, int>)));
+
+            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int, int>(null, x => x, x => x, (x, ys) => x, EqualityComparer<int>.Default));
+            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int, int>(AsyncEnumerable.Return(42), default(Func<int, int>), x => x, (x, ys) => x, EqualityComparer<int>.Default));
+            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int, int>(AsyncEnumerable.Return(42), x => x, default(Func<int, int>), (x, ys) => x, EqualityComparer<int>.Default));
+            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int, int>(AsyncEnumerable.Return(42), x => x, x => x, default(Func<int, IAsyncEnumerable<int>, int>), EqualityComparer<int>.Default));
+            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int, int>(AsyncEnumerable.Return(42), x => x, x => x, (x, ys) => x, default(IEqualityComparer<int>)));
+        }
+
+        [Fact]
+        public void GroupBy1()
+        {
+            var xs = new[] {
+                new { Name = "Bart", Age = 27 },
+                new { Name = "John", Age = 62 },
+                new { Name = "Eric", Age = 27 },
+                new { Name = "Lisa", Age = 14 },
+                new { Name = "Brad", Age = 27 },
+                new { Name = "Lisa", Age = 23 },
+                new { Name = "Eric", Age = 42 },
+            };
+
+            var ys = xs.ToAsyncEnumerable();
+
+            var res = ys.GroupBy(x => x.Age / 10);
+
+            var e = res.GetAsyncEnumerator();
+
+            Assert.True(e.MoveNextAsync().Result);
+            Assert.Equal(2, e.Current.Key);
+            var g1 = e.Current.GetAsyncEnumerator();
+            HasNext(g1, xs[0]);
+            HasNext(g1, xs[2]);
+            HasNext(g1, xs[4]);
+            HasNext(g1, xs[5]);
+            NoNext(g1);
+
+            Assert.True(e.MoveNextAsync().Result);
+            Assert.Equal(6, e.Current.Key);
+            var g2 = e.Current.GetAsyncEnumerator();
+            HasNext(g2, xs[1]);
+            NoNext(g2);
+
+            Assert.True(e.MoveNextAsync().Result);
+            Assert.Equal(1, e.Current.Key);
+            var g3 = e.Current.GetAsyncEnumerator();
+            HasNext(g3, xs[3]);
+            NoNext(g3);
+
+            Assert.True(e.MoveNextAsync().Result);
+            Assert.Equal(4, e.Current.Key);
+            var g4 = e.Current.GetAsyncEnumerator();
+            HasNext(g4, xs[6]);
+            NoNext(g4);
+
+            NoNext(e);
+        }
+
+        [Fact]
+        public void GroupBy2()
+        {
+            var xs = new[] {
+                new { Name = "Bart", Age = 27 },
+                new { Name = "John", Age = 62 },
+                new { Name = "Eric", Age = 27 },
+                new { Name = "Lisa", Age = 14 },
+                new { Name = "Brad", Age = 27 },
+                new { Name = "Lisa", Age = 23 },
+                new { Name = "Eric", Age = 42 },
+            };
+
+            var ys = xs.ToAsyncEnumerable();
+
+            var res = ys.GroupBy(x => x.Age / 10);
+
+            var e = res.GetAsyncEnumerator();
+
+            Assert.True(e.MoveNextAsync().Result);
+            var g1 = e.Current;
+            Assert.Equal(2, g1.Key);
+
+            Assert.True(e.MoveNextAsync().Result);
+            var g2 = e.Current;
+            Assert.Equal(6, g2.Key);
+
+            Assert.True(e.MoveNextAsync().Result);
+            var g3 = e.Current;
+            Assert.Equal(1, g3.Key);
+
+            Assert.True(e.MoveNextAsync().Result);
+            var g4 = e.Current;
+            Assert.Equal(4, g4.Key);
+
+            NoNext(e);
+
+            var g1e = g1.GetAsyncEnumerator();
+            HasNext(g1e, xs[0]);
+            HasNext(g1e, xs[2]);
+            HasNext(g1e, xs[4]);
+            HasNext(g1e, xs[5]);
+            NoNext(g1e);
+
+            var g2e = g2.GetAsyncEnumerator();
+            HasNext(g2e, xs[1]);
+            NoNext(g2e);
+
+            var g3e = g3.GetAsyncEnumerator();
+            HasNext(g3e, xs[3]);
+            NoNext(g3e);
+
+            var g4e = g4.GetAsyncEnumerator();
+            HasNext(g4e, xs[6]);
+            NoNext(g4e);
+        }
+
+        [Fact]
+        public void GroupBy3()
+        {
+            var xs = AsyncEnumerable.Empty<int>();
+            var ys = xs.GroupBy(x => x);
+
+            var e = ys.GetAsyncEnumerator();
+            NoNext(e);
+        }
+
+        [Fact]
+        public void GroupBy4()
+        {
+            var ex = new Exception("Bang!");
+            var xs = AsyncEnumerable.Throw<int>(ex);
+            var ys = xs.GroupBy(x => x);
+
+            var e = ys.GetAsyncEnumerator();
+            AssertThrows(() => e.MoveNextAsync().Wait(WaitTimeoutMs), (Exception ex_) => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+        }
+
+        [Fact]
+        public void GroupBy5()
+        {
+            var xs = GetXs().ToAsyncEnumerable();
+            var ys = xs.GroupBy(x => x);
+
+            var e = ys.GetAsyncEnumerator();
+
+            AssertThrows(() => e.MoveNextAsync().Wait(WaitTimeoutMs), (Exception ex_) => ((AggregateException)ex_).Flatten().InnerExceptions.Single().Message == "Bang!");
+
+            //Assert.True(e.MoveNext().Result);
+            //var g1 = e.Current;
+            //Assert.Equal(g1.Key, 42);
+            //var g1e = g1.GetEnumerator();
+            //HasNext(g1e, 42);
+
+            //Assert.True(e.MoveNext().Result);
+            //var g2 = e.Current;
+            //Assert.Equal(g2.Key, 43);
+            //var g2e = g2.GetEnumerator();
+            //HasNext(g2e, 43);
+
+
+            //AssertThrows<Exception>(() => g1e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single().Message == "Bang!");
+            //AssertThrows<Exception>(() => g2e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single().Message == "Bang!");
+        }
+
+        [Fact]
+        public void GroupBy6()
+        {
+            var xs = GetXs().ToAsyncEnumerable();
+            var ys = xs.GroupBy(x => x);
+
+            var e = ys.GetAsyncEnumerator();
+
+            AssertThrows(() => e.MoveNextAsync().Wait(WaitTimeoutMs), (Exception ex_) => ((AggregateException)ex_).Flatten().InnerExceptions.Single().Message == "Bang!");
+
+            //Assert.True(e.MoveNext().Result);
+            //var g1 = e.Current;
+            //Assert.Equal(g1.Key, 42);
+            //var g1e = g1.GetEnumerator();
+            //HasNext(g1e, 42);
+            //AssertThrows<Exception>(() => g1e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single().Message == "Bang!");
+
+
+        }
+
+        static IEnumerable<int> GetXs()
+        {
+            yield return 42;
+            yield return 43;
+            throw new Exception("Bang!");
+        }
+
+        [Fact]
+        public void GroupBy7()
+        {
+            var ex = new Exception("Bang!");
+            var xs = AsyncEnumerable.Return(42);
+            var ys = xs.GroupBy<int, int>(new Func<int, int>(x => { throw ex; }));
+
+            var e = ys.GetAsyncEnumerator();
+            AssertThrows(() => e.MoveNextAsync().Wait(WaitTimeoutMs), (Exception ex_) => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+        }
+
+        [Fact]
+        public void GroupBy8()
+        {
+            var ex = new Exception("Bang!");
+            var xs = new[] { 1, 2, 3 }.ToAsyncEnumerable();
+            var ys = xs.GroupBy<int, int>(x => { if (x == 3) throw ex; return x; });
+
+            var e = ys.GetAsyncEnumerator();
+
+            AssertThrows(() => e.MoveNextAsync().Wait(WaitTimeoutMs), (Exception ex_) => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+
+            //Assert.True(e.MoveNext().Result);
+            //var g1 = e.Current;
+            //Assert.Equal(g1.Key, 1);
+            //var g1e = g1.GetEnumerator();
+            //HasNext(g1e, 1);
+
+            //Assert.True(e.MoveNext().Result);
+            //var g2 = e.Current;
+            //Assert.Equal(g2.Key, 2);
+            //var g2e = g2.GetEnumerator();
+            //HasNext(g2e, 2);
+
+
+            //AssertThrows<Exception>(() => g1e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+            //AssertThrows<Exception>(() => g2e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
+        }
+
+        [Fact]
+        public void GroupBy9()
+        {
+            var xs = AsyncEnumerable.Range(0, 10);
+            var ys = xs.GroupBy(x => x % 3, x => (char)('a' + x));
+
+            var e = ys.GetAsyncEnumerator();
+
+            Assert.True(e.MoveNextAsync().Result);
+            var g1 = e.Current;
+            Assert.Equal(0, g1.Key);
+            var g1e = g1.GetAsyncEnumerator();
+            HasNext(g1e, 'a');
+            HasNext(g1e, 'd');
+            HasNext(g1e, 'g');
+            HasNext(g1e, 'j');
+            NoNext(g1e);
+
+            Assert.True(e.MoveNextAsync().Result);
+            var g2 = e.Current;
+            Assert.Equal(1, g2.Key);
+            var g2e = g2.GetAsyncEnumerator();
+            HasNext(g2e, 'b');
+            HasNext(g2e, 'e');
+            HasNext(g2e, 'h');
+            NoNext(g2e);
+
+            Assert.True(e.MoveNextAsync().Result);
+            var g3 = e.Current;
+            Assert.Equal(2, g3.Key);
+            var g3e = g3.GetAsyncEnumerator();
+            HasNext(g3e, 'c');
+            HasNext(g3e, 'f');
+            HasNext(g3e, 'i');
+            NoNext(g3e);
+
+            NoNext(e);
+        }
+
+        [Fact]
+        public void GroupBy10()
+        {
+            var xs = AsyncEnumerable.Range(0, 10);
+            var ys = xs.GroupBy(x => x % 3, x => (char)('a' + x), (k, cs) => k + " - " + cs.Aggregate("", (a, c) => a + c).Result);
+
+            var e = ys.GetAsyncEnumerator();
+            HasNext(e, "0 - adgj");
+            HasNext(e, "1 - beh");
+            HasNext(e, "2 - cfi");
+            NoNext(e);
+        }
+
+        [Fact]
+        public void GroupBy11()
+        {
+            var xs = AsyncEnumerable.Range(0, 10);
+            var ys = xs.GroupBy(x => x % 3, (k, cs) => k + " - " + cs.Aggregate("", (a, c) => a + c).Result);
+
+            var e = ys.GetAsyncEnumerator();
+            HasNext(e, "0 - 0369");
+            HasNext(e, "1 - 147");
+            HasNext(e, "2 - 258");
+            NoNext(e);
+        }
+
+        [Fact]
+        public void GroupBy12()
+        {
+            var xs = AsyncEnumerable.Range(0, 10);
+            var ys = xs.GroupBy(x => x, new EqMod(3));
+
+            var e = ys.GetAsyncEnumerator();
+
+            Assert.True(e.MoveNextAsync().Result);
+            var g1 = e.Current;
+            Assert.Equal(0, g1.Key);
+            var g1e = g1.GetAsyncEnumerator();
+            HasNext(g1e, 0);
+            HasNext(g1e, 3);
+            HasNext(g1e, 6);
+            HasNext(g1e, 9);
+            NoNext(g1e);
+
+            Assert.True(e.MoveNextAsync().Result);
+            var g2 = e.Current;
+            Assert.Equal(1, g2.Key);
+            var g2e = g2.GetAsyncEnumerator();
+            HasNext(g2e, 1);
+            HasNext(g2e, 4);
+            HasNext(g2e, 7);
+            NoNext(g2e);
+
+            Assert.True(e.MoveNextAsync().Result);
+            var g3 = e.Current;
+            Assert.Equal(2, g3.Key);
+            var g3e = g3.GetAsyncEnumerator();
+            HasNext(g3e, 2);
+            HasNext(g3e, 5);
+            HasNext(g3e, 8);
+            NoNext(g3e);
+
+            NoNext(e);
+        }
+
+        [Fact]
+        public void GroupBy13()
+        {
+            var xs = AsyncEnumerable.Range(0, 10);
+            var ys = xs.GroupBy(x => x, x => (char)('a' + x), new EqMod(3));
+
+            var e = ys.GetAsyncEnumerator();
+
+            Assert.True(e.MoveNextAsync().Result);
+            var g1 = e.Current;
+            Assert.Equal(0, g1.Key);
+            var g1e = g1.GetAsyncEnumerator();
+            HasNext(g1e, 'a');
+            HasNext(g1e, 'd');
+            HasNext(g1e, 'g');
+            HasNext(g1e, 'j');
+            NoNext(g1e);
+
+            Assert.True(e.MoveNextAsync().Result);
+            var g2 = e.Current;
+            Assert.Equal(1, g2.Key);
+            var g2e = g2.GetAsyncEnumerator();
+            HasNext(g2e, 'b');
+            HasNext(g2e, 'e');
+            HasNext(g2e, 'h');
+            NoNext(g2e);
+
+            Assert.True(e.MoveNextAsync().Result);
+            var g3 = e.Current;
+            Assert.Equal(2, g3.Key);
+            var g3e = g3.GetAsyncEnumerator();
+            HasNext(g3e, 'c');
+            HasNext(g3e, 'f');
+            HasNext(g3e, 'i');
+            NoNext(g3e);
+
+            NoNext(e);
+        }
+
+        [Fact]
+        public void GroupBy14()
+        {
+            var xs = AsyncEnumerable.Range(0, 10);
+            var ys = xs.GroupBy(x => x, x => (char)('a' + x), (k, cs) => k + " - " + cs.Aggregate("", (a, c) => a + c).Result, new EqMod(3));
+
+            var e = ys.GetAsyncEnumerator();
+            HasNext(e, "0 - adgj");
+            HasNext(e, "1 - beh");
+            HasNext(e, "2 - cfi");
+            NoNext(e);
+        }
+
+        [Fact]
+        public void GroupBy15()
+        {
+            var xs = AsyncEnumerable.Range(0, 10);
+            var ys = xs.GroupBy(x => x, (k, cs) => k + " - " + cs.Aggregate("", (a, c) => a + c).Result, new EqMod(3));
+
+            var e = ys.GetAsyncEnumerator();
+            HasNext(e, "0 - 0369");
+            HasNext(e, "1 - 147");
+            HasNext(e, "2 - 258");
+            NoNext(e);
+        }
+
+        [Fact]
+        public async Task GroupBy16()
+        {
+            var xs = AsyncEnumerable.Range(0, 10);
+            var ys = xs.GroupBy(x => x, x => (char)('a' + x), new EqMod(3));
+
+            var e = ys.GetAsyncEnumerator();
+
+            Assert.True(e.MoveNextAsync().Result);
+            var g1 = e.Current;
+            Assert.Equal(0, g1.Key);
+            var g1e = g1.GetAsyncEnumerator();
+            HasNext(g1e, 'a');
+            HasNext(g1e, 'd');
+            HasNext(g1e, 'g');
+            HasNext(g1e, 'j');
+            NoNext(g1e);
+            await g1e.DisposeAsync();
+
+            Assert.True(e.MoveNextAsync().Result);
+            var g2 = e.Current;
+            Assert.Equal(1, g2.Key);
+            var g2e = g2.GetAsyncEnumerator();
+            HasNext(g2e, 'b');
+            HasNext(g2e, 'e');
+            HasNext(g2e, 'h');
+            NoNext(g2e);
+            await g2e.DisposeAsync();
+
+            Assert.True(e.MoveNextAsync().Result);
+            var g3 = e.Current;
+            Assert.Equal(2, g3.Key);
+            var g3e = g3.GetAsyncEnumerator();
+            HasNext(g3e, 'c');
+            HasNext(g3e, 'f');
+            HasNext(g3e, 'i');
+            NoNext(g3e);
+            await g3e.DisposeAsync();
+
+            NoNext(e);
+
+            await e.DisposeAsync();
+        }
+
+        [Fact]
+        public async Task GroupBy17()
+        {
+            var xs = AsyncEnumerable.Range(0, 10);
+            var ys = xs.GroupBy(x => x, x => (char)('a' + x), new EqMod(3));
+
+            var e = ys.GetAsyncEnumerator();
+            await e.DisposeAsync();
+
+            Assert.False(e.MoveNextAsync().Result);
+        }
+
+        [Fact]
+        public async Task GroupBy18()
+        {
+            var xs = AsyncEnumerable.Range(0, 10);
+            var ys = xs.GroupBy(x => x, x => (char)('a' + x), new EqMod(3));
+
+            var e = ys.GetAsyncEnumerator();
+
+            Assert.True(e.MoveNextAsync().Result);
+            var g1 = e.Current;
+            Assert.Equal(0, g1.Key);
+            var g1e = g1.GetAsyncEnumerator();
+            HasNext(g1e, 'a');
+
+            await e.DisposeAsync();
+
+            HasNext(g1e, 'd');
+            HasNext(g1e, 'g');
+            HasNext(g1e, 'j');
+            NoNext(g1e);
+            await g1e.DisposeAsync();
+
+            Assert.False(e.MoveNextAsync().Result);
+        }
+
+        [Fact]
+        public async Task GroupBy19()
+        {
+            // We're using Kvp here because the types will eval as equal for this test
+            var xs = new[]
+            {
+                new Kvp("Bart", 27),
+                new Kvp("John", 62),
+                new Kvp("Eric", 27),
+                new Kvp("Lisa", 14),
+                new Kvp("Brad", 27),
+                new Kvp("Lisa", 23),
+                new Kvp("Eric", 42)
+            };
+
+            var ys = xs.ToAsyncEnumerable();
+
+            var res = ys.GroupBy(x => x.Item / 10);
+
+            await SequenceIdentity(res);
+        }
+
+
+        [Fact]
+        public async Task GroupBy20()
+        {
+            var xs = AsyncEnumerable.Range(0, 10);
+            var ys = xs.GroupBy(x => x % 3, x => (char)('a' + x), (k, cs) => k + " - " + cs.Aggregate("", (a, c) => a + c).Result);
+
+            var arr = new[] { "0 - adgj", "1 - beh", "2 - cfi" };
+
+            Assert.Equal(arr, await ys.ToArray());
+        }
+
+        [Fact]
+        public async Task GroupBy21()
+        {
+            var xs = AsyncEnumerable.Range(0, 10);
+            var ys = xs.GroupBy(x => x % 3, x => (char)('a' + x), (k, cs) => k + " - " + cs.Aggregate("", (a, c) => a + c).Result);
+
+            var arr = new List<string> { "0 - adgj", "1 - beh", "2 - cfi" };
+
+            Assert.Equal(arr, await ys.ToList());
+        }
+
+        [Fact]
+        public async Task GroupBy22()
+        {
+            var xs = AsyncEnumerable.Range(0, 10);
+            var ys = xs.GroupBy(x => x % 3, x => (char)('a' + x), (k, cs) => k + " - " + cs.Aggregate("", (a, c) => a + c).Result);
+
+            Assert.Equal(3, await ys.Count());
+        }
+
+        [Fact]
+        public async Task GroupBy23()
+        {
+            var xs = AsyncEnumerable.Range(0, 10);
+            var ys = xs.GroupBy(x => x % 3, x => (char)('a' + x), (k, cs) => k + " - " + cs.Aggregate("", (a, c) => a + c).Result);
+
+            await SequenceIdentity(ys);
+        }
+
+        [Fact]
+        public async Task GroupBy24()
+        {
+            var xs = AsyncEnumerable.Range(0, 10);
+            var ys = xs.GroupBy(x => x % 3, x => (char)('a' + x));
+
+            var g1a = new[] { 'a', 'd', 'g', 'j' };
+            var g2a = new[] { 'b', 'e', 'h' };
+            var g3a = new[] { 'c', 'f', 'i' };
+
+            var gar = await ys.ToArray();
+
+            Assert.Equal(3, gar.Length);
+
+            var gg1 = gar[0];
+            var gg1a = await gg1.ToArray();
+
+            Assert.Equal(g1a, gg1a);
+
+            var gg2 = gar[1];
+            var gg2a = await gg2.ToArray();
+
+            Assert.Equal(g2a, gg2a);
+
+            var gg3 = gar[2];
+            var gg3a = await gg3.ToArray();
+            Assert.Equal(g3a, gg3a);
+        }
+
+        [Fact]
+        public async Task GroupBy25()
+        {
+            var xs = AsyncEnumerable.Range(0, 10);
+            var ys = xs.GroupBy(x => x % 3, x => (char)('a' + x));
+
+            var g1a = new List<char> { 'a', 'd', 'g', 'j' };
+            var g2a = new List<char> { 'b', 'e', 'h' };
+            var g3a = new List<char> { 'c', 'f', 'i' };
+
+            var gar = await ys.ToList();
+
+            Assert.Equal(3, gar.Count);
+
+            var gg1 = gar[0];
+            var gg1a = await gg1.ToList();
+            Assert.Equal(g1a, gg1a);
+
+            var gg2 = gar[1];
+            var gg2a = await gg2.ToList();
+            Assert.Equal(g2a, gg2a);
+
+            var gg3 = gar[2];
+            var gg3a = await gg3.ToList();
+            Assert.Equal(g3a, gg3a);
+        }
+
+        [Fact]
+        public async Task GroupBy26()
+        {
+            var xs = AsyncEnumerable.Range(0, 10);
+            var ys = xs.GroupBy(x => x % 3, x => (char)('a' + x));
+
+            var gar = await ys.ToList();
+
+            Assert.Equal(3, gar.Count);
+
+            var gg1 = gar[0];
+            var gg1a = await gg1.Count();
+            Assert.Equal(4, gg1a);
+
+            var gg2 = gar[1];
+            var gg2a = await gg2.Count();
+            Assert.Equal(3, gg2a);
+
+            var gg3 = gar[2];
+            var gg3a = await gg3.Count();
+            Assert.Equal(3, gg3a);
+        }
+
+        [Fact]
+        public async Task GroupBy27()
+        {
+            var xs = AsyncEnumerable.Range(0, 10);
+            var ys = xs.GroupBy(x => x % 3, x => (char)('a' + x));
+
+            var gar = await ys.Count();
+
+            Assert.Equal(3, gar);
+        }
+
+        [Fact]
+        public async Task GroupBy28()
+        {
+            var xs = AsyncEnumerable.Range(0, 10);
+            var ys = xs.GroupBy(x => x % 3, x => (char)('a' + x));
+
+            await SequenceIdentity(ys);
+        }
+
+        [Fact]
+        public async Task GroupBy29()
+        {
+            var xs = AsyncEnumerable.Range(0, 10);
+            var ys = xs.GroupBy(x => x, new EqMod(3));
+
+            var g1a = new List<int> { 0, 3, 6, 9 };
+            var g2a = new List<int> { 1, 4, 7 };
+            var g3a = new List<int> { 2, 5, 8 };
+
+            var gar = await ys.ToList();
+
+            Assert.Equal(3, gar.Count);
+
+            var gg1 = gar[0];
+            var gg1a = await gg1.ToList();
+            Assert.Equal(g1a, gg1a);
+
+            var gg2 = gar[1];
+            var gg2a = await gg2.ToList();
+            Assert.Equal(g2a, gg2a);
+
+            var gg3 = gar[2];
+            var gg3a = await gg3.ToList();
+            Assert.Equal(g3a, gg3a);
+        }
+
+        [Fact]
+        public async Task GroupBy30()
+        {
+            var xs = AsyncEnumerable.Range(0, 10);
+            var ys = xs.GroupBy(x => x, new EqMod(3));
+
+
+            var gar = await ys.ToList();
+
+            Assert.Equal(3, gar.Count);
+
+            var gg1 = gar[0];
+            var gg1a = await gg1.Count();
+            Assert.Equal(4, gg1a);
+
+            var gg2 = gar[1];
+            var gg2a = await gg2.Count();
+            Assert.Equal(3, gg2a);
+
+            var gg3 = gar[2];
+            var gg3a = await gg3.Count();
+            Assert.Equal(3, gg3a);
+        }
+
+        [Fact]
+        public async Task GroupBy31()
+        {
+            var xs = AsyncEnumerable.Range(0, 10);
+            var ys = xs.GroupBy(x => x, new EqMod(3));
+
+            var g1a = new[] { 0, 3, 6, 9 };
+            var g2a = new[] { 1, 4, 7 };
+            var g3a = new[] { 2, 5, 8 };
+
+            var gar = await ys.ToArray();
+
+            Assert.Equal(3, gar.Length);
+
+            var gg1 = gar[0];
+            var gg1a = await gg1.ToArray();
+
+            Assert.Equal(g1a, gg1a);
+
+            var gg2 = gar[1];
+            var gg2a = await gg2.ToArray();
+
+            Assert.Equal(g2a, gg2a);
+
+            var gg3 = gar[2];
+            var gg3a = await gg3.ToArray();
+            Assert.Equal(g3a, gg3a);
+        }
+
+        [Fact]
+        public async Task GroupBy32()
+        {
+            var xs = AsyncEnumerable.Range(0, 10);
+            var ys = xs.GroupBy(x => x, new EqMod(3));
+
+            var gar = await ys.Count();
+
+            Assert.Equal(3, gar);
+        }
+
+        [Fact]
+        public async Task GroupBy33()
+        {
+            var xs = AsyncEnumerable.Range(0, 10);
+            var ys = xs.GroupBy(x => x, new EqMod(3));
+
+            await SequenceIdentity(ys);
+        }
+
+        [Fact]
+        public async Task GroupBy34()
+        {
+            var xs = AsyncEnumerable.Range(0, 10);
+            var ys = xs.GroupBy(x => x, (k, cs) => k + " - " + cs.Aggregate("", (a, c) => a + c).Result, new EqMod(3));
+
+            var arr = new[] { "0 - 0369", "1 - 147", "2 - 258" };
+
+            Assert.Equal(arr, await ys.ToArray());
+        }
+
+        [Fact]
+        public async Task GroupBy35()
+        {
+            var xs = AsyncEnumerable.Range(0, 10);
+            var ys = xs.GroupBy(x => x, (k, cs) => k + " - " + cs.Aggregate("", (a, c) => a + c).Result, new EqMod(3));
+
+            var arr = new List<string> { "0 - 0369", "1 - 147", "2 - 258" };
+
+            Assert.Equal(arr, await ys.ToList());
+        }
+
+        [Fact]
+        public async Task GroupBy36()
+        {
+            var xs = AsyncEnumerable.Range(0, 10);
+            var ys = xs.GroupBy(x => x, (k, cs) => k + " - " + cs.Aggregate("", (a, c) => a + c).Result, new EqMod(3));
+
+            Assert.Equal(3, await ys.Count());
+        }
+
+        [Fact]
+        public async Task GroupBy37()
+        {
+            var xs = AsyncEnumerable.Range(0, 10);
+            var ys = xs.GroupBy(x => x, (k, cs) => k + " - " + cs.Aggregate("", (a, c) => a + c).Result, new EqMod(3));
+
+            await SequenceIdentity(ys);
+        }
+
+        private sealed class EqMod : IEqualityComparer<int>
+        {
+            private readonly int _d;
+
+            public EqMod(int d)
+            {
+                _d = d;
+            }
+
+            public bool Equals(int x, int y)
+            {
+                return EqualityComparer<int>.Default.Equals(x % _d, y % _d);
+            }
+
+            public int GetHashCode(int obj)
+            {
+                return EqualityComparer<int>.Default.GetHashCode(obj % _d);
+            }
+        }
+
+        private sealed class Kvp : IEquatable<Kvp>
+        {
+            public Kvp(string key, int item)
+            {
+                Key = key;
+                Item = item;
+            }
+
+            public string Key { get; }
+            public int Item { get; }
+
+            public bool Equals(Kvp other)
+            {
+                if (ReferenceEquals(null, other)) return false;
+                if (ReferenceEquals(this, other)) return true;
+                return string.Equals(Key, other.Key) && Item == other.Item;
+            }
+
+            public override bool Equals(object obj)
+            {
+                if (ReferenceEquals(null, obj)) return false;
+                if (ReferenceEquals(this, obj)) return true;
+                if (obj.GetType() != GetType()) return false;
+                return Equals((Kvp)obj);
+            }
+
+            public override int GetHashCode()
+            {
+                unchecked
+                {
+                    return ((Key != null ? Key.GetHashCode() : 0) * 397) ^ Item;
+                }
+            }
+
+            public static bool operator ==(Kvp left, Kvp right)
+            {
+                return Equals(left, right);
+            }
+
+            public static bool operator !=(Kvp left, Kvp right)
+            {
+                return !Equals(left, right);
+            }
+        }
+    }
+}