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 ElementAtElementAtOrDefaultTests 11 { 12 private static readonly Func<int, IEnumerable<int>> Positions = x => new[] { 0, x / 2, Math.Max(0, x - 1) }.Distinct(); 13 private static readonly Func<int, IEnumerable<int>> InvalidPositions = x => new[] { -1, x, x * 2 }.Distinct(); 14 ElementAtUnorderedData(int[] counts)15 public static IEnumerable<object[]> ElementAtUnorderedData(int[] counts) 16 { 17 // A deliberate decision was made here to test with all types, because this reflects partitioning/indexing 18 foreach (object[] results in UnorderedSources.Ranges(counts.DefaultIfEmpty(Sources.OuterLoopCount), Positions)) yield return results; 19 } 20 ElementAtData(int[] counts)21 public static IEnumerable<object[]> ElementAtData(int[] counts) 22 { 23 foreach (object[] results in Sources.Ranges(counts.DefaultIfEmpty(Sources.OuterLoopCount), Positions)) yield return results; 24 } 25 ElementAtOutOfRangeData(int[] counts)26 public static IEnumerable<object[]> ElementAtOutOfRangeData(int[] counts) 27 { 28 foreach (object[] results in UnorderedSources.Ranges(counts.DefaultIfEmpty(Sources.OuterLoopCount), InvalidPositions)) yield return results; 29 foreach (object[] results in Sources.Ranges(counts.DefaultIfEmpty(Sources.OuterLoopCount), InvalidPositions)) yield return results; 30 } 31 32 // 33 // ElementAt and ElementAtOrDefault 34 // 35 [Theory] 36 [MemberData(nameof(ElementAtUnorderedData), new[] { 1, 2, 16 })] 37 [MemberData(nameof(ElementAtData), new[] { 1, 2, 16 })] ElementAt(Labeled<ParallelQuery<int>> labeled, int count, int position)38 public static void ElementAt(Labeled<ParallelQuery<int>> labeled, int count, int position) 39 { 40 // For unordered collections, which element is chosen isn't actually guaranteed, but an effect of the implementation. 41 // If this test starts failing it should be split, and possibly mentioned in release notes. 42 ParallelQuery<int> query = labeled.Item; 43 Assert.Equal(position, query.ElementAt(position)); 44 } 45 46 [Theory] 47 [OuterLoop] 48 [MemberData(nameof(ElementAtUnorderedData), new int[] { /* Sources.OuterLoopCount */ })] 49 [MemberData(nameof(ElementAtData), new int[] { /* Sources.OuterLoopCount */ })] ElementAt_Longrunning(Labeled<ParallelQuery<int>> labeled, int count, int position)50 public static void ElementAt_Longrunning(Labeled<ParallelQuery<int>> labeled, int count, int position) 51 { 52 ElementAt(labeled, count, position); 53 } 54 55 [Theory] 56 [MemberData(nameof(ElementAtOutOfRangeData), new[] { 0, 1, 2, 16 })] ElementAt_OutOfRange(Labeled<ParallelQuery<int>> labeled, int count, int position)57 public static void ElementAt_OutOfRange(Labeled<ParallelQuery<int>> labeled, int count, int position) 58 { 59 ParallelQuery<int> query = labeled.Item; 60 Assert.Throws<ArgumentOutOfRangeException>(() => query.ElementAt(position)); 61 } 62 63 [Theory] 64 [OuterLoop] 65 [MemberData(nameof(ElementAtOutOfRangeData), new int[] { /* Sources.OuterLoopCount */ })] ElementAt_OutOfRange_Longrunning(Labeled<ParallelQuery<int>> labeled, int count, int position)66 public static void ElementAt_OutOfRange_Longrunning(Labeled<ParallelQuery<int>> labeled, int count, int position) 67 { 68 ElementAt_OutOfRange(labeled, count, position); 69 } 70 71 [Theory] 72 [MemberData(nameof(ElementAtUnorderedData), new[] { 0, 1, 2, 16 })] 73 [MemberData(nameof(ElementAtData), new[] { 0, 1, 2, 16 })] ElementAtOrDefault(Labeled<ParallelQuery<int>> labeled, int count, int position)74 public static void ElementAtOrDefault(Labeled<ParallelQuery<int>> labeled, int count, int position) 75 { 76 // For unordered collections, which element is chosen isn't actually guaranteed, but an effect of the implementation. 77 // If this test starts failing it should be split, and possibly mentioned in release notes. 78 ParallelQuery<int> query = labeled.Item; 79 Assert.Equal(position, query.ElementAtOrDefault(position)); 80 } 81 82 [Theory] 83 [OuterLoop] 84 [MemberData(nameof(ElementAtUnorderedData), new int[] { /* Sources.OuterLoopCount */ })] 85 [MemberData(nameof(ElementAtData), new int[] { /* Sources.OuterLoopCount */ })] ElementAtOrDefault_Longrunning(Labeled<ParallelQuery<int>> labeled, int count, int position)86 public static void ElementAtOrDefault_Longrunning(Labeled<ParallelQuery<int>> labeled, int count, int position) 87 { 88 ElementAtOrDefault(labeled, count, position); 89 } 90 91 [Theory] 92 [MemberData(nameof(ElementAtOutOfRangeData), new[] { 0, 1, 2, 16 })] ElementAtOrDefault_OutOfRange(Labeled<ParallelQuery<int>> labeled, int count, int position)93 public static void ElementAtOrDefault_OutOfRange(Labeled<ParallelQuery<int>> labeled, int count, int position) 94 { 95 ParallelQuery<int> query = labeled.Item; 96 Assert.Equal(default(int), query.ElementAtOrDefault(position)); 97 } 98 99 [Theory] 100 [OuterLoop] 101 [MemberData(nameof(ElementAtOutOfRangeData), new int[] { /* Sources.OuterLoopCount */ })] ElementAtOrDefault_OutOfRange_Longrunning(Labeled<ParallelQuery<int>> labeled, int count, int position)102 public static void ElementAtOrDefault_OutOfRange_Longrunning(Labeled<ParallelQuery<int>> labeled, int count, int position) 103 { 104 ElementAtOrDefault_OutOfRange(labeled, count, position); 105 } 106 107 [Fact] ElementAt_OperationCanceledException_PreCanceled()108 public static void ElementAt_OperationCanceledException_PreCanceled() 109 { 110 AssertThrows.AlreadyCanceled(source => source.ElementAt(0)); 111 AssertThrows.AlreadyCanceled(source => source.ElementAtOrDefault(0)); 112 } 113 114 [Fact] ElementAt_ArgumentNullException()115 public static void ElementAt_ArgumentNullException() 116 { 117 AssertExtensions.Throws<ArgumentNullException>("source", () => ((ParallelQuery<object>)null).ElementAt(0)); 118 AssertExtensions.Throws<ArgumentNullException>("source", () => ((ParallelQuery<object>)null).ElementAtOrDefault(0)); 119 } 120 } 121 } 122