Skip to content

Commit 12229d8

Browse files
authored
Async Support (#12)
* Option MapAsync * Option MapAsync tests * Option MapAsync coverage * Option MapOrAsync * Option MapOrElseAsync * Update codecov.yml * AndThenAsync * OrElseAsync * ValuesAsync, FirstOrNoneAsync * Async namespace * Code coverage * Result MapAsync tests * Result MapOrElseAsync * Result AndThenAsync * Result OrElseAsync * Result ValuesAsync, ErrorsAsync * Bumping version number * Cleanup * Removing unnecessary awaits * Test coverage * Documenting coverlet bug
1 parent f90e783 commit 12229d8

14 files changed

+2371
-79
lines changed

codecov.yml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
codecov:
2-
token: eb32817d-b3ab-4145-a1b0-65742c9ad600
3-
fixes:
1+
fixes:
42
- "/[A-Za-z]+/runner/work/RustyOptions/RustyOptions/::"
53
- "[A-Za-z]:\\[a-z]+\\RustyOptions\\RustyOptions\\src\\RustyOptions\\::src/RustyOptions/"
Lines changed: 297 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,297 @@
1+
using System.Runtime.CompilerServices;
2+
using RustyOptions.Async;
3+
using static RustyOptions.Option;
4+
5+
namespace RustyOptions.Tests;
6+
7+
public sealed class OptionAsyncTests
8+
{
9+
[Theory]
10+
[MemberData(nameof(GetMapAsyncValues))]
11+
public async Task CanMapAsync(object source, object mapper, Option<long> expected)
12+
{
13+
switch ((source, mapper))
14+
{
15+
case (Option<int> src, Func<int, ValueTask<long>> mpr):
16+
Assert.Equal(expected, await src.MapAsync(mpr));
17+
break;
18+
case (Option<int> src, Func<int, Task<long>> mpr):
19+
Assert.Equal(expected, await src.MapAsync(mpr));
20+
break;
21+
case (ValueTask<Option<int>> src, Func<int, long> mpr):
22+
Assert.Equal(expected, await src.MapAsync(mpr));
23+
break;
24+
case (Task<Option<int>> src, Func<int, long> mpr):
25+
Assert.Equal(expected, await src.MapAsync(mpr));
26+
break;
27+
case (ValueTask<Option<int>> src, Func<int, ValueTask<long>> mpr):
28+
Assert.Equal(expected, await src.MapAsync(mpr));
29+
break;
30+
case (Task<Option<int>> src, Func<int, ValueTask<long>> mpr):
31+
Assert.Equal(expected, await src.MapAsync(mpr));
32+
break;
33+
case (ValueTask<Option<int>> src, Func<int, Task<long>> mpr):
34+
Assert.Equal(expected, await src.MapAsync(mpr));
35+
break;
36+
case (Task<Option<int>> src, Func<int, Task<long>> mpr):
37+
Assert.Equal(expected, await src.MapAsync(mpr));
38+
break;
39+
40+
default:
41+
Assert.Fail($"Unexpected source/mapper: {source.GetType().Name}/{mapper.GetType().Name}");
42+
break;
43+
}
44+
}
45+
46+
public static IEnumerable<object[]> GetMapAsyncValues()
47+
{
48+
var expected = Some(84L);
49+
var expectedNone = None<long>();
50+
var source = Some(42);
51+
var sourceNone = None<int>();
52+
var taskSrc = Task.FromResult(source);
53+
var valTaskSrc = ValueTask.FromResult(source);
54+
var taskSrcNone = Task.FromResult(sourceNone);
55+
var valTaskSrcNone = ValueTask.FromResult(sourceNone);
56+
57+
var mapper = (int x) => (long)(x * 2);
58+
var taskMapper = (int x) => Task.FromResult((long)(x * 2));
59+
var valTaskMapper = (int x) => ValueTask.FromResult((long)(x * 2));
60+
61+
yield return new object[] { source, taskMapper, expected };
62+
yield return new object[] { source, valTaskMapper, expected };
63+
yield return new object[] { taskSrc, mapper, expected };
64+
yield return new object[] { valTaskSrc, mapper, expected };
65+
yield return new object[] { taskSrc, taskMapper, expected };
66+
yield return new object[] { valTaskSrc, taskMapper, expected };
67+
yield return new object[] { taskSrc, valTaskMapper, expected };
68+
yield return new object[] { valTaskSrc, valTaskMapper, expected };
69+
70+
yield return new object[] { sourceNone, taskMapper, expectedNone };
71+
yield return new object[] { sourceNone, valTaskMapper, expectedNone };
72+
yield return new object[] { taskSrcNone, mapper, expectedNone };
73+
yield return new object[] { valTaskSrcNone, mapper, expectedNone };
74+
yield return new object[] { taskSrcNone, taskMapper, expectedNone };
75+
yield return new object[] { valTaskSrcNone, taskMapper, expectedNone };
76+
yield return new object[] { taskSrcNone, valTaskMapper, expectedNone };
77+
yield return new object[] { valTaskSrcNone, valTaskMapper, expectedNone };
78+
}
79+
80+
[Theory]
81+
[MemberData(nameof(GetMapOrElseAsyncValues))]
82+
public async Task CanMapOrElseAsync(object source, object mapper, object defaultFactory, long expected)
83+
{
84+
switch ((source, mapper, defaultFactory))
85+
{
86+
case (Option<int> src, Func<int, ValueTask<long>> mpr, Func<ValueTask<long>> dff):
87+
Assert.Equal(expected, await src.MapOrElseAsync(mpr, dff));
88+
break;
89+
case (Option<int> src, Func<int, Task<long>> mpr, Func<Task<long>> dff):
90+
Assert.Equal(expected, await src.MapOrElseAsync(mpr, dff));
91+
break;
92+
case (ValueTask<Option<int>> src, Func<int, long> mpr, Func<long> dff):
93+
Assert.Equal(expected, await src.MapOrElseAsync(mpr, dff));
94+
break;
95+
case (Task<Option<int>> src, Func<int, long> mpr, Func<long> dff):
96+
Assert.Equal(expected, await src.MapOrElseAsync(mpr, dff));
97+
break;
98+
case (ValueTask<Option<int>> src, Func<int, ValueTask<long>> mpr, Func<ValueTask<long>> dff):
99+
Assert.Equal(expected, await src.MapOrElseAsync(mpr, dff));
100+
break;
101+
case (Task<Option<int>> src, Func<int, ValueTask<long>> mpr, Func<ValueTask<long>> dff):
102+
Assert.Equal(expected, await src.MapOrElseAsync(mpr, dff));
103+
break;
104+
case (ValueTask<Option<int>> src, Func<int, Task<long>> mpr, Func<Task<long>> dff):
105+
Assert.Equal(expected, await src.MapOrElseAsync(mpr, dff));
106+
break;
107+
case (Task<Option<int>> src, Func<int, Task<long>> mpr, Func<Task<long>> dff):
108+
Assert.Equal(expected, await src.MapOrElseAsync(mpr, dff));
109+
break;
110+
111+
default:
112+
Assert.Fail($"Unexpected source/mapper: {source.GetType().Name}/{mapper.GetType().Name}");
113+
break;
114+
}
115+
}
116+
117+
public static IEnumerable<object[]> GetMapOrElseAsyncValues()
118+
{
119+
var defaultFactory = () => -1L;
120+
var taskDefault = () => Task.FromResult(-1L);
121+
var valueTaskDefault = () => ValueTask.FromResult(-1L);
122+
123+
var expected = 84L;
124+
var expectedNone = -1L;
125+
126+
var source = Some(42);
127+
var sourceNone = None<int>();
128+
var taskSrc = Task.FromResult(source);
129+
var valTaskSrc = ValueTask.FromResult(source);
130+
var taskSrcNone = Task.FromResult(sourceNone);
131+
var valTaskSrcNone = ValueTask.FromResult(sourceNone);
132+
133+
var mapper = (int x) => (long)(x * 2);
134+
var taskMapper = (int x) => Task.FromResult((long)(x * 2));
135+
var valTaskMapper = (int x) => ValueTask.FromResult((long)(x * 2));
136+
137+
yield return new object[] { source, taskMapper, taskDefault, expected };
138+
yield return new object[] { source, valTaskMapper, valueTaskDefault, expected };
139+
yield return new object[] { taskSrc, mapper, defaultFactory, expected };
140+
yield return new object[] { valTaskSrc, mapper, defaultFactory, expected };
141+
yield return new object[] { taskSrc, taskMapper, taskDefault, expected };
142+
yield return new object[] { valTaskSrc, taskMapper, taskDefault, expected };
143+
yield return new object[] { taskSrc, valTaskMapper, valueTaskDefault, expected };
144+
yield return new object[] { valTaskSrc, valTaskMapper, valueTaskDefault, expected };
145+
146+
yield return new object[] { sourceNone, taskMapper, taskDefault, expectedNone };
147+
yield return new object[] { sourceNone, valTaskMapper, valueTaskDefault, expectedNone };
148+
yield return new object[] { taskSrcNone, mapper, defaultFactory, expectedNone };
149+
yield return new object[] { valTaskSrcNone, mapper, defaultFactory, expectedNone };
150+
yield return new object[] { taskSrcNone, taskMapper, taskDefault, expectedNone };
151+
yield return new object[] { valTaskSrcNone, taskMapper, taskDefault, expectedNone };
152+
yield return new object[] { taskSrcNone, valTaskMapper, valueTaskDefault, expectedNone };
153+
yield return new object[] { valTaskSrcNone, valTaskMapper, valueTaskDefault, expectedNone };
154+
}
155+
156+
[Theory]
157+
[MemberData(nameof(GetAndThenAsyncValues))]
158+
public async Task CanAndThenAsync(object source, object mapper, Option<long> expected)
159+
{
160+
switch ((source, mapper))
161+
{
162+
case (Option<int> src, Func<int, ValueTask<Option<long>>> mpr):
163+
Assert.Equal(expected, await src.AndThenAsync(mpr));
164+
break;
165+
case (Option<int> src, Func<int, Task<Option<long>>> mpr):
166+
Assert.Equal(expected, await src.AndThenAsync(mpr));
167+
break;
168+
case (ValueTask<Option<int>> src, Func<int, Option<long>> mpr):
169+
Assert.Equal(expected, await src.AndThenAsync(mpr));
170+
break;
171+
case (Task<Option<int>> src, Func<int, Option<long>> mpr):
172+
Assert.Equal(expected, await src.AndThenAsync(mpr));
173+
break;
174+
case (ValueTask<Option<int>> src, Func<int, ValueTask<Option<long>>> mpr):
175+
Assert.Equal(expected, await src.AndThenAsync(mpr));
176+
break;
177+
case (Task<Option<int>> src, Func<int, ValueTask<Option<long>>> mpr):
178+
Assert.Equal(expected, await src.AndThenAsync(mpr));
179+
break;
180+
case (ValueTask<Option<int>> src, Func<int, Task<Option<long>>> mpr):
181+
Assert.Equal(expected, await src.AndThenAsync(mpr));
182+
break;
183+
case (Task<Option<int>> src, Func<int, Task<Option<long>>> mpr):
184+
Assert.Equal(expected, await src.AndThenAsync(mpr));
185+
break;
186+
187+
default:
188+
Assert.Fail($"Unexpected source/mapper: {source.GetType().Name}/{mapper.GetType().Name}");
189+
break;
190+
}
191+
}
192+
193+
public static IEnumerable<object[]> GetAndThenAsyncValues()
194+
{
195+
var expected = Some(84L);
196+
var expectedNone = None<long>();
197+
var source = Some(42);
198+
var sourceNone = None<int>();
199+
var taskSrc = Task.FromResult(source);
200+
var valTaskSrc = ValueTask.FromResult(source);
201+
var taskSrcNone = Task.FromResult(sourceNone);
202+
var valTaskSrcNone = ValueTask.FromResult(sourceNone);
203+
204+
var mapper = (int x) => Some((long)(x * 2));
205+
var taskMapper = (int x) => Task.FromResult(Some((long)(x * 2)));
206+
var valTaskMapper = (int x) => ValueTask.FromResult(Some((long)(x * 2)));
207+
208+
yield return new object[] { source, taskMapper, expected };
209+
yield return new object[] { source, valTaskMapper, expected };
210+
yield return new object[] { taskSrc, mapper, expected };
211+
yield return new object[] { valTaskSrc, mapper, expected };
212+
yield return new object[] { taskSrc, taskMapper, expected };
213+
yield return new object[] { valTaskSrc, taskMapper, expected };
214+
yield return new object[] { taskSrc, valTaskMapper, expected };
215+
yield return new object[] { valTaskSrc, valTaskMapper, expected };
216+
217+
yield return new object[] { sourceNone, taskMapper, expectedNone };
218+
yield return new object[] { sourceNone, valTaskMapper, expectedNone };
219+
yield return new object[] { taskSrcNone, mapper, expectedNone };
220+
yield return new object[] { valTaskSrcNone, mapper, expectedNone };
221+
yield return new object[] { taskSrcNone, taskMapper, expectedNone };
222+
yield return new object[] { valTaskSrcNone, taskMapper, expectedNone };
223+
yield return new object[] { taskSrcNone, valTaskMapper, expectedNone };
224+
yield return new object[] { valTaskSrcNone, valTaskMapper, expectedNone };
225+
}
226+
227+
[Theory]
228+
[MemberData(nameof(GetOrElseAsyncValues))]
229+
public async Task CanOrElseAsync(object source, object mapper, Option<int> expected)
230+
{
231+
switch ((source, mapper))
232+
{
233+
case (Option<int> src, Func<ValueTask<Option<int>>> mpr):
234+
Assert.Equal(expected, await src.OrElseAsync(mpr));
235+
break;
236+
case (Option<int> src, Func<Task<Option<int>>> mpr):
237+
Assert.Equal(expected, await src.OrElseAsync(mpr));
238+
break;
239+
case (ValueTask<Option<int>> src, Func<Option<int>> mpr):
240+
Assert.Equal(expected, await src.OrElseAsync(mpr));
241+
break;
242+
case (Task<Option<int>> src, Func<Option<int>> mpr):
243+
Assert.Equal(expected, await src.OrElseAsync(mpr));
244+
break;
245+
case (ValueTask<Option<int>> src, Func<ValueTask<Option<int>>> mpr):
246+
Assert.Equal(expected, await src.OrElseAsync(mpr));
247+
break;
248+
case (Task<Option<int>> src, Func<ValueTask<Option<int>>> mpr):
249+
Assert.Equal(expected, await src.OrElseAsync(mpr));
250+
break;
251+
case (ValueTask<Option<int>> src, Func<Task<Option<int>>> mpr):
252+
Assert.Equal(expected, await src.OrElseAsync(mpr));
253+
break;
254+
case (Task<Option<int>> src, Func<Task<Option<int>>> mpr):
255+
Assert.Equal(expected, await src.OrElseAsync(mpr));
256+
break;
257+
258+
default:
259+
Assert.Fail($"Unexpected source/mapper: {source.GetType().Name}/{mapper.GetType().Name}");
260+
break;
261+
}
262+
}
263+
264+
public static IEnumerable<object[]> GetOrElseAsyncValues()
265+
{
266+
var expected = Some(42);
267+
var expectedNone = Some(-1);
268+
var source = Some(42);
269+
var sourceNone = None<int>();
270+
var taskSrc = Task.FromResult(source);
271+
var valTaskSrc = ValueTask.FromResult(source);
272+
var taskSrcNone = Task.FromResult(sourceNone);
273+
var valTaskSrcNone = ValueTask.FromResult(sourceNone);
274+
275+
var mapper = () => Some(-1);
276+
var taskMapper = () => Task.FromResult(Some(-1));
277+
var valTaskMapper = () => ValueTask.FromResult(Some(-1));
278+
279+
yield return new object[] { source, taskMapper, expected };
280+
yield return new object[] { source, valTaskMapper, expected };
281+
yield return new object[] { taskSrc, mapper, expected };
282+
yield return new object[] { valTaskSrc, mapper, expected };
283+
yield return new object[] { taskSrc, taskMapper, expected };
284+
yield return new object[] { valTaskSrc, taskMapper, expected };
285+
yield return new object[] { taskSrc, valTaskMapper, expected };
286+
yield return new object[] { valTaskSrc, valTaskMapper, expected };
287+
288+
yield return new object[] { sourceNone, taskMapper, expectedNone };
289+
yield return new object[] { sourceNone, valTaskMapper, expectedNone };
290+
yield return new object[] { taskSrcNone, mapper, expectedNone };
291+
yield return new object[] { valTaskSrcNone, mapper, expectedNone };
292+
yield return new object[] { taskSrcNone, taskMapper, expectedNone };
293+
yield return new object[] { valTaskSrcNone, taskMapper, expectedNone };
294+
yield return new object[] { taskSrcNone, valTaskMapper, expectedNone };
295+
yield return new object[] { valTaskSrcNone, valTaskMapper, expectedNone };
296+
}
297+
}

0 commit comments

Comments
 (0)