Select.cs 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913
  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;
  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([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([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([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([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([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([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([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([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([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([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([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([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([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([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([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([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([1, 2, 3, 4, 5]);
  230. var ys = xs.Select(x => x * 2);
  231. int[] expected = [2, 4, 6, 8, 10];
  232. Assert.Equal(expected, await ys.ToArrayAsync());
  233. }
  234. [Fact]
  235. public void SelectAwait_Null()
  236. {
  237. Assert.Throws<ArgumentNullException>(() => AsyncEnumerable.SelectAwait<int, int>(default, x => new ValueTask<int>(x)));
  238. Assert.Throws<ArgumentNullException>(() => AsyncEnumerable.SelectAwait(default, (int x, int i) => new ValueTask<int>(x)));
  239. Assert.Throws<ArgumentNullException>(() => AsyncEnumerable.SelectAwait(Return42, default(Func<int, ValueTask<int>>)));
  240. Assert.Throws<ArgumentNullException>(() => AsyncEnumerable.SelectAwait(Return42, default(Func<int, int, ValueTask<int>>)));
  241. }
  242. [Fact]
  243. public async Task SelectAwait_Simple()
  244. {
  245. var xs = ToAsyncEnumerable([0, 1, 2]);
  246. var ys = xs.SelectAwait(x => new ValueTask<char>((char)('a' + x)));
  247. var e = ys.GetAsyncEnumerator();
  248. await HasNextAsync(e, 'a');
  249. await HasNextAsync(e, 'b');
  250. await HasNextAsync(e, 'c');
  251. await NoNextAsync(e);
  252. }
  253. [Fact]
  254. public async Task SelectAwait_Simple_IList()
  255. {
  256. var xs = ToAsyncEnumerableIList([0, 1, 2]);
  257. var ys = xs.SelectAwait(x => new ValueTask<char>((char)('a' + x)));
  258. var e = ys.GetAsyncEnumerator();
  259. await HasNextAsync(e, 'a');
  260. await HasNextAsync(e, 'b');
  261. await HasNextAsync(e, 'c');
  262. await NoNextAsync(e);
  263. }
  264. [Fact]
  265. public async Task SelectAwait_Simple_AsyncIterator()
  266. {
  267. var xs = new[] { 0, 1, 2 }.ToAsyncEnumerable();
  268. var ys = xs.SelectAwait(x => new ValueTask<char>((char)('a' + x)));
  269. var e = ys.GetAsyncEnumerator();
  270. await HasNextAsync(e, 'a');
  271. await HasNextAsync(e, 'b');
  272. await HasNextAsync(e, 'c');
  273. await NoNextAsync(e);
  274. }
  275. [Fact]
  276. public async Task SelectAwait_Indexed()
  277. {
  278. var xs = ToAsyncEnumerable([8, 5, 7]);
  279. var ys = xs.SelectAwait((x, i) => new ValueTask<char>((char)('a' + i)));
  280. var e = ys.GetAsyncEnumerator();
  281. await HasNextAsync(e, 'a');
  282. await HasNextAsync(e, 'b');
  283. await HasNextAsync(e, 'c');
  284. await NoNextAsync(e);
  285. }
  286. [Fact]
  287. public async Task SelectAwait_Indexed_IList()
  288. {
  289. var xs = ToAsyncEnumerableIList([8, 5, 7]);
  290. var ys = xs.SelectAwait((x, i) => new ValueTask<char>((char)('a' + i)));
  291. var e = ys.GetAsyncEnumerator();
  292. await HasNextAsync(e, 'a');
  293. await HasNextAsync(e, 'b');
  294. await HasNextAsync(e, 'c');
  295. await NoNextAsync(e);
  296. }
  297. [Fact]
  298. public async Task SelectAwait_Indexed_AsyncIterator()
  299. {
  300. var xs = new[] { 8, 5, 7 }.ToAsyncEnumerable();
  301. var ys = xs.SelectAwait((x, i) => new ValueTask<char>((char)('a' + i)));
  302. var e = ys.GetAsyncEnumerator();
  303. await HasNextAsync(e, 'a');
  304. await HasNextAsync(e, 'b');
  305. await HasNextAsync(e, 'c');
  306. await NoNextAsync(e);
  307. }
  308. [Fact]
  309. public async Task SelectAwait_Throws_Selector()
  310. {
  311. var xs = ToAsyncEnumerable([0, 1, 2]);
  312. var ys = xs.SelectAwait(x => new ValueTask<int>(1 / x));
  313. var e = ys.GetAsyncEnumerator();
  314. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  315. }
  316. [Fact]
  317. public async Task SelectAwait_Throws_Selector_IList()
  318. {
  319. var xs = ToAsyncEnumerableIList([0, 1, 2]);
  320. var ys = xs.SelectAwait(x => new ValueTask<int>(1 / x));
  321. var e = ys.GetAsyncEnumerator();
  322. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  323. }
  324. [Fact]
  325. public async Task SelectAwait_Throws_Selector_AsyncIterator()
  326. {
  327. var xs = new[] { 0, 1, 2 }.ToAsyncEnumerable();
  328. var ys = xs.SelectAwait(x => new ValueTask<int>(1 / x));
  329. var e = ys.GetAsyncEnumerator();
  330. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  331. }
  332. [Fact]
  333. public async Task SelectAwait_Indexed_Throws_Selector()
  334. {
  335. var xs = ToAsyncEnumerable([8, 5, 7]);
  336. var ys = xs.SelectAwait((x, i) => new ValueTask<int>(1 / i));
  337. var e = ys.GetAsyncEnumerator();
  338. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  339. }
  340. [Fact]
  341. public async Task SelectAwait_Indexed_Throws_Selector_IList()
  342. {
  343. var xs = ToAsyncEnumerableIList([8, 5, 7]);
  344. var ys = xs.SelectAwait((x, i) => new ValueTask<int>(1 / i));
  345. var e = ys.GetAsyncEnumerator();
  346. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  347. }
  348. [Fact]
  349. public async Task SelectAwait_Indexed_Throws_Selector_AsyncIterator()
  350. {
  351. var xs = new[] { 8, 5, 7 }.ToAsyncEnumerable();
  352. var ys = xs.SelectAwait((x, i) => new ValueTask<int>(1 / i));
  353. var e = ys.GetAsyncEnumerator();
  354. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  355. }
  356. [Fact]
  357. public async Task SelectAwait_SelectSelect()
  358. {
  359. var xs = ToAsyncEnumerable([0, 1, 2]);
  360. var ys = xs.SelectAwait(i => new ValueTask<int>(i + 3)).SelectAwait(x => new ValueTask<char>((char)('a' + x)));
  361. var e = ys.GetAsyncEnumerator();
  362. await HasNextAsync(e, 'd');
  363. await HasNextAsync(e, 'e');
  364. await HasNextAsync(e, 'f');
  365. await NoNextAsync(e);
  366. }
  367. [Fact]
  368. public async Task SelectAwait_SelectSelect_IList()
  369. {
  370. var xs = ToAsyncEnumerableIList([0, 1, 2]);
  371. var ys = xs.SelectAwait(i => new ValueTask<int>(i + 3)).SelectAwait(x => new ValueTask<char>((char)('a' + x)));
  372. var e = ys.GetAsyncEnumerator();
  373. await HasNextAsync(e, 'd');
  374. await HasNextAsync(e, 'e');
  375. await HasNextAsync(e, 'f');
  376. await NoNextAsync(e);
  377. }
  378. [Fact]
  379. public async Task SelectAwait_SelectSelectAwaitIterator()
  380. {
  381. var xs = new[] { 0, 1, 2 }.ToAsyncEnumerable();
  382. var ys = xs.SelectAwait(i => new ValueTask<int>(i + 3)).SelectAwait(x => new ValueTask<char>((char)('a' + x)));
  383. var e = ys.GetAsyncEnumerator();
  384. await HasNextAsync(e, 'd');
  385. await HasNextAsync(e, 'e');
  386. await HasNextAsync(e, 'f');
  387. await NoNextAsync(e);
  388. }
  389. [Fact]
  390. public async Task SelectAwait_SequenceIdentity()
  391. {
  392. var xs = ToAsyncEnumerable([1, 2, 3]);
  393. var ys = xs.SelectAwait(x => new ValueTask<char>((char)('a' + x)));
  394. await SequenceIdentity(ys);
  395. }
  396. [Fact]
  397. public async Task SelectAwait_SequenceIdentity_IList()
  398. {
  399. var xs = ToAsyncEnumerableIList([1, 2, 3]);
  400. var ys = xs.SelectAwait(x => new ValueTask<char>((char)('a' + x)));
  401. await SequenceIdentity(ys);
  402. }
  403. [Fact]
  404. public async Task SelectAwait_SequenceIdentity_AsyncIterator()
  405. {
  406. var xs = new[] { 0, 1, 2 }.ToAsyncEnumerable();
  407. var ys = xs.SelectAwait(x => new ValueTask<char>((char)('a' + x)));
  408. await SequenceIdentity(ys);
  409. }
  410. [Fact]
  411. public async Task SelectAwait_Indexed_SequenceIdentity()
  412. {
  413. var xs = ToAsyncEnumerable([8, 5, 7]);
  414. var ys = xs.SelectAwait((x, i) => new ValueTask<char>((char)('a' + i)));
  415. await SequenceIdentity(ys);
  416. }
  417. [Fact]
  418. public async Task SelectAwait_Indexed_SequenceIdentity_IList()
  419. {
  420. var xs = ToAsyncEnumerableIList([8, 5, 7]);
  421. var ys = xs.SelectAwait((x, i) => new ValueTask<char>((char)('a' + i)));
  422. await SequenceIdentity(ys);
  423. }
  424. [Fact]
  425. public async Task SelectAwait_Indexed_SequenceIdentity_AsyncIterator()
  426. {
  427. var xs = new[] { 8, 5, 7 }.ToAsyncEnumerable();
  428. var ys = xs.SelectAwait((x, i) => new ValueTask<char>((char)('a' + i)));
  429. await SequenceIdentity(ys);
  430. }
  431. [Fact]
  432. public async Task SelectAwait_IList_Count()
  433. {
  434. var xs = ToAsyncEnumerableIList([1, 2, 3, 4, 5]);
  435. var ys = xs.SelectAwait(x => new ValueTask<int>(x * 2));
  436. Assert.Equal(5, await ys.CountAsync());
  437. }
  438. [Fact]
  439. public async Task SelectAwait_IList_ToList()
  440. {
  441. var xs = ToAsyncEnumerableIList([1, 2, 3, 4, 5]);
  442. var ys = xs.SelectAwait(x => new ValueTask<int>(x * 2));
  443. Assert.Equal(new[] { 2, 4, 6, 8, 10 }, await ys.ToListAsync());
  444. }
  445. [Fact]
  446. public async Task SelectAwait_IList_ToArray()
  447. {
  448. var xs = ToAsyncEnumerableIList([1, 2, 3, 4, 5]);
  449. var ys = xs.SelectAwait(x => new ValueTask<int>(x * 2));
  450. int[] expected = [2, 4, 6, 8, 10];
  451. Assert.Equal(expected, await ys.ToArrayAsync());
  452. }
  453. #if !NO_DEEP_CANCELLATION
  454. [Fact]
  455. public void SelectAwaitWithCancellation_Null()
  456. {
  457. Assert.Throws<ArgumentNullException>(() => AsyncEnumerable.SelectAwaitWithCancellation(default, (int x, CancellationToken ct) => new ValueTask<int>(x)));
  458. Assert.Throws<ArgumentNullException>(() => AsyncEnumerable.SelectAwaitWithCancellation(default, (int x, int i, CancellationToken ct) => new ValueTask<int>(x)));
  459. Assert.Throws<ArgumentNullException>(() => AsyncEnumerable.SelectAwaitWithCancellation(Return42, default(Func<int, CancellationToken, ValueTask<int>>)));
  460. Assert.Throws<ArgumentNullException>(() => AsyncEnumerable.SelectAwaitWithCancellation(Return42, default(Func<int, int, CancellationToken, ValueTask<int>>)));
  461. }
  462. [Fact]
  463. public async Task SelectAwaitWithCancellation_Simple()
  464. {
  465. var xs = ToAsyncEnumerable([0, 1, 2]);
  466. var ys = xs.SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<char>((char)('a' + x)));
  467. var e = ys.GetAsyncEnumerator();
  468. await HasNextAsync(e, 'a');
  469. await HasNextAsync(e, 'b');
  470. await HasNextAsync(e, 'c');
  471. await NoNextAsync(e);
  472. }
  473. [Fact]
  474. public async Task SelectAwaitWithCancellation_Simple_IList()
  475. {
  476. var xs = ToAsyncEnumerableIList([0, 1, 2]);
  477. var ys = xs.SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<char>((char)('a' + x)));
  478. var e = ys.GetAsyncEnumerator();
  479. await HasNextAsync(e, 'a');
  480. await HasNextAsync(e, 'b');
  481. await HasNextAsync(e, 'c');
  482. await NoNextAsync(e);
  483. }
  484. [Fact]
  485. public async Task SelectAwaitWithCancellation_Simple_Async_CancelIterator()
  486. {
  487. var xs = new[] { 0, 1, 2 }.ToAsyncEnumerable();
  488. var ys = xs.SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<char>((char)('a' + x)));
  489. var e = ys.GetAsyncEnumerator();
  490. await HasNextAsync(e, 'a');
  491. await HasNextAsync(e, 'b');
  492. await HasNextAsync(e, 'c');
  493. await NoNextAsync(e);
  494. }
  495. [Fact]
  496. public async Task SelectAwaitWithCancellation_Indexed()
  497. {
  498. var xs = ToAsyncEnumerable([8, 5, 7]);
  499. var ys = xs.SelectAwaitWithCancellation((x, i, ct) => new ValueTask<char>((char)('a' + i)));
  500. var e = ys.GetAsyncEnumerator();
  501. await HasNextAsync(e, 'a');
  502. await HasNextAsync(e, 'b');
  503. await HasNextAsync(e, 'c');
  504. await NoNextAsync(e);
  505. }
  506. [Fact]
  507. public async Task SelectAwaitWithCancellation_Indexed_IList()
  508. {
  509. var xs = ToAsyncEnumerableIList([8, 5, 7]);
  510. var ys = xs.SelectAwaitWithCancellation((x, i, ct) => new ValueTask<char>((char)('a' + i)));
  511. var e = ys.GetAsyncEnumerator();
  512. await HasNextAsync(e, 'a');
  513. await HasNextAsync(e, 'b');
  514. await HasNextAsync(e, 'c');
  515. await NoNextAsync(e);
  516. }
  517. [Fact]
  518. public async Task SelectAwaitWithCancellation_Indexed_Async_CancelIterator()
  519. {
  520. var xs = new[] { 8, 5, 7 }.ToAsyncEnumerable();
  521. var ys = xs.SelectAwaitWithCancellation((x, i, ct) => new ValueTask<char>((char)('a' + i)));
  522. var e = ys.GetAsyncEnumerator();
  523. await HasNextAsync(e, 'a');
  524. await HasNextAsync(e, 'b');
  525. await HasNextAsync(e, 'c');
  526. await NoNextAsync(e);
  527. }
  528. [Fact]
  529. public async Task SelectAwaitWithCancellation_Throws_Selector()
  530. {
  531. var xs = ToAsyncEnumerable([0, 1, 2]);
  532. var ys = xs.SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<int>(1 / x));
  533. var e = ys.GetAsyncEnumerator();
  534. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  535. }
  536. [Fact]
  537. public async Task SelectAwaitWithCancellation_Throws_Selector_IList()
  538. {
  539. var xs = ToAsyncEnumerableIList([0, 1, 2]);
  540. var ys = xs.SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<int>(1 / x));
  541. var e = ys.GetAsyncEnumerator();
  542. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  543. }
  544. [Fact]
  545. public async Task SelectAwaitWithCancellation_Throws_Selector_Async_CancelIterator()
  546. {
  547. var xs = new[] { 0, 1, 2 }.ToAsyncEnumerable();
  548. var ys = xs.SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<int>(1 / x));
  549. var e = ys.GetAsyncEnumerator();
  550. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  551. }
  552. [Fact]
  553. public async Task SelectAwaitWithCancellation_Indexed_Throws_Selector()
  554. {
  555. var xs = ToAsyncEnumerable([8, 5, 7]);
  556. var ys = xs.SelectAwaitWithCancellation((x, i, ct) => new ValueTask<int>(1 / i));
  557. var e = ys.GetAsyncEnumerator();
  558. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  559. }
  560. [Fact]
  561. public async Task SelectAwaitWithCancellation_Indexed_Throws_Selector_IList()
  562. {
  563. var xs = ToAsyncEnumerableIList([8, 5, 7]);
  564. var ys = xs.SelectAwaitWithCancellation((x, i, ct) => new ValueTask<int>(1 / i));
  565. var e = ys.GetAsyncEnumerator();
  566. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  567. }
  568. [Fact]
  569. public async Task SelectAwaitWithCancellation_Indexed_Throws_Selector_Async_CancelIterator()
  570. {
  571. var xs = new[] { 8, 5, 7 }.ToAsyncEnumerable();
  572. var ys = xs.SelectAwaitWithCancellation((x, i, ct) => new ValueTask<int>(1 / i));
  573. var e = ys.GetAsyncEnumerator();
  574. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  575. }
  576. [Fact]
  577. public async Task SelectAwaitWithCancellation_SelectSelect()
  578. {
  579. var xs = ToAsyncEnumerable([0, 1, 2]);
  580. var ys = xs.SelectAwaitWithCancellation((int i, CancellationToken ct) => new ValueTask<int>(i + 3)).SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<char>((char)('a' + x)));
  581. var e = ys.GetAsyncEnumerator();
  582. await HasNextAsync(e, 'd');
  583. await HasNextAsync(e, 'e');
  584. await HasNextAsync(e, 'f');
  585. await NoNextAsync(e);
  586. }
  587. [Fact]
  588. public async Task SelectAwaitWithCancellation_SelectSelect_IList()
  589. {
  590. var xs = ToAsyncEnumerableIList([0, 1, 2]);
  591. var ys = xs.SelectAwaitWithCancellation((int i, CancellationToken ct) => new ValueTask<int>(i + 3)).SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<char>((char)('a' + x)));
  592. var e = ys.GetAsyncEnumerator();
  593. await HasNextAsync(e, 'd');
  594. await HasNextAsync(e, 'e');
  595. await HasNextAsync(e, 'f');
  596. await NoNextAsync(e);
  597. }
  598. [Fact]
  599. public async Task SelectAwaitWithCancellation_SelectSelectAwait_CancelIterator()
  600. {
  601. var xs = new[] { 0, 1, 2 }.ToAsyncEnumerable();
  602. var ys = xs.SelectAwaitWithCancellation((int i, CancellationToken ct) => new ValueTask<int>(i + 3)).SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<char>((char)('a' + x)));
  603. var e = ys.GetAsyncEnumerator();
  604. await HasNextAsync(e, 'd');
  605. await HasNextAsync(e, 'e');
  606. await HasNextAsync(e, 'f');
  607. await NoNextAsync(e);
  608. }
  609. [Fact]
  610. public async Task SelectAwaitWithCancellation_SequenceIdentity()
  611. {
  612. var xs = ToAsyncEnumerable([1, 2, 3]);
  613. var ys = xs.SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<char>((char)('a' + x)));
  614. await SequenceIdentity(ys);
  615. }
  616. [Fact]
  617. public async Task SelectAwaitWithCancellation_SequenceIdentity_IList()
  618. {
  619. var xs = ToAsyncEnumerableIList([1, 2, 3]);
  620. var ys = xs.SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<char>((char)('a' + x)));
  621. await SequenceIdentity(ys);
  622. }
  623. [Fact]
  624. public async Task SelectAwaitWithCancellation_SequenceIdentity_Async_CancelIterator()
  625. {
  626. var xs = new[] { 0, 1, 2 }.ToAsyncEnumerable();
  627. var ys = xs.SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<char>((char)('a' + x)));
  628. await SequenceIdentity(ys);
  629. }
  630. [Fact]
  631. public async Task SelectAwaitWithCancellation_Indexed_SequenceIdentity()
  632. {
  633. var xs = ToAsyncEnumerable([8, 5, 7]);
  634. var ys = xs.SelectAwaitWithCancellation((x, i, ct) => new ValueTask<char>((char)('a' + i)));
  635. await SequenceIdentity(ys);
  636. }
  637. [Fact]
  638. public async Task SelectAwaitWithCancellation_Indexed_SequenceIdentity_IList()
  639. {
  640. var xs = ToAsyncEnumerableIList([8, 5, 7]);
  641. var ys = xs.SelectAwaitWithCancellation((x, i, ct) => new ValueTask<char>((char)('a' + i)));
  642. await SequenceIdentity(ys);
  643. }
  644. [Fact]
  645. public async Task SelectAwaitWithCancellation_Indexed_SequenceIdentity_Async_CancelIterator()
  646. {
  647. var xs = new[] { 8, 5, 7 }.ToAsyncEnumerable();
  648. var ys = xs.SelectAwaitWithCancellation((x, i, ct) => new ValueTask<char>((char)('a' + i)));
  649. await SequenceIdentity(ys);
  650. }
  651. [Fact]
  652. public async Task SelectAwaitWithCancellation_IList_Count()
  653. {
  654. var xs = ToAsyncEnumerableIList([1, 2, 3, 4, 5]);
  655. var ys = xs.SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<int>(x * 2));
  656. Assert.Equal(5, await ys.CountAsync());
  657. }
  658. [Fact]
  659. public async Task SelectAwaitWithCancellation_IList_ToList()
  660. {
  661. var xs = ToAsyncEnumerableIList([1, 2, 3, 4, 5]);
  662. var ys = xs.SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<int>(x * 2));
  663. Assert.Equal(new[] { 2, 4, 6, 8, 10 }, await ys.ToListAsync());
  664. }
  665. [Fact]
  666. public async Task SelectAwaitWithCancellation_IList_ToArray()
  667. {
  668. var xs = ToAsyncEnumerableIList([1, 2, 3, 4, 5]);
  669. var ys = xs.SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<int>(x * 2));
  670. int[] expected = [2, 4, 6, 8, 10];
  671. Assert.Equal(expected, await ys.ToArrayAsync());
  672. }
  673. #endif
  674. #if NET8_0_OR_GREATER
  675. #pragma warning disable CA1859 // Use specific iterator type for perf. Not really necessary for tests.
  676. #endif
  677. private static IAsyncEnumerable<int> ToAsyncEnumerable(int[] xs) => new MyIterator(xs);
  678. #if NET8_0_OR_GREATER
  679. #pragma warning restore CA1859
  680. #endif
  681. private class MyIterator : IAsyncEnumerable<int>
  682. {
  683. private readonly int[] _xs;
  684. public MyIterator(int[] xs) => _xs = xs;
  685. public IAsyncEnumerator<int> GetAsyncEnumerator(CancellationToken cancellationToken = default) => new Enumerator(this);
  686. private class Enumerator : IAsyncEnumerator<int>
  687. {
  688. private readonly MyIterator _parent;
  689. private int _i = -1;
  690. public Enumerator(MyIterator parent) => _parent = parent;
  691. public int Current => _parent._xs[_i];
  692. public ValueTask DisposeAsync() => new();
  693. public ValueTask<bool> MoveNextAsync() => new(++_i < _parent._xs.Length);
  694. }
  695. }
  696. #if NET8_0_OR_GREATER
  697. #pragma warning disable CA1859 // Use specific iterator type for perf. Not really necessary for tests.
  698. #endif
  699. private static IAsyncEnumerable<int> ToAsyncEnumerableIList(int[] xs) => new MyIteratorIList(xs);
  700. #if NET8_0_OR_GREATER
  701. #pragma warning restore CA1859
  702. #endif
  703. private class MyIteratorIList : IAsyncEnumerable<int>, IList<int>
  704. {
  705. private readonly int[] _xs;
  706. public MyIteratorIList(int[] xs) => _xs = xs;
  707. public int this[int index] { get => _xs[index]; set => throw new NotImplementedException(); }
  708. public int Count => _xs.Length;
  709. public bool IsReadOnly => true;
  710. public void Add(int item) => throw new NotImplementedException();
  711. public void Clear() => throw new NotImplementedException();
  712. public bool Contains(int item) => Array.IndexOf(_xs, item) >= 0;
  713. public void CopyTo(int[] array, int arrayIndex) => throw new NotImplementedException();
  714. public IAsyncEnumerator<int> GetAsyncEnumerator(CancellationToken cancellationToken = default) => new Enumerator(this);
  715. public IEnumerator<int> GetEnumerator() => _xs.AsEnumerable().GetEnumerator();
  716. public int IndexOf(int item) => Array.IndexOf(_xs, item);
  717. public void Insert(int index, int item) => throw new NotImplementedException();
  718. public bool Remove(int item) => throw new NotImplementedException();
  719. public void RemoveAt(int index) => throw new NotImplementedException();
  720. IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
  721. private class Enumerator : IAsyncEnumerator<int>
  722. {
  723. private readonly MyIteratorIList _parent;
  724. private int _i = -1;
  725. public Enumerator(MyIteratorIList parent) => _parent = parent;
  726. public int Current => _parent._xs[_i];
  727. public ValueTask DisposeAsync() => new();
  728. public ValueTask<bool> MoveNextAsync() => new(++_i < _parent._xs.Length);
  729. }
  730. }
  731. }
  732. }