AsyncTests.Exceptions.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608
  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 partial class AsyncTests
  13. {
  14. [Fact]
  15. public void Catch_Null()
  16. {
  17. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.Catch<int, Exception>(default, x => null));
  18. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.Catch<int, Exception>(AsyncEnumerable.Return(42), default));
  19. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.Catch<int>(default, AsyncEnumerable.Return(42)));
  20. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.Catch<int>(AsyncEnumerable.Return(42), default));
  21. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.Catch<int>(default));
  22. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.Catch<int>(default(IEnumerable<IAsyncEnumerable<int>>)));
  23. }
  24. [Fact]
  25. public void Catch1()
  26. {
  27. var err = false;
  28. var xs = new[] { 1, 2, 3 }.ToAsyncEnumerable();
  29. var ys = new[] { 4, 5, 6 }.ToAsyncEnumerable();
  30. var res = xs.Catch<int, Exception>(ex_ => { err = true; return ys; });
  31. var e = res.GetEnumerator();
  32. HasNext(e, 1);
  33. HasNext(e, 2);
  34. HasNext(e, 3);
  35. NoNext(e);
  36. Assert.False(err);
  37. }
  38. [Fact]
  39. public void Catch2()
  40. {
  41. var ex = new InvalidOperationException("Bang!");
  42. var err = false;
  43. var xs = new[] { 1, 2, 3 }.ToAsyncEnumerable().Concat(AsyncEnumerable.Throw<int>(ex));
  44. var ys = new[] { 4, 5, 6 }.ToAsyncEnumerable();
  45. var res = xs.Catch<int, InvalidOperationException>(ex_ => { err = true; return ys; });
  46. var e = res.GetEnumerator();
  47. HasNext(e, 1);
  48. HasNext(e, 2);
  49. HasNext(e, 3);
  50. Assert.False(err);
  51. HasNext(e, 4);
  52. Assert.True(err);
  53. HasNext(e, 5);
  54. HasNext(e, 6);
  55. NoNext(e);
  56. }
  57. [Fact]
  58. public void Catch3()
  59. {
  60. var ex = new InvalidOperationException("Bang!");
  61. var err = false;
  62. var xs = new[] { 1, 2, 3 }.ToAsyncEnumerable().Concat(AsyncEnumerable.Throw<int>(ex));
  63. var ys = new[] { 4, 5, 6 }.ToAsyncEnumerable();
  64. var res = xs.Catch<int, Exception>(ex_ => { err = true; return ys; });
  65. var e = res.GetEnumerator();
  66. HasNext(e, 1);
  67. HasNext(e, 2);
  68. HasNext(e, 3);
  69. Assert.False(err);
  70. HasNext(e, 4);
  71. Assert.True(err);
  72. HasNext(e, 5);
  73. HasNext(e, 6);
  74. NoNext(e);
  75. }
  76. [Fact]
  77. public void Catch4()
  78. {
  79. var ex = new DivideByZeroException();
  80. var err = false;
  81. var xs = new[] { 1, 2, 3 }.ToAsyncEnumerable().Concat(AsyncEnumerable.Throw<int>(ex));
  82. var ys = new[] { 4, 5, 6 }.ToAsyncEnumerable();
  83. var res = xs.Catch<int, InvalidOperationException>(ex_ => { err = true; return ys; });
  84. var e = res.GetEnumerator();
  85. HasNext(e, 1);
  86. HasNext(e, 2);
  87. HasNext(e, 3);
  88. AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
  89. Assert.False(err);
  90. }
  91. [Fact]
  92. public void Catch5()
  93. {
  94. var ex = new InvalidOperationException("Bang!");
  95. var ex2 = new Exception("Oops!");
  96. var xs = new[] { 1, 2, 3 }.ToAsyncEnumerable().Concat(AsyncEnumerable.Throw<int>(ex));
  97. var ys = new[] { 4, 5, 6 }.ToAsyncEnumerable();
  98. var res = xs.Catch<int, InvalidOperationException>(ex_ => { if (ex_.Message == "Bang!") { throw ex2; } return ys; });
  99. var e = res.GetEnumerator();
  100. HasNext(e, 1);
  101. HasNext(e, 2);
  102. HasNext(e, 3);
  103. AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex2);
  104. }
  105. [Fact]
  106. public void Catch6()
  107. {
  108. var ex = new InvalidOperationException("Bang!");
  109. var err = false;
  110. var xs = new[] { 1, 2, 3 }.ToAsyncEnumerable().Concat(AsyncEnumerable.Throw<int>(ex));
  111. var res = xs.Catch<int, InvalidOperationException>(ex_ => { err = true; return xs; });
  112. var e = res.GetEnumerator();
  113. HasNext(e, 1);
  114. HasNext(e, 2);
  115. HasNext(e, 3);
  116. Assert.False(err);
  117. HasNext(e, 1);
  118. Assert.True(err);
  119. HasNext(e, 2);
  120. HasNext(e, 3);
  121. AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
  122. }
  123. [Fact]
  124. public void Catch7()
  125. {
  126. var xs = new[] { 1, 2, 3 }.ToAsyncEnumerable();
  127. var ys = new[] { 4, 5, 6 }.ToAsyncEnumerable();
  128. var res = AsyncEnumerable.Catch(xs, ys);
  129. var e = res.GetEnumerator();
  130. HasNext(e, 1);
  131. HasNext(e, 2);
  132. HasNext(e, 3);
  133. NoNext(e);
  134. }
  135. [Fact]
  136. public void Catch8()
  137. {
  138. var ex = new InvalidOperationException("Bang!");
  139. var xs = new[] { 1, 2, 3 }.ToAsyncEnumerable().Concat(AsyncEnumerable.Throw<int>(ex));
  140. var ys = new[] { 4, 5, 6 }.ToAsyncEnumerable();
  141. var res = AsyncEnumerable.Catch(xs, ys);
  142. var e = res.GetEnumerator();
  143. HasNext(e, 1);
  144. HasNext(e, 2);
  145. HasNext(e, 3);
  146. HasNext(e, 4);
  147. HasNext(e, 5);
  148. HasNext(e, 6);
  149. NoNext(e);
  150. }
  151. [Fact]
  152. public void Catch9()
  153. {
  154. var ex = new InvalidOperationException("Bang!");
  155. var xs = new[] { 1, 2, 3 }.ToAsyncEnumerable().Concat(AsyncEnumerable.Throw<int>(ex));
  156. var ys = new[] { 4, 5, 6 }.ToAsyncEnumerable();
  157. var res = AsyncEnumerable.Catch(new[] { xs, xs, ys, ys });
  158. var e = res.GetEnumerator();
  159. HasNext(e, 1);
  160. HasNext(e, 2);
  161. HasNext(e, 3);
  162. HasNext(e, 1);
  163. HasNext(e, 2);
  164. HasNext(e, 3);
  165. HasNext(e, 4);
  166. HasNext(e, 5);
  167. HasNext(e, 6);
  168. NoNext(e);
  169. }
  170. [Fact]
  171. public void Catch10()
  172. {
  173. var res = CatchXss().Catch();
  174. var e = res.GetEnumerator();
  175. HasNext(e, 1);
  176. HasNext(e, 2);
  177. HasNext(e, 3);
  178. AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single().Message == "Bang!");
  179. }
  180. private IEnumerable<IAsyncEnumerable<int>> CatchXss()
  181. {
  182. yield return new[] { 1, 2, 3 }.ToAsyncEnumerable().Concat(AsyncEnumerable.Throw<int>(new Exception("!!!")));
  183. throw new Exception("Bang!");
  184. }
  185. [Fact]
  186. public void Catch11()
  187. {
  188. var ex = new InvalidOperationException("Bang!");
  189. var xs = new[] { 1, 2, 3 }.ToAsyncEnumerable().Concat(AsyncEnumerable.Throw<int>(ex));
  190. var res = AsyncEnumerable.Catch(new[] { xs, xs });
  191. var e = res.GetEnumerator();
  192. HasNext(e, 1);
  193. HasNext(e, 2);
  194. HasNext(e, 3);
  195. HasNext(e, 1);
  196. HasNext(e, 2);
  197. HasNext(e, 3);
  198. AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
  199. }
  200. [Fact]
  201. public void Catch12()
  202. {
  203. var res = AsyncEnumerable.Catch(Enumerable.Empty<IAsyncEnumerable<int>>());
  204. var e = res.GetEnumerator();
  205. NoNext(e);
  206. }
  207. [Fact]
  208. public async Task Catch13()
  209. {
  210. var ex = new InvalidOperationException("Bang!");
  211. var xs = new[] { 1, 2, 3 }.ToAsyncEnumerable().Concat(AsyncEnumerable.Throw<int>(ex));
  212. var ys = new[] { 4, 5, 6 }.ToAsyncEnumerable();
  213. var res = AsyncEnumerable.Catch(new[] { xs, xs, ys, ys });
  214. await SequenceIdentity(res);
  215. }
  216. [Fact]
  217. public async Task Catch14()
  218. {
  219. var err = false;
  220. var xs = new[] { 1, 2, 3 }.ToAsyncEnumerable();
  221. var ys = new[] { 4, 5, 6 }.ToAsyncEnumerable();
  222. var res = xs.Catch<int, Exception>(ex_ => { err = true; return ys; });
  223. await SequenceIdentity(res);
  224. Assert.False(err);
  225. }
  226. [Fact]
  227. public void Finally_Null()
  228. {
  229. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.Finally(default(IAsyncEnumerable<int>), () => { }));
  230. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.Finally(AsyncEnumerable.Return(42), null));
  231. }
  232. [Fact]
  233. public void Finally1()
  234. {
  235. var b = false;
  236. var xs = AsyncEnumerable.Empty<int>().Finally(() => { b = true; });
  237. var e = xs.GetEnumerator();
  238. Assert.False(b);
  239. NoNext(e);
  240. Assert.True(b);
  241. }
  242. [Fact]
  243. public void Finally2()
  244. {
  245. var b = false;
  246. var xs = AsyncEnumerable.Return(42).Finally(() => { b = true; });
  247. var e = xs.GetEnumerator();
  248. Assert.False(b);
  249. HasNext(e, 42);
  250. Assert.False(b);
  251. NoNext(e);
  252. Assert.True(b);
  253. }
  254. [Fact]
  255. public void Finally3()
  256. {
  257. var ex = new Exception("Bang!");
  258. var b = false;
  259. var xs = AsyncEnumerable.Throw<int>(ex).Finally(() => { b = true; });
  260. var e = xs.GetEnumerator();
  261. Assert.False(b);
  262. AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
  263. Assert.True(b);
  264. }
  265. [Fact]
  266. public void Finally4()
  267. {
  268. var b = false;
  269. var xs = new[] { 1, 2 }.ToAsyncEnumerable().Finally(() => { b = true; });
  270. var e = xs.GetEnumerator();
  271. Assert.False(b);
  272. HasNext(e, 1);
  273. Assert.False(b);
  274. HasNext(e, 2);
  275. Assert.False(b);
  276. NoNext(e);
  277. Assert.True(b);
  278. }
  279. [Fact]
  280. public void Finally5()
  281. {
  282. var b = false;
  283. var xs = new[] { 1, 2 }.ToAsyncEnumerable().Finally(() => { b = true; });
  284. var e = xs.GetEnumerator();
  285. Assert.False(b);
  286. HasNext(e, 1);
  287. e.Dispose();
  288. Assert.True(b);
  289. }
  290. [Fact]
  291. public async Task Finally6()
  292. {
  293. var b = false;
  294. var xs = new[] { 1, 2 }.ToAsyncEnumerable().Finally(() => { Volatile.Write(ref b, true); });
  295. var e = xs.GetEnumerator();
  296. var cts = new CancellationTokenSource();
  297. var t = e.MoveNext(cts.Token);
  298. cts.Cancel();
  299. t.Wait(WaitTimeoutMs);
  300. for (var i = 0; i < WaitTimeoutMs / 100; i++)
  301. {
  302. if (Volatile.Read(ref b))
  303. {
  304. return;
  305. }
  306. await Task.Delay(100);
  307. }
  308. Assert.True(true, "Timeout while waiting for b to become true.");
  309. }
  310. [Fact]
  311. public async Task Finally7()
  312. {
  313. var i = 0;
  314. var xs = new[] { 1, 2 }.ToAsyncEnumerable().Finally(() => { i++; });
  315. await SequenceIdentity(xs);
  316. Assert.Equal(2, i);
  317. }
  318. [Fact]
  319. public void OnErrorResumeNext_Null()
  320. {
  321. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.OnErrorResumeNext<int>(default, AsyncEnumerable.Return(42)));
  322. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.OnErrorResumeNext<int>(AsyncEnumerable.Return(42), default));
  323. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.OnErrorResumeNext<int>(default));
  324. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.OnErrorResumeNext<int>(default(IEnumerable<IAsyncEnumerable<int>>)));
  325. }
  326. [Fact]
  327. public void OnErrorResumeNext7()
  328. {
  329. var xs = new[] { 1, 2, 3 }.ToAsyncEnumerable();
  330. var ys = new[] { 4, 5, 6 }.ToAsyncEnumerable();
  331. var res = AsyncEnumerable.OnErrorResumeNext(xs, ys);
  332. var e = res.GetEnumerator();
  333. HasNext(e, 1);
  334. HasNext(e, 2);
  335. HasNext(e, 3);
  336. HasNext(e, 4);
  337. HasNext(e, 5);
  338. HasNext(e, 6);
  339. NoNext(e);
  340. }
  341. [Fact]
  342. public void OnErrorResumeNext8()
  343. {
  344. var ex = new InvalidOperationException("Bang!");
  345. var xs = new[] { 1, 2, 3 }.ToAsyncEnumerable().Concat(AsyncEnumerable.Throw<int>(ex));
  346. var ys = new[] { 4, 5, 6 }.ToAsyncEnumerable();
  347. var res = AsyncEnumerable.OnErrorResumeNext(xs, ys);
  348. var e = res.GetEnumerator();
  349. HasNext(e, 1);
  350. HasNext(e, 2);
  351. HasNext(e, 3);
  352. HasNext(e, 4);
  353. HasNext(e, 5);
  354. HasNext(e, 6);
  355. NoNext(e);
  356. }
  357. [Fact]
  358. public void OnErrorResumeNext9()
  359. {
  360. var ex = new InvalidOperationException("Bang!");
  361. var xs = new[] { 1, 2, 3 }.ToAsyncEnumerable().Concat(AsyncEnumerable.Throw<int>(ex));
  362. var ys = new[] { 4, 5, 6 }.ToAsyncEnumerable();
  363. var res = AsyncEnumerable.OnErrorResumeNext(new[] { xs, xs, ys, ys });
  364. var e = res.GetEnumerator();
  365. HasNext(e, 1);
  366. HasNext(e, 2);
  367. HasNext(e, 3);
  368. HasNext(e, 1);
  369. HasNext(e, 2);
  370. HasNext(e, 3);
  371. HasNext(e, 4);
  372. HasNext(e, 5);
  373. HasNext(e, 6);
  374. HasNext(e, 4);
  375. HasNext(e, 5);
  376. HasNext(e, 6);
  377. NoNext(e);
  378. }
  379. [Fact]
  380. public void OnErrorResumeNext10()
  381. {
  382. var res = OnErrorResumeNextXss().OnErrorResumeNext();
  383. var e = res.GetEnumerator();
  384. HasNext(e, 1);
  385. HasNext(e, 2);
  386. HasNext(e, 3);
  387. AssertThrows<Exception>(() => e.MoveNext().Wait(WaitTimeoutMs), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single().Message == "Bang!");
  388. }
  389. private IEnumerable<IAsyncEnumerable<int>> OnErrorResumeNextXss()
  390. {
  391. yield return new[] { 1, 2, 3 }.ToAsyncEnumerable().Concat(AsyncEnumerable.Throw<int>(new Exception("!!!")));
  392. throw new Exception("Bang!");
  393. }
  394. [Fact]
  395. public void OnErrorResumeNext11()
  396. {
  397. var ex = new InvalidOperationException("Bang!");
  398. var xs = new[] { 1, 2, 3 }.ToAsyncEnumerable().Concat(AsyncEnumerable.Throw<int>(ex));
  399. var res = AsyncEnumerable.OnErrorResumeNext(new[] { xs, xs });
  400. var e = res.GetEnumerator();
  401. HasNext(e, 1);
  402. HasNext(e, 2);
  403. HasNext(e, 3);
  404. HasNext(e, 1);
  405. HasNext(e, 2);
  406. HasNext(e, 3);
  407. NoNext(e);
  408. }
  409. [Fact]
  410. public void OnErrorResumeNext12()
  411. {
  412. var res = AsyncEnumerable.OnErrorResumeNext(Enumerable.Empty<IAsyncEnumerable<int>>());
  413. var e = res.GetEnumerator();
  414. NoNext(e);
  415. }
  416. [Fact]
  417. public async Task OnErrorResumeNext13()
  418. {
  419. var xs = new[] { 1, 2, 3 }.ToAsyncEnumerable();
  420. var ys = new[] { 4, 5, 6 }.ToAsyncEnumerable();
  421. var res = AsyncEnumerable.OnErrorResumeNext(xs, ys);
  422. await SequenceIdentity(res);
  423. }
  424. [Fact]
  425. public void Retry_Null()
  426. {
  427. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.Retry<int>(default));
  428. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.Retry<int>(default, 1));
  429. AssertThrows<ArgumentOutOfRangeException>(() => AsyncEnumerable.Retry<int>(AsyncEnumerable.Return(42), -1));
  430. }
  431. [Fact]
  432. public void Retry1()
  433. {
  434. var xs = new[] { 1, 2, 3 }.ToAsyncEnumerable();
  435. var res = xs.Retry();
  436. var e = res.GetEnumerator();
  437. HasNext(e, 1);
  438. HasNext(e, 2);
  439. HasNext(e, 3);
  440. NoNext(e);
  441. }
  442. [Fact]
  443. public void Retry2()
  444. {
  445. var ex = new InvalidOperationException("Bang!");
  446. var xs = new[] { 1, 2, 3 }.ToAsyncEnumerable().Concat(AsyncEnumerable.Throw<int>(ex));
  447. var res = xs.Retry();
  448. var e = res.GetEnumerator();
  449. HasNext(e, 1);
  450. HasNext(e, 2);
  451. HasNext(e, 3);
  452. HasNext(e, 1);
  453. HasNext(e, 2);
  454. HasNext(e, 3);
  455. HasNext(e, 1);
  456. HasNext(e, 2);
  457. HasNext(e, 3);
  458. }
  459. }
  460. }