AsyncTests.Creation.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  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. #if !NO_TPL
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Linq;
  8. using System.Text;
  9. using Xunit;
  10. using System.Threading.Tasks;
  11. using System.Threading;
  12. namespace Tests
  13. {
  14. static class Ext
  15. {
  16. public static Task<bool> MoveNext<T>(this IAsyncEnumerator<T> enumerator)
  17. {
  18. return enumerator.MoveNext(CancellationToken.None);
  19. }
  20. }
  21. public partial class AsyncTests
  22. {
  23. [Fact]
  24. public void Return()
  25. {
  26. var xs = AsyncEnumerable.Return(42);
  27. HasNext(xs.GetEnumerator(), 42);
  28. }
  29. [Fact]
  30. public void Never()
  31. {
  32. var xs = AsyncEnumerable.Never<int>();
  33. var e = xs.GetEnumerator();
  34. Assert.False(e.MoveNext().IsCompleted); // Very rudimentary check
  35. AssertThrows<InvalidOperationException>(() => Nop(e.Current));
  36. e.Dispose();
  37. }
  38. [Fact]
  39. public void Empty1()
  40. {
  41. var xs = AsyncEnumerable.Empty<int>();
  42. NoNext(xs.GetEnumerator());
  43. }
  44. [Fact]
  45. public void Empty2()
  46. {
  47. var xs = AsyncEnumerable.Empty<int>();
  48. var e = xs.GetEnumerator();
  49. Assert.False(e.MoveNext().Result);
  50. AssertThrows<InvalidOperationException>(() => Nop(e.Current));
  51. }
  52. [Fact]
  53. public void Throw_Null()
  54. {
  55. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.Throw<int>(null));
  56. }
  57. [Fact]
  58. public void Throw()
  59. {
  60. var ex = new Exception("Bang");
  61. var xs = AsyncEnumerable.Throw<int>(ex);
  62. var e = xs.GetEnumerator();
  63. AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).InnerExceptions.Single() == ex);
  64. AssertThrows<InvalidOperationException>(() => Nop(e.Current));
  65. }
  66. private void Nop(object o)
  67. {
  68. }
  69. [Fact]
  70. public void Range_Null()
  71. {
  72. AssertThrows<ArgumentOutOfRangeException>(() => AsyncEnumerable.Range(0, -1));
  73. }
  74. [Fact]
  75. public void Range1()
  76. {
  77. var xs = AsyncEnumerable.Range(2, 5);
  78. var e = xs.GetEnumerator();
  79. HasNext(e, 2);
  80. HasNext(e, 3);
  81. HasNext(e, 4);
  82. HasNext(e, 5);
  83. HasNext(e, 6);
  84. NoNext(e);
  85. }
  86. [Fact]
  87. public void Range2()
  88. {
  89. var xs = AsyncEnumerable.Range(2, 0);
  90. var e = xs.GetEnumerator();
  91. NoNext(e);
  92. }
  93. [Fact]
  94. public void Repeat_Null()
  95. {
  96. AssertThrows<ArgumentOutOfRangeException>(() => AsyncEnumerable.Repeat(0, -1));
  97. }
  98. [Fact]
  99. public void Repeat1()
  100. {
  101. var xs = AsyncEnumerable.Repeat(2, 5);
  102. var e = xs.GetEnumerator();
  103. HasNext(e, 2);
  104. HasNext(e, 2);
  105. HasNext(e, 2);
  106. HasNext(e, 2);
  107. HasNext(e, 2);
  108. NoNext(e);
  109. }
  110. [Fact]
  111. public void Repeat2()
  112. {
  113. var xs = AsyncEnumerable.Repeat(2, 0);
  114. var e = xs.GetEnumerator();
  115. NoNext(e);
  116. }
  117. [Fact]
  118. public void Repeat3()
  119. {
  120. var xs = AsyncEnumerable.Repeat(2);
  121. var e = xs.GetEnumerator();
  122. HasNext(e, 2);
  123. HasNext(e, 2);
  124. HasNext(e, 2);
  125. HasNext(e, 2);
  126. HasNext(e, 2);
  127. e.Dispose();
  128. }
  129. [Fact]
  130. public void Defer_Null()
  131. {
  132. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.Defer<int>(null));
  133. }
  134. [Fact]
  135. public void Defer1()
  136. {
  137. var x = 0;
  138. var xs = AsyncEnumerable.Defer<int>(() => new[] { x }.ToAsyncEnumerable());
  139. {
  140. var e = xs.GetEnumerator();
  141. HasNext(e, 0);
  142. NoNext(e);
  143. }
  144. {
  145. x++;
  146. var e = xs.GetEnumerator();
  147. HasNext(e, 1);
  148. NoNext(e);
  149. }
  150. }
  151. [Fact]
  152. public void Generate_Null()
  153. {
  154. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.Generate<int, int>(0, null, x => x, x => x));
  155. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.Generate<int, int>(0, x => true, null, x => x));
  156. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.Generate<int, int>(0, x => true, x => x, null));
  157. }
  158. [Fact]
  159. public void Generate1()
  160. {
  161. var xs = AsyncEnumerable.Generate(0, x => x < 5, x => x + 1, x => x * x);
  162. var e = xs.GetEnumerator();
  163. HasNext(e, 0);
  164. HasNext(e, 1);
  165. HasNext(e, 4);
  166. HasNext(e, 9);
  167. HasNext(e, 16);
  168. NoNext(e);
  169. e.Dispose();
  170. }
  171. [Fact]
  172. public void Generate2()
  173. {
  174. var ex = new Exception("Bang!");
  175. var xs = AsyncEnumerable.Generate(0, x => { throw ex; }, x => x + 1, x => x * x);
  176. var e = xs.GetEnumerator();
  177. AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).InnerExceptions.Single() == ex);
  178. }
  179. [Fact]
  180. public void Generate3()
  181. {
  182. var ex = new Exception("Bang!");
  183. var xs = AsyncEnumerable.Generate(0, x => true, x => x + 1, x => { if (x == 1) throw ex; return x * x; });
  184. var e = xs.GetEnumerator();
  185. HasNext(e, 0);
  186. AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).InnerExceptions.Single() == ex);
  187. }
  188. [Fact]
  189. public void Generate4()
  190. {
  191. var ex = new Exception("Bang!");
  192. var xs = AsyncEnumerable.Generate(0, x => true, x => { throw ex; }, x => x * x);
  193. var e = xs.GetEnumerator();
  194. HasNext(e, 0);
  195. AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).InnerExceptions.Single() == ex);
  196. }
  197. [Fact]
  198. public void Using_Null()
  199. {
  200. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.Using<int, IDisposable>(null, _ => null));
  201. AssertThrows<ArgumentNullException>(() => AsyncEnumerable.Using<int, IDisposable>(() => new MyD(null), null));
  202. }
  203. [Fact]
  204. public void Using1()
  205. {
  206. var i = 0;
  207. var d = 0;
  208. var xs = AsyncEnumerable.Using(
  209. () =>
  210. {
  211. i++;
  212. return new MyD(() => { d++; });
  213. },
  214. _ => AsyncEnumerable.Return(42)
  215. );
  216. Assert.Equal(0, i);
  217. var e = xs.GetEnumerator();
  218. Assert.Equal(1, i);
  219. }
  220. [Fact]
  221. public void Using2()
  222. {
  223. var i = 0;
  224. var d = 0;
  225. var xs = AsyncEnumerable.Using(
  226. () =>
  227. {
  228. i++;
  229. return new MyD(() => { d++; });
  230. },
  231. _ => AsyncEnumerable.Return(42)
  232. );
  233. Assert.Equal(0, i);
  234. var e = xs.GetEnumerator();
  235. Assert.Equal(1, i);
  236. e.Dispose();
  237. Assert.Equal(1, d);
  238. }
  239. [Fact]
  240. public void Using3()
  241. {
  242. var ex = new Exception("Bang!");
  243. var i = 0;
  244. var d = 0;
  245. var xs = AsyncEnumerable.Using<int, MyD>(
  246. () =>
  247. {
  248. i++;
  249. return new MyD(() => { d++; });
  250. },
  251. _ => { throw ex; }
  252. );
  253. Assert.Equal(0, i);
  254. AssertThrows<Exception>(() => xs.GetEnumerator(), ex_ => ex_ == ex);
  255. Assert.Equal(1, d);
  256. }
  257. [Fact]
  258. public void Using4()
  259. {
  260. var i = 0;
  261. var disposed = new TaskCompletionSource<bool>();
  262. var xs = AsyncEnumerable.Using(
  263. () =>
  264. {
  265. i++;
  266. return new MyD(() => { disposed.TrySetResult(true); });
  267. },
  268. _ => AsyncEnumerable.Return(42)
  269. );
  270. Assert.Equal(0, i);
  271. var e = xs.GetEnumerator();
  272. Assert.Equal(1, i);
  273. HasNext(e, 42);
  274. NoNext(e);
  275. Assert.True(disposed.Task.Result);
  276. }
  277. [Fact]
  278. public void Using5()
  279. {
  280. var ex = new Exception("Bang!");
  281. var i = 0;
  282. var disposed = new TaskCompletionSource<bool>();
  283. var xs = AsyncEnumerable.Using(
  284. () =>
  285. {
  286. i++;
  287. return new MyD(() => { disposed.TrySetResult(true); });
  288. },
  289. _ => AsyncEnumerable.Throw<int>(ex)
  290. );
  291. Assert.Equal(0, i);
  292. var e = xs.GetEnumerator();
  293. Assert.Equal(1, i);
  294. AssertThrows<Exception>(() => e.MoveNext().Wait(), ex_ => ((AggregateException)ex_).Flatten().InnerExceptions.Single() == ex);
  295. Assert.True(disposed.Task.Result);
  296. }
  297. [Fact]
  298. public void Using6()
  299. {
  300. var i = 0;
  301. var disposed = new TaskCompletionSource<bool>();
  302. var xs = AsyncEnumerable.Using(
  303. () =>
  304. {
  305. i++;
  306. return new MyD(() => { disposed.TrySetResult(true); });
  307. },
  308. _ => AsyncEnumerable.Range(0, 10)
  309. );
  310. Assert.Equal(0, i);
  311. var e = xs.GetEnumerator();
  312. Assert.Equal(1, i);
  313. HasNext(e, 0);
  314. HasNext(e, 1);
  315. var cts = new CancellationTokenSource();
  316. var t = e.MoveNext(cts.Token);
  317. cts.Cancel();
  318. try
  319. {
  320. t.Wait();
  321. }
  322. catch (AggregateException ex)
  323. {
  324. ex.Flatten().Handle(inner => inner is TaskCanceledException);
  325. }
  326. Assert.True(disposed.Task.Result);
  327. }
  328. class MyD : IDisposable
  329. {
  330. private readonly Action _dispose;
  331. public MyD(Action dispose)
  332. {
  333. _dispose = dispose;
  334. }
  335. public void Dispose()
  336. {
  337. _dispose();
  338. }
  339. }
  340. }
  341. }
  342. #endif