@@ -14,6 +14,8 @@ open FSharp.Control
14
14
// TaskSeq.skipWhileInclusiveAsync
15
15
//
16
16
17
+ exception SideEffectPastEnd of string
18
+
17
19
[<AutoOpen>]
18
20
module With =
19
21
/// The only real difference in semantics between the base and the *Inclusive variant lies in whether the final item is skipped.
@@ -182,36 +184,34 @@ module SideEffects =
182
184
[<InlineData( false , true ) >]
183
185
[<InlineData( true , false ) >]
184
186
[<InlineData( true , true ) >]
185
- let ``TaskSeq - skipWhileXXX prove it does not read beyond the failing yield `` ( inclusive , isAsync ) = task {
187
+ let ``TaskSeq - skipWhileXXX prove it reads the entire input stream `` ( inclusive , isAsync ) = task {
186
188
let mutable x = 42 // for this test, the potential mutation should not actually occur
187
189
let functionToTest = getFunction inclusive isAsync ((=) 42 )
188
190
189
191
let items = taskSeq {
190
192
yield x // Always passes the test; always skipped
191
193
yield x * 2 // Fails the test, skipped depending on "inclusive"
192
- x <- x + 1 // we are proving we never get here
194
+ x <- x + 1 // we are proving we ALWAYS get here
193
195
}
194
196
195
- // we skip one more if "inclusive"
196
- let expected = if inclusive then [||] else [| 84 |]
197
-
198
197
x |> should equal 42
199
198
let! first = items |> functionToTest |> TaskSeq.toArrayAsync
200
- x |> should equal 42
199
+ x |> should equal 43
200
+ first |> should equal ( if inclusive then [||] else [| 84 |])
201
+
201
202
let! repeat = items |> functionToTest |> TaskSeq.toArrayAsync
202
- x |> should equal 42
203
+ x |> should equal 44
203
204
204
- first |> should equal expected
205
- repeat |> should equal expected
206
- x |> should equal 42 // if the var changed, we got too far
205
+ repeat
206
+ |> should equal ( if inclusive then [| 86 |] else [| 43 ; 86 |])
207
207
}
208
208
209
209
[<Theory>]
210
210
[<InlineData( false , false ) >]
211
211
[<InlineData( false , true ) >]
212
212
[<InlineData( true , false ) >]
213
213
[<InlineData( true , true ) >]
214
- let ``TaskSeq - skipWhileXXX prove side effects are executed`` ( inclusive , isAsync ) = task {
214
+ let ``TaskSeq - skipWhileXXX prove side effects are properly executed`` ( inclusive , isAsync ) = task {
215
215
let mutable x = 41
216
216
let functionToTest = getFunction inclusive isAsync ((>) 50 )
217
217
@@ -220,17 +220,18 @@ module SideEffects =
220
220
yield x
221
221
x <- x + 2
222
222
yield x * 2
223
- x <- x + 200 // as previously proven, we should not trigger this
223
+ x <- x + 200 // as previously proven, we should ALWAYS trigger this
224
224
}
225
225
226
- let expectedFirst = if inclusive then [||] else [| 44 * 2 |]
227
- let expectedRepeat = if inclusive then [||] else [| 47 * 2 |]
226
+ let expectedFirst = if inclusive then [||] else [| 88 |]
227
+ let expectedRepeat = if inclusive then [| 494 |] else [| 245 ; 494 |]
228
228
229
229
x |> should equal 41
230
230
let! first = items |> functionToTest |> TaskSeq.toArrayAsync
231
- x |> should equal 44
231
+ x |> should equal 244
232
+
232
233
let! repeat = items |> functionToTest |> TaskSeq.toArrayAsync
233
- x |> should equal 47
234
+ x |> should equal 447
234
235
235
236
first |> should equal expectedFirst
236
237
repeat |> should equal expectedRepeat
@@ -313,40 +314,19 @@ module Other =
313
314
[<InlineData( false , true ) >]
314
315
[<InlineData( true , false ) >]
315
316
[<InlineData( true , true ) >]
316
- let ``TaskSeq - skipWhileXXX stops consuming after predicate fails`` ( inclusive , isAsync ) = task {
317
- do !
318
- seq {
319
- yield ! [ 1 ; 2 ; 2 ; 3 ; 3 ]
320
- yield failwith " Too far"
321
- }
322
- |> TaskSeq.ofSeq
323
- |> TaskSeq.skipWhile ( fun x -> x <= 2 )
324
- |> verifyDigitsAsString " CC"
325
-
326
- do !
327
- seq {
328
- yield ! [ 1 ; 2 ; 2 ; 3 ; 3 ]
329
- yield failwith " Too far"
330
- }
331
- |> TaskSeq.ofSeq
332
- |> TaskSeq.skipWhileInclusive ( fun x -> x <= 2 )
333
- |> verifyDigitsAsString " C"
334
-
335
- do !
336
- seq {
337
- yield ! [ 1 ; 2 ; 2 ; 3 ; 3 ]
338
- yield failwith " Too far"
339
- }
340
- |> TaskSeq.ofSeq
341
- |> TaskSeq.skipWhileAsync ( fun x -> Task.fromResult ( x <= 2 ))
342
- |> verifyDigitsAsString " CC"
343
-
344
- do !
345
- seq {
346
- yield ! [ 1 ; 2 ; 2 ; 3 ; 3 ]
347
- yield failwith " Too far"
348
- }
349
- |> TaskSeq.ofSeq
350
- |> TaskSeq.skipWhileInclusiveAsync ( fun x -> Task.fromResult ( x <= 2 ))
351
- |> verifyDigitsAsString " C"
352
- }
317
+ let ``TaskSeq - skipWhileXXX stops consuming after predicate fails`` ( inclusive , isAsync ) =
318
+ let testSkipper skipper =
319
+ fun () ->
320
+ seq {
321
+ yield ! [ 1 ; 2 ; 2 ; 3 ; 3 ]
322
+ yield SideEffectPastEnd " Too far" |> raise
323
+ }
324
+ |> TaskSeq.ofSeq
325
+ |> skipper
326
+ |> consumeTaskSeq
327
+ |> should throwAsyncExact typeof< SideEffectPastEnd>
328
+
329
+ do testSkipper ( TaskSeq.skipWhile ( fun x -> x <= 2 ))
330
+ do testSkipper ( TaskSeq.skipWhileInclusive ( fun x -> x <= 2 ))
331
+ do testSkipper ( TaskSeq.skipWhileAsync ( fun x -> Task.fromResult ( x <= 2 )))
332
+ do testSkipper ( TaskSeq.skipWhileInclusiveAsync ( fun x -> Task.fromResult ( x <= 2 )))
0 commit comments