Skip to content

Commit b159ff5

Browse files
authored
Merge branch 'main' into feature/test-coverage-improvements-edge-cases
2 parents 04f04e6 + 0b5b735 commit b159ff5

1 file changed

Lines changed: 192 additions & 0 deletions

File tree

tests/FSharp.Control.AsyncSeq.Tests/AsyncSeqTests.fs

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1882,6 +1882,86 @@ let ``Seq.ofAsyncSeq with exception`` () =
18821882
Seq.ofAsyncSeq asyncSeqWithError |> Seq.toList |> ignore
18831883
) |> ignore
18841884

1885+
[<Test>]
1886+
let ``AsyncSeq.intervalMs should generate sequence with timestamps``() =
1887+
let result =
1888+
AsyncSeq.intervalMs 50
1889+
|> AsyncSeq.take 3
1890+
|> AsyncSeq.toListAsync
1891+
|> AsyncOps.timeoutMs 1000
1892+
|> Async.RunSynchronously
1893+
1894+
Assert.AreEqual(3, result.Length)
1895+
// Verify timestamps are increasing
1896+
Assert.IsTrue(result.[1] > result.[0])
1897+
Assert.IsTrue(result.[2] > result.[1])
1898+
1899+
[<Test>]
1900+
let ``AsyncSeq.intervalMs with zero period should work``() =
1901+
let result =
1902+
AsyncSeq.intervalMs 0
1903+
|> AsyncSeq.take 2
1904+
|> AsyncSeq.toListAsync
1905+
|> AsyncOps.timeoutMs 500
1906+
|> Async.RunSynchronously
1907+
1908+
Assert.AreEqual(2, result.Length)
1909+
1910+
[<Test>]
1911+
let ``AsyncSeq.take with negative count should throw ArgumentException``() =
1912+
Assert.Throws<System.ArgumentException>(fun () ->
1913+
AsyncSeq.ofSeq [1;2;3]
1914+
|> AsyncSeq.take -1
1915+
|> AsyncSeq.toListAsync
1916+
|> Async.RunSynchronously
1917+
|> ignore
1918+
) |> ignore
1919+
1920+
[<Test>]
1921+
let ``AsyncSeq.skip with negative count should throw ArgumentException``() =
1922+
Assert.Throws<System.ArgumentException>(fun () ->
1923+
AsyncSeq.ofSeq [1;2;3]
1924+
|> AsyncSeq.skip -1
1925+
|> AsyncSeq.toListAsync
1926+
|> Async.RunSynchronously
1927+
|> ignore
1928+
) |> ignore
1929+
1930+
[<Test>]
1931+
let ``AsyncSeq.take zero should return empty sequence``() =
1932+
let expected = []
1933+
let actual =
1934+
AsyncSeq.ofSeq [1;2;3]
1935+
|> AsyncSeq.take 0
1936+
|> AsyncSeq.toListAsync
1937+
|> Async.RunSynchronously
1938+
1939+
Assert.AreEqual(expected, actual)
1940+
1941+
[<Test>]
1942+
let ``AsyncSeq.skip zero should return original sequence``() =
1943+
let expected = [1;2;3]
1944+
let actual =
1945+
AsyncSeq.ofSeq [1;2;3]
1946+
|> AsyncSeq.skip 0
1947+
|> AsyncSeq.toListAsync
1948+
|> Async.RunSynchronously
1949+
1950+
Assert.AreEqual(expected, actual)
1951+
1952+
[<Test>]
1953+
let ``AsyncSeq.replicateInfinite with exception should propagate exception``() =
1954+
let exceptionMsg = "test exception"
1955+
let expected = System.ArgumentException(exceptionMsg)
1956+
1957+
Assert.Throws<System.ArgumentException>(fun () ->
1958+
AsyncSeq.replicateInfinite (raise expected)
1959+
|> AsyncSeq.take 2
1960+
|> AsyncSeq.toListAsync
1961+
|> Async.RunSynchronously
1962+
|> ignore
1963+
) |> ignore
1964+
18851965
#if (NETSTANDARD2_1 || NETCOREAPP3_0)
18861966
[<Test>]
18871967
let ``AsyncSeq.ofAsyncEnum should roundtrip successfully``() =
@@ -2102,3 +2182,115 @@ let ``AsyncSeq.mapAsyncParallel with exception should propagate``() =
21022182
Assert.Throws<System.Exception>(fun () ->
21032183
exceptionSeq |> AsyncSeq.toListSynchronously |> ignore
21042184
) |> ignore
2185+
2186+
// ----------------------------------------------------------------------------
2187+
// Additional Coverage Tests targeting uncovered edge cases and branches
2188+
2189+
[<Test>]
2190+
let ``AsyncSeq.bufferByCount with size 1 should work`` () =
2191+
let source = asyncSeq { yield 1; yield 2; yield 3 }
2192+
let result = AsyncSeq.bufferByCount 1 source |> AsyncSeq.toListSynchronously
2193+
Assert.AreEqual([[|1|]; [|2|]; [|3|]], result)
2194+
2195+
[<Test>]
2196+
let ``AsyncSeq.bufferByCount with empty sequence should return empty`` () =
2197+
let result = AsyncSeq.bufferByCount 2 AsyncSeq.empty |> AsyncSeq.toListSynchronously
2198+
Assert.AreEqual([], result)
2199+
2200+
[<Test>]
2201+
let ``AsyncSeq.bufferByCount with size larger than sequence should return partial`` () =
2202+
let source = asyncSeq { yield 1; yield 2 }
2203+
let result = AsyncSeq.bufferByCount 5 source |> AsyncSeq.toListSynchronously
2204+
Assert.AreEqual([[|1; 2|]], result)
2205+
2206+
[<Test>]
2207+
let ``AsyncSeq.pairwise with empty sequence should return empty`` () =
2208+
let result = AsyncSeq.pairwise AsyncSeq.empty |> AsyncSeq.toListSynchronously
2209+
Assert.AreEqual([], result)
2210+
2211+
[<Test>]
2212+
let ``AsyncSeq.pairwise with single element should return empty`` () =
2213+
let source = asyncSeq { yield 42 }
2214+
let result = AsyncSeq.pairwise source |> AsyncSeq.toListSynchronously
2215+
Assert.AreEqual([], result)
2216+
2217+
[<Test>]
2218+
let ``AsyncSeq.pairwise with three elements should produce two pairs`` () =
2219+
let source = asyncSeq { yield 1; yield 2; yield 3 }
2220+
let result = AsyncSeq.pairwise source |> AsyncSeq.toListSynchronously
2221+
Assert.AreEqual([(1, 2); (2, 3)], result)
2222+
2223+
[<Test>]
2224+
let ``AsyncSeq.distinctUntilChangedWith should work with custom equality`` () =
2225+
let source = asyncSeq { yield "a"; yield "A"; yield "B"; yield "b"; yield "c" }
2226+
let customEq (x: string) (y: string) = x.ToLower() = y.ToLower()
2227+
let result = AsyncSeq.distinctUntilChangedWith customEq source |> AsyncSeq.toListSynchronously
2228+
Assert.AreEqual(["a"; "B"; "c"], result)
2229+
2230+
[<Test>]
2231+
let ``AsyncSeq.distinctUntilChangedWith with all same elements should return single`` () =
2232+
let source = asyncSeq { yield 1; yield 1; yield 1 }
2233+
let result = AsyncSeq.distinctUntilChangedWith (=) source |> AsyncSeq.toListSynchronously
2234+
Assert.AreEqual([1], result)
2235+
2236+
[<Test>]
2237+
let ``AsyncSeq.append with both sequences having exceptions should propagate first`` () =
2238+
async {
2239+
let seq1 = asyncSeq { yield 1; failwith "error1" }
2240+
let seq2 = asyncSeq { yield 2; failwith "error2" }
2241+
let combined = AsyncSeq.append seq1 seq2
2242+
2243+
try
2244+
let! _ = AsyncSeq.toListAsync combined
2245+
Assert.Fail("Expected exception to be thrown")
2246+
with
2247+
| ex when ex.Message = "error1" ->
2248+
() // Expected - first sequence's error should be thrown
2249+
| ex ->
2250+
Assert.Fail($"Unexpected exception: {ex.Message}")
2251+
} |> Async.RunSynchronously
2252+
2253+
[<Test>]
2254+
let ``AsyncSeq.concat with nested exceptions should propagate properly`` () =
2255+
async {
2256+
let nested = asyncSeq {
2257+
yield asyncSeq { yield 1; yield 2 }
2258+
yield asyncSeq { failwith "nested error" }
2259+
yield asyncSeq { yield 3 }
2260+
}
2261+
let flattened = AsyncSeq.concat nested
2262+
2263+
try
2264+
let! result = AsyncSeq.toListAsync flattened
2265+
Assert.Fail("Expected exception to be thrown")
2266+
with
2267+
| ex when ex.Message = "nested error" ->
2268+
() // Expected
2269+
| ex ->
2270+
Assert.Fail($"Unexpected exception: {ex.Message}")
2271+
} |> Async.RunSynchronously
2272+
2273+
[<Test>]
2274+
let ``AsyncSeq.choose with all None should return empty`` () =
2275+
let source = asyncSeq { yield 1; yield 2; yield 3 }
2276+
let result = AsyncSeq.choose (fun _ -> None) source |> AsyncSeq.toListSynchronously
2277+
Assert.AreEqual([], result)
2278+
2279+
[<Test>]
2280+
let ``AsyncSeq.choose with mixed Some and None should filter correctly`` () =
2281+
let source = asyncSeq { yield 1; yield 2; yield 3; yield 4 }
2282+
let chooser x = if x % 2 = 0 then Some (x * 2) else None
2283+
let result = AsyncSeq.choose chooser source |> AsyncSeq.toListSynchronously
2284+
Assert.AreEqual([4; 8], result)
2285+
2286+
[<Test>]
2287+
let ``AsyncSeq.chooseAsync with async transformation should work`` () =
2288+
async {
2289+
let source = asyncSeq { yield 1; yield 2; yield 3; yield 4 }
2290+
let chooserAsync x = async {
2291+
if x % 2 = 0 then return Some (x * 3) else return None
2292+
}
2293+
let! result = AsyncSeq.chooseAsync chooserAsync source |> AsyncSeq.toListAsync
2294+
Assert.AreEqual([6; 12], result)
2295+
} |> Async.RunSynchronously
2296+

0 commit comments

Comments
 (0)