2019-02-06 14:49:11 +00:00
|
|
|
# Chronos Test Suite
|
|
|
|
# (c) Copyright 2018-Present
|
2018-05-22 23:28:16 +00:00
|
|
|
# Status Research & Development GmbH
|
|
|
|
#
|
|
|
|
# Licensed under either of
|
|
|
|
# Apache License, version 2.0, (LICENSE-APACHEv2)
|
|
|
|
# MIT license (LICENSE-MIT)
|
|
|
|
import unittest
|
2019-02-06 14:49:11 +00:00
|
|
|
import ../chronos
|
2018-05-22 23:28:16 +00:00
|
|
|
|
2019-03-30 22:31:10 +00:00
|
|
|
suite "Future[T] behavior test suite":
|
|
|
|
proc testFuture1(): Future[int] {.async.} =
|
|
|
|
await sleepAsync(0.milliseconds)
|
2018-05-22 23:28:16 +00:00
|
|
|
|
2019-03-30 22:31:10 +00:00
|
|
|
proc testFuture2(): Future[int] {.async.} =
|
|
|
|
return 1
|
2018-05-22 23:28:16 +00:00
|
|
|
|
2019-03-30 22:31:10 +00:00
|
|
|
proc testFuture3(): Future[int] {.async.} =
|
|
|
|
result = await testFuture2()
|
2018-05-22 23:28:16 +00:00
|
|
|
|
2019-03-30 22:31:10 +00:00
|
|
|
proc testFuture100(): Future[int] {.async.} =
|
|
|
|
await sleepAsync(100.milliseconds)
|
2019-03-24 16:57:36 +00:00
|
|
|
|
2019-03-30 22:31:10 +00:00
|
|
|
proc testFuture4(): Future[int] {.async.} =
|
|
|
|
## Test for not immediately completed future and timeout = -1
|
2018-07-20 08:58:01 +00:00
|
|
|
result = 0
|
2019-03-30 22:31:10 +00:00
|
|
|
try:
|
|
|
|
var res = await wait(testFuture1(), InfiniteDuration)
|
|
|
|
result = 1
|
|
|
|
except:
|
|
|
|
result = 0
|
2018-07-20 08:58:01 +00:00
|
|
|
|
2019-03-30 22:31:10 +00:00
|
|
|
if result == 0:
|
|
|
|
return -1
|
2018-07-20 08:58:01 +00:00
|
|
|
|
2019-03-30 22:31:10 +00:00
|
|
|
## Test for immediately completed future and timeout = -1
|
2018-07-20 08:58:01 +00:00
|
|
|
result = 0
|
2019-03-30 22:31:10 +00:00
|
|
|
try:
|
|
|
|
var res = await wait(testFuture2(), InfiniteDuration)
|
|
|
|
result = 2
|
|
|
|
except:
|
|
|
|
result = 0
|
2018-07-20 08:58:01 +00:00
|
|
|
|
2019-03-30 22:31:10 +00:00
|
|
|
if result == 0:
|
|
|
|
return -2
|
2019-03-15 00:54:16 +00:00
|
|
|
|
2019-03-30 22:31:10 +00:00
|
|
|
## Test for not immediately completed future and timeout = 0
|
|
|
|
result = 0
|
|
|
|
try:
|
|
|
|
var res = await wait(testFuture1(), 0.milliseconds)
|
|
|
|
except AsyncTimeoutError:
|
|
|
|
result = 3
|
2019-03-15 00:54:16 +00:00
|
|
|
|
2019-03-30 22:31:10 +00:00
|
|
|
if result == 0:
|
|
|
|
return -3
|
2019-03-15 00:54:16 +00:00
|
|
|
|
2019-03-30 22:31:10 +00:00
|
|
|
## Test for immediately completed future and timeout = 0
|
|
|
|
result = 0
|
|
|
|
try:
|
|
|
|
var res = await wait(testFuture2(), 0.milliseconds)
|
|
|
|
result = 4
|
|
|
|
except:
|
|
|
|
result = 0
|
2019-03-15 00:54:16 +00:00
|
|
|
|
2019-03-30 22:31:10 +00:00
|
|
|
if result == 0:
|
|
|
|
return -4
|
2019-03-15 00:54:16 +00:00
|
|
|
|
2019-03-30 22:31:10 +00:00
|
|
|
## Test for future which cannot be completed in timeout period
|
|
|
|
result = 0
|
|
|
|
try:
|
|
|
|
var res = await wait(testFuture100(), 50.milliseconds)
|
|
|
|
except AsyncTimeoutError:
|
|
|
|
result = 5
|
|
|
|
|
|
|
|
if result == 0:
|
|
|
|
return -5
|
|
|
|
|
|
|
|
## Test for future which will be completed before timeout exceeded.
|
|
|
|
try:
|
|
|
|
var res = await wait(testFuture100(), 500.milliseconds)
|
|
|
|
result = 6
|
|
|
|
except:
|
|
|
|
result = -6
|
|
|
|
|
|
|
|
proc test1(): bool =
|
|
|
|
var fut = testFuture1()
|
|
|
|
poll()
|
|
|
|
poll()
|
|
|
|
if not fut.finished:
|
|
|
|
poll()
|
|
|
|
result = fut.finished
|
|
|
|
|
|
|
|
proc test2(): bool =
|
|
|
|
var fut = testFuture3()
|
|
|
|
result = fut.finished
|
|
|
|
|
|
|
|
proc test3(): string =
|
|
|
|
var testResult = ""
|
|
|
|
var fut = testFuture1()
|
|
|
|
fut.addCallback proc(udata: pointer) =
|
|
|
|
testResult &= "1"
|
|
|
|
fut.addCallback proc(udata: pointer) =
|
|
|
|
testResult &= "2"
|
|
|
|
fut.addCallback proc(udata: pointer) =
|
|
|
|
testResult &= "3"
|
|
|
|
fut.addCallback proc(udata: pointer) =
|
|
|
|
testResult &= "4"
|
|
|
|
fut.addCallback proc(udata: pointer) =
|
|
|
|
testResult &= "5"
|
|
|
|
discard waitFor(fut)
|
|
|
|
poll()
|
|
|
|
if fut.finished:
|
|
|
|
result = testResult
|
|
|
|
|
|
|
|
proc test4(): string =
|
|
|
|
var testResult = ""
|
|
|
|
var fut = testFuture1()
|
|
|
|
proc cb1(udata: pointer) =
|
|
|
|
testResult &= "1"
|
|
|
|
proc cb2(udata: pointer) =
|
|
|
|
testResult &= "2"
|
|
|
|
proc cb3(udata: pointer) =
|
|
|
|
testResult &= "3"
|
|
|
|
proc cb4(udata: pointer) =
|
|
|
|
testResult &= "4"
|
|
|
|
proc cb5(udata: pointer) =
|
|
|
|
testResult &= "5"
|
|
|
|
fut.addCallback cb1
|
|
|
|
fut.addCallback cb2
|
|
|
|
fut.addCallback cb3
|
|
|
|
fut.addCallback cb4
|
|
|
|
fut.addCallback cb5
|
|
|
|
fut.removeCallback cb3
|
|
|
|
discard waitFor(fut)
|
|
|
|
poll()
|
|
|
|
if fut.finished:
|
|
|
|
result = testResult
|
|
|
|
|
|
|
|
proc test5(): int =
|
|
|
|
result = waitFor(testFuture4())
|
|
|
|
|
|
|
|
proc testAllVarargs(): int =
|
|
|
|
var completedFutures = 0
|
|
|
|
|
|
|
|
proc vlient1() {.async.} =
|
|
|
|
await sleepAsync(100.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
|
|
|
|
proc vlient2() {.async.} =
|
|
|
|
await sleepAsync(200.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
|
|
|
|
proc vlient3() {.async.} =
|
|
|
|
await sleepAsync(300.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
|
|
|
|
proc vlient4() {.async.} =
|
|
|
|
await sleepAsync(400.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
|
|
|
|
proc vlient5() {.async.} =
|
|
|
|
await sleepAsync(500.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
|
|
|
|
proc vlient1f() {.async.} =
|
|
|
|
await sleepAsync(100.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
if true:
|
|
|
|
raise newException(ValueError, "")
|
|
|
|
|
|
|
|
proc vlient2f() {.async.} =
|
|
|
|
await sleepAsync(100.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
if true:
|
|
|
|
raise newException(ValueError, "")
|
|
|
|
|
|
|
|
proc vlient3f() {.async.} =
|
|
|
|
await sleepAsync(100.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
if true:
|
|
|
|
raise newException(ValueError, "")
|
|
|
|
|
|
|
|
proc vlient4f() {.async.} =
|
|
|
|
await sleepAsync(100.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
if true:
|
|
|
|
raise newException(ValueError, "")
|
|
|
|
|
|
|
|
proc vlient5f() {.async.} =
|
|
|
|
await sleepAsync(100.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
if true:
|
|
|
|
raise newException(ValueError, "")
|
|
|
|
|
|
|
|
proc client1(): Future[int] {.async.} =
|
|
|
|
await sleepAsync(100.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
result = 1
|
|
|
|
|
|
|
|
proc client2(): Future[int] {.async.} =
|
|
|
|
await sleepAsync(200.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
result = 1
|
|
|
|
|
|
|
|
proc client3(): Future[int] {.async.} =
|
|
|
|
await sleepAsync(300.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
result = 1
|
|
|
|
|
|
|
|
proc client4(): Future[int] {.async.} =
|
|
|
|
await sleepAsync(400.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
result = 1
|
|
|
|
|
|
|
|
proc client5(): Future[int] {.async.} =
|
|
|
|
await sleepAsync(500.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
result = 1
|
|
|
|
|
|
|
|
proc client1f(): Future[int] {.async.} =
|
|
|
|
await sleepAsync(100.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
if true:
|
|
|
|
raise newException(ValueError, "")
|
|
|
|
|
|
|
|
proc client2f(): Future[int] {.async.} =
|
|
|
|
await sleepAsync(200.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
if true:
|
|
|
|
raise newException(ValueError, "")
|
|
|
|
|
|
|
|
proc client3f(): Future[int] {.async.} =
|
|
|
|
await sleepAsync(300.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
if true:
|
|
|
|
raise newException(ValueError, "")
|
|
|
|
|
|
|
|
proc client4f(): Future[int] {.async.} =
|
|
|
|
await sleepAsync(400.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
if true:
|
|
|
|
raise newException(ValueError, "")
|
|
|
|
|
|
|
|
proc client5f(): Future[int] {.async.} =
|
|
|
|
await sleepAsync(500.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
if true:
|
|
|
|
raise newException(ValueError, "")
|
|
|
|
|
|
|
|
waitFor(all(vlient1(), vlient2(), vlient3(), vlient4(), vlient5()))
|
|
|
|
# 5 completed futures = 5
|
|
|
|
result += completedFutures
|
|
|
|
completedFutures = 0
|
|
|
|
try:
|
|
|
|
waitFor(all(vlient1(), vlient1f(),
|
|
|
|
vlient2(), vlient2f(),
|
|
|
|
vlient3(), vlient3f(),
|
|
|
|
vlient4(), vlient4f(),
|
|
|
|
vlient5(), vlient5f()))
|
|
|
|
result -= 10000
|
|
|
|
except:
|
|
|
|
discard
|
|
|
|
# 10 completed futures = 10
|
|
|
|
result += completedFutures
|
|
|
|
|
|
|
|
completedFutures = 0
|
|
|
|
var res = waitFor(all(client1(), client2(), client3(), client4(), client5()))
|
|
|
|
for item in res:
|
|
|
|
result += item
|
|
|
|
# 5 completed futures + 5 values = 10
|
|
|
|
result += completedFutures
|
|
|
|
|
|
|
|
completedFutures = 0
|
|
|
|
try:
|
|
|
|
var res = waitFor(all(client1(), client1f(),
|
|
|
|
client2(), client2f(),
|
|
|
|
client3(), client3f(),
|
|
|
|
client4(), client4f(),
|
|
|
|
client5(), client5f()))
|
|
|
|
result -= 10000
|
|
|
|
except:
|
|
|
|
discard
|
|
|
|
# 10 completed futures = 10
|
|
|
|
result += completedFutures
|
|
|
|
|
|
|
|
proc testAllSeq(): int =
|
|
|
|
var completedFutures = 0
|
|
|
|
var vfutures = newSeq[Future[void]]()
|
|
|
|
var nfutures = newSeq[Future[int]]()
|
|
|
|
|
|
|
|
proc vlient1() {.async.} =
|
|
|
|
await sleepAsync(100.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
|
|
|
|
proc vlient2() {.async.} =
|
|
|
|
await sleepAsync(200.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
|
|
|
|
proc vlient3() {.async.} =
|
|
|
|
await sleepAsync(300.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
|
|
|
|
proc vlient4() {.async.} =
|
|
|
|
await sleepAsync(400.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
|
|
|
|
proc vlient5() {.async.} =
|
|
|
|
await sleepAsync(500.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
|
|
|
|
proc vlient1f() {.async.} =
|
|
|
|
await sleepAsync(100.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
if true:
|
|
|
|
raise newException(ValueError, "")
|
|
|
|
|
|
|
|
proc vlient2f() {.async.} =
|
|
|
|
await sleepAsync(100.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
if true:
|
|
|
|
raise newException(ValueError, "")
|
|
|
|
|
|
|
|
proc vlient3f() {.async.} =
|
|
|
|
await sleepAsync(100.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
if true:
|
|
|
|
raise newException(ValueError, "")
|
|
|
|
|
|
|
|
proc vlient4f() {.async.} =
|
|
|
|
await sleepAsync(100.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
if true:
|
|
|
|
raise newException(ValueError, "")
|
|
|
|
|
|
|
|
proc vlient5f() {.async.} =
|
|
|
|
await sleepAsync(100.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
if true:
|
|
|
|
raise newException(ValueError, "")
|
|
|
|
|
|
|
|
proc client1(): Future[int] {.async.} =
|
|
|
|
await sleepAsync(100.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
result = 1
|
|
|
|
|
|
|
|
proc client2(): Future[int] {.async.} =
|
|
|
|
await sleepAsync(200.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
result = 1
|
|
|
|
|
|
|
|
proc client3(): Future[int] {.async.} =
|
|
|
|
await sleepAsync(300.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
result = 1
|
|
|
|
|
|
|
|
proc client4(): Future[int] {.async.} =
|
|
|
|
await sleepAsync(400.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
result = 1
|
|
|
|
|
|
|
|
proc client5(): Future[int] {.async.} =
|
|
|
|
await sleepAsync(500.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
result = 1
|
|
|
|
|
|
|
|
proc client1f(): Future[int] {.async.} =
|
|
|
|
await sleepAsync(100.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
if true:
|
|
|
|
raise newException(ValueError, "")
|
|
|
|
|
|
|
|
proc client2f(): Future[int] {.async.} =
|
|
|
|
await sleepAsync(200.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
if true:
|
|
|
|
raise newException(ValueError, "")
|
|
|
|
|
|
|
|
proc client3f(): Future[int] {.async.} =
|
|
|
|
await sleepAsync(300.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
if true:
|
|
|
|
raise newException(ValueError, "")
|
|
|
|
|
|
|
|
proc client4f(): Future[int] {.async.} =
|
|
|
|
await sleepAsync(400.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
if true:
|
|
|
|
raise newException(ValueError, "")
|
|
|
|
|
|
|
|
proc client5f(): Future[int] {.async.} =
|
|
|
|
await sleepAsync(500.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
if true:
|
|
|
|
raise newException(ValueError, "")
|
|
|
|
|
|
|
|
vfutures.setLen(0)
|
|
|
|
for i in 0..<10:
|
|
|
|
vfutures.add(vlient1())
|
|
|
|
vfutures.add(vlient2())
|
|
|
|
vfutures.add(vlient3())
|
|
|
|
vfutures.add(vlient4())
|
|
|
|
vfutures.add(vlient5())
|
2019-03-15 00:54:16 +00:00
|
|
|
|
|
|
|
waitFor(all(vfutures))
|
2019-03-30 22:31:10 +00:00
|
|
|
# 5 * 10 completed futures = 50
|
|
|
|
result += completedFutures
|
|
|
|
|
|
|
|
completedFutures = 0
|
|
|
|
vfutures.setLen(0)
|
|
|
|
for i in 0..<10:
|
|
|
|
vfutures.add(vlient1())
|
|
|
|
vfutures.add(vlient1f())
|
|
|
|
vfutures.add(vlient2())
|
|
|
|
vfutures.add(vlient2f())
|
|
|
|
vfutures.add(vlient3())
|
|
|
|
vfutures.add(vlient3f())
|
|
|
|
vfutures.add(vlient4())
|
|
|
|
vfutures.add(vlient4f())
|
|
|
|
vfutures.add(vlient5())
|
|
|
|
vfutures.add(vlient5f())
|
|
|
|
|
|
|
|
try:
|
|
|
|
waitFor(all(vfutures))
|
|
|
|
result -= 10000
|
|
|
|
except:
|
|
|
|
discard
|
|
|
|
# 10 * 10 completed futures = 100
|
|
|
|
result += completedFutures
|
|
|
|
|
|
|
|
completedFutures = 0
|
|
|
|
nfutures.setLen(0)
|
|
|
|
for i in 0..<10:
|
|
|
|
nfutures.add(client1())
|
|
|
|
nfutures.add(client2())
|
|
|
|
nfutures.add(client3())
|
|
|
|
nfutures.add(client4())
|
|
|
|
nfutures.add(client5())
|
|
|
|
|
|
|
|
var res = waitFor(all(nfutures))
|
|
|
|
for i in 0..<len(nfutures):
|
|
|
|
result += res[i]
|
|
|
|
# 5 * 10 completed futures + 5 * 10 results = 100
|
|
|
|
result += completedFutures
|
|
|
|
|
|
|
|
completedFutures = 0
|
|
|
|
nfutures.setLen(0)
|
|
|
|
for i in 0..<10:
|
|
|
|
nfutures.add(client1())
|
|
|
|
nfutures.add(client1f())
|
|
|
|
nfutures.add(client2())
|
|
|
|
nfutures.add(client2f())
|
|
|
|
nfutures.add(client3())
|
|
|
|
nfutures.add(client3f())
|
|
|
|
nfutures.add(client4())
|
|
|
|
nfutures.add(client4f())
|
|
|
|
nfutures.add(client5())
|
|
|
|
nfutures.add(client5f())
|
|
|
|
|
|
|
|
try:
|
|
|
|
var results = waitFor(all(nfutures))
|
|
|
|
result -= 10000
|
|
|
|
except:
|
|
|
|
discard
|
|
|
|
|
|
|
|
# 10 * 10 completed futures + 0 * 10 results = 100
|
|
|
|
result += completedFutures
|
|
|
|
|
|
|
|
proc testAsyncDiscard(): int =
|
|
|
|
var completedFutures = 0
|
|
|
|
|
|
|
|
proc client1() {.async.} =
|
|
|
|
await sleepAsync(100.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
|
|
|
|
proc client2() {.async.} =
|
|
|
|
await sleepAsync(200.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
|
|
|
|
proc client3() {.async.} =
|
|
|
|
await sleepAsync(300.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
|
|
|
|
proc client4() {.async.} =
|
|
|
|
await sleepAsync(400.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
|
|
|
|
proc client5() {.async.} =
|
|
|
|
await sleepAsync(500.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
|
|
|
|
proc client1f() {.async.} =
|
|
|
|
await sleepAsync(100.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
if true:
|
|
|
|
raise newException(ValueError, "")
|
|
|
|
|
|
|
|
proc client2f() {.async.} =
|
|
|
|
await sleepAsync(200.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
if true:
|
|
|
|
raise newException(ValueError, "")
|
|
|
|
|
|
|
|
proc client3f() {.async.} =
|
|
|
|
await sleepAsync(300.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
if true:
|
|
|
|
raise newException(ValueError, "")
|
|
|
|
|
|
|
|
proc client4f() {.async.} =
|
|
|
|
await sleepAsync(400.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
if true:
|
|
|
|
raise newException(ValueError, "")
|
|
|
|
|
|
|
|
proc client5f() {.async.} =
|
|
|
|
await sleepAsync(500.milliseconds)
|
|
|
|
inc(completedFutures)
|
|
|
|
if true:
|
|
|
|
raise newException(ValueError, "")
|
|
|
|
|
|
|
|
asyncDiscard client1()
|
|
|
|
asyncDiscard client1f()
|
|
|
|
asyncDiscard client2()
|
|
|
|
asyncDiscard client2f()
|
|
|
|
asyncDiscard client3()
|
|
|
|
asyncDiscard client3f()
|
|
|
|
asyncDiscard client4()
|
|
|
|
asyncDiscard client4f()
|
|
|
|
asyncDiscard client5()
|
|
|
|
asyncDiscard client5f()
|
|
|
|
|
|
|
|
waitFor(sleepAsync(2000.milliseconds))
|
|
|
|
result = completedFutures
|
|
|
|
|
|
|
|
proc testAllZero(): bool =
|
|
|
|
var tseq = newSeq[Future[int]]()
|
|
|
|
var fut = all(tseq)
|
|
|
|
result = fut.finished
|
|
|
|
|
2019-06-04 16:51:35 +00:00
|
|
|
proc testOneIndexZero(): bool =
|
|
|
|
var tseq = newSeq[Future[int]]()
|
|
|
|
var fut = oneIndex(tseq)
|
|
|
|
result = fut.finished and fut.failed
|
|
|
|
|
|
|
|
proc testOneValueZero(): bool =
|
|
|
|
var tseq = newSeq[Future[int]]()
|
|
|
|
var fut = oneValue(tseq)
|
|
|
|
result = fut.finished and fut.failed
|
|
|
|
|
|
|
|
proc testOneIndexVarargs(): bool =
|
|
|
|
proc vlient1() {.async.} =
|
|
|
|
await sleepAsync(100.milliseconds)
|
|
|
|
|
|
|
|
proc vlient2() {.async.} =
|
|
|
|
await sleepAsync(200.milliseconds)
|
|
|
|
|
|
|
|
proc vlient3() {.async.} =
|
|
|
|
await sleepAsync(300.milliseconds)
|
|
|
|
|
|
|
|
proc client1(): Future[int] {.async.} =
|
|
|
|
await sleepAsync(100.milliseconds)
|
|
|
|
result = 10
|
|
|
|
|
|
|
|
proc client2(): Future[int] {.async.} =
|
|
|
|
await sleepAsync(200.milliseconds)
|
|
|
|
result = 20
|
|
|
|
|
|
|
|
proc client3(): Future[int] {.async.} =
|
|
|
|
await sleepAsync(300.milliseconds)
|
|
|
|
result = 30
|
|
|
|
|
|
|
|
var res10 = waitFor(oneIndex(vlient1(), vlient2(), vlient3()))
|
|
|
|
var res11 = waitFor(oneIndex(vlient2(), vlient1(), vlient3()))
|
|
|
|
var res12 = waitFor(oneIndex(vlient3(), vlient2(), vlient1()))
|
|
|
|
if res10 != 0 or res11 != 1 or res12 != 2:
|
|
|
|
return
|
|
|
|
|
|
|
|
var res20 = waitFor(oneIndex(client1(), client2(), client3()))
|
|
|
|
var res21 = waitFor(oneIndex(client2(), client1(), client3()))
|
|
|
|
var res22 = waitFor(oneIndex(client3(), client2(), client1()))
|
|
|
|
if res20 != 0 or res21 != 1 or res22 != 2:
|
|
|
|
return
|
|
|
|
|
|
|
|
result = true
|
|
|
|
|
|
|
|
proc testOneValueVarargs(): bool =
|
|
|
|
proc vlient1() {.async.} =
|
|
|
|
await sleepAsync(100.milliseconds)
|
|
|
|
|
|
|
|
proc vlient2() {.async.} =
|
|
|
|
await sleepAsync(200.milliseconds)
|
|
|
|
|
|
|
|
proc vlient3() {.async.} =
|
|
|
|
await sleepAsync(300.milliseconds)
|
|
|
|
|
|
|
|
proc client1(): Future[int] {.async.} =
|
|
|
|
await sleepAsync(100.milliseconds)
|
|
|
|
result = 10
|
|
|
|
|
|
|
|
proc client2(): Future[int] {.async.} =
|
|
|
|
await sleepAsync(200.milliseconds)
|
|
|
|
result = 20
|
|
|
|
|
|
|
|
proc client3(): Future[int] {.async.} =
|
|
|
|
await sleepAsync(300.milliseconds)
|
|
|
|
result = 30
|
|
|
|
|
|
|
|
var v10 = vlient1()
|
|
|
|
var v11 = vlient2()
|
|
|
|
var v12 = vlient3()
|
|
|
|
var v20 = vlient2()
|
|
|
|
var v21 = vlient1()
|
|
|
|
var v22 = vlient3()
|
|
|
|
var v30 = vlient3()
|
|
|
|
var v31 = vlient2()
|
|
|
|
var v32 = vlient1()
|
|
|
|
|
|
|
|
waitFor(oneValue(v10, v11, v12))
|
|
|
|
waitFor(oneValue(v20, v21, v22))
|
|
|
|
waitFor(oneValue(v30, v31, v32))
|
|
|
|
|
|
|
|
if (not v10.finished) or (not v21.finished) or (not v32.finished):
|
|
|
|
return
|
|
|
|
|
|
|
|
var res30 = waitFor(oneValue(client1(), client2(), client3()))
|
|
|
|
var res31 = waitFor(oneValue(client2(), client1(), client3()))
|
|
|
|
var res32 = waitFor(oneValue(client3(), client2(), client1()))
|
|
|
|
if res30 != 10 or res31 != 10 or res32 != 10:
|
|
|
|
return
|
|
|
|
|
|
|
|
result = true
|
|
|
|
|
|
|
|
proc testOneIndexSeq(): bool =
|
|
|
|
proc vlient1() {.async.} =
|
|
|
|
await sleepAsync(100.milliseconds)
|
|
|
|
|
|
|
|
proc vlient2() {.async.} =
|
|
|
|
await sleepAsync(200.milliseconds)
|
|
|
|
|
|
|
|
proc vlient3() {.async.} =
|
|
|
|
await sleepAsync(300.milliseconds)
|
|
|
|
|
|
|
|
proc client1(): Future[int] {.async.} =
|
|
|
|
await sleepAsync(100.milliseconds)
|
|
|
|
result = 10
|
|
|
|
|
|
|
|
proc client2(): Future[int] {.async.} =
|
|
|
|
await sleepAsync(200.milliseconds)
|
|
|
|
result = 20
|
|
|
|
|
|
|
|
proc client3(): Future[int] {.async.} =
|
|
|
|
await sleepAsync(300.milliseconds)
|
|
|
|
result = 30
|
|
|
|
|
|
|
|
var res10 = waitFor(oneIndex(@[vlient1(), vlient2(), vlient3()]))
|
|
|
|
var res11 = waitFor(oneIndex(@[vlient2(), vlient1(), vlient3()]))
|
|
|
|
var res12 = waitFor(oneIndex(@[vlient3(), vlient2(), vlient1()]))
|
|
|
|
if res10 != 0 or res11 != 1 or res12 != 2:
|
|
|
|
return
|
|
|
|
|
|
|
|
var res20 = waitFor(oneIndex(@[client1(), client2(), client3()]))
|
|
|
|
var res21 = waitFor(oneIndex(@[client2(), client1(), client3()]))
|
|
|
|
var res22 = waitFor(oneIndex(@[client3(), client2(), client1()]))
|
|
|
|
if res20 != 0 or res21 != 1 or res22 != 2:
|
|
|
|
return
|
|
|
|
|
|
|
|
result = true
|
|
|
|
|
|
|
|
proc testOneValueSeq(): bool =
|
|
|
|
proc vlient1() {.async.} =
|
|
|
|
await sleepAsync(100.milliseconds)
|
|
|
|
|
|
|
|
proc vlient2() {.async.} =
|
|
|
|
await sleepAsync(200.milliseconds)
|
|
|
|
|
|
|
|
proc vlient3() {.async.} =
|
|
|
|
await sleepAsync(300.milliseconds)
|
|
|
|
|
|
|
|
proc client1(): Future[int] {.async.} =
|
|
|
|
await sleepAsync(100.milliseconds)
|
|
|
|
result = 10
|
|
|
|
|
|
|
|
proc client2(): Future[int] {.async.} =
|
|
|
|
await sleepAsync(200.milliseconds)
|
|
|
|
result = 20
|
|
|
|
|
|
|
|
proc client3(): Future[int] {.async.} =
|
|
|
|
await sleepAsync(300.milliseconds)
|
|
|
|
result = 30
|
|
|
|
|
|
|
|
var v10 = vlient1()
|
|
|
|
var v11 = vlient2()
|
|
|
|
var v12 = vlient3()
|
|
|
|
var v20 = vlient2()
|
|
|
|
var v21 = vlient1()
|
|
|
|
var v22 = vlient3()
|
|
|
|
var v30 = vlient3()
|
|
|
|
var v31 = vlient2()
|
|
|
|
var v32 = vlient1()
|
|
|
|
|
|
|
|
waitFor(oneValue(@[v10, v11, v12]))
|
|
|
|
waitFor(oneValue(@[v20, v21, v22]))
|
|
|
|
waitFor(oneValue(@[v30, v31, v32]))
|
|
|
|
|
|
|
|
if (not v10.finished) or (not v21.finished) or (not v32.finished):
|
|
|
|
return
|
|
|
|
|
|
|
|
var res30 = waitFor(oneValue(@[client1(), client2(), client3()]))
|
|
|
|
var res31 = waitFor(oneValue(@[client2(), client1(), client3()]))
|
|
|
|
var res32 = waitFor(oneValue(@[client3(), client2(), client1()]))
|
|
|
|
if res30 != 10 or res31 != 10 or res32 != 10:
|
|
|
|
return
|
|
|
|
|
|
|
|
result = true
|
|
|
|
|
2019-06-26 12:36:01 +00:00
|
|
|
proc testCancelIter(): bool =
|
|
|
|
var completed = 0
|
|
|
|
|
|
|
|
proc client1() {.async.} =
|
|
|
|
await sleepAsync(1.seconds)
|
|
|
|
inc(completed)
|
|
|
|
|
|
|
|
proc client2() {.async.} =
|
|
|
|
await client1()
|
|
|
|
inc(completed)
|
|
|
|
|
|
|
|
proc client3() {.async.} =
|
|
|
|
await client2()
|
|
|
|
inc(completed)
|
|
|
|
|
|
|
|
proc client4() {.async.} =
|
|
|
|
await client3()
|
|
|
|
inc(completed)
|
|
|
|
|
|
|
|
var fut = client4()
|
|
|
|
fut.cancel()
|
|
|
|
|
|
|
|
# Future must not be cancelled immediately, because it has many nested
|
|
|
|
# futures.
|
|
|
|
if fut.cancelled():
|
|
|
|
return false
|
|
|
|
|
|
|
|
try:
|
|
|
|
waitFor fut
|
|
|
|
result = false
|
|
|
|
except CancelledError:
|
|
|
|
if completed == 0:
|
|
|
|
result = true
|
|
|
|
else:
|
|
|
|
result = false
|
|
|
|
|
|
|
|
proc testCancelAndWait(): bool =
|
|
|
|
var completed = 0
|
|
|
|
|
|
|
|
proc client1() {.async.} =
|
|
|
|
await sleepAsync(1.seconds)
|
|
|
|
inc(completed)
|
|
|
|
|
|
|
|
proc client2() {.async.} =
|
|
|
|
await client1()
|
|
|
|
inc(completed)
|
|
|
|
|
|
|
|
proc client3() {.async.} =
|
|
|
|
await client2()
|
|
|
|
inc(completed)
|
|
|
|
|
|
|
|
proc client4() {.async.} =
|
|
|
|
await client3()
|
|
|
|
inc(completed)
|
|
|
|
|
|
|
|
var fut = client4()
|
|
|
|
waitFor cancelAndWait(fut)
|
|
|
|
if not(fut.cancelled()):
|
|
|
|
return false
|
|
|
|
return true
|
|
|
|
|
|
|
|
proc testBreakCancellation(): bool =
|
|
|
|
var completed = 0
|
|
|
|
|
|
|
|
proc client1() {.async.} =
|
|
|
|
await sleepAsync(1.seconds)
|
|
|
|
inc(completed)
|
|
|
|
|
|
|
|
proc client2() {.async.} =
|
|
|
|
try:
|
|
|
|
await client1()
|
|
|
|
except CancelledError:
|
|
|
|
discard
|
|
|
|
inc(completed)
|
|
|
|
|
|
|
|
var fut1 = client2()
|
|
|
|
var fut2 = client2()
|
|
|
|
fut1.cancel()
|
|
|
|
waitFor fut1
|
|
|
|
waitFor cancelAndWait(fut2)
|
|
|
|
|
|
|
|
if fut1.cancelled():
|
|
|
|
return false
|
|
|
|
if fut2.cancelled():
|
|
|
|
return false
|
|
|
|
|
|
|
|
if completed != 2:
|
|
|
|
return false
|
|
|
|
|
|
|
|
return true
|
|
|
|
|
|
|
|
proc testCancelCallback(): bool =
|
|
|
|
var completed = 0
|
|
|
|
var cancelled = 0
|
|
|
|
|
|
|
|
proc client1(duration: Duration): Future[void] =
|
|
|
|
## Suspends the execution of the current async procedure for the next
|
|
|
|
## ``duration`` time.
|
|
|
|
var retFuture = newFuture[void]()
|
|
|
|
let moment = Moment.fromNow(duration)
|
|
|
|
|
|
|
|
proc completion(data: pointer) {.gcsafe.} =
|
|
|
|
inc(completed)
|
|
|
|
if not(retFuture.finished()):
|
|
|
|
retFuture.complete()
|
|
|
|
|
|
|
|
proc cancel(udata: pointer) {.gcsafe.} =
|
|
|
|
inc(cancelled)
|
|
|
|
if not(retFuture.finished()):
|
|
|
|
removeTimer(moment, completion, cast[pointer](retFuture))
|
|
|
|
|
|
|
|
retFuture.cancelCallback = cancel
|
|
|
|
addTimer(moment, completion, cast[pointer](retFuture))
|
|
|
|
return retFuture
|
|
|
|
|
|
|
|
var fut = client1(100.milliseconds)
|
|
|
|
fut.cancel()
|
2019-06-26 12:50:40 +00:00
|
|
|
waitFor(sleepAsync(500.milliseconds))
|
2019-06-26 12:36:01 +00:00
|
|
|
|
|
|
|
if not(fut.cancelled()):
|
|
|
|
return false
|
|
|
|
if (completed != 0) and (cancelled != 1):
|
|
|
|
return false
|
|
|
|
return true
|
|
|
|
|
2019-03-30 22:31:10 +00:00
|
|
|
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 "all[T](varargs) test":
|
|
|
|
check testAllVarargs() == 35
|
|
|
|
test "all[T](seq) test":
|
|
|
|
check testAllSeq() == 350
|
|
|
|
test "all[T](zero) test":
|
|
|
|
check testAllZero() == true
|
|
|
|
test "asyncDiscard() test":
|
|
|
|
check testAsyncDiscard() == 10
|
2019-06-04 16:51:35 +00:00
|
|
|
test "oneIndex[T](zero) test":
|
|
|
|
check testOneIndexZero() == true
|
|
|
|
test "oneValue[T](zero) test":
|
|
|
|
check testOneValueZero() == true
|
|
|
|
test "oneIndex[T](varargs) test":
|
|
|
|
check testOneIndexVarargs() == true
|
|
|
|
test "oneValue[T](varargs) test":
|
|
|
|
check testOneValueVarargs() == true
|
|
|
|
test "oneIndex[T](seq) test":
|
|
|
|
check testOneIndexSeq() == true
|
|
|
|
test "oneValue[T](seq) test":
|
|
|
|
check testOneValueSeq() == true
|
2019-06-26 12:36:01 +00:00
|
|
|
|
|
|
|
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
|