AsyncTests.Creation.cs 12 KB

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