GroupBy.cs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the Apache 2.0 License.
  3. // See the LICENSE file in the project root for more information.
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Linq;
  7. using System.Threading;
  8. using System.Threading.Tasks;
  9. using Xunit;
  10. namespace Tests
  11. {
  12. public class GroupBy : AsyncEnumerableTests
  13. {
  14. [Fact]
  15. public void GroupBy_Null()
  16. {
  17. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int>(null, x => x));
  18. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int>(AsyncEnumerable.Return(42), default(Func<int, int>)));
  19. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int>(null, x => x, EqualityComparer<int>.Default));
  20. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int>(AsyncEnumerable.Return(42), default(Func<int, int>), EqualityComparer<int>.Default));
  21. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int>(AsyncEnumerable.Return(42), x => x, default(IEqualityComparer<int>)));
  22. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(null, x => x, x => x));
  23. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(AsyncEnumerable.Return(42), default(Func<int, int>), x => x));
  24. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(AsyncEnumerable.Return(42), x => x, default(Func<int, int>)));
  25. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(null, x => x, x => x, EqualityComparer<int>.Default));
  26. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(AsyncEnumerable.Return(42), default(Func<int, int>), x => x, EqualityComparer<int>.Default));
  27. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(AsyncEnumerable.Return(42), x => x, default(Func<int, int>), EqualityComparer<int>.Default));
  28. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(AsyncEnumerable.Return(42), x => x, x => x, default(IEqualityComparer<int>)));
  29. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(null, x => x, (x, ys) => x));
  30. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(AsyncEnumerable.Return(42), default(Func<int, int>), (x, ys) => x));
  31. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(AsyncEnumerable.Return(42), x => x, default(Func<int, IAsyncEnumerable<int>, int>)));
  32. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(null, x => x, (x, ys) => x, EqualityComparer<int>.Default));
  33. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(AsyncEnumerable.Return(42), default(Func<int, int>), (x, ys) => x, EqualityComparer<int>.Default));
  34. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(AsyncEnumerable.Return(42), x => x, default(Func<int, IAsyncEnumerable<int>, int>), EqualityComparer<int>.Default));
  35. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int>(AsyncEnumerable.Return(42), x => x, (x, ys) => x, default(IEqualityComparer<int>)));
  36. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int, int>(null, x => x, x => x, (x, ys) => x));
  37. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int, int>(AsyncEnumerable.Return(42), default(Func<int, int>), x => x, (x, ys) => x));
  38. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int, int>(AsyncEnumerable.Return(42), x => x, default(Func<int, int>), (x, ys) => x));
  39. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int, int>(AsyncEnumerable.Return(42), x => x, x => x, default(Func<int, IAsyncEnumerable<int>, int>)));
  40. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int, int>(null, x => x, x => x, (x, ys) => x, EqualityComparer<int>.Default));
  41. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int, int>(AsyncEnumerable.Return(42), default(Func<int, int>), x => x, (x, ys) => x, EqualityComparer<int>.Default));
  42. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int, int>(AsyncEnumerable.Return(42), x => x, default(Func<int, int>), (x, ys) => x, EqualityComparer<int>.Default));
  43. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int, int>(AsyncEnumerable.Return(42), x => x, x => x, default(Func<int, IAsyncEnumerable<int>, int>), EqualityComparer<int>.Default));
  44. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.GroupBy<int, int, int, int>(AsyncEnumerable.Return(42), x => x, x => x, (x, ys) => x, default(IEqualityComparer<int>)));
  45. }
  46. [Fact]
  47. public void GroupBy1()
  48. {
  49. var xs = new[] {
  50. new { Name = "Bart", Age = 27 },
  51. new { Name = "John", Age = 62 },
  52. new { Name = "Eric", Age = 27 },
  53. new { Name = "Lisa", Age = 14 },
  54. new { Name = "Brad", Age = 27 },
  55. new { Name = "Lisa", Age = 23 },
  56. new { Name = "Eric", Age = 42 },
  57. };
  58. var ys = xs.ToAsyncEnumerable();
  59. var res = ys.GroupBy(x => x.Age / 10);
  60. var e = res.GetAsyncEnumerator();
  61. Assert.True(e.MoveNextAsync().Result);
  62. Assert.Equal(2, e.Current.Key);
  63. var g1 = e.Current.GetAsyncEnumerator();
  64. HasNext(g1, xs[0]);
  65. HasNext(g1, xs[2]);
  66. HasNext(g1, xs[4]);
  67. HasNext(g1, xs[5]);
  68. NoNext(g1);
  69. Assert.True(e.MoveNextAsync().Result);
  70. Assert.Equal(6, e.Current.Key);
  71. var g2 = e.Current.GetAsyncEnumerator();
  72. HasNext(g2, xs[1]);
  73. NoNext(g2);
  74. Assert.True(e.MoveNextAsync().Result);
  75. Assert.Equal(1, e.Current.Key);
  76. var g3 = e.Current.GetAsyncEnumerator();
  77. HasNext(g3, xs[3]);
  78. NoNext(g3);
  79. Assert.True(e.MoveNextAsync().Result);
  80. Assert.Equal(4, e.Current.Key);
  81. var g4 = e.Current.GetAsyncEnumerator();
  82. HasNext(g4, xs[6]);
  83. NoNext(g4);
  84. NoNext(e);
  85. }
  86. [Fact]
  87. public void GroupBy2()
  88. {
  89. var xs = new[] {
  90. new { Name = "Bart", Age = 27 },
  91. new { Name = "John", Age = 62 },
  92. new { Name = "Eric", Age = 27 },
  93. new { Name = "Lisa", Age = 14 },
  94. new { Name = "Brad", Age = 27 },
  95. new { Name = "Lisa", Age = 23 },
  96. new { Name = "Eric", Age = 42 },
  97. };
  98. var ys = xs.ToAsyncEnumerable();
  99. var res = ys.GroupBy(x => x.Age / 10);
  100. var e = res.GetAsyncEnumerator();
  101. Assert.True(e.MoveNextAsync().Result);
  102. var g1 = e.Current;
  103. Assert.Equal(2, g1.Key);
  104. Assert.True(e.MoveNextAsync().Result);
  105. var g2 = e.Current;
  106. Assert.Equal(6, g2.Key);
  107. Assert.True(e.MoveNextAsync().Result);
  108. var g3 = e.Current;
  109. Assert.Equal(1, g3.Key);
  110. Assert.True(e.MoveNextAsync().Result);
  111. var g4 = e.Current;
  112. Assert.Equal(4, g4.Key);
  113. NoNext(e);
  114. var g1e = g1.GetAsyncEnumerator();
  115. HasNext(g1e, xs[0]);
  116. HasNext(g1e, xs[2]);
  117. HasNext(g1e, xs[4]);
  118. HasNext(g1e, xs[5]);
  119. NoNext(g1e);
  120. var g2e = g2.GetAsyncEnumerator();
  121. HasNext(g2e, xs[1]);
  122. NoNext(g2e);
  123. var g3e = g3.GetAsyncEnumerator();
  124. HasNext(g3e, xs[3]);
  125. NoNext(g3e);
  126. var g4e = g4.GetAsyncEnumerator();
  127. HasNext(g4e, xs[6]);
  128. NoNext(g4e);
  129. }
  130. [Fact]
  131. public void GroupBy3()
  132. {
  133. var xs = AsyncEnumerable.Empty<int>();
  134. var ys = xs.GroupBy(x => x);
  135. var e = ys.GetAsyncEnumerator();
  136. NoNext(e);
  137. }
  138. [Fact]
  139. public void GroupBy4()
  140. {
  141. var ex = new Exception("Bang!");
  142. var xs = AsyncEnumerable.Throw<int>(ex);
  143. var ys = xs.GroupBy(x => x);
  144. var e = ys.GetAsyncEnumerator();
  145. AssertThrows(() => e.MoveNextAsync().Wait(WaitTimeoutMs), (Exception ex_) => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
  146. }
  147. [Fact]
  148. public void GroupBy5()
  149. {
  150. var xs = GetXs().ToAsyncEnumerable();
  151. var ys = xs.GroupBy(x => x);
  152. var e = ys.GetAsyncEnumerator();
  153. AssertThrows(() => e.MoveNextAsync().Wait(WaitTimeoutMs), (Exception ex_) => ((AggregateException)ex_).Flatten().InnerExceptions.Single().Message == "Bang!");
  154. //Assert.True(e.MoveNext().Result);
  155. //var g1 = e.Current;
  156. //Assert.Equal(g1.Key, 42);
  157. //var g1e = g1.GetEnumerator();
  158. //HasNext(g1e, 42);
  159. //Assert.True(e.MoveNext().Result);
  160. //var g2 = e.Current;
  161. //Assert.Equal(g2.Key, 43);
  162. //var g2e = g2.GetEnumerator();
  163. //HasNext(g2e, 43);
  164. //AssertThrows<Exception>(() => g1e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single().Message == "Bang!");
  165. //AssertThrows<Exception>(() => g2e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single().Message == "Bang!");
  166. }
  167. [Fact]
  168. public void GroupBy6()
  169. {
  170. var xs = GetXs().ToAsyncEnumerable();
  171. var ys = xs.GroupBy(x => x);
  172. var e = ys.GetAsyncEnumerator();
  173. AssertThrows(() => e.MoveNextAsync().Wait(WaitTimeoutMs), (Exception ex_) => ((AggregateException)ex_).Flatten().InnerExceptions.Single().Message == "Bang!");
  174. //Assert.True(e.MoveNext().Result);
  175. //var g1 = e.Current;
  176. //Assert.Equal(g1.Key, 42);
  177. //var g1e = g1.GetEnumerator();
  178. //HasNext(g1e, 42);
  179. //AssertThrows<Exception>(() => g1e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single().Message == "Bang!");
  180. }
  181. static IEnumerable<int> GetXs()
  182. {
  183. yield return 42;
  184. yield return 43;
  185. throw new Exception("Bang!");
  186. }
  187. [Fact]
  188. public void GroupBy7()
  189. {
  190. var ex = new Exception("Bang!");
  191. var xs = AsyncEnumerable.Return(42);
  192. var ys = xs.GroupBy<int, int>(new Func<int, int>(x => { throw ex; }));
  193. var e = ys.GetAsyncEnumerator();
  194. AssertThrows(() => e.MoveNextAsync().Wait(WaitTimeoutMs), (Exception ex_) => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
  195. }
  196. [Fact]
  197. public void GroupBy8()
  198. {
  199. var ex = new Exception("Bang!");
  200. var xs = new[] { 1, 2, 3 }.ToAsyncEnumerable();
  201. var ys = xs.GroupBy<int, int>(x => { if (x == 3) throw ex; return x; });
  202. var e = ys.GetAsyncEnumerator();
  203. AssertThrows(() => e.MoveNextAsync().Wait(WaitTimeoutMs), (Exception ex_) => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
  204. //Assert.True(e.MoveNext().Result);
  205. //var g1 = e.Current;
  206. //Assert.Equal(g1.Key, 1);
  207. //var g1e = g1.GetEnumerator();
  208. //HasNext(g1e, 1);
  209. //Assert.True(e.MoveNext().Result);
  210. //var g2 = e.Current;
  211. //Assert.Equal(g2.Key, 2);
  212. //var g2e = g2.GetEnumerator();
  213. //HasNext(g2e, 2);
  214. //AssertThrows<Exception>(() => g1e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
  215. //AssertThrows<Exception>(() => g2e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
  216. }
  217. [Fact]
  218. public void GroupBy9()
  219. {
  220. var xs = AsyncEnumerable.Range(0, 10);
  221. var ys = xs.GroupBy(x => x % 3, x => (char)('a' + x));
  222. var e = ys.GetAsyncEnumerator();
  223. Assert.True(e.MoveNextAsync().Result);
  224. var g1 = e.Current;
  225. Assert.Equal(0, g1.Key);
  226. var g1e = g1.GetAsyncEnumerator();
  227. HasNext(g1e, 'a');
  228. HasNext(g1e, 'd');
  229. HasNext(g1e, 'g');
  230. HasNext(g1e, 'j');
  231. NoNext(g1e);
  232. Assert.True(e.MoveNextAsync().Result);
  233. var g2 = e.Current;
  234. Assert.Equal(1, g2.Key);
  235. var g2e = g2.GetAsyncEnumerator();
  236. HasNext(g2e, 'b');
  237. HasNext(g2e, 'e');
  238. HasNext(g2e, 'h');
  239. NoNext(g2e);
  240. Assert.True(e.MoveNextAsync().Result);
  241. var g3 = e.Current;
  242. Assert.Equal(2, g3.Key);
  243. var g3e = g3.GetAsyncEnumerator();
  244. HasNext(g3e, 'c');
  245. HasNext(g3e, 'f');
  246. HasNext(g3e, 'i');
  247. NoNext(g3e);
  248. NoNext(e);
  249. }
  250. [Fact]
  251. public void GroupBy10()
  252. {
  253. var xs = AsyncEnumerable.Range(0, 10);
  254. var ys = xs.GroupBy(x => x % 3, x => (char)('a' + x), (k, cs) => k + " - " + cs.Aggregate("", (a, c) => a + c).Result);
  255. var e = ys.GetAsyncEnumerator();
  256. HasNext(e, "0 - adgj");
  257. HasNext(e, "1 - beh");
  258. HasNext(e, "2 - cfi");
  259. NoNext(e);
  260. }
  261. [Fact]
  262. public void GroupBy11()
  263. {
  264. var xs = AsyncEnumerable.Range(0, 10);
  265. var ys = xs.GroupBy(x => x % 3, (k, cs) => k + " - " + cs.Aggregate("", (a, c) => a + c).Result);
  266. var e = ys.GetAsyncEnumerator();
  267. HasNext(e, "0 - 0369");
  268. HasNext(e, "1 - 147");
  269. HasNext(e, "2 - 258");
  270. NoNext(e);
  271. }
  272. [Fact]
  273. public void GroupBy12()
  274. {
  275. var xs = AsyncEnumerable.Range(0, 10);
  276. var ys = xs.GroupBy(x => x, new EqMod(3));
  277. var e = ys.GetAsyncEnumerator();
  278. Assert.True(e.MoveNextAsync().Result);
  279. var g1 = e.Current;
  280. Assert.Equal(0, g1.Key);
  281. var g1e = g1.GetAsyncEnumerator();
  282. HasNext(g1e, 0);
  283. HasNext(g1e, 3);
  284. HasNext(g1e, 6);
  285. HasNext(g1e, 9);
  286. NoNext(g1e);
  287. Assert.True(e.MoveNextAsync().Result);
  288. var g2 = e.Current;
  289. Assert.Equal(1, g2.Key);
  290. var g2e = g2.GetAsyncEnumerator();
  291. HasNext(g2e, 1);
  292. HasNext(g2e, 4);
  293. HasNext(g2e, 7);
  294. NoNext(g2e);
  295. Assert.True(e.MoveNextAsync().Result);
  296. var g3 = e.Current;
  297. Assert.Equal(2, g3.Key);
  298. var g3e = g3.GetAsyncEnumerator();
  299. HasNext(g3e, 2);
  300. HasNext(g3e, 5);
  301. HasNext(g3e, 8);
  302. NoNext(g3e);
  303. NoNext(e);
  304. }
  305. [Fact]
  306. public void GroupBy13()
  307. {
  308. var xs = AsyncEnumerable.Range(0, 10);
  309. var ys = xs.GroupBy(x => x, x => (char)('a' + x), new EqMod(3));
  310. var e = ys.GetAsyncEnumerator();
  311. Assert.True(e.MoveNextAsync().Result);
  312. var g1 = e.Current;
  313. Assert.Equal(0, g1.Key);
  314. var g1e = g1.GetAsyncEnumerator();
  315. HasNext(g1e, 'a');
  316. HasNext(g1e, 'd');
  317. HasNext(g1e, 'g');
  318. HasNext(g1e, 'j');
  319. NoNext(g1e);
  320. Assert.True(e.MoveNextAsync().Result);
  321. var g2 = e.Current;
  322. Assert.Equal(1, g2.Key);
  323. var g2e = g2.GetAsyncEnumerator();
  324. HasNext(g2e, 'b');
  325. HasNext(g2e, 'e');
  326. HasNext(g2e, 'h');
  327. NoNext(g2e);
  328. Assert.True(e.MoveNextAsync().Result);
  329. var g3 = e.Current;
  330. Assert.Equal(2, g3.Key);
  331. var g3e = g3.GetAsyncEnumerator();
  332. HasNext(g3e, 'c');
  333. HasNext(g3e, 'f');
  334. HasNext(g3e, 'i');
  335. NoNext(g3e);
  336. NoNext(e);
  337. }
  338. [Fact]
  339. public void GroupBy14()
  340. {
  341. var xs = AsyncEnumerable.Range(0, 10);
  342. var ys = xs.GroupBy(x => x, x => (char)('a' + x), (k, cs) => k + " - " + cs.Aggregate("", (a, c) => a + c).Result, new EqMod(3));
  343. var e = ys.GetAsyncEnumerator();
  344. HasNext(e, "0 - adgj");
  345. HasNext(e, "1 - beh");
  346. HasNext(e, "2 - cfi");
  347. NoNext(e);
  348. }
  349. [Fact]
  350. public void GroupBy15()
  351. {
  352. var xs = AsyncEnumerable.Range(0, 10);
  353. var ys = xs.GroupBy(x => x, (k, cs) => k + " - " + cs.Aggregate("", (a, c) => a + c).Result, new EqMod(3));
  354. var e = ys.GetAsyncEnumerator();
  355. HasNext(e, "0 - 0369");
  356. HasNext(e, "1 - 147");
  357. HasNext(e, "2 - 258");
  358. NoNext(e);
  359. }
  360. [Fact]
  361. public async Task GroupBy16()
  362. {
  363. var xs = AsyncEnumerable.Range(0, 10);
  364. var ys = xs.GroupBy(x => x, x => (char)('a' + x), new EqMod(3));
  365. var e = ys.GetAsyncEnumerator();
  366. Assert.True(e.MoveNextAsync().Result);
  367. var g1 = e.Current;
  368. Assert.Equal(0, g1.Key);
  369. var g1e = g1.GetAsyncEnumerator();
  370. HasNext(g1e, 'a');
  371. HasNext(g1e, 'd');
  372. HasNext(g1e, 'g');
  373. HasNext(g1e, 'j');
  374. NoNext(g1e);
  375. await g1e.DisposeAsync();
  376. Assert.True(e.MoveNextAsync().Result);
  377. var g2 = e.Current;
  378. Assert.Equal(1, g2.Key);
  379. var g2e = g2.GetAsyncEnumerator();
  380. HasNext(g2e, 'b');
  381. HasNext(g2e, 'e');
  382. HasNext(g2e, 'h');
  383. NoNext(g2e);
  384. await g2e.DisposeAsync();
  385. Assert.True(e.MoveNextAsync().Result);
  386. var g3 = e.Current;
  387. Assert.Equal(2, g3.Key);
  388. var g3e = g3.GetAsyncEnumerator();
  389. HasNext(g3e, 'c');
  390. HasNext(g3e, 'f');
  391. HasNext(g3e, 'i');
  392. NoNext(g3e);
  393. await g3e.DisposeAsync();
  394. NoNext(e);
  395. await e.DisposeAsync();
  396. }
  397. [Fact]
  398. public async Task GroupBy17()
  399. {
  400. var xs = AsyncEnumerable.Range(0, 10);
  401. var ys = xs.GroupBy(x => x, x => (char)('a' + x), new EqMod(3));
  402. var e = ys.GetAsyncEnumerator();
  403. await e.DisposeAsync();
  404. Assert.False(e.MoveNextAsync().Result);
  405. }
  406. [Fact]
  407. public async Task GroupBy18()
  408. {
  409. var xs = AsyncEnumerable.Range(0, 10);
  410. var ys = xs.GroupBy(x => x, x => (char)('a' + x), new EqMod(3));
  411. var e = ys.GetAsyncEnumerator();
  412. Assert.True(e.MoveNextAsync().Result);
  413. var g1 = e.Current;
  414. Assert.Equal(0, g1.Key);
  415. var g1e = g1.GetAsyncEnumerator();
  416. HasNext(g1e, 'a');
  417. await e.DisposeAsync();
  418. HasNext(g1e, 'd');
  419. HasNext(g1e, 'g');
  420. HasNext(g1e, 'j');
  421. NoNext(g1e);
  422. await g1e.DisposeAsync();
  423. Assert.False(e.MoveNextAsync().Result);
  424. }
  425. [Fact]
  426. public async Task GroupBy19()
  427. {
  428. // We're using Kvp here because the types will eval as equal for this test
  429. var xs = new[]
  430. {
  431. new Kvp("Bart", 27),
  432. new Kvp("John", 62),
  433. new Kvp("Eric", 27),
  434. new Kvp("Lisa", 14),
  435. new Kvp("Brad", 27),
  436. new Kvp("Lisa", 23),
  437. new Kvp("Eric", 42)
  438. };
  439. var ys = xs.ToAsyncEnumerable();
  440. var res = ys.GroupBy(x => x.Item / 10);
  441. await SequenceIdentity(res);
  442. }
  443. [Fact]
  444. public async Task GroupBy20()
  445. {
  446. var xs = AsyncEnumerable.Range(0, 10);
  447. var ys = xs.GroupBy(x => x % 3, x => (char)('a' + x), (k, cs) => k + " - " + cs.Aggregate("", (a, c) => a + c).Result);
  448. var arr = new[] { "0 - adgj", "1 - beh", "2 - cfi" };
  449. Assert.Equal(arr, await ys.ToArray());
  450. }
  451. [Fact]
  452. public async Task GroupBy21()
  453. {
  454. var xs = AsyncEnumerable.Range(0, 10);
  455. var ys = xs.GroupBy(x => x % 3, x => (char)('a' + x), (k, cs) => k + " - " + cs.Aggregate("", (a, c) => a + c).Result);
  456. var arr = new List<string> { "0 - adgj", "1 - beh", "2 - cfi" };
  457. Assert.Equal(arr, await ys.ToList());
  458. }
  459. [Fact]
  460. public async Task GroupBy22()
  461. {
  462. var xs = AsyncEnumerable.Range(0, 10);
  463. var ys = xs.GroupBy(x => x % 3, x => (char)('a' + x), (k, cs) => k + " - " + cs.Aggregate("", (a, c) => a + c).Result);
  464. Assert.Equal(3, await ys.Count());
  465. }
  466. [Fact]
  467. public async Task GroupBy23()
  468. {
  469. var xs = AsyncEnumerable.Range(0, 10);
  470. var ys = xs.GroupBy(x => x % 3, x => (char)('a' + x), (k, cs) => k + " - " + cs.Aggregate("", (a, c) => a + c).Result);
  471. await SequenceIdentity(ys);
  472. }
  473. [Fact]
  474. public async Task GroupBy24()
  475. {
  476. var xs = AsyncEnumerable.Range(0, 10);
  477. var ys = xs.GroupBy(x => x % 3, x => (char)('a' + x));
  478. var g1a = new[] { 'a', 'd', 'g', 'j' };
  479. var g2a = new[] { 'b', 'e', 'h' };
  480. var g3a = new[] { 'c', 'f', 'i' };
  481. var gar = await ys.ToArray();
  482. Assert.Equal(3, gar.Length);
  483. var gg1 = gar[0];
  484. var gg1a = await gg1.ToArray();
  485. Assert.Equal(g1a, gg1a);
  486. var gg2 = gar[1];
  487. var gg2a = await gg2.ToArray();
  488. Assert.Equal(g2a, gg2a);
  489. var gg3 = gar[2];
  490. var gg3a = await gg3.ToArray();
  491. Assert.Equal(g3a, gg3a);
  492. }
  493. [Fact]
  494. public async Task GroupBy25()
  495. {
  496. var xs = AsyncEnumerable.Range(0, 10);
  497. var ys = xs.GroupBy(x => x % 3, x => (char)('a' + x));
  498. var g1a = new List<char> { 'a', 'd', 'g', 'j' };
  499. var g2a = new List<char> { 'b', 'e', 'h' };
  500. var g3a = new List<char> { 'c', 'f', 'i' };
  501. var gar = await ys.ToList();
  502. Assert.Equal(3, gar.Count);
  503. var gg1 = gar[0];
  504. var gg1a = await gg1.ToList();
  505. Assert.Equal(g1a, gg1a);
  506. var gg2 = gar[1];
  507. var gg2a = await gg2.ToList();
  508. Assert.Equal(g2a, gg2a);
  509. var gg3 = gar[2];
  510. var gg3a = await gg3.ToList();
  511. Assert.Equal(g3a, gg3a);
  512. }
  513. [Fact]
  514. public async Task GroupBy26()
  515. {
  516. var xs = AsyncEnumerable.Range(0, 10);
  517. var ys = xs.GroupBy(x => x % 3, x => (char)('a' + x));
  518. var gar = await ys.ToList();
  519. Assert.Equal(3, gar.Count);
  520. var gg1 = gar[0];
  521. var gg1a = await gg1.Count();
  522. Assert.Equal(4, gg1a);
  523. var gg2 = gar[1];
  524. var gg2a = await gg2.Count();
  525. Assert.Equal(3, gg2a);
  526. var gg3 = gar[2];
  527. var gg3a = await gg3.Count();
  528. Assert.Equal(3, gg3a);
  529. }
  530. [Fact]
  531. public async Task GroupBy27()
  532. {
  533. var xs = AsyncEnumerable.Range(0, 10);
  534. var ys = xs.GroupBy(x => x % 3, x => (char)('a' + x));
  535. var gar = await ys.Count();
  536. Assert.Equal(3, gar);
  537. }
  538. [Fact]
  539. public async Task GroupBy28()
  540. {
  541. var xs = AsyncEnumerable.Range(0, 10);
  542. var ys = xs.GroupBy(x => x % 3, x => (char)('a' + x));
  543. await SequenceIdentity(ys);
  544. }
  545. [Fact]
  546. public async Task GroupBy29()
  547. {
  548. var xs = AsyncEnumerable.Range(0, 10);
  549. var ys = xs.GroupBy(x => x, new EqMod(3));
  550. var g1a = new List<int> { 0, 3, 6, 9 };
  551. var g2a = new List<int> { 1, 4, 7 };
  552. var g3a = new List<int> { 2, 5, 8 };
  553. var gar = await ys.ToList();
  554. Assert.Equal(3, gar.Count);
  555. var gg1 = gar[0];
  556. var gg1a = await gg1.ToList();
  557. Assert.Equal(g1a, gg1a);
  558. var gg2 = gar[1];
  559. var gg2a = await gg2.ToList();
  560. Assert.Equal(g2a, gg2a);
  561. var gg3 = gar[2];
  562. var gg3a = await gg3.ToList();
  563. Assert.Equal(g3a, gg3a);
  564. }
  565. [Fact]
  566. public async Task GroupBy30()
  567. {
  568. var xs = AsyncEnumerable.Range(0, 10);
  569. var ys = xs.GroupBy(x => x, new EqMod(3));
  570. var gar = await ys.ToList();
  571. Assert.Equal(3, gar.Count);
  572. var gg1 = gar[0];
  573. var gg1a = await gg1.Count();
  574. Assert.Equal(4, gg1a);
  575. var gg2 = gar[1];
  576. var gg2a = await gg2.Count();
  577. Assert.Equal(3, gg2a);
  578. var gg3 = gar[2];
  579. var gg3a = await gg3.Count();
  580. Assert.Equal(3, gg3a);
  581. }
  582. [Fact]
  583. public async Task GroupBy31()
  584. {
  585. var xs = AsyncEnumerable.Range(0, 10);
  586. var ys = xs.GroupBy(x => x, new EqMod(3));
  587. var g1a = new[] { 0, 3, 6, 9 };
  588. var g2a = new[] { 1, 4, 7 };
  589. var g3a = new[] { 2, 5, 8 };
  590. var gar = await ys.ToArray();
  591. Assert.Equal(3, gar.Length);
  592. var gg1 = gar[0];
  593. var gg1a = await gg1.ToArray();
  594. Assert.Equal(g1a, gg1a);
  595. var gg2 = gar[1];
  596. var gg2a = await gg2.ToArray();
  597. Assert.Equal(g2a, gg2a);
  598. var gg3 = gar[2];
  599. var gg3a = await gg3.ToArray();
  600. Assert.Equal(g3a, gg3a);
  601. }
  602. [Fact]
  603. public async Task GroupBy32()
  604. {
  605. var xs = AsyncEnumerable.Range(0, 10);
  606. var ys = xs.GroupBy(x => x, new EqMod(3));
  607. var gar = await ys.Count();
  608. Assert.Equal(3, gar);
  609. }
  610. [Fact]
  611. public async Task GroupBy33()
  612. {
  613. var xs = AsyncEnumerable.Range(0, 10);
  614. var ys = xs.GroupBy(x => x, new EqMod(3));
  615. await SequenceIdentity(ys);
  616. }
  617. [Fact]
  618. public async Task GroupBy34()
  619. {
  620. var xs = AsyncEnumerable.Range(0, 10);
  621. var ys = xs.GroupBy(x => x, (k, cs) => k + " - " + cs.Aggregate("", (a, c) => a + c).Result, new EqMod(3));
  622. var arr = new[] { "0 - 0369", "1 - 147", "2 - 258" };
  623. Assert.Equal(arr, await ys.ToArray());
  624. }
  625. [Fact]
  626. public async Task GroupBy35()
  627. {
  628. var xs = AsyncEnumerable.Range(0, 10);
  629. var ys = xs.GroupBy(x => x, (k, cs) => k + " - " + cs.Aggregate("", (a, c) => a + c).Result, new EqMod(3));
  630. var arr = new List<string> { "0 - 0369", "1 - 147", "2 - 258" };
  631. Assert.Equal(arr, await ys.ToList());
  632. }
  633. [Fact]
  634. public async Task GroupBy36()
  635. {
  636. var xs = AsyncEnumerable.Range(0, 10);
  637. var ys = xs.GroupBy(x => x, (k, cs) => k + " - " + cs.Aggregate("", (a, c) => a + c).Result, new EqMod(3));
  638. Assert.Equal(3, await ys.Count());
  639. }
  640. [Fact]
  641. public async Task GroupBy37()
  642. {
  643. var xs = AsyncEnumerable.Range(0, 10);
  644. var ys = xs.GroupBy(x => x, (k, cs) => k + " - " + cs.Aggregate("", (a, c) => a + c).Result, new EqMod(3));
  645. await SequenceIdentity(ys);
  646. }
  647. private sealed class EqMod : IEqualityComparer<int>
  648. {
  649. private readonly int _d;
  650. public EqMod(int d)
  651. {
  652. _d = d;
  653. }
  654. public bool Equals(int x, int y)
  655. {
  656. return EqualityComparer<int>.Default.Equals(x % _d, y % _d);
  657. }
  658. public int GetHashCode(int obj)
  659. {
  660. return EqualityComparer<int>.Default.GetHashCode(obj % _d);
  661. }
  662. }
  663. private sealed class Kvp : IEquatable<Kvp>
  664. {
  665. public Kvp(string key, int item)
  666. {
  667. Key = key;
  668. Item = item;
  669. }
  670. public string Key { get; }
  671. public int Item { get; }
  672. public bool Equals(Kvp other)
  673. {
  674. if (ReferenceEquals(null, other)) return false;
  675. if (ReferenceEquals(this, other)) return true;
  676. return string.Equals(Key, other.Key) && Item == other.Item;
  677. }
  678. public override bool Equals(object obj)
  679. {
  680. if (ReferenceEquals(null, obj)) return false;
  681. if (ReferenceEquals(this, obj)) return true;
  682. if (obj.GetType() != GetType()) return false;
  683. return Equals((Kvp)obj);
  684. }
  685. public override int GetHashCode()
  686. {
  687. unchecked
  688. {
  689. return ((Key != null ? Key.GetHashCode() : 0) * 397) ^ Item;
  690. }
  691. }
  692. public static bool operator ==(Kvp left, Kvp right)
  693. {
  694. return Equals(left, right);
  695. }
  696. public static bool operator !=(Kvp left, Kvp right)
  697. {
  698. return !Equals(left, right);
  699. }
  700. }
  701. }
  702. }