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