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 5 using System.Collections.Generic; 6 using Xunit; 7 8 namespace System.Linq.Parallel.Tests 9 { 10 public static class TakeTakeWhileTests 11 { 12 private static readonly Func<int, IEnumerable<int>> TakePosition = x => new[] { -x, -1, 0, 1, x / 2, x, x * 2 }.Distinct(); 13 14 // 15 // Take 16 // 17 TakeUnorderedData(int[] counts)18 public static IEnumerable<object[]> TakeUnorderedData(int[] counts) 19 { 20 foreach (int count in counts.DefaultIfEmpty(Sources.OuterLoopCount / 4)) 21 { 22 foreach (int position in TakePosition(count)) 23 { 24 yield return new object[] { count, position }; 25 } 26 } 27 } 28 TakeData(int[] counts)29 public static IEnumerable<object[]> TakeData(int[] counts) 30 { 31 foreach (object[] results in Sources.Ranges(counts.DefaultIfEmpty(Sources.OuterLoopCount / 4), TakePosition)) yield return results; 32 } 33 34 [Theory] 35 [MemberData(nameof(TakeUnorderedData), new[] { 0, 1, 2, 16 })] Take_Unordered(int count, int take)36 public static void Take_Unordered(int count, int take) 37 { 38 // For unordered collections, which elements (if any) are taken isn't actually guaranteed, but an effect of the implementation. 39 // If this test starts failing it should be updated, and possibly mentioned in release notes. 40 IntegerRangeSet seen = new IntegerRangeSet(0, Math.Min(count, Math.Max(0, take))); 41 foreach (int i in UnorderedSources.Default(count).Take(take)) 42 { 43 seen.Add(i); 44 } 45 seen.AssertComplete(); 46 } 47 48 [Theory] 49 [OuterLoop] 50 [MemberData(nameof(TakeUnorderedData), new int[] { /* Sources.OuterLoopCount */ })] Take_Unordered_Longrunning(int count, int take)51 public static void Take_Unordered_Longrunning(int count, int take) 52 { 53 Take_Unordered(count, take); 54 } 55 56 [Theory] 57 [MemberData(nameof(TakeData), new[] { 0, 1, 2, 16 })] Take(Labeled<ParallelQuery<int>> labeled, int count, int take)58 public static void Take(Labeled<ParallelQuery<int>> labeled, int count, int take) 59 { 60 ParallelQuery<int> query = labeled.Item; 61 int seen = 0; 62 foreach (int i in query.Take(take)) 63 { 64 Assert.Equal(seen++, i); 65 } 66 Assert.Equal(Math.Min(count, Math.Max(0, take)), seen); 67 } 68 69 [Theory] 70 [OuterLoop] 71 [MemberData(nameof(TakeData), new int[] { /* Sources.OuterLoopCount */ })] Take_Longrunning(Labeled<ParallelQuery<int>> labeled, int count, int take)72 public static void Take_Longrunning(Labeled<ParallelQuery<int>> labeled, int count, int take) 73 { 74 Take(labeled, count, take); 75 } 76 77 [Theory] 78 [MemberData(nameof(TakeUnorderedData), new[] { 0, 1, 2, 16 })] Take_Unordered_NotPipelined(int count, int take)79 public static void Take_Unordered_NotPipelined(int count, int take) 80 { 81 // For unordered collections, which elements (if any) are taken isn't actually guaranteed, but an effect of the implementation. 82 // If this test starts failing it should be updated, and possibly mentioned in release notes. 83 IntegerRangeSet seen = new IntegerRangeSet(0, Math.Min(count, Math.Max(0, take))); 84 Assert.All(UnorderedSources.Default(count).Take(take).ToList(), x => seen.Add(x)); 85 seen.AssertComplete(); 86 } 87 88 [Theory] 89 [OuterLoop] 90 [MemberData(nameof(TakeUnorderedData), new int[] { /* Sources.OuterLoopCount */ })] Take_Unordered_NotPipelined_Longrunning(int count, int take)91 public static void Take_Unordered_NotPipelined_Longrunning(int count, int take) 92 { 93 Take_Unordered_NotPipelined(count, take); 94 } 95 96 [Theory] 97 [MemberData(nameof(TakeData), new[] { 0, 1, 2, 16 })] Take_NotPipelined(Labeled<ParallelQuery<int>> labeled, int count, int take)98 public static void Take_NotPipelined(Labeled<ParallelQuery<int>> labeled, int count, int take) 99 { 100 ParallelQuery<int> query = labeled.Item; 101 int seen = 0; 102 Assert.All(query.Take(take).ToList(), x => Assert.Equal(seen++, x)); 103 Assert.Equal(Math.Min(count, Math.Max(0, take)), seen); 104 } 105 106 [Theory] 107 [OuterLoop] 108 [MemberData(nameof(TakeData), new int[] { /* Sources.OuterLoopCount */ })] Take_NotPipelined_Longrunning(Labeled<ParallelQuery<int>> labeled, int count, int take)109 public static void Take_NotPipelined_Longrunning(Labeled<ParallelQuery<int>> labeled, int count, int take) 110 { 111 Take_NotPipelined(labeled, count, take); 112 } 113 114 [Fact] Take_ArgumentNullException()115 public static void Take_ArgumentNullException() 116 { 117 AssertExtensions.Throws<ArgumentNullException>("source", () => ((ParallelQuery<bool>)null).Take(0)); 118 } 119 120 // 121 // TakeWhile 122 // TakeWhileData(int[] counts)123 public static IEnumerable<object[]> TakeWhileData(int[] counts) 124 { 125 foreach (object[] results in Sources.Ranges(counts.DefaultIfEmpty(Sources.OuterLoopCount / 4))) 126 { 127 yield return new[] { results[0], results[1], new[] { 0 } }; 128 yield return new[] { results[0], results[1], Enumerable.Range((int)results[1] / 2, ((int)results[1] - 1) / 2 + 1).ToArray() }; 129 yield return new[] { results[0], results[1], new[] { (int)results[1] - 1 } }; 130 } 131 } 132 133 [Theory] 134 [MemberData(nameof(TakeUnorderedData), new[] { 0, 1, 2, 16 })] TakeWhile_Unordered(int count, int take)135 public static void TakeWhile_Unordered(int count, int take) 136 { 137 // For unordered collections, which elements (if any) are taken isn't actually guaranteed, but an effect of the implementation. 138 // If this test starts failing it should be updated, and possibly mentioned in release notes. 139 IntegerRangeSet seen = new IntegerRangeSet(0, Math.Min(count, Math.Max(0, take))); 140 foreach (int i in UnorderedSources.Default(count).TakeWhile(x => x < take)) 141 { 142 seen.Add(i); 143 } 144 seen.AssertComplete(); 145 } 146 147 [Theory] 148 [OuterLoop] 149 [MemberData(nameof(TakeUnorderedData), new int[] { /* Sources.OuterLoopCount */ })] TakeWhile_Unordered_Longrunning(int count, int take)150 public static void TakeWhile_Unordered_Longrunning(int count, int take) 151 { 152 TakeWhile_Unordered(count, take); 153 } 154 155 [Theory] 156 [MemberData(nameof(TakeData), new[] { 0, 1, 2, 16 })] TakeWhile(Labeled<ParallelQuery<int>> labeled, int count, int take)157 public static void TakeWhile(Labeled<ParallelQuery<int>> labeled, int count, int take) 158 { 159 ParallelQuery<int> query = labeled.Item; 160 int seen = 0; 161 foreach (int i in query.TakeWhile(x => x < take)) 162 { 163 Assert.Equal(seen++, i); 164 } 165 Assert.Equal(Math.Min(count, Math.Max(0, take)), seen); 166 } 167 168 [Theory] 169 [OuterLoop] 170 [MemberData(nameof(TakeData), new int[] { /* Sources.OuterLoopCount */ })] TakeWhile_Longrunning(Labeled<ParallelQuery<int>> labeled, int count, int take)171 public static void TakeWhile_Longrunning(Labeled<ParallelQuery<int>> labeled, int count, int take) 172 { 173 TakeWhile(labeled, count, take); 174 } 175 176 [Theory] 177 [MemberData(nameof(TakeUnorderedData), new[] { 0, 1, 2, 16 })] TakeWhile_Unordered_NotPipelined(int count, int take)178 public static void TakeWhile_Unordered_NotPipelined(int count, int take) 179 { 180 // For unordered collections, which elements (if any) are taken isn't actually guaranteed, but an effect of the implementation. 181 // If this test starts failing it should be updated, and possibly mentioned in release notes. 182 IntegerRangeSet seen = new IntegerRangeSet(0, Math.Min(count, Math.Max(0, take))); 183 Assert.All(UnorderedSources.Default(count).TakeWhile(x => x < take).ToList(), x => seen.Add(x)); 184 seen.AssertComplete(); 185 } 186 187 [Theory] 188 [OuterLoop] 189 [MemberData(nameof(TakeUnorderedData), new int[] { /* Sources.OuterLoopCount */ })] TakeWhile_Unordered_NotPipelined_Longrunning(int count, int take)190 public static void TakeWhile_Unordered_NotPipelined_Longrunning(int count, int take) 191 { 192 TakeWhile_Unordered_NotPipelined(count, take); 193 } 194 195 [Theory] 196 [MemberData(nameof(TakeData), new[] { 0, 1, 2, 16 })] TakeWhile_NotPipelined(Labeled<ParallelQuery<int>> labeled, int count, int take)197 public static void TakeWhile_NotPipelined(Labeled<ParallelQuery<int>> labeled, int count, int take) 198 { 199 ParallelQuery<int> query = labeled.Item; 200 int seen = 0; 201 Assert.All(query.TakeWhile(x => x < take).ToList(), x => Assert.Equal(seen++, x)); 202 Assert.Equal(Math.Min(count, Math.Max(0, take)), seen); 203 } 204 205 [Theory] 206 [OuterLoop] 207 [MemberData(nameof(TakeData), new int[] { /* Sources.OuterLoopCount */ })] TakeWhile_NotPipelined_Longrunning(Labeled<ParallelQuery<int>> labeled, int count, int take)208 public static void TakeWhile_NotPipelined_Longrunning(Labeled<ParallelQuery<int>> labeled, int count, int take) 209 { 210 TakeWhile_NotPipelined(labeled, count, take); 211 } 212 213 [Theory] 214 [MemberData(nameof(TakeUnorderedData), new[] { 0, 1, 2, 16 })] TakeWhile_Indexed_Unordered(int count, int take)215 public static void TakeWhile_Indexed_Unordered(int count, int take) 216 { 217 // For unordered collections, which elements (if any) are taken isn't actually guaranteed, but an effect of the implementation. 218 // If this test starts failing it should be updated, and possibly mentioned in release notes. 219 IntegerRangeSet seen = new IntegerRangeSet(0, Math.Min(count, Math.Max(0, take))); 220 foreach (int i in UnorderedSources.Default(count).TakeWhile((x, index) => index < take)) 221 { 222 seen.Add(i); 223 } 224 seen.AssertComplete(); 225 } 226 227 [Theory] 228 [OuterLoop] 229 [MemberData(nameof(TakeUnorderedData), new int[] { /* Sources.OuterLoopCount */ })] TakeWhile_Indexed_Unordered_Longrunning(int count, int take)230 public static void TakeWhile_Indexed_Unordered_Longrunning(int count, int take) 231 { 232 TakeWhile_Indexed_Unordered(count, take); 233 } 234 235 [Theory] 236 [MemberData(nameof(TakeData), new[] { 0, 1, 2, 16 })] TakeWhile_Indexed(Labeled<ParallelQuery<int>> labeled, int count, int take)237 public static void TakeWhile_Indexed(Labeled<ParallelQuery<int>> labeled, int count, int take) 238 { 239 ParallelQuery<int> query = labeled.Item; 240 int seen = 0; 241 foreach (int i in query.TakeWhile((x, index) => index < take)) 242 { 243 Assert.Equal(seen++, i); 244 } 245 Assert.Equal(Math.Min(count, Math.Max(0, take)), seen); 246 } 247 248 [Theory] 249 [OuterLoop] 250 [MemberData(nameof(TakeData), new int[] { /* Sources.OuterLoopCount */ })] TakeWhile_Indexed_Longrunning(Labeled<ParallelQuery<int>> labeled, int count, int take)251 public static void TakeWhile_Indexed_Longrunning(Labeled<ParallelQuery<int>> labeled, int count, int take) 252 { 253 TakeWhile_Indexed(labeled, count, take); 254 } 255 256 [Theory] 257 [MemberData(nameof(TakeUnorderedData), new[] { 0, 1, 2, 16 })] TakeWhile_Indexed_Unordered_NotPipelined(int count, int take)258 public static void TakeWhile_Indexed_Unordered_NotPipelined(int count, int take) 259 { 260 // For unordered collections, which elements (if any) are taken isn't actually guaranteed, but an effect of the implementation. 261 // If this test starts failing it should be updated, and possibly mentioned in release notes. 262 IntegerRangeSet seen = new IntegerRangeSet(0, Math.Min(count, Math.Max(0, take))); 263 Assert.All(UnorderedSources.Default(count).TakeWhile((x, index) => index < take).ToList(), x => seen.Add(x)); 264 seen.AssertComplete(); 265 } 266 267 [Theory] 268 [OuterLoop] 269 [MemberData(nameof(TakeUnorderedData), new int[] { /* Sources.OuterLoopCount */ })] TakeWhile_Indexed_Unordered_NotPipelined_Longrunning(int count, int take)270 public static void TakeWhile_Indexed_Unordered_NotPipelined_Longrunning(int count, int take) 271 { 272 TakeWhile_Indexed_Unordered_NotPipelined(count, take); 273 } 274 275 [Theory] 276 [MemberData(nameof(TakeData), new[] { 0, 1, 2, 16 })] TakeWhile_Indexed_NotPipelined(Labeled<ParallelQuery<int>> labeled, int count, int take)277 public static void TakeWhile_Indexed_NotPipelined(Labeled<ParallelQuery<int>> labeled, int count, int take) 278 { 279 ParallelQuery<int> query = labeled.Item; 280 int seen = 0; 281 Assert.All(query.TakeWhile((x, index) => index < take).ToList(), x => Assert.Equal(seen++, x)); 282 Assert.Equal(Math.Min(count, Math.Max(0, take)), seen); 283 } 284 285 [Theory] 286 [OuterLoop] 287 [MemberData(nameof(TakeData), new int[] { /* Sources.OuterLoopCount */ })] TakeWhile_Indexed_NotPipelined_Longrunning(Labeled<ParallelQuery<int>> labeled, int count, int take)288 public static void TakeWhile_Indexed_NotPipelined_Longrunning(Labeled<ParallelQuery<int>> labeled, int count, int take) 289 { 290 TakeWhile_Indexed_NotPipelined(labeled, count, take); 291 } 292 293 [Theory] 294 [MemberData(nameof(TakeUnorderedData), new[] { 0, 1, 2, 16 })] TakeWhile_AllFalse(int count, int take)295 public static void TakeWhile_AllFalse(int count, int take) 296 { 297 Assert.Empty(UnorderedSources.Default(count).TakeWhile(x => false)); 298 } 299 300 [Theory] 301 [OuterLoop] 302 [MemberData(nameof(TakeUnorderedData), new int[] { /* Sources.OuterLoopCount */ })] TakeWhile_AllFalse_Longrunning(int count, int take)303 public static void TakeWhile_AllFalse_Longrunning(int count, int take) 304 { 305 TakeWhile_AllFalse(count, take); 306 } 307 308 [Theory] 309 [MemberData(nameof(TakeData), new[] { 0, 1, 2, 16 })] TakeWhile_AllTrue(Labeled<ParallelQuery<int>> labeled, int count, int take)310 public static void TakeWhile_AllTrue(Labeled<ParallelQuery<int>> labeled, int count, int take) 311 { 312 ParallelQuery<int> query = labeled.Item; 313 int seen = 0; 314 Assert.All(query.TakeWhile(x => true), x => Assert.Equal(seen++, x)); 315 Assert.Equal(count, seen); 316 } 317 318 [Theory] 319 [OuterLoop] 320 [MemberData(nameof(TakeData), new int[] { /* Sources.OuterLoopCount */ })] TakeWhile_AllTrue_Longrunning(Labeled<ParallelQuery<int>> labeled, int count, int take)321 public static void TakeWhile_AllTrue_Longrunning(Labeled<ParallelQuery<int>> labeled, int count, int take) 322 { 323 TakeWhile_AllTrue(labeled, count, take); 324 } 325 326 [Theory] 327 [MemberData(nameof(TakeWhileData), new[] { 2, 16 })] TakeWhile_SomeTrue(Labeled<ParallelQuery<int>> labeled, int count, int[] take)328 public static void TakeWhile_SomeTrue(Labeled<ParallelQuery<int>> labeled, int count, int[] take) 329 { 330 ParallelQuery<int> query = labeled.Item; 331 int seen = 0; 332 Assert.All(query.TakeWhile(x => take.Contains(x)), x => Assert.Equal(seen++, x)); 333 Assert.Equal(take.Min() > 0 ? 0 : take.Max() + 1, seen); 334 } 335 336 [Theory] 337 [OuterLoop] 338 [MemberData(nameof(TakeWhileData), new int[] { /* Sources.OuterLoopCount */ })] TakeWhile_SomeTrue_Longrunning(Labeled<ParallelQuery<int>> labeled, int count, int[] take)339 public static void TakeWhile_SomeTrue_Longrunning(Labeled<ParallelQuery<int>> labeled, int count, int[] take) 340 { 341 TakeWhile_SomeTrue(labeled, count, take); 342 } 343 344 [Theory] 345 [MemberData(nameof(TakeWhileData), new[] { 2, 16 })] TakeWhile_SomeFalse(Labeled<ParallelQuery<int>> labeled, int count, int[] take)346 public static void TakeWhile_SomeFalse(Labeled<ParallelQuery<int>> labeled, int count, int[] take) 347 { 348 ParallelQuery<int> query = labeled.Item; 349 int seen = 0; 350 Assert.All(query.TakeWhile(x => !take.Contains(x)), x => Assert.Equal(seen++, x)); 351 Assert.Equal(take.Min(), seen); 352 } 353 354 [Theory] 355 [OuterLoop] 356 [MemberData(nameof(TakeWhileData), new int[] { /* Sources.OuterLoopCount */ })] TakeWhile_SomeFalse_Longrunning(Labeled<ParallelQuery<int>> labeled, int count, int[] take)357 public static void TakeWhile_SomeFalse_Longrunning(Labeled<ParallelQuery<int>> labeled, int count, int[] take) 358 { 359 TakeWhile_SomeFalse(labeled, count, take); 360 } 361 362 [Fact] TakeWhile_ArgumentNullException()363 public static void TakeWhile_ArgumentNullException() 364 { 365 AssertExtensions.Throws<ArgumentNullException>("source", () => ((ParallelQuery<bool>)null).TakeWhile(x => true)); 366 AssertExtensions.Throws<ArgumentNullException>("predicate", () => ParallelEnumerable.Empty<bool>().TakeWhile((Func<bool, bool>)null)); 367 AssertExtensions.Throws<ArgumentNullException>("predicate", () => ParallelEnumerable.Empty<bool>().TakeWhile((Func<bool, int, bool>)null)); 368 } 369 } 370 } 371