nim-codex/tests/codex/utils/testasynciter.nim

161 lines
3.7 KiB
Nim

import std/sugar
import pkg/questionable
import pkg/chronos
import pkg/codex/utils/asynciter
import ../../asynctest
import ../helpers
asyncchecksuite "Test AsyncIter":
test "Should be finished":
let iter = AsyncIter[int].empty()
check:
iter.finished == true
test "Should map each item using `map`":
let
iter1 = AsyncIter[int].new(0..<5).delayBy(10.millis)
iter2 = map[int, string](iter1,
proc (i: int): Future[string] {.async.} =
$i
)
var collected: seq[string]
for fut in iter2:
collected.add(await fut)
check:
collected == @["0", "1", "2", "3", "4"]
test "Should leave only odd items using `filter`":
let
iter1 = AsyncIter[int].new(0..<5).delayBy(10.millis)
iter2 = await filter[int](iter1,
proc (i: int): Future[bool] {.async.} =
(i mod 2) == 1
)
var collected: seq[int]
for fut in iter2:
collected.add(await fut)
check:
collected == @[1, 3]
test "Should leave only odd items using `mapFilter`":
let
iter1 = AsyncIter[int].new(0..<5).delayBy(10.millis)
iter2 = await mapFilter[int, string](iter1,
proc (i: int): Future[?string] {.async.} =
if (i mod 2) == 1:
some($i)
else:
string.none
)
var collected: seq[string]
for fut in iter2:
collected.add(await fut)
check:
collected == @["1", "3"]
test "Should yield all items before err using `map`":
let
iter1 = AsyncIter[int].new(0..<5).delayBy(10.millis)
iter2 = map[int, string](iter1,
proc (i: int): Future[string] {.async.} =
if i < 3:
return $i
else:
raise newException(CatchableError, "Some error")
)
var collected: seq[string]
expect CatchableError:
for fut in iter2:
collected.add(await fut)
check:
collected == @["0", "1", "2"]
iter2.finished
test "Should yield all items before err using `filter`":
let
iter1 = AsyncIter[int].new(0..<5).delayBy(10.millis)
iter2 = await filter[int](iter1,
proc (i: int): Future[bool] {.async.} =
if i < 3:
return true
else:
raise newException(CatchableError, "Some error")
)
var collected: seq[int]
expect CatchableError:
for fut in iter2:
collected.add(await fut)
check:
collected == @[0, 1, 2]
iter2.finished
test "Should yield all items before err using `mapFilter`":
let
iter1 = AsyncIter[int].new(0..<5).delayBy(10.millis)
iter2 = await mapFilter[int, string](iter1,
proc (i: int): Future[?string] {.async.} =
if i < 3:
return some($i)
else:
raise newException(CatchableError, "Some error")
)
var collected: seq[string]
expect CatchableError:
for fut in iter2:
collected.add(await fut)
check:
collected == @["0", "1", "2"]
iter2.finished
test "Should propagate cancellation error immediately":
let
fut = newFuture[?string]("testasynciter")
let
iter1 = AsyncIter[int].new(0..<5).delayBy(10.millis)
iter2 = await mapFilter[int, string](iter1,
proc (i: int): Future[?string] {.async.} =
if i < 3:
return some($i)
else:
return await fut
)
proc cancelFut(): Future[void] {.async.} =
await sleepAsync(100.millis)
await fut.cancelAndWait()
asyncSpawn(cancelFut())
var collected: seq[string]
expect CancelledError:
for fut in iter2:
collected.add(await fut)
check:
collected == @["0", "1"]
iter2.finished