1
1
module TaskSeq.Tests.Concat
2
2
3
+ open System
3
4
open System.Collections .Generic
4
5
5
6
open Xunit
@@ -8,7 +9,11 @@ open FsUnit.Xunit
8
9
open FSharp.Control
9
10
10
11
//
11
- // TaskSeq.concat
12
+ // TaskSeq.concat - of task seqs
13
+ // TaskSeq.concat - of seqs
14
+ // TaskSeq.concat - of lists
15
+ // TaskSeq.concat - of arrays
16
+ // TaskSeq.concat - of resizable arrays
12
17
//
13
18
14
19
let validateSequence ts =
@@ -20,31 +25,126 @@ let validateSequence ts =
20
25
21
26
module EmptySeq =
22
27
[<Fact>]
23
- let ``Null source is invalid`` () = assertNullArg <| fun () -> TaskSeq.concat null
28
+ let ``Null source is invalid ( taskseq ) `` () =
29
+ assertNullArg
30
+ <| fun () -> TaskSeq.concat ( null : TaskSeq< TaskSeq<_>>)
31
+
32
+ [<Fact>]
33
+ let ``Null source is invalid ( seq ) `` () =
34
+ assertNullArg
35
+ <| fun () -> TaskSeq.concat ( null : TaskSeq< seq<_>>)
36
+
37
+ [<Fact>]
38
+ let ``Null source is invalid ( array ) `` () =
39
+ assertNullArg
40
+ <| fun () -> TaskSeq.concat ( null : TaskSeq< array<_>>)
41
+
42
+ [<Fact>]
43
+ let ``Null source is invalid ( list ) `` () =
44
+ assertNullArg
45
+ <| fun () -> TaskSeq.concat ( null : TaskSeq< list<_>>)
46
+
47
+ [<Fact>]
48
+ let ``Null source is invalid ( resizarray ) `` () =
49
+ assertNullArg
50
+ <| fun () -> TaskSeq.concat ( null : TaskSeq< ResizeArray<_>>)
24
51
25
52
[<Theory; ClassData( typeof< TestEmptyVariants>) >]
26
- let ``TaskSeq - concat with empty sequences`` variant =
53
+ let ``TaskSeq - concat with nested empty task sequences`` variant =
27
54
taskSeq {
28
- yield Gen.getEmptyVariant variant // not yield-bang!
29
55
yield Gen.getEmptyVariant variant
30
56
yield Gen.getEmptyVariant variant
57
+ yield Gen.getEmptyVariant variant
58
+ }
59
+ |> TaskSeq.concat
60
+ |> verifyEmpty
61
+
62
+ [<Fact>]
63
+ let ``TaskSeq - concat with nested empty sequences`` () =
64
+ taskSeq {
65
+ yield Seq.empty< string>
66
+ yield Seq.empty< string>
67
+ yield Seq.empty< string>
68
+ }
69
+ |> TaskSeq.concat
70
+ |> verifyEmpty
71
+
72
+ [<Fact>]
73
+ let ``TaskSeq - concat with nested empty arrays`` () =
74
+ taskSeq {
75
+ yield Array.empty< int>
76
+ yield Array.empty< int>
77
+ yield Array.empty< int>
78
+ }
79
+ |> TaskSeq.concat
80
+ |> verifyEmpty
81
+
82
+ [<Fact>]
83
+ let ``TaskSeq - concat with nested empty lists`` () =
84
+ taskSeq {
85
+ yield List.empty< Guid>
86
+ yield List.empty< Guid>
87
+ yield List.empty< Guid>
31
88
}
32
89
|> TaskSeq.concat
33
90
|> verifyEmpty
34
91
92
+ [<Fact>]
93
+ let ``TaskSeq - concat with multiple nested empty resizable arrays`` () =
94
+ taskSeq {
95
+ yield ResizeArray( List.empty< byte>)
96
+ yield ResizeArray( List.empty< byte>)
97
+ yield ResizeArray( List.empty< byte>)
98
+ }
99
+ |> TaskSeq.concat
100
+ |> verifyEmpty
101
+
102
+ [<Theory; ClassData( typeof< TestEmptyVariants>) >]
103
+ let ``TaskSeq - concat with empty source ( taskseq ) `` variant =
104
+ Gen.getEmptyVariant variant
105
+ |> TaskSeq.box
106
+ |> TaskSeq.cast< IAsyncEnumerable< int>> // task seq is empty so this should not raise
107
+ |> TaskSeq.concat
108
+ |> verifyEmpty
109
+
110
+ [<Theory; ClassData( typeof< TestEmptyVariants>) >]
111
+ let ``TaskSeq - concat with empty source ( seq ) `` variant =
112
+ Gen.getEmptyVariant variant
113
+ |> TaskSeq.box
114
+ |> TaskSeq.cast< int seq> // task seq is empty so this should not raise
115
+ |> TaskSeq.concat
116
+ |> verifyEmpty
117
+
35
118
[<Theory; ClassData( typeof< TestEmptyVariants>) >]
36
- let ``TaskSeq - concat with top sequence empty `` variant =
119
+ let ``TaskSeq - concat with empty source ( list ) `` variant =
37
120
Gen.getEmptyVariant variant
38
121
|> TaskSeq.box
39
- |> TaskSeq.cast< IAsyncEnumerable < int>> // casting an int to an enumerable, LOL!
122
+ |> TaskSeq.cast< int list > // task seq is empty so this should not raise
40
123
|> TaskSeq.concat
41
124
|> verifyEmpty
42
125
126
+ [<Theory; ClassData( typeof< TestEmptyVariants>) >]
127
+ let ``TaskSeq - concat with empty source ( array ) `` variant =
128
+ Gen.getEmptyVariant variant
129
+ |> TaskSeq.box
130
+ |> TaskSeq.cast< int[]> // task seq is empty so this should not raise
131
+ |> TaskSeq.concat
132
+ |> verifyEmpty
133
+
134
+ [<Theory; ClassData( typeof< TestEmptyVariants>) >]
135
+ let ``TaskSeq - concat with empty source ( resizearray ) `` variant =
136
+ Gen.getEmptyVariant variant
137
+ |> TaskSeq.box
138
+ |> TaskSeq.cast< ResizeArray< int>> // task seq is empty so this should not raise
139
+ |> TaskSeq.concat
140
+ |> verifyEmpty
141
+
142
+
43
143
module Immutable =
44
144
[<Theory; ClassData( typeof< TestImmTaskSeq>) >]
45
145
let ``TaskSeq - concat with three sequences of sequences`` variant =
46
146
taskSeq {
47
- yield Gen.getSeqImmutable variant // not yield-bang!
147
+ yield Gen.getSeqImmutable variant
48
148
yield Gen.getSeqImmutable variant
49
149
yield Gen.getSeqImmutable variant
50
150
}
@@ -55,7 +155,7 @@ module Immutable =
55
155
let ``TaskSeq - concat with three sequences of sequences and few empties`` variant =
56
156
taskSeq {
57
157
yield TaskSeq.empty
58
- yield Gen.getSeqImmutable variant // not yield-bang!
158
+ yield Gen.getSeqImmutable variant
59
159
yield TaskSeq.empty
60
160
yield TaskSeq.empty
61
161
yield Gen.getSeqImmutable variant
@@ -69,23 +169,100 @@ module Immutable =
69
169
|> TaskSeq.concat
70
170
|> validateSequence
71
171
72
- module SideEffect =
73
172
[<Theory; ClassData( typeof< TestImmTaskSeq>) >]
74
- let ``TaskSeq - concat consumes until the end , including side - effects`` variant =
173
+ let ``TaskSeq - concat throws when one of inner task sequence is null`` variant =
174
+ fun () ->
175
+ taskSeq {
176
+ yield Gen.getSeqImmutable variant
177
+ yield TaskSeq.empty
178
+ yield null
179
+ }
180
+ |> TaskSeq.concat
181
+ |> consumeTaskSeq
182
+ |> should throwAsyncExact typeof< NullReferenceException>
183
+
184
+ module SideEffect =
185
+ [<Fact>]
186
+ let ``TaskSeq - concat executes side effects of nested ( taskseq ) `` () =
75
187
let mutable i = 0
76
188
77
189
taskSeq {
78
- yield Gen.getSeqImmutable variant // not yield-bang!
79
- yield Gen.getSeqImmutable variant
190
+ yield Gen.getSeqImmutable SeqImmutable.ThreadSpinWait
191
+ yield Gen.getSeqImmutable SeqImmutable.ThreadSpinWait
80
192
81
193
yield taskSeq {
82
194
yield ! [ 1 .. 10 ]
83
195
i <- i + 1
84
196
}
85
197
}
86
198
|> TaskSeq.concat
87
- |> validateSequence
88
- |> Task.map ( fun () -> i |> should equal 1 )
199
+ |> TaskSeq.last // consume
200
+ |> Task.map ( fun _ -> i |> should equal 1 )
201
+
202
+ [<Fact>]
203
+ let ``TaskSeq - concat executes side effects of nested ( seq ) `` () =
204
+ let mutable i = 0
205
+
206
+ taskSeq {
207
+ yield seq { 1 .. 10 }
208
+ yield seq { 1 .. 10 }
209
+
210
+ yield seq {
211
+ yield ! [ 1 .. 10 ]
212
+ i <- i + 1
213
+ }
214
+ }
215
+ |> TaskSeq.concat
216
+ |> TaskSeq.last // consume
217
+ |> Task.map ( fun _ -> i |> should equal 1 )
218
+
219
+ [<Fact>]
220
+ let ``TaskSeq - concat executes side effects of nested ( array ) `` () =
221
+ let mutable i = 0
222
+
223
+ taskSeq {
224
+ yield [| 1 .. 10 |]
225
+ yield [| 1 .. 10 |]
226
+
227
+ yield [| yield ! [ 1 .. 10 ]; i <- i + 1 |]
228
+ }
229
+ |> TaskSeq.concat
230
+ |> TaskSeq.last // consume
231
+ |> Task.map ( fun _ -> i |> should equal 1 )
232
+
233
+ [<Fact>]
234
+ let ``TaskSeq - concat executes side effects of nested ( list ) `` () =
235
+ let mutable i = 0
236
+
237
+ taskSeq {
238
+ yield [ 1 .. 10 ]
239
+ yield [ 1 .. 10 ]
240
+
241
+ yield [ yield ! [ 1 .. 10 ]; i <- i + 1 ]
242
+ }
243
+ |> TaskSeq.concat
244
+ |> TaskSeq.last // consume
245
+ |> Task.map ( fun _ -> i |> should equal 1 )
246
+
247
+ [<Fact>]
248
+ let ``TaskSeq - concat executes side effects of nested ( resizearray ) `` () =
249
+ let mutable i = 0
250
+
251
+ taskSeq {
252
+ yield ResizeArray { 1 .. 10 }
253
+ yield ResizeArray { 1 .. 10 }
254
+
255
+ yield
256
+ ResizeArray(
257
+ seq {
258
+ yield ! [ 1 .. 10 ]
259
+ i <- i + 1
260
+ }
261
+ )
262
+ }
263
+ |> TaskSeq.concat
264
+ |> TaskSeq.last // consume
265
+ |> Task.map ( fun _ -> i |> should equal 1 )
89
266
90
267
[<Theory; ClassData( typeof< TestImmTaskSeq>) >]
91
268
let ``TaskSeq - concat consumes side effects in empty sequences`` variant =
0 commit comments