@@ -133,3 +133,87 @@ module SideEffects =
133
133
|> TaskSeq.map ((+) '@' )
134
134
|> TaskSeq.toArrayAsync
135
135
|> Task.map ( String >> should equal " ABCDE" )
136
+
137
+ [<Theory; InlineData( false , false ); InlineData( true , false ); InlineData( false , true ); InlineData( true , true ) >]
138
+ let ``TaskSeq - takeWhile ( Inclusive )?( Async )? __special - case__ prove it does not read beyond the failing yield`` ( inclusive , async ) = task {
139
+ let mutable x = 42 // for this test, the potential mutation should not actually occur
140
+
141
+ let items = taskSeq {
142
+ yield x // Always passes the test; always returned
143
+ yield x * 2 // the failing item (which will also be yielded in the result when using *Inclusive)
144
+ x <- x + 1 // we are proving we never get here
145
+ }
146
+
147
+ let f =
148
+ match inclusive, async with
149
+ | false , false -> TaskSeq.takeWhile ( fun x -> x = 42 )
150
+ | true , false -> TaskSeq.takeWhileInclusive ( fun x -> x = 42 )
151
+ | false , true -> TaskSeq.takeWhileAsync ( fun x -> task { return x = 42 })
152
+ | true , true -> TaskSeq.takeWhileInclusiveAsync ( fun x -> task { return x = 42 })
153
+
154
+ let expected = if inclusive then [| 42 ; 84 |] else [| 42 |]
155
+
156
+ let! first = items |> f |> TaskSeq.toArrayAsync
157
+ let! repeat = items |> f |> TaskSeq.toArrayAsync
158
+
159
+ first |> should equal expected
160
+ repeat |> should equal expected
161
+ x |> should equal 42
162
+ }
163
+
164
+ [<Theory; InlineData( false , false ); InlineData( true , false ); InlineData( false , true ); InlineData( true , true ) >]
165
+ let ``TaskSeq - takeWhile ( Inclusive )?( Async )? __special - case__ prove side effects are executed`` ( inclusive , async ) = task {
166
+ let mutable x = 41
167
+
168
+ let items = taskSeq {
169
+ x <- x + 1
170
+ yield x
171
+ x <- x + 2
172
+ yield x * 2
173
+ x <- x + 200 // as previously proven, we should not trigger this
174
+ }
175
+
176
+ let f =
177
+ match inclusive, async with
178
+ | false , false -> TaskSeq.takeWhile ( fun x -> x < 50 )
179
+ | true , false -> TaskSeq.takeWhileInclusive ( fun x -> x < 50 )
180
+ | false , true -> TaskSeq.takeWhileAsync ( fun x -> task { return x < 50 })
181
+ | true , true -> TaskSeq.takeWhileInclusiveAsync ( fun x -> task { return x < 50 })
182
+
183
+ let expectedFirst = if inclusive then [| 42 ; 44 * 2 |] else [| 42 |]
184
+ let expectedRepeat = if inclusive then [| 45 ; 47 * 2 |] else [| 45 |]
185
+
186
+ let! first = items |> f |> TaskSeq.toArrayAsync
187
+ x |> should equal 44
188
+ let! repeat = items |> f |> TaskSeq.toArrayAsync
189
+ x |> should equal 47
190
+
191
+ first |> should equal expectedFirst
192
+ repeat |> should equal expectedRepeat
193
+ }
194
+
195
+ [<Theory; ClassData( typeof< TestSideEffectTaskSeq>) >]
196
+ let ``TaskSeq - takeWhile consumes the prefix of a longer sequence , with mutation`` variant = task {
197
+ let ts = Gen.getSeqWithSideEffect variant
198
+
199
+ let! first = TaskSeq.takeWhile ( fun x -> x < 5 ) ts |> TaskSeq.toArrayAsync
200
+ let expected = [| 1 .. 4 |]
201
+ first |> should equal expected
202
+
203
+ // side effect, reiterating causes it to resume from where we left it (minus the failing item)
204
+ let! repeat = TaskSeq.takeWhile ( fun x -> x < 5 ) ts |> TaskSeq.toArrayAsync
205
+ repeat |> should not' ( equal expected)
206
+ }
207
+
208
+ [<Theory; ClassData( typeof< TestSideEffectTaskSeq>) >]
209
+ let ``TaskSeq - takeWhileInclusiveAsync consumes the prefix for a longer sequence , with mutation`` variant = task {
210
+ let ts = Gen.getSeqWithSideEffect variant
211
+
212
+ let! first = TaskSeq.takeWhileInclusiveAsync ( fun x -> task { return x < 5 }) ts |> TaskSeq.toArrayAsync
213
+ let expected = [| 1 .. 5 |]
214
+ first |> should equal expected
215
+
216
+ // side effect, reiterating causes it to resume from where we left it (minus the failing item)
217
+ let! repeat = TaskSeq.takeWhileInclusiveAsync ( fun x -> task { return x < 5 }) ts |> TaskSeq.toArrayAsync
218
+ repeat |> should not' ( equal expected)
219
+ }
0 commit comments