SingleOrDefault.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  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.Linq;
  6. using System.Threading;
  7. using System.Threading.Tasks;
  8. using Xunit;
  9. namespace Tests
  10. {
  11. public class SingleOrDefault : AsyncEnumerableTests
  12. {
  13. [Fact]
  14. public async Task SingleOrDefaultAsync_Null()
  15. {
  16. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.SingleOrDefaultAsync<int>(default).AsTask());
  17. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.SingleOrDefaultAsync<int>(default, CancellationToken.None).AsTask());
  18. }
  19. [Fact]
  20. public async Task SingleOrDefaultAsync_Empty()
  21. {
  22. var res = AsyncEnumerable.Empty<int>().SingleOrDefaultAsync();
  23. Assert.Equal(0, await res);
  24. }
  25. [Fact]
  26. public async Task SingleOrDefaultAsync_Empty_IList()
  27. {
  28. var res = new int[0].ToAsyncEnumerable().SingleOrDefaultAsync();
  29. Assert.Equal(0, await res);
  30. }
  31. [Fact]
  32. public async Task SingleOrDefaultAsync_Single_IList()
  33. {
  34. var res = Return42.SingleOrDefaultAsync();
  35. Assert.Equal(42, await res);
  36. }
  37. [Fact]
  38. public async Task SingleOrDefaultAsync_Single()
  39. {
  40. var res = new[] { 42 }.ToAsyncEnumerable().Where(x => x > 0).SingleOrDefaultAsync();
  41. Assert.Equal(42, await res);
  42. }
  43. [Fact]
  44. public async Task SingleOrDefaultAsync_Throws_Source()
  45. {
  46. var ex = new Exception("Bang!");
  47. var res = Throw<int>(ex).SingleOrDefaultAsync();
  48. await AssertThrowsAsync(res, ex);
  49. }
  50. [Fact]
  51. public async Task SingleOrDefaultAsync_MoreThanOne_IList()
  52. {
  53. var res = new[] { 42, 45, 90 }.ToAsyncEnumerable().SingleOrDefaultAsync();
  54. await AssertThrowsAsync<InvalidOperationException>(res.AsTask());
  55. }
  56. [Fact]
  57. public async Task SingleOrDefaultAsync_MoreThanOne()
  58. {
  59. var res = new[] { 42, 45, 90 }.ToAsyncEnumerable().Select(x => x).SingleOrDefaultAsync();
  60. await AssertThrowsAsync<InvalidOperationException>(res.AsTask());
  61. }
  62. [Fact]
  63. public async Task SingleOrDefaultAsync_Predicate_Null()
  64. {
  65. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.SingleOrDefaultAsync<int>(default, x => true).AsTask());
  66. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.SingleOrDefaultAsync(Return42, default(Func<int, bool>)).AsTask());
  67. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.SingleOrDefaultAsync<int>(default, x => true, CancellationToken.None).AsTask());
  68. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.SingleOrDefaultAsync(Return42, default, CancellationToken.None).AsTask());
  69. }
  70. [Fact]
  71. public async Task SingleOrDefaultAsync_Predicate_Empty()
  72. {
  73. var res = AsyncEnumerable.Empty<int>().SingleOrDefaultAsync(x => true);
  74. Assert.Equal(0, await res);
  75. }
  76. [Fact]
  77. public async Task SingleOrDefaultAsync_Predicate_NoMatch_Single()
  78. {
  79. var res = Return42.SingleOrDefaultAsync(x => x % 2 != 0);
  80. Assert.Equal(0, await res);
  81. }
  82. [Fact]
  83. public async Task SingleOrDefaultAsync_Predicate_OneMatch_Single()
  84. {
  85. var res = Return42.SingleOrDefaultAsync(x => x % 2 == 0);
  86. Assert.Equal(42, await res);
  87. }
  88. [Fact]
  89. public async Task SingleOrDefaultAsync_Predicate_OneMatch_Many()
  90. {
  91. var res = new[] { 42, 45, 90 }.ToAsyncEnumerable().SingleOrDefaultAsync(x => x % 2 != 0);
  92. Assert.Equal(45, await res);
  93. }
  94. [Fact]
  95. public async Task SingleOrDefaultAsync_Predicate_NoMatch_Many()
  96. {
  97. var res = new[] { 42, 45, 90 }.ToAsyncEnumerable().SingleOrDefaultAsync(x => x < 10);
  98. Assert.Equal(0, await res);
  99. }
  100. [Fact]
  101. public async Task SingleOrDefaultAsync_Predicate_MoreThanOne()
  102. {
  103. var res = new[] { 42, 45, 90 }.ToAsyncEnumerable().SingleOrDefaultAsync(x => true);
  104. await AssertThrowsAsync<InvalidOperationException>(res.AsTask());
  105. }
  106. [Fact]
  107. public async Task SingleOrDefaultAsync_Predicate_Throws_Source()
  108. {
  109. var ex = new Exception("Bang!");
  110. var res = Throw<int>(ex).SingleOrDefaultAsync(x => true);
  111. await AssertThrowsAsync(res, ex);
  112. }
  113. [Fact]
  114. public async Task SingleOrDefaultAwaitAsync_Predicate_Null()
  115. {
  116. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.SingleOrDefaultAwaitAsync<int>(default, x => new ValueTask<bool>(true)).AsTask());
  117. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.SingleOrDefaultAwaitAsync(Return42, default).AsTask());
  118. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.SingleOrDefaultAwaitAsync<int>(default, x => new ValueTask<bool>(true), CancellationToken.None).AsTask());
  119. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.SingleOrDefaultAwaitAsync(Return42, default, CancellationToken.None).AsTask());
  120. }
  121. [Fact]
  122. public async Task SingleOrDefaultAwaitAsync_Predicate_Empty()
  123. {
  124. var res = AsyncEnumerable.Empty<int>().SingleOrDefaultAwaitAsync(x => new ValueTask<bool>(true));
  125. Assert.Equal(0, await res);
  126. }
  127. [Fact]
  128. public async Task SingleOrDefaultAwaitAsync_Predicate_NoMatch_Single()
  129. {
  130. var res = Return42.SingleOrDefaultAwaitAsync(x => new ValueTask<bool>(x % 2 != 0));
  131. Assert.Equal(0, await res);
  132. }
  133. [Fact]
  134. public async Task SingleOrDefaultAwaitAsync_Predicate_OneMatch_Single()
  135. {
  136. var res = Return42.SingleOrDefaultAwaitAsync(x => new ValueTask<bool>(x % 2 == 0));
  137. Assert.Equal(42, await res);
  138. }
  139. [Fact]
  140. public async Task SingleOrDefaultAwaitAsync_Predicate_OneMatch_Many()
  141. {
  142. var res = new[] { 42, 45, 90 }.ToAsyncEnumerable().SingleOrDefaultAwaitAsync(x => new ValueTask<bool>(x % 2 != 0));
  143. Assert.Equal(45, await res);
  144. }
  145. [Fact]
  146. public async Task SingleOrDefaultAwaitAsync_Predicate_NoMatch_Many()
  147. {
  148. var res = new[] { 42, 45, 90 }.ToAsyncEnumerable().SingleOrDefaultAwaitAsync(x => new ValueTask<bool>(x < 10));
  149. Assert.Equal(0, await res);
  150. }
  151. [Fact]
  152. public async Task SingleOrDefaultAwaitAsync_Predicate_MoreThanOne()
  153. {
  154. var res = new[] { 42, 45, 90 }.ToAsyncEnumerable().SingleOrDefaultAwaitAsync(x => new ValueTask<bool>(true));
  155. await AssertThrowsAsync<InvalidOperationException>(res.AsTask());
  156. }
  157. [Fact]
  158. public async Task SingleOrDefaultAwaitAsync_Predicate_Throws_Source()
  159. {
  160. var ex = new Exception("Bang!");
  161. var res = Throw<int>(ex).SingleOrDefaultAwaitAsync(x => new ValueTask<bool>(true));
  162. await AssertThrowsAsync(res, ex);
  163. }
  164. #if !NO_DEEP_CANCELLATION
  165. [Fact]
  166. public async Task SingleOrDefaultAwaitWithCancellationAsync_Predicate_Null()
  167. {
  168. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.SingleOrDefaultAwaitWithCancellationAsync<int>(default, (x, ct) => new ValueTask<bool>(true), CancellationToken.None).AsTask());
  169. await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.SingleOrDefaultAwaitWithCancellationAsync(Return42, default, CancellationToken.None).AsTask());
  170. }
  171. [Fact]
  172. public async Task SingleOrDefaultAwaitWithCancellationAsync_Predicate_Empty()
  173. {
  174. var res = AsyncEnumerable.Empty<int>().SingleOrDefaultAwaitWithCancellationAsync((x, ct) => new ValueTask<bool>(true));
  175. Assert.Equal(0, await res);
  176. }
  177. [Fact]
  178. public async Task SingleOrDefaultAwaitWithCancellationAsync_Predicate_NoMatch_Single()
  179. {
  180. var res = Return42.SingleOrDefaultAwaitWithCancellationAsync((x, ct) => new ValueTask<bool>(x % 2 != 0));
  181. Assert.Equal(0, await res);
  182. }
  183. [Fact]
  184. public async Task SingleOrDefaultAwaitWithCancellationAsync_Predicate_OneMatch_Single()
  185. {
  186. var res = Return42.SingleOrDefaultAwaitWithCancellationAsync((x, ct) => new ValueTask<bool>(x % 2 == 0));
  187. Assert.Equal(42, await res);
  188. }
  189. [Fact]
  190. public async Task SingleOrDefaultAwaitWithCancellationAsync_Predicate_OneMatch_Many()
  191. {
  192. var res = new[] { 42, 45, 90 }.ToAsyncEnumerable().SingleOrDefaultAwaitWithCancellationAsync((x, ct) => new ValueTask<bool>(x % 2 != 0));
  193. Assert.Equal(45, await res);
  194. }
  195. [Fact]
  196. public async Task SingleOrDefaultAwaitWithCancellationAsync_Predicate_NoMatch_Many()
  197. {
  198. var res = new[] { 42, 45, 90 }.ToAsyncEnumerable().SingleOrDefaultAwaitWithCancellationAsync((x, ct) => new ValueTask<bool>(x < 10));
  199. Assert.Equal(0, await res);
  200. }
  201. [Fact]
  202. public async Task SingleOrDefaultAwaitWithCancellationAsync_Predicate_MoreThanOne()
  203. {
  204. var res = new[] { 42, 45, 90 }.ToAsyncEnumerable().SingleOrDefaultAwaitWithCancellationAsync((x, ct) => new ValueTask<bool>(true));
  205. await AssertThrowsAsync<InvalidOperationException>(res.AsTask());
  206. }
  207. [Fact]
  208. public async Task SingleOrDefaultAwaitWithCancellationAsync_Predicate_Throws_Source()
  209. {
  210. var ex = new Exception("Bang!");
  211. var res = Throw<int>(ex).SingleOrDefaultAwaitWithCancellationAsync((x, ct) => new ValueTask<bool>(true));
  212. await AssertThrowsAsync(res, ex);
  213. }
  214. #endif
  215. }
  216. }