@@ -4300,3 +4300,139 @@ let ``AsyncSeq.partitionAsync splits by async predicate`` () =
43004300 |> Async.RunSynchronously
43014301 Assert.AreEqual([| 2 ; 4 ; 6 |], trues)
43024302 Assert.AreEqual([| 1 ; 3 ; 5 |], falses)
4303+
4304+ // ===== mapiAsync =====
4305+
4306+ [<Test>]
4307+ let ``AsyncSeq.mapiAsync maps elements with their int64 index`` () =
4308+ let result =
4309+ AsyncSeq.ofSeq [ " a" ; " b" ; " c" ]
4310+ |> AsyncSeq.mapiAsync ( fun i x -> async { return sprintf " %d :%s " i x })
4311+ |> AsyncSeq.toArrayAsync
4312+ |> Async.RunSynchronously
4313+ Assert.AreEqual([| " 0:a" ; " 1:b" ; " 2:c" |], result)
4314+
4315+ [<Test>]
4316+ let ``AsyncSeq.mapiAsync on empty sequence returns empty`` () =
4317+ let result =
4318+ AsyncSeq.empty< string>
4319+ |> AsyncSeq.mapiAsync ( fun i x -> async { return sprintf " %d :%s " i x })
4320+ |> AsyncSeq.toArrayAsync
4321+ |> Async.RunSynchronously
4322+ Assert.AreEqual([||], result)
4323+
4324+ [<Test>]
4325+ let ``AsyncSeq.mapiAsync index is int64 and starts at zero`` () =
4326+ let indices = ResizeArray< int64>()
4327+ AsyncSeq.ofSeq [ 10 ; 20 ; 30 ]
4328+ |> AsyncSeq.mapiAsync ( fun i x -> async { indices.Add( i); return x })
4329+ |> AsyncSeq.toArrayAsync
4330+ |> Async.RunSynchronously
4331+ |> ignore
4332+ Assert.AreEqual([| 0 L; 1 L; 2 L |], indices.ToArray())
4333+
4334+ [<Test>]
4335+ let ``AsyncSeq.mapiAsync matches mapi for pure function`` () =
4336+ for n in 0 .. 20 do
4337+ let ls = List.init n ( fun x -> x + 1 )
4338+ let expected = ls |> List.mapi ( fun i x -> i * x) |> List.toArray
4339+ let actual =
4340+ AsyncSeq.ofSeq ls
4341+ |> AsyncSeq.mapiAsync ( fun i x -> async { return int i * x })
4342+ |> AsyncSeq.toArrayAsync
4343+ |> Async.RunSynchronously
4344+ Assert.AreEqual( expected, actual)
4345+
4346+ // ===== tryPickAsync / pickAsync =====
4347+
4348+ [<Test>]
4349+ let ``AsyncSeq.tryPickAsync returns Some for first matching element`` () =
4350+ let result =
4351+ AsyncSeq.ofSeq [ 1 ; 2 ; 3 ; 4 ; 5 ]
4352+ |> AsyncSeq.tryPickAsync ( fun x -> async { return if x > 3 then Some ( x * 10 ) else None })
4353+ |> Async.RunSynchronously
4354+ Assert.AreEqual( Some 40 , result)
4355+
4356+ [<Test>]
4357+ let ``AsyncSeq.tryPickAsync returns None when no element matches`` () =
4358+ let result =
4359+ AsyncSeq.ofSeq [ 1 ; 2 ; 3 ]
4360+ |> AsyncSeq.tryPickAsync ( fun x -> async { return if x > 99 then Some x else None })
4361+ |> Async.RunSynchronously
4362+ Assert.AreEqual( None, result)
4363+
4364+ [<Test>]
4365+ let ``AsyncSeq.tryPickAsync returns None for empty sequence`` () =
4366+ let result =
4367+ AsyncSeq.empty< int>
4368+ |> AsyncSeq.tryPickAsync ( fun x -> async { return Some x })
4369+ |> Async.RunSynchronously
4370+ Assert.AreEqual( None, result)
4371+
4372+ [<Test>]
4373+ let ``AsyncSeq.tryPickAsync returns first match not last`` () =
4374+ let result =
4375+ AsyncSeq.ofSeq [ 10 ; 20 ; 30 ]
4376+ |> AsyncSeq.tryPickAsync ( fun x -> async { return if x % 10 = 0 then Some x else None })
4377+ |> Async.RunSynchronously
4378+ Assert.AreEqual( Some 10 , result)
4379+
4380+ [<Test>]
4381+ let ``AsyncSeq.pickAsync returns value for first matching element`` () =
4382+ let result =
4383+ AsyncSeq.ofSeq [ 1 ; 2 ; 3 ; 4 ; 5 ]
4384+ |> AsyncSeq.pickAsync ( fun x -> async { return if x = 3 then Some " three" else None })
4385+ |> Async.RunSynchronously
4386+ Assert.AreEqual( " three" , result)
4387+
4388+ [<Test>]
4389+ let ``AsyncSeq.pickAsync raises KeyNotFoundException when no match`` () =
4390+ Assert.Throws< System.Collections.Generic.KeyNotFoundException>( fun () ->
4391+ AsyncSeq.ofSeq [ 1 ; 2 ; 3 ]
4392+ |> AsyncSeq.pickAsync ( fun x -> async { return if x > 99 then Some x else None })
4393+ |> Async.RunSynchronously
4394+ |> ignore) |> ignore
4395+
4396+ [<Test>]
4397+ let ``AsyncSeq.pickAsync raises KeyNotFoundException for empty sequence`` () =
4398+ Assert.Throws< System.Collections.Generic.KeyNotFoundException>( fun () ->
4399+ AsyncSeq.empty< int>
4400+ |> AsyncSeq.pickAsync ( fun x -> async { return Some x })
4401+ |> Async.RunSynchronously
4402+ |> ignore) |> ignore
4403+
4404+ // ===== groupByAsync =====
4405+
4406+ [<Test>]
4407+ let ``AsyncSeq.groupByAsync groups elements by async projection`` () =
4408+ let result =
4409+ AsyncSeq.ofSeq [ 1 .. 6 ]
4410+ |> AsyncSeq.groupByAsync ( fun x -> async { return x % 2 })
4411+ |> AsyncSeq.mapAsyncParallel ( fun ( key , grp ) -> async {
4412+ let! items = AsyncSeq.toArrayAsync grp
4413+ return key, Array.sort items })
4414+ |> AsyncSeq.toArrayAsync
4415+ |> Async.RunSynchronously
4416+ |> Array.sortBy fst
4417+ Assert.AreEqual([| ( 0 , [| 2 ; 4 ; 6 |]); ( 1 , [| 1 ; 3 ; 5 |]) |], result)
4418+
4419+ [<Test>]
4420+ let ``AsyncSeq.groupByAsync on empty sequence returns empty`` () =
4421+ let result =
4422+ AsyncSeq.empty< int>
4423+ |> AsyncSeq.groupByAsync ( fun x -> async { return x % 2 })
4424+ |> AsyncSeq.toArrayAsync
4425+ |> Async.RunSynchronously
4426+ Assert.AreEqual([||], result)
4427+
4428+ [<Test>]
4429+ let ``AsyncSeq.groupByAsync with all - same key produces single group`` () =
4430+ let result =
4431+ AsyncSeq.ofSeq [ 1 ; 2 ; 3 ]
4432+ |> AsyncSeq.groupByAsync ( fun _ -> async { return " same" })
4433+ |> AsyncSeq.mapAsyncParallel ( fun ( key , grp ) -> async {
4434+ let! items = AsyncSeq.toArrayAsync grp
4435+ return key, Array.sort items })
4436+ |> AsyncSeq.toArrayAsync
4437+ |> Async.RunSynchronously
4438+ Assert.AreEqual([| ( " same" , [| 1 ; 2 ; 3 |]) |], result)
0 commit comments