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 AverageTests
11     {
12         //
13         // Average
14         //
15 
16         // Get a set of ranges from 0 to each count, with an extra parameter containing the expected average.
AverageData(int[] counts)17         public static IEnumerable<object[]> AverageData(int[] counts)
18         {
19             foreach (int count in counts)
20             {
21                 yield return new object[] { count, (count - 1) / 2.0 };
22             }
23         }
24 
25         [Theory]
26         [MemberData(nameof(AverageData), new[] { 1, 2, 16 })]
Average_Int(int count, double average)27         public static void Average_Int(int count, double average)
28         {
29             Assert.Equal(average, UnorderedSources.Default(count).Average());
30             Assert.Equal((double?)average, UnorderedSources.Default(count).Select(x => (int?)x).Average());
31             Assert.Equal(-average, UnorderedSources.Default(count).Average(x => -x));
32             Assert.Equal(-(double?)average, UnorderedSources.Default(count).Average(x => -(int?)x));
33         }
34 
35         [Fact]
36         [OuterLoop]
Average_Int_Longrunning()37         public static void Average_Int_Longrunning()
38         {
39             Average_Int(Sources.OuterLoopCount, (Sources.OuterLoopCount - 1) / 2.0);
40         }
41 
42         [Theory]
43         [MemberData(nameof(AverageData), new[] { 1, 2, 16 })]
Average_Int_SomeNull(int count, double average)44         public static void Average_Int_SomeNull(int count, double average)
45         {
46             Assert.Equal(Math.Truncate(average), UnorderedSources.Default(count).Select(x => (x % 2 == 0) ? (int?)x : null).Average());
47             Assert.Equal(Math.Truncate(-average), UnorderedSources.Default(count).Average(x => (x % 2 == 0) ? -(int?)x : null));
48         }
49 
50         [Theory]
51         [MemberData(nameof(AverageData), new[] { 1, 2, 16 })]
Average_Int_AllNull(int count, double average)52         public static void Average_Int_AllNull(int count, double average)
53         {
54             Assert.Null(UnorderedSources.Default(count).Select(x => (int?)null).Average());
55             Assert.Null(UnorderedSources.Default(count).Average(x => (int?)null));
56         }
57 
58         [Theory]
59         [MemberData(nameof(AverageData), new[] { 1, 2, 16 })]
Average_Long(int count, double average)60         public static void Average_Long(int count, double average)
61         {
62             Assert.Equal(average, UnorderedSources.Default(count).Select(x => (long)x).Average());
63             Assert.Equal((double?)average, UnorderedSources.Default(count).Select(x => (long?)x).Average());
64             Assert.Equal(-average, UnorderedSources.Default(count).Average(x => -(long)x));
65             Assert.Equal(-(double?)average, UnorderedSources.Default(count).Average(x => -(long?)x));
66         }
67 
68         [Fact]
69         [OuterLoop]
Average_Long_Longrunning()70         public static void Average_Long_Longrunning()
71         {
72             Average_Long(Sources.OuterLoopCount, (Sources.OuterLoopCount - 1) / 2.0);
73         }
74 
75         [Fact]
Average_Long_Overflow()76         public static void Average_Long_Overflow()
77         {
78             AssertThrows.Wrapped<OverflowException>(() => UnorderedSources.Default(2).Select(x => x == 0 ? 1 : long.MaxValue).Average());
79             AssertThrows.Wrapped<OverflowException>(() => UnorderedSources.Default(2).Select(x => x == 0 ? (long?)1 : long.MaxValue).Average());
80             AssertThrows.Wrapped<OverflowException>(() => UnorderedSources.Default(2).Average(x => x == 0 ? -1 : long.MinValue));
81             AssertThrows.Wrapped<OverflowException>(() => UnorderedSources.Default(2).Average(x => x == 0 ? (long?)-1 : long.MinValue));
82         }
83 
84         [Theory]
85         [MemberData(nameof(AverageData), new[] { 1, 2, 16 })]
Average_Long_SomeNull(int count, double average)86         public static void Average_Long_SomeNull(int count, double average)
87         {
88             Assert.Equal(Math.Truncate(average), UnorderedSources.Default(count).Select(x => (x % 2 == 0) ? (long?)x : null).Average());
89             Assert.Equal(Math.Truncate(-average), UnorderedSources.Default(count).Average(x => (x % 2 == 0) ? -(long?)x : null));
90         }
91 
92         [Theory]
93         [InlineData(1)]
94         [InlineData(2)]
95         [InlineData(16)]
Average_Long_AllNull(int count)96         public static void Average_Long_AllNull(int count)
97         {
98             Assert.Null(UnorderedSources.Default(count).Select(x => (long?)null).Average());
99             Assert.Null(UnorderedSources.Default(count).Average(x => (long?)null));
100         }
101 
102         [Theory]
103         [MemberData(nameof(AverageData), new[] { 1, 2, 16 })]
Average_Float(int count, float average)104         public static void Average_Float(int count, float average)
105         {
106             Assert.Equal(average, UnorderedSources.Default(count).Select(x => (float)x).Average());
107             Assert.Equal((float?)average, UnorderedSources.Default(count).Select(x => (float?)x).Average());
108             Assert.Equal(-average, UnorderedSources.Default(count).Average(x => -(float)x));
109             Assert.Equal(-(float?)average, UnorderedSources.Default(count).Average(x => -(float?)x));
110         }
111 
112         [Fact]
113         [OuterLoop]
Average_Float_Longrunning()114         public static void Average_Float_Longrunning()
115         {
116             Average_Float(Sources.OuterLoopCount, (Sources.OuterLoopCount - 1) / 2.0F);
117         }
118 
119         [Theory]
120         [MemberData(nameof(AverageData), new[] { 1, 2, 16 })]
Average_Float_SomeNull(int count, float average)121         public static void Average_Float_SomeNull(int count, float average)
122         {
123             Assert.Equal((float?)Math.Truncate(average), UnorderedSources.Default(count).Select(x => (x % 2 == 0) ? (float?)x : null).Average());
124             Assert.Equal((float?)Math.Truncate(-average), UnorderedSources.Default(count).Average(x => (x % 2 == 0) ? -(float?)x : null));
125         }
126 
127         [Theory]
128         [InlineData(1)]
129         [InlineData(2)]
130         [InlineData(16)]
Average_Float_AllNull(int count)131         public static void Average_Float_AllNull(int count)
132         {
133             Assert.Null(UnorderedSources.Default(count).Select(x => (float?)null).Average());
134             Assert.Null(UnorderedSources.Default(count).Average(x => (float?)null));
135         }
136 
137         [Theory]
138         [MemberData(nameof(AverageData), new[] { 1, 2, 16 })]
Average_Double(int count, double average)139         public static void Average_Double(int count, double average)
140         {
141             Assert.Equal(average, UnorderedSources.Default(count).Select(x => (double)x).Average());
142             Assert.Equal((double?)average, UnorderedSources.Default(count).Select(x => (double?)x).Average());
143             Assert.Equal(-average, UnorderedSources.Default(count).Average(x => -(double)x));
144             Assert.Equal(-(double?)average, UnorderedSources.Default(count).Average(x => -(double?)x));
145         }
146 
147         [Fact]
148         [OuterLoop]
Average_Double_Longrunning()149         public static void Average_Double_Longrunning()
150         {
151             Average_Double(Sources.OuterLoopCount, (Sources.OuterLoopCount - 1) / 2.0);
152         }
153 
154         [Theory]
155         [MemberData(nameof(AverageData), new[] { 1, 2, 16 })]
Average_Double_SomeNull(int count, double average)156         public static void Average_Double_SomeNull(int count, double average)
157         {
158             Assert.Equal(Math.Truncate(average), UnorderedSources.Default(count).Select(x => (x % 2 == 0) ? (double?)x : null).Average());
159             Assert.Equal(Math.Truncate(-average), UnorderedSources.Default(count).Average(x => (x % 2 == 0) ? -(double?)x : null));
160         }
161 
162         [Theory]
163         [InlineData(1)]
164         [InlineData(2)]
165         [InlineData(16)]
Average_Double_AllNull(int count)166         public static void Average_Double_AllNull(int count)
167         {
168             Assert.Null(UnorderedSources.Default(count).Select(x => (double?)null).Average());
169             Assert.Null(UnorderedSources.Default(count).Average(x => (double?)null));
170         }
171 
172         [Theory]
173         [MemberData(nameof(AverageData), new[] { 1, 2, 16 })]
Average_Decimal(int count, decimal average)174         public static void Average_Decimal(int count, decimal average)
175         {
176             Assert.Equal(average, UnorderedSources.Default(count).Select(x => (decimal)x).Average());
177             Assert.Equal((decimal?)average, UnorderedSources.Default(count).Select(x => (decimal?)x).Average());
178             Assert.Equal(-average, UnorderedSources.Default(count).Average(x => -(decimal)x));
179             Assert.Equal(-(decimal?)average, UnorderedSources.Default(count).Average(x => -(decimal?)x));
180         }
181 
182         [Fact]
183         [OuterLoop]
Average_Decimal_Longrunning()184         public static void Average_Decimal_Longrunning()
185         {
186             Average_Decimal(Sources.OuterLoopCount, (Sources.OuterLoopCount - 1) / 2.0M);
187         }
188 
189         [Theory]
190         [MemberData(nameof(AverageData), new[] { 1, 2, 16 })]
Average_Decimal_SomeNull(int count, decimal average)191         public static void Average_Decimal_SomeNull(int count, decimal average)
192         {
193             Assert.Equal(Math.Truncate(average), UnorderedSources.Default(count).Select(x => (x % 2 == 0) ? (decimal?)x : null).Average());
194             Assert.Equal(Math.Truncate(-average), UnorderedSources.Default(count).Average(x => (x % 2 == 0) ? -(decimal?)x : null));
195         }
196 
197         [Theory]
198         [InlineData(1)]
199         [InlineData(2)]
200         [InlineData(16)]
Average_Decimal_AllNull(int count)201         public static void Average_Decimal_AllNull(int count)
202         {
203             Assert.Null(UnorderedSources.Default(count).Select(x => (decimal?)null).Average());
204             Assert.Null(UnorderedSources.Default(count).Average(x => (decimal?)null));
205         }
206 
207         [Fact]
Average_InvalidOperationException()208         public static void Average_InvalidOperationException()
209         {
210             Assert.Throws<InvalidOperationException>(() => ParallelEnumerable.Empty<int>().Average());
211             Assert.Throws<InvalidOperationException>(() => ParallelEnumerable.Empty<int>().Average(x => x));
212             Assert.Throws<InvalidOperationException>(() => ParallelEnumerable.Empty<long>().Average());
213             Assert.Throws<InvalidOperationException>(() => ParallelEnumerable.Empty<long>().Average(x => x));
214             Assert.Throws<InvalidOperationException>(() => ParallelEnumerable.Empty<float>().Average());
215             Assert.Throws<InvalidOperationException>(() => ParallelEnumerable.Empty<float>().Average(x => x));
216             Assert.Throws<InvalidOperationException>(() => ParallelEnumerable.Empty<double>().Average());
217             Assert.Throws<InvalidOperationException>(() => ParallelEnumerable.Empty<double>().Average(x => x));
218             Assert.Throws<InvalidOperationException>(() => ParallelEnumerable.Empty<decimal>().Average());
219             Assert.Throws<InvalidOperationException>(() => ParallelEnumerable.Empty<decimal>().Average(x => x));
220             // Nullables return null when empty
221             Assert.Null(ParallelEnumerable.Empty<int?>().Average());
222             Assert.Null(ParallelEnumerable.Empty<int?>().Average(x => x));
223             Assert.Null(ParallelEnumerable.Empty<long?>().Average());
224             Assert.Null(ParallelEnumerable.Empty<long?>().Average(x => x));
225             Assert.Null(ParallelEnumerable.Empty<float?>().Average());
226             Assert.Null(ParallelEnumerable.Empty<float?>().Average(x => x));
227             Assert.Null(ParallelEnumerable.Empty<double?>().Average());
228             Assert.Null(ParallelEnumerable.Empty<double?>().Average(x => x));
229             Assert.Null(ParallelEnumerable.Empty<decimal?>().Average());
230             Assert.Null(ParallelEnumerable.Empty<decimal?>().Average(x => x));
231         }
232 
233         [Fact]
Average_OperationCanceledException()234         public static void Average_OperationCanceledException()
235         {
236             AssertThrows.EventuallyCanceled((source, canceler) => source.Average(x => { canceler(); return x; }));
237             AssertThrows.EventuallyCanceled((source, canceler) => source.Average(x => { canceler(); return (int?)x; }));
238 
239             AssertThrows.EventuallyCanceled((source, canceler) => source.Average(x => { canceler(); return (long)x; }));
240             AssertThrows.EventuallyCanceled((source, canceler) => source.Average(x => { canceler(); return (long?)x; }));
241 
242             AssertThrows.EventuallyCanceled((source, canceler) => source.Average(x => { canceler(); return (float)x; }));
243             AssertThrows.EventuallyCanceled((source, canceler) => source.Average(x => { canceler(); return (float?)x; }));
244 
245             AssertThrows.EventuallyCanceled((source, canceler) => source.Average(x => { canceler(); return (double)x; }));
246             AssertThrows.EventuallyCanceled((source, canceler) => source.Average(x => { canceler(); return (double?)x; }));
247 
248             AssertThrows.EventuallyCanceled((source, canceler) => source.Average(x => { canceler(); return (decimal)x; }));
249             AssertThrows.EventuallyCanceled((source, canceler) => source.Average(x => { canceler(); return (decimal?)x; }));
250         }
251 
252         [Fact]
Average_AggregateException_Wraps_OperationCanceledException()253         public static void Average_AggregateException_Wraps_OperationCanceledException()
254         {
255             AssertThrows.OtherTokenCanceled((source, canceler) => source.Average(x => { canceler(); return x; }));
256             AssertThrows.OtherTokenCanceled((source, canceler) => source.Average(x => { canceler(); return (int?)x; }));
257 
258             AssertThrows.OtherTokenCanceled((source, canceler) => source.Average(x => { canceler(); return (long)x; }));
259             AssertThrows.OtherTokenCanceled((source, canceler) => source.Average(x => { canceler(); return (long?)x; }));
260 
261             AssertThrows.OtherTokenCanceled((source, canceler) => source.Average(x => { canceler(); return (float)x; }));
262             AssertThrows.OtherTokenCanceled((source, canceler) => source.Average(x => { canceler(); return (float?)x; }));
263 
264             AssertThrows.OtherTokenCanceled((source, canceler) => source.Average(x => { canceler(); return (double)x; }));
265             AssertThrows.OtherTokenCanceled((source, canceler) => source.Average(x => { canceler(); return (double?)x; }));
266 
267             AssertThrows.OtherTokenCanceled((source, canceler) => source.Average(x => { canceler(); return (decimal)x; }));
268             AssertThrows.OtherTokenCanceled((source, canceler) => source.Average(x => { canceler(); return (decimal?)x; }));
269 
270             AssertThrows.SameTokenNotCanceled((source, canceler) => source.Average(x => { canceler(); return x; }));
271             AssertThrows.SameTokenNotCanceled((source, canceler) => source.Average(x => { canceler(); return (int?)x; }));
272 
273             AssertThrows.SameTokenNotCanceled((source, canceler) => source.Average(x => { canceler(); return (long)x; }));
274             AssertThrows.SameTokenNotCanceled((source, canceler) => source.Average(x => { canceler(); return (long?)x; }));
275 
276             AssertThrows.SameTokenNotCanceled((source, canceler) => source.Average(x => { canceler(); return (float)x; }));
277             AssertThrows.SameTokenNotCanceled((source, canceler) => source.Average(x => { canceler(); return (float?)x; }));
278 
279             AssertThrows.SameTokenNotCanceled((source, canceler) => source.Average(x => { canceler(); return (double)x; }));
280             AssertThrows.SameTokenNotCanceled((source, canceler) => source.Average(x => { canceler(); return (double?)x; }));
281 
282             AssertThrows.SameTokenNotCanceled((source, canceler) => source.Average(x => { canceler(); return (decimal)x; }));
283             AssertThrows.SameTokenNotCanceled((source, canceler) => source.Average(x => { canceler(); return (decimal?)x; }));
284         }
285 
286         [Fact]
Average_OperationCanceledException_PreCanceled()287         public static void Average_OperationCanceledException_PreCanceled()
288         {
289             AssertThrows.AlreadyCanceled(source => source.Average(x => x));
290             AssertThrows.AlreadyCanceled(source => source.Average(x => (int?)x));
291 
292             AssertThrows.AlreadyCanceled(source => source.Average(x => (long)x));
293             AssertThrows.AlreadyCanceled(source => source.Average(x => (long?)x));
294 
295             AssertThrows.AlreadyCanceled(source => source.Average(x => (float)x));
296             AssertThrows.AlreadyCanceled(source => source.Average(x => (float?)x));
297 
298             AssertThrows.AlreadyCanceled(source => source.Average(x => (double)x));
299             AssertThrows.AlreadyCanceled(source => source.Average(x => (double?)x));
300 
301             AssertThrows.AlreadyCanceled(source => source.Average(x => (decimal)x));
302             AssertThrows.AlreadyCanceled(source => source.Average(x => (decimal?)x));
303         }
304 
305         [Fact]
Average_AggregateException()306         public static void Average_AggregateException()
307         {
308             AssertThrows.Wrapped<DeliberateTestException>(() => UnorderedSources.Default(1).Average((Func<int, int>)(x => { throw new DeliberateTestException(); })));
309             AssertThrows.Wrapped<DeliberateTestException>(() => UnorderedSources.Default(1).Average((Func<int, int?>)(x => { throw new DeliberateTestException(); })));
310 
311             AssertThrows.Wrapped<DeliberateTestException>(() => UnorderedSources.Default(1).Average((Func<int, long>)(x => { throw new DeliberateTestException(); })));
312             AssertThrows.Wrapped<DeliberateTestException>(() => UnorderedSources.Default(1).Average((Func<int, long?>)(x => { throw new DeliberateTestException(); })));
313 
314             AssertThrows.Wrapped<DeliberateTestException>(() => UnorderedSources.Default(1).Average((Func<int, float>)(x => { throw new DeliberateTestException(); })));
315             AssertThrows.Wrapped<DeliberateTestException>(() => UnorderedSources.Default(1).Average((Func<int, float?>)(x => { throw new DeliberateTestException(); })));
316 
317             AssertThrows.Wrapped<DeliberateTestException>(() => UnorderedSources.Default(1).Average((Func<int, double>)(x => { throw new DeliberateTestException(); })));
318             AssertThrows.Wrapped<DeliberateTestException>(() => UnorderedSources.Default(1).Average((Func<int, double?>)(x => { throw new DeliberateTestException(); })));
319 
320             AssertThrows.Wrapped<DeliberateTestException>(() => UnorderedSources.Default(1).Average((Func<int, decimal>)(x => { throw new DeliberateTestException(); })));
321             AssertThrows.Wrapped<DeliberateTestException>(() => UnorderedSources.Default(1).Average((Func<int, decimal?>)(x => { throw new DeliberateTestException(); })));
322         }
323 
324         [Fact]
Average_ArgumentNullException()325         public static void Average_ArgumentNullException()
326         {
327             AssertExtensions.Throws<ArgumentNullException>("source", () => ((ParallelQuery<int>)null).Average());
328             AssertExtensions.Throws<ArgumentNullException>("selector", () => ParallelEnumerable.Repeat(0, 1).Average((Func<int, int>)null));
329             AssertExtensions.Throws<ArgumentNullException>("source", () => ((ParallelQuery<int?>)null).Average());
330             AssertExtensions.Throws<ArgumentNullException>("selector", () => ParallelEnumerable.Repeat((int?)0, 1).Average((Func<int?, int?>)null));
331 
332             AssertExtensions.Throws<ArgumentNullException>("source", () => ((ParallelQuery<long>)null).Average());
333             AssertExtensions.Throws<ArgumentNullException>("selector", () => ParallelEnumerable.Repeat((long)0, 1).Average((Func<long, long>)null));
334             AssertExtensions.Throws<ArgumentNullException>("source", () => ((ParallelQuery<long?>)null).Average());
335             AssertExtensions.Throws<ArgumentNullException>("selector", () => ParallelEnumerable.Repeat((long?)0, 1).Average((Func<long?, long?>)null));
336 
337             AssertExtensions.Throws<ArgumentNullException>("source", () => ((ParallelQuery<float>)null).Average());
338             AssertExtensions.Throws<ArgumentNullException>("selector", () => ParallelEnumerable.Repeat((float)0, 1).Average((Func<float, float>)null));
339             AssertExtensions.Throws<ArgumentNullException>("source", () => ((ParallelQuery<float?>)null).Average());
340             AssertExtensions.Throws<ArgumentNullException>("selector", () => ParallelEnumerable.Repeat((float?)0, 1).Average((Func<float?, float?>)null));
341 
342             AssertExtensions.Throws<ArgumentNullException>("source", () => ((ParallelQuery<double>)null).Average());
343             AssertExtensions.Throws<ArgumentNullException>("selector", () => ParallelEnumerable.Repeat((double)0, 1).Average((Func<double, double>)null));
344             AssertExtensions.Throws<ArgumentNullException>("source", () => ((ParallelQuery<double?>)null).Average());
345             AssertExtensions.Throws<ArgumentNullException>("selector", () => ParallelEnumerable.Repeat((double?)0, 1).Average((Func<double?, double?>)null));
346 
347             AssertExtensions.Throws<ArgumentNullException>("source", () => ((ParallelQuery<decimal>)null).Average());
348             AssertExtensions.Throws<ArgumentNullException>("selector", () => ParallelEnumerable.Repeat((decimal)0, 1).Average((Func<decimal, decimal>)null));
349             AssertExtensions.Throws<ArgumentNullException>("source", () => ((ParallelQuery<decimal?>)null).Average());
350             AssertExtensions.Throws<ArgumentNullException>("selector", () => ParallelEnumerable.Repeat((decimal?)0, 1).Average((Func<decimal?, decimal?>)null));
351         }
352     }
353 }
354