simplify future tests (#196)

This commit is contained in:
Jacek Sieka 2021-06-04 12:28:04 +02:00 committed by GitHub
parent a46cc59627
commit 252e5d0d50
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 165 additions and 224 deletions

View File

@ -84,19 +84,19 @@ suite "Future[T] behavior test suite":
except: except:
result = -6 result = -6
proc test1(): bool = test "Async undefined behavior (#7758) test":
var fut = testFuture1() var fut = testFuture1()
poll() poll()
poll() poll()
if not fut.finished: if not fut.finished:
poll() poll()
result = fut.finished check: fut.finished
proc test2(): bool = test "Immediately completed asynchronous procedure test":
var fut = testFuture3() var fut = testFuture3()
result = fut.finished check: fut.finished
proc test3(): string = test "Future[T] callbacks are invoked in reverse order (#7197) test":
var testResult = "" var testResult = ""
var fut = testFuture1() var fut = testFuture1()
fut.addCallback proc(udata: pointer) = fut.addCallback proc(udata: pointer) =
@ -111,10 +111,12 @@ suite "Future[T] behavior test suite":
testResult &= "5" testResult &= "5"
discard waitFor(fut) discard waitFor(fut)
poll() poll()
if fut.finished:
result = testResult
proc test4(): string = check:
fut.finished
testResult == "12345"
test "Future[T] callbacks not changing order after removeCallback()":
var testResult = "" var testResult = ""
var fut = testFuture1() var fut = testFuture1()
proc cb1(udata: pointer) = proc cb1(udata: pointer) =
@ -135,13 +137,15 @@ suite "Future[T] behavior test suite":
fut.removeCallback cb3 fut.removeCallback cb3
discard waitFor(fut) discard waitFor(fut)
poll() poll()
if fut.finished: check:
result = testResult fut.finished
testResult == "1245"
proc test5(): int = test "wait[T]() test":
result = waitFor(testFuture4()) check:
waitFor(testFuture4()) == 6
proc testAsyncDiscard(): int = test "discard result Future[T] test":
var completedFutures = 0 var completedFutures = 0
proc client1() {.async.} = proc client1() {.async.} =
@ -206,14 +210,16 @@ suite "Future[T] behavior test suite":
discard client5f() discard client5f()
waitFor(sleepAsync(2000.milliseconds)) waitFor(sleepAsync(2000.milliseconds))
result = completedFutures check:
completedFutures == 10
proc testAllFuturesZero(): bool = test "allFutures(zero) test":
var tseq = newSeq[Future[int]]() var tseq = newSeq[Future[int]]()
var fut = allFutures(tseq) var fut = allFutures(tseq)
result = fut.finished check:
fut.finished
proc testAllFuturesVarargs(): int = test "allFutures(varargs) test":
var completedFutures = 0 var completedFutures = 0
proc vlient1() {.async.} = proc vlient1() {.async.} =
@ -322,22 +328,21 @@ suite "Future[T] behavior test suite":
raise newException(ValueError, "") raise newException(ValueError, "")
waitFor(allFutures(vlient1(), vlient2(), vlient3(), vlient4(), vlient5())) waitFor(allFutures(vlient1(), vlient2(), vlient3(), vlient4(), vlient5()))
# 5 completed futures = 5
result += completedFutures
check: completedFutures == 5
completedFutures = 0 completedFutures = 0
waitFor(allFutures(vlient1(), vlient1f(), waitFor(allFutures(vlient1(), vlient1f(),
vlient2(), vlient2f(), vlient2(), vlient2f(),
vlient3(), vlient3f(), vlient3(), vlient3f(),
vlient4(), vlient4f(), vlient4(), vlient4f(),
vlient5(), vlient5f())) vlient5(), vlient5f()))
# 10 completed futures = 10
result += completedFutures check: completedFutures == 10
completedFutures = 0 completedFutures = 0
waitFor(allFutures(client1(), client2(), client3(), client4(), client5())) waitFor(allFutures(client1(), client2(), client3(), client4(), client5()))
# 5 completed futures check: completedFutures == 5
result += completedFutures
completedFutures = 0 completedFutures = 0
waitFor(allFutures(client1(), client1f(), waitFor(allFutures(client1(), client1f(),
@ -345,10 +350,9 @@ suite "Future[T] behavior test suite":
client3(), client3f(), client3(), client3f(),
client4(), client4f(), client4(), client4f(),
client5(), client5f())) client5(), client5f()))
# 10 completed futures = 10 check: completedFutures == 10
result += completedFutures
proc testAllFuturesSeq(): int = test "allFutures(varargs) test":
var completedFutures = 0 var completedFutures = 0
var vfutures = newSeq[Future[void]]() var vfutures = newSeq[Future[void]]()
var nfutures = newSeq[Future[int]]() var nfutures = newSeq[Future[int]]()
@ -468,7 +472,7 @@ suite "Future[T] behavior test suite":
waitFor(allFutures(vfutures)) waitFor(allFutures(vfutures))
# 5 * 10 completed futures = 50 # 5 * 10 completed futures = 50
result += completedFutures check: completedFutures == 50
completedFutures = 0 completedFutures = 0
vfutures.setLen(0) vfutures.setLen(0)
@ -486,7 +490,7 @@ suite "Future[T] behavior test suite":
waitFor(allFutures(vfutures)) waitFor(allFutures(vfutures))
# 10 * 10 completed futures = 100 # 10 * 10 completed futures = 100
result += completedFutures check: completedFutures == 100
completedFutures = 0 completedFutures = 0
nfutures.setLen(0) nfutures.setLen(0)
@ -499,7 +503,7 @@ suite "Future[T] behavior test suite":
waitFor(allFutures(nfutures)) waitFor(allFutures(nfutures))
# 5 * 10 completed futures = 50 # 5 * 10 completed futures = 50
result += completedFutures check: completedFutures == 50
completedFutures = 0 completedFutures = 0
nfutures.setLen(0) nfutures.setLen(0)
@ -518,9 +522,9 @@ suite "Future[T] behavior test suite":
waitFor(allFutures(nfutures)) waitFor(allFutures(nfutures))
# 10 * 10 completed futures = 100 # 10 * 10 completed futures = 100
result += completedFutures check: completedFutures == 100
proc testAllCompleted(operation: int): bool = test "allFutures() already completed test":
proc client1(): Future[int] {.async.} = proc client1(): Future[int] {.async.} =
result = 1 result = 1
@ -528,19 +532,31 @@ suite "Future[T] behavior test suite":
if true: if true:
raise newException(ValueError, "") raise newException(ValueError, "")
if operation == 1:
var fut = allFutures(client1(), client2()) var fut = allFutures(client1(), client2())
result = fut.finished() and not(fut.failed()) check:
elif operation == 2: fut.finished()
var fut = allFinished(client1(), client2()) not(fut.failed())
result = fut.finished() and not(fut.failed()) and (len(fut.read()) == 2)
proc testOneZero(): bool = test "allFinished() already completed test":
proc client1(): Future[int] {.async.} =
result = 1
proc client2(): Future[int] {.async.} =
if true:
raise newException(ValueError, "")
var fut = allFinished(client1(), client2())
check:
fut.finished()
not(fut.failed())
len(fut.read()) == 2
test "one(zero) test":
var tseq = newSeq[Future[int]]() var tseq = newSeq[Future[int]]()
var fut = one(tseq) var fut = one(tseq)
result = fut.finished and fut.failed check: fut.finished and fut.failed
proc testOneVarargs(): bool = test "one(varargs) test":
proc vlient1() {.async.} = proc vlient1() {.async.} =
await sleepAsync(100.milliseconds) await sleepAsync(100.milliseconds)
@ -577,8 +593,10 @@ suite "Future[T] behavior test suite":
var fut33 = vlient1() var fut33 = vlient1()
var res3 = waitFor(one(fut31, fut32, fut33)) var res3 = waitFor(one(fut31, fut32, fut33))
if fut11 != res1 or fut22 != res2 or fut33 != res3: check:
return false fut11 == res1
fut22 == res2
fut33 == res3
var cut11 = client1() var cut11 = client1()
var cut12 = client2() var cut12 = client2()
@ -595,12 +613,12 @@ suite "Future[T] behavior test suite":
var cut33 = client1() var cut33 = client1()
var res6 = waitFor(one(cut31, cut32, cut33)) var res6 = waitFor(one(cut31, cut32, cut33))
if cut11 != res4 or cut22 != res5 or cut33 != res6: check:
return false cut11 == res4
cut22 == res5
cut33 == res6
result = true test "one(seq) test":
proc testOneSeq(): bool =
proc vlient1() {.async.} = proc vlient1() {.async.} =
await sleepAsync(100.milliseconds) await sleepAsync(100.milliseconds)
@ -637,8 +655,10 @@ suite "Future[T] behavior test suite":
var v32 = vlient1() var v32 = vlient1()
var res3 = waitFor(one(@[v30, v31, v32])) var res3 = waitFor(one(@[v30, v31, v32]))
if res1 != v10 or res2 != v21 or res3 != v32: check:
return false res1 == v10
res2 == v21
res3 == v32
var c10 = client1() var c10 = client1()
var c11 = client2() var c11 = client2()
@ -655,12 +675,12 @@ suite "Future[T] behavior test suite":
var c32 = client1() var c32 = client1()
var res6 = waitFor(one(@[c30, c31, c32])) var res6 = waitFor(one(@[c30, c31, c32]))
if res4 != c10 or res5 != c21 or res6 != c32: check:
return false res4 == c10
res5 == c21
res6 == c32
result = true test "one(completed) test":
proc testOneCompleted(): bool =
proc client1(): Future[int] {.async.} = proc client1(): Future[int] {.async.} =
result = 1 result = 1
@ -681,8 +701,13 @@ suite "Future[T] behavior test suite":
var f31 = client3() var f31 = client3()
var fut2 = one(f31, f21, f11) var fut2 = one(f31, f21, f11)
result = fut1.finished() and not(fut1.failed()) and fut1.read() == f10 and check:
fut2.finished() and not(fut2.failed()) and fut2.read() == f21 fut1.finished()
not(fut1.failed())
fut1.read() == f10
fut2.finished()
not(fut2.failed())
fut2.read() == f21
proc waitForNeLocal[T](fut: Future[T]): Future[T] = proc waitForNeLocal[T](fut: Future[T]): Future[T] =
## **Blocks** the current thread until the specified future completes. ## **Blocks** the current thread until the specified future completes.
@ -690,8 +715,7 @@ suite "Future[T] behavior test suite":
poll() poll()
result = fut result = fut
proc testOr(): bool = test "or() test":
proc client1() {.async.} = proc client1() {.async.} =
await sleepAsync(200.milliseconds) await sleepAsync(200.milliseconds)
@ -719,18 +743,19 @@ suite "Future[T] behavior test suite":
var f9 = waitForNeLocal(client3() or client4()) var f9 = waitForNeLocal(client3() or client4())
var f10 = waitForNeLocal(client4() or client3()) var f10 = waitForNeLocal(client4() or client3())
result = (f1.finished() and not(f1.failed())) and check:
(f2.finished() and not(f2.failed())) and (f1.finished() and not(f1.failed()))
(f3.finished() and not(f3.failed())) and (f2.finished() and not(f2.failed()))
(f4.finished() and not(f4.failed())) and (f3.finished() and not(f3.failed()))
(f5.finished() and f5.failed()) and (f4.finished() and not(f4.failed()))
(f6.finished() and f6.failed()) and (f5.finished() and f5.failed())
(f7.finished() and not(f7.failed())) and (f6.finished() and f6.failed())
(f8.finished() and not(f8.failed())) and (f7.finished() and not(f7.failed()))
(f9.finished() and f9.failed()) and (f8.finished() and not(f8.failed()))
(f9.finished() and f9.failed())
(f10.finished() and f10.failed()) (f10.finished() and f10.failed())
proc testOrCompleted(): bool = test "or() already completed test":
proc client1(): Future[int] {.async.} = proc client1(): Future[int] {.async.} =
result = 1 result = 1
proc client2(): Future[int] {.async.} = proc client2(): Future[int] {.async.} =
@ -747,14 +772,15 @@ suite "Future[T] behavior test suite":
var f5 = client3() or client1() var f5 = client3() or client1()
var f6 = client3() or client2() var f6 = client3() or client2()
result = (f1.finished() and not(f1.failed())) and check:
(f1.finished() and not(f1.failed())) and
(f2.finished() and not(f2.failed())) and (f2.finished() and not(f2.failed())) and
(f3.finished() and f3.failed()) and (f3.finished() and f3.failed()) and
(f4.finished() and f4.failed()) and (f4.finished() and f4.failed()) and
(f5.finished() and not(f5.failed())) and (f5.finished() and not(f5.failed())) and
(f6.finished() and f6.failed()) (f6.finished() and f6.failed())
proc testCancelIter(): bool = test "cancel() async procedure test":
var completed = 0 var completed = 0
proc client1() {.async.} = proc client1() {.async.} =
@ -778,19 +804,15 @@ suite "Future[T] behavior test suite":
# Future must not be cancelled immediately, because it has many nested # Future must not be cancelled immediately, because it has many nested
# futures. # futures.
if fut.cancelled(): check:
return false not fut.cancelled()
try: expect(CancelledError):
waitFor fut waitFor fut
result = false
except CancelledError:
if completed == 0:
result = true
else:
result = false
proc testCancelAndWait(): bool = check: completed == 0
test "cancelAndWait() test":
var completed = 0 var completed = 0
proc client1() {.async.} = proc client1() {.async.} =
@ -811,11 +833,10 @@ suite "Future[T] behavior test suite":
var fut = client4() var fut = client4()
waitFor cancelAndWait(fut) waitFor cancelAndWait(fut)
if not(fut.cancelled()): check:
return false fut.cancelled()
return true
proc testBreakCancellation(): bool = test "Break cancellation propagation test":
var completed = 0 var completed = 0
proc client1() {.async.} = proc client1() {.async.} =
@ -835,17 +856,12 @@ suite "Future[T] behavior test suite":
waitFor fut1 waitFor fut1
waitFor cancelAndWait(fut2) waitFor cancelAndWait(fut2)
if fut1.cancelled(): check:
return false not fut1.cancelled()
if fut2.cancelled(): not fut2.cancelled()
return false completed == 2
if completed != 2: test "Cancellation callback test":
return false
return true
proc testCancelCallback(): bool =
var completed = 0 var completed = 0
var cancelled = 0 var cancelled = 0
@ -873,11 +889,10 @@ suite "Future[T] behavior test suite":
fut.cancel() fut.cancel()
waitFor(sleepAsync(500.milliseconds)) waitFor(sleepAsync(500.milliseconds))
if not(fut.cancelled()): check:
return false fut.cancelled()
if (completed != 0) and (cancelled != 1): completed == 0
return false cancelled == 1
return true
proc testWaitAsync(): Future[bool] {.async.} = proc testWaitAsync(): Future[bool] {.async.} =
var neverFlag1, neverFlag2, neverFlag3: bool var neverFlag1, neverFlag2, neverFlag3: bool
@ -960,15 +975,14 @@ suite "Future[T] behavior test suite":
(raceFut2.state == FutureState.Cancelled) and (raceFut2.state == FutureState.Cancelled) and
(raceFut3.state == FutureState.Cancelled) (raceFut3.state == FutureState.Cancelled)
proc testWait(): bool = test "Cancellation wait() test":
waitFor(testWaitAsync()) check: waitFor(testWaitAsync())
proc testWithTimeout(): bool = test "Cancellation withTimeout() test":
waitFor(testWithTimeoutAsync()) check: waitFor(testWithTimeoutAsync())
proc testCancellationRace(): bool =
waitFor(testCancellationRaceAsync())
test "Cancellation race test":
check: waitFor(testCancellationRaceAsync())
proc testAsyncSpawnAsync(): Future[bool] {.async.} = proc testAsyncSpawnAsync(): Future[bool] {.async.} =
@ -1018,10 +1032,10 @@ suite "Future[T] behavior test suite":
return true return true
proc testAsyncSpawn(): bool = test "asyncSpawn() test":
waitFor(testAsyncSpawnAsync()) check: waitFor(testAsyncSpawnAsync())
proc testSrcLocation(): bool = test "location test":
# WARNING: This test is very sensitive to line numbers and module name. # WARNING: This test is very sensitive to line numbers and module name.
proc macroFuture() {.async.} = proc macroFuture() {.async.} =
@ -1058,16 +1072,15 @@ suite "Future[T] behavior test suite":
(loc.line == line) and ($loc.file == file) and (loc.line == line) and ($loc.file == file) and
(loc.procedure == procedure) (loc.procedure == procedure)
let r10 = chk(loc10, "testfut.nim", 1027, "macroFuture") check:
let r11 = chk(loc11, "testfut.nim", 1028, "") chk(loc10, "testfut.nim", 1041, "macroFuture")
let r20 = chk(loc20, "testfut.nim", 1040, "template") chk(loc11, "testfut.nim", 1042, "")
let r21 = chk(loc21, "testfut.nim", 1043, "") chk(loc20, "testfut.nim", 1054, "template")
let r30 = chk(loc30, "testfut.nim", 1037, "procedure") chk(loc21, "testfut.nim", 1057, "")
let r31 = chk(loc31, "testfut.nim", 1044, "") chk(loc30, "testfut.nim", 1051, "procedure")
chk(loc31, "testfut.nim", 1058, "")
r10 and r11 and r20 and r21 and r30 and r31 test "withTimeout(fut) should wait cancellation test":
proc testWithTimeoutCancelAndWait(): bool =
proc futureNeverEnds(): Future[void] = proc futureNeverEnds(): Future[void] =
newFuture[void]("neverending.future") newFuture[void]("neverending.future")
@ -1087,9 +1100,9 @@ suite "Future[T] behavior test suite":
except CatchableError: except CatchableError:
return false return false
waitFor testWithTimeout() check: waitFor testWithTimeout()
proc testWaitCancelAndWait(): bool = test "wait(fut) should wait cancellation test":
proc futureNeverEnds(): Future[void] = proc futureNeverEnds(): Future[void] =
newFuture[void]("neverending.future") newFuture[void]("neverending.future")
@ -1111,16 +1124,19 @@ suite "Future[T] behavior test suite":
except CatchableError: except CatchableError:
return false return false
waitFor testWait() check: waitFor testWait()
proc testRaceZero(): bool = test "race(zero) test":
var tseq = newSeq[FutureBase]() var tseq = newSeq[FutureBase]()
var fut1 = race(tseq) var fut1 = race(tseq)
var fut2 = race() var fut2 = race()
var fut3 = race([]) var fut3 = race([])
fut1.failed() and fut2.failed() and fut3.failed() check:
fut1.failed()
fut2.failed()
fut3.failed()
proc testRaceVarargs(): bool = test "race(varargs) test":
proc vlient1() {.async.} = proc vlient1() {.async.} =
await sleepAsync(100.milliseconds) await sleepAsync(100.milliseconds)
@ -1174,15 +1190,13 @@ suite "Future[T] behavior test suite":
var fut43 = ilient3() var fut43 = ilient3()
var res4 = waitFor(race(fut41, fut42, fut43)) var res4 = waitFor(race(fut41, fut42, fut43))
if (FutureBase(fut11) != res1) or check:
(FutureBase(fut22) != res2) or FutureBase(fut11) == res1
(FutureBase(fut33) != res3) or FutureBase(fut22) == res2
(FutureBase(fut41) != res4): FutureBase(fut33) == res3
return false FutureBase(fut41) == res4
result = true test "race(seq) test":
proc testRaceSeq(): bool =
proc vlient1() {.async.} = proc vlient1() {.async.} =
await sleepAsync(100.milliseconds) await sleepAsync(100.milliseconds)
@ -1240,15 +1254,13 @@ suite "Future[T] behavior test suite":
var res4 = waitFor(race(@[FutureBase(v40), FutureBase(v41), var res4 = waitFor(race(@[FutureBase(v40), FutureBase(v41),
FutureBase(v42)])) FutureBase(v42)]))
if res1 != FutureBase(v10) or check:
res2 != FutureBase(v21) or res1 == FutureBase(v10)
res3 != FutureBase(v32) or res2 == FutureBase(v21)
res4 != FutureBase(v40): res3 == FutureBase(v32)
return false res4 == FutureBase(v40)
result = true test "race() already completed test":
proc testRaceCompleted(): bool =
proc client1(): Future[int] {.async.} = proc client1(): Future[int] {.async.} =
result = 1 result = 1
@ -1269,10 +1281,11 @@ suite "Future[T] behavior test suite":
var f31 = client3() var f31 = client3()
var fut2 = race(f31, f21, f11) var fut2 = race(f31, f21, f11)
result = (fut1.done() and fut1.read() == FutureBase(f10)) and check:
(fut2.done() and fut2.read() == FutureBase(f21)) fut1.done() and fut1.read() == FutureBase(f10)
fut2.done() and fut2.read() == FutureBase(f21)
proc testRaceCancelled(): bool = test "race() cancellation test":
proc client1() {.async.} = proc client1() {.async.} =
await sleepAsync(100.milliseconds) await sleepAsync(100.milliseconds)
@ -1290,88 +1303,16 @@ suite "Future[T] behavior test suite":
var fut = race(f1, f2, f3) var fut = race(f1, f2, f3)
waitFor(cancelAndWait(fut)) waitFor(cancelAndWait(fut))
if f1.finished() or f2.finished() or f3.finished(): check:
return false not f1.finished()
not f2.finished()
not f3.finished()
waitFor(sleepAsync(400.milliseconds)) waitFor(sleepAsync(400.milliseconds))
if not(f1.finished()) or not(f2.finished()) or not(f3.finished()):
return false
return true check:
f1.finished()
f2.finished()
f3.finished()
test "Async undefined behavior (#7758) test":
check test1() == true
test "Immediately completed asynchronous procedure test":
check test2() == true
test "Future[T] callbacks are invoked in reverse order (#7197) test":
check test3() == "12345"
test "Future[T] callbacks not changing order after removeCallback()":
check test4() == "1245"
test "wait[T]() test":
check test5() == 6
test "discard result Future[T] test":
check testAsyncDiscard() == 10
test "allFutures(zero) test":
check testAllFuturesZero() == true
test "allFutures(varargs) test":
check testAllFuturesVarargs() == 30
test "allFutures(varargs) test":
check testAllFuturesSeq() == 300
test "allFutures() already completed test":
check testAllCompleted(1) == true
test "allFinished() already completed test":
check testAllCompleted(2) == true
test "one(zero) test":
check testOneZero() == true
test "one(varargs) test":
check testOneVarargs() == true
test "one(seq) test":
check testOneSeq() == true
test "one() already completed test":
check testOneCompleted() == true
test "or() test":
check testOr() == true
test "or() already completed test":
check testOrCompleted() == true
test "race(zero) test":
check testRaceZero() == true
test "race(varargs) test":
check testRaceVarargs() == true
test "race(seq) test":
check testRaceSeq() == true
test "race() already completed test":
check testRaceCompleted() == true
test "race() cancellation test":
check testRaceCancelled() == true
test "cancel() async procedure test":
check testCancelIter() == true
test "cancelAndWait() test":
check testCancelAndWait() == true
test "Break cancellation propagation test":
check testBreakCancellation() == true
test "Cancellation callback test":
check testCancelCallback() == true
test "Cancellation wait() test":
check testWait() == true
test "Cancellation withTimeout() test":
check testWithTimeout() == true
test "Cancellation race test":
check testCancellationRace() == true
test "asyncSpawn() test":
check testAsyncSpawn() == true
test "location test":
check testSrcLocation() == true
test "withTimeout(fut) should wait cancellation test":
check testWithTimeoutCancelAndWait()
test "wait(fut) should wait cancellation test":
check testWaitCancelAndWait()