Select.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  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_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_SelectSelect_AsyncIterator()
  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. private static IAsyncEnumerable<int> ToAsyncEnumerable(int[] xs) => new MyIterator(xs);
  213. private class MyIterator : IAsyncEnumerable<int>
  214. {
  215. private readonly int[] _xs;
  216. public MyIterator(int[] xs) => _xs = xs;
  217. public IAsyncEnumerator<int> GetAsyncEnumerator(CancellationToken cancellationToken = default) => new Enumerator(this);
  218. private class Enumerator : IAsyncEnumerator<int>
  219. {
  220. private readonly MyIterator _parent;
  221. private int _i = -1;
  222. public Enumerator(MyIterator parent) => _parent = parent;
  223. public int Current => _parent._xs[_i];
  224. public ValueTask DisposeAsync() => new ValueTask();
  225. public ValueTask<bool> MoveNextAsync() => new ValueTask<bool>(++_i < _parent._xs.Length);
  226. }
  227. }
  228. private static IAsyncEnumerable<int> ToAsyncEnumerableIList(int[] xs) => new MyIteratorIList(xs);
  229. private class MyIteratorIList : IAsyncEnumerable<int>, IList<int>
  230. {
  231. private readonly int[] _xs;
  232. public MyIteratorIList(int[] xs) => _xs = xs;
  233. public int this[int index] { get => _xs[index]; set => throw new NotImplementedException(); }
  234. public int Count => _xs.Length;
  235. public bool IsReadOnly => true;
  236. public void Add(int item) => throw new NotImplementedException();
  237. public void Clear() => throw new NotImplementedException();
  238. public bool Contains(int item) => Array.IndexOf(_xs, item) >= 0;
  239. public void CopyTo(int[] array, int arrayIndex) => throw new NotImplementedException();
  240. public IAsyncEnumerator<int> GetAsyncEnumerator(CancellationToken cancellationToken = default) => new Enumerator(this);
  241. public IEnumerator<int> GetEnumerator() => _xs.AsEnumerable().GetEnumerator();
  242. public int IndexOf(int item) => Array.IndexOf(_xs, item);
  243. public void Insert(int index, int item) => throw new NotImplementedException();
  244. public bool Remove(int item) => throw new NotImplementedException();
  245. public void RemoveAt(int index) => throw new NotImplementedException();
  246. IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
  247. private class Enumerator : IAsyncEnumerator<int>
  248. {
  249. private readonly MyIteratorIList _parent;
  250. private int _i = -1;
  251. public Enumerator(MyIteratorIList parent) => _parent = parent;
  252. public int Current => _parent._xs[_i];
  253. public ValueTask DisposeAsync() => new ValueTask();
  254. public ValueTask<bool> MoveNextAsync() => new ValueTask<bool>(++_i < _parent._xs.Length);
  255. }
  256. }
  257. }
  258. }