AsyncTests.Aggregates.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  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 Xunit;
  8. using System.Collections;
  9. using System.Threading;
  10. using System.Threading.Tasks;
  11. // ReSharper disable InvokeAsExtensionMethod
  12. // ReSharper disable InconsistentNaming
  13. // ReSharper disable RedundantTypeArgumentsOfMethod
  14. namespace Tests
  15. {
  16. public partial class AsyncTests
  17. {
  18. private const int WaitTimeoutMs = 5000;
  19. [Fact]
  20. public async Task IsEmpty_Null()
  21. {
  22. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.IsEmpty<int>(null));
  23. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.IsEmpty<int>(null, CancellationToken.None));
  24. }
  25. [Fact]
  26. public async Task ToLookup_Null()
  27. {
  28. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ToLookup<int, int>(default(IAsyncEnumerable<int>), x => 0));
  29. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ToLookup<int, int>(AsyncEnumerable.Return(42), default(Func<int, int>)));
  30. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ToLookup<int, int>(default(IAsyncEnumerable<int>), x => 0, EqualityComparer<int>.Default));
  31. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ToLookup<int, int>(AsyncEnumerable.Return(42), default(Func<int, int>), EqualityComparer<int>.Default));
  32. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ToLookup<int, int>(AsyncEnumerable.Return(42), x => 0, default(IEqualityComparer<int>)));
  33. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ToLookup<int, int, int>(default(IAsyncEnumerable<int>), x => 0, x => 0));
  34. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ToLookup<int, int, int>(AsyncEnumerable.Return(42), default(Func<int, int>), x => 0));
  35. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ToLookup<int, int, int>(AsyncEnumerable.Return(42), x => 0, default(Func<int, int>)));
  36. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ToLookup<int, int, int>(default(IAsyncEnumerable<int>), x => 0, x => 0, EqualityComparer<int>.Default));
  37. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ToLookup<int, int, int>(AsyncEnumerable.Return(42), default(Func<int, int>), x => 0, EqualityComparer<int>.Default));
  38. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ToLookup<int, int, int>(AsyncEnumerable.Return(42), x => 0, default(Func<int, int>), EqualityComparer<int>.Default));
  39. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ToLookup<int, int, int>(AsyncEnumerable.Return(42), x => 0, x => 0, default(IEqualityComparer<int>)));
  40. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ToLookup<int, int>(default(IAsyncEnumerable<int>), x => 0, CancellationToken.None));
  41. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ToLookup<int, int>(AsyncEnumerable.Return(42), default(Func<int, int>), CancellationToken.None));
  42. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ToLookup<int, int>(default(IAsyncEnumerable<int>), x => 0, EqualityComparer<int>.Default, CancellationToken.None));
  43. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ToLookup<int, int>(AsyncEnumerable.Return(42), default(Func<int, int>), EqualityComparer<int>.Default, CancellationToken.None));
  44. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ToLookup<int, int>(AsyncEnumerable.Return(42), x => 0, default(IEqualityComparer<int>), CancellationToken.None));
  45. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ToLookup<int, int, int>(default(IAsyncEnumerable<int>), x => 0, x => 0, CancellationToken.None));
  46. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ToLookup<int, int, int>(AsyncEnumerable.Return(42), default(Func<int, int>), x => 0, CancellationToken.None));
  47. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ToLookup<int, int, int>(AsyncEnumerable.Return(42), x => 0, default(Func<int, int>), CancellationToken.None));
  48. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ToLookup<int, int, int>(default(IAsyncEnumerable<int>), x => 0, x => 0, EqualityComparer<int>.Default, CancellationToken.None));
  49. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ToLookup<int, int, int>(AsyncEnumerable.Return(42), default(Func<int, int>), x => 0, EqualityComparer<int>.Default, CancellationToken.None));
  50. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ToLookup<int, int, int>(AsyncEnumerable.Return(42), x => 0, default(Func<int, int>), EqualityComparer<int>.Default, CancellationToken.None));
  51. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ToLookup<int, int, int>(AsyncEnumerable.Return(42), x => 0, x => 0, default(IEqualityComparer<int>), CancellationToken.None));
  52. }
  53. [Fact]
  54. public void ToLookup1()
  55. {
  56. var xs = new[] { 1, 4 }.ToAsyncEnumerable();
  57. var res = xs.ToLookup(x => x % 2).Result;
  58. Assert.True(res.Contains(0));
  59. Assert.True(res.Contains(1));
  60. Assert.True(res[0].Contains(4));
  61. Assert.True(res[1].Contains(1));
  62. Assert.True(res.Count == 2);
  63. }
  64. [Fact]
  65. public void ToLookup2()
  66. {
  67. var xs = new[] { 1, 4, 2 }.ToAsyncEnumerable();
  68. var res = xs.ToLookup(x => x % 2).Result;
  69. Assert.True(res.Contains(0));
  70. Assert.True(res.Contains(1));
  71. Assert.True(res[0].Contains(4));
  72. Assert.True(res[0].Contains(2));
  73. Assert.True(res[1].Contains(1));
  74. Assert.True(res.Count == 2);
  75. }
  76. [Fact]
  77. public void ToLookup3()
  78. {
  79. var xs = new[] { 1, 4 }.ToAsyncEnumerable();
  80. var res = xs.ToLookup(x => x % 2, x => x + 1).Result;
  81. Assert.True(res.Contains(0));
  82. Assert.True(res.Contains(1));
  83. Assert.True(res[0].Contains(5));
  84. Assert.True(res[1].Contains(2));
  85. Assert.True(res.Count == 2);
  86. }
  87. [Fact]
  88. public void ToLookup4()
  89. {
  90. var xs = new[] { 1, 4, 2 }.ToAsyncEnumerable();
  91. var res = xs.ToLookup(x => x % 2, x => x + 1).Result;
  92. Assert.True(res.Contains(0));
  93. Assert.True(res.Contains(1));
  94. Assert.True(res[0].Contains(5));
  95. Assert.True(res[0].Contains(3));
  96. Assert.True(res[1].Contains(2));
  97. Assert.True(res.Count == 2);
  98. }
  99. [Fact]
  100. public void ToLookup5()
  101. {
  102. var xs = new[] { 1, 4 }.ToAsyncEnumerable();
  103. var res = xs.ToLookup(x => x % 2, new Eq()).Result;
  104. Assert.True(res.Contains(0));
  105. Assert.True(res.Contains(1));
  106. Assert.True(res[0].Contains(4));
  107. Assert.True(res[1].Contains(1));
  108. Assert.True(res.Count == 2);
  109. }
  110. [Fact]
  111. public void ToLookup6()
  112. {
  113. var xs = new[] { 1, 4, 2 }.ToAsyncEnumerable();
  114. var res = xs.ToLookup(x => x % 2, new Eq()).Result;
  115. Assert.True(res.Contains(0));
  116. Assert.True(res.Contains(1));
  117. Assert.True(res[0].Contains(4));
  118. Assert.True(res[0].Contains(2));
  119. Assert.True(res[1].Contains(1));
  120. Assert.True(res.Count == 2);
  121. }
  122. [Fact]
  123. public void ToLookup7()
  124. {
  125. var xs = new[] { 1, 4, 2 }.ToAsyncEnumerable();
  126. var res = xs.ToLookup(x => x % 2).Result;
  127. foreach (var g in res)
  128. Assert.True(g.Key == 0 || g.Key == 1);
  129. }
  130. [Fact]
  131. public void ToLookup8()
  132. {
  133. var xs = new[] { 1, 4, 2 }.ToAsyncEnumerable();
  134. var res = xs.ToLookup(x => x % 2).Result;
  135. #pragma warning disable IDE0007 // Use implicit type
  136. foreach (IGrouping<int, int> g in (IEnumerable)res)
  137. Assert.True(g.Key == 0 || g.Key == 1);
  138. #pragma warning restore IDE0007 // Use implicit type
  139. }
  140. [Fact]
  141. public void ToLookup9()
  142. {
  143. var xs = new[] { 1, 4, 2 }.ToAsyncEnumerable();
  144. var res = xs.ToLookup(x => x % 2, x => x, new Eq()).Result;
  145. Assert.True(res.Contains(0));
  146. Assert.True(res.Contains(1));
  147. Assert.True(res[0].Contains(4));
  148. Assert.True(res[0].Contains(2));
  149. Assert.True(res[1].Contains(1));
  150. Assert.True(res.Count == 2);
  151. }
  152. [Fact]
  153. public async Task Min_Null()
  154. {
  155. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.Min(default(IAsyncEnumerable<DateTime>), Comparer<DateTime>.Default));
  156. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.Min(AsyncEnumerable.Empty<DateTime>(), default(IComparer<DateTime>)));
  157. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.Min(default(IAsyncEnumerable<DateTime>), Comparer<DateTime>.Default, CancellationToken.None));
  158. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.Min(AsyncEnumerable.Empty<DateTime>(), default(IComparer<DateTime>), CancellationToken.None));
  159. }
  160. [Fact]
  161. public async Task Max_Null()
  162. {
  163. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.Max(default(IAsyncEnumerable<DateTime>), Comparer<DateTime>.Default));
  164. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.Max(AsyncEnumerable.Empty<DateTime>(), default(IComparer<DateTime>)));
  165. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.Max(default(IAsyncEnumerable<DateTime>), Comparer<DateTime>.Default, CancellationToken.None));
  166. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.Max(AsyncEnumerable.Empty<DateTime>(), default(IComparer<DateTime>), CancellationToken.None));
  167. }
  168. [Fact]
  169. public async Task MinBy_Null()
  170. {
  171. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.MinBy(default(IAsyncEnumerable<int>), x => x));
  172. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.MinBy(AsyncEnumerable.Return(42), default(Func<int, int>)));
  173. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.MinBy(default(IAsyncEnumerable<int>), x => x, Comparer<int>.Default));
  174. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.MinBy(AsyncEnumerable.Return(42), default(Func<int, int>), Comparer<int>.Default));
  175. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.MinBy(AsyncEnumerable.Return(42), x => x, default(IComparer<int>)));
  176. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.MinBy(default(IAsyncEnumerable<int>), x => x, CancellationToken.None));
  177. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.MinBy(AsyncEnumerable.Return(42), default(Func<int, int>), CancellationToken.None));
  178. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.MinBy(default(IAsyncEnumerable<int>), x => x, Comparer<int>.Default, CancellationToken.None));
  179. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.MinBy(AsyncEnumerable.Return(42), default(Func<int, int>), Comparer<int>.Default, CancellationToken.None));
  180. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.MinBy(AsyncEnumerable.Return(42), x => x, default(IComparer<int>), CancellationToken.None));
  181. }
  182. [Fact]
  183. public void MinBy1()
  184. {
  185. var xs = new[] { 3, 5, 7, 6, 4, 2 }.ToAsyncEnumerable().MinBy(x => x / 2);
  186. var res = xs.Result;
  187. Assert.True(res.SequenceEqual(new[] { 3, 2 }));
  188. }
  189. [Fact]
  190. public void MinBy2()
  191. {
  192. var xs = new int[0].ToAsyncEnumerable().MinBy(x => x / 2);
  193. AssertThrows<Exception>(() => xs.Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() is InvalidOperationException);
  194. }
  195. [Fact]
  196. public void MinBy3()
  197. {
  198. var ex = new Exception("Bang!");
  199. var xs = new[] { 3, 5, 7, 6, 4, 2 }.ToAsyncEnumerable().MinBy(x => { if (x == 3) throw ex; return x; });
  200. AssertThrows<Exception>(() => xs.Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
  201. }
  202. [Fact]
  203. public void MinBy4()
  204. {
  205. var ex = new Exception("Bang!");
  206. var xs = new[] { 3, 5, 7, 6, 4, 2 }.ToAsyncEnumerable().MinBy(x => { if (x == 4) throw ex; return x; });
  207. AssertThrows<Exception>(() => xs.Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
  208. }
  209. [Fact]
  210. public void MinBy5()
  211. {
  212. var ex = new Exception("Bang!");
  213. var xs = new[] { 3, 5, 7, 6, 4, 2 }.ToAsyncEnumerable().Concat(AsyncEnumerable.Throw<int>(ex)).MinBy(x => x, Comparer<int>.Default);
  214. AssertThrows<Exception>(() => xs.Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
  215. }
  216. [Fact]
  217. public async Task MaxBy_Null()
  218. {
  219. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.MaxBy(default(IAsyncEnumerable<int>), x => x));
  220. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.MaxBy(AsyncEnumerable.Return(42), default(Func<int, int>)));
  221. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.MaxBy(default(IAsyncEnumerable<int>), x => x, Comparer<int>.Default));
  222. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.MaxBy(AsyncEnumerable.Return(42), default(Func<int, int>), Comparer<int>.Default));
  223. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.MaxBy(AsyncEnumerable.Return(42), x => x, default(IComparer<int>)));
  224. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.MaxBy(default(IAsyncEnumerable<int>), x => x, CancellationToken.None));
  225. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.MaxBy(AsyncEnumerable.Return(42), default(Func<int, int>), CancellationToken.None));
  226. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.MaxBy(default(IAsyncEnumerable<int>), x => x, Comparer<int>.Default, CancellationToken.None));
  227. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.MaxBy(AsyncEnumerable.Return(42), default(Func<int, int>), Comparer<int>.Default, CancellationToken.None));
  228. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.MaxBy(AsyncEnumerable.Return(42), x => x, default(IComparer<int>), CancellationToken.None));
  229. }
  230. [Fact]
  231. public void MaxBy1()
  232. {
  233. var xs = new[] { 3, 5, 7, 6, 4, 2 }.ToAsyncEnumerable().MaxBy(x => x / 2);
  234. var res = xs.Result;
  235. Assert.True(res.SequenceEqual(new[] { 7, 6 }));
  236. }
  237. [Fact]
  238. public void MaxBy2()
  239. {
  240. var xs = new int[0].ToAsyncEnumerable().MaxBy(x => x / 2);
  241. AssertThrows<Exception>(() => xs.Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() is InvalidOperationException);
  242. }
  243. [Fact]
  244. public void MaxBy3()
  245. {
  246. var ex = new Exception("Bang!");
  247. var xs = new[] { 3, 5, 7, 6, 4, 2 }.ToAsyncEnumerable().MaxBy(x => { if (x == 3) throw ex; return x; });
  248. AssertThrows<Exception>(() => xs.Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
  249. }
  250. [Fact]
  251. public void MaxBy4()
  252. {
  253. var ex = new Exception("Bang!");
  254. var xs = new[] { 3, 5, 7, 6, 4, 2 }.ToAsyncEnumerable().MaxBy(x => { if (x == 4) throw ex; return x; });
  255. AssertThrows<Exception>(() => xs.Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
  256. }
  257. [Fact]
  258. public void MaxBy5()
  259. {
  260. var ex = new Exception("Bang!");
  261. var xs = new[] { 3, 5, 7, 6, 4, 2 }.ToAsyncEnumerable().Concat(AsyncEnumerable.Throw<int>(ex)).MaxBy(x => x, Comparer<int>.Default);
  262. AssertThrows<Exception>(() => xs.Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
  263. }
  264. private sealed class Eq : IEqualityComparer<int>
  265. {
  266. public bool Equals(int x, int y)
  267. {
  268. return EqualityComparer<int>.Default.Equals(Math.Abs(x), Math.Abs(y));
  269. }
  270. public int GetHashCode(int obj)
  271. {
  272. return EqualityComparer<int>.Default.GetHashCode(Math.Abs(obj));
  273. }
  274. }
  275. }
  276. }