From c07c1eb1b66ecf537cc1a7be9ec6bcc2d6fa8a33 Mon Sep 17 00:00:00 2001 From: Abel Braaksma Date: Fri, 14 Oct 2022 22:12:01 +0200 Subject: [PATCH 1/5] Switch on test timeouts on individual tests, even though it has a warning for parallel running --- .../TaskSeq.Choose.Tests.fs | 10 ++-- .../TaskSeq.Collect.Tests.fs | 10 ++-- .../TaskSeq.Filter.Tests.fs | 8 +-- .../TaskSeq.Find.Tests.fs | 50 +++++++++---------- .../TaskSeq.Fold.Tests.fs | 8 +-- .../TaskSeq.Head.Tests.fs | 14 +++--- .../TaskSeq.Item.Tests.fs | 46 ++++++++--------- .../TaskSeq.Iter.Tests.fs | 8 +-- .../TaskSeq.Last.Tests.fs | 14 +++--- src/FSharpy.TaskSeq.Test/TaskSeq.Map.Tests.fs | 4 +- .../TaskSeq.OfXXX.Tests.fs | 18 +++---- .../TaskSeq.Pick.Tests.fs | 50 +++++++++---------- src/FSharpy.TaskSeq.Test/TaskSeq.PocTests.fs | 10 ++-- src/FSharpy.TaskSeq.Test/TaskSeq.Tests.CE.fs | 24 ++++----- .../TaskSeq.Tests.Other.fs | 6 +-- .../TaskSeq.ToXXX.Tests.fs | 16 +++--- 16 files changed, 148 insertions(+), 148 deletions(-) diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.Choose.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Choose.Tests.fs index c70bbd7e..cae438ac 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.Choose.Tests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Choose.Tests.fs @@ -9,14 +9,14 @@ open FsToolkit.ErrorHandling open FSharpy -[] +[] let ``ZHang timeout test`` () = task { let! empty = Task.Delay 30 empty |> should be Null } -[] +[] let ``TaskSeq-choose on an empty sequence`` () = task { let! empty = TaskSeq.empty @@ -26,7 +26,7 @@ let ``TaskSeq-choose on an empty sequence`` () = task { List.isEmpty empty |> should be True } -[] +[] let ``TaskSeq-chooseAsync on an empty sequence`` () = task { let! empty = TaskSeq.empty @@ -36,7 +36,7 @@ let ``TaskSeq-chooseAsync on an empty sequence`` () = task { List.isEmpty empty |> should be True } -[] +[] let ``TaskSeq-choose can convert and filter`` () = task { let! alphabet = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -46,7 +46,7 @@ let ``TaskSeq-choose can convert and filter`` () = task { String alphabet |> should equal "ABCDEFGHIJKLMNOPQRSTUVWXYZ" } -[] +[] let ``TaskSeq-chooseAsync can convert and filter`` () = task { let! alphabet = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.Collect.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Collect.Tests.fs index 3d405e2d..604af79a 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.Collect.Tests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Collect.Tests.fs @@ -6,7 +6,7 @@ open FsToolkit.ErrorHandling open FSharpy -[] +[] let ``TaskSeq-collect operates in correct order`` () = task { let! sq = createDummyTaskSeq 10 @@ -22,7 +22,7 @@ let ``TaskSeq-collect operates in correct order`` () = task { |> should equal "ABBCCDDEEFFGGHHIIJJK" } -[] +[] let ``TaskSeq-collectSeq operates in correct order`` () = task { let! sq = createDummyTaskSeq 10 @@ -38,7 +38,7 @@ let ``TaskSeq-collectSeq operates in correct order`` () = task { |> should equal "ABBCCDDEEFFGGHHIIJJK" } -[] +[] let ``TaskSeq-collect with empty task sequences`` () = task { let! sq = createDummyTaskSeq 10 @@ -48,7 +48,7 @@ let ``TaskSeq-collect with empty task sequences`` () = task { Seq.isEmpty sq |> should be True } -[] +[] let ``TaskSeq-collectSeq with empty sequences`` () = task { let! sq = createDummyTaskSeq 10 @@ -58,7 +58,7 @@ let ``TaskSeq-collectSeq with empty sequences`` () = task { 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.Filter.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Filter.Tests.fs index 79c413cd..5d00523f 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.Filter.Tests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Filter.Tests.fs @@ -7,7 +7,7 @@ open FsToolkit.ErrorHandling open FSharpy -[] +[] let ``TaskSeq-filter on an empty sequence`` () = task { let! empty = TaskSeq.empty @@ -17,7 +17,7 @@ let ``TaskSeq-filter on an empty sequence`` () = task { List.isEmpty empty |> should be True } -[] +[] let ``TaskSeq-filterAsync on an empty sequence`` () = task { let! empty = TaskSeq.empty @@ -27,7 +27,7 @@ let ``TaskSeq-filterAsync on an empty sequence`` () = task { List.isEmpty empty |> should be True } -[] +[] let ``TaskSeq-filter filters correctly`` () = task { let! alphabet = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -40,7 +40,7 @@ let ``TaskSeq-filter filters correctly`` () = task { String alphabet |> should equal "Z[\]^_`abcdefghijklmnopqr" } -[] +[] let ``TaskSeq-filterAsync filters correctly`` () = task { let! alphabet = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.Find.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Find.Tests.fs index dcf58b28..76af67d2 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.Find.Tests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Find.Tests.fs @@ -13,19 +13,19 @@ open System.Collections.Generic // the tryXXX versions are at the bottom half // -[] +[] let ``TaskSeq-find on an empty sequence raises KeyNotFoundException`` () = task { fun () -> TaskSeq.empty |> TaskSeq.find ((=) 12) |> Task.ignore |> should throwAsyncExact typeof } -[] +[] let ``TaskSeq-find on an empty sequence raises KeyNotFoundException - variant`` () = task { fun () -> taskSeq { do () } |> TaskSeq.find ((=) 12) |> Task.ignore |> should throwAsyncExact typeof } -[] +[] let ``TaskSeq-findAsync on an empty sequence raises KeyNotFoundException`` () = task { fun () -> TaskSeq.empty @@ -34,7 +34,7 @@ let ``TaskSeq-findAsync on an empty sequence raises KeyNotFoundException`` () = |> should throwAsyncExact typeof } -[] +[] let ``TaskSeq-find sad path raises KeyNotFoundException`` () = task { fun () -> createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -44,7 +44,7 @@ let ``TaskSeq-find sad path raises KeyNotFoundException`` () = task { |> should throwAsyncExact typeof } -[] +[] let ``TaskSeq-findAsync sad path raises KeyNotFoundException`` () = task { fun () -> createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -54,7 +54,7 @@ let ``TaskSeq-findAsync sad path raises KeyNotFoundException`` () = task { |> should throwAsyncExact typeof } -[] +[] let ``TaskSeq-find sad path raises KeyNotFoundException variant`` () = task { fun () -> createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -64,7 +64,7 @@ let ``TaskSeq-find sad path raises KeyNotFoundException variant`` () = task { |> should throwAsyncExact typeof } -[] +[] let ``TaskSeq-findAsync sad path raises KeyNotFoundException variant`` () = task { fun () -> createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -75,7 +75,7 @@ let ``TaskSeq-findAsync sad path raises KeyNotFoundException variant`` () = task } -[] +[] let ``TaskSeq-find happy path middle of seq`` () = task { let! twentyFive = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -84,7 +84,7 @@ let ``TaskSeq-find happy path middle of seq`` () = task { twentyFive |> should equal 25 } -[] +[] let ``TaskSeq-findAsync happy path middle of seq`` () = task { let! twentyFive = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -93,7 +93,7 @@ let ``TaskSeq-findAsync happy path middle of seq`` () = task { twentyFive |> should equal 25 } -[] +[] let ``TaskSeq-find happy path first item of seq`` () = task { let! first = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -102,7 +102,7 @@ let ``TaskSeq-find happy path first item of seq`` () = task { first |> should equal 1 } -[] +[] let ``TaskSeq-findAsync happy path first item of seq`` () = task { let! first = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -111,7 +111,7 @@ let ``TaskSeq-findAsync happy path first item of seq`` () = task { first |> should equal 1 } -[] +[] let ``TaskSeq-find happy path last item of seq`` () = task { let! last = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -120,7 +120,7 @@ let ``TaskSeq-find happy path last item of seq`` () = task { last |> should equal 50 } -[] +[] let ``TaskSeq-findAsync happy path last item of seq`` () = task { let! last = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -134,13 +134,13 @@ let ``TaskSeq-findAsync happy path last item of seq`` () = task { // TaskSeq.tryFindAsync // -[] +[] let ``TaskSeq-tryFind on an empty sequence returns None`` () = task { let! nothing = TaskSeq.empty |> TaskSeq.tryFind ((=) 12) nothing |> should be None' } -[] +[] let ``TaskSeq-tryFindAsync on an empty sequence returns None`` () = task { let! nothing = TaskSeq.empty @@ -149,7 +149,7 @@ let ``TaskSeq-tryFindAsync on an empty sequence returns None`` () = task { nothing |> should be None' } -[] +[] let ``TaskSeq-tryFind sad path returns None`` () = task { let! nothing = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -158,7 +158,7 @@ let ``TaskSeq-tryFind sad path returns None`` () = task { nothing |> should be None' } -[] +[] let ``TaskSeq-tryFindAsync sad path return None`` () = task { let! nothing = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -167,7 +167,7 @@ let ``TaskSeq-tryFindAsync sad path return None`` () = task { nothing |> should be None' } -[] +[] let ``TaskSeq-tryFind sad path returns None variant`` () = task { let! nothing = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -176,7 +176,7 @@ let ``TaskSeq-tryFind sad path returns None variant`` () = task { nothing |> should be None' } -[] +[] let ``TaskSeq-tryFindAsync sad path return None - variant`` () = task { let! nothing = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -186,7 +186,7 @@ let ``TaskSeq-tryFindAsync sad path return None - variant`` () = task { } -[] +[] let ``TaskSeq-tryFind happy path middle of seq`` () = task { let! twentyFive = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -196,7 +196,7 @@ let ``TaskSeq-tryFind happy path middle of seq`` () = task { twentyFive |> should equal (Some 25) } -[] +[] let ``TaskSeq-tryFindAsync happy path middle of seq`` () = task { let! twentyFive = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -206,7 +206,7 @@ let ``TaskSeq-tryFindAsync happy path middle of seq`` () = task { twentyFive |> should equal (Some 25) } -[] +[] let ``TaskSeq-tryFind happy path first item of seq`` () = task { let! first = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -216,7 +216,7 @@ let ``TaskSeq-tryFind happy path first item of seq`` () = task { first |> should equal (Some 1) } -[] +[] let ``TaskSeq-tryFindAsync happy path first item of seq`` () = task { let! first = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -226,7 +226,7 @@ let ``TaskSeq-tryFindAsync happy path first item of seq`` () = task { first |> should equal (Some 1) } -[] +[] let ``TaskSeq-tryFind happy path last item of seq`` () = task { let! last = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -236,7 +236,7 @@ let ``TaskSeq-tryFind happy path last item of seq`` () = task { last |> should equal (Some 50) } -[] +[] let ``TaskSeq-tryFindAsync happy path last item of seq`` () = task { let! last = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.Fold.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Fold.Tests.fs index fa6e310b..3ca001b3 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.Fold.Tests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Fold.Tests.fs @@ -8,7 +8,7 @@ open FsToolkit.ErrorHandling open FSharpy -[] +[] let ``TaskSeq-fold folds with every item`` () = task { let! alphabet = createDummyTaskSeqWith 50L<µs> 1000L<µs> 26 @@ -18,7 +18,7 @@ let ``TaskSeq-fold folds with every item`` () = task { |> should equal "ABCDEFGHIJKLMNOPQRSTUVWXYZ" } -[] +[] let ``TaskSeq-foldAsync folds with every item`` () = task { let! alphabet = createDummyTaskSeqWith 50L<µs> 1000L<µs> 26 @@ -30,7 +30,7 @@ let ``TaskSeq-foldAsync folds with every item`` () = task { |> should equal "ABCDEFGHIJKLMNOPQRSTUVWXYZ" } -[] +[] let ``TaskSeq-fold takes state on empty IAsyncEnumberable`` () = task { let! empty = TaskSeq.empty @@ -39,7 +39,7 @@ let ``TaskSeq-fold takes state on empty IAsyncEnumberable`` () = task { empty |> should equal '_' } -[] +[] let ``TaskSeq-foldAsync takes state on empty IAsyncEnumerable`` () = task { let! alphabet = TaskSeq.empty diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.Head.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Head.Tests.fs index f11ad2ac..afaa49b4 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.Head.Tests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Head.Tests.fs @@ -8,38 +8,38 @@ open FsToolkit.ErrorHandling open FSharpy -[] +[] let ``TaskSeq-head throws on empty sequences`` () = task { fun () -> TaskSeq.empty |> TaskSeq.head |> Task.ignore |> should throwAsyncExact typeof } -[] +[] let ``TaskSeq-head throws on empty sequences - variant`` () = task { fun () -> taskSeq { do () } |> TaskSeq.head |> Task.ignore |> should throwAsyncExact typeof } -[] +[] let ``TaskSeq-tryHead returns None on empty sequences`` () = task { let! nothing = TaskSeq.empty |> TaskSeq.tryHead nothing |> should be None' } -[] +[] let ``TaskSeq-head gets the first item in a longer sequence`` () = task { let! head = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 |> TaskSeq.head head |> should equal 1 } -[] +[] let ``TaskSeq-head gets the only item in a singleton sequence`` () = task { let! head = taskSeq { yield 10 } |> TaskSeq.head head |> should equal 10 } -[] +[] let ``TaskSeq-tryHead gets the first item in a longer sequence`` () = task { let! head = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -49,7 +49,7 @@ let ``TaskSeq-tryHead gets the first item in a longer sequence`` () = task { head |> should equal (Some 1) } -[] +[] let ``TaskSeq-tryHead gets the only item in a singleton sequence`` () = task { let! head = taskSeq { yield 10 } |> TaskSeq.tryHead head |> should be Some' diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.Item.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Item.Tests.fs index 85c058fc..00dcf353 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.Item.Tests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Item.Tests.fs @@ -8,19 +8,19 @@ open FsToolkit.ErrorHandling open FSharpy -[] +[] let ``TaskSeq-item throws on empty sequences`` () = task { fun () -> TaskSeq.empty |> TaskSeq.item 0 |> Task.ignore |> should throwAsyncExact typeof } -[] +[] let ``TaskSeq-item throws on empty sequence - variant`` () = task { fun () -> taskSeq { do () } |> TaskSeq.item 50000 |> Task.ignore |> should throwAsyncExact typeof } -[] +[] let ``TaskSeq-item throws when not found`` () = task { fun () -> createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -29,7 +29,7 @@ let ``TaskSeq-item throws when not found`` () = task { |> should throwAsyncExact typeof } -[] +[] let ``TaskSeq-item throws when not found - variant`` () = task { fun () -> createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -38,13 +38,13 @@ let ``TaskSeq-item throws when not found - variant`` () = task { |> should throwAsyncExact typeof } -[] +[] let ``TaskSeq-item throws when accessing 2nd item in singleton sequence`` () = task { fun () -> taskSeq { yield 10 } |> TaskSeq.item 1 |> Task.ignore // zero-based! |> should throwAsyncExact typeof } -[] +[] let ``TaskSeq-item always throws with negative values`` () = task { let make50 () = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -70,19 +70,19 @@ let ``TaskSeq-item always throws with negative values`` () = task { |> should throwAsyncExact typeof } -[] +[] let ``TaskSeq-tryItem returns None on empty sequences`` () = task { let! nothing = TaskSeq.empty |> TaskSeq.tryItem 0 nothing |> should be None' } -[] +[] let ``TaskSeq-tryItem returns None on empty sequence - variant`` () = task { let! nothing = taskSeq { do () } |> TaskSeq.tryItem 50000 nothing |> should be None' } -[] +[] let ``TaskSeq-tryItem returns None when not found`` () = task { let! nothing = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -91,7 +91,7 @@ let ``TaskSeq-tryItem returns None when not found`` () = task { nothing |> should be None' } -[] +[] let ``TaskSeq-tryItem returns None when not found - variant`` () = task { let! nothing = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -100,13 +100,13 @@ let ``TaskSeq-tryItem returns None when not found - variant`` () = task { nothing |> should be None' } -[] +[] let ``TaskSeq-tryItem returns None when accessing 2nd item in singleton sequence`` () = task { let! nothing = taskSeq { yield 10 } |> TaskSeq.tryItem 1 // zero-based! nothing |> should be None' } -[] +[] let ``TaskSeq-tryItem returns None throws with negative values`` () = task { let make50 () = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -129,7 +129,7 @@ let ``TaskSeq-tryItem returns None throws with negative values`` () = task { nothing |> should be None' } -[] +[] let ``TaskSeq-item can get the first item in a longer sequence`` () = task { let! head = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -138,7 +138,7 @@ let ``TaskSeq-item can get the first item in a longer sequence`` () = task { head |> should equal 1 } -[] +[] let ``TaskSeq-item can get the last item in a longer sequence`` () = task { let! head = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -147,13 +147,13 @@ let ``TaskSeq-item can get the last item in a longer sequence`` () = task { head |> should equal 50 } -[] +[] let ``TaskSeq-item can get the first item in a singleton sequence`` () = task { let! head = taskSeq { yield 10 } |> TaskSeq.item 0 // zero-based index! head |> should equal 10 } -[] +[] let ``TaskSeq-tryItem can get the first item in a longer sequence`` () = task { let! head = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -163,7 +163,7 @@ let ``TaskSeq-tryItem can get the first item in a longer sequence`` () = task { head |> should equal (Some 1) } -[] +[] let ``TaskSeq-tryItem in a very long sequence (5_000 items - slow variant)`` () = task { let! head = createDummyDirectTaskSeq 5_001 |> TaskSeq.tryItem 5_000 // zero-based! @@ -171,7 +171,7 @@ let ``TaskSeq-tryItem in a very long sequence (5_000 items - slow variant)`` () head |> should equal (Some 5_001) } -[] +[] let ``TaskSeq-tryItem in a very long sequence (50_000 items - slow variant)`` () = task { let! head = createDummyDirectTaskSeq 50_001 |> TaskSeq.tryItem 50_000 // zero-based! @@ -179,7 +179,7 @@ let ``TaskSeq-tryItem in a very long sequence (50_000 items - slow variant)`` () head |> should equal (Some 50_001) } -[] +[] let ``TaskSeq-tryItem in a very long sequence (50_000 items - fast variant)`` () = task { let! head = // using taskSeq instead of the delayed-task approach above, which creates an extra closure for each @@ -194,7 +194,7 @@ let ``TaskSeq-tryItem in a very long sequence (50_000 items - fast variant)`` () head |> should equal (Some 50_000) } -[] +[] let ``TaskSeq-tryItem in a very long sequence (50_000 items - using sync Seq)`` () = task { // this test is just for smoke-test perf comparison with TaskSeq above let head = @@ -208,7 +208,7 @@ let ``TaskSeq-tryItem in a very long sequence (50_000 items - using sync Seq)`` head |> should equal (Some 50_000) } -[] +[] let ``TaskSeq-tryItem in a very long sequence (500_000 items - fast variant)`` () = task { let! head = taskSeq { @@ -221,7 +221,7 @@ let ``TaskSeq-tryItem in a very long sequence (500_000 items - fast variant)`` ( head |> should equal (Some 500_000) } -[] +[] let ``TaskSeq-tryItem in a very long sequence (500_000 items - using sync Seq)`` () = task { // this test is just for smoke-test perf comparison with TaskSeq above let head = @@ -235,7 +235,7 @@ let ``TaskSeq-tryItem in a very long sequence (500_000 items - using sync Seq)`` head |> should equal (Some 500_000) } -[] +[] let ``TaskSeq-tryItem gets the first item in a singleton sequence`` () = task { let! head = taskSeq { yield 10 } |> TaskSeq.tryItem 0 // zero-based! head |> should be Some' diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.Iter.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Iter.Tests.fs index f8418b21..ca5faad9 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.Iter.Tests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Iter.Tests.fs @@ -7,7 +7,7 @@ open FsToolkit.ErrorHandling open FSharpy -[] +[] let ``TaskSeq-iteri should go over all items`` () = task { let tq = createDummyTaskSeq 10 let mutable sum = 0 @@ -15,7 +15,7 @@ let ``TaskSeq-iteri should go over all items`` () = task { 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 @@ -23,7 +23,7 @@ let ``TaskSeq-iter should go over all items`` () = task { 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 @@ -35,7 +35,7 @@ let ``TaskSeq-iteriAsync should go over all items`` () = task { 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 diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.Last.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Last.Tests.fs index 8453457e..5db77a02 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.Last.Tests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Last.Tests.fs @@ -8,38 +8,38 @@ open FsToolkit.ErrorHandling open FSharpy -[] +[] let ``TaskSeq-last throws on empty sequences`` () = task { fun () -> TaskSeq.empty |> TaskSeq.last |> Task.ignore |> should throwAsyncExact typeof } -[] +[] let ``TaskSeq-last throws on empty sequences - variant`` () = task { fun () -> taskSeq { do () } |> TaskSeq.last |> Task.ignore |> should throwAsyncExact typeof } -[] +[] let ``TaskSeq-tryLast returns None on empty sequences`` () = task { let! nothing = TaskSeq.empty |> TaskSeq.tryLast nothing |> should be None' } -[] +[] let ``TaskSeq-last gets the last item in a longer sequence`` () = task { let! last = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 |> TaskSeq.last last |> should equal 50 } -[] +[] let ``TaskSeq-last gets the only item in a singleton sequence`` () = task { let! last = taskSeq { yield 10 } |> TaskSeq.last last |> should equal 10 } -[] +[] let ``TaskSeq-tryLast gets the last item in a longer sequence`` () = task { let! last = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -49,7 +49,7 @@ let ``TaskSeq-tryLast gets the last item in a longer sequence`` () = task { last |> should equal (Some 50) } -[] +[] let ``TaskSeq-tryLast gets the only item in a singleton sequence`` () = task { let! last = taskSeq { yield 10 } |> TaskSeq.tryLast last |> should be Some' diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.Map.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Map.Tests.fs index 46dc1154..a85e7274 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.Map.Tests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Map.Tests.fs @@ -7,7 +7,7 @@ open FsToolkit.ErrorHandling open FSharpy -[] +[] let ``TaskSeq-map maps in correct order`` () = task { let! sq = createDummyTaskSeq 10 @@ -20,7 +20,7 @@ let ``TaskSeq-map maps in correct order`` () = task { |> should equal "ABCDEFGHIJ" } -[] +[] let ``TaskSeq-mapAsync maps in correct order`` () = task { let! sq = createDummyTaskSeq 10 diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.OfXXX.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.OfXXX.Tests.fs index 0cb51387..6e5be915 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.OfXXX.Tests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.OfXXX.Tests.fs @@ -11,47 +11,47 @@ let validateSequence sq = task { 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.Pick.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Pick.Tests.fs index 6e8c63de..10d619ee 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.Pick.Tests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Pick.Tests.fs @@ -15,7 +15,7 @@ open FSharpy // the tryXXX versions are at the bottom half // -[] +[] let ``TaskSeq-pick on an empty sequence raises KeyNotFoundException`` () = task { fun () -> TaskSeq.empty @@ -24,7 +24,7 @@ let ``TaskSeq-pick on an empty sequence raises KeyNotFoundException`` () = task |> should throwAsyncExact typeof } -[] +[] let ``TaskSeq-pick on an empty sequence raises KeyNotFoundException - variant`` () = task { fun () -> taskSeq { do () } @@ -33,7 +33,7 @@ let ``TaskSeq-pick on an empty sequence raises KeyNotFoundException - variant`` |> should throwAsyncExact typeof } -[] +[] let ``TaskSeq-pickAsync on an empty sequence raises KeyNotFoundException`` () = task { fun () -> TaskSeq.empty @@ -42,7 +42,7 @@ let ``TaskSeq-pickAsync on an empty sequence raises KeyNotFoundException`` () = |> should throwAsyncExact typeof } -[] +[] let ``TaskSeq-pick sad path raises KeyNotFoundException`` () = task { fun () -> createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -52,7 +52,7 @@ let ``TaskSeq-pick sad path raises KeyNotFoundException`` () = task { |> should throwAsyncExact typeof } -[] +[] let ``TaskSeq-pickAsync sad path raises KeyNotFoundException`` () = task { fun () -> createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -62,7 +62,7 @@ let ``TaskSeq-pickAsync sad path raises KeyNotFoundException`` () = task { |> should throwAsyncExact typeof } -[] +[] let ``TaskSeq-pick sad path raises KeyNotFoundException variant`` () = task { fun () -> createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -72,7 +72,7 @@ let ``TaskSeq-pick sad path raises KeyNotFoundException variant`` () = task { |> should throwAsyncExact typeof } -[] +[] let ``TaskSeq-pickAsync sad path raises KeyNotFoundException variant`` () = task { fun () -> createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -83,7 +83,7 @@ let ``TaskSeq-pickAsync sad path raises KeyNotFoundException variant`` () = task } -[] +[] let ``TaskSeq-pick happy path middle of seq`` () = task { let! twentyFive = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -92,7 +92,7 @@ let ``TaskSeq-pick happy path middle of seq`` () = task { twentyFive |> should equal "foo" } -[] +[] let ``TaskSeq-pickAsync happy path middle of seq`` () = task { let! twentyFive = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -101,7 +101,7 @@ let ``TaskSeq-pickAsync happy path middle of seq`` () = task { twentyFive |> should equal "foo" } -[] +[] let ``TaskSeq-pick happy path first item of seq`` () = task { let! first = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -110,7 +110,7 @@ let ``TaskSeq-pick happy path first item of seq`` () = task { first |> should equal "first1" } -[] +[] let ``TaskSeq-pickAsync happy path first item of seq`` () = task { let! first = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -119,7 +119,7 @@ let ``TaskSeq-pickAsync happy path first item of seq`` () = task { first |> should equal "first1" } -[] +[] let ``TaskSeq-pick happy path last item of seq`` () = task { let! last = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -128,7 +128,7 @@ let ``TaskSeq-pick happy path last item of seq`` () = task { last |> should equal "last50" } -[] +[] let ``TaskSeq-pickAsync happy path last item of seq`` () = task { let! last = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -142,7 +142,7 @@ let ``TaskSeq-pickAsync happy path last item of seq`` () = task { // TaskSeq.tryPickAsync // -[] +[] let ``TaskSeq-tryPick on an empty sequence returns None`` () = task { let! nothing = TaskSeq.empty @@ -151,7 +151,7 @@ let ``TaskSeq-tryPick on an empty sequence returns None`` () = task { nothing |> should be None' } -[] +[] let ``TaskSeq-tryPickAsync on an empty sequence returns None`` () = task { let! nothing = TaskSeq.empty @@ -160,7 +160,7 @@ let ``TaskSeq-tryPickAsync on an empty sequence returns None`` () = task { nothing |> should be None' } -[] +[] let ``TaskSeq-tryPick sad path returns None`` () = task { let! nothing = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -169,7 +169,7 @@ let ``TaskSeq-tryPick sad path returns None`` () = task { nothing |> should be None' } -[] +[] let ``TaskSeq-tryPickAsync sad path return None`` () = task { let! nothing = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -178,7 +178,7 @@ let ``TaskSeq-tryPickAsync sad path return None`` () = task { nothing |> should be None' } -[] +[] let ``TaskSeq-tryPick sad path returns None variant`` () = task { let! nothing = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -187,7 +187,7 @@ let ``TaskSeq-tryPick sad path returns None variant`` () = task { nothing |> should be None' } -[] +[] let ``TaskSeq-tryPickAsync sad path return None - variant`` () = task { let! nothing = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -197,7 +197,7 @@ let ``TaskSeq-tryPickAsync sad path return None - variant`` () = task { } -[] +[] let ``TaskSeq-tryPick happy path middle of seq`` () = task { let! twentyFive = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -207,7 +207,7 @@ let ``TaskSeq-tryPick happy path middle of seq`` () = task { twentyFive |> should equal (Some "foo25") } -[] +[] let ``TaskSeq-tryPickAsync happy path middle of seq`` () = task { let! twentyFive = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -217,7 +217,7 @@ let ``TaskSeq-tryPickAsync happy path middle of seq`` () = task { twentyFive |> should equal (Some "foo25") } -[] +[] let ``TaskSeq-tryPick happy path first item of seq`` () = task { let! first = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -227,7 +227,7 @@ let ``TaskSeq-tryPick happy path first item of seq`` () = task { first |> should equal (Some "foo1") } -[] +[] let ``TaskSeq-tryPickAsync happy path first item of seq`` () = task { let! first = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -237,7 +237,7 @@ let ``TaskSeq-tryPickAsync happy path first item of seq`` () = task { first |> should equal (Some "foo1") } -[] +[] let ``TaskSeq-tryPick happy path last item of seq`` () = task { let! last = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 @@ -247,7 +247,7 @@ let ``TaskSeq-tryPick happy path last item of seq`` () = task { last |> should equal (Some "foo50") } -[] +[] let ``TaskSeq-tryPickAsync happy path last item of seq`` () = task { let! last = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.PocTests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.PocTests.fs index 23d4c003..fe23de47 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.PocTests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.PocTests.fs @@ -17,14 +17,14 @@ open FSharpy module ``PoC's for seq of tasks`` = - [] + [] let ``Good: Show joining tasks with continuation is good`` () = task { // acts like a fold let! results = createAndJoinMultipleTasks 10 joinWithContinuation results |> should equal 10 } - [] + [] let ``Good: Show that joining tasks with 'bind' in task CE is good`` () = task { let! tasks = createAndJoinMultipleTasks 10 joinIdentityDelayed @@ -40,7 +40,7 @@ module ``PoC's for seq of tasks`` = results |> should equal <| Array.init len ((+) 1) } - [] + [] let ``Good: Show that joining tasks with 'taskSeq' is good`` () = task { let! tasks = createAndJoinMultipleTasks 10 joinIdentityDelayed @@ -57,7 +57,7 @@ module ``PoC's for seq of tasks`` = <| Array.init (Array.length results) ((+) 1) } - [] + [] let ``Bad: Show that joining tasks with 'traverseTaskResult' can be bad`` () = task { let! taskList = createAndJoinMultipleTasks 10 joinIdentityHotStarted @@ -74,7 +74,7 @@ module ``PoC's for seq of tasks`` = | Error err -> failwith $"Impossible: {err}" } - [] + [] let ``Bad: Show that joining tasks as a list of tasks can be bad`` () = task { let! taskList = createAndJoinMultipleTasks 10 joinIdentityHotStarted diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.Tests.CE.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Tests.CE.fs index a8d4a0dc..d123de8a 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.Tests.CE.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Tests.CE.fs @@ -1,4 +1,4 @@ -module FSharpy.Tests.``taskSeq Computation Expression`` +module FSharpy.Tests.``taskSeq Computation Expression`` open Xunit open FsUnit.Xunit @@ -9,7 +9,7 @@ open System.Threading.Tasks open System.Diagnostics -[] +[] let ``CE taskSeq with several yield!`` () = task { let tskSeq = taskSeq { yield! createDummyTaskSeq 10 @@ -24,7 +24,7 @@ let ``CE taskSeq with several yield!`` () = task { |> should equal (List.concat [ [ 1..10 ]; [ 1..5 ]; [ 1..10 ]; [ 1..5 ] ]) } -[] +[] let ``CE taskSeq with nested yield!`` () = task { let control = seq { yield! [ 1..10 ] @@ -58,7 +58,7 @@ let ``CE taskSeq with nested yield!`` () = task { data |> should haveLength 150 } -[] +[] let ``CE taskSeq with nested deeply yield! perf test 8521 nested tasks`` () = task { let control = seq { yield! [ 1..10 ] @@ -113,7 +113,7 @@ let ``CE taskSeq with nested deeply yield! perf test 8521 nested tasks`` () = ta data |> should equal (List.ofSeq control) } -[] +[] let ``CE taskSeq with several return!`` () = task { // TODO: should we even support this? Traditional 'seq' doesn't. let tskSeq = taskSeq { @@ -128,7 +128,7 @@ let ``CE taskSeq with several return!`` () = task { } -[] +[] let ``CE taskSeq with mixing yield! and yield`` () = task { let tskSeq = taskSeq { yield! createDummyTaskSeq 10 @@ -146,7 +146,7 @@ let ``CE taskSeq with mixing yield! and yield`` () = task { |> should equal (List.concat [ [ 1..10 ]; [ 42 ]; [ 1..5 ]; [ 42 ]; [ 1..10 ]; [ 42 ]; [ 1..5 ] ]) } -[] +[] let ``CE taskSeq: 1000 TaskDelay-delayed tasks using yield!`` () = task { // Smoke performance test // Runs in slightly over half a second (average of spin-wait, plus small overhead) @@ -156,7 +156,7 @@ let ``CE taskSeq: 1000 TaskDelay-delayed tasks using yield!`` () = task { data |> should equal [ 1..1000 ] } -[] +[] let ``CE taskSeq: 1000 sync-running tasks using yield!`` () = task { // Smoke performance test // Runs in a few 10's of ms, because of absense of Task.Delay @@ -166,7 +166,7 @@ let ``CE taskSeq: 1000 sync-running tasks using yield!`` () = task { data |> should equal [ 1..1000 ] } -[] +[] let ``CE taskSeq: 5000 sync-running tasks using yield!`` () = task { // Smoke performance test // Compare with task-ce test below. Uses a no-delay hot-started sequence of tasks. @@ -175,7 +175,7 @@ let ``CE taskSeq: 5000 sync-running tasks using yield!`` () = task { data |> should equal [ 1..5000 ] } -[] +[] let ``CE task: 1000 TaskDelay-delayed tasks using for-loop`` () = task { // Uses SpinWait for effective task-delaying // for smoke-test comparison with taskSeq @@ -189,7 +189,7 @@ let ``CE task: 1000 TaskDelay-delayed tasks using for-loop`` () = task { i |> should equal 1000 } -[] +[] let ``CE task: 1000 list of sync-running tasks using for-loop`` () = task { // runs in a few 10's of ms, because of absense of Task.Delay // for smoke-test comparison with taskSeq @@ -203,7 +203,7 @@ let ``CE task: 1000 list of sync-running tasks using for-loop`` () = task { i |> should equal 1000 } -[] +[] let ``CE task: 5000 list of sync-running tasks using for-loop`` () = task { // runs in a few 100's of ms, because of absense of Task.Delay // for smoke-test comparison with taskSeq diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.Tests.Other.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Tests.Other.fs index bd0100f7..ad18e084 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.Tests.Other.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Tests.Other.fs @@ -7,20 +7,20 @@ open FsToolkit.ErrorHandling open FSharpy -[] +[] let ``TaskSeq-empty returns an empty sequence`` () = task { let! sq = TaskSeq.empty |> TaskSeq.toSeqCachedAsync Seq.isEmpty sq |> should be True Seq.length sq |> should equal 0 } -[] +[] let ``TaskSeq-isEmpty returns true for empty`` () = task { let! isEmpty = TaskSeq.empty |> TaskSeq.isEmpty isEmpty |> should be True } -[] +[] let ``TaskSeq-isEmpty returns false for non-empty`` () = task { let! isEmpty = taskSeq { yield 42 } |> TaskSeq.isEmpty isEmpty |> should be False diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.ToXXX.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.ToXXX.Tests.fs index 5d57feca..c78ef5d2 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.ToXXX.Tests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.ToXXX.Tests.fs @@ -20,54 +20,54 @@ open System.Collections.Generic /// /// //////////////////////////////////////////////////////////////////////////// -[] +[] let ``TaskSeq-toArrayAsync should succeed`` () = task { let tq = createDummyTaskSeq 10 let! (results: _[]) = tq |> TaskSeq.toArrayAsync results |> should equal [| 1..10 |] } -[] +[] let ``TaskSeq-toListAsync should succeed`` () = task { let tq = createDummyTaskSeq 10 let! (results: list<_>) = tq |> TaskSeq.toListAsync 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 [| 1..10 |] } -[] +[] let ``TaskSeq-toIListAsync should succeed`` () = task { let tq = createDummyTaskSeq 10 let! (results: IList<_>) = tq |> TaskSeq.toIListAsync results |> Seq.toArray |> should equal [| 1..10 |] } -[] +[] let ``TaskSeq-toResizeArray should succeed`` () = task { let tq = createDummyTaskSeq 10 let! (results: ResizeArray<_>) = tq |> TaskSeq.toResizeArrayAsync 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 [| 1..10 |] -[] +[] let ``TaskSeq-toList should succeed and be blocking`` () = let tq = createDummyTaskSeq 10 let (results: list<_>) = tq |> TaskSeq.toList results |> should equal [ 1..10 ] -[] +[] let ``TaskSeq-toSeqCached should succeed and be blocking`` () = let tq = createDummyTaskSeq 10 let (results: seq<_>) = tq |> TaskSeq.toSeqCached From 01c083d463dbc8fa6ede0f42962673f5eabd0fd2 Mon Sep 17 00:00:00 2001 From: Abel Braaksma Date: Fri, 14 Oct 2022 22:25:13 +0200 Subject: [PATCH 2/5] Set blame timeout to 60s and re-enable parallelization Re-enable parallelization Blame-timeout to 60s --- .github/workflows/main.yaml | 4 ++-- .github/workflows/test.yaml | 5 ++--- src/FSharpy.TaskSeq.Test/AssemblyInfo.fs | 2 +- src/FSharpy.TaskSeq.v3.ncrunchsolution | 6 ++++++ 4 files changed, 11 insertions(+), 6 deletions(-) create mode 100644 src/FSharpy.TaskSeq.v3.ncrunchsolution diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 7d06a2c3..23f4edaa 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -36,7 +36,7 @@ jobs: uses: actions/setup-dotnet@v3 # build it, test it, pack it - name: Run dotnet test - release - run: dotnet test -c Release --blame-hang-timeout 15000ms --logger "trx;LogFileName=test-results-release.trx" --logger "console;verbosity=detailed" .\src\FSharpy.TaskSeq.Test\FSharpy.TaskSeq.Test.fsproj + run: dotnet test -c Release --blame-hang-timeout 60000ms --logger "trx;LogFileName=test-results-release.trx" --logger "console;verbosity=detailed" .\src\FSharpy.TaskSeq.Test\FSharpy.TaskSeq.Test.fsproj - name: Publish test results - release uses: dorny/test-reporter@v1 if: always() @@ -60,7 +60,7 @@ jobs: uses: actions/setup-dotnet@v3 # build it, test it, pack it - name: Run dotnet test - debug - run: dotnet test -c Debug --blame-hang-timeout 15000ms --logger "trx;LogFileName=test-results-debug.trx" --logger "console;verbosity=detailed" .\src\FSharpy.TaskSeq.Test\FSharpy.TaskSeq.Test.fsproj + run: dotnet test -c Debug --blame-hang-timeout 60000ms --logger "trx;LogFileName=test-results-debug.trx" --logger "console;verbosity=detailed" .\src\FSharpy.TaskSeq.Test\FSharpy.TaskSeq.Test.fsproj - name: Publish test results - debug uses: dorny/test-reporter@v1 if: always() diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 3dac727f..b2739dd3 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -17,7 +17,7 @@ jobs: uses: actions/setup-dotnet@v3 # build it, test it, pack it - name: Run dotnet test - release - run: dotnet test -c Release --blame-hang-timeout 15000ms --logger "trx;LogFileName=test-results-release.trx" --logger "console;verbosity=detailed" .\src\FSharpy.TaskSeq.Test\FSharpy.TaskSeq.Test.fsproj + run: dotnet test -c Release --blame-hang-timeout 60000ms --logger "trx;LogFileName=test-results-release.trx" --logger "console;verbosity=detailed" .\src\FSharpy.TaskSeq.Test\FSharpy.TaskSeq.Test.fsproj - name: Publish test results - release uses: dorny/test-reporter@v1 if: always() @@ -41,7 +41,7 @@ jobs: uses: actions/setup-dotnet@v3 # build it, test it, pack it - name: Run dotnet test - debug - run: dotnet test -c Debug --blame-hang-timeout 15000ms --logger "trx;LogFileName=test-results-debug.trx" --logger "console;verbosity=detailed" .\src\FSharpy.TaskSeq.Test\FSharpy.TaskSeq.Test.fsproj + run: dotnet test -c Debug --blame-hang-timeout 60000ms --logger "trx;LogFileName=test-results-debug.trx" --logger "console;verbosity=detailed" .\src\FSharpy.TaskSeq.Test\FSharpy.TaskSeq.Test.fsproj - name: Publish test results - debug uses: dorny/test-reporter@v1 if: always() @@ -50,4 +50,3 @@ jobs: # this path glob pattern requires forward slashes! path: ./src/FSharpy.TaskSeq.Test/TestResults/test-results-debug.trx reporter: dotnet-trx - \ No newline at end of file diff --git a/src/FSharpy.TaskSeq.Test/AssemblyInfo.fs b/src/FSharpy.TaskSeq.Test/AssemblyInfo.fs index 4f019eaa..c7bd404a 100644 --- a/src/FSharpy.TaskSeq.Test/AssemblyInfo.fs +++ b/src/FSharpy.TaskSeq.Test/AssemblyInfo.fs @@ -2,7 +2,7 @@ namespace FSharpy.Tests open System.Runtime.CompilerServices -[] +[] [] do () diff --git a/src/FSharpy.TaskSeq.v3.ncrunchsolution b/src/FSharpy.TaskSeq.v3.ncrunchsolution new file mode 100644 index 00000000..10420ac9 --- /dev/null +++ b/src/FSharpy.TaskSeq.v3.ncrunchsolution @@ -0,0 +1,6 @@ + + + True + True + + \ No newline at end of file From 3951fbfbb7525de76eccfe75d948a17d0f3349c7 Mon Sep 17 00:00:00 2001 From: Abel Braaksma Date: Sat, 15 Oct 2022 00:38:37 +0200 Subject: [PATCH 3/5] Use Interlocked.Increment for our dummy tasks in the tests --- src/FSharpy.TaskSeq.Test/TestUtils.fs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/FSharpy.TaskSeq.Test/TestUtils.fs b/src/FSharpy.TaskSeq.Test/TestUtils.fs index 0f16920d..10a46e01 100644 --- a/src/FSharpy.TaskSeq.Test/TestUtils.fs +++ b/src/FSharpy.TaskSeq.Test/TestUtils.fs @@ -1,4 +1,4 @@ -namespace FSharpy.Tests +namespace FSharpy.Tests open System open System.Threading @@ -65,12 +65,13 @@ type DummyTaskFactory(µsecMin: int64<µs>, µsecMax: int64<µs>) = //let! _ = Task.Delay(rnd ()) let! _ = Task.Delay 0 // this creates a resume state, which seems more efficient than SpinWait.SpinOnce, see DelayHelper. DelayHelper.delayMicroseconds (rnd ()) false - x <- x + 1 + Interlocked.Increment &x |> ignore + //x <- x + 1 return x // this dereferences the variable } let runTaskDirect i = backgroundTask { - x <- x + 1 + Interlocked.Increment &x |> ignore return x } From 32facc633b2b37bced0fa958d1b32bc63d285bb9 Mon Sep 17 00:00:00 2001 From: Abel Braaksma Date: Sat, 15 Oct 2022 01:06:54 +0200 Subject: [PATCH 4/5] Arduously added logging to each test, there must be a better way to find out whether a test has started (but not finished) Log "starting a test", because xUnit does not do it --- .../TaskSeq.Choose.Tests.fs | 112 ++-- .../TaskSeq.Collect.Tests.fs | 133 ++-- .../TaskSeq.Filter.Tests.fs | 105 ++-- .../TaskSeq.Find.Tests.fs | 556 +++++++++-------- .../TaskSeq.Fold.Tests.fs | 93 +-- .../TaskSeq.Head.Tests.fs | 118 ++-- .../TaskSeq.Item.Tests.fs | 538 +++++++++------- .../TaskSeq.Iter.Tests.fs | 94 +-- .../TaskSeq.Last.Tests.fs | 117 ++-- src/FSharpy.TaskSeq.Test/TaskSeq.Map.Tests.fs | 59 +- .../TaskSeq.OfXXX.Tests.fs | 120 ++-- .../TaskSeq.Pick.Tests.fs | 572 ++++++++++-------- src/FSharpy.TaskSeq.Test/TaskSeq.PocTests.fs | 125 ++-- src/FSharpy.TaskSeq.Test/TaskSeq.Tests.CE.fs | 378 ++++++------ .../TaskSeq.Tests.Other.fs | 48 +- .../TaskSeq.ToXXX.Tests.fs | 123 ++-- src/FSharpy.TaskSeq.Test/TestUtils.fs | 9 + 17 files changed, 1878 insertions(+), 1422 deletions(-) diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.Choose.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Choose.Tests.fs index cae438ac..967b0660 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.Choose.Tests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Choose.Tests.fs @@ -1,4 +1,4 @@ -module FSharpy.Tests.Choose +namespace FSharpy.Tests open System open System.Threading.Tasks @@ -8,50 +8,68 @@ open FsUnit.Xunit open FsToolkit.ErrorHandling open FSharpy +open Xunit.Abstractions -[] -let ``ZHang timeout test`` () = task { - let! empty = Task.Delay 30 - - empty |> should be Null -} - -[] -let ``TaskSeq-choose on an empty sequence`` () = task { - let! empty = - TaskSeq.empty - |> TaskSeq.choose (fun _ -> Some 42) - |> TaskSeq.toListAsync - - List.isEmpty empty |> should be True -} - -[] -let ``TaskSeq-chooseAsync on an empty sequence`` () = task { - let! empty = - TaskSeq.empty - |> TaskSeq.chooseAsync (fun _ -> task { return Some 42 }) - |> TaskSeq.toListAsync - - List.isEmpty empty |> should be True -} - -[] -let ``TaskSeq-choose can convert and filter`` () = task { - let! alphabet = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.choose (fun number -> if number <= 26 then Some(char number + '@') else None) - |> TaskSeq.toArrayAsync - - String alphabet |> should equal "ABCDEFGHIJKLMNOPQRSTUVWXYZ" -} - -[] -let ``TaskSeq-chooseAsync can convert and filter`` () = task { - let! alphabet = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.choose (fun number -> if number <= 26 then Some(char number + '@') else None) - |> TaskSeq.toArrayAsync - - String alphabet |> should equal "ABCDEFGHIJKLMNOPQRSTUVWXYZ" -} + +type Choose(output: ITestOutputHelper) = + + [] + let ``ZHang timeout test`` () = + logStart output + + task { + let! empty = Task.Delay 30 + empty |> should be Null + } + + [] + let ``TaskSeq-choose on an empty sequence`` () = + logStart output + + task { + let! empty = + TaskSeq.empty + |> TaskSeq.choose (fun _ -> Some 42) + |> TaskSeq.toListAsync + + List.isEmpty empty |> should be True + } + + [] + let ``TaskSeq-chooseAsync on an empty sequence`` () = + logStart output + + task { + let! empty = + TaskSeq.empty + |> TaskSeq.chooseAsync (fun _ -> task { return Some 42 }) + |> TaskSeq.toListAsync + + List.isEmpty empty |> should be True + } + + [] + let ``TaskSeq-choose can convert and filter`` () = + logStart output + + task { + let! alphabet = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.choose (fun number -> if number <= 26 then Some(char number + '@') else None) + |> TaskSeq.toArrayAsync + + String alphabet |> should equal "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + } + + [] + let ``TaskSeq-chooseAsync can convert and filter`` () = + logStart output + + task { + let! alphabet = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.choose (fun number -> if number <= 26 then Some(char number + '@') else None) + |> TaskSeq.toArrayAsync + + String alphabet |> should equal "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + } diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.Collect.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Collect.Tests.fs index 604af79a..2ee6a160 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.Collect.Tests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Collect.Tests.fs @@ -1,4 +1,4 @@ -module FSharpy.Tests.Collect +namespace FSharpy.Tests open Xunit open FsUnit.Xunit @@ -6,60 +6,77 @@ 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 -} +type Collect(output) = + + [] + let ``TaskSeq-collect operates in correct order`` () = + logStart output + + 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`` () = + logStart output + + 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`` () = + logStart output + + 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`` () = + logStart output + + task { + let! sq = + createDummyTaskSeq 10 + |> TaskSeq.collectSeq (fun _ -> Seq.empty) + |> TaskSeq.toSeqCachedAsync + + Seq.isEmpty sq |> should be True + } + + [] + let ``TaskSeq-empty is empty`` () = + logStart output + + task { + let! sq = TaskSeq.empty |> TaskSeq.toSeqCachedAsync + Seq.isEmpty sq |> should be True + } diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.Filter.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Filter.Tests.fs index 5d00523f..afb2b5b9 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.Filter.Tests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Filter.Tests.fs @@ -1,4 +1,4 @@ -module FSharpy.Tests.Filter +namespace FSharpy.Tests open System open Xunit @@ -7,47 +7,62 @@ open FsToolkit.ErrorHandling open FSharpy -[] -let ``TaskSeq-filter on an empty sequence`` () = task { - let! empty = - TaskSeq.empty - |> TaskSeq.filter ((=) 12) - |> TaskSeq.toListAsync - - List.isEmpty empty |> should be True -} - -[] -let ``TaskSeq-filterAsync on an empty sequence`` () = task { - let! empty = - TaskSeq.empty - |> TaskSeq.filterAsync (fun x -> task { return x = 12 }) - |> TaskSeq.toListAsync - - List.isEmpty empty |> should be True -} - -[] -let ``TaskSeq-filter filters correctly`` () = task { - let! alphabet = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.filter ((<=) 26) // lambda of '>' etc inverts order of args, so this means 'greater than' - |> TaskSeq.map char - |> TaskSeq.map ((+) '@') - |> TaskSeq.toArrayAsync - - // we filtered all digits above-or-equal-to 26 - String alphabet |> should equal "Z[\]^_`abcdefghijklmnopqr" -} - -[] -let ``TaskSeq-filterAsync filters correctly`` () = task { - let! alphabet = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.filterAsync (fun x -> task { return x <= 26 }) - |> TaskSeq.map char - |> TaskSeq.map ((+) '@') - |> TaskSeq.toArrayAsync - - String alphabet |> should equal "ABCDEFGHIJKLMNOPQRSTUVWXYZ" -} + +type Filter(output) = + + [] + let ``TaskSeq-filter on an empty sequence`` () = + logStart output + + task { + let! empty = + TaskSeq.empty + |> TaskSeq.filter ((=) 12) + |> TaskSeq.toListAsync + + List.isEmpty empty |> should be True + } + + [] + let ``TaskSeq-filterAsync on an empty sequence`` () = + logStart output + + task { + let! empty = + TaskSeq.empty + |> TaskSeq.filterAsync (fun x -> task { return x = 12 }) + |> TaskSeq.toListAsync + + List.isEmpty empty |> should be True + } + + [] + let ``TaskSeq-filter filters correctly`` () = + logStart output + + task { + let! alphabet = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.filter ((<=) 26) // lambda of '>' etc inverts order of args, so this means 'greater than' + |> TaskSeq.map char + |> TaskSeq.map ((+) '@') + |> TaskSeq.toArrayAsync + + // we filtered all digits above-or-equal-to 26 + String alphabet |> should equal "Z[\]^_`abcdefghijklmnopqr" + } + + [] + let ``TaskSeq-filterAsync filters correctly`` () = + logStart output + + task { + let! alphabet = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.filterAsync (fun x -> task { return x <= 26 }) + |> TaskSeq.map char + |> TaskSeq.map ((+) '@') + |> TaskSeq.toArrayAsync + + String alphabet |> should equal "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + } diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.Find.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Find.Tests.fs index 76af67d2..e08bc8cd 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.Find.Tests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Find.Tests.fs @@ -1,4 +1,4 @@ -module FSharpy.Tests.Find +namespace FSharpy.Tests open Xunit open FsUnit.Xunit @@ -7,241 +7,319 @@ open FsToolkit.ErrorHandling open FSharpy open System.Collections.Generic -// -// TaskSeq.find -// TaskSeq.findAsync -// the tryXXX versions are at the bottom half -// - -[] -let ``TaskSeq-find on an empty sequence raises KeyNotFoundException`` () = task { - fun () -> TaskSeq.empty |> TaskSeq.find ((=) 12) |> Task.ignore - |> should throwAsyncExact typeof -} - -[] -let ``TaskSeq-find on an empty sequence raises KeyNotFoundException - variant`` () = task { - fun () -> taskSeq { do () } |> TaskSeq.find ((=) 12) |> Task.ignore - |> should throwAsyncExact typeof -} - -[] -let ``TaskSeq-findAsync on an empty sequence raises KeyNotFoundException`` () = task { - fun () -> - TaskSeq.empty - |> TaskSeq.findAsync (fun x -> task { return x = 12 }) - |> Task.ignore - |> should throwAsyncExact typeof -} - -[] -let ``TaskSeq-find sad path raises KeyNotFoundException`` () = task { - fun () -> - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.find ((=) 0) // dummy tasks sequence starts at 1 - |> Task.ignore - - |> should throwAsyncExact typeof -} - -[] -let ``TaskSeq-findAsync sad path raises KeyNotFoundException`` () = task { - fun () -> - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.findAsync (fun x -> task { return x = 0 }) // dummy tasks sequence starts at 1 - |> Task.ignore - - |> should throwAsyncExact typeof -} - -[] -let ``TaskSeq-find sad path raises KeyNotFoundException variant`` () = task { - fun () -> - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.find ((=) 51) // dummy tasks sequence ends at 50 - |> Task.ignore - - |> should throwAsyncExact typeof -} - -[] -let ``TaskSeq-findAsync sad path raises KeyNotFoundException variant`` () = task { - fun () -> - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.findAsync (fun x -> task { return x = 51 }) // dummy tasks sequence ends at 50 - |> Task.ignore - - |> should throwAsyncExact typeof -} - - -[] -let ``TaskSeq-find happy path middle of seq`` () = task { - let! twentyFive = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.find (fun x -> x < 26 && x > 24) - - twentyFive |> should equal 25 -} - -[] -let ``TaskSeq-findAsync happy path middle of seq`` () = task { - let! twentyFive = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.findAsync (fun x -> task { return x < 26 && x > 24 }) - - twentyFive |> should equal 25 -} - -[] -let ``TaskSeq-find happy path first item of seq`` () = task { - let! first = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.find ((=) 1) // dummy tasks seq starts at 1 - - first |> should equal 1 -} - -[] -let ``TaskSeq-findAsync happy path first item of seq`` () = task { - let! first = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.findAsync (fun x -> task { return x = 1 }) // dummy tasks seq starts at 1 - - first |> should equal 1 -} - -[] -let ``TaskSeq-find happy path last item of seq`` () = task { - let! last = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.find ((=) 50) // dummy tasks seq ends at 50 - - last |> should equal 50 -} - -[] -let ``TaskSeq-findAsync happy path last item of seq`` () = task { - let! last = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.findAsync (fun x -> task { return x = 50 }) // dummy tasks seq ends at 50 - - last |> should equal 50 -} - -// -// TaskSeq.tryFind -// TaskSeq.tryFindAsync -// - -[] -let ``TaskSeq-tryFind on an empty sequence returns None`` () = task { - let! nothing = TaskSeq.empty |> TaskSeq.tryFind ((=) 12) - nothing |> should be None' -} - -[] -let ``TaskSeq-tryFindAsync on an empty sequence returns None`` () = task { - let! nothing = - TaskSeq.empty - |> TaskSeq.tryFindAsync (fun x -> task { return x = 12 }) - - nothing |> should be None' -} - -[] -let ``TaskSeq-tryFind sad path returns None`` () = task { - let! nothing = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.tryFind ((=) 0) // dummy tasks sequence starts at 1 - - nothing |> should be None' -} - -[] -let ``TaskSeq-tryFindAsync sad path return None`` () = task { - let! nothing = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.tryFindAsync (fun x -> task { return x = 0 }) // dummy tasks sequence starts at 1 - - nothing |> should be None' -} - -[] -let ``TaskSeq-tryFind sad path returns None variant`` () = task { - let! nothing = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.tryFind ((<=) 51) // dummy tasks sequence ends at 50 (inverted sign in lambda!) - - nothing |> should be None' -} - -[] -let ``TaskSeq-tryFindAsync sad path return None - variant`` () = task { - let! nothing = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.tryFindAsync (fun x -> task { return x >= 51 }) // dummy tasks sequence ends at 50 - - nothing |> should be None' -} - - -[] -let ``TaskSeq-tryFind happy path middle of seq`` () = task { - let! twentyFive = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.tryFind (fun x -> x < 26 && x > 24) - - twentyFive |> should be Some' - twentyFive |> should equal (Some 25) -} - -[] -let ``TaskSeq-tryFindAsync happy path middle of seq`` () = task { - let! twentyFive = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.tryFindAsync (fun x -> task { return x < 26 && x > 24 }) - - twentyFive |> should be Some' - twentyFive |> should equal (Some 25) -} - -[] -let ``TaskSeq-tryFind happy path first item of seq`` () = task { - let! first = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.tryFind ((=) 1) // dummy tasks seq starts at 1 - - first |> should be Some' - first |> should equal (Some 1) -} - -[] -let ``TaskSeq-tryFindAsync happy path first item of seq`` () = task { - let! first = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.tryFindAsync (fun x -> task { return x = 1 }) // dummy tasks seq starts at 1 - - first |> should be Some' - first |> should equal (Some 1) -} - -[] -let ``TaskSeq-tryFind happy path last item of seq`` () = task { - let! last = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.tryFind ((=) 50) // dummy tasks seq ends at 50 - - last |> should be Some' - last |> should equal (Some 50) -} - -[] -let ``TaskSeq-tryFindAsync happy path last item of seq`` () = task { - let! last = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.tryFindAsync (fun x -> task { return x = 50 }) // dummy tasks seq ends at 50 - - last |> should be Some' - last |> should equal (Some 50) -} + +type Find(output) = + + // + // TaskSeq.find + // TaskSeq.findAsync + // the tryXXX versions are at the bottom half + // + + [] + let ``TaskSeq-find on an empty sequence raises KeyNotFoundException`` () = + logStart output + + task { + fun () -> TaskSeq.empty |> TaskSeq.find ((=) 12) |> Task.ignore + |> should throwAsyncExact typeof + } + + [] + let ``TaskSeq-find on an empty sequence raises KeyNotFoundException - variant`` () = + logStart output + + task { + fun () -> taskSeq { do () } |> TaskSeq.find ((=) 12) |> Task.ignore + |> should throwAsyncExact typeof + } + + [] + let ``TaskSeq-findAsync on an empty sequence raises KeyNotFoundException`` () = + logStart output + + task { + fun () -> + TaskSeq.empty + |> TaskSeq.findAsync (fun x -> task { return x = 12 }) + |> Task.ignore + |> should throwAsyncExact typeof + } + + [] + let ``TaskSeq-find sad path raises KeyNotFoundException`` () = + logStart output + + task { + fun () -> + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.find ((=) 0) // dummy tasks sequence starts at 1 + |> Task.ignore + + |> should throwAsyncExact typeof + } + + [] + let ``TaskSeq-findAsync sad path raises KeyNotFoundException`` () = + logStart output + + task { + fun () -> + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.findAsync (fun x -> task { return x = 0 }) // dummy tasks sequence starts at 1 + |> Task.ignore + + |> should throwAsyncExact typeof + } + + [] + let ``TaskSeq-find sad path raises KeyNotFoundException variant`` () = + logStart output + + task { + fun () -> + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.find ((=) 51) // dummy tasks sequence ends at 50 + |> Task.ignore + + |> should throwAsyncExact typeof + } + + [] + let ``TaskSeq-findAsync sad path raises KeyNotFoundException variant`` () = + logStart output + + task { + fun () -> + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.findAsync (fun x -> task { return x = 51 }) // dummy tasks sequence ends at 50 + |> Task.ignore + + |> should throwAsyncExact typeof + } + + + [] + let ``TaskSeq-find happy path middle of seq`` () = + logStart output + + task { + let! twentyFive = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.find (fun x -> x < 26 && x > 24) + + twentyFive |> should equal 25 + } + + [] + let ``TaskSeq-findAsync happy path middle of seq`` () = + logStart output + + task { + let! twentyFive = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.findAsync (fun x -> task { return x < 26 && x > 24 }) + + twentyFive |> should equal 25 + } + + [] + let ``TaskSeq-find happy path first item of seq`` () = + logStart output + + task { + let! first = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.find ((=) 1) // dummy tasks seq starts at 1 + + first |> should equal 1 + } + + [] + let ``TaskSeq-findAsync happy path first item of seq`` () = + logStart output + + task { + let! first = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.findAsync (fun x -> task { return x = 1 }) // dummy tasks seq starts at 1 + + first |> should equal 1 + } + + [] + let ``TaskSeq-find happy path last item of seq`` () = + logStart output + + task { + let! last = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.find ((=) 50) // dummy tasks seq ends at 50 + + last |> should equal 50 + } + + [] + let ``TaskSeq-findAsync happy path last item of seq`` () = + logStart output + + task { + let! last = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.findAsync (fun x -> task { return x = 50 }) // dummy tasks seq ends at 50 + + last |> should equal 50 + } + + // + // TaskSeq.tryFind + // TaskSeq.tryFindAsync + // + + [] + let ``TaskSeq-tryFind on an empty sequence returns None`` () = + logStart output + + task { + let! nothing = TaskSeq.empty |> TaskSeq.tryFind ((=) 12) + nothing |> should be None' + } + + [] + let ``TaskSeq-tryFindAsync on an empty sequence returns None`` () = + logStart output + + task { + let! nothing = + TaskSeq.empty + |> TaskSeq.tryFindAsync (fun x -> task { return x = 12 }) + + nothing |> should be None' + } + + [] + let ``TaskSeq-tryFind sad path returns None`` () = + logStart output + + task { + let! nothing = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.tryFind ((=) 0) // dummy tasks sequence starts at 1 + + nothing |> should be None' + } + + [] + let ``TaskSeq-tryFindAsync sad path return None`` () = + logStart output + + task { + let! nothing = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.tryFindAsync (fun x -> task { return x = 0 }) // dummy tasks sequence starts at 1 + + nothing |> should be None' + } + + [] + let ``TaskSeq-tryFind sad path returns None variant`` () = + logStart output + + task { + let! nothing = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.tryFind ((<=) 51) // dummy tasks sequence ends at 50 (inverted sign in lambda!) + + nothing |> should be None' + } + + [] + let ``TaskSeq-tryFindAsync sad path return None - variant`` () = + logStart output + + task { + let! nothing = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.tryFindAsync (fun x -> task { return x >= 51 }) // dummy tasks sequence ends at 50 + + nothing |> should be None' + } + + + [] + let ``TaskSeq-tryFind happy path middle of seq`` () = + logStart output + + task { + let! twentyFive = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.tryFind (fun x -> x < 26 && x > 24) + + twentyFive |> should be Some' + twentyFive |> should equal (Some 25) + } + + [] + let ``TaskSeq-tryFindAsync happy path middle of seq`` () = + logStart output + + task { + let! twentyFive = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.tryFindAsync (fun x -> task { return x < 26 && x > 24 }) + + twentyFive |> should be Some' + twentyFive |> should equal (Some 25) + } + + [] + let ``TaskSeq-tryFind happy path first item of seq`` () = + logStart output + + task { + let! first = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.tryFind ((=) 1) // dummy tasks seq starts at 1 + + first |> should be Some' + first |> should equal (Some 1) + } + + [] + let ``TaskSeq-tryFindAsync happy path first item of seq`` () = + logStart output + + task { + let! first = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.tryFindAsync (fun x -> task { return x = 1 }) // dummy tasks seq starts at 1 + + first |> should be Some' + first |> should equal (Some 1) + } + + [] + let ``TaskSeq-tryFind happy path last item of seq`` () = + logStart output + + task { + let! last = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.tryFind ((=) 50) // dummy tasks seq ends at 50 + + last |> should be Some' + last |> should equal (Some 50) + } + + [] + let ``TaskSeq-tryFindAsync happy path last item of seq`` () = + logStart output + + task { + let! last = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.tryFindAsync (fun x -> task { return x = 50 }) // dummy tasks seq ends at 50 + + last |> should be Some' + last |> should equal (Some 50) + } diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.Fold.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Fold.Tests.fs index 3ca001b3..32154896 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.Fold.Tests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Fold.Tests.fs @@ -1,4 +1,4 @@ -module FSharpy.Tests.Fold +namespace FSharpy.Tests open System.Text open Xunit @@ -7,43 +7,56 @@ open FsToolkit.ErrorHandling open FSharpy +type Fold(output) = -[] -let ``TaskSeq-fold folds with every item`` () = task { - let! alphabet = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 26 - |> TaskSeq.fold (fun (state: StringBuilder) item -> state.Append(char item + '@')) (StringBuilder()) - - alphabet.ToString() - |> should equal "ABCDEFGHIJKLMNOPQRSTUVWXYZ" -} - -[] -let ``TaskSeq-foldAsync folds with every item`` () = task { - let! alphabet = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 26 - |> TaskSeq.foldAsync - (fun (state: StringBuilder) item -> task { return state.Append(char item + '@') }) - (StringBuilder()) - - alphabet.ToString() - |> should equal "ABCDEFGHIJKLMNOPQRSTUVWXYZ" -} - -[] -let ``TaskSeq-fold takes state on empty IAsyncEnumberable`` () = task { - let! empty = - TaskSeq.empty - |> TaskSeq.fold (fun _ item -> char (item + 64)) '_' - - empty |> should equal '_' -} - -[] -let ``TaskSeq-foldAsync takes state on empty IAsyncEnumerable`` () = task { - let! alphabet = - TaskSeq.empty - |> TaskSeq.foldAsync (fun _ item -> task { return char (item + 64) }) '_' - - alphabet |> should equal '_' -} + [] + let ``TaskSeq-fold folds with every item`` () = + logStart output + + task { + let! alphabet = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 26 + |> TaskSeq.fold (fun (state: StringBuilder) item -> state.Append(char item + '@')) (StringBuilder()) + + alphabet.ToString() + |> should equal "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + } + + [] + let ``TaskSeq-foldAsync folds with every item`` () = + logStart output + + task { + let! alphabet = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 26 + |> TaskSeq.foldAsync + (fun (state: StringBuilder) item -> task { return state.Append(char item + '@') }) + (StringBuilder()) + + alphabet.ToString() + |> should equal "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + } + + [] + let ``TaskSeq-fold takes state on empty IAsyncEnumberable`` () = + logStart output + + task { + let! empty = + TaskSeq.empty + |> TaskSeq.fold (fun _ item -> char (item + 64)) '_' + + empty |> should equal '_' + } + + [] + let ``TaskSeq-foldAsync takes state on empty IAsyncEnumerable`` () = + logStart output + + task { + let! alphabet = + TaskSeq.empty + |> TaskSeq.foldAsync (fun _ item -> task { return char (item + 64) }) '_' + + alphabet |> should equal '_' + } diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.Head.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Head.Tests.fs index afaa49b4..7c63db54 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.Head.Tests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Head.Tests.fs @@ -1,4 +1,4 @@ -module FSharpy.Tests.Head +namespace FSharpy.Tests open System open Xunit @@ -7,51 +7,73 @@ open FsToolkit.ErrorHandling open FSharpy +type Head(output) = -[] -let ``TaskSeq-head throws on empty sequences`` () = task { - fun () -> TaskSeq.empty |> TaskSeq.head |> Task.ignore - |> should throwAsyncExact typeof -} - -[] -let ``TaskSeq-head throws on empty sequences - variant`` () = task { - fun () -> taskSeq { do () } |> TaskSeq.head |> Task.ignore - |> should throwAsyncExact typeof -} - -[] -let ``TaskSeq-tryHead returns None on empty sequences`` () = task { - let! nothing = TaskSeq.empty |> TaskSeq.tryHead - nothing |> should be None' -} - -[] -let ``TaskSeq-head gets the first item in a longer sequence`` () = task { - let! head = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 |> TaskSeq.head - - head |> should equal 1 -} - -[] -let ``TaskSeq-head gets the only item in a singleton sequence`` () = task { - let! head = taskSeq { yield 10 } |> TaskSeq.head - head |> should equal 10 -} - -[] -let ``TaskSeq-tryHead gets the first item in a longer sequence`` () = task { - let! head = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.tryHead - - head |> should be Some' - head |> should equal (Some 1) -} - -[] -let ``TaskSeq-tryHead gets the only item in a singleton sequence`` () = task { - let! head = taskSeq { yield 10 } |> TaskSeq.tryHead - head |> should be Some' - head |> should equal (Some 10) -} + [] + let ``TaskSeq-head throws on empty sequences`` () = + logStart output + + task { + fun () -> TaskSeq.empty |> TaskSeq.head |> Task.ignore + |> should throwAsyncExact typeof + } + + [] + let ``TaskSeq-head throws on empty sequences - variant`` () = + logStart output + + task { + fun () -> taskSeq { do () } |> TaskSeq.head |> Task.ignore + |> should throwAsyncExact typeof + } + + [] + let ``TaskSeq-tryHead returns None on empty sequences`` () = + logStart output + + task { + let! nothing = TaskSeq.empty |> TaskSeq.tryHead + nothing |> should be None' + } + + [] + let ``TaskSeq-head gets the first item in a longer sequence`` () = + logStart output + + task { + let! head = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 |> TaskSeq.head + + head |> should equal 1 + } + + [] + let ``TaskSeq-head gets the only item in a singleton sequence`` () = + logStart output + + task { + let! head = taskSeq { yield 10 } |> TaskSeq.head + head |> should equal 10 + } + + [] + let ``TaskSeq-tryHead gets the first item in a longer sequence`` () = + logStart output + + task { + let! head = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.tryHead + + head |> should be Some' + head |> should equal (Some 1) + } + + [] + let ``TaskSeq-tryHead gets the only item in a singleton sequence`` () = + logStart output + + task { + let! head = taskSeq { yield 10 } |> TaskSeq.tryHead + head |> should be Some' + head |> should equal (Some 10) + } diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.Item.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Item.Tests.fs index 00dcf353..a6407b1f 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.Item.Tests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Item.Tests.fs @@ -1,4 +1,4 @@ -module FSharpy.Tests.Item +namespace FSharpy.Tests open System open Xunit @@ -7,237 +7,307 @@ open FsToolkit.ErrorHandling open FSharpy +type Item(output) = -[] -let ``TaskSeq-item throws on empty sequences`` () = task { - fun () -> TaskSeq.empty |> TaskSeq.item 0 |> Task.ignore - |> should throwAsyncExact typeof -} - -[] -let ``TaskSeq-item throws on empty sequence - variant`` () = task { - fun () -> taskSeq { do () } |> TaskSeq.item 50000 |> Task.ignore - |> should throwAsyncExact typeof -} - -[] -let ``TaskSeq-item throws when not found`` () = task { - fun () -> - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.item 51 - |> Task.ignore - |> should throwAsyncExact typeof -} - -[] -let ``TaskSeq-item throws when not found - variant`` () = task { - fun () -> - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.item Int32.MaxValue - |> Task.ignore - |> should throwAsyncExact typeof -} - -[] -let ``TaskSeq-item throws when accessing 2nd item in singleton sequence`` () = task { - fun () -> taskSeq { yield 10 } |> TaskSeq.item 1 |> Task.ignore // zero-based! - |> should throwAsyncExact typeof -} - -[] -let ``TaskSeq-item always throws with negative values`` () = task { - let make50 () = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - - fun () -> make50 () |> TaskSeq.item -1 |> Task.ignore - |> should throwAsyncExact typeof - - fun () -> make50 () |> TaskSeq.item -10000 |> Task.ignore - |> should throwAsyncExact typeof - - fun () -> make50 () |> TaskSeq.item Int32.MinValue |> Task.ignore - |> should throwAsyncExact typeof - - fun () -> TaskSeq.empty |> TaskSeq.item -1 |> Task.ignore - |> should throwAsyncExact typeof - - fun () -> TaskSeq.empty |> TaskSeq.item -10000 |> Task.ignore - |> should throwAsyncExact typeof - - fun () -> - TaskSeq.empty - |> TaskSeq.item Int32.MinValue - |> Task.ignore - |> should throwAsyncExact typeof -} - -[] -let ``TaskSeq-tryItem returns None on empty sequences`` () = task { - let! nothing = TaskSeq.empty |> TaskSeq.tryItem 0 - nothing |> should be None' -} - -[] -let ``TaskSeq-tryItem returns None on empty sequence - variant`` () = task { - let! nothing = taskSeq { do () } |> TaskSeq.tryItem 50000 - nothing |> should be None' -} - -[] -let ``TaskSeq-tryItem returns None when not found`` () = task { - let! nothing = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.tryItem 50 // zero-based index, so a sequence of 50 items has its last item at index 49 - - nothing |> should be None' -} - -[] -let ``TaskSeq-tryItem returns None when not found - variant`` () = task { - let! nothing = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.tryItem Int32.MaxValue - - nothing |> should be None' -} - -[] -let ``TaskSeq-tryItem returns None when accessing 2nd item in singleton sequence`` () = task { - let! nothing = taskSeq { yield 10 } |> TaskSeq.tryItem 1 // zero-based! - nothing |> should be None' -} - -[] -let ``TaskSeq-tryItem returns None throws with negative values`` () = task { - let make50 () = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - - let! nothing = make50 () |> TaskSeq.tryItem -1 - nothing |> should be None' - - let! nothing = make50 () |> TaskSeq.tryItem -10000 - nothing |> should be None' - - let! nothing = make50 () |> TaskSeq.tryItem Int32.MinValue - nothing |> should be None' - - let! nothing = TaskSeq.empty |> TaskSeq.tryItem -1 - nothing |> should be None' - - let! nothing = TaskSeq.empty |> TaskSeq.tryItem -10000 - nothing |> should be None' - - let! nothing = TaskSeq.empty |> TaskSeq.tryItem Int32.MinValue - nothing |> should be None' -} - -[] -let ``TaskSeq-item can get the first item in a longer sequence`` () = task { - let! head = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.item 0 - - head |> should equal 1 -} - -[] -let ``TaskSeq-item can get the last item in a longer sequence`` () = task { - let! head = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.item 49 - - head |> should equal 50 -} - -[] -let ``TaskSeq-item can get the first item in a singleton sequence`` () = task { - let! head = taskSeq { yield 10 } |> TaskSeq.item 0 // zero-based index! - head |> should equal 10 -} - -[] -let ``TaskSeq-tryItem can get the first item in a longer sequence`` () = task { - let! head = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.tryItem 0 // zero-based! - - head |> should be Some' - head |> should equal (Some 1) -} - -[] -let ``TaskSeq-tryItem in a very long sequence (5_000 items - slow variant)`` () = task { - let! head = createDummyDirectTaskSeq 5_001 |> TaskSeq.tryItem 5_000 // zero-based! - - head |> should be Some' - head |> should equal (Some 5_001) -} - -[] -let ``TaskSeq-tryItem in a very long sequence (50_000 items - slow variant)`` () = task { - let! head = createDummyDirectTaskSeq 50_001 |> TaskSeq.tryItem 50_000 // zero-based! - - head |> should be Some' - head |> should equal (Some 50_001) -} - -[] -let ``TaskSeq-tryItem in a very long sequence (50_000 items - fast variant)`` () = task { - let! head = - // using taskSeq instead of the delayed-task approach above, which creates an extra closure for each - // task, we can really see the speed of the 'taskSeq' CE!! This is - taskSeq { - for i in [ 0..50_000 ] do - yield i - } - |> TaskSeq.tryItem 50_000 // zero-based! - - head |> should be Some' - head |> should equal (Some 50_000) -} - -[] -let ``TaskSeq-tryItem in a very long sequence (50_000 items - using sync Seq)`` () = task { - // this test is just for smoke-test perf comparison with TaskSeq above - let head = - seq { - for i in [ 0..50_000 ] do - yield i - } - |> Seq.tryItem 50_000 // zero-based! - - head |> should be Some' - head |> should equal (Some 50_000) -} - -[] -let ``TaskSeq-tryItem in a very long sequence (500_000 items - fast variant)`` () = task { - let! head = - taskSeq { - for i in [ 0..500_000 ] do - yield i - } - |> TaskSeq.tryItem 500_000 // zero-based! - - head |> should be Some' - head |> should equal (Some 500_000) -} - -[] -let ``TaskSeq-tryItem in a very long sequence (500_000 items - using sync Seq)`` () = task { - // this test is just for smoke-test perf comparison with TaskSeq above - let head = - seq { - for i in [ 0..500_000 ] do - yield i - } - |> Seq.tryItem 500_000 // zero-based! - - head |> should be Some' - head |> should equal (Some 500_000) -} - -[] -let ``TaskSeq-tryItem gets the first item in a singleton sequence`` () = task { - let! head = taskSeq { yield 10 } |> TaskSeq.tryItem 0 // zero-based! - head |> should be Some' - head |> should equal (Some 10) -} + [] + let ``TaskSeq-item throws on empty sequences`` () = + logStart output + + task { + fun () -> TaskSeq.empty |> TaskSeq.item 0 |> Task.ignore + |> should throwAsyncExact typeof + } + + [] + let ``TaskSeq-item throws on empty sequence - variant`` () = + logStart output + + task { + fun () -> taskSeq { do () } |> TaskSeq.item 50000 |> Task.ignore + |> should throwAsyncExact typeof + } + + [] + let ``TaskSeq-item throws when not found`` () = + logStart output + + task { + fun () -> + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.item 51 + |> Task.ignore + |> should throwAsyncExact typeof + } + + [] + let ``TaskSeq-item throws when not found - variant`` () = + logStart output + + task { + fun () -> + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.item Int32.MaxValue + |> Task.ignore + |> should throwAsyncExact typeof + } + + [] + let ``TaskSeq-item throws when accessing 2nd item in singleton sequence`` () = + logStart output + + task { + fun () -> taskSeq { yield 10 } |> TaskSeq.item 1 |> Task.ignore // zero-based! + |> should throwAsyncExact typeof + } + + [] + let ``TaskSeq-item always throws with negative values`` () = + logStart output + + task { + let make50 () = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + + fun () -> make50 () |> TaskSeq.item -1 |> Task.ignore + |> should throwAsyncExact typeof + + fun () -> make50 () |> TaskSeq.item -10000 |> Task.ignore + |> should throwAsyncExact typeof + + fun () -> make50 () |> TaskSeq.item Int32.MinValue |> Task.ignore + |> should throwAsyncExact typeof + + fun () -> TaskSeq.empty |> TaskSeq.item -1 |> Task.ignore + |> should throwAsyncExact typeof + + fun () -> TaskSeq.empty |> TaskSeq.item -10000 |> Task.ignore + |> should throwAsyncExact typeof + + fun () -> + TaskSeq.empty + |> TaskSeq.item Int32.MinValue + |> Task.ignore + |> should throwAsyncExact typeof + } + + [] + let ``TaskSeq-tryItem returns None on empty sequences`` () = + logStart output + + task { + let! nothing = TaskSeq.empty |> TaskSeq.tryItem 0 + nothing |> should be None' + } + + [] + let ``TaskSeq-tryItem returns None on empty sequence - variant`` () = + logStart output + + task { + let! nothing = taskSeq { do () } |> TaskSeq.tryItem 50000 + nothing |> should be None' + } + + [] + let ``TaskSeq-tryItem returns None when not found`` () = + logStart output + + task { + let! nothing = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.tryItem 50 // zero-based index, so a sequence of 50 items has its last item at index 49 + + nothing |> should be None' + } + + [] + let ``TaskSeq-tryItem returns None when not found - variant`` () = + logStart output + + task { + let! nothing = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.tryItem Int32.MaxValue + + nothing |> should be None' + } + + [] + let ``TaskSeq-tryItem returns None when accessing 2nd item in singleton sequence`` () = + logStart output + + task { + let! nothing = taskSeq { yield 10 } |> TaskSeq.tryItem 1 // zero-based! + nothing |> should be None' + } + + [] + let ``TaskSeq-tryItem returns None throws with negative values`` () = + logStart output + + task { + let make50 () = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + + let! nothing = make50 () |> TaskSeq.tryItem -1 + nothing |> should be None' + + let! nothing = make50 () |> TaskSeq.tryItem -10000 + nothing |> should be None' + + let! nothing = make50 () |> TaskSeq.tryItem Int32.MinValue + nothing |> should be None' + + let! nothing = TaskSeq.empty |> TaskSeq.tryItem -1 + nothing |> should be None' + + let! nothing = TaskSeq.empty |> TaskSeq.tryItem -10000 + nothing |> should be None' + + let! nothing = TaskSeq.empty |> TaskSeq.tryItem Int32.MinValue + nothing |> should be None' + } + + [] + let ``TaskSeq-item can get the first item in a longer sequence`` () = + logStart output + + task { + let! head = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.item 0 + + head |> should equal 1 + } + + [] + let ``TaskSeq-item can get the last item in a longer sequence`` () = + logStart output + + task { + let! head = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.item 49 + + head |> should equal 50 + } + + [] + let ``TaskSeq-item can get the first item in a singleton sequence`` () = + logStart output + + task { + let! head = taskSeq { yield 10 } |> TaskSeq.item 0 // zero-based index! + head |> should equal 10 + } + + [] + let ``TaskSeq-tryItem can get the first item in a longer sequence`` () = + logStart output + + task { + let! head = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.tryItem 0 // zero-based! + + head |> should be Some' + head |> should equal (Some 1) + } + + [] + let ``TaskSeq-tryItem in a very long sequence (5_000 items - slow variant)`` () = + logStart output + + task { + let! head = createDummyDirectTaskSeq 5_001 |> TaskSeq.tryItem 5_000 // zero-based! + + head |> should be Some' + head |> should equal (Some 5_001) + } + + [] + let ``TaskSeq-tryItem in a very long sequence (50_000 items - slow variant)`` () = + logStart output + + task { + let! head = createDummyDirectTaskSeq 50_001 |> TaskSeq.tryItem 50_000 // zero-based! + + head |> should be Some' + head |> should equal (Some 50_001) + } + + [] + let ``TaskSeq-tryItem in a very long sequence (50_000 items - fast variant)`` () = + logStart output + + task { + let! head = + // using taskSeq instead of the delayed-task approach above, which creates an extra closure for each + // task, we can really see the speed of the 'taskSeq' CE!! This is + taskSeq { + for i in [ 0..50_000 ] do + yield i + } + |> TaskSeq.tryItem 50_000 // zero-based! + + head |> should be Some' + head |> should equal (Some 50_000) + } + + [] + let ``TaskSeq-tryItem in a very long sequence (50_000 items - using sync Seq)`` () = + logStart output + + task { + // this test is just for smoke-test perf comparison with TaskSeq above + let head = + seq { + for i in [ 0..50_000 ] do + yield i + } + |> Seq.tryItem 50_000 // zero-based! + + head |> should be Some' + head |> should equal (Some 50_000) + } + + [] + let ``TaskSeq-tryItem in a very long sequence (500_000 items - fast variant)`` () = + logStart output + + task { + let! head = + taskSeq { + for i in [ 0..500_000 ] do + yield i + } + |> TaskSeq.tryItem 500_000 // zero-based! + + head |> should be Some' + head |> should equal (Some 500_000) + } + + [] + let ``TaskSeq-tryItem in a very long sequence (500_000 items - using sync Seq)`` () = + logStart output + + task { + // this test is just for smoke-test perf comparison with TaskSeq above + let head = + seq { + for i in [ 0..500_000 ] do + yield i + } + |> Seq.tryItem 500_000 // zero-based! + + head |> should be Some' + head |> should equal (Some 500_000) + } + + [] + let ``TaskSeq-tryItem gets the first item in a singleton sequence`` () = + logStart output + + task { + let! head = taskSeq { yield 10 } |> TaskSeq.tryItem 0 // zero-based! + head |> should be Some' + head |> should equal (Some 10) + } diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.Iter.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Iter.Tests.fs index ca5faad9..b6f7eef0 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.Iter.Tests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Iter.Tests.fs @@ -1,4 +1,4 @@ -module FSharpy.Tests.Iter +namespace FSharpy.Tests open Xunit open FsUnit.Xunit @@ -7,42 +7,56 @@ 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 -} +type Iter(output) = + + [] + let ``TaskSeq-iteri should go over all items`` () = + logStart output + + 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`` () = + logStart output + + 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`` () = + logStart output + + 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`` () = + logStart output + + 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.Last.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Last.Tests.fs index 5db77a02..729b1138 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.Last.Tests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Last.Tests.fs @@ -1,4 +1,4 @@ -module FSharpy.Tests.Last +namespace FSharpy.Tests open System open Xunit @@ -7,51 +7,72 @@ open FsToolkit.ErrorHandling open FSharpy +type Last(output) = + [] + let ``TaskSeq-last throws on empty sequences`` () = + logStart output -[] -let ``TaskSeq-last throws on empty sequences`` () = task { - fun () -> TaskSeq.empty |> TaskSeq.last |> Task.ignore - |> should throwAsyncExact typeof -} - -[] -let ``TaskSeq-last throws on empty sequences - variant`` () = task { - fun () -> taskSeq { do () } |> TaskSeq.last |> Task.ignore - |> should throwAsyncExact typeof -} - -[] -let ``TaskSeq-tryLast returns None on empty sequences`` () = task { - let! nothing = TaskSeq.empty |> TaskSeq.tryLast - nothing |> should be None' -} - -[] -let ``TaskSeq-last gets the last item in a longer sequence`` () = task { - let! last = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 |> TaskSeq.last - - last |> should equal 50 -} - -[] -let ``TaskSeq-last gets the only item in a singleton sequence`` () = task { - let! last = taskSeq { yield 10 } |> TaskSeq.last - last |> should equal 10 -} - -[] -let ``TaskSeq-tryLast gets the last item in a longer sequence`` () = task { - let! last = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.tryLast - - last |> should be Some' - last |> should equal (Some 50) -} - -[] -let ``TaskSeq-tryLast gets the only item in a singleton sequence`` () = task { - let! last = taskSeq { yield 10 } |> TaskSeq.tryLast - last |> should be Some' - last |> should equal (Some 10) -} + task { + fun () -> TaskSeq.empty |> TaskSeq.last |> Task.ignore + |> should throwAsyncExact typeof + } + + [] + let ``TaskSeq-last throws on empty sequences - variant`` () = + logStart output + + task { + fun () -> taskSeq { do () } |> TaskSeq.last |> Task.ignore + |> should throwAsyncExact typeof + } + + [] + let ``TaskSeq-tryLast returns None on empty sequences`` () = + logStart output + + task { + let! nothing = TaskSeq.empty |> TaskSeq.tryLast + nothing |> should be None' + } + + [] + let ``TaskSeq-last gets the last item in a longer sequence`` () = + logStart output + + task { + let! last = createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 |> TaskSeq.last + + last |> should equal 50 + } + + [] + let ``TaskSeq-last gets the only item in a singleton sequence`` () = + logStart output + + task { + let! last = taskSeq { yield 10 } |> TaskSeq.last + last |> should equal 10 + } + + [] + let ``TaskSeq-tryLast gets the last item in a longer sequence`` () = + logStart output + + task { + let! last = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.tryLast + + last |> should be Some' + last |> should equal (Some 50) + } + + [] + let ``TaskSeq-tryLast gets the only item in a singleton sequence`` () = + logStart output + + task { + let! last = taskSeq { yield 10 } |> TaskSeq.tryLast + last |> should be Some' + last |> should equal (Some 10) + } diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.Map.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Map.Tests.fs index a85e7274..a748c12d 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.Map.Tests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Map.Tests.fs @@ -1,4 +1,4 @@ -module FSharpy.Tests.Map +namespace FSharpy.Tests open Xunit open FsUnit.Xunit @@ -6,29 +6,36 @@ open FsToolkit.ErrorHandling open FSharpy +type Map(output) = -[] -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" -} + [] + let ``TaskSeq-map maps in correct order`` () = + logStart output + + 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`` () = + logStart output + + 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 index 6e5be915..f6b1ed75 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.OfXXX.Tests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.OfXXX.Tests.fs @@ -1,4 +1,4 @@ -module FSharpy.Tests.``Conversion-From`` +namespace FSharpy.Tests open Xunit open FsUnit.Xunit @@ -6,52 +6,72 @@ 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 +type ``Conversion-From``(output) = + + let validateSequence sq = task { + let! sq = TaskSeq.toArrayAsync sq + do sq |> Seq.toArray |> should equal [| 0..9 |] + } + + [] + let ``TaskSeq-ofAsyncArray should succeed`` () = + logStart output + + Array.init 10 (fun x -> async { return x }) + |> TaskSeq.ofAsyncArray + |> validateSequence + + [] + let ``TaskSeq-ofAsyncList should succeed`` () = + logStart output + + List.init 10 (fun x -> async { return x }) + |> TaskSeq.ofAsyncList + |> validateSequence + + [] + let ``TaskSeq-ofAsyncSeq should succeed`` () = + logStart output + + Seq.init 10 (fun x -> async { return x }) + |> TaskSeq.ofAsyncSeq + |> validateSequence + + [] + let ``TaskSeq-ofTaskArray should succeed`` () = + logStart output + + Array.init 10 (fun x -> task { return x }) + |> TaskSeq.ofTaskArray + |> validateSequence + + [] + let ``TaskSeq-ofTaskList should succeed`` () = + logStart output + + List.init 10 (fun x -> task { return x }) + |> TaskSeq.ofTaskList + |> validateSequence + + [] + let ``TaskSeq-ofTaskSeq should succeed`` () = + logStart output + + Seq.init 10 (fun x -> task { return x }) + |> TaskSeq.ofTaskSeq + |> validateSequence + + [] + let ``TaskSeq-ofArray should succeed`` () = + logStart output + Array.init 10 id |> TaskSeq.ofArray |> validateSequence + + [] + let ``TaskSeq-ofList should succeed`` () = + logStart output + List.init 10 id |> TaskSeq.ofList |> validateSequence + + [] + let ``TaskSeq-ofSeq should succeed`` () = + logStart output + Seq.init 10 id |> TaskSeq.ofSeq |> validateSequence diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.Pick.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Pick.Tests.fs index 10d619ee..608f9aee 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.Pick.Tests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Pick.Tests.fs @@ -1,4 +1,4 @@ -module FSharpy.Tests.Pick +namespace FSharpy.Tests open System open System.Collections.Generic @@ -8,251 +8,327 @@ open FsToolkit.ErrorHandling open FSharpy +type Pick(output) = + + // + // TaskSeq.pick + // TaskSeq.pickAsync + // the tryXXX versions are at the bottom half + // + + [] + let ``TaskSeq-pick on an empty sequence raises KeyNotFoundException`` () = + logStart output + + task { + fun () -> + TaskSeq.empty + |> TaskSeq.pick (fun x -> if x = 12 then Some x else None) + |> Task.ignore + |> should throwAsyncExact typeof + } + + [] + let ``TaskSeq-pick on an empty sequence raises KeyNotFoundException - variant`` () = + logStart output + + task { + fun () -> + taskSeq { do () } + |> TaskSeq.pick (fun x -> if x = 12 then Some x else None) + |> Task.ignore + |> should throwAsyncExact typeof + } + + [] + let ``TaskSeq-pickAsync on an empty sequence raises KeyNotFoundException`` () = + logStart output + + task { + fun () -> + TaskSeq.empty + |> TaskSeq.pickAsync (fun x -> task { return if x = 12 then Some x else None }) + |> Task.ignore + |> should throwAsyncExact typeof + } + + [] + let ``TaskSeq-pick sad path raises KeyNotFoundException`` () = + logStart output + + task { + fun () -> + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.pick (fun x -> if x = 0 then Some x else None) // dummy tasks sequence starts at 1 + |> Task.ignore + + |> should throwAsyncExact typeof + } + + [] + let ``TaskSeq-pickAsync sad path raises KeyNotFoundException`` () = + logStart output + + task { + fun () -> + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.pickAsync (fun x -> task { return if x < 0 then Some x else None }) // dummy tasks sequence starts at 1 + |> Task.ignore + + |> should throwAsyncExact typeof + } + + [] + let ``TaskSeq-pick sad path raises KeyNotFoundException variant`` () = + logStart output + + task { + fun () -> + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.pick (fun x -> if x = 51 then Some x else None) // dummy tasks sequence ends at 50 + |> Task.ignore + + |> should throwAsyncExact typeof + } + + [] + let ``TaskSeq-pickAsync sad path raises KeyNotFoundException variant`` () = + logStart output + + task { + fun () -> + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.pickAsync (fun x -> task { return if x = 51 then Some x else None }) // dummy tasks sequence ends at 50 + |> Task.ignore + + |> should throwAsyncExact typeof + } + + + [] + let ``TaskSeq-pick happy path middle of seq`` () = + logStart output + + task { + let! twentyFive = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.pick (fun x -> if x < 26 && x > 24 then Some "foo" else None) + + twentyFive |> should equal "foo" + } + + [] + let ``TaskSeq-pickAsync happy path middle of seq`` () = + logStart output + + task { + let! twentyFive = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.pickAsync (fun x -> task { return if x < 26 && x > 24 then Some "foo" else None }) + + twentyFive |> should equal "foo" + } + + [] + let ``TaskSeq-pick happy path first item of seq`` () = + logStart output + + task { + let! first = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.pick (fun x -> if x = 1 then Some $"first{x}" else None) // dummy tasks seq starts at 1 + + first |> should equal "first1" + } + + [] + let ``TaskSeq-pickAsync happy path first item of seq`` () = + logStart output + + task { + let! first = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.pickAsync (fun x -> task { return if x = 1 then Some $"first{x}" else None }) // dummy tasks seq starts at 1 + + first |> should equal "first1" + } + + [] + let ``TaskSeq-pick happy path last item of seq`` () = + logStart output -// -// TaskSeq.pick -// TaskSeq.pickAsync -// the tryXXX versions are at the bottom half -// - -[] -let ``TaskSeq-pick on an empty sequence raises KeyNotFoundException`` () = task { - fun () -> - TaskSeq.empty - |> TaskSeq.pick (fun x -> if x = 12 then Some x else None) - |> Task.ignore - |> should throwAsyncExact typeof -} - -[] -let ``TaskSeq-pick on an empty sequence raises KeyNotFoundException - variant`` () = task { - fun () -> - taskSeq { do () } - |> TaskSeq.pick (fun x -> if x = 12 then Some x else None) - |> Task.ignore - |> should throwAsyncExact typeof -} - -[] -let ``TaskSeq-pickAsync on an empty sequence raises KeyNotFoundException`` () = task { - fun () -> - TaskSeq.empty - |> TaskSeq.pickAsync (fun x -> task { return if x = 12 then Some x else None }) - |> Task.ignore - |> should throwAsyncExact typeof -} - -[] -let ``TaskSeq-pick sad path raises KeyNotFoundException`` () = task { - fun () -> - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.pick (fun x -> if x = 0 then Some x else None) // dummy tasks sequence starts at 1 - |> Task.ignore - - |> should throwAsyncExact typeof -} - -[] -let ``TaskSeq-pickAsync sad path raises KeyNotFoundException`` () = task { - fun () -> - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.pickAsync (fun x -> task { return if x < 0 then Some x else None }) // dummy tasks sequence starts at 1 - |> Task.ignore - - |> should throwAsyncExact typeof -} - -[] -let ``TaskSeq-pick sad path raises KeyNotFoundException variant`` () = task { - fun () -> - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.pick (fun x -> if x = 51 then Some x else None) // dummy tasks sequence ends at 50 - |> Task.ignore - - |> should throwAsyncExact typeof -} - -[] -let ``TaskSeq-pickAsync sad path raises KeyNotFoundException variant`` () = task { - fun () -> - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.pickAsync (fun x -> task { return if x = 51 then Some x else None }) // dummy tasks sequence ends at 50 - |> Task.ignore - - |> should throwAsyncExact typeof -} - - -[] -let ``TaskSeq-pick happy path middle of seq`` () = task { - let! twentyFive = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.pick (fun x -> if x < 26 && x > 24 then Some "foo" else None) - - twentyFive |> should equal "foo" -} - -[] -let ``TaskSeq-pickAsync happy path middle of seq`` () = task { - let! twentyFive = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.pickAsync (fun x -> task { return if x < 26 && x > 24 then Some "foo" else None }) - - twentyFive |> should equal "foo" -} - -[] -let ``TaskSeq-pick happy path first item of seq`` () = task { - let! first = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.pick (fun x -> if x = 1 then Some $"first{x}" else None) // dummy tasks seq starts at 1 - - first |> should equal "first1" -} - -[] -let ``TaskSeq-pickAsync happy path first item of seq`` () = task { - let! first = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.pickAsync (fun x -> task { return if x = 1 then Some $"first{x}" else None }) // dummy tasks seq starts at 1 - - first |> should equal "first1" -} - -[] -let ``TaskSeq-pick happy path last item of seq`` () = task { - let! last = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.pick (fun x -> if x = 50 then Some $"last{x}" else None) // dummy tasks seq ends at 50 - - last |> should equal "last50" -} - -[] -let ``TaskSeq-pickAsync happy path last item of seq`` () = task { - let! last = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.pickAsync (fun x -> task { return if x = 50 then Some $"last{x}" else None }) // dummy tasks seq ends at 50 - - last |> should equal "last50" -} - -// -// TaskSeq.tryPick -// TaskSeq.tryPickAsync -// - -[] -let ``TaskSeq-tryPick on an empty sequence returns None`` () = task { - let! nothing = - TaskSeq.empty - |> TaskSeq.tryPick (fun x -> if x = 12 then Some x else None) - - nothing |> should be None' -} - -[] -let ``TaskSeq-tryPickAsync on an empty sequence returns None`` () = task { - let! nothing = - TaskSeq.empty - |> TaskSeq.tryPickAsync (fun x -> task { return if x = 12 then Some x else None }) - - nothing |> should be None' -} - -[] -let ``TaskSeq-tryPick sad path returns None`` () = task { - let! nothing = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.tryPick (fun x -> if x = 0 then Some x else None) // dummy tasks sequence starts at 1 - - nothing |> should be None' -} - -[] -let ``TaskSeq-tryPickAsync sad path return None`` () = task { - let! nothing = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.tryPickAsync (fun x -> task { return if x = 0 then Some x else None }) // dummy tasks sequence starts at 1 - - nothing |> should be None' -} - -[] -let ``TaskSeq-tryPick sad path returns None variant`` () = task { - let! nothing = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.tryPick (fun x -> if x >= 51 then Some x else None) // dummy tasks sequence ends at 50 (inverted sign in lambda!) - - nothing |> should be None' -} - -[] -let ``TaskSeq-tryPickAsync sad path return None - variant`` () = task { - let! nothing = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.tryPickAsync (fun x -> task { return if x >= 51 then Some x else None }) // dummy tasks sequence ends at 50 - - nothing |> should be None' -} - - -[] -let ``TaskSeq-tryPick happy path middle of seq`` () = task { - let! twentyFive = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.tryPick (fun x -> if x < 26 && x > 24 then Some $"foo{x}" else None) - - twentyFive |> should be Some' - twentyFive |> should equal (Some "foo25") -} - -[] -let ``TaskSeq-tryPickAsync happy path middle of seq`` () = task { - let! twentyFive = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.tryPickAsync (fun x -> task { return if x < 26 && x > 24 then Some $"foo{x}" else None }) - - twentyFive |> should be Some' - twentyFive |> should equal (Some "foo25") -} - -[] -let ``TaskSeq-tryPick happy path first item of seq`` () = task { - let! first = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.tryPick (sprintf "foo%i" >> Some) // dummy tasks seq starts at 1 - - first |> should be Some' - first |> should equal (Some "foo1") -} - -[] -let ``TaskSeq-tryPickAsync happy path first item of seq`` () = task { - let! first = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.tryPickAsync (fun x -> task { return (sprintf "foo%i" >> Some) x }) // dummy tasks seq starts at 1 - - first |> should be Some' - first |> should equal (Some "foo1") -} - -[] -let ``TaskSeq-tryPick happy path last item of seq`` () = task { - let! last = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.tryPick (fun x -> if x = 50 then Some $"foo{x}" else None) // dummy tasks seq ends at 50 - - last |> should be Some' - last |> should equal (Some "foo50") -} - -[] -let ``TaskSeq-tryPickAsync happy path last item of seq`` () = task { - let! last = - createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 - |> TaskSeq.tryPickAsync (fun x -> task { return if x = 50 then Some $"foo{x}" else None }) // dummy tasks seq ends at 50 - - last |> should be Some' - last |> should equal (Some "foo50") -} + task { + let! last = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.pick (fun x -> if x = 50 then Some $"last{x}" else None) // dummy tasks seq ends at 50 + + last |> should equal "last50" + } + + [] + let ``TaskSeq-pickAsync happy path last item of seq`` () = + logStart output + + task { + let! last = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.pickAsync (fun x -> task { return if x = 50 then Some $"last{x}" else None }) // dummy tasks seq ends at 50 + + last |> should equal "last50" + } + + // + // TaskSeq.tryPick + // TaskSeq.tryPickAsync + // + + [] + let ``TaskSeq-tryPick on an empty sequence returns None`` () = + logStart output + + task { + let! nothing = + TaskSeq.empty + |> TaskSeq.tryPick (fun x -> if x = 12 then Some x else None) + + nothing |> should be None' + } + + [] + let ``TaskSeq-tryPickAsync on an empty sequence returns None`` () = + logStart output + + task { + let! nothing = + TaskSeq.empty + |> TaskSeq.tryPickAsync (fun x -> task { return if x = 12 then Some x else None }) + + nothing |> should be None' + } + + [] + let ``TaskSeq-tryPick sad path returns None`` () = + logStart output + + task { + let! nothing = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.tryPick (fun x -> if x = 0 then Some x else None) // dummy tasks sequence starts at 1 + + nothing |> should be None' + } + + [] + let ``TaskSeq-tryPickAsync sad path return None`` () = + logStart output + + task { + let! nothing = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.tryPickAsync (fun x -> task { return if x = 0 then Some x else None }) // dummy tasks sequence starts at 1 + + nothing |> should be None' + } + + [] + let ``TaskSeq-tryPick sad path returns None variant`` () = + logStart output + + task { + let! nothing = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.tryPick (fun x -> if x >= 51 then Some x else None) // dummy tasks sequence ends at 50 (inverted sign in lambda!) + + nothing |> should be None' + } + + [] + let ``TaskSeq-tryPickAsync sad path return None - variant`` () = + logStart output + + task { + let! nothing = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.tryPickAsync (fun x -> task { return if x >= 51 then Some x else None }) // dummy tasks sequence ends at 50 + + nothing |> should be None' + } + + + [] + let ``TaskSeq-tryPick happy path middle of seq`` () = + logStart output + + task { + let! twentyFive = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.tryPick (fun x -> if x < 26 && x > 24 then Some $"foo{x}" else None) + + twentyFive |> should be Some' + twentyFive |> should equal (Some "foo25") + } + + [] + let ``TaskSeq-tryPickAsync happy path middle of seq`` () = + logStart output + + task { + let! twentyFive = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.tryPickAsync (fun x -> task { return if x < 26 && x > 24 then Some $"foo{x}" else None }) + + twentyFive |> should be Some' + twentyFive |> should equal (Some "foo25") + } + + [] + let ``TaskSeq-tryPick happy path first item of seq`` () = + logStart output + + task { + let! first = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.tryPick (sprintf "foo%i" >> Some) // dummy tasks seq starts at 1 + + first |> should be Some' + first |> should equal (Some "foo1") + } + + [] + let ``TaskSeq-tryPickAsync happy path first item of seq`` () = + logStart output + + task { + let! first = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.tryPickAsync (fun x -> task { return (sprintf "foo%i" >> Some) x }) // dummy tasks seq starts at 1 + + first |> should be Some' + first |> should equal (Some "foo1") + } + + [] + let ``TaskSeq-tryPick happy path last item of seq`` () = + logStart output + + task { + let! last = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.tryPick (fun x -> if x = 50 then Some $"foo{x}" else None) // dummy tasks seq ends at 50 + + last |> should be Some' + last |> should equal (Some "foo50") + } + + [] + let ``TaskSeq-tryPickAsync happy path last item of seq`` () = + logStart output + + task { + let! last = + createDummyTaskSeqWith 50L<µs> 1000L<µs> 50 + |> TaskSeq.tryPickAsync (fun x -> task { return if x = 50 then Some $"foo{x}" else None }) // dummy tasks seq ends at 50 + + last |> should be Some' + last |> should equal (Some "foo50") + } diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.PocTests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.PocTests.fs index fe23de47..9e94f626 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.PocTests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.PocTests.fs @@ -15,77 +15,92 @@ open FSharpy ///////////////////////////////////////////////////////////////////////////// -module ``PoC's for seq of tasks`` = +type ``PoC's for seq of tasks``(output) = [] - let ``Good: Show joining tasks with continuation is good`` () = task { - // acts like a fold - let! results = createAndJoinMultipleTasks 10 joinWithContinuation - results |> should equal 10 - } + let ``Good: Show joining tasks with continuation is good`` () = + logStart output + + task { + // acts like a fold + let! results = createAndJoinMultipleTasks 10 joinWithContinuation + results |> should equal 10 + } [] - let ``Good: Show that joining tasks with 'bind' in task CE is good`` () = task { - let! tasks = createAndJoinMultipleTasks 10 joinIdentityDelayed + let ``Good: Show that joining tasks with 'bind' in task CE is good`` () = + logStart output - let tasks = tasks |> Array.ofList - let len = Array.length tasks - let results = Array.zeroCreate len + task { + let! tasks = createAndJoinMultipleTasks 10 joinIdentityDelayed - for i in 0 .. len - 1 do - // this uses Task.bind under the hood, which ensures order-of-execution and wait-for-previous - let! item = tasks[i]() // only now are we delay-executing the task in the array - results[i] <- item + let tasks = tasks |> Array.ofList + let len = Array.length tasks + let results = Array.zeroCreate len - results |> should equal <| Array.init len ((+) 1) - } + for i in 0 .. len - 1 do + // this uses Task.bind under the hood, which ensures order-of-execution and wait-for-previous + let! item = tasks[i]() // only now are we delay-executing the task in the array + results[i] <- item - [] - let ``Good: Show that joining tasks with 'taskSeq' is good`` () = task { - let! tasks = createAndJoinMultipleTasks 10 joinIdentityDelayed - - let asAsyncSeq = taskSeq { - for task in tasks do - // cannot use `yield!` here, as `taskSeq` expects it to return a seq - let! x = task () - yield x + results |> should equal <| Array.init len ((+) 1) } - let! results = asAsyncSeq |> TaskSeq.toArrayAsync + [] + let ``Good: Show that joining tasks with 'taskSeq' is good`` () = + logStart output - results |> should equal - <| Array.init (Array.length results) ((+) 1) - } + task { + let! tasks = createAndJoinMultipleTasks 10 joinIdentityDelayed - [] - let ``Bad: Show that joining tasks with 'traverseTaskResult' can be bad`` () = task { - let! taskList = createAndJoinMultipleTasks 10 joinIdentityHotStarted + let asAsyncSeq = taskSeq { + for task in tasks do + // cannot use `yield!` here, as `taskSeq` expects it to return a seq + let! x = task () + yield x + } - // since tasks are hot-started, by this time they are already *all* running - let! results = - taskList - |> List.map (Task.map Result.Ok) - |> List.traverseTaskResultA id + let! results = asAsyncSeq |> TaskSeq.toArrayAsync - match results with - | Ok results -> - results |> should not' - <| equal (List.init (List.length results) ((+) 1)) - | Error err -> failwith $"Impossible: {err}" - } + results |> should equal + <| Array.init (Array.length results) ((+) 1) + } [] - let ``Bad: Show that joining tasks as a list of tasks can be bad`` () = task { - let! taskList = createAndJoinMultipleTasks 10 joinIdentityHotStarted + let ``Bad: Show that joining tasks with 'traverseTaskResult' can be bad`` () = + logStart output + + task { + let! taskList = createAndJoinMultipleTasks 10 joinIdentityHotStarted + + // since tasks are hot-started, by this time they are already *all* running + let! results = + taskList + |> List.map (Task.map Result.Ok) + |> List.traverseTaskResultA id + + match results with + | Ok results -> + results |> should not' + <| equal (List.init (List.length results) ((+) 1)) + | Error err -> failwith $"Impossible: {err}" + } + + [] + let ``Bad: Show that joining tasks as a list of tasks can be bad`` () = + logStart output - // since tasks are hot-started, by this time they are already *all* running - let tasks = taskList |> Array.ofList - let results = Array.zeroCreate 10 + task { + let! taskList = createAndJoinMultipleTasks 10 joinIdentityHotStarted - for i in 0..9 do - let! item = tasks[i] - results[i] <- item + // since tasks are hot-started, by this time they are already *all* running + let tasks = taskList |> Array.ofList + let results = Array.zeroCreate 10 - results |> should not' - <| equal (Array.init (Array.length results) ((+) 1)) - } + for i in 0..9 do + let! item = tasks[i] + results[i] <- item + + results |> should not' + <| equal (Array.init (Array.length results) ((+) 1)) + } diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.Tests.CE.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Tests.CE.fs index d123de8a..6402e0b1 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.Tests.CE.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Tests.CE.fs @@ -1,4 +1,4 @@ -module FSharpy.Tests.``taskSeq Computation Expression`` +namespace FSharpy.Tests open Xunit open FsUnit.Xunit @@ -8,82 +8,86 @@ open FSharpy open System.Threading.Tasks open System.Diagnostics +type ``taskSeq Computation Expression``(output) = -[] -let ``CE taskSeq with several yield!`` () = task { - let tskSeq = taskSeq { - yield! createDummyTaskSeq 10 - yield! createDummyTaskSeq 5 - yield! createDummyTaskSeq 10 - yield! createDummyTaskSeq 5 - } + [] + let ``CE taskSeq with several yield!`` () = + logStart output - let! data = tskSeq |> TaskSeq.toListAsync + task { + let tskSeq = taskSeq { + yield! createDummyTaskSeq 10 + yield! createDummyTaskSeq 5 + yield! createDummyTaskSeq 10 + yield! createDummyTaskSeq 5 + } - data - |> should equal (List.concat [ [ 1..10 ]; [ 1..5 ]; [ 1..10 ]; [ 1..5 ] ]) -} + let! data = tskSeq |> TaskSeq.toListAsync -[] -let ``CE taskSeq with nested yield!`` () = task { - let control = seq { - yield! [ 1..10 ] + data + |> should equal (List.concat [ [ 1..10 ]; [ 1..5 ]; [ 1..10 ]; [ 1..5 ] ]) + } - for i in 0..9 do - yield! [ 1..2 ] + [] + let ``CE taskSeq with nested yield!`` () = + logStart output - for i in 0..2 do - yield! seq { yield 42 } + task { + let control = seq { + yield! [ 1..10 ] - for i in 100..102 do - yield! seq { yield! seq { yield i } } - } + for i in 0..9 do + yield! [ 1..2 ] - let tskSeq = taskSeq { - yield! createDummyTaskSeq 10 + for i in 0..2 do + yield! seq { yield 42 } + + for i in 100..102 do + yield! seq { yield! seq { yield i } } + } - for i in 0..9 do - yield! createDummyTaskSeq 2 + let tskSeq = taskSeq { + yield! createDummyTaskSeq 10 - for i in 0..2 do - yield! taskSeq { yield 42 } + for i in 0..9 do + yield! createDummyTaskSeq 2 - for i in 100..102 do - yield! taskSeq { yield! taskSeq { yield i } } - } + for i in 0..2 do + yield! taskSeq { yield 42 } - let! data = tskSeq |> TaskSeq.toListAsync + for i in 100..102 do + yield! taskSeq { yield! taskSeq { yield i } } + } - data |> should equal (List.ofSeq control) - data |> should haveLength 150 -} + let! data = tskSeq |> TaskSeq.toListAsync -[] -let ``CE taskSeq with nested deeply yield! perf test 8521 nested tasks`` () = task { - let control = seq { - yield! [ 1..10 ] + data |> should equal (List.ofSeq control) + data |> should haveLength 150 + } - // original: - yield! Seq.concat <| Seq.init 4251 (fun _ -> [ 1; 2 ]) - //yield! Seq.concat <| Seq.init 120 (fun _ -> [ 1; 2 ]) - } + [] + let ``CE taskSeq with nested deeply yield! perf test 8521 nested tasks`` () = + logStart output - let createTasks = createDummyTaskSeqWith 1L<µs> 10L<µs> - // FIXME: it appears that deeply nesting adds to performance degradation, need to benchmark/profile this - // probably cause: since this is *fast* with DirectTask, the reason is likely the way the Task.Delay causes - // *many* subtasks to be delayed, resulting in exponential delay. Reason: max accuracy of Delay is about 15ms (!) + task { + let control = seq { + yield! [ 1..10 ] - // RESOLUTION: seems to have been caused by erratic Task.Delay which has only a 15ms resolution - let tskSeq = taskSeq { - yield! createTasks 10 + // original: + yield! Seq.concat <| Seq.init 4251 (fun _ -> [ 1; 2 ]) + //yield! Seq.concat <| Seq.init 120 (fun _ -> [ 1; 2 ]) + } - // nestings amount to 8512 sequences of [1;2] - for i in 0..2 do - yield! createTasks 2 + let createTasks = createDummyTaskSeqWith 1L<µs> 10L<µs> + // FIXME: it appears that deeply nesting adds to performance degradation, need to benchmark/profile this + // probably cause: since this is *fast* with DirectTask, the reason is likely the way the Task.Delay causes + // *many* subtasks to be delayed, resulting in exponential delay. Reason: max accuracy of Delay is about 15ms (!) - for i in 0..2 do - yield! createTasks 2 + // RESOLUTION: seems to have been caused by erratic Task.Delay which has only a 15ms resolution + let tskSeq = taskSeq { + yield! createTasks 10 + // nestings amount to 8512 sequences of [1;2] for i in 0..2 do yield! createTasks 2 @@ -96,123 +100,153 @@ let ``CE taskSeq with nested deeply yield! perf test 8521 nested tasks`` () = ta for i in 0..2 do yield! createTasks 2 - for i in 0..2 do - yield! createTasks 2 + for i in 0..2 do + yield! createTasks 2 - for i in 0..2 do - yield! createTasks 2 + for i in 0..2 do + yield! createTasks 2 for i in 0..2 do yield! createTasks 2 - yield! TaskSeq.empty - } - - let! data = tskSeq |> TaskSeq.toListAsync - data |> List.length |> should equal 8512 - data |> should equal (List.ofSeq control) -} - -[] -let ``CE taskSeq with several return!`` () = task { - // TODO: should we even support this? Traditional 'seq' doesn't. - let tskSeq = taskSeq { - return! createDummyTaskSeq 10 - return! createDummyTaskSeq 5 - } - - let! data = tskSeq |> TaskSeq.toListAsync - - // FIXME!!! This behavior is *probably* not correct - data |> should equal [ 1..10 ] -} - - -[] -let ``CE taskSeq with mixing yield! and yield`` () = task { - let tskSeq = taskSeq { - yield! createDummyTaskSeq 10 - yield 42 - yield! createDummyTaskSeq 5 - yield 42 - yield! createDummyTaskSeq 10 - yield 42 - yield! createDummyTaskSeq 5 - } - - let! data = tskSeq |> TaskSeq.toListAsync - - data - |> should equal (List.concat [ [ 1..10 ]; [ 42 ]; [ 1..5 ]; [ 42 ]; [ 1..10 ]; [ 42 ]; [ 1..5 ] ]) -} - -[] -let ``CE taskSeq: 1000 TaskDelay-delayed tasks using yield!`` () = task { - // Smoke performance test - // Runs in slightly over half a second (average of spin-wait, plus small overhead) - // should generally be about as fast as `task`, see below for equivalent test. - let tskSeq = taskSeq { yield! createDummyTaskSeqWith 50L<µs> 1000L<µs> 1000 } - let! data = tskSeq |> TaskSeq.toListAsync - data |> should equal [ 1..1000 ] -} - -[] -let ``CE taskSeq: 1000 sync-running tasks using yield!`` () = task { - // Smoke performance test - // Runs in a few 10's of ms, because of absense of Task.Delay - // should generally be about as fast as `task`, see below - let tskSeq = taskSeq { yield! createDummyDirectTaskSeq 1000 } - let! data = tskSeq |> TaskSeq.toListAsync - data |> should equal [ 1..1000 ] -} - -[] -let ``CE taskSeq: 5000 sync-running tasks using yield!`` () = task { - // Smoke performance test - // Compare with task-ce test below. Uses a no-delay hot-started sequence of tasks. - let tskSeq = taskSeq { yield! createDummyDirectTaskSeq 5000 } - let! data = tskSeq |> TaskSeq.toListAsync - data |> should equal [ 1..5000 ] -} - -[] -let ``CE task: 1000 TaskDelay-delayed tasks using for-loop`` () = task { - // Uses SpinWait for effective task-delaying - // for smoke-test comparison with taskSeq - let tasks = DummyTaskFactory(50L<µs>, 1000L<µs>).CreateDelayedTasks 1000 - let mutable i = 0 - - for t in tasks do - i <- i + 1 - do! t () |> Task.ignore - - i |> should equal 1000 -} - -[] -let ``CE task: 1000 list of sync-running tasks using for-loop`` () = task { - // runs in a few 10's of ms, because of absense of Task.Delay - // for smoke-test comparison with taskSeq - let tasks = DummyTaskFactory().CreateDirectTasks 1000 - let mutable i = 0 - - for t in tasks do - i <- i + 1 - do! t () |> Task.ignore - - i |> should equal 1000 -} - -[] -let ``CE task: 5000 list of sync-running tasks using for-loop`` () = task { - // runs in a few 100's of ms, because of absense of Task.Delay - // for smoke-test comparison with taskSeq - let tasks = DummyTaskFactory().CreateDirectTasks 5000 - let mutable i = 0 - - for t in tasks do - i <- i + 1 - do! t () |> Task.ignore - - i |> should equal 5000 -} + for i in 0..2 do + yield! createTasks 2 + + for i in 0..2 do + yield! createTasks 2 + + yield! TaskSeq.empty + } + + let! data = tskSeq |> TaskSeq.toListAsync + data |> List.length |> should equal 8512 + data |> should equal (List.ofSeq control) + } + + [] + let ``CE taskSeq with several return!`` () = + logStart output + + task { + // TODO: should we even support this? Traditional 'seq' doesn't. + let tskSeq = taskSeq { + return! createDummyTaskSeq 10 + return! createDummyTaskSeq 5 + } + + let! data = tskSeq |> TaskSeq.toListAsync + + // FIXME!!! This behavior is *probably* not correct + data |> should equal [ 1..10 ] + } + + + [] + let ``CE taskSeq with mixing yield! and yield`` () = + logStart output + + task { + let tskSeq = taskSeq { + yield! createDummyTaskSeq 10 + yield 42 + yield! createDummyTaskSeq 5 + yield 42 + yield! createDummyTaskSeq 10 + yield 42 + yield! createDummyTaskSeq 5 + } + + let! data = tskSeq |> TaskSeq.toListAsync + + data + |> should equal (List.concat [ [ 1..10 ]; [ 42 ]; [ 1..5 ]; [ 42 ]; [ 1..10 ]; [ 42 ]; [ 1..5 ] ]) + } + + [] + let ``CE taskSeq: 1000 TaskDelay-delayed tasks using yield!`` () = + logStart output + + task { + // Smoke performance test + // Runs in slightly over half a second (average of spin-wait, plus small overhead) + // should generally be about as fast as `task`, see below for equivalent test. + let tskSeq = taskSeq { yield! createDummyTaskSeqWith 50L<µs> 1000L<µs> 1000 } + let! data = tskSeq |> TaskSeq.toListAsync + data |> should equal [ 1..1000 ] + } + + [] + let ``CE taskSeq: 1000 sync-running tasks using yield!`` () = + logStart output + + task { + // Smoke performance test + // Runs in a few 10's of ms, because of absense of Task.Delay + // should generally be about as fast as `task`, see below + let tskSeq = taskSeq { yield! createDummyDirectTaskSeq 1000 } + let! data = tskSeq |> TaskSeq.toListAsync + data |> should equal [ 1..1000 ] + } + + [] + let ``CE taskSeq: 5000 sync-running tasks using yield!`` () = + logStart output + + task { + // Smoke performance test + // Compare with task-ce test below. Uses a no-delay hot-started sequence of tasks. + let tskSeq = taskSeq { yield! createDummyDirectTaskSeq 5000 } + let! data = tskSeq |> TaskSeq.toListAsync + data |> should equal [ 1..5000 ] + } + + [] + let ``CE task: 1000 TaskDelay-delayed tasks using for-loop`` () = + logStart output + + task { + // Uses SpinWait for effective task-delaying + // for smoke-test comparison with taskSeq + let tasks = DummyTaskFactory(50L<µs>, 1000L<µs>).CreateDelayedTasks 1000 + let mutable i = 0 + + for t in tasks do + i <- i + 1 + do! t () |> Task.ignore + + i |> should equal 1000 + } + + [] + let ``CE task: 1000 list of sync-running tasks using for-loop`` () = + logStart output + + task { + // runs in a few 10's of ms, because of absense of Task.Delay + // for smoke-test comparison with taskSeq + let tasks = DummyTaskFactory().CreateDirectTasks 1000 + let mutable i = 0 + + for t in tasks do + i <- i + 1 + do! t () |> Task.ignore + + i |> should equal 1000 + } + + [] + let ``CE task: 5000 list of sync-running tasks using for-loop`` () = + logStart output + + task { + // runs in a few 100's of ms, because of absense of Task.Delay + // for smoke-test comparison with taskSeq + let tasks = DummyTaskFactory().CreateDirectTasks 5000 + let mutable i = 0 + + for t in tasks do + i <- i + 1 + do! t () |> Task.ignore + + i |> should equal 5000 + } diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.Tests.Other.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Tests.Other.fs index ad18e084..3fe7162d 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.Tests.Other.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Tests.Other.fs @@ -1,4 +1,4 @@ -module FSharpy.Tests.``Other functions`` +namespace FSharpy.Tests open Xunit open FsUnit.Xunit @@ -6,22 +6,32 @@ open FsToolkit.ErrorHandling open FSharpy +type ``Other functions``(output) = -[] -let ``TaskSeq-empty returns an empty sequence`` () = task { - let! sq = TaskSeq.empty |> TaskSeq.toSeqCachedAsync - Seq.isEmpty sq |> should be True - Seq.length sq |> should equal 0 -} - -[] -let ``TaskSeq-isEmpty returns true for empty`` () = task { - let! isEmpty = TaskSeq.empty |> TaskSeq.isEmpty - isEmpty |> should be True -} - -[] -let ``TaskSeq-isEmpty returns false for non-empty`` () = task { - let! isEmpty = taskSeq { yield 42 } |> TaskSeq.isEmpty - isEmpty |> should be False -} + [] + let ``TaskSeq-empty returns an empty sequence`` () = + logStart output + + task { + let! sq = TaskSeq.empty |> TaskSeq.toSeqCachedAsync + Seq.isEmpty sq |> should be True + Seq.length sq |> should equal 0 + } + + [] + let ``TaskSeq-isEmpty returns true for empty`` () = + logStart output + + task { + let! isEmpty = TaskSeq.empty |> TaskSeq.isEmpty + isEmpty |> should be True + } + + [] + let ``TaskSeq-isEmpty returns false for non-empty`` () = + logStart output + + task { + let! isEmpty = taskSeq { yield 42 } |> TaskSeq.isEmpty + isEmpty |> should be False + } diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.ToXXX.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.ToXXX.Tests.fs index c78ef5d2..63d4d125 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.ToXXX.Tests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.ToXXX.Tests.fs @@ -1,4 +1,4 @@ -module FSharpy.Tests.``Conversion-To`` +namespace FSharpy.Tests open Xunit open FsUnit.Xunit @@ -20,55 +20,72 @@ open System.Collections.Generic /// /// //////////////////////////////////////////////////////////////////////////// -[] -let ``TaskSeq-toArrayAsync should succeed`` () = task { - let tq = createDummyTaskSeq 10 - let! (results: _[]) = tq |> TaskSeq.toArrayAsync - results |> should equal [| 1..10 |] -} - -[] -let ``TaskSeq-toListAsync should succeed`` () = task { - let tq = createDummyTaskSeq 10 - let! (results: list<_>) = tq |> TaskSeq.toListAsync - 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 [| 1..10 |] -} - -[] -let ``TaskSeq-toIListAsync should succeed`` () = task { - let tq = createDummyTaskSeq 10 - let! (results: IList<_>) = tq |> TaskSeq.toIListAsync - results |> Seq.toArray |> should equal [| 1..10 |] -} - -[] -let ``TaskSeq-toResizeArray should succeed`` () = task { - let tq = createDummyTaskSeq 10 - let! (results: ResizeArray<_>) = tq |> TaskSeq.toResizeArrayAsync - 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 [| 1..10 |] - -[] -let ``TaskSeq-toList should succeed and be blocking`` () = - let tq = createDummyTaskSeq 10 - let (results: list<_>) = tq |> TaskSeq.toList - 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 [| 1..10 |] +type ``Conversion-To``(output) = + + [] + let ``TaskSeq-toArrayAsync should succeed`` () = + logStart output + + task { + let tq = createDummyTaskSeq 10 + let! (results: _[]) = tq |> TaskSeq.toArrayAsync + results |> should equal [| 1..10 |] + } + + [] + let ``TaskSeq-toListAsync should succeed`` () = + logStart output + + task { + let tq = createDummyTaskSeq 10 + let! (results: list<_>) = tq |> TaskSeq.toListAsync + results |> should equal [ 1..10 ] + } + + [] + let ``TaskSeq-toSeqCachedAsync should succeed`` () = + logStart output + + task { + let tq = createDummyTaskSeq 10 + let! (results: seq<_>) = tq |> TaskSeq.toSeqCachedAsync + results |> Seq.toArray |> should equal [| 1..10 |] + } + + [] + let ``TaskSeq-toIListAsync should succeed`` () = + logStart output + + task { + let tq = createDummyTaskSeq 10 + let! (results: IList<_>) = tq |> TaskSeq.toIListAsync + results |> Seq.toArray |> should equal [| 1..10 |] + } + + [] + let ``TaskSeq-toResizeArray should succeed`` () = + logStart output + + task { + let tq = createDummyTaskSeq 10 + let! (results: ResizeArray<_>) = tq |> TaskSeq.toResizeArrayAsync + 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 [| 1..10 |] + + [] + let ``TaskSeq-toList should succeed and be blocking`` () = + let tq = createDummyTaskSeq 10 + let (results: list<_>) = tq |> TaskSeq.toList + 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 [| 1..10 |] diff --git a/src/FSharpy.TaskSeq.Test/TestUtils.fs b/src/FSharpy.TaskSeq.Test/TestUtils.fs index 10a46e01..2d187fa5 100644 --- a/src/FSharpy.TaskSeq.Test/TestUtils.fs +++ b/src/FSharpy.TaskSeq.Test/TestUtils.fs @@ -8,6 +8,8 @@ open System.Diagnostics open FsToolkit.ErrorHandling open FSharpy +open Xunit.Abstractions +open System.Reflection /// Milliseconds [] @@ -17,6 +19,13 @@ type ms [] type µs +[] +module Log = + let inline logStart (output: ITestOutputHelper) = + let name = MethodBase.GetCurrentMethod().Name + output.WriteLine $"Starting test: {name}" + + /// Helpers for short waits, as Task.Delay has about 15ms precision. /// Inspired by IoT code: https://github.com/dotnet/iot/pull/235/files module DelayHelper = From d20265066ed401141beac063db158ec55fba6587 Mon Sep 17 00:00:00 2001 From: Abel Braaksma Date: Sat, 15 Oct 2022 02:48:50 +0200 Subject: [PATCH 5/5] Skip all tests and run reflected and in parallel * Skip all tests and run by hand, i.e. reflection-based runner test * Implement our own test runner * Run parallelized self-written testrunner several times in parallel --- .../FSharpy.TaskSeq.Test.fsproj | 1 + src/FSharpy.TaskSeq.Test/TaskSeq.AllTests.fs | 153 ++++++++++++++++++ .../TaskSeq.Choose.Tests.fs | 10 +- .../TaskSeq.Collect.Tests.fs | 10 +- .../TaskSeq.Filter.Tests.fs | 8 +- .../TaskSeq.Find.Tests.fs | 50 +++--- .../TaskSeq.Fold.Tests.fs | 8 +- .../TaskSeq.Head.Tests.fs | 14 +- .../TaskSeq.Item.Tests.fs | 46 +++--- .../TaskSeq.Iter.Tests.fs | 8 +- .../TaskSeq.Last.Tests.fs | 14 +- src/FSharpy.TaskSeq.Test/TaskSeq.Map.Tests.fs | 4 +- .../TaskSeq.OfXXX.Tests.fs | 18 +-- .../TaskSeq.Pick.Tests.fs | 50 +++--- src/FSharpy.TaskSeq.Test/TaskSeq.PocTests.fs | 10 +- src/FSharpy.TaskSeq.Test/TaskSeq.Tests.CE.fs | 22 +-- .../TaskSeq.Tests.Other.fs | 6 +- .../TaskSeq.ToXXX.Tests.fs | 16 +- 18 files changed, 301 insertions(+), 147 deletions(-) create mode 100644 src/FSharpy.TaskSeq.Test/TaskSeq.AllTests.fs diff --git a/src/FSharpy.TaskSeq.Test/FSharpy.TaskSeq.Test.fsproj b/src/FSharpy.TaskSeq.Test/FSharpy.TaskSeq.Test.fsproj index dd013994..200e0f88 100644 --- a/src/FSharpy.TaskSeq.Test/FSharpy.TaskSeq.Test.fsproj +++ b/src/FSharpy.TaskSeq.Test/FSharpy.TaskSeq.Test.fsproj @@ -11,6 +11,7 @@ + diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.AllTests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.AllTests.fs new file mode 100644 index 00000000..f4573b1c --- /dev/null +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.AllTests.fs @@ -0,0 +1,153 @@ +namespace FSharpy.Tests + +open System +open System.Threading.Tasks +open System.Reflection + +open Xunit +open FsUnit.Xunit +open FsToolkit.ErrorHandling + +open FSharpy +open Xunit.Abstractions + + +type AllTests(output: ITestOutputHelper) = + let createParallelRunner () = + let myAsm = Assembly.GetExecutingAssembly() + + let allMethods = [ + for ty in myAsm.DefinedTypes do + for mem in ty.DeclaredMembers do + match mem.MemberType with + | MemberTypes.Method -> + if mem.Name.StartsWith("TaskSeq") || mem.Name.StartsWith("CE") then + yield ty, mem :?> MethodInfo + | _ -> () + ] + + let all = seq { + for (ty, method) in allMethods do + let ctor = ty.GetConstructor [| typeof |] + + if isNull ctor then + failwith "Constructor for test not found" + + let testObj = ctor.Invoke([| output |]) + + if method.ReturnType.Name.Contains "Task" then + //task { + // let! x = Async.StartChildAsTask (Async.ofTask (method.Invoke(testObj, null) :?> Task)) + // return! x + //} + async { + return! + method.Invoke(testObj, null) :?> Task + |> Async.AwaitTask + } + else + async { return method.Invoke(testObj, null) |> ignore } + } + + all |> Async.Parallel |> Async.map ignore + + let multiply f x = + seq { + for i in [ 0..x ] do + yield f () + } + |> Async.Parallel + |> Async.map ignore + + [] + let ``Run all tests 1 times in parallel`` () = task { do! multiply createParallelRunner 1 } + + [] + [] + let ``Run all tests X times in parallel`` i = task { do! multiply createParallelRunner i } + + [] + [] + let ``Run all tests again X times in parallel`` i = task { do! multiply createParallelRunner i } + + [] + [] + let ``Run all tests and once more, X times in parallel`` i = task { do! multiply createParallelRunner i } + + +//[] +//let ``Run all tests 3 times in parallel`` () = +// multiply createParallelRunner 15 +// |> Async.RunSynchronously + + +//[] +//let ``Run all tests 4 times in parallel`` () = +// multiply createParallelRunner 15 +// |> Async.RunSynchronously + + +//[] +//let ``Run all tests 5 times in parallel`` () = +// multiply createParallelRunner 15 +// |> Async.RunSynchronously + + +//[] +//let ``Run all tests 6 times in parallel`` () = +// multiply createParallelRunner 15 +// |> Async.RunSynchronously + + +//[] +//let ``Run all tests 7 times in parallel`` () = +// multiply createParallelRunner 15 +// |> Async.RunSynchronously + + +//[] +//let ``Run all tests 8 times in parallel`` () = +// multiply createParallelRunner 15 +// |> Async.RunSynchronously + + +//[] +//let ``Run all tests 9 times in parallel`` () = +// multiply createParallelRunner 15 +// |> Async.RunSynchronously + + +//[] +//let ``Run all tests 10 times in parallel`` () = +// multiply createParallelRunner 15 +// |> Async.RunSynchronously + + +//[] +//let ``Run all tests 11 times in parallel`` () = +// multiply createParallelRunner 15 +// |> Async.RunSynchronously + + +//[] +//let ``Run all tests 12 times in parallel`` () = +// multiply createParallelRunner 15 +// |> Async.RunSynchronously + + +//[] +//let ``Run all tests 13 times in parallel`` () = +// multiply createParallelRunner 15 +// |> Async.RunSynchronously + + +//[] +//let ``Run all tests 14 times in parallel`` () = +// multiply createParallelRunner 15 +// |> Async.RunSynchronously + + +//[] +//let ``Run all tests 15 times in parallel`` () = +// multiply createParallelRunner 15 +// |> Async.RunSynchronously diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.Choose.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Choose.Tests.fs index 967b0660..0a8357b9 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.Choose.Tests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Choose.Tests.fs @@ -13,7 +13,7 @@ open Xunit.Abstractions type Choose(output: ITestOutputHelper) = - [] + [] let ``ZHang timeout test`` () = logStart output @@ -22,7 +22,7 @@ type Choose(output: ITestOutputHelper) = empty |> should be Null } - [] + [] let ``TaskSeq-choose on an empty sequence`` () = logStart output @@ -35,7 +35,7 @@ type Choose(output: ITestOutputHelper) = List.isEmpty empty |> should be True } - [] + [] let ``TaskSeq-chooseAsync on an empty sequence`` () = logStart output @@ -48,7 +48,7 @@ type Choose(output: ITestOutputHelper) = List.isEmpty empty |> should be True } - [] + [] let ``TaskSeq-choose can convert and filter`` () = logStart output @@ -61,7 +61,7 @@ type Choose(output: ITestOutputHelper) = String alphabet |> should equal "ABCDEFGHIJKLMNOPQRSTUVWXYZ" } - [] + [] let ``TaskSeq-chooseAsync can convert and filter`` () = logStart output diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.Collect.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Collect.Tests.fs index 2ee6a160..728b15cc 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.Collect.Tests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Collect.Tests.fs @@ -8,7 +8,7 @@ open FSharpy type Collect(output) = - [] + [] let ``TaskSeq-collect operates in correct order`` () = logStart output @@ -27,7 +27,7 @@ type Collect(output) = |> should equal "ABBCCDDEEFFGGHHIIJJK" } - [] + [] let ``TaskSeq-collectSeq operates in correct order`` () = logStart output @@ -46,7 +46,7 @@ type Collect(output) = |> should equal "ABBCCDDEEFFGGHHIIJJK" } - [] + [] let ``TaskSeq-collect with empty task sequences`` () = logStart output @@ -59,7 +59,7 @@ type Collect(output) = Seq.isEmpty sq |> should be True } - [] + [] let ``TaskSeq-collectSeq with empty sequences`` () = logStart output @@ -72,7 +72,7 @@ type Collect(output) = Seq.isEmpty sq |> should be True } - [] + [] let ``TaskSeq-empty is empty`` () = logStart output diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.Filter.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Filter.Tests.fs index afb2b5b9..5b78ab80 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.Filter.Tests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Filter.Tests.fs @@ -10,7 +10,7 @@ open FSharpy type Filter(output) = - [] + [] let ``TaskSeq-filter on an empty sequence`` () = logStart output @@ -23,7 +23,7 @@ type Filter(output) = List.isEmpty empty |> should be True } - [] + [] let ``TaskSeq-filterAsync on an empty sequence`` () = logStart output @@ -36,7 +36,7 @@ type Filter(output) = List.isEmpty empty |> should be True } - [] + [] let ``TaskSeq-filter filters correctly`` () = logStart output @@ -52,7 +52,7 @@ type Filter(output) = String alphabet |> should equal "Z[\]^_`abcdefghijklmnopqr" } - [] + [] let ``TaskSeq-filterAsync filters correctly`` () = logStart output diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.Find.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Find.Tests.fs index e08bc8cd..7837ea87 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.Find.Tests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Find.Tests.fs @@ -16,7 +16,7 @@ type Find(output) = // the tryXXX versions are at the bottom half // - [] + [] let ``TaskSeq-find on an empty sequence raises KeyNotFoundException`` () = logStart output @@ -25,7 +25,7 @@ type Find(output) = |> should throwAsyncExact typeof } - [] + [] let ``TaskSeq-find on an empty sequence raises KeyNotFoundException - variant`` () = logStart output @@ -34,7 +34,7 @@ type Find(output) = |> should throwAsyncExact typeof } - [] + [] let ``TaskSeq-findAsync on an empty sequence raises KeyNotFoundException`` () = logStart output @@ -46,7 +46,7 @@ type Find(output) = |> should throwAsyncExact typeof } - [] + [] let ``TaskSeq-find sad path raises KeyNotFoundException`` () = logStart output @@ -59,7 +59,7 @@ type Find(output) = |> should throwAsyncExact typeof } - [] + [] let ``TaskSeq-findAsync sad path raises KeyNotFoundException`` () = logStart output @@ -72,7 +72,7 @@ type Find(output) = |> should throwAsyncExact typeof } - [] + [] let ``TaskSeq-find sad path raises KeyNotFoundException variant`` () = logStart output @@ -85,7 +85,7 @@ type Find(output) = |> should throwAsyncExact typeof } - [] + [] let ``TaskSeq-findAsync sad path raises KeyNotFoundException variant`` () = logStart output @@ -99,7 +99,7 @@ type Find(output) = } - [] + [] let ``TaskSeq-find happy path middle of seq`` () = logStart output @@ -111,7 +111,7 @@ type Find(output) = twentyFive |> should equal 25 } - [] + [] let ``TaskSeq-findAsync happy path middle of seq`` () = logStart output @@ -123,7 +123,7 @@ type Find(output) = twentyFive |> should equal 25 } - [] + [] let ``TaskSeq-find happy path first item of seq`` () = logStart output @@ -135,7 +135,7 @@ type Find(output) = first |> should equal 1 } - [] + [] let ``TaskSeq-findAsync happy path first item of seq`` () = logStart output @@ -147,7 +147,7 @@ type Find(output) = first |> should equal 1 } - [] + [] let ``TaskSeq-find happy path last item of seq`` () = logStart output @@ -159,7 +159,7 @@ type Find(output) = last |> should equal 50 } - [] + [] let ``TaskSeq-findAsync happy path last item of seq`` () = logStart output @@ -176,7 +176,7 @@ type Find(output) = // TaskSeq.tryFindAsync // - [] + [] let ``TaskSeq-tryFind on an empty sequence returns None`` () = logStart output @@ -185,7 +185,7 @@ type Find(output) = nothing |> should be None' } - [] + [] let ``TaskSeq-tryFindAsync on an empty sequence returns None`` () = logStart output @@ -197,7 +197,7 @@ type Find(output) = nothing |> should be None' } - [] + [] let ``TaskSeq-tryFind sad path returns None`` () = logStart output @@ -209,7 +209,7 @@ type Find(output) = nothing |> should be None' } - [] + [] let ``TaskSeq-tryFindAsync sad path return None`` () = logStart output @@ -221,7 +221,7 @@ type Find(output) = nothing |> should be None' } - [] + [] let ``TaskSeq-tryFind sad path returns None variant`` () = logStart output @@ -233,7 +233,7 @@ type Find(output) = nothing |> should be None' } - [] + [] let ``TaskSeq-tryFindAsync sad path return None - variant`` () = logStart output @@ -246,7 +246,7 @@ type Find(output) = } - [] + [] let ``TaskSeq-tryFind happy path middle of seq`` () = logStart output @@ -259,7 +259,7 @@ type Find(output) = twentyFive |> should equal (Some 25) } - [] + [] let ``TaskSeq-tryFindAsync happy path middle of seq`` () = logStart output @@ -272,7 +272,7 @@ type Find(output) = twentyFive |> should equal (Some 25) } - [] + [] let ``TaskSeq-tryFind happy path first item of seq`` () = logStart output @@ -285,7 +285,7 @@ type Find(output) = first |> should equal (Some 1) } - [] + [] let ``TaskSeq-tryFindAsync happy path first item of seq`` () = logStart output @@ -298,7 +298,7 @@ type Find(output) = first |> should equal (Some 1) } - [] + [] let ``TaskSeq-tryFind happy path last item of seq`` () = logStart output @@ -311,7 +311,7 @@ type Find(output) = last |> should equal (Some 50) } - [] + [] let ``TaskSeq-tryFindAsync happy path last item of seq`` () = logStart output diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.Fold.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Fold.Tests.fs index 32154896..3102ea80 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.Fold.Tests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Fold.Tests.fs @@ -9,7 +9,7 @@ open FSharpy type Fold(output) = - [] + [] let ``TaskSeq-fold folds with every item`` () = logStart output @@ -22,7 +22,7 @@ type Fold(output) = |> should equal "ABCDEFGHIJKLMNOPQRSTUVWXYZ" } - [] + [] let ``TaskSeq-foldAsync folds with every item`` () = logStart output @@ -37,7 +37,7 @@ type Fold(output) = |> should equal "ABCDEFGHIJKLMNOPQRSTUVWXYZ" } - [] + [] let ``TaskSeq-fold takes state on empty IAsyncEnumberable`` () = logStart output @@ -49,7 +49,7 @@ type Fold(output) = empty |> should equal '_' } - [] + [] let ``TaskSeq-foldAsync takes state on empty IAsyncEnumerable`` () = logStart output diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.Head.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Head.Tests.fs index 7c63db54..39d68ef9 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.Head.Tests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Head.Tests.fs @@ -9,7 +9,7 @@ open FSharpy type Head(output) = - [] + [] let ``TaskSeq-head throws on empty sequences`` () = logStart output @@ -18,7 +18,7 @@ type Head(output) = |> should throwAsyncExact typeof } - [] + [] let ``TaskSeq-head throws on empty sequences - variant`` () = logStart output @@ -27,7 +27,7 @@ type Head(output) = |> should throwAsyncExact typeof } - [] + [] let ``TaskSeq-tryHead returns None on empty sequences`` () = logStart output @@ -36,7 +36,7 @@ type Head(output) = nothing |> should be None' } - [] + [] let ``TaskSeq-head gets the first item in a longer sequence`` () = logStart output @@ -46,7 +46,7 @@ type Head(output) = head |> should equal 1 } - [] + [] let ``TaskSeq-head gets the only item in a singleton sequence`` () = logStart output @@ -55,7 +55,7 @@ type Head(output) = head |> should equal 10 } - [] + [] let ``TaskSeq-tryHead gets the first item in a longer sequence`` () = logStart output @@ -68,7 +68,7 @@ type Head(output) = head |> should equal (Some 1) } - [] + [] let ``TaskSeq-tryHead gets the only item in a singleton sequence`` () = logStart output diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.Item.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Item.Tests.fs index a6407b1f..f7ef0d71 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.Item.Tests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Item.Tests.fs @@ -9,7 +9,7 @@ open FSharpy type Item(output) = - [] + [] let ``TaskSeq-item throws on empty sequences`` () = logStart output @@ -18,7 +18,7 @@ type Item(output) = |> should throwAsyncExact typeof } - [] + [] let ``TaskSeq-item throws on empty sequence - variant`` () = logStart output @@ -27,7 +27,7 @@ type Item(output) = |> should throwAsyncExact typeof } - [] + [] let ``TaskSeq-item throws when not found`` () = logStart output @@ -39,7 +39,7 @@ type Item(output) = |> should throwAsyncExact typeof } - [] + [] let ``TaskSeq-item throws when not found - variant`` () = logStart output @@ -51,7 +51,7 @@ type Item(output) = |> should throwAsyncExact typeof } - [] + [] let ``TaskSeq-item throws when accessing 2nd item in singleton sequence`` () = logStart output @@ -60,7 +60,7 @@ type Item(output) = |> should throwAsyncExact typeof } - [] + [] let ``TaskSeq-item always throws with negative values`` () = logStart output @@ -89,7 +89,7 @@ type Item(output) = |> should throwAsyncExact typeof } - [] + [] let ``TaskSeq-tryItem returns None on empty sequences`` () = logStart output @@ -98,7 +98,7 @@ type Item(output) = nothing |> should be None' } - [] + [] let ``TaskSeq-tryItem returns None on empty sequence - variant`` () = logStart output @@ -107,7 +107,7 @@ type Item(output) = nothing |> should be None' } - [] + [] let ``TaskSeq-tryItem returns None when not found`` () = logStart output @@ -119,7 +119,7 @@ type Item(output) = nothing |> should be None' } - [] + [] let ``TaskSeq-tryItem returns None when not found - variant`` () = logStart output @@ -131,7 +131,7 @@ type Item(output) = nothing |> should be None' } - [] + [] let ``TaskSeq-tryItem returns None when accessing 2nd item in singleton sequence`` () = logStart output @@ -140,7 +140,7 @@ type Item(output) = nothing |> should be None' } - [] + [] let ``TaskSeq-tryItem returns None throws with negative values`` () = logStart output @@ -166,7 +166,7 @@ type Item(output) = nothing |> should be None' } - [] + [] let ``TaskSeq-item can get the first item in a longer sequence`` () = logStart output @@ -178,7 +178,7 @@ type Item(output) = head |> should equal 1 } - [] + [] let ``TaskSeq-item can get the last item in a longer sequence`` () = logStart output @@ -190,7 +190,7 @@ type Item(output) = head |> should equal 50 } - [] + [] let ``TaskSeq-item can get the first item in a singleton sequence`` () = logStart output @@ -199,7 +199,7 @@ type Item(output) = head |> should equal 10 } - [] + [] let ``TaskSeq-tryItem can get the first item in a longer sequence`` () = logStart output @@ -212,7 +212,7 @@ type Item(output) = head |> should equal (Some 1) } - [] + [] let ``TaskSeq-tryItem in a very long sequence (5_000 items - slow variant)`` () = logStart output @@ -223,7 +223,7 @@ type Item(output) = head |> should equal (Some 5_001) } - [] + [] let ``TaskSeq-tryItem in a very long sequence (50_000 items - slow variant)`` () = logStart output @@ -234,7 +234,7 @@ type Item(output) = head |> should equal (Some 50_001) } - [] + [] let ``TaskSeq-tryItem in a very long sequence (50_000 items - fast variant)`` () = logStart output @@ -252,7 +252,7 @@ type Item(output) = head |> should equal (Some 50_000) } - [] + [] let ``TaskSeq-tryItem in a very long sequence (50_000 items - using sync Seq)`` () = logStart output @@ -269,7 +269,7 @@ type Item(output) = head |> should equal (Some 50_000) } - [] + [] let ``TaskSeq-tryItem in a very long sequence (500_000 items - fast variant)`` () = logStart output @@ -285,7 +285,7 @@ type Item(output) = head |> should equal (Some 500_000) } - [] + [] let ``TaskSeq-tryItem in a very long sequence (500_000 items - using sync Seq)`` () = logStart output @@ -302,7 +302,7 @@ type Item(output) = head |> should equal (Some 500_000) } - [] + [] let ``TaskSeq-tryItem gets the first item in a singleton sequence`` () = logStart output diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.Iter.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Iter.Tests.fs index b6f7eef0..012efd4c 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.Iter.Tests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Iter.Tests.fs @@ -9,7 +9,7 @@ open FSharpy type Iter(output) = - [] + [] let ``TaskSeq-iteri should go over all items`` () = logStart output @@ -20,7 +20,7 @@ type Iter(output) = sum |> should equal 45 // index starts at 0 } - [] + [] let ``TaskSeq-iter should go over all items`` () = logStart output @@ -31,7 +31,7 @@ type Iter(output) = sum |> should equal 55 // task-dummies started at 1 } - [] + [] let ``TaskSeq-iteriAsync should go over all items`` () = logStart output @@ -46,7 +46,7 @@ type Iter(output) = sum |> should equal 45 // index starts at 0 } - [] + [] let ``TaskSeq-iterAsync should go over all items`` () = logStart output diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.Last.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Last.Tests.fs index 729b1138..a957e51f 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.Last.Tests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Last.Tests.fs @@ -8,7 +8,7 @@ open FsToolkit.ErrorHandling open FSharpy type Last(output) = - [] + [] let ``TaskSeq-last throws on empty sequences`` () = logStart output @@ -17,7 +17,7 @@ type Last(output) = |> should throwAsyncExact typeof } - [] + [] let ``TaskSeq-last throws on empty sequences - variant`` () = logStart output @@ -26,7 +26,7 @@ type Last(output) = |> should throwAsyncExact typeof } - [] + [] let ``TaskSeq-tryLast returns None on empty sequences`` () = logStart output @@ -35,7 +35,7 @@ type Last(output) = nothing |> should be None' } - [] + [] let ``TaskSeq-last gets the last item in a longer sequence`` () = logStart output @@ -45,7 +45,7 @@ type Last(output) = last |> should equal 50 } - [] + [] let ``TaskSeq-last gets the only item in a singleton sequence`` () = logStart output @@ -54,7 +54,7 @@ type Last(output) = last |> should equal 10 } - [] + [] let ``TaskSeq-tryLast gets the last item in a longer sequence`` () = logStart output @@ -67,7 +67,7 @@ type Last(output) = last |> should equal (Some 50) } - [] + [] let ``TaskSeq-tryLast gets the only item in a singleton sequence`` () = logStart output diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.Map.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Map.Tests.fs index a748c12d..f8ffbee8 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.Map.Tests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Map.Tests.fs @@ -8,7 +8,7 @@ open FSharpy type Map(output) = - [] + [] let ``TaskSeq-map maps in correct order`` () = logStart output @@ -24,7 +24,7 @@ type Map(output) = |> should equal "ABCDEFGHIJ" } - [] + [] let ``TaskSeq-mapAsync maps in correct order`` () = logStart output diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.OfXXX.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.OfXXX.Tests.fs index f6b1ed75..b67d0c2a 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.OfXXX.Tests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.OfXXX.Tests.fs @@ -13,7 +13,7 @@ type ``Conversion-From``(output) = do sq |> Seq.toArray |> should equal [| 0..9 |] } - [] + [] let ``TaskSeq-ofAsyncArray should succeed`` () = logStart output @@ -21,7 +21,7 @@ type ``Conversion-From``(output) = |> TaskSeq.ofAsyncArray |> validateSequence - [] + [] let ``TaskSeq-ofAsyncList should succeed`` () = logStart output @@ -29,7 +29,7 @@ type ``Conversion-From``(output) = |> TaskSeq.ofAsyncList |> validateSequence - [] + [] let ``TaskSeq-ofAsyncSeq should succeed`` () = logStart output @@ -37,7 +37,7 @@ type ``Conversion-From``(output) = |> TaskSeq.ofAsyncSeq |> validateSequence - [] + [] let ``TaskSeq-ofTaskArray should succeed`` () = logStart output @@ -45,7 +45,7 @@ type ``Conversion-From``(output) = |> TaskSeq.ofTaskArray |> validateSequence - [] + [] let ``TaskSeq-ofTaskList should succeed`` () = logStart output @@ -53,7 +53,7 @@ type ``Conversion-From``(output) = |> TaskSeq.ofTaskList |> validateSequence - [] + [] let ``TaskSeq-ofTaskSeq should succeed`` () = logStart output @@ -61,17 +61,17 @@ type ``Conversion-From``(output) = |> TaskSeq.ofTaskSeq |> validateSequence - [] + [] let ``TaskSeq-ofArray should succeed`` () = logStart output Array.init 10 id |> TaskSeq.ofArray |> validateSequence - [] + [] let ``TaskSeq-ofList should succeed`` () = logStart output List.init 10 id |> TaskSeq.ofList |> validateSequence - [] + [] let ``TaskSeq-ofSeq should succeed`` () = logStart output Seq.init 10 id |> TaskSeq.ofSeq |> validateSequence diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.Pick.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Pick.Tests.fs index 608f9aee..ba50370b 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.Pick.Tests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Pick.Tests.fs @@ -16,7 +16,7 @@ type Pick(output) = // the tryXXX versions are at the bottom half // - [] + [] let ``TaskSeq-pick on an empty sequence raises KeyNotFoundException`` () = logStart output @@ -28,7 +28,7 @@ type Pick(output) = |> should throwAsyncExact typeof } - [] + [] let ``TaskSeq-pick on an empty sequence raises KeyNotFoundException - variant`` () = logStart output @@ -40,7 +40,7 @@ type Pick(output) = |> should throwAsyncExact typeof } - [] + [] let ``TaskSeq-pickAsync on an empty sequence raises KeyNotFoundException`` () = logStart output @@ -52,7 +52,7 @@ type Pick(output) = |> should throwAsyncExact typeof } - [] + [] let ``TaskSeq-pick sad path raises KeyNotFoundException`` () = logStart output @@ -65,7 +65,7 @@ type Pick(output) = |> should throwAsyncExact typeof } - [] + [] let ``TaskSeq-pickAsync sad path raises KeyNotFoundException`` () = logStart output @@ -78,7 +78,7 @@ type Pick(output) = |> should throwAsyncExact typeof } - [] + [] let ``TaskSeq-pick sad path raises KeyNotFoundException variant`` () = logStart output @@ -91,7 +91,7 @@ type Pick(output) = |> should throwAsyncExact typeof } - [] + [] let ``TaskSeq-pickAsync sad path raises KeyNotFoundException variant`` () = logStart output @@ -105,7 +105,7 @@ type Pick(output) = } - [] + [] let ``TaskSeq-pick happy path middle of seq`` () = logStart output @@ -117,7 +117,7 @@ type Pick(output) = twentyFive |> should equal "foo" } - [] + [] let ``TaskSeq-pickAsync happy path middle of seq`` () = logStart output @@ -129,7 +129,7 @@ type Pick(output) = twentyFive |> should equal "foo" } - [] + [] let ``TaskSeq-pick happy path first item of seq`` () = logStart output @@ -141,7 +141,7 @@ type Pick(output) = first |> should equal "first1" } - [] + [] let ``TaskSeq-pickAsync happy path first item of seq`` () = logStart output @@ -153,7 +153,7 @@ type Pick(output) = first |> should equal "first1" } - [] + [] let ``TaskSeq-pick happy path last item of seq`` () = logStart output @@ -165,7 +165,7 @@ type Pick(output) = last |> should equal "last50" } - [] + [] let ``TaskSeq-pickAsync happy path last item of seq`` () = logStart output @@ -182,7 +182,7 @@ type Pick(output) = // TaskSeq.tryPickAsync // - [] + [] let ``TaskSeq-tryPick on an empty sequence returns None`` () = logStart output @@ -194,7 +194,7 @@ type Pick(output) = nothing |> should be None' } - [] + [] let ``TaskSeq-tryPickAsync on an empty sequence returns None`` () = logStart output @@ -206,7 +206,7 @@ type Pick(output) = nothing |> should be None' } - [] + [] let ``TaskSeq-tryPick sad path returns None`` () = logStart output @@ -218,7 +218,7 @@ type Pick(output) = nothing |> should be None' } - [] + [] let ``TaskSeq-tryPickAsync sad path return None`` () = logStart output @@ -230,7 +230,7 @@ type Pick(output) = nothing |> should be None' } - [] + [] let ``TaskSeq-tryPick sad path returns None variant`` () = logStart output @@ -242,7 +242,7 @@ type Pick(output) = nothing |> should be None' } - [] + [] let ``TaskSeq-tryPickAsync sad path return None - variant`` () = logStart output @@ -255,7 +255,7 @@ type Pick(output) = } - [] + [] let ``TaskSeq-tryPick happy path middle of seq`` () = logStart output @@ -268,7 +268,7 @@ type Pick(output) = twentyFive |> should equal (Some "foo25") } - [] + [] let ``TaskSeq-tryPickAsync happy path middle of seq`` () = logStart output @@ -281,7 +281,7 @@ type Pick(output) = twentyFive |> should equal (Some "foo25") } - [] + [] let ``TaskSeq-tryPick happy path first item of seq`` () = logStart output @@ -294,7 +294,7 @@ type Pick(output) = first |> should equal (Some "foo1") } - [] + [] let ``TaskSeq-tryPickAsync happy path first item of seq`` () = logStart output @@ -307,7 +307,7 @@ type Pick(output) = first |> should equal (Some "foo1") } - [] + [] let ``TaskSeq-tryPick happy path last item of seq`` () = logStart output @@ -320,7 +320,7 @@ type Pick(output) = last |> should equal (Some "foo50") } - [] + [] let ``TaskSeq-tryPickAsync happy path last item of seq`` () = logStart output diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.PocTests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.PocTests.fs index 9e94f626..5eb7c01e 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.PocTests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.PocTests.fs @@ -17,7 +17,7 @@ open FSharpy type ``PoC's for seq of tasks``(output) = - [] + [] let ``Good: Show joining tasks with continuation is good`` () = logStart output @@ -27,7 +27,7 @@ type ``PoC's for seq of tasks``(output) = results |> should equal 10 } - [] + [] let ``Good: Show that joining tasks with 'bind' in task CE is good`` () = logStart output @@ -46,7 +46,7 @@ type ``PoC's for seq of tasks``(output) = results |> should equal <| Array.init len ((+) 1) } - [] + [] let ``Good: Show that joining tasks with 'taskSeq' is good`` () = logStart output @@ -66,7 +66,7 @@ type ``PoC's for seq of tasks``(output) = <| Array.init (Array.length results) ((+) 1) } - [] + [] let ``Bad: Show that joining tasks with 'traverseTaskResult' can be bad`` () = logStart output @@ -86,7 +86,7 @@ type ``PoC's for seq of tasks``(output) = | Error err -> failwith $"Impossible: {err}" } - [] + [] let ``Bad: Show that joining tasks as a list of tasks can be bad`` () = logStart output diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.Tests.CE.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Tests.CE.fs index 6402e0b1..def62005 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.Tests.CE.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Tests.CE.fs @@ -10,7 +10,7 @@ open System.Diagnostics type ``taskSeq Computation Expression``(output) = - [] + [] let ``CE taskSeq with several yield!`` () = logStart output @@ -28,7 +28,7 @@ type ``taskSeq Computation Expression``(output) = |> should equal (List.concat [ [ 1..10 ]; [ 1..5 ]; [ 1..10 ]; [ 1..5 ] ]) } - [] + [] let ``CE taskSeq with nested yield!`` () = logStart output @@ -65,7 +65,7 @@ type ``taskSeq Computation Expression``(output) = data |> should haveLength 150 } - [] + [] let ``CE taskSeq with nested deeply yield! perf test 8521 nested tasks`` () = logStart output @@ -123,7 +123,7 @@ type ``taskSeq Computation Expression``(output) = data |> should equal (List.ofSeq control) } - [] + [] let ``CE taskSeq with several return!`` () = logStart output @@ -141,7 +141,7 @@ type ``taskSeq Computation Expression``(output) = } - [] + [] let ``CE taskSeq with mixing yield! and yield`` () = logStart output @@ -162,7 +162,7 @@ type ``taskSeq Computation Expression``(output) = |> should equal (List.concat [ [ 1..10 ]; [ 42 ]; [ 1..5 ]; [ 42 ]; [ 1..10 ]; [ 42 ]; [ 1..5 ] ]) } - [] + [] let ``CE taskSeq: 1000 TaskDelay-delayed tasks using yield!`` () = logStart output @@ -175,7 +175,7 @@ type ``taskSeq Computation Expression``(output) = data |> should equal [ 1..1000 ] } - [] + [] let ``CE taskSeq: 1000 sync-running tasks using yield!`` () = logStart output @@ -188,7 +188,7 @@ type ``taskSeq Computation Expression``(output) = data |> should equal [ 1..1000 ] } - [] + [] let ``CE taskSeq: 5000 sync-running tasks using yield!`` () = logStart output @@ -200,7 +200,7 @@ type ``taskSeq Computation Expression``(output) = data |> should equal [ 1..5000 ] } - [] + [] let ``CE task: 1000 TaskDelay-delayed tasks using for-loop`` () = logStart output @@ -217,7 +217,7 @@ type ``taskSeq Computation Expression``(output) = i |> should equal 1000 } - [] + [] let ``CE task: 1000 list of sync-running tasks using for-loop`` () = logStart output @@ -234,7 +234,7 @@ type ``taskSeq Computation Expression``(output) = i |> should equal 1000 } - [] + [] let ``CE task: 5000 list of sync-running tasks using for-loop`` () = logStart output diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.Tests.Other.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.Tests.Other.fs index 3fe7162d..0f925b02 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.Tests.Other.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.Tests.Other.fs @@ -8,7 +8,7 @@ open FSharpy type ``Other functions``(output) = - [] + [] let ``TaskSeq-empty returns an empty sequence`` () = logStart output @@ -18,7 +18,7 @@ type ``Other functions``(output) = Seq.length sq |> should equal 0 } - [] + [] let ``TaskSeq-isEmpty returns true for empty`` () = logStart output @@ -27,7 +27,7 @@ type ``Other functions``(output) = isEmpty |> should be True } - [] + [] let ``TaskSeq-isEmpty returns false for non-empty`` () = logStart output diff --git a/src/FSharpy.TaskSeq.Test/TaskSeq.ToXXX.Tests.fs b/src/FSharpy.TaskSeq.Test/TaskSeq.ToXXX.Tests.fs index 63d4d125..b5395fd0 100644 --- a/src/FSharpy.TaskSeq.Test/TaskSeq.ToXXX.Tests.fs +++ b/src/FSharpy.TaskSeq.Test/TaskSeq.ToXXX.Tests.fs @@ -22,7 +22,7 @@ open System.Collections.Generic type ``Conversion-To``(output) = - [] + [] let ``TaskSeq-toArrayAsync should succeed`` () = logStart output @@ -32,7 +32,7 @@ type ``Conversion-To``(output) = results |> should equal [| 1..10 |] } - [] + [] let ``TaskSeq-toListAsync should succeed`` () = logStart output @@ -42,7 +42,7 @@ type ``Conversion-To``(output) = results |> should equal [ 1..10 ] } - [] + [] let ``TaskSeq-toSeqCachedAsync should succeed`` () = logStart output @@ -52,7 +52,7 @@ type ``Conversion-To``(output) = results |> Seq.toArray |> should equal [| 1..10 |] } - [] + [] let ``TaskSeq-toIListAsync should succeed`` () = logStart output @@ -62,7 +62,7 @@ type ``Conversion-To``(output) = results |> Seq.toArray |> should equal [| 1..10 |] } - [] + [] let ``TaskSeq-toResizeArray should succeed`` () = logStart output @@ -72,19 +72,19 @@ type ``Conversion-To``(output) = 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 [| 1..10 |] - [] + [] let ``TaskSeq-toList should succeed and be blocking`` () = let tq = createDummyTaskSeq 10 let (results: list<_>) = tq |> TaskSeq.toList results |> should equal [ 1..10 ] - [] + [] let ``TaskSeq-toSeqCached should succeed and be blocking`` () = let tq = createDummyTaskSeq 10 let (results: seq<_>) = tq |> TaskSeq.toSeqCached