1
0

Amb.cs 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the MIT 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 Amb : AsyncEnumerableExTests
  13. {
  14. [Fact]
  15. public void Amb_Null()
  16. {
  17. Assert.Throws<ArgumentNullException>(() => AsyncEnumerableEx.Amb(default, Return42));
  18. Assert.Throws<ArgumentNullException>(() => AsyncEnumerableEx.Amb(Return42, default));
  19. }
  20. [Fact]
  21. public async Task Amb_First_Wins()
  22. {
  23. var source = AsyncEnumerable.Range(1, 5).Amb(AsyncEnumerableEx.Never<int>());
  24. var xs = source.GetAsyncEnumerator();
  25. try
  26. {
  27. for (var i = 1; i <= 5; i++)
  28. {
  29. Assert.True(await xs.MoveNextAsync());
  30. Assert.Equal(i, xs.Current);
  31. }
  32. Assert.False(await xs.MoveNextAsync());
  33. }
  34. finally
  35. {
  36. await xs.DisposeAsync();
  37. }
  38. }
  39. [Fact]
  40. public async Task Amb_First_Wins_Alt()
  41. {
  42. var source = AsyncEnumerable.Range(1, 5).Amb(AsyncEnumerable.Range(1, 5).SelectAwait(async v =>
  43. {
  44. await Task.Delay(500);
  45. return v;
  46. }));
  47. var xs = source.GetAsyncEnumerator();
  48. try
  49. {
  50. for (var i = 1; i <= 5; i++)
  51. {
  52. Assert.True(await xs.MoveNextAsync());
  53. Assert.Equal(i, xs.Current);
  54. }
  55. Assert.False(await xs.MoveNextAsync());
  56. }
  57. finally
  58. {
  59. await xs.DisposeAsync();
  60. }
  61. }
  62. [Fact]
  63. public async Task Amb_Second_Wins()
  64. {
  65. var source = AsyncEnumerableEx.Never<int>().Amb(AsyncEnumerable.Range(1, 5));
  66. var xs = source.GetAsyncEnumerator();
  67. try
  68. {
  69. for (var i = 1; i <= 5; i++)
  70. {
  71. Assert.True(await xs.MoveNextAsync());
  72. Assert.Equal(i, xs.Current);
  73. }
  74. Assert.False(await xs.MoveNextAsync());
  75. }
  76. finally
  77. {
  78. await xs.DisposeAsync();
  79. }
  80. }
  81. [Fact]
  82. public async Task Amb_Second_Wins_Alt()
  83. {
  84. var source = AsyncEnumerable.Range(1, 5).SelectAwait(async v =>
  85. {
  86. await Task.Delay(500);
  87. return v;
  88. }).Amb(AsyncEnumerable.Range(6, 5));
  89. var xs = source.GetAsyncEnumerator();
  90. try
  91. {
  92. for (var i = 1; i <= 5; i++)
  93. {
  94. Assert.True(await xs.MoveNextAsync());
  95. Assert.Equal(i + 5, xs.Current);
  96. }
  97. Assert.False(await xs.MoveNextAsync());
  98. }
  99. finally
  100. {
  101. await xs.DisposeAsync();
  102. }
  103. }
  104. [Fact]
  105. public async Task Amb_Many_First_Wins()
  106. {
  107. var source = AsyncEnumerableEx.Amb(
  108. AsyncEnumerable.Range(1, 5),
  109. AsyncEnumerableEx.Never<int>(),
  110. AsyncEnumerableEx.Never<int>()
  111. );
  112. var xs = source.GetAsyncEnumerator();
  113. try
  114. {
  115. for (var i = 1; i <= 5; i++)
  116. {
  117. Assert.True(await xs.MoveNextAsync());
  118. Assert.Equal(i, xs.Current);
  119. }
  120. Assert.False(await xs.MoveNextAsync());
  121. }
  122. finally
  123. {
  124. await xs.DisposeAsync();
  125. }
  126. }
  127. [Fact]
  128. public async Task Amb_Many_Last_Wins()
  129. {
  130. var source = AsyncEnumerableEx.Amb(
  131. AsyncEnumerableEx.Never<int>(),
  132. AsyncEnumerableEx.Never<int>(),
  133. AsyncEnumerable.Range(1, 5)
  134. );
  135. var xs = source.GetAsyncEnumerator();
  136. try
  137. {
  138. for (var i = 1; i <= 5; i++)
  139. {
  140. Assert.True(await xs.MoveNextAsync());
  141. Assert.Equal(i, xs.Current);
  142. }
  143. Assert.False(await xs.MoveNextAsync());
  144. }
  145. finally
  146. {
  147. await xs.DisposeAsync();
  148. }
  149. }
  150. [Fact]
  151. public async Task Amb_Many_Enum_First_Wins()
  152. {
  153. var source = AsyncEnumerableEx.Amb(new[] {
  154. AsyncEnumerable.Range(1, 5),
  155. AsyncEnumerableEx.Never<int>(),
  156. AsyncEnumerableEx.Never<int>()
  157. }.AsEnumerable()
  158. );
  159. var xs = source.GetAsyncEnumerator();
  160. try
  161. {
  162. for (var i = 1; i <= 5; i++)
  163. {
  164. Assert.True(await xs.MoveNextAsync());
  165. Assert.Equal(i, xs.Current);
  166. }
  167. Assert.False(await xs.MoveNextAsync());
  168. }
  169. finally
  170. {
  171. await xs.DisposeAsync();
  172. }
  173. }
  174. [Fact]
  175. public async Task Amb_Many_Enum_Last_Wins()
  176. {
  177. var source = AsyncEnumerableEx.Amb(new[] {
  178. AsyncEnumerableEx.Never<int>(),
  179. AsyncEnumerableEx.Never<int>(),
  180. AsyncEnumerable.Range(1, 5)
  181. }.AsEnumerable()
  182. );
  183. var xs = source.GetAsyncEnumerator();
  184. try
  185. {
  186. for (var i = 1; i <= 5; i++)
  187. {
  188. Assert.True(await xs.MoveNextAsync());
  189. Assert.Equal(i, xs.Current);
  190. }
  191. Assert.False(await xs.MoveNextAsync());
  192. }
  193. finally
  194. {
  195. await xs.DisposeAsync();
  196. }
  197. }
  198. [Fact]
  199. public async Task Amb_First_GetAsyncEnumerator_Crashes()
  200. {
  201. var source = new FailingGetAsyncEnumerator<int>().Amb(AsyncEnumerableEx.Never<int>());
  202. var xs = source.GetAsyncEnumerator();
  203. try
  204. {
  205. await xs.MoveNextAsync();
  206. Assert.Fail("Should not have gotten here");
  207. }
  208. catch (InvalidOperationException)
  209. {
  210. // we expect this
  211. }
  212. finally
  213. {
  214. await xs.DisposeAsync();
  215. }
  216. }
  217. [Fact]
  218. public async Task Amb_Second_GetAsyncEnumerator_Crashes()
  219. {
  220. var source = AsyncEnumerableEx.Never<int>().Amb(new FailingGetAsyncEnumerator<int>());
  221. var xs = source.GetAsyncEnumerator();
  222. try
  223. {
  224. await xs.MoveNextAsync();
  225. Assert.Fail("Should not have gotten here");
  226. }
  227. catch (InvalidOperationException)
  228. {
  229. // we expect this
  230. }
  231. finally
  232. {
  233. await xs.DisposeAsync();
  234. }
  235. }
  236. [Fact]
  237. public async Task Amb_Many_First_GetAsyncEnumerator_Crashes()
  238. {
  239. var source = AsyncEnumerableEx.Amb(
  240. new FailingGetAsyncEnumerator<int>(),
  241. AsyncEnumerableEx.Never<int>(),
  242. AsyncEnumerableEx.Never<int>()
  243. );
  244. var xs = source.GetAsyncEnumerator();
  245. try
  246. {
  247. await xs.MoveNextAsync();
  248. Assert.Fail("Should not have gotten here");
  249. }
  250. catch (InvalidOperationException)
  251. {
  252. // we expect this
  253. }
  254. finally
  255. {
  256. await xs.DisposeAsync();
  257. }
  258. }
  259. [Fact]
  260. public async Task Amb_Many_Last_GetAsyncEnumerator_Crashes()
  261. {
  262. var source = AsyncEnumerableEx.Amb(
  263. AsyncEnumerableEx.Never<int>(),
  264. AsyncEnumerableEx.Never<int>(),
  265. new FailingGetAsyncEnumerator<int>()
  266. );
  267. var xs = source.GetAsyncEnumerator();
  268. try
  269. {
  270. await xs.MoveNextAsync();
  271. Assert.Fail("Should not have gotten here");
  272. }
  273. catch (InvalidOperationException)
  274. {
  275. // we expect this
  276. }
  277. finally
  278. {
  279. await xs.DisposeAsync();
  280. }
  281. }
  282. private class FailingGetAsyncEnumerator<T> : IAsyncEnumerable<T>
  283. {
  284. public IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default)
  285. {
  286. throw new InvalidOperationException();
  287. }
  288. }
  289. }
  290. }