From 375fbae68f65bd7291c7188919965140d33307d3 Mon Sep 17 00:00:00 2001 From: Abel Braaksma Date: Wed, 12 Oct 2022 18:50:02 +0200 Subject: [PATCH 1/2] Reorganize tests for simplicity and improve test coverage --- .../FSharpy.TaskSeq.Test.fsproj | 5 + .../TaskSeq.Collect.Tests.fs | 65 ++++++++ .../TaskSeq.Iter.Tests.fs | 48 ++++++ src/FSharpy.TaskSeq.Test/TaskSeq.Map.Tests.fs | 34 +++++ .../TaskSeq.OfXXX.Tests.fs | 57 +++++++ src/FSharpy.TaskSeq.Test/TaskSeq.Tests.fs | 142 +----------------- .../TaskSeq.ToXXX.Tests.fs | 74 +++++++++ src/FSharpy.TaskSeq.Test/TestUtils.fs | 12 ++ src/FSharpy.TaskSeq/TaskSeq.fs | 71 +++++---- 9 files changed, 346 insertions(+), 162 deletions(-) create mode 100644 src/FSharpy.TaskSeq.Test/TaskSeq.Collect.Tests.fs create mode 100644 src/FSharpy.TaskSeq.Test/TaskSeq.Iter.Tests.fs create mode 100644 src/FSharpy.TaskSeq.Test/TaskSeq.Map.Tests.fs create mode 100644 src/FSharpy.TaskSeq.Test/TaskSeq.OfXXX.Tests.fs create mode 100644 src/FSharpy.TaskSeq.Test/TaskSeq.ToXXX.Tests.fs diff --git a/src/FSharpy.TaskSeq.Test/FSharpy.TaskSeq.Test.fsproj b/src/FSharpy.TaskSeq.Test/FSharpy.TaskSeq.Test.fsproj index 99c30574..5e550ff5 100644 --- a/src/FSharpy.TaskSeq.Test/FSharpy.TaskSeq.Test.fsproj +++ b/src/FSharpy.TaskSeq.Test/FSharpy.TaskSeq.Test.fsproj @@ -9,6 +9,11 @@ + + + + + diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.Collect.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Collect.Tests.fs new file mode 100644 index 00000000..4a437ade --- /dev/null +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Collect.Tests.fs @@ -0,0 +1,65 @@ +module FSharpy.TaskSeq.Tests.Collect + +open Xunit +open FsUnit.Xunit +open FsToolkit.ErrorHandling + +open FSharpy + +[] +let ``TaskSeq-collect operates in correct order`` () = task { + let! sq = + createDummyTaskSeq 10 + |> TaskSeq.collect (fun item -> taskSeq { + yield char (item + 64) + yield char (item + 65) + }) + |> TaskSeq.toSeqCachedAsync + + sq + |> Seq.map string + |> String.concat "" + |> should equal "ABBCCDDEEFFGGHHIIJJK" +} + +[] +let ``TaskSeq-collectSeq operates in correct order`` () = task { + let! sq = + createDummyTaskSeq 10 + |> TaskSeq.collectSeq (fun item -> seq { + yield char (item + 64) + yield char (item + 65) + }) + |> TaskSeq.toSeqCachedAsync + + sq + |> Seq.map string + |> String.concat "" + |> should equal "ABBCCDDEEFFGGHHIIJJK" +} + +[] +let ``TaskSeq-collect with empty task sequences`` () = task { + let! sq = + createDummyTaskSeq 10 + |> TaskSeq.collect (fun _ -> TaskSeq.ofSeq Seq.empty) + |> TaskSeq.toSeqCachedAsync + + Seq.isEmpty sq |> should be True +} + +[] +let ``TaskSeq-collectSeq with empty sequences`` () = task { + let! sq = + createDummyTaskSeq 10 + |> TaskSeq.collectSeq (fun _ -> Seq.empty) + |> TaskSeq.toSeqCachedAsync + + Seq.isEmpty sq |> should be True +} + +[] +let ``TaskSeq-empty is empty`` () = task { + let! sq = TaskSeq.empty |> TaskSeq.toSeqCachedAsync + Seq.isEmpty sq |> should be True +} diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.Iter.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Iter.Tests.fs new file mode 100644 index 00000000..7825b64c --- /dev/null +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Iter.Tests.fs @@ -0,0 +1,48 @@ +module FSharpy.TaskSeq.Tests.Iter + +open Xunit +open FsUnit.Xunit +open FsToolkit.ErrorHandling + +open FSharpy + + +[] +let ``TaskSeq-iteri should go over all items`` () = task { + let tq = createDummyTaskSeq 10 + let mutable sum = 0 + do! tq |> TaskSeq.iteri (fun i _ -> sum <- sum + i) + sum |> should equal 45 // index starts at 0 +} + +[] +let ``TaskSeq-iter should go over all items`` () = task { + let tq = createDummyTaskSeq 10 + let mutable sum = 0 + do! tq |> TaskSeq.iter (fun item -> sum <- sum + item) + sum |> should equal 55 // task-dummies started at 1 +} + +[] +let ``TaskSeq-iteriAsync should go over all items`` () = task { + let tq = createDummyTaskSeq 10 + let mutable sum = 0 + + do! + tq + |> TaskSeq.iteriAsync (fun i _ -> task { sum <- sum + i }) + + sum |> should equal 45 // index starts at 0 +} + +[] +let ``TaskSeq-iterAsync should go over all items`` () = task { + let tq = createDummyTaskSeq 10 + let mutable sum = 0 + + do! + tq + |> TaskSeq.iterAsync (fun item -> task { sum <- sum + item }) + + sum |> should equal 55 // task-dummies started at 1 +} diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.Map.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Map.Tests.fs new file mode 100644 index 00000000..0392a28e --- /dev/null +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Map.Tests.fs @@ -0,0 +1,34 @@ +module FSharpy.TaskSeq.Tests.Map + +open Xunit +open FsUnit.Xunit +open FsToolkit.ErrorHandling + +open FSharpy + + +[] +let ``TaskSeq-map maps in correct order`` () = task { + let! sq = + createDummyTaskSeq 10 + |> TaskSeq.map (fun item -> char (item + 64)) + |> TaskSeq.toSeqCachedAsync + + sq + |> Seq.map string + |> String.concat "" + |> should equal "ABCDEFGHIJ" +} + +[] +let ``TaskSeq-mapAsync maps in correct order`` () = task { + let! sq = + createDummyTaskSeq 10 + |> TaskSeq.mapAsync (fun item -> task { return char (item + 64) }) + |> TaskSeq.toSeqCachedAsync + + sq + |> Seq.map string + |> String.concat "" + |> should equal "ABCDEFGHIJ" +} diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.OfXXX.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.OfXXX.Tests.fs new file mode 100644 index 00000000..5a15377b --- /dev/null +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.OfXXX.Tests.fs @@ -0,0 +1,57 @@ +module FSharpy.TaskSeq.Tests.``Conversion-From`` + +open Xunit +open FsUnit.Xunit +open FsToolkit.ErrorHandling + +open FSharpy + +let validateSequence sq = task { + let! sq = TaskSeq.toArrayAsync sq + do sq |> Seq.toArray |> should equal [| 0..9 |] +} + +[] +let ``TaskSeq-ofAsyncArray should succeed`` () = + Array.init 10 (fun x -> async { return x }) + |> TaskSeq.ofAsyncArray + |> validateSequence + +[] +let ``TaskSeq-ofAsyncList should succeed`` () = + List.init 10 (fun x -> async { return x }) + |> TaskSeq.ofAsyncList + |> validateSequence + +[] +let ``TaskSeq-ofAsyncSeq should succeed`` () = + Seq.init 10 (fun x -> async { return x }) + |> TaskSeq.ofAsyncSeq + |> validateSequence + +[] +let ``TaskSeq-ofTaskArray should succeed`` () = + Array.init 10 (fun x -> task { return x }) + |> TaskSeq.ofTaskArray + |> validateSequence + +[] +let ``TaskSeq-ofTaskList should succeed`` () = + List.init 10 (fun x -> task { return x }) + |> TaskSeq.ofTaskList + |> validateSequence + +[] +let ``TaskSeq-ofTaskSeq should succeed`` () = + Seq.init 10 (fun x -> task { return x }) + |> TaskSeq.ofTaskSeq + |> validateSequence + +[] +let ``TaskSeq-ofArray should succeed`` () = Array.init 10 id |> TaskSeq.ofArray |> validateSequence + +[] +let ``TaskSeq-ofList should succeed`` () = List.init 10 id |> TaskSeq.ofList |> validateSequence + +[] +let ``TaskSeq-ofSeq should succeed`` () = Seq.init 10 id |> TaskSeq.ofSeq |> validateSequence diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Tests.fs index 6781d382..83cab90b 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.Tests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Tests.fs @@ -1,4 +1,4 @@ -namespace FSharpy.TaskSeq.Tests +module FSharpy.TaskSeq.Tests.``Utility functions`` open Xunit open FsUnit.Xunit @@ -6,138 +6,10 @@ open FsToolkit.ErrorHandling open FSharpy -module TaskSeqTests = - let createTaskSeq count = - /// Set of delayed tasks in the form of `unit -> Task` - let tasks = DummyTaskFactory().CreateDelayedTasks count - taskSeq { - for task in tasks do - // cannot use `yield!` here, as `taskSeq` expects it to return a seq - let! x = task () - yield x - } - - [] - let ``TaskSeq-iteri should go over all items`` () = task { - let tq = createTaskSeq 10 - let mutable sum = 0 - do! tq |> TaskSeq.iteri (fun i _ -> sum <- sum + i) - sum |> should equal 45 // index starts at 0 - } - - [] - let ``TaskSeq-iter should go over all items`` () = task { - let tq = createTaskSeq 10 - let mutable sum = 0 - do! tq |> TaskSeq.iter (fun item -> sum <- sum + item) - sum |> should equal 55 // task-dummies started at 1 - } - - [] - let ``TaskSeq-iteriAsync should go over all items`` () = task { - let tq = createTaskSeq 10 - let mutable sum = 0 - - do! - tq - |> TaskSeq.iteriAsync (fun i _ -> task { sum <- sum + i }) - - sum |> should equal 45 // index starts at 0 - } - - [] - let ``TaskSeq-iterAsync should go over all items`` () = task { - let tq = createTaskSeq 10 - let mutable sum = 0 - - do! - tq - |> TaskSeq.iterAsync (fun item -> task { sum <- sum + item }) - - sum |> should equal 55 // task-dummies started at 1 - } - - [] - let ``TaskSeq-map maps in correct order`` () = task { - let! sq = - createTaskSeq 10 - |> TaskSeq.map (fun item -> char (item + 64)) - |> TaskSeq.toSeqCachedAsync - - sq - |> Seq.map string - |> String.concat "" - |> should equal "ABCDEFGHIJ" - } - - [] - let ``TaskSeq-mapAsync maps in correct order`` () = task { - let! sq = - createTaskSeq 10 - |> TaskSeq.mapAsync (fun item -> task { return char (item + 64) }) - |> TaskSeq.toSeqCachedAsync - - sq - |> Seq.map string - |> String.concat "" - |> should equal "ABCDEFGHIJ" - } - - [] - let ``TaskSeq-collect operates in correct order`` () = task { - let! sq = - createTaskSeq 10 - |> TaskSeq.collect (fun item -> taskSeq { - yield char (item + 64) - yield char (item + 65) - }) - |> TaskSeq.toSeqCachedAsync - - sq - |> Seq.map string - |> String.concat "" - |> should equal "ABBCCDDEEFFGGHHIIJJK" - } - - [] - let ``TaskSeq-collectSeq operates in correct order`` () = task { - let! sq = - createTaskSeq 10 - |> TaskSeq.collectSeq (fun item -> seq { - yield char (item + 64) - yield char (item + 65) - }) - |> TaskSeq.toSeqCachedAsync - - sq - |> Seq.map string - |> String.concat "" - |> should equal "ABBCCDDEEFFGGHHIIJJK" - } - - [] - let ``TaskSeq-collect with empty task sequences`` () = task { - let! sq = - createTaskSeq 10 - |> TaskSeq.collect (fun _ -> TaskSeq.ofSeq Seq.empty) - |> TaskSeq.toSeqCachedAsync - - Seq.isEmpty sq |> should be True - } - - [] - let ``TaskSeq-collectSeq with empty sequences`` () = task { - let! sq = - createTaskSeq 10 - |> TaskSeq.collectSeq (fun _ -> Seq.empty) - |> TaskSeq.toSeqCachedAsync - - Seq.isEmpty sq |> should be True - } - - [] - let ``TaskSeq-empty is empty`` () = task { - let! sq = TaskSeq.empty |> TaskSeq.toSeqCachedAsync - Seq.isEmpty sq |> should be True - } +[] +let ``TaskSeq-empty is empty`` () = task { + let! sq = TaskSeq.empty |> TaskSeq.toSeqCachedAsync + Seq.isEmpty sq |> should be True + Seq.length sq |> should equal 0 +} diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.ToXXX.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.ToXXX.Tests.fs new file mode 100644 index 00000000..8afe9f48 --- /dev/null +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.ToXXX.Tests.fs @@ -0,0 +1,74 @@ +module FSharpy.TaskSeq.Tests.``Conversion-To`` + +open Xunit +open FsUnit.Xunit +open FsToolkit.ErrorHandling + +open FSharpy +open System.Collections.Generic + +//////////////////////////////////////////////////////////////////////////// +/// /// +/// Notes for contributors: /// +/// /// +/// Conversion functions are expected to return a certain type /// +/// To prevent accidental change of signature, and because most /// +/// sequence-like functions can succeed tests interchangeably with /// +/// different sequence-like signatures, these tests /// +/// deliberately have a type annotation to prevent accidental changing /// +/// of the surface-area signatures. /// +/// /// +//////////////////////////////////////////////////////////////////////////// + +[] +let ``TaskSeq-toArrayAsync should succeed`` () = task { + let tq = createDummyTaskSeq 10 + let! (results: _[]) = tq |> TaskSeq.toArrayAsync + results |> should equal [| 0..9 |] +} + +[] +let ``TaskSeq-toListAsync should succeed`` () = task { + let tq = createDummyTaskSeq 10 + let! (results: list<_>) = tq |> TaskSeq.toListAsync + results |> should equal [ 0..9 ] +} + +[] +let ``TaskSeq-toSeqCachedAsync should succeed`` () = task { + let tq = createDummyTaskSeq 10 + let! (results: seq<_>) = tq |> TaskSeq.toSeqCachedAsync + results |> Seq.toArray |> should equal [| 0..9 |] +} + +[] +let ``TaskSeq-toIListAsync should succeed`` () = task { + let tq = createDummyTaskSeq 10 + let! (results: IList<_>) = tq |> TaskSeq.toIListAsync + results |> Seq.toArray |> should equal [| 0..9 |] +} + +[] +let ``TaskSeq-toResizeArray should succeed`` () = task { + let tq = createDummyTaskSeq 10 + let! (results: ResizeArray<_>) = tq |> TaskSeq.toResizeArrayAsync + results |> should equal [| 0..9 |] +} + +[] +let ``TaskSeq-toArray should succeed and be blocking`` () = + let tq = createDummyTaskSeq 10 + let (results: _[]) = tq |> TaskSeq.toArray + results |> should equal [| 0..9 |] + +[] +let ``TaskSeq-toList should succeed and be blocking`` () = + let tq = createDummyTaskSeq 10 + let (results: list<_>) = tq |> TaskSeq.toList + results |> should equal [ 0..9 ] + +[] +let ``TaskSeq-toSeqCached should succeed and be blocking`` () = + let tq = createDummyTaskSeq 10 + let (results: seq<_>) = tq |> TaskSeq.toSeqCached + results |> Seq.toArray |> should equal [| 0..9 |] diff --git a/src/FSharpy.TaskSeq.Test/TestUtils.fs b/src/FSharpy.TaskSeq.Test/TestUtils.fs index f7b6209d..c915f73d 100644 --- a/src/FSharpy.TaskSeq.Test/TestUtils.fs +++ b/src/FSharpy.TaskSeq.Test/TestUtils.fs @@ -59,3 +59,15 @@ module TestUtils = let combinedTask = joiner tasks // start the combined tasks combinedTask () + + /// Create a bunch of dummy tasks + let createDummyTaskSeq count = + /// Set of delayed tasks in the form of `unit -> Task` + let tasks = DummyTaskFactory().CreateDelayedTasks count + + taskSeq { + for task in tasks do + // cannot use `yield!` here, as `taskSeq` expects it to return a seq + let! x = task () + yield x + } diff --git a/src/FSharpy.TaskSeq/TaskSeq.fs b/src/FSharpy.TaskSeq/TaskSeq.fs index 76505102..a9448d91 100644 --- a/src/FSharpy.TaskSeq/TaskSeq.fs +++ b/src/FSharpy.TaskSeq/TaskSeq.fs @@ -11,7 +11,18 @@ module TaskSeq = // Just for convenience module Internal = TaskSeqInternal - /// Returns taskSeq as an array. This function is blocking until the sequence is exhausted. + /// Initialize an empty taskSeq. + let empty<'T> = taskSeq { + for c: 'T in [] do + yield c + } + + + // + // Convert 'ToXXX' functions + // + + /// Returns taskSeq as an array. This function is blocking until the sequence is exhausted and will properly dispose of the resources. let toList (t: taskSeq<'T>) = [ let e = t.GetAsyncEnumerator(CancellationToken()) @@ -23,7 +34,7 @@ module TaskSeq = ] - /// Returns taskSeq as an array. This function is blocking until the sequence is exhausted. + /// Returns taskSeq as an array. This function is blocking until the sequence is exhausted and will properly dispose of the resources. let toArray (taskSeq: taskSeq<'T>) = [| let e = taskSeq.GetAsyncEnumerator(CancellationToken()) @@ -34,12 +45,39 @@ module TaskSeq = e.DisposeAsync().AsTask().Wait() |] - /// Initialize an empty taskSeq. - let empty<'T> = taskSeq { - for c: 'T in [] do - yield c + /// Returns taskSeq as a seq, similar to Seq.cached. This function is blocking until the sequence is exhausted and will properly dispose of the resources. + let toSeqCached (taskSeq: taskSeq<'T>) = seq { + let e = taskSeq.GetAsyncEnumerator(CancellationToken()) + + try + while (let vt = e.MoveNextAsync() in if vt.IsCompleted then vt.Result else vt.AsTask().Result) do + yield e.Current + finally + e.DisposeAsync().AsTask().Wait() } + /// Unwraps the taskSeq as a Task>. This function is non-blocking. + let toArrayAsync taskSeq = + Internal.toResizeArrayAsync taskSeq + |> Task.map (fun a -> a.ToArray()) + + /// Unwraps the taskSeq as a Task>. This function is non-blocking. + let toListAsync taskSeq = Internal.toResizeArrayAndMapAsync List.ofSeq taskSeq + + /// Unwraps the taskSeq as a Task>. This function is non-blocking. + let toResizeArrayAsync taskSeq = Internal.toResizeArrayAsync taskSeq + + /// Unwraps the taskSeq as a Task>. This function is non-blocking. + let toIListAsync taskSeq = Internal.toResizeArrayAndMapAsync (fun x -> x :> IList<_>) taskSeq + + /// Unwraps the taskSeq as a Task>. This function is non-blocking, + /// exhausts the sequence and caches the results of the tasks in the sequence. + let toSeqCachedAsync taskSeq = Internal.toResizeArrayAndMapAsync (fun x -> x :> seq<_>) taskSeq + + // + // Convert 'OfXXX' functions + // + /// Create a taskSeq of an array. let ofArray (array: 'T[]) = taskSeq { for c in array do @@ -106,27 +144,6 @@ module TaskSeq = yield c } - // - // Convert 'To' functions - // - - /// Unwraps the taskSeq as a Task>. This function is non-blocking. - let toArrayAsync taskSeq = - Internal.toResizeArrayAsync taskSeq - |> Task.map (fun a -> a.ToArray()) - - /// Unwraps the taskSeq as a Task>. This function is non-blocking. - let toListAsync taskSeq = Internal.toResizeArrayAndMapAsync List.ofSeq taskSeq - - /// Unwraps the taskSeq as a Task>. This function is non-blocking. - let toResizeArrayAsync taskSeq = Internal.toResizeArrayAsync taskSeq - - /// Unwraps the taskSeq as a Task>. This function is non-blocking. - let toIListAsync taskSeq = Internal.toResizeArrayAndMapAsync (fun x -> x :> IList<_>) taskSeq - - /// Unwraps the taskSeq as a Task>. This function is non-blocking, - /// exhausts the sequence and caches the results of the tasks in the sequence. - let toSeqCachedAsync taskSeq = Internal.toResizeArrayAndMapAsync (fun x -> x :> seq<_>) taskSeq // // iter/map/collect functions From 4e61d5604392c08b76c5e81aef8e2d660a08f92c Mon Sep 17 00:00:00 2001 From: Abel Braaksma Date: Wed, 12 Oct 2022 18:51:56 +0200 Subject: [PATCH 2/2] Fix tests --- src/FSharpy.TaskSeq.Test/TaskSeq.ToXXX.Tests.fs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.ToXXX.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.ToXXX.Tests.fs index 8afe9f48..27ac1230 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.ToXXX.Tests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.ToXXX.Tests.fs @@ -24,51 +24,51 @@ open System.Collections.Generic let ``TaskSeq-toArrayAsync should succeed`` () = task { let tq = createDummyTaskSeq 10 let! (results: _[]) = tq |> TaskSeq.toArrayAsync - results |> should equal [| 0..9 |] + results |> should equal [| 1..10 |] } [] let ``TaskSeq-toListAsync should succeed`` () = task { let tq = createDummyTaskSeq 10 let! (results: list<_>) = tq |> TaskSeq.toListAsync - results |> should equal [ 0..9 ] + results |> should equal [ 1..10 ] } [] let ``TaskSeq-toSeqCachedAsync should succeed`` () = task { let tq = createDummyTaskSeq 10 let! (results: seq<_>) = tq |> TaskSeq.toSeqCachedAsync - results |> Seq.toArray |> should equal [| 0..9 |] + results |> Seq.toArray |> should equal [| 1..10 |] } [] let ``TaskSeq-toIListAsync should succeed`` () = task { let tq = createDummyTaskSeq 10 let! (results: IList<_>) = tq |> TaskSeq.toIListAsync - results |> Seq.toArray |> should equal [| 0..9 |] + results |> Seq.toArray |> should equal [| 1..10 |] } [] let ``TaskSeq-toResizeArray should succeed`` () = task { let tq = createDummyTaskSeq 10 let! (results: ResizeArray<_>) = tq |> TaskSeq.toResizeArrayAsync - results |> should equal [| 0..9 |] + results |> Seq.toArray |> should equal [| 1..10 |] } [] let ``TaskSeq-toArray should succeed and be blocking`` () = let tq = createDummyTaskSeq 10 let (results: _[]) = tq |> TaskSeq.toArray - results |> should equal [| 0..9 |] + results |> should equal [| 1..10 |] [] let ``TaskSeq-toList should succeed and be blocking`` () = let tq = createDummyTaskSeq 10 let (results: list<_>) = tq |> TaskSeq.toList - results |> should equal [ 0..9 ] + results |> should equal [ 1..10 ] [] let ``TaskSeq-toSeqCached should succeed and be blocking`` () = let tq = createDummyTaskSeq 10 let (results: seq<_>) = tq |> TaskSeq.toSeqCached - results |> Seq.toArray |> should equal [| 0..9 |] + results |> Seq.toArray |> should equal [| 1..10 |]