From 3bfedca0f9faad468dadbafd25415ce7fa5913da Mon Sep 17 00:00:00 2001 From: Abel Braaksma Date: Wed, 20 Dec 2023 23:27:34 +0100 Subject: [PATCH] Add/update tests for `where` and `whereAsync` --- .../TaskSeq.Filter.Tests.fs | 119 ++++++++++++------ src/FSharp.Control.TaskSeq.Test/TestUtils.fs | 7 ++ 2 files changed, 87 insertions(+), 39 deletions(-) diff --git a/src/FSharp.Control.TaskSeq.Test/TaskSeq.Filter.Tests.fs b/src/FSharp.Control.TaskSeq.Test/TaskSeq.Filter.Tests.fs index fb67ad9f..0e189cc5 100644 --- a/src/FSharp.Control.TaskSeq.Test/TaskSeq.Filter.Tests.fs +++ b/src/FSharp.Control.TaskSeq.Test/TaskSeq.Filter.Tests.fs @@ -10,67 +10,108 @@ open FSharp.Control // // TaskSeq.filter // TaskSeq.filterAsync +// TaskSeq.where +// TaskSeq.whereAsync // module EmptySeq = [] - let ``Null source is invalid`` () = + let ``TaskSeq-filter or where with null source raises`` () = assertNullArg <| fun () -> TaskSeq.filter (fun _ -> false) null assertNullArg <| fun () -> TaskSeq.filterAsync (fun _ -> Task.fromResult false) null + assertNullArg + <| fun () -> TaskSeq.where (fun _ -> false) null + + assertNullArg + <| fun () -> TaskSeq.whereAsync (fun _ -> Task.fromResult false) null + [)>] - let ``TaskSeq-filter has no effect`` variant = - Gen.getEmptyVariant variant - |> TaskSeq.filter ((=) 12) - |> TaskSeq.toListAsync - |> Task.map (List.isEmpty >> should be True) + let ``TaskSeq-filter or where has no effect`` variant = task { + do! + Gen.getEmptyVariant variant + |> TaskSeq.filter ((=) 12) + |> TaskSeq.toListAsync + |> Task.map (List.isEmpty >> should be True) + + do! + Gen.getEmptyVariant variant + |> TaskSeq.where ((=) 12) + |> TaskSeq.toListAsync + |> Task.map (List.isEmpty >> should be True) + } [)>] - let ``TaskSeq-filterAsync has no effect`` variant = - Gen.getEmptyVariant variant - |> TaskSeq.filterAsync (fun x -> task { return x = 12 }) - |> TaskSeq.toListAsync - |> Task.map (List.isEmpty >> should be True) + let ``TaskSeq-filterAsync or whereAsync has no effect`` variant = task { + do! + Gen.getEmptyVariant variant + |> TaskSeq.filterAsync (fun x -> task { return x = 12 }) + |> TaskSeq.toListAsync + |> Task.map (List.isEmpty >> should be True) + + do! + Gen.getEmptyVariant variant + |> TaskSeq.whereAsync (fun x -> task { return x = 12 }) + |> TaskSeq.toListAsync + |> Task.map (List.isEmpty >> should be True) + } module Immutable = [)>] - let ``TaskSeq-filter filters correctly`` variant = - Gen.getSeqImmutable variant - |> TaskSeq.filter ((<=) 5) // greater than - |> TaskSeq.map char - |> TaskSeq.map ((+) '@') - |> TaskSeq.toArrayAsync - |> Task.map (String >> should equal "EFGHIJ") + let ``TaskSeq-filter or where filters correctly`` variant = task { + do! + Gen.getSeqImmutable variant + |> TaskSeq.filter ((<=) 5) // greater than + |> verifyDigitsAsString "EFGHIJ" + + do! + Gen.getSeqImmutable variant + |> TaskSeq.where ((>) 5) // greater than + |> verifyDigitsAsString "ABCD" + } [)>] - let ``TaskSeq-filterAsync filters correctly`` variant = - Gen.getSeqImmutable variant - |> TaskSeq.filterAsync (fun x -> task { return x <= 5 }) - |> TaskSeq.map char - |> TaskSeq.map ((+) '@') - |> TaskSeq.toArrayAsync - |> Task.map (String >> should equal "ABCDE") + let ``TaskSeq-filterAsync or whereAsync filters correctly`` variant = task { + do! + Gen.getSeqImmutable variant + |> TaskSeq.filterAsync (fun x -> task { return x <= 5 }) + |> verifyDigitsAsString "ABCDE" + + do! + Gen.getSeqImmutable variant + |> TaskSeq.whereAsync (fun x -> task { return x > 5 }) + |> verifyDigitsAsString "FGHIJ" + + } module SideEffects = [)>] - let ``TaskSeq-filter filters correctly`` variant = - Gen.getSeqWithSideEffect variant - |> TaskSeq.filter ((<=) 5) // greater than - |> TaskSeq.map char - |> TaskSeq.map ((+) '@') - |> TaskSeq.toArrayAsync - |> Task.map (String >> should equal "EFGHIJ") + let ``TaskSeq-filter filters correctly`` variant = task { + do! + Gen.getSeqWithSideEffect variant + |> TaskSeq.filter ((<=) 5) // greater than or equal + |> verifyDigitsAsString "EFGHIJ" + + do! + Gen.getSeqWithSideEffect variant + |> TaskSeq.where ((>) 5) // less than + |> verifyDigitsAsString "ABCD" + } [)>] - let ``TaskSeq-filterAsync filters correctly`` variant = - Gen.getSeqWithSideEffect variant - |> TaskSeq.filterAsync (fun x -> task { return x <= 5 }) - |> TaskSeq.map char - |> TaskSeq.map ((+) '@') - |> TaskSeq.toArrayAsync - |> Task.map (String >> should equal "ABCDE") + let ``TaskSeq-filterAsync filters correctly`` variant = task { + do! + Gen.getSeqWithSideEffect variant + |> TaskSeq.filterAsync (fun x -> task { return x <= 5 }) + |> verifyDigitsAsString "ABCDE" + + do! + Gen.getSeqWithSideEffect variant + |> TaskSeq.whereAsync (fun x -> task { return x > 5 && x < 9 }) + |> verifyDigitsAsString "FGH" + } diff --git a/src/FSharp.Control.TaskSeq.Test/TestUtils.fs b/src/FSharp.Control.TaskSeq.Test/TestUtils.fs index d8afe1b6..c98b4797 100644 --- a/src/FSharp.Control.TaskSeq.Test/TestUtils.fs +++ b/src/FSharp.Control.TaskSeq.Test/TestUtils.fs @@ -141,6 +141,13 @@ module TestUtils = |> TaskSeq.toArrayAsync |> Task.map (should equal [| 1..10 |]) + /// Turns a sequence of numbers into a string, starting with A for '1' + let verifyDigitsAsString expected = + TaskSeq.map char + >> TaskSeq.map ((+) '@') + >> TaskSeq.toArrayAsync + >> Task.map (String >> should equal expected) + /// Delays (no spin-wait!) between 20 and 70ms, assuming a 15.6ms resolution clock let longDelay () = task { do! Task.Delay(Random().Next(20, 70)) }