Select.cs 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898
  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;
  6. using System.Collections.Generic;
  7. using System.Linq;
  8. using System.Threading;
  9. using System.Threading.Tasks;
  10. using Xunit;
  11. namespace Tests
  12. {
  13. public class Select : AsyncEnumerableTests
  14. {
  15. [Fact]
  16. public void Select_Sync_Null()
  17. {
  18. Assert.Throws<ArgumentNullException>(() => AsyncEnumerable.Select<int, int>(default, x => x));
  19. Assert.Throws<ArgumentNullException>(() => AsyncEnumerable.Select<int, int>(default, (x, i) => x));
  20. Assert.Throws<ArgumentNullException>(() => AsyncEnumerable.Select(Return42, default(Func<int, int>)));
  21. Assert.Throws<ArgumentNullException>(() => AsyncEnumerable.Select(Return42, default(Func<int, int, int>)));
  22. }
  23. [Fact]
  24. public async Task Select_Sync_Simple()
  25. {
  26. var xs = ToAsyncEnumerable(new[] { 0, 1, 2 });
  27. var ys = xs.Select(x => (char)('a' + x));
  28. var e = ys.GetAsyncEnumerator();
  29. await HasNextAsync(e, 'a');
  30. await HasNextAsync(e, 'b');
  31. await HasNextAsync(e, 'c');
  32. await NoNextAsync(e);
  33. }
  34. [Fact]
  35. public async Task Select_Sync_Simple_IList()
  36. {
  37. var xs = ToAsyncEnumerableIList(new[] { 0, 1, 2 });
  38. var ys = xs.Select(x => (char)('a' + x));
  39. var e = ys.GetAsyncEnumerator();
  40. await HasNextAsync(e, 'a');
  41. await HasNextAsync(e, 'b');
  42. await HasNextAsync(e, 'c');
  43. await NoNextAsync(e);
  44. }
  45. [Fact]
  46. public async Task Select_Sync_Simple_AsyncIterator()
  47. {
  48. var xs = new[] { 0, 1, 2 }.ToAsyncEnumerable();
  49. var ys = xs.Select(x => (char)('a' + x));
  50. var e = ys.GetAsyncEnumerator();
  51. await HasNextAsync(e, 'a');
  52. await HasNextAsync(e, 'b');
  53. await HasNextAsync(e, 'c');
  54. await NoNextAsync(e);
  55. }
  56. [Fact]
  57. public async Task Select_Sync_Indexed()
  58. {
  59. var xs = ToAsyncEnumerable(new[] { 8, 5, 7 });
  60. var ys = xs.Select((x, i) => (char)('a' + i));
  61. var e = ys.GetAsyncEnumerator();
  62. await HasNextAsync(e, 'a');
  63. await HasNextAsync(e, 'b');
  64. await HasNextAsync(e, 'c');
  65. await NoNextAsync(e);
  66. }
  67. [Fact]
  68. public async Task Select_Sync_Indexed_IList()
  69. {
  70. var xs = ToAsyncEnumerableIList(new[] { 8, 5, 7 });
  71. var ys = xs.Select((x, i) => (char)('a' + i));
  72. var e = ys.GetAsyncEnumerator();
  73. await HasNextAsync(e, 'a');
  74. await HasNextAsync(e, 'b');
  75. await HasNextAsync(e, 'c');
  76. await NoNextAsync(e);
  77. }
  78. [Fact]
  79. public async Task Select_Sync_Indexed_AsyncIterator()
  80. {
  81. var xs = new[] { 8, 5, 7 }.ToAsyncEnumerable();
  82. var ys = xs.Select((x, i) => (char)('a' + i));
  83. var e = ys.GetAsyncEnumerator();
  84. await HasNextAsync(e, 'a');
  85. await HasNextAsync(e, 'b');
  86. await HasNextAsync(e, 'c');
  87. await NoNextAsync(e);
  88. }
  89. [Fact]
  90. public async Task Select_Sync_Throws_Selector()
  91. {
  92. var xs = ToAsyncEnumerable(new[] { 0, 1, 2 });
  93. var ys = xs.Select(x => 1 / x);
  94. var e = ys.GetAsyncEnumerator();
  95. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  96. }
  97. [Fact]
  98. public async Task Select_Sync_Throws_Selector_IList()
  99. {
  100. var xs = ToAsyncEnumerableIList(new[] { 0, 1, 2 });
  101. var ys = xs.Select(x => 1 / x);
  102. var e = ys.GetAsyncEnumerator();
  103. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  104. }
  105. [Fact]
  106. public async Task Select_Sync_Throws_Selector_AsyncIterator()
  107. {
  108. var xs = new[] { 0, 1, 2 }.ToAsyncEnumerable();
  109. var ys = xs.Select(x => 1 / x);
  110. var e = ys.GetAsyncEnumerator();
  111. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  112. }
  113. [Fact]
  114. public async Task Select_Sync_Indexed_Throws_Selector()
  115. {
  116. var xs = ToAsyncEnumerable(new[] { 8, 5, 7 });
  117. var ys = xs.Select((x, i) => 1 / i);
  118. var e = ys.GetAsyncEnumerator();
  119. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  120. }
  121. [Fact]
  122. public async Task Select_Sync_Indexed_Throws_Selector_IList()
  123. {
  124. var xs = ToAsyncEnumerableIList(new[] { 8, 5, 7 });
  125. var ys = xs.Select((x, i) => 1 / i);
  126. var e = ys.GetAsyncEnumerator();
  127. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  128. }
  129. [Fact]
  130. public async Task Select_Sync_Indexed_Throws_Selector_AsyncIterator()
  131. {
  132. var xs = new[] { 8, 5, 7 }.ToAsyncEnumerable();
  133. var ys = xs.Select((x, i) => 1 / i);
  134. var e = ys.GetAsyncEnumerator();
  135. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  136. }
  137. [Fact]
  138. public async Task Select_Sync_SelectSelect()
  139. {
  140. var xs = ToAsyncEnumerable(new[] { 0, 1, 2 });
  141. var ys = xs.Select(i => i + 3).Select(x => (char)('a' + x));
  142. var e = ys.GetAsyncEnumerator();
  143. await HasNextAsync(e, 'd');
  144. await HasNextAsync(e, 'e');
  145. await HasNextAsync(e, 'f');
  146. await NoNextAsync(e);
  147. }
  148. [Fact]
  149. public async Task Select_Sync_SelectSelect_IList()
  150. {
  151. var xs = ToAsyncEnumerableIList(new[] { 0, 1, 2 });
  152. var ys = xs.Select(i => i + 3).Select(x => (char)('a' + x));
  153. var e = ys.GetAsyncEnumerator();
  154. await HasNextAsync(e, 'd');
  155. await HasNextAsync(e, 'e');
  156. await HasNextAsync(e, 'f');
  157. await NoNextAsync(e);
  158. }
  159. [Fact]
  160. public async Task Select_Sync_SelectSelectAwaitIterator()
  161. {
  162. var xs = new[] { 0, 1, 2 }.ToAsyncEnumerable();
  163. var ys = xs.Select(i => i + 3).Select(x => (char)('a' + x));
  164. var e = ys.GetAsyncEnumerator();
  165. await HasNextAsync(e, 'd');
  166. await HasNextAsync(e, 'e');
  167. await HasNextAsync(e, 'f');
  168. await NoNextAsync(e);
  169. }
  170. [Fact]
  171. public async Task Select_Sync_SequenceIdentity()
  172. {
  173. var xs = ToAsyncEnumerable(new[] { 1, 2, 3 });
  174. var ys = xs.Select(x => (char)('a' + x));
  175. await SequenceIdentity(ys);
  176. }
  177. [Fact]
  178. public async Task Select_Sync_SequenceIdentity_IList()
  179. {
  180. var xs = ToAsyncEnumerableIList(new[] { 1, 2, 3 });
  181. var ys = xs.Select(x => (char)('a' + x));
  182. await SequenceIdentity(ys);
  183. }
  184. [Fact]
  185. public async Task Select_Sync_SequenceIdentity_AsyncIterator()
  186. {
  187. var xs = new[] { 0, 1, 2 }.ToAsyncEnumerable();
  188. var ys = xs.Select(x => (char)('a' + x));
  189. await SequenceIdentity(ys);
  190. }
  191. [Fact]
  192. public async Task Select_Sync_Indexed_SequenceIdentity()
  193. {
  194. var xs = ToAsyncEnumerable(new[] { 8, 5, 7 });
  195. var ys = xs.Select((x, i) => (char)('a' + i));
  196. await SequenceIdentity(ys);
  197. }
  198. [Fact]
  199. public async Task Select_Sync_Indexed_SequenceIdentity_IList()
  200. {
  201. var xs = ToAsyncEnumerableIList(new[] { 8, 5, 7 });
  202. var ys = xs.Select((x, i) => (char)('a' + i));
  203. await SequenceIdentity(ys);
  204. }
  205. [Fact]
  206. public async Task Select_Sync_Indexed_SequenceIdentity_AsyncIterator()
  207. {
  208. var xs = new[] { 8, 5, 7 }.ToAsyncEnumerable();
  209. var ys = xs.Select((x, i) => (char)('a' + i));
  210. await SequenceIdentity(ys);
  211. }
  212. [Fact]
  213. public async Task Select_Sync_IList_Count()
  214. {
  215. var xs = ToAsyncEnumerableIList(new[] { 1, 2, 3, 4, 5 });
  216. var ys = xs.Select(x => x * 2);
  217. Assert.Equal(5, await ys.CountAsync());
  218. }
  219. [Fact]
  220. public async Task Select_Sync_IList_ToList()
  221. {
  222. var xs = ToAsyncEnumerableIList(new[] { 1, 2, 3, 4, 5 });
  223. var ys = xs.Select(x => x * 2);
  224. Assert.Equal(new[] { 2, 4, 6, 8, 10 }, await ys.ToListAsync());
  225. }
  226. [Fact]
  227. public async Task Select_Sync_IList_ToArray()
  228. {
  229. var xs = ToAsyncEnumerableIList(new[] { 1, 2, 3, 4, 5 });
  230. var ys = xs.Select(x => x * 2);
  231. Assert.Equal(new[] { 2, 4, 6, 8, 10 }, await ys.ToArrayAsync());
  232. }
  233. [Fact]
  234. public void SelectAwait_Null()
  235. {
  236. Assert.Throws<ArgumentNullException>(() => AsyncEnumerable.SelectAwait<int, int>(default, x => new ValueTask<int>(x)));
  237. Assert.Throws<ArgumentNullException>(() => AsyncEnumerable.SelectAwait(default, (int x, int i) => new ValueTask<int>(x)));
  238. Assert.Throws<ArgumentNullException>(() => AsyncEnumerable.SelectAwait(Return42, default(Func<int, ValueTask<int>>)));
  239. Assert.Throws<ArgumentNullException>(() => AsyncEnumerable.SelectAwait(Return42, default(Func<int, int, ValueTask<int>>)));
  240. }
  241. [Fact]
  242. public async Task SelectAwait_Simple()
  243. {
  244. var xs = ToAsyncEnumerable(new[] { 0, 1, 2 });
  245. var ys = xs.SelectAwait(x => new ValueTask<char>((char)('a' + x)));
  246. var e = ys.GetAsyncEnumerator();
  247. await HasNextAsync(e, 'a');
  248. await HasNextAsync(e, 'b');
  249. await HasNextAsync(e, 'c');
  250. await NoNextAsync(e);
  251. }
  252. [Fact]
  253. public async Task SelectAwait_Simple_IList()
  254. {
  255. var xs = ToAsyncEnumerableIList(new[] { 0, 1, 2 });
  256. var ys = xs.SelectAwait(x => new ValueTask<char>((char)('a' + x)));
  257. var e = ys.GetAsyncEnumerator();
  258. await HasNextAsync(e, 'a');
  259. await HasNextAsync(e, 'b');
  260. await HasNextAsync(e, 'c');
  261. await NoNextAsync(e);
  262. }
  263. [Fact]
  264. public async Task SelectAwait_Simple_AsyncIterator()
  265. {
  266. var xs = new[] { 0, 1, 2 }.ToAsyncEnumerable();
  267. var ys = xs.SelectAwait(x => new ValueTask<char>((char)('a' + x)));
  268. var e = ys.GetAsyncEnumerator();
  269. await HasNextAsync(e, 'a');
  270. await HasNextAsync(e, 'b');
  271. await HasNextAsync(e, 'c');
  272. await NoNextAsync(e);
  273. }
  274. [Fact]
  275. public async Task SelectAwait_Indexed()
  276. {
  277. var xs = ToAsyncEnumerable(new[] { 8, 5, 7 });
  278. var ys = xs.SelectAwait((x, i) => new ValueTask<char>((char)('a' + i)));
  279. var e = ys.GetAsyncEnumerator();
  280. await HasNextAsync(e, 'a');
  281. await HasNextAsync(e, 'b');
  282. await HasNextAsync(e, 'c');
  283. await NoNextAsync(e);
  284. }
  285. [Fact]
  286. public async Task SelectAwait_Indexed_IList()
  287. {
  288. var xs = ToAsyncEnumerableIList(new[] { 8, 5, 7 });
  289. var ys = xs.SelectAwait((x, i) => new ValueTask<char>((char)('a' + i)));
  290. var e = ys.GetAsyncEnumerator();
  291. await HasNextAsync(e, 'a');
  292. await HasNextAsync(e, 'b');
  293. await HasNextAsync(e, 'c');
  294. await NoNextAsync(e);
  295. }
  296. [Fact]
  297. public async Task SelectAwait_Indexed_AsyncIterator()
  298. {
  299. var xs = new[] { 8, 5, 7 }.ToAsyncEnumerable();
  300. var ys = xs.SelectAwait((x, i) => new ValueTask<char>((char)('a' + i)));
  301. var e = ys.GetAsyncEnumerator();
  302. await HasNextAsync(e, 'a');
  303. await HasNextAsync(e, 'b');
  304. await HasNextAsync(e, 'c');
  305. await NoNextAsync(e);
  306. }
  307. [Fact]
  308. public async Task SelectAwait_Throws_Selector()
  309. {
  310. var xs = ToAsyncEnumerable(new[] { 0, 1, 2 });
  311. var ys = xs.SelectAwait(x => new ValueTask<int>(1 / x));
  312. var e = ys.GetAsyncEnumerator();
  313. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  314. }
  315. [Fact]
  316. public async Task SelectAwait_Throws_Selector_IList()
  317. {
  318. var xs = ToAsyncEnumerableIList(new[] { 0, 1, 2 });
  319. var ys = xs.SelectAwait(x => new ValueTask<int>(1 / x));
  320. var e = ys.GetAsyncEnumerator();
  321. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  322. }
  323. [Fact]
  324. public async Task SelectAwait_Throws_Selector_AsyncIterator()
  325. {
  326. var xs = new[] { 0, 1, 2 }.ToAsyncEnumerable();
  327. var ys = xs.SelectAwait(x => new ValueTask<int>(1 / x));
  328. var e = ys.GetAsyncEnumerator();
  329. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  330. }
  331. [Fact]
  332. public async Task SelectAwait_Indexed_Throws_Selector()
  333. {
  334. var xs = ToAsyncEnumerable(new[] { 8, 5, 7 });
  335. var ys = xs.SelectAwait((x, i) => new ValueTask<int>(1 / i));
  336. var e = ys.GetAsyncEnumerator();
  337. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  338. }
  339. [Fact]
  340. public async Task SelectAwait_Indexed_Throws_Selector_IList()
  341. {
  342. var xs = ToAsyncEnumerableIList(new[] { 8, 5, 7 });
  343. var ys = xs.SelectAwait((x, i) => new ValueTask<int>(1 / i));
  344. var e = ys.GetAsyncEnumerator();
  345. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  346. }
  347. [Fact]
  348. public async Task SelectAwait_Indexed_Throws_Selector_AsyncIterator()
  349. {
  350. var xs = new[] { 8, 5, 7 }.ToAsyncEnumerable();
  351. var ys = xs.SelectAwait((x, i) => new ValueTask<int>(1 / i));
  352. var e = ys.GetAsyncEnumerator();
  353. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  354. }
  355. [Fact]
  356. public async Task SelectAwait_SelectSelect()
  357. {
  358. var xs = ToAsyncEnumerable(new[] { 0, 1, 2 });
  359. var ys = xs.SelectAwait(i => new ValueTask<int>(i + 3)).SelectAwait(x => new ValueTask<char>((char)('a' + x)));
  360. var e = ys.GetAsyncEnumerator();
  361. await HasNextAsync(e, 'd');
  362. await HasNextAsync(e, 'e');
  363. await HasNextAsync(e, 'f');
  364. await NoNextAsync(e);
  365. }
  366. [Fact]
  367. public async Task SelectAwait_SelectSelect_IList()
  368. {
  369. var xs = ToAsyncEnumerableIList(new[] { 0, 1, 2 });
  370. var ys = xs.SelectAwait(i => new ValueTask<int>(i + 3)).SelectAwait(x => new ValueTask<char>((char)('a' + x)));
  371. var e = ys.GetAsyncEnumerator();
  372. await HasNextAsync(e, 'd');
  373. await HasNextAsync(e, 'e');
  374. await HasNextAsync(e, 'f');
  375. await NoNextAsync(e);
  376. }
  377. [Fact]
  378. public async Task SelectAwait_SelectSelectAwaitIterator()
  379. {
  380. var xs = new[] { 0, 1, 2 }.ToAsyncEnumerable();
  381. var ys = xs.SelectAwait(i => new ValueTask<int>(i + 3)).SelectAwait(x => new ValueTask<char>((char)('a' + x)));
  382. var e = ys.GetAsyncEnumerator();
  383. await HasNextAsync(e, 'd');
  384. await HasNextAsync(e, 'e');
  385. await HasNextAsync(e, 'f');
  386. await NoNextAsync(e);
  387. }
  388. [Fact]
  389. public async Task SelectAwait_SequenceIdentity()
  390. {
  391. var xs = ToAsyncEnumerable(new[] { 1, 2, 3 });
  392. var ys = xs.SelectAwait(x => new ValueTask<char>((char)('a' + x)));
  393. await SequenceIdentity(ys);
  394. }
  395. [Fact]
  396. public async Task SelectAwait_SequenceIdentity_IList()
  397. {
  398. var xs = ToAsyncEnumerableIList(new[] { 1, 2, 3 });
  399. var ys = xs.SelectAwait(x => new ValueTask<char>((char)('a' + x)));
  400. await SequenceIdentity(ys);
  401. }
  402. [Fact]
  403. public async Task SelectAwait_SequenceIdentity_AsyncIterator()
  404. {
  405. var xs = new[] { 0, 1, 2 }.ToAsyncEnumerable();
  406. var ys = xs.SelectAwait(x => new ValueTask<char>((char)('a' + x)));
  407. await SequenceIdentity(ys);
  408. }
  409. [Fact]
  410. public async Task SelectAwait_Indexed_SequenceIdentity()
  411. {
  412. var xs = ToAsyncEnumerable(new[] { 8, 5, 7 });
  413. var ys = xs.SelectAwait((x, i) => new ValueTask<char>((char)('a' + i)));
  414. await SequenceIdentity(ys);
  415. }
  416. [Fact]
  417. public async Task SelectAwait_Indexed_SequenceIdentity_IList()
  418. {
  419. var xs = ToAsyncEnumerableIList(new[] { 8, 5, 7 });
  420. var ys = xs.SelectAwait((x, i) => new ValueTask<char>((char)('a' + i)));
  421. await SequenceIdentity(ys);
  422. }
  423. [Fact]
  424. public async Task SelectAwait_Indexed_SequenceIdentity_AsyncIterator()
  425. {
  426. var xs = new[] { 8, 5, 7 }.ToAsyncEnumerable();
  427. var ys = xs.SelectAwait((x, i) => new ValueTask<char>((char)('a' + i)));
  428. await SequenceIdentity(ys);
  429. }
  430. [Fact]
  431. public async Task SelectAwait_IList_Count()
  432. {
  433. var xs = ToAsyncEnumerableIList(new[] { 1, 2, 3, 4, 5 });
  434. var ys = xs.SelectAwait(x => new ValueTask<int>(x * 2));
  435. Assert.Equal(5, await ys.CountAsync());
  436. }
  437. [Fact]
  438. public async Task SelectAwait_IList_ToList()
  439. {
  440. var xs = ToAsyncEnumerableIList(new[] { 1, 2, 3, 4, 5 });
  441. var ys = xs.SelectAwait(x => new ValueTask<int>(x * 2));
  442. Assert.Equal(new[] { 2, 4, 6, 8, 10 }, await ys.ToListAsync());
  443. }
  444. [Fact]
  445. public async Task SelectAwait_IList_ToArray()
  446. {
  447. var xs = ToAsyncEnumerableIList(new[] { 1, 2, 3, 4, 5 });
  448. var ys = xs.SelectAwait(x => new ValueTask<int>(x * 2));
  449. Assert.Equal(new[] { 2, 4, 6, 8, 10 }, await ys.ToArrayAsync());
  450. }
  451. #if !NO_DEEP_CANCELLATION
  452. [Fact]
  453. public void SelectAwaitWithCancellation_Null()
  454. {
  455. Assert.Throws<ArgumentNullException>(() => AsyncEnumerable.SelectAwaitWithCancellation(default, (int x, CancellationToken ct) => new ValueTask<int>(x)));
  456. Assert.Throws<ArgumentNullException>(() => AsyncEnumerable.SelectAwaitWithCancellation(default, (int x, int i, CancellationToken ct) => new ValueTask<int>(x)));
  457. Assert.Throws<ArgumentNullException>(() => AsyncEnumerable.SelectAwaitWithCancellation(Return42, default(Func<int, CancellationToken, ValueTask<int>>)));
  458. Assert.Throws<ArgumentNullException>(() => AsyncEnumerable.SelectAwaitWithCancellation(Return42, default(Func<int, int, CancellationToken, ValueTask<int>>)));
  459. }
  460. [Fact]
  461. public async Task SelectAwaitWithCancellation_Simple()
  462. {
  463. var xs = ToAsyncEnumerable(new[] { 0, 1, 2 });
  464. var ys = xs.SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<char>((char)('a' + x)));
  465. var e = ys.GetAsyncEnumerator();
  466. await HasNextAsync(e, 'a');
  467. await HasNextAsync(e, 'b');
  468. await HasNextAsync(e, 'c');
  469. await NoNextAsync(e);
  470. }
  471. [Fact]
  472. public async Task SelectAwaitWithCancellation_Simple_IList()
  473. {
  474. var xs = ToAsyncEnumerableIList(new[] { 0, 1, 2 });
  475. var ys = xs.SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<char>((char)('a' + x)));
  476. var e = ys.GetAsyncEnumerator();
  477. await HasNextAsync(e, 'a');
  478. await HasNextAsync(e, 'b');
  479. await HasNextAsync(e, 'c');
  480. await NoNextAsync(e);
  481. }
  482. [Fact]
  483. public async Task SelectAwaitWithCancellation_Simple_Async_CancelIterator()
  484. {
  485. var xs = new[] { 0, 1, 2 }.ToAsyncEnumerable();
  486. var ys = xs.SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<char>((char)('a' + x)));
  487. var e = ys.GetAsyncEnumerator();
  488. await HasNextAsync(e, 'a');
  489. await HasNextAsync(e, 'b');
  490. await HasNextAsync(e, 'c');
  491. await NoNextAsync(e);
  492. }
  493. [Fact]
  494. public async Task SelectAwaitWithCancellation_Indexed()
  495. {
  496. var xs = ToAsyncEnumerable(new[] { 8, 5, 7 });
  497. var ys = xs.SelectAwaitWithCancellation((x, i, ct) => new ValueTask<char>((char)('a' + i)));
  498. var e = ys.GetAsyncEnumerator();
  499. await HasNextAsync(e, 'a');
  500. await HasNextAsync(e, 'b');
  501. await HasNextAsync(e, 'c');
  502. await NoNextAsync(e);
  503. }
  504. [Fact]
  505. public async Task SelectAwaitWithCancellation_Indexed_IList()
  506. {
  507. var xs = ToAsyncEnumerableIList(new[] { 8, 5, 7 });
  508. var ys = xs.SelectAwaitWithCancellation((x, i, ct) => new ValueTask<char>((char)('a' + i)));
  509. var e = ys.GetAsyncEnumerator();
  510. await HasNextAsync(e, 'a');
  511. await HasNextAsync(e, 'b');
  512. await HasNextAsync(e, 'c');
  513. await NoNextAsync(e);
  514. }
  515. [Fact]
  516. public async Task SelectAwaitWithCancellation_Indexed_Async_CancelIterator()
  517. {
  518. var xs = new[] { 8, 5, 7 }.ToAsyncEnumerable();
  519. var ys = xs.SelectAwaitWithCancellation((x, i, ct) => new ValueTask<char>((char)('a' + i)));
  520. var e = ys.GetAsyncEnumerator();
  521. await HasNextAsync(e, 'a');
  522. await HasNextAsync(e, 'b');
  523. await HasNextAsync(e, 'c');
  524. await NoNextAsync(e);
  525. }
  526. [Fact]
  527. public async Task SelectAwaitWithCancellation_Throws_Selector()
  528. {
  529. var xs = ToAsyncEnumerable(new[] { 0, 1, 2 });
  530. var ys = xs.SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<int>(1 / x));
  531. var e = ys.GetAsyncEnumerator();
  532. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  533. }
  534. [Fact]
  535. public async Task SelectAwaitWithCancellation_Throws_Selector_IList()
  536. {
  537. var xs = ToAsyncEnumerableIList(new[] { 0, 1, 2 });
  538. var ys = xs.SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<int>(1 / x));
  539. var e = ys.GetAsyncEnumerator();
  540. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  541. }
  542. [Fact]
  543. public async Task SelectAwaitWithCancellation_Throws_Selector_Async_CancelIterator()
  544. {
  545. var xs = new[] { 0, 1, 2 }.ToAsyncEnumerable();
  546. var ys = xs.SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<int>(1 / x));
  547. var e = ys.GetAsyncEnumerator();
  548. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  549. }
  550. [Fact]
  551. public async Task SelectAwaitWithCancellation_Indexed_Throws_Selector()
  552. {
  553. var xs = ToAsyncEnumerable(new[] { 8, 5, 7 });
  554. var ys = xs.SelectAwaitWithCancellation((x, i, ct) => new ValueTask<int>(1 / i));
  555. var e = ys.GetAsyncEnumerator();
  556. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  557. }
  558. [Fact]
  559. public async Task SelectAwaitWithCancellation_Indexed_Throws_Selector_IList()
  560. {
  561. var xs = ToAsyncEnumerableIList(new[] { 8, 5, 7 });
  562. var ys = xs.SelectAwaitWithCancellation((x, i, ct) => new ValueTask<int>(1 / i));
  563. var e = ys.GetAsyncEnumerator();
  564. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  565. }
  566. [Fact]
  567. public async Task SelectAwaitWithCancellation_Indexed_Throws_Selector_Async_CancelIterator()
  568. {
  569. var xs = new[] { 8, 5, 7 }.ToAsyncEnumerable();
  570. var ys = xs.SelectAwaitWithCancellation((x, i, ct) => new ValueTask<int>(1 / i));
  571. var e = ys.GetAsyncEnumerator();
  572. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  573. }
  574. [Fact]
  575. public async Task SelectAwaitWithCancellation_SelectSelect()
  576. {
  577. var xs = ToAsyncEnumerable(new[] { 0, 1, 2 });
  578. var ys = xs.SelectAwaitWithCancellation((int i, CancellationToken ct) => new ValueTask<int>(i + 3)).SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<char>((char)('a' + x)));
  579. var e = ys.GetAsyncEnumerator();
  580. await HasNextAsync(e, 'd');
  581. await HasNextAsync(e, 'e');
  582. await HasNextAsync(e, 'f');
  583. await NoNextAsync(e);
  584. }
  585. [Fact]
  586. public async Task SelectAwaitWithCancellation_SelectSelect_IList()
  587. {
  588. var xs = ToAsyncEnumerableIList(new[] { 0, 1, 2 });
  589. var ys = xs.SelectAwaitWithCancellation((int i, CancellationToken ct) => new ValueTask<int>(i + 3)).SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<char>((char)('a' + x)));
  590. var e = ys.GetAsyncEnumerator();
  591. await HasNextAsync(e, 'd');
  592. await HasNextAsync(e, 'e');
  593. await HasNextAsync(e, 'f');
  594. await NoNextAsync(e);
  595. }
  596. [Fact]
  597. public async Task SelectAwaitWithCancellation_SelectSelectAwait_CancelIterator()
  598. {
  599. var xs = new[] { 0, 1, 2 }.ToAsyncEnumerable();
  600. var ys = xs.SelectAwaitWithCancellation((int i, CancellationToken ct) => new ValueTask<int>(i + 3)).SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<char>((char)('a' + x)));
  601. var e = ys.GetAsyncEnumerator();
  602. await HasNextAsync(e, 'd');
  603. await HasNextAsync(e, 'e');
  604. await HasNextAsync(e, 'f');
  605. await NoNextAsync(e);
  606. }
  607. [Fact]
  608. public async Task SelectAwaitWithCancellation_SequenceIdentity()
  609. {
  610. var xs = ToAsyncEnumerable(new[] { 1, 2, 3 });
  611. var ys = xs.SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<char>((char)('a' + x)));
  612. await SequenceIdentity(ys);
  613. }
  614. [Fact]
  615. public async Task SelectAwaitWithCancellation_SequenceIdentity_IList()
  616. {
  617. var xs = ToAsyncEnumerableIList(new[] { 1, 2, 3 });
  618. var ys = xs.SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<char>((char)('a' + x)));
  619. await SequenceIdentity(ys);
  620. }
  621. [Fact]
  622. public async Task SelectAwaitWithCancellation_SequenceIdentity_Async_CancelIterator()
  623. {
  624. var xs = new[] { 0, 1, 2 }.ToAsyncEnumerable();
  625. var ys = xs.SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<char>((char)('a' + x)));
  626. await SequenceIdentity(ys);
  627. }
  628. [Fact]
  629. public async Task SelectAwaitWithCancellation_Indexed_SequenceIdentity()
  630. {
  631. var xs = ToAsyncEnumerable(new[] { 8, 5, 7 });
  632. var ys = xs.SelectAwaitWithCancellation((x, i, ct) => new ValueTask<char>((char)('a' + i)));
  633. await SequenceIdentity(ys);
  634. }
  635. [Fact]
  636. public async Task SelectAwaitWithCancellation_Indexed_SequenceIdentity_IList()
  637. {
  638. var xs = ToAsyncEnumerableIList(new[] { 8, 5, 7 });
  639. var ys = xs.SelectAwaitWithCancellation((x, i, ct) => new ValueTask<char>((char)('a' + i)));
  640. await SequenceIdentity(ys);
  641. }
  642. [Fact]
  643. public async Task SelectAwaitWithCancellation_Indexed_SequenceIdentity_Async_CancelIterator()
  644. {
  645. var xs = new[] { 8, 5, 7 }.ToAsyncEnumerable();
  646. var ys = xs.SelectAwaitWithCancellation((x, i, ct) => new ValueTask<char>((char)('a' + i)));
  647. await SequenceIdentity(ys);
  648. }
  649. [Fact]
  650. public async Task SelectAwaitWithCancellation_IList_Count()
  651. {
  652. var xs = ToAsyncEnumerableIList(new[] { 1, 2, 3, 4, 5 });
  653. var ys = xs.SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<int>(x * 2));
  654. Assert.Equal(5, await ys.CountAsync());
  655. }
  656. [Fact]
  657. public async Task SelectAwaitWithCancellation_IList_ToList()
  658. {
  659. var xs = ToAsyncEnumerableIList(new[] { 1, 2, 3, 4, 5 });
  660. var ys = xs.SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<int>(x * 2));
  661. Assert.Equal(new[] { 2, 4, 6, 8, 10 }, await ys.ToListAsync());
  662. }
  663. [Fact]
  664. public async Task SelectAwaitWithCancellation_IList_ToArray()
  665. {
  666. var xs = ToAsyncEnumerableIList(new[] { 1, 2, 3, 4, 5 });
  667. var ys = xs.SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<int>(x * 2));
  668. Assert.Equal(new[] { 2, 4, 6, 8, 10 }, await ys.ToArrayAsync());
  669. }
  670. #endif
  671. private static IAsyncEnumerable<int> ToAsyncEnumerable(int[] xs) => new MyIterator(xs);
  672. private class MyIterator : IAsyncEnumerable<int>
  673. {
  674. private readonly int[] _xs;
  675. public MyIterator(int[] xs) => _xs = xs;
  676. public IAsyncEnumerator<int> GetAsyncEnumerator(CancellationToken cancellationToken = default) => new Enumerator(this);
  677. private class Enumerator : IAsyncEnumerator<int>
  678. {
  679. private readonly MyIterator _parent;
  680. private int _i = -1;
  681. public Enumerator(MyIterator parent) => _parent = parent;
  682. public int Current => _parent._xs[_i];
  683. public ValueTask DisposeAsync() => new ValueTask();
  684. public ValueTask<bool> MoveNextAsync() => new ValueTask<bool>(++_i < _parent._xs.Length);
  685. }
  686. }
  687. private static IAsyncEnumerable<int> ToAsyncEnumerableIList(int[] xs) => new MyIteratorIList(xs);
  688. private class MyIteratorIList : IAsyncEnumerable<int>, IList<int>
  689. {
  690. private readonly int[] _xs;
  691. public MyIteratorIList(int[] xs) => _xs = xs;
  692. public int this[int index] { get => _xs[index]; set => throw new NotImplementedException(); }
  693. public int Count => _xs.Length;
  694. public bool IsReadOnly => true;
  695. public void Add(int item) => throw new NotImplementedException();
  696. public void Clear() => throw new NotImplementedException();
  697. public bool Contains(int item) => Array.IndexOf(_xs, item) >= 0;
  698. public void CopyTo(int[] array, int arrayIndex) => throw new NotImplementedException();
  699. public IAsyncEnumerator<int> GetAsyncEnumerator(CancellationToken cancellationToken = default) => new Enumerator(this);
  700. public IEnumerator<int> GetEnumerator() => _xs.AsEnumerable().GetEnumerator();
  701. public int IndexOf(int item) => Array.IndexOf(_xs, item);
  702. public void Insert(int index, int item) => throw new NotImplementedException();
  703. public bool Remove(int item) => throw new NotImplementedException();
  704. public void RemoveAt(int index) => throw new NotImplementedException();
  705. IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
  706. private class Enumerator : IAsyncEnumerator<int>
  707. {
  708. private readonly MyIteratorIList _parent;
  709. private int _i = -1;
  710. public Enumerator(MyIteratorIList parent) => _parent = parent;
  711. public int Current => _parent._xs[_i];
  712. public ValueTask DisposeAsync() => new ValueTask();
  713. public ValueTask<bool> MoveNextAsync() => new ValueTask<bool>(++_i < _parent._xs.Length);
  714. }
  715. }
  716. }
  717. }