GroupBy.cs 30 KB

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