-
Notifications
You must be signed in to change notification settings - Fork 4.7k
/
FirstFirstOrDefaultTests.cs
183 lines (162 loc) · 8.25 KB
/
FirstFirstOrDefaultTests.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Generic;
using Xunit;
namespace System.Linq.Parallel.Tests
{
public static class FirstFirstOrDefaultTests
{
private static readonly Func<int, IEnumerable<int>> Positions = x => new[] { 0, x / 2, Math.Max(0, x - 1) }.Distinct();
public static IEnumerable<object[]> FirstUnorderedData(int[] counts)
{
foreach (int count in counts.DefaultIfEmpty(Sources.OuterLoopCount))
{
foreach (int position in Positions(count))
{
yield return new object[] { Labeled.Label("UnorderedDefault", UnorderedSources.Default(count)), count, position };
}
}
}
public static IEnumerable<object[]> FirstData(int[] counts)
{
foreach (object[] results in Sources.Ranges(counts.DefaultIfEmpty(Sources.OuterLoopCount), Positions)) yield return results;
}
//
// First and FirstOrDefault
//
[Theory]
[MemberData(nameof(FirstUnorderedData), new[] { 1, 2, 16 })]
[MemberData(nameof(FirstData), new[] { 1, 2, 16 })]
public static void First(Labeled<ParallelQuery<int>> labeled, int count, int position)
{
// For unordered collections, which element is chosen isn't actually guaranteed, but an effect of the implementation.
// If this test starts failing it should be split, and possibly mentioned in release notes.
_ = count;
ParallelQuery<int> query = labeled.Item;
Assert.Equal(0, query.First());
Assert.Equal(position, query.First(x => x >= position));
}
[Theory]
[OuterLoop]
[MemberData(nameof(FirstUnorderedData), new int[] { /* Sources.OuterLoopCount */ })]
[MemberData(nameof(FirstData), new int[] { /* Sources.OuterLoopCount */ })]
public static void First_Longrunning(Labeled<ParallelQuery<int>> labeled, int count, int position)
{
First(labeled, count, position);
}
[Theory]
[MemberData(nameof(FirstUnorderedData), new[] { 1, 2, 16 })]
[MemberData(nameof(FirstData), new[] { 1, 2, 16 })]
public static void FirstOrDefault(Labeled<ParallelQuery<int>> labeled, int count, int position)
{
// For unordered collections, which element is chosen isn't actually guaranteed, but an effect of the implementation.
// If this test starts failing it should be split, and possibly mentioned in release notes.
_ = count;
ParallelQuery<int> query = labeled.Item;
Assert.Equal(0, query.FirstOrDefault());
Assert.Equal(position, query.FirstOrDefault(x => x >= position));
}
[Theory]
[OuterLoop]
[MemberData(nameof(FirstUnorderedData), new int[] { /* Sources.OuterLoopCount */ })]
[MemberData(nameof(FirstData), new int[] { /* Sources.OuterLoopCount */ })]
public static void FirstOrDefault_Longrunning(Labeled<ParallelQuery<int>> labeled, int count, int position)
{
FirstOrDefault(labeled, count, position);
}
[Theory]
[MemberData(nameof(FirstUnorderedData), new[] { 0 })]
[MemberData(nameof(FirstData), new[] { 0 })]
public static void First_Empty(Labeled<ParallelQuery<int>> labeled, int count, int position)
{
_ = count;
_ = position;
ParallelQuery<int> query = labeled.Item;
Assert.Throws<InvalidOperationException>(() => query.First());
}
[Theory]
[MemberData(nameof(FirstUnorderedData), new[] { 0 })]
[MemberData(nameof(FirstData), new[] { 0 })]
public static void FirstOrDefault_Empty(Labeled<ParallelQuery<int>> labeled, int count, int position)
{
_ = count;
_ = position;
ParallelQuery<int> query = labeled.Item;
Assert.Equal(default(int), query.FirstOrDefault());
}
[Theory]
[MemberData(nameof(FirstUnorderedData), new[] { 1, 2, 16 })]
[MemberData(nameof(FirstData), new[] { 0, 1, 2, 16 })]
public static void First_NoMatch(Labeled<ParallelQuery<int>> labeled, int count, int position)
{
_ = position;
ParallelQuery<int> query = labeled.Item;
IntegerRangeSet seen = new IntegerRangeSet(0, count);
Assert.Throws<InvalidOperationException>(() => query.First(x => !seen.Add(x)));
seen.AssertComplete();
}
[Theory]
[OuterLoop]
[MemberData(nameof(FirstUnorderedData), new int[] { /* Sources.OuterLoopCount */ })]
[MemberData(nameof(FirstData), new int[] { /* Sources.OuterLoopCount */ })]
public static void First_NoMatch_Longrunning(Labeled<ParallelQuery<int>> labeled, int count, int position)
{
First_NoMatch(labeled, count, position);
}
[Theory]
[MemberData(nameof(FirstUnorderedData), new[] { 1, 2, 16 })]
[MemberData(nameof(FirstData), new[] { 0, 1, 2, 16 })]
public static void FirstOrDefault_NoMatch(Labeled<ParallelQuery<int>> labeled, int count, int position)
{
_ = position;
ParallelQuery<int> query = labeled.Item;
IntegerRangeSet seen = new IntegerRangeSet(0, count);
Assert.Equal(default(int), query.FirstOrDefault(x => !seen.Add(x)));
seen.AssertComplete();
}
[Theory]
[OuterLoop]
[MemberData(nameof(FirstUnorderedData), new int[] { /* Sources.OuterLoopCount */ })]
[MemberData(nameof(FirstData), new int[] { /* Sources.OuterLoopCount */ })]
public static void FirstOrDefault_NoMatch_Longrunning(Labeled<ParallelQuery<int>> labeled, int count, int position)
{
FirstOrDefault_NoMatch(labeled, count, position);
}
[Fact]
public static void First_OperationCanceledException()
{
AssertThrows.EventuallyCanceled((source, canceler) => source.First(x => { canceler(); return false; }));
AssertThrows.EventuallyCanceled((source, canceler) => source.FirstOrDefault(x => { canceler(); return false; }));
}
[Fact]
public static void First_AggregateException_Wraps_OperationCanceledException()
{
AssertThrows.OtherTokenCanceled((source, canceler) => source.First(x => { canceler(); return false; }));
AssertThrows.OtherTokenCanceled((source, canceler) => source.FirstOrDefault(x => { canceler(); return false; }));
AssertThrows.SameTokenNotCanceled((source, canceler) => source.First(x => { canceler(); return false; }));
AssertThrows.SameTokenNotCanceled((source, canceler) => source.FirstOrDefault(x => { canceler(); return false; }));
}
[Fact]
public static void First_OperationCanceledException_PreCanceled()
{
AssertThrows.AlreadyCanceled(source => source.First());
AssertThrows.AlreadyCanceled(source => source.First(x => true));
AssertThrows.AlreadyCanceled(source => source.FirstOrDefault());
AssertThrows.AlreadyCanceled(source => source.FirstOrDefault(x => true));
}
[Fact]
public static void First_AggregateException()
{
AssertThrows.Wrapped<DeliberateTestException>(() => UnorderedSources.Default(1).First(x => { throw new DeliberateTestException(); }));
AssertThrows.Wrapped<DeliberateTestException>(() => UnorderedSources.Default(1).FirstOrDefault(x => { throw new DeliberateTestException(); }));
}
[Fact]
public static void First_ArgumentNullException()
{
AssertExtensions.Throws<ArgumentNullException>("source", () => ((ParallelQuery<bool>)null).First());
AssertExtensions.Throws<ArgumentNullException>("source", () => ((ParallelQuery<bool>)null).FirstOrDefault());
AssertExtensions.Throws<ArgumentNullException>("predicate", () => ParallelEnumerable.Empty<int>().First(null));
AssertExtensions.Throws<ArgumentNullException>("predicate", () => ParallelEnumerable.Empty<int>().FirstOrDefault(null));
}
}
}