mirror of https://github.com/vacp2p/nim-libp2p.git
Cleanup tests (#435)
* add async testing methods * refactor with async testing methods * use iffy in async tests
This commit is contained in:
parent
23ffd1f9f9
commit
55b763264e
|
@ -46,6 +46,27 @@ template checkTrackers*() =
|
|||
# Also test the GC is not fooling with us
|
||||
GC_fullCollect()
|
||||
|
||||
template asyncTeardown*(body: untyped): untyped =
|
||||
teardown:
|
||||
waitFor((
|
||||
proc() {.async.} =
|
||||
body
|
||||
)())
|
||||
|
||||
template asyncSetup*(body: untyped): untyped =
|
||||
setup:
|
||||
waitFor((
|
||||
proc() {.async.} =
|
||||
body
|
||||
)())
|
||||
|
||||
template asyncTest*(name: string, body: untyped): untyped =
|
||||
test name:
|
||||
waitFor((
|
||||
proc() {.async.} =
|
||||
body
|
||||
)())
|
||||
|
||||
type RngWrap = object
|
||||
rng: ref BrHmacDrbgContext
|
||||
|
||||
|
|
|
@ -38,357 +38,336 @@ suite "FloodSub":
|
|||
teardown:
|
||||
checkTrackers()
|
||||
|
||||
test "FloodSub basic publish/subscribe A -> B":
|
||||
proc runTests() {.async.} =
|
||||
var completionFut = newFuture[bool]()
|
||||
proc handler(topic: string, data: seq[byte]) {.async, gcsafe.} =
|
||||
check topic == "foobar"
|
||||
completionFut.complete(true)
|
||||
asyncTest "FloodSub basic publish/subscribe A -> B":
|
||||
var completionFut = newFuture[bool]()
|
||||
proc handler(topic: string, data: seq[byte]) {.async, gcsafe.} =
|
||||
check topic == "foobar"
|
||||
completionFut.complete(true)
|
||||
|
||||
let
|
||||
nodes = generateNodes(2)
|
||||
let
|
||||
nodes = generateNodes(2)
|
||||
|
||||
# start switches
|
||||
nodesFut = await allFinished(
|
||||
nodes[0].switch.start(),
|
||||
nodes[1].switch.start(),
|
||||
)
|
||||
# start switches
|
||||
nodesFut = await allFinished(
|
||||
nodes[0].switch.start(),
|
||||
nodes[1].switch.start(),
|
||||
)
|
||||
|
||||
# start pubsub
|
||||
await allFuturesThrowing(
|
||||
allFinished(
|
||||
nodes[0].start(),
|
||||
nodes[1].start(),
|
||||
))
|
||||
# start pubsub
|
||||
await allFuturesThrowing(
|
||||
allFinished(
|
||||
nodes[0].start(),
|
||||
nodes[1].start(),
|
||||
))
|
||||
|
||||
await subscribeNodes(nodes)
|
||||
await subscribeNodes(nodes)
|
||||
|
||||
await nodes[1].subscribe("foobar", handler)
|
||||
await waitSub(nodes[0], nodes[1], "foobar")
|
||||
await nodes[1].subscribe("foobar", handler)
|
||||
await waitSub(nodes[0], nodes[1], "foobar")
|
||||
|
||||
check (await nodes[0].publish("foobar", "Hello!".toBytes())) > 0
|
||||
check (await completionFut.wait(5.seconds)) == true
|
||||
check (await nodes[0].publish("foobar", "Hello!".toBytes())) > 0
|
||||
check (await completionFut.wait(5.seconds)) == true
|
||||
|
||||
await allFuturesThrowing(
|
||||
await allFuturesThrowing(
|
||||
nodes[0].switch.stop(),
|
||||
nodes[1].switch.stop()
|
||||
)
|
||||
|
||||
await allFuturesThrowing(
|
||||
nodes[0].stop(),
|
||||
nodes[1].stop()
|
||||
)
|
||||
|
||||
await allFuturesThrowing(nodesFut.concat())
|
||||
|
||||
asyncTest "FloodSub basic publish/subscribe B -> A":
|
||||
var completionFut = newFuture[bool]()
|
||||
proc handler(topic: string, data: seq[byte]) {.async, gcsafe.} =
|
||||
check topic == "foobar"
|
||||
completionFut.complete(true)
|
||||
|
||||
let
|
||||
nodes = generateNodes(2)
|
||||
|
||||
# start switches
|
||||
nodesFut = await allFinished(
|
||||
nodes[0].switch.start(),
|
||||
nodes[1].switch.start(),
|
||||
)
|
||||
|
||||
# start pubsubcon
|
||||
await allFuturesThrowing(
|
||||
allFinished(
|
||||
nodes[0].start(),
|
||||
nodes[1].start(),
|
||||
))
|
||||
|
||||
await subscribeNodes(nodes)
|
||||
|
||||
await nodes[0].subscribe("foobar", handler)
|
||||
await waitSub(nodes[1], nodes[0], "foobar")
|
||||
|
||||
check (await nodes[1].publish("foobar", "Hello!".toBytes())) > 0
|
||||
|
||||
check (await completionFut.wait(5.seconds)) == true
|
||||
|
||||
await allFuturesThrowing(
|
||||
nodes[0].switch.stop(),
|
||||
nodes[1].switch.stop()
|
||||
)
|
||||
|
||||
await allFuturesThrowing(
|
||||
nodes[0].stop(),
|
||||
nodes[1].stop()
|
||||
)
|
||||
|
||||
await allFuturesThrowing(nodesFut)
|
||||
|
||||
asyncTest "FloodSub validation should succeed":
|
||||
var handlerFut = newFuture[bool]()
|
||||
proc handler(topic: string, data: seq[byte]) {.async, gcsafe.} =
|
||||
check topic == "foobar"
|
||||
handlerFut.complete(true)
|
||||
|
||||
let
|
||||
nodes = generateNodes(2)
|
||||
|
||||
# start switches
|
||||
nodesFut = await allFinished(
|
||||
nodes[0].switch.start(),
|
||||
nodes[1].switch.start(),
|
||||
)
|
||||
|
||||
# start pubsubcon
|
||||
await allFuturesThrowing(
|
||||
allFinished(
|
||||
nodes[0].start(),
|
||||
nodes[1].start(),
|
||||
))
|
||||
|
||||
await subscribeNodes(nodes)
|
||||
|
||||
await nodes[1].subscribe("foobar", handler)
|
||||
await waitSub(nodes[0], nodes[1], "foobar")
|
||||
|
||||
var validatorFut = newFuture[bool]()
|
||||
proc validator(topic: string,
|
||||
message: Message): Future[ValidationResult] {.async.} =
|
||||
check topic == "foobar"
|
||||
validatorFut.complete(true)
|
||||
result = ValidationResult.Accept
|
||||
|
||||
nodes[1].addValidator("foobar", validator)
|
||||
|
||||
check (await nodes[0].publish("foobar", "Hello!".toBytes())) > 0
|
||||
check (await handlerFut) == true
|
||||
|
||||
await allFuturesThrowing(
|
||||
nodes[0].switch.stop(),
|
||||
nodes[1].switch.stop()
|
||||
)
|
||||
|
||||
await allFuturesThrowing(
|
||||
nodes[0].stop(),
|
||||
nodes[1].stop()
|
||||
await allFuturesThrowing(
|
||||
nodes[0].stop(),
|
||||
nodes[1].stop()
|
||||
)
|
||||
|
||||
await allFuturesThrowing(nodesFut)
|
||||
|
||||
asyncTest "FloodSub validation should fail":
|
||||
proc handler(topic: string, data: seq[byte]) {.async, gcsafe.} =
|
||||
check false # if we get here, it should fail
|
||||
|
||||
let
|
||||
nodes = generateNodes(2)
|
||||
|
||||
# start switches
|
||||
nodesFut = await allFinished(
|
||||
nodes[0].switch.start(),
|
||||
nodes[1].switch.start(),
|
||||
)
|
||||
|
||||
await allFuturesThrowing(nodesFut.concat())
|
||||
# start pubsubcon
|
||||
await allFuturesThrowing(
|
||||
allFinished(
|
||||
nodes[0].start(),
|
||||
nodes[1].start(),
|
||||
))
|
||||
|
||||
waitFor(runTests())
|
||||
await subscribeNodes(nodes)
|
||||
await nodes[1].subscribe("foobar", handler)
|
||||
await waitSub(nodes[0], nodes[1], "foobar")
|
||||
|
||||
test "FloodSub basic publish/subscribe B -> A":
|
||||
proc runTests() {.async.} =
|
||||
var completionFut = newFuture[bool]()
|
||||
proc handler(topic: string, data: seq[byte]) {.async, gcsafe.} =
|
||||
check topic == "foobar"
|
||||
completionFut.complete(true)
|
||||
var validatorFut = newFuture[bool]()
|
||||
proc validator(topic: string,
|
||||
message: Message): Future[ValidationResult] {.async.} =
|
||||
validatorFut.complete(true)
|
||||
result = ValidationResult.Reject
|
||||
|
||||
let
|
||||
nodes = generateNodes(2)
|
||||
nodes[1].addValidator("foobar", validator)
|
||||
|
||||
# start switches
|
||||
nodesFut = await allFinished(
|
||||
nodes[0].switch.start(),
|
||||
nodes[1].switch.start(),
|
||||
)
|
||||
discard await nodes[0].publish("foobar", "Hello!".toBytes())
|
||||
|
||||
# start pubsubcon
|
||||
await allFuturesThrowing(
|
||||
allFinished(
|
||||
nodes[0].start(),
|
||||
nodes[1].start(),
|
||||
))
|
||||
|
||||
await subscribeNodes(nodes)
|
||||
|
||||
await nodes[0].subscribe("foobar", handler)
|
||||
await waitSub(nodes[1], nodes[0], "foobar")
|
||||
|
||||
check (await nodes[1].publish("foobar", "Hello!".toBytes())) > 0
|
||||
|
||||
check (await completionFut.wait(5.seconds)) == true
|
||||
|
||||
await allFuturesThrowing(
|
||||
await allFuturesThrowing(
|
||||
nodes[0].switch.stop(),
|
||||
nodes[1].switch.stop()
|
||||
)
|
||||
|
||||
await allFuturesThrowing(
|
||||
nodes[0].stop(),
|
||||
nodes[1].stop()
|
||||
await allFuturesThrowing(
|
||||
nodes[0].stop(),
|
||||
nodes[1].stop()
|
||||
)
|
||||
|
||||
await allFuturesThrowing(nodesFut)
|
||||
|
||||
asyncTest "FloodSub validation one fails and one succeeds":
|
||||
var handlerFut = newFuture[bool]()
|
||||
proc handler(topic: string, data: seq[byte]) {.async, gcsafe.} =
|
||||
check topic == "foo"
|
||||
handlerFut.complete(true)
|
||||
|
||||
let
|
||||
nodes = generateNodes(2)
|
||||
|
||||
# start switches
|
||||
nodesFut = await allFinished(
|
||||
nodes[0].switch.start(),
|
||||
nodes[1].switch.start(),
|
||||
)
|
||||
|
||||
await allFuturesThrowing(nodesFut)
|
||||
# start pubsubcon
|
||||
await allFuturesThrowing(
|
||||
allFinished(
|
||||
nodes[0].start(),
|
||||
nodes[1].start(),
|
||||
))
|
||||
|
||||
waitFor(runTests())
|
||||
await subscribeNodes(nodes)
|
||||
await nodes[1].subscribe("foo", handler)
|
||||
await waitSub(nodes[0], nodes[1], "foo")
|
||||
await nodes[1].subscribe("bar", handler)
|
||||
await waitSub(nodes[0], nodes[1], "bar")
|
||||
|
||||
test "FloodSub validation should succeed":
|
||||
proc runTests() {.async.} =
|
||||
var handlerFut = newFuture[bool]()
|
||||
proc handler(topic: string, data: seq[byte]) {.async, gcsafe.} =
|
||||
check topic == "foobar"
|
||||
handlerFut.complete(true)
|
||||
|
||||
let
|
||||
nodes = generateNodes(2)
|
||||
|
||||
# start switches
|
||||
nodesFut = await allFinished(
|
||||
nodes[0].switch.start(),
|
||||
nodes[1].switch.start(),
|
||||
)
|
||||
|
||||
# start pubsubcon
|
||||
await allFuturesThrowing(
|
||||
allFinished(
|
||||
nodes[0].start(),
|
||||
nodes[1].start(),
|
||||
))
|
||||
|
||||
await subscribeNodes(nodes)
|
||||
|
||||
await nodes[1].subscribe("foobar", handler)
|
||||
await waitSub(nodes[0], nodes[1], "foobar")
|
||||
|
||||
var validatorFut = newFuture[bool]()
|
||||
proc validator(topic: string,
|
||||
message: Message): Future[ValidationResult] {.async.} =
|
||||
check topic == "foobar"
|
||||
validatorFut.complete(true)
|
||||
proc validator(topic: string,
|
||||
message: Message): Future[ValidationResult] {.async.} =
|
||||
if topic == "foo":
|
||||
result = ValidationResult.Accept
|
||||
|
||||
nodes[1].addValidator("foobar", validator)
|
||||
|
||||
check (await nodes[0].publish("foobar", "Hello!".toBytes())) > 0
|
||||
check (await handlerFut) == true
|
||||
|
||||
await allFuturesThrowing(
|
||||
nodes[0].switch.stop(),
|
||||
nodes[1].switch.stop()
|
||||
)
|
||||
|
||||
await allFuturesThrowing(
|
||||
nodes[0].stop(),
|
||||
nodes[1].stop()
|
||||
)
|
||||
|
||||
await allFuturesThrowing(nodesFut)
|
||||
|
||||
waitFor(runTests())
|
||||
|
||||
test "FloodSub validation should fail":
|
||||
proc runTests() {.async.} =
|
||||
proc handler(topic: string, data: seq[byte]) {.async, gcsafe.} =
|
||||
check false # if we get here, it should fail
|
||||
|
||||
let
|
||||
nodes = generateNodes(2)
|
||||
|
||||
# start switches
|
||||
nodesFut = await allFinished(
|
||||
nodes[0].switch.start(),
|
||||
nodes[1].switch.start(),
|
||||
)
|
||||
|
||||
# start pubsubcon
|
||||
await allFuturesThrowing(
|
||||
allFinished(
|
||||
nodes[0].start(),
|
||||
nodes[1].start(),
|
||||
))
|
||||
|
||||
await subscribeNodes(nodes)
|
||||
await nodes[1].subscribe("foobar", handler)
|
||||
await waitSub(nodes[0], nodes[1], "foobar")
|
||||
|
||||
var validatorFut = newFuture[bool]()
|
||||
proc validator(topic: string,
|
||||
message: Message): Future[ValidationResult] {.async.} =
|
||||
validatorFut.complete(true)
|
||||
else:
|
||||
result = ValidationResult.Reject
|
||||
|
||||
nodes[1].addValidator("foobar", validator)
|
||||
nodes[1].addValidator("foo", "bar", validator)
|
||||
|
||||
discard await nodes[0].publish("foobar", "Hello!".toBytes())
|
||||
check (await nodes[0].publish("foo", "Hello!".toBytes())) > 0
|
||||
check (await nodes[0].publish("bar", "Hello!".toBytes())) > 0
|
||||
|
||||
await allFuturesThrowing(
|
||||
nodes[0].switch.stop(),
|
||||
nodes[1].switch.stop()
|
||||
await allFuturesThrowing(
|
||||
nodes[0].switch.stop(),
|
||||
nodes[1].switch.stop()
|
||||
)
|
||||
|
||||
await allFuturesThrowing(
|
||||
nodes[0].stop(),
|
||||
nodes[1].stop()
|
||||
)
|
||||
|
||||
await allFuturesThrowing(nodesFut)
|
||||
|
||||
asyncTest "FloodSub multiple peers, no self trigger":
|
||||
var runs = 10
|
||||
|
||||
var futs = newSeq[(Future[void], TopicHandler, ref int)](runs)
|
||||
for i in 0..<runs:
|
||||
closureScope:
|
||||
var
|
||||
fut = newFuture[void]()
|
||||
counter = new int
|
||||
futs[i] = (
|
||||
fut,
|
||||
(proc(topic: string, data: seq[byte]) {.async, gcsafe.} =
|
||||
check topic == "foobar"
|
||||
inc counter[]
|
||||
if counter[] == runs - 1:
|
||||
fut.complete()),
|
||||
counter
|
||||
)
|
||||
|
||||
await allFuturesThrowing(
|
||||
nodes[0].stop(),
|
||||
nodes[1].stop()
|
||||
)
|
||||
let
|
||||
nodes = generateNodes(runs, triggerSelf = false)
|
||||
nodesFut = nodes.mapIt(it.switch.start())
|
||||
|
||||
await allFuturesThrowing(nodesFut)
|
||||
await allFuturesThrowing(nodes.mapIt(it.start()))
|
||||
await subscribeNodes(nodes)
|
||||
|
||||
waitFor(runTests())
|
||||
for i in 0..<runs:
|
||||
await nodes[i].subscribe("foobar", futs[i][1])
|
||||
|
||||
test "FloodSub validation one fails and one succeeds":
|
||||
proc runTests() {.async.} =
|
||||
var handlerFut = newFuture[bool]()
|
||||
proc handler(topic: string, data: seq[byte]) {.async, gcsafe.} =
|
||||
check topic == "foo"
|
||||
handlerFut.complete(true)
|
||||
var subs: seq[Future[void]]
|
||||
for i in 0..<runs:
|
||||
for y in 0..<runs:
|
||||
if y != i:
|
||||
subs &= waitSub(nodes[i], nodes[y], "foobar")
|
||||
await allFuturesThrowing(subs)
|
||||
|
||||
let
|
||||
nodes = generateNodes(2)
|
||||
var pubs: seq[Future[int]]
|
||||
for i in 0..<runs:
|
||||
pubs &= nodes[i].publish("foobar", ("Hello!" & $i).toBytes())
|
||||
await allFuturesThrowing(pubs)
|
||||
|
||||
# start switches
|
||||
nodesFut = await allFinished(
|
||||
nodes[0].switch.start(),
|
||||
nodes[1].switch.start(),
|
||||
await allFuturesThrowing(futs.mapIt(it[0]))
|
||||
await allFuturesThrowing(
|
||||
nodes.mapIt(
|
||||
allFutures(
|
||||
it.stop(),
|
||||
it.switch.stop())))
|
||||
|
||||
await allFuturesThrowing(nodesFut)
|
||||
|
||||
asyncTest "FloodSub multiple peers, with self trigger":
|
||||
var runs = 10
|
||||
|
||||
var futs = newSeq[(Future[void], TopicHandler, ref int)](runs)
|
||||
for i in 0..<runs:
|
||||
closureScope:
|
||||
var
|
||||
fut = newFuture[void]()
|
||||
counter = new int
|
||||
futs[i] = (
|
||||
fut,
|
||||
(proc(topic: string, data: seq[byte]) {.async, gcsafe.} =
|
||||
check topic == "foobar"
|
||||
inc counter[]
|
||||
if counter[] == runs - 1:
|
||||
fut.complete()),
|
||||
counter
|
||||
)
|
||||
|
||||
# start pubsubcon
|
||||
await allFuturesThrowing(
|
||||
allFinished(
|
||||
nodes[0].start(),
|
||||
nodes[1].start(),
|
||||
))
|
||||
let
|
||||
nodes = generateNodes(runs, triggerSelf = true)
|
||||
nodesFut = nodes.mapIt(it.switch.start())
|
||||
|
||||
await subscribeNodes(nodes)
|
||||
await nodes[1].subscribe("foo", handler)
|
||||
await waitSub(nodes[0], nodes[1], "foo")
|
||||
await nodes[1].subscribe("bar", handler)
|
||||
await waitSub(nodes[0], nodes[1], "bar")
|
||||
await allFuturesThrowing(nodes.mapIt(it.start()))
|
||||
await subscribeNodes(nodes)
|
||||
|
||||
proc validator(topic: string,
|
||||
message: Message): Future[ValidationResult] {.async.} =
|
||||
if topic == "foo":
|
||||
result = ValidationResult.Accept
|
||||
else:
|
||||
result = ValidationResult.Reject
|
||||
for i in 0..<runs:
|
||||
await nodes[i].subscribe("foobar", futs[i][1])
|
||||
|
||||
nodes[1].addValidator("foo", "bar", validator)
|
||||
var subs: seq[Future[void]]
|
||||
for i in 0..<runs:
|
||||
for y in 0..<runs:
|
||||
if y != i:
|
||||
subs &= waitSub(nodes[i], nodes[y], "foobar")
|
||||
await allFuturesThrowing(subs)
|
||||
|
||||
check (await nodes[0].publish("foo", "Hello!".toBytes())) > 0
|
||||
check (await nodes[0].publish("bar", "Hello!".toBytes())) > 0
|
||||
var pubs: seq[Future[int]]
|
||||
for i in 0..<runs:
|
||||
pubs &= nodes[i].publish("foobar", ("Hello!" & $i).toBytes())
|
||||
await allFuturesThrowing(pubs)
|
||||
|
||||
await allFuturesThrowing(
|
||||
nodes[0].switch.stop(),
|
||||
nodes[1].switch.stop()
|
||||
)
|
||||
await allFuturesThrowing(futs.mapIt(it[0]))
|
||||
await allFuturesThrowing(
|
||||
nodes.mapIt(
|
||||
allFutures(
|
||||
it.stop(),
|
||||
it.switch.stop())))
|
||||
|
||||
await allFuturesThrowing(
|
||||
nodes[0].stop(),
|
||||
nodes[1].stop()
|
||||
)
|
||||
|
||||
await allFuturesThrowing(nodesFut)
|
||||
|
||||
waitFor(runTests())
|
||||
|
||||
test "FloodSub multiple peers, no self trigger":
|
||||
proc runTests() {.async.} =
|
||||
var runs = 10
|
||||
|
||||
var futs = newSeq[(Future[void], TopicHandler, ref int)](runs)
|
||||
for i in 0..<runs:
|
||||
closureScope:
|
||||
var
|
||||
fut = newFuture[void]()
|
||||
counter = new int
|
||||
futs[i] = (
|
||||
fut,
|
||||
(proc(topic: string, data: seq[byte]) {.async, gcsafe.} =
|
||||
check topic == "foobar"
|
||||
inc counter[]
|
||||
if counter[] == runs - 1:
|
||||
fut.complete()),
|
||||
counter
|
||||
)
|
||||
|
||||
let
|
||||
nodes = generateNodes(runs, triggerSelf = false)
|
||||
nodesFut = nodes.mapIt(it.switch.start())
|
||||
|
||||
await allFuturesThrowing(nodes.mapIt(it.start()))
|
||||
await subscribeNodes(nodes)
|
||||
|
||||
for i in 0..<runs:
|
||||
await nodes[i].subscribe("foobar", futs[i][1])
|
||||
|
||||
var subs: seq[Future[void]]
|
||||
for i in 0..<runs:
|
||||
for y in 0..<runs:
|
||||
if y != i:
|
||||
subs &= waitSub(nodes[i], nodes[y], "foobar")
|
||||
await allFuturesThrowing(subs)
|
||||
|
||||
var pubs: seq[Future[int]]
|
||||
for i in 0..<runs:
|
||||
pubs &= nodes[i].publish("foobar", ("Hello!" & $i).toBytes())
|
||||
await allFuturesThrowing(pubs)
|
||||
|
||||
await allFuturesThrowing(futs.mapIt(it[0]))
|
||||
await allFuturesThrowing(
|
||||
nodes.mapIt(
|
||||
allFutures(
|
||||
it.stop(),
|
||||
it.switch.stop())))
|
||||
|
||||
await allFuturesThrowing(nodesFut)
|
||||
|
||||
waitFor(runTests())
|
||||
|
||||
test "FloodSub multiple peers, with self trigger":
|
||||
proc runTests() {.async.} =
|
||||
var runs = 10
|
||||
|
||||
var futs = newSeq[(Future[void], TopicHandler, ref int)](runs)
|
||||
for i in 0..<runs:
|
||||
closureScope:
|
||||
var
|
||||
fut = newFuture[void]()
|
||||
counter = new int
|
||||
futs[i] = (
|
||||
fut,
|
||||
(proc(topic: string, data: seq[byte]) {.async, gcsafe.} =
|
||||
check topic == "foobar"
|
||||
inc counter[]
|
||||
if counter[] == runs - 1:
|
||||
fut.complete()),
|
||||
counter
|
||||
)
|
||||
|
||||
let
|
||||
nodes = generateNodes(runs, triggerSelf = true)
|
||||
nodesFut = nodes.mapIt(it.switch.start())
|
||||
|
||||
await allFuturesThrowing(nodes.mapIt(it.start()))
|
||||
await subscribeNodes(nodes)
|
||||
|
||||
for i in 0..<runs:
|
||||
await nodes[i].subscribe("foobar", futs[i][1])
|
||||
|
||||
var subs: seq[Future[void]]
|
||||
for i in 0..<runs:
|
||||
for y in 0..<runs:
|
||||
if y != i:
|
||||
subs &= waitSub(nodes[i], nodes[y], "foobar")
|
||||
await allFuturesThrowing(subs)
|
||||
|
||||
var pubs: seq[Future[int]]
|
||||
for i in 0..<runs:
|
||||
pubs &= nodes[i].publish("foobar", ("Hello!" & $i).toBytes())
|
||||
await allFuturesThrowing(pubs)
|
||||
|
||||
await allFuturesThrowing(futs.mapIt(it[0]))
|
||||
await allFuturesThrowing(
|
||||
nodes.mapIt(
|
||||
allFutures(
|
||||
it.stop(),
|
||||
it.switch.stop())))
|
||||
|
||||
await allFuturesThrowing(nodesFut)
|
||||
|
||||
waitFor(runTests())
|
||||
await allFuturesThrowing(nodesFut)
|
||||
|
|
|
@ -30,404 +30,345 @@ suite "GossipSub internal":
|
|||
teardown:
|
||||
checkTrackers()
|
||||
|
||||
test "topic params":
|
||||
proc testRun(): Future[bool] {.async.} =
|
||||
let params = TopicParams.init()
|
||||
params.validateParameters().tryGet()
|
||||
asyncTest "topic params":
|
||||
let params = TopicParams.init()
|
||||
params.validateParameters().tryGet()
|
||||
|
||||
return true
|
||||
asyncTest "`rebalanceMesh` Degree Lo":
|
||||
let gossipSub = TestGossipSub.init(newStandardSwitch())
|
||||
|
||||
check:
|
||||
waitFor(testRun()) == true
|
||||
let topic = "foobar"
|
||||
gossipSub.mesh[topic] = initHashSet[PubSubPeer]()
|
||||
gossipSub.topicParams[topic] = TopicParams.init()
|
||||
|
||||
test "`rebalanceMesh` Degree Lo":
|
||||
proc testRun(): Future[bool] {.async.} =
|
||||
let gossipSub = TestGossipSub.init(newStandardSwitch())
|
||||
var conns = newSeq[Connection]()
|
||||
gossipSub.gossipsub[topic] = initHashSet[PubSubPeer]()
|
||||
for i in 0..<15:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
let peer = gossipSub.getPubSubPeer(peerInfo.peerId)
|
||||
peer.sendConn = conn
|
||||
gossipSub.onNewPeer(peer)
|
||||
gossipSub.peers[peerInfo.peerId] = peer
|
||||
gossipSub.gossipsub[topic].incl(peer)
|
||||
|
||||
let topic = "foobar"
|
||||
gossipSub.mesh[topic] = initHashSet[PubSubPeer]()
|
||||
gossipSub.topicParams[topic] = TopicParams.init()
|
||||
check gossipSub.peers.len == 15
|
||||
await gossipSub.rebalanceMesh(topic)
|
||||
check gossipSub.mesh[topic].len == GossipSubD # + 2 # account opportunistic grafts
|
||||
|
||||
var conns = newSeq[Connection]()
|
||||
gossipSub.gossipsub[topic] = initHashSet[PubSubPeer]()
|
||||
for i in 0..<15:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
let peer = gossipSub.getPubSubPeer(peerInfo.peerId)
|
||||
peer.sendConn = conn
|
||||
gossipSub.onNewPeer(peer)
|
||||
gossipSub.peers[peerInfo.peerId] = peer
|
||||
gossipSub.gossipsub[topic].incl(peer)
|
||||
await allFuturesThrowing(conns.mapIt(it.close()))
|
||||
await gossipSub.switch.stop()
|
||||
|
||||
check gossipSub.peers.len == 15
|
||||
await gossipSub.rebalanceMesh(topic)
|
||||
check gossipSub.mesh[topic].len == GossipSubD # + 2 # account opportunistic grafts
|
||||
asyncTest "`rebalanceMesh` Degree Hi":
|
||||
let gossipSub = TestGossipSub.init(newStandardSwitch())
|
||||
|
||||
await allFuturesThrowing(conns.mapIt(it.close()))
|
||||
await gossipSub.switch.stop()
|
||||
result = true
|
||||
let topic = "foobar"
|
||||
gossipSub.mesh[topic] = initHashSet[PubSubPeer]()
|
||||
gossipSub.topicParams[topic] = TopicParams.init()
|
||||
|
||||
check:
|
||||
waitFor(testRun()) == true
|
||||
var conns = newSeq[Connection]()
|
||||
gossipSub.gossipsub[topic] = initHashSet[PubSubPeer]()
|
||||
for i in 0..<15:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = PeerInfo.init(PrivateKey.random(ECDSA, rng[]).get())
|
||||
conn.peerInfo = peerInfo
|
||||
let peer = gossipSub.getPubSubPeer(peerInfo.peerId)
|
||||
gossipSub.onNewPeer(peer)
|
||||
gossipSub.grafted(peer, topic)
|
||||
gossipSub.peers[peerInfo.peerId] = peer
|
||||
gossipSub.mesh[topic].incl(peer)
|
||||
|
||||
test "`rebalanceMesh` Degree Hi":
|
||||
proc testRun(): Future[bool] {.async.} =
|
||||
let gossipSub = TestGossipSub.init(newStandardSwitch())
|
||||
check gossipSub.mesh[topic].len == 15
|
||||
await gossipSub.rebalanceMesh(topic)
|
||||
check gossipSub.mesh[topic].len == GossipSubD + gossipSub.parameters.dScore
|
||||
|
||||
let topic = "foobar"
|
||||
gossipSub.mesh[topic] = initHashSet[PubSubPeer]()
|
||||
gossipSub.topicParams[topic] = TopicParams.init()
|
||||
await allFuturesThrowing(conns.mapIt(it.close()))
|
||||
await gossipSub.switch.stop()
|
||||
|
||||
var conns = newSeq[Connection]()
|
||||
gossipSub.gossipsub[topic] = initHashSet[PubSubPeer]()
|
||||
for i in 0..<15:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = PeerInfo.init(PrivateKey.random(ECDSA, rng[]).get())
|
||||
conn.peerInfo = peerInfo
|
||||
let peer = gossipSub.getPubSubPeer(peerInfo.peerId)
|
||||
gossipSub.onNewPeer(peer)
|
||||
asyncTest "`replenishFanout` Degree Lo":
|
||||
let gossipSub = TestGossipSub.init(newStandardSwitch())
|
||||
|
||||
proc handler(peer: PubSubPeer, msg: RPCMsg) {.async.} =
|
||||
discard
|
||||
|
||||
let topic = "foobar"
|
||||
gossipSub.gossipsub[topic] = initHashSet[PubSubPeer]()
|
||||
gossipSub.topicParams[topic] = TopicParams.init()
|
||||
|
||||
var conns = newSeq[Connection]()
|
||||
for i in 0..<15:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
var peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
let peer = gossipSub.getPubSubPeer(peerInfo.peerId)
|
||||
gossipSub.onNewPeer(peer)
|
||||
peer.handler = handler
|
||||
gossipSub.gossipsub[topic].incl(peer)
|
||||
|
||||
check gossipSub.gossipsub[topic].len == 15
|
||||
gossipSub.replenishFanout(topic)
|
||||
check gossipSub.fanout[topic].len == GossipSubD
|
||||
|
||||
await allFuturesThrowing(conns.mapIt(it.close()))
|
||||
await gossipSub.switch.stop()
|
||||
|
||||
asyncTest "`dropFanoutPeers` drop expired fanout topics":
|
||||
let gossipSub = TestGossipSub.init(newStandardSwitch())
|
||||
|
||||
proc handler(peer: PubSubPeer, msg: RPCMsg) {.async.} =
|
||||
discard
|
||||
|
||||
let topic = "foobar"
|
||||
gossipSub.topicParams[topic] = TopicParams.init()
|
||||
gossipSub.fanout[topic] = initHashSet[PubSubPeer]()
|
||||
gossipSub.lastFanoutPubSub[topic] = Moment.fromNow(1.millis)
|
||||
await sleepAsync(5.millis) # allow the topic to expire
|
||||
|
||||
var conns = newSeq[Connection]()
|
||||
for i in 0..<6:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = PeerInfo.init(PrivateKey.random(ECDSA, rng[]).get())
|
||||
conn.peerInfo = peerInfo
|
||||
let peer = gossipSub.getPubSubPeer(peerInfo.peerId)
|
||||
gossipSub.onNewPeer(peer)
|
||||
peer.handler = handler
|
||||
gossipSub.fanout[topic].incl(peer)
|
||||
|
||||
check gossipSub.fanout[topic].len == GossipSubD
|
||||
|
||||
gossipSub.dropFanoutPeers()
|
||||
check topic notin gossipSub.fanout
|
||||
|
||||
await allFuturesThrowing(conns.mapIt(it.close()))
|
||||
await gossipSub.switch.stop()
|
||||
|
||||
asyncTest "`dropFanoutPeers` leave unexpired fanout topics":
|
||||
let gossipSub = TestGossipSub.init(newStandardSwitch())
|
||||
|
||||
proc handler(peer: PubSubPeer, msg: RPCMsg) {.async.} =
|
||||
discard
|
||||
|
||||
let topic1 = "foobar1"
|
||||
let topic2 = "foobar2"
|
||||
gossipSub.topicParams[topic1] = TopicParams.init()
|
||||
gossipSub.topicParams[topic2] = TopicParams.init()
|
||||
gossipSub.fanout[topic1] = initHashSet[PubSubPeer]()
|
||||
gossipSub.fanout[topic2] = initHashSet[PubSubPeer]()
|
||||
gossipSub.lastFanoutPubSub[topic1] = Moment.fromNow(1.millis)
|
||||
gossipSub.lastFanoutPubSub[topic2] = Moment.fromNow(1.minutes)
|
||||
await sleepAsync(5.millis) # allow the topic to expire
|
||||
|
||||
var conns = newSeq[Connection]()
|
||||
for i in 0..<6:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
let peer = gossipSub.getPubSubPeer(peerInfo.peerId)
|
||||
gossipSub.onNewPeer(peer)
|
||||
peer.handler = handler
|
||||
gossipSub.fanout[topic1].incl(peer)
|
||||
gossipSub.fanout[topic2].incl(peer)
|
||||
|
||||
check gossipSub.fanout[topic1].len == GossipSubD
|
||||
check gossipSub.fanout[topic2].len == GossipSubD
|
||||
|
||||
gossipSub.dropFanoutPeers()
|
||||
check topic1 notin gossipSub.fanout
|
||||
check topic2 in gossipSub.fanout
|
||||
|
||||
await allFuturesThrowing(conns.mapIt(it.close()))
|
||||
await gossipSub.switch.stop()
|
||||
|
||||
asyncTest "`getGossipPeers` - should gather up to degree D non intersecting peers":
|
||||
let gossipSub = TestGossipSub.init(newStandardSwitch())
|
||||
|
||||
proc handler(peer: PubSubPeer, msg: RPCMsg) {.async.} =
|
||||
discard
|
||||
|
||||
let topic = "foobar"
|
||||
gossipSub.topicParams[topic] = TopicParams.init()
|
||||
gossipSub.mesh[topic] = initHashSet[PubSubPeer]()
|
||||
gossipSub.fanout[topic] = initHashSet[PubSubPeer]()
|
||||
gossipSub.gossipsub[topic] = initHashSet[PubSubPeer]()
|
||||
var conns = newSeq[Connection]()
|
||||
|
||||
# generate mesh and fanout peers
|
||||
for i in 0..<30:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
let peer = gossipSub.getPubSubPeer(peerInfo.peerId)
|
||||
gossipSub.onNewPeer(peer)
|
||||
peer.handler = handler
|
||||
if i mod 2 == 0:
|
||||
gossipSub.fanout[topic].incl(peer)
|
||||
else:
|
||||
gossipSub.grafted(peer, topic)
|
||||
gossipSub.peers[peerInfo.peerId] = peer
|
||||
gossipSub.mesh[topic].incl(peer)
|
||||
|
||||
check gossipSub.mesh[topic].len == 15
|
||||
await gossipSub.rebalanceMesh(topic)
|
||||
check gossipSub.mesh[topic].len == GossipSubD + gossipSub.parameters.dScore
|
||||
# generate gossipsub (free standing) peers
|
||||
for i in 0..<15:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
let peer = gossipSub.getPubSubPeer(peerInfo.peerId)
|
||||
gossipSub.onNewPeer(peer)
|
||||
peer.handler = handler
|
||||
gossipSub.gossipsub[topic].incl(peer)
|
||||
|
||||
await allFuturesThrowing(conns.mapIt(it.close()))
|
||||
await gossipSub.switch.stop()
|
||||
# generate messages
|
||||
var seqno = 0'u64
|
||||
for i in 0..5:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
inc seqno
|
||||
let msg = Message.init(some(peerInfo), ("HELLO" & $i).toBytes(), topic, some(seqno), false)
|
||||
gossipSub.mcache.put(gossipSub.msgIdProvider(msg), msg)
|
||||
|
||||
result = true
|
||||
check gossipSub.fanout[topic].len == 15
|
||||
check gossipSub.mesh[topic].len == 15
|
||||
check gossipSub.gossipsub[topic].len == 15
|
||||
|
||||
check:
|
||||
waitFor(testRun()) == true
|
||||
let peers = gossipSub.getGossipPeers()
|
||||
check peers.len == GossipSubD
|
||||
for p in peers.keys:
|
||||
check not gossipSub.fanout.hasPeerID(topic, p.peerId)
|
||||
check not gossipSub.mesh.hasPeerID(topic, p.peerId)
|
||||
|
||||
test "`replenishFanout` Degree Lo":
|
||||
proc testRun(): Future[bool] {.async.} =
|
||||
let gossipSub = TestGossipSub.init(newStandardSwitch())
|
||||
await allFuturesThrowing(conns.mapIt(it.close()))
|
||||
await gossipSub.switch.stop()
|
||||
|
||||
proc handler(peer: PubSubPeer, msg: RPCMsg) {.async.} =
|
||||
discard
|
||||
asyncTest "`getGossipPeers` - should not crash on missing topics in mesh":
|
||||
let gossipSub = TestGossipSub.init(newStandardSwitch())
|
||||
|
||||
let topic = "foobar"
|
||||
gossipSub.gossipsub[topic] = initHashSet[PubSubPeer]()
|
||||
gossipSub.topicParams[topic] = TopicParams.init()
|
||||
proc handler(peer: PubSubPeer, msg: RPCMsg) {.async.} =
|
||||
discard
|
||||
|
||||
var conns = newSeq[Connection]()
|
||||
for i in 0..<15:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
var peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
let peer = gossipSub.getPubSubPeer(peerInfo.peerId)
|
||||
gossipSub.onNewPeer(peer)
|
||||
peer.handler = handler
|
||||
let topic = "foobar"
|
||||
gossipSub.topicParams[topic] = TopicParams.init()
|
||||
gossipSub.fanout[topic] = initHashSet[PubSubPeer]()
|
||||
gossipSub.gossipsub[topic] = initHashSet[PubSubPeer]()
|
||||
var conns = newSeq[Connection]()
|
||||
for i in 0..<30:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
let peer = gossipSub.getPubSubPeer(peerInfo.peerId)
|
||||
gossipSub.onNewPeer(peer)
|
||||
peer.handler = handler
|
||||
if i mod 2 == 0:
|
||||
gossipSub.fanout[topic].incl(peer)
|
||||
else:
|
||||
gossipSub.gossipsub[topic].incl(peer)
|
||||
|
||||
check gossipSub.gossipsub[topic].len == 15
|
||||
gossipSub.replenishFanout(topic)
|
||||
check gossipSub.fanout[topic].len == GossipSubD
|
||||
# generate messages
|
||||
var seqno = 0'u64
|
||||
for i in 0..5:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
inc seqno
|
||||
let msg = Message.init(some(peerInfo), ("HELLO" & $i).toBytes(), topic, some(seqno), false)
|
||||
gossipSub.mcache.put(gossipSub.msgIdProvider(msg), msg)
|
||||
|
||||
await allFuturesThrowing(conns.mapIt(it.close()))
|
||||
await gossipSub.switch.stop()
|
||||
let peers = gossipSub.getGossipPeers()
|
||||
check peers.len == GossipSubD
|
||||
|
||||
result = true
|
||||
await allFuturesThrowing(conns.mapIt(it.close()))
|
||||
await gossipSub.switch.stop()
|
||||
|
||||
check:
|
||||
waitFor(testRun()) == true
|
||||
asyncTest "`getGossipPeers` - should not crash on missing topics in fanout":
|
||||
let gossipSub = TestGossipSub.init(newStandardSwitch())
|
||||
|
||||
test "`dropFanoutPeers` drop expired fanout topics":
|
||||
proc testRun(): Future[bool] {.async.} =
|
||||
let gossipSub = TestGossipSub.init(newStandardSwitch())
|
||||
proc handler(peer: PubSubPeer, msg: RPCMsg) {.async.} =
|
||||
discard
|
||||
|
||||
proc handler(peer: PubSubPeer, msg: RPCMsg) {.async.} =
|
||||
discard
|
||||
let topic = "foobar"
|
||||
gossipSub.topicParams[topic] = TopicParams.init()
|
||||
gossipSub.mesh[topic] = initHashSet[PubSubPeer]()
|
||||
gossipSub.gossipsub[topic] = initHashSet[PubSubPeer]()
|
||||
var conns = newSeq[Connection]()
|
||||
for i in 0..<30:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
let peer = gossipSub.getPubSubPeer(peerInfo.peerId)
|
||||
gossipSub.onNewPeer(peer)
|
||||
peer.handler = handler
|
||||
if i mod 2 == 0:
|
||||
gossipSub.mesh[topic].incl(peer)
|
||||
gossipSub.grafted(peer, topic)
|
||||
else:
|
||||
gossipSub.gossipsub[topic].incl(peer)
|
||||
|
||||
let topic = "foobar"
|
||||
gossipSub.topicParams[topic] = TopicParams.init()
|
||||
gossipSub.fanout[topic] = initHashSet[PubSubPeer]()
|
||||
gossipSub.lastFanoutPubSub[topic] = Moment.fromNow(1.millis)
|
||||
await sleepAsync(5.millis) # allow the topic to expire
|
||||
# generate messages
|
||||
var seqno = 0'u64
|
||||
for i in 0..5:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
inc seqno
|
||||
let msg = Message.init(some(peerInfo), ("HELLO" & $i).toBytes(), topic, some(seqno), false)
|
||||
gossipSub.mcache.put(gossipSub.msgIdProvider(msg), msg)
|
||||
|
||||
var conns = newSeq[Connection]()
|
||||
for i in 0..<6:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = PeerInfo.init(PrivateKey.random(ECDSA, rng[]).get())
|
||||
conn.peerInfo = peerInfo
|
||||
let peer = gossipSub.getPubSubPeer(peerInfo.peerId)
|
||||
gossipSub.onNewPeer(peer)
|
||||
peer.handler = handler
|
||||
let peers = gossipSub.getGossipPeers()
|
||||
check peers.len == GossipSubD
|
||||
|
||||
await allFuturesThrowing(conns.mapIt(it.close()))
|
||||
await gossipSub.switch.stop()
|
||||
|
||||
asyncTest "`getGossipPeers` - should not crash on missing topics in gossip":
|
||||
let gossipSub = TestGossipSub.init(newStandardSwitch())
|
||||
|
||||
proc handler(peer: PubSubPeer, msg: RPCMsg) {.async.} =
|
||||
discard
|
||||
|
||||
let topic = "foobar"
|
||||
gossipSub.topicParams[topic] = TopicParams.init()
|
||||
gossipSub.mesh[topic] = initHashSet[PubSubPeer]()
|
||||
gossipSub.fanout[topic] = initHashSet[PubSubPeer]()
|
||||
var conns = newSeq[Connection]()
|
||||
for i in 0..<30:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
let peer = gossipSub.getPubSubPeer(peerInfo.peerId)
|
||||
gossipSub.onNewPeer(peer)
|
||||
peer.handler = handler
|
||||
if i mod 2 == 0:
|
||||
gossipSub.mesh[topic].incl(peer)
|
||||
gossipSub.grafted(peer, topic)
|
||||
else:
|
||||
gossipSub.fanout[topic].incl(peer)
|
||||
|
||||
check gossipSub.fanout[topic].len == GossipSubD
|
||||
# generate messages
|
||||
var seqno = 0'u64
|
||||
for i in 0..5:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
inc seqno
|
||||
let msg = Message.init(some(peerInfo), ("bar" & $i).toBytes(), topic, some(seqno), false)
|
||||
gossipSub.mcache.put(gossipSub.msgIdProvider(msg), msg)
|
||||
|
||||
gossipSub.dropFanoutPeers()
|
||||
check topic notin gossipSub.fanout
|
||||
let peers = gossipSub.getGossipPeers()
|
||||
check peers.len == 0
|
||||
|
||||
await allFuturesThrowing(conns.mapIt(it.close()))
|
||||
await gossipSub.switch.stop()
|
||||
|
||||
result = true
|
||||
|
||||
check:
|
||||
waitFor(testRun()) == true
|
||||
|
||||
test "`dropFanoutPeers` leave unexpired fanout topics":
|
||||
proc testRun(): Future[bool] {.async.} =
|
||||
let gossipSub = TestGossipSub.init(newStandardSwitch())
|
||||
|
||||
proc handler(peer: PubSubPeer, msg: RPCMsg) {.async.} =
|
||||
discard
|
||||
|
||||
let topic1 = "foobar1"
|
||||
let topic2 = "foobar2"
|
||||
gossipSub.topicParams[topic1] = TopicParams.init()
|
||||
gossipSub.topicParams[topic2] = TopicParams.init()
|
||||
gossipSub.fanout[topic1] = initHashSet[PubSubPeer]()
|
||||
gossipSub.fanout[topic2] = initHashSet[PubSubPeer]()
|
||||
gossipSub.lastFanoutPubSub[topic1] = Moment.fromNow(1.millis)
|
||||
gossipSub.lastFanoutPubSub[topic2] = Moment.fromNow(1.minutes)
|
||||
await sleepAsync(5.millis) # allow the topic to expire
|
||||
|
||||
var conns = newSeq[Connection]()
|
||||
for i in 0..<6:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
let peer = gossipSub.getPubSubPeer(peerInfo.peerId)
|
||||
gossipSub.onNewPeer(peer)
|
||||
peer.handler = handler
|
||||
gossipSub.fanout[topic1].incl(peer)
|
||||
gossipSub.fanout[topic2].incl(peer)
|
||||
|
||||
check gossipSub.fanout[topic1].len == GossipSubD
|
||||
check gossipSub.fanout[topic2].len == GossipSubD
|
||||
|
||||
gossipSub.dropFanoutPeers()
|
||||
check topic1 notin gossipSub.fanout
|
||||
check topic2 in gossipSub.fanout
|
||||
|
||||
await allFuturesThrowing(conns.mapIt(it.close()))
|
||||
await gossipSub.switch.stop()
|
||||
|
||||
result = true
|
||||
|
||||
check:
|
||||
waitFor(testRun()) == true
|
||||
|
||||
test "`getGossipPeers` - should gather up to degree D non intersecting peers":
|
||||
proc testRun(): Future[bool] {.async.} =
|
||||
let gossipSub = TestGossipSub.init(newStandardSwitch())
|
||||
|
||||
proc handler(peer: PubSubPeer, msg: RPCMsg) {.async.} =
|
||||
discard
|
||||
|
||||
let topic = "foobar"
|
||||
gossipSub.topicParams[topic] = TopicParams.init()
|
||||
gossipSub.mesh[topic] = initHashSet[PubSubPeer]()
|
||||
gossipSub.fanout[topic] = initHashSet[PubSubPeer]()
|
||||
gossipSub.gossipsub[topic] = initHashSet[PubSubPeer]()
|
||||
var conns = newSeq[Connection]()
|
||||
|
||||
# generate mesh and fanout peers
|
||||
for i in 0..<30:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
let peer = gossipSub.getPubSubPeer(peerInfo.peerId)
|
||||
gossipSub.onNewPeer(peer)
|
||||
peer.handler = handler
|
||||
if i mod 2 == 0:
|
||||
gossipSub.fanout[topic].incl(peer)
|
||||
else:
|
||||
gossipSub.grafted(peer, topic)
|
||||
gossipSub.mesh[topic].incl(peer)
|
||||
|
||||
# generate gossipsub (free standing) peers
|
||||
for i in 0..<15:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
let peer = gossipSub.getPubSubPeer(peerInfo.peerId)
|
||||
gossipSub.onNewPeer(peer)
|
||||
peer.handler = handler
|
||||
gossipSub.gossipsub[topic].incl(peer)
|
||||
|
||||
# generate messages
|
||||
var seqno = 0'u64
|
||||
for i in 0..5:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
inc seqno
|
||||
let msg = Message.init(some(peerInfo), ("HELLO" & $i).toBytes(), topic, some(seqno), false)
|
||||
gossipSub.mcache.put(gossipSub.msgIdProvider(msg), msg)
|
||||
|
||||
check gossipSub.fanout[topic].len == 15
|
||||
check gossipSub.mesh[topic].len == 15
|
||||
check gossipSub.gossipsub[topic].len == 15
|
||||
|
||||
let peers = gossipSub.getGossipPeers()
|
||||
check peers.len == GossipSubD
|
||||
for p in peers.keys:
|
||||
check not gossipSub.fanout.hasPeerID(topic, p.peerId)
|
||||
check not gossipSub.mesh.hasPeerID(topic, p.peerId)
|
||||
|
||||
await allFuturesThrowing(conns.mapIt(it.close()))
|
||||
await gossipSub.switch.stop()
|
||||
|
||||
result = true
|
||||
|
||||
check:
|
||||
waitFor(testRun()) == true
|
||||
|
||||
test "`getGossipPeers` - should not crash on missing topics in mesh":
|
||||
proc testRun(): Future[bool] {.async.} =
|
||||
let gossipSub = TestGossipSub.init(newStandardSwitch())
|
||||
|
||||
proc handler(peer: PubSubPeer, msg: RPCMsg) {.async.} =
|
||||
discard
|
||||
|
||||
let topic = "foobar"
|
||||
gossipSub.topicParams[topic] = TopicParams.init()
|
||||
gossipSub.fanout[topic] = initHashSet[PubSubPeer]()
|
||||
gossipSub.gossipsub[topic] = initHashSet[PubSubPeer]()
|
||||
var conns = newSeq[Connection]()
|
||||
for i in 0..<30:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
let peer = gossipSub.getPubSubPeer(peerInfo.peerId)
|
||||
gossipSub.onNewPeer(peer)
|
||||
peer.handler = handler
|
||||
if i mod 2 == 0:
|
||||
gossipSub.fanout[topic].incl(peer)
|
||||
else:
|
||||
gossipSub.gossipsub[topic].incl(peer)
|
||||
|
||||
# generate messages
|
||||
var seqno = 0'u64
|
||||
for i in 0..5:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
inc seqno
|
||||
let msg = Message.init(some(peerInfo), ("HELLO" & $i).toBytes(), topic, some(seqno), false)
|
||||
gossipSub.mcache.put(gossipSub.msgIdProvider(msg), msg)
|
||||
|
||||
let peers = gossipSub.getGossipPeers()
|
||||
check peers.len == GossipSubD
|
||||
|
||||
await allFuturesThrowing(conns.mapIt(it.close()))
|
||||
await gossipSub.switch.stop()
|
||||
|
||||
result = true
|
||||
|
||||
check:
|
||||
waitFor(testRun()) == true
|
||||
|
||||
test "`getGossipPeers` - should not crash on missing topics in fanout":
|
||||
proc testRun(): Future[bool] {.async.} =
|
||||
let gossipSub = TestGossipSub.init(newStandardSwitch())
|
||||
|
||||
proc handler(peer: PubSubPeer, msg: RPCMsg) {.async.} =
|
||||
discard
|
||||
|
||||
let topic = "foobar"
|
||||
gossipSub.topicParams[topic] = TopicParams.init()
|
||||
gossipSub.mesh[topic] = initHashSet[PubSubPeer]()
|
||||
gossipSub.gossipsub[topic] = initHashSet[PubSubPeer]()
|
||||
var conns = newSeq[Connection]()
|
||||
for i in 0..<30:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
let peer = gossipSub.getPubSubPeer(peerInfo.peerId)
|
||||
gossipSub.onNewPeer(peer)
|
||||
peer.handler = handler
|
||||
if i mod 2 == 0:
|
||||
gossipSub.mesh[topic].incl(peer)
|
||||
gossipSub.grafted(peer, topic)
|
||||
else:
|
||||
gossipSub.gossipsub[topic].incl(peer)
|
||||
|
||||
# generate messages
|
||||
var seqno = 0'u64
|
||||
for i in 0..5:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
inc seqno
|
||||
let msg = Message.init(some(peerInfo), ("HELLO" & $i).toBytes(), topic, some(seqno), false)
|
||||
gossipSub.mcache.put(gossipSub.msgIdProvider(msg), msg)
|
||||
|
||||
let peers = gossipSub.getGossipPeers()
|
||||
check peers.len == GossipSubD
|
||||
|
||||
await allFuturesThrowing(conns.mapIt(it.close()))
|
||||
await gossipSub.switch.stop()
|
||||
|
||||
result = true
|
||||
|
||||
check:
|
||||
waitFor(testRun()) == true
|
||||
|
||||
test "`getGossipPeers` - should not crash on missing topics in gossip":
|
||||
proc testRun(): Future[bool] {.async.} =
|
||||
let gossipSub = TestGossipSub.init(newStandardSwitch())
|
||||
|
||||
proc handler(peer: PubSubPeer, msg: RPCMsg) {.async.} =
|
||||
discard
|
||||
|
||||
let topic = "foobar"
|
||||
gossipSub.topicParams[topic] = TopicParams.init()
|
||||
gossipSub.mesh[topic] = initHashSet[PubSubPeer]()
|
||||
gossipSub.fanout[topic] = initHashSet[PubSubPeer]()
|
||||
var conns = newSeq[Connection]()
|
||||
for i in 0..<30:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
let peer = gossipSub.getPubSubPeer(peerInfo.peerId)
|
||||
gossipSub.onNewPeer(peer)
|
||||
peer.handler = handler
|
||||
if i mod 2 == 0:
|
||||
gossipSub.mesh[topic].incl(peer)
|
||||
gossipSub.grafted(peer, topic)
|
||||
else:
|
||||
gossipSub.fanout[topic].incl(peer)
|
||||
|
||||
# generate messages
|
||||
var seqno = 0'u64
|
||||
for i in 0..5:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
inc seqno
|
||||
let msg = Message.init(some(peerInfo), ("bar" & $i).toBytes(), topic, some(seqno), false)
|
||||
gossipSub.mcache.put(gossipSub.msgIdProvider(msg), msg)
|
||||
|
||||
let peers = gossipSub.getGossipPeers()
|
||||
check peers.len == 0
|
||||
|
||||
await allFuturesThrowing(conns.mapIt(it.close()))
|
||||
await gossipSub.switch.stop()
|
||||
|
||||
result = true
|
||||
|
||||
check:
|
||||
waitFor(testRun()) == true
|
||||
await allFuturesThrowing(conns.mapIt(it.close()))
|
||||
await gossipSub.switch.stop()
|
||||
|
|
|
@ -28,375 +28,320 @@ proc randomPeerInfo(): PeerInfo =
|
|||
|
||||
suite "GossipSub internal":
|
||||
teardown:
|
||||
for tracker in testTrackers():
|
||||
# echo tracker.dump()
|
||||
check tracker.isLeaked() == false
|
||||
checkTrackers()
|
||||
|
||||
test "`rebalanceMesh` Degree Lo":
|
||||
proc testRun(): Future[bool] {.async.} =
|
||||
let gossipSub = TestGossipSub.init(newStandardSwitch())
|
||||
asyncTest "`rebalanceMesh` Degree Lo":
|
||||
let gossipSub = TestGossipSub.init(newStandardSwitch())
|
||||
|
||||
let topic = "foobar"
|
||||
gossipSub.mesh[topic] = initHashSet[PubSubPeer]()
|
||||
let topic = "foobar"
|
||||
gossipSub.mesh[topic] = initHashSet[PubSubPeer]()
|
||||
|
||||
var conns = newSeq[Connection]()
|
||||
gossipSub.gossipsub[topic] = initHashSet[PubSubPeer]()
|
||||
for i in 0..<15:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
let peer = gossipSub.getPubSubPeer(peerInfo.peerId)
|
||||
peer.sendConn = conn
|
||||
gossipSub.peers[peerInfo.peerId] = peer
|
||||
var conns = newSeq[Connection]()
|
||||
gossipSub.gossipsub[topic] = initHashSet[PubSubPeer]()
|
||||
for i in 0..<15:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
let peer = gossipSub.getPubSubPeer(peerInfo.peerId)
|
||||
peer.sendConn = conn
|
||||
gossipSub.peers[peerInfo.peerId] = peer
|
||||
gossipSub.mesh[topic].incl(peer)
|
||||
|
||||
check gossipSub.peers.len == 15
|
||||
await gossipSub.rebalanceMesh(topic)
|
||||
check gossipSub.mesh[topic].len == GossipSubD
|
||||
|
||||
await allFuturesThrowing(conns.mapIt(it.close()))
|
||||
await gossipSub.switch.stop()
|
||||
|
||||
asyncTest "`rebalanceMesh` Degree Hi":
|
||||
let gossipSub = TestGossipSub.init(newStandardSwitch())
|
||||
|
||||
let topic = "foobar"
|
||||
gossipSub.mesh[topic] = initHashSet[PubSubPeer]()
|
||||
gossipSub.topics[topic] = Topic() # has to be in topics to rebalance
|
||||
|
||||
gossipSub.gossipsub[topic] = initHashSet[PubSubPeer]()
|
||||
var conns = newSeq[Connection]()
|
||||
for i in 0..<15:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = PeerInfo.init(PrivateKey.random(ECDSA, rng[]).get())
|
||||
conn.peerInfo = peerInfo
|
||||
let peer = gossipSub.getPubSubPeer(peerInfo.peerId)
|
||||
gossipSub.peers[peerInfo.peerId] = peer
|
||||
gossipSub.mesh[topic].incl(peer)
|
||||
|
||||
check gossipSub.mesh[topic].len == 15
|
||||
await gossipSub.rebalanceMesh(topic)
|
||||
check gossipSub.mesh[topic].len == GossipSubD
|
||||
|
||||
await allFuturesThrowing(conns.mapIt(it.close()))
|
||||
await gossipSub.switch.stop()
|
||||
|
||||
asyncTest "`replenishFanout` Degree Lo":
|
||||
let gossipSub = TestGossipSub.init(newStandardSwitch())
|
||||
|
||||
proc handler(peer: PubSubPeer, msg: RPCMsg) {.async.} =
|
||||
discard
|
||||
|
||||
let topic = "foobar"
|
||||
gossipSub.gossipsub[topic] = initHashSet[PubSubPeer]()
|
||||
|
||||
var conns = newSeq[Connection]()
|
||||
for i in 0..<15:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
var peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
let peer = gossipSub.getPubSubPeer(peerInfo.peerId)
|
||||
peer.handler = handler
|
||||
gossipSub.gossipsub[topic].incl(peer)
|
||||
|
||||
check gossipSub.gossipsub[topic].len == 15
|
||||
gossipSub.replenishFanout(topic)
|
||||
check gossipSub.fanout[topic].len == GossipSubD
|
||||
|
||||
await allFuturesThrowing(conns.mapIt(it.close()))
|
||||
await gossipSub.switch.stop()
|
||||
|
||||
asyncTest "`dropFanoutPeers` drop expired fanout topics":
|
||||
let gossipSub = TestGossipSub.init(newStandardSwitch())
|
||||
|
||||
proc handler(peer: PubSubPeer, msg: RPCMsg) {.async.} =
|
||||
discard
|
||||
|
||||
let topic = "foobar"
|
||||
gossipSub.fanout[topic] = initHashSet[PubSubPeer]()
|
||||
gossipSub.lastFanoutPubSub[topic] = Moment.fromNow(1.millis)
|
||||
await sleepAsync(5.millis) # allow the topic to expire
|
||||
|
||||
var conns = newSeq[Connection]()
|
||||
for i in 0..<6:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = PeerInfo.init(PrivateKey.random(ECDSA, rng[]).get())
|
||||
conn.peerInfo = peerInfo
|
||||
let peer = gossipSub.getPubSubPeer(peerInfo.peerId)
|
||||
peer.handler = handler
|
||||
gossipSub.fanout[topic].incl(peer)
|
||||
|
||||
check gossipSub.fanout[topic].len == GossipSubD
|
||||
|
||||
gossipSub.dropFanoutPeers()
|
||||
check topic notin gossipSub.fanout
|
||||
|
||||
await allFuturesThrowing(conns.mapIt(it.close()))
|
||||
await gossipSub.switch.stop()
|
||||
|
||||
asyncTEst "`dropFanoutPeers` leave unexpired fanout topics":
|
||||
let gossipSub = TestGossipSub.init(newStandardSwitch())
|
||||
|
||||
proc handler(peer: PubSubPeer, msg: RPCMsg) {.async.} =
|
||||
discard
|
||||
|
||||
let topic1 = "foobar1"
|
||||
let topic2 = "foobar2"
|
||||
gossipSub.fanout[topic1] = initHashSet[PubSubPeer]()
|
||||
gossipSub.fanout[topic2] = initHashSet[PubSubPeer]()
|
||||
gossipSub.lastFanoutPubSub[topic1] = Moment.fromNow(1.millis)
|
||||
gossipSub.lastFanoutPubSub[topic2] = Moment.fromNow(1.minutes)
|
||||
await sleepAsync(5.millis) # allow the topic to expire
|
||||
|
||||
var conns = newSeq[Connection]()
|
||||
for i in 0..<6:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
let peer = gossipSub.getPubSubPeer(peerInfo.peerId)
|
||||
peer.handler = handler
|
||||
gossipSub.fanout[topic1].incl(peer)
|
||||
gossipSub.fanout[topic2].incl(peer)
|
||||
|
||||
check gossipSub.fanout[topic1].len == GossipSubD
|
||||
check gossipSub.fanout[topic2].len == GossipSubD
|
||||
|
||||
gossipSub.dropFanoutPeers()
|
||||
check topic1 notin gossipSub.fanout
|
||||
check topic2 in gossipSub.fanout
|
||||
|
||||
await allFuturesThrowing(conns.mapIt(it.close()))
|
||||
await gossipSub.switch.stop()
|
||||
|
||||
asyncTest "`getGossipPeers` - should gather up to degree D non intersecting peers":
|
||||
let gossipSub = TestGossipSub.init(newStandardSwitch())
|
||||
|
||||
proc handler(peer: PubSubPeer, msg: RPCMsg) {.async.} =
|
||||
discard
|
||||
|
||||
let topic = "foobar"
|
||||
gossipSub.mesh[topic] = initHashSet[PubSubPeer]()
|
||||
gossipSub.fanout[topic] = initHashSet[PubSubPeer]()
|
||||
gossipSub.gossipsub[topic] = initHashSet[PubSubPeer]()
|
||||
var conns = newSeq[Connection]()
|
||||
|
||||
# generate mesh and fanout peers
|
||||
for i in 0..<30:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
let peer = gossipSub.getPubSubPeer(peerInfo.peerId)
|
||||
peer.handler = handler
|
||||
if i mod 2 == 0:
|
||||
gossipSub.fanout[topic].incl(peer)
|
||||
else:
|
||||
gossipSub.mesh[topic].incl(peer)
|
||||
|
||||
check gossipSub.peers.len == 15
|
||||
await gossipSub.rebalanceMesh(topic)
|
||||
check gossipSub.mesh[topic].len == GossipSubD
|
||||
# generate gossipsub (free standing) peers
|
||||
for i in 0..<15:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
let peer = gossipSub.getPubSubPeer(peerInfo.peerId)
|
||||
peer.handler = handler
|
||||
gossipSub.gossipsub[topic].incl(peer)
|
||||
|
||||
await allFuturesThrowing(conns.mapIt(it.close()))
|
||||
await gossipSub.switch.stop()
|
||||
result = true
|
||||
# generate messages
|
||||
var seqno = 0'u64
|
||||
for i in 0..5:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
inc seqno
|
||||
let msg = Message.init(some(peerInfo), ("HELLO" & $i).toBytes(), topic, some(seqno), false)
|
||||
gossipSub.mcache.put(gossipSub.msgIdProvider(msg), msg)
|
||||
|
||||
check:
|
||||
waitFor(testRun()) == true
|
||||
check gossipSub.fanout[topic].len == 15
|
||||
check gossipSub.mesh[topic].len == 15
|
||||
check gossipSub.gossipsub[topic].len == 15
|
||||
|
||||
test "`rebalanceMesh` Degree Hi":
|
||||
proc testRun(): Future[bool] {.async.} =
|
||||
let gossipSub = TestGossipSub.init(newStandardSwitch())
|
||||
let peers = gossipSub.getGossipPeers()
|
||||
check peers.len == GossipSubD
|
||||
for p in peers.keys:
|
||||
check not gossipSub.fanout.hasPeerID(topic, p.peerId)
|
||||
check not gossipSub.mesh.hasPeerID(topic, p.peerId)
|
||||
|
||||
let topic = "foobar"
|
||||
gossipSub.mesh[topic] = initHashSet[PubSubPeer]()
|
||||
gossipSub.topics[topic] = Topic() # has to be in topics to rebalance
|
||||
await allFuturesThrowing(conns.mapIt(it.close()))
|
||||
await gossipSub.switch.stop()
|
||||
|
||||
gossipSub.gossipsub[topic] = initHashSet[PubSubPeer]()
|
||||
var conns = newSeq[Connection]()
|
||||
for i in 0..<15:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = PeerInfo.init(PrivateKey.random(ECDSA, rng[]).get())
|
||||
conn.peerInfo = peerInfo
|
||||
let peer = gossipSub.getPubSubPeer(peerInfo.peerId)
|
||||
gossipSub.peers[peerInfo.peerId] = peer
|
||||
gossipSub.mesh[topic].incl(peer)
|
||||
asyncTest "`getGossipPeers` - should not crash on missing topics in mesh":
|
||||
let gossipSub = TestGossipSub.init(newStandardSwitch())
|
||||
|
||||
check gossipSub.mesh[topic].len == 15
|
||||
await gossipSub.rebalanceMesh(topic)
|
||||
check gossipSub.mesh[topic].len == GossipSubD
|
||||
proc handler(peer: PubSubPeer, msg: RPCMsg) {.async.} =
|
||||
discard
|
||||
|
||||
await allFuturesThrowing(conns.mapIt(it.close()))
|
||||
await gossipSub.switch.stop()
|
||||
|
||||
result = true
|
||||
|
||||
check:
|
||||
waitFor(testRun()) == true
|
||||
|
||||
test "`replenishFanout` Degree Lo":
|
||||
proc testRun(): Future[bool] {.async.} =
|
||||
let gossipSub = TestGossipSub.init(newStandardSwitch())
|
||||
|
||||
proc handler(peer: PubSubPeer, msg: RPCMsg) {.async.} =
|
||||
discard
|
||||
|
||||
let topic = "foobar"
|
||||
gossipSub.gossipsub[topic] = initHashSet[PubSubPeer]()
|
||||
|
||||
var conns = newSeq[Connection]()
|
||||
for i in 0..<15:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
var peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
let peer = gossipSub.getPubSubPeer(peerInfo.peerId)
|
||||
peer.handler = handler
|
||||
let topic = "foobar"
|
||||
gossipSub.fanout[topic] = initHashSet[PubSubPeer]()
|
||||
gossipSub.gossipsub[topic] = initHashSet[PubSubPeer]()
|
||||
var conns = newSeq[Connection]()
|
||||
for i in 0..<30:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
let peer = gossipSub.getPubSubPeer(peerInfo.peerId)
|
||||
peer.handler = handler
|
||||
if i mod 2 == 0:
|
||||
gossipSub.fanout[topic].incl(peer)
|
||||
else:
|
||||
gossipSub.gossipsub[topic].incl(peer)
|
||||
|
||||
check gossipSub.gossipsub[topic].len == 15
|
||||
gossipSub.replenishFanout(topic)
|
||||
check gossipSub.fanout[topic].len == GossipSubD
|
||||
# generate messages
|
||||
var seqno = 0'u64
|
||||
for i in 0..5:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
inc seqno
|
||||
let msg = Message.init(some(peerInfo), ("HELLO" & $i).toBytes(), topic, some(seqno), false)
|
||||
gossipSub.mcache.put(gossipSub.msgIdProvider(msg), msg)
|
||||
|
||||
await allFuturesThrowing(conns.mapIt(it.close()))
|
||||
await gossipSub.switch.stop()
|
||||
let peers = gossipSub.getGossipPeers()
|
||||
check peers.len == GossipSubD
|
||||
|
||||
result = true
|
||||
await allFuturesThrowing(conns.mapIt(it.close()))
|
||||
await gossipSub.switch.stop()
|
||||
|
||||
check:
|
||||
waitFor(testRun()) == true
|
||||
asyncTest "`getGossipPeers` - should not crash on missing topics in fanout":
|
||||
let gossipSub = TestGossipSub.init(newStandardSwitch())
|
||||
|
||||
test "`dropFanoutPeers` drop expired fanout topics":
|
||||
proc testRun(): Future[bool] {.async.} =
|
||||
let gossipSub = TestGossipSub.init(newStandardSwitch())
|
||||
proc handler(peer: PubSubPeer, msg: RPCMsg) {.async.} =
|
||||
discard
|
||||
|
||||
proc handler(peer: PubSubPeer, msg: RPCMsg) {.async.} =
|
||||
discard
|
||||
let topic = "foobar"
|
||||
gossipSub.mesh[topic] = initHashSet[PubSubPeer]()
|
||||
gossipSub.gossipsub[topic] = initHashSet[PubSubPeer]()
|
||||
var conns = newSeq[Connection]()
|
||||
for i in 0..<30:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
let peer = gossipSub.getPubSubPeer(peerInfo.peerId)
|
||||
peer.handler = handler
|
||||
if i mod 2 == 0:
|
||||
gossipSub.mesh[topic].incl(peer)
|
||||
else:
|
||||
gossipSub.gossipsub[topic].incl(peer)
|
||||
|
||||
let topic = "foobar"
|
||||
gossipSub.fanout[topic] = initHashSet[PubSubPeer]()
|
||||
gossipSub.lastFanoutPubSub[topic] = Moment.fromNow(1.millis)
|
||||
await sleepAsync(5.millis) # allow the topic to expire
|
||||
# generate messages
|
||||
var seqno = 0'u64
|
||||
for i in 0..5:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
inc seqno
|
||||
let msg = Message.init(some(peerInfo), ("HELLO" & $i).toBytes(), topic, some(seqno), false)
|
||||
gossipSub.mcache.put(gossipSub.msgIdProvider(msg), msg)
|
||||
|
||||
var conns = newSeq[Connection]()
|
||||
for i in 0..<6:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = PeerInfo.init(PrivateKey.random(ECDSA, rng[]).get())
|
||||
conn.peerInfo = peerInfo
|
||||
let peer = gossipSub.getPubSubPeer(peerInfo.peerId)
|
||||
peer.handler = handler
|
||||
let peers = gossipSub.getGossipPeers()
|
||||
check peers.len == GossipSubD
|
||||
|
||||
await allFuturesThrowing(conns.mapIt(it.close()))
|
||||
await gossipSub.switch.stop()
|
||||
|
||||
asyncTest "`getGossipPeers` - should not crash on missing topics in gossip":
|
||||
let gossipSub = TestGossipSub.init(newStandardSwitch())
|
||||
|
||||
proc handler(peer: PubSubPeer, msg: RPCMsg) {.async.} =
|
||||
discard
|
||||
|
||||
let topic = "foobar"
|
||||
gossipSub.mesh[topic] = initHashSet[PubSubPeer]()
|
||||
gossipSub.fanout[topic] = initHashSet[PubSubPeer]()
|
||||
var conns = newSeq[Connection]()
|
||||
for i in 0..<30:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
let peer = gossipSub.getPubSubPeer(peerInfo.peerId)
|
||||
peer.handler = handler
|
||||
if i mod 2 == 0:
|
||||
gossipSub.mesh[topic].incl(peer)
|
||||
else:
|
||||
gossipSub.fanout[topic].incl(peer)
|
||||
|
||||
check gossipSub.fanout[topic].len == GossipSubD
|
||||
# generate messages
|
||||
var seqno = 0'u64
|
||||
for i in 0..5:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
inc seqno
|
||||
let msg = Message.init(some(peerInfo), ("bar" & $i).toBytes(), topic, some(seqno), false)
|
||||
gossipSub.mcache.put(gossipSub.msgIdProvider(msg), msg)
|
||||
|
||||
gossipSub.dropFanoutPeers()
|
||||
check topic notin gossipSub.fanout
|
||||
let peers = gossipSub.getGossipPeers()
|
||||
check peers.len == 0
|
||||
|
||||
await allFuturesThrowing(conns.mapIt(it.close()))
|
||||
await gossipSub.switch.stop()
|
||||
|
||||
result = true
|
||||
|
||||
check:
|
||||
waitFor(testRun()) == true
|
||||
|
||||
test "`dropFanoutPeers` leave unexpired fanout topics":
|
||||
proc testRun(): Future[bool] {.async.} =
|
||||
let gossipSub = TestGossipSub.init(newStandardSwitch())
|
||||
|
||||
proc handler(peer: PubSubPeer, msg: RPCMsg) {.async.} =
|
||||
discard
|
||||
|
||||
let topic1 = "foobar1"
|
||||
let topic2 = "foobar2"
|
||||
gossipSub.fanout[topic1] = initHashSet[PubSubPeer]()
|
||||
gossipSub.fanout[topic2] = initHashSet[PubSubPeer]()
|
||||
gossipSub.lastFanoutPubSub[topic1] = Moment.fromNow(1.millis)
|
||||
gossipSub.lastFanoutPubSub[topic2] = Moment.fromNow(1.minutes)
|
||||
await sleepAsync(5.millis) # allow the topic to expire
|
||||
|
||||
var conns = newSeq[Connection]()
|
||||
for i in 0..<6:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
let peer = gossipSub.getPubSubPeer(peerInfo.peerId)
|
||||
peer.handler = handler
|
||||
gossipSub.fanout[topic1].incl(peer)
|
||||
gossipSub.fanout[topic2].incl(peer)
|
||||
|
||||
check gossipSub.fanout[topic1].len == GossipSubD
|
||||
check gossipSub.fanout[topic2].len == GossipSubD
|
||||
|
||||
gossipSub.dropFanoutPeers()
|
||||
check topic1 notin gossipSub.fanout
|
||||
check topic2 in gossipSub.fanout
|
||||
|
||||
await allFuturesThrowing(conns.mapIt(it.close()))
|
||||
await gossipSub.switch.stop()
|
||||
|
||||
result = true
|
||||
|
||||
check:
|
||||
waitFor(testRun()) == true
|
||||
|
||||
test "`getGossipPeers` - should gather up to degree D non intersecting peers":
|
||||
proc testRun(): Future[bool] {.async.} =
|
||||
let gossipSub = TestGossipSub.init(newStandardSwitch())
|
||||
|
||||
proc handler(peer: PubSubPeer, msg: RPCMsg) {.async.} =
|
||||
discard
|
||||
|
||||
let topic = "foobar"
|
||||
gossipSub.mesh[topic] = initHashSet[PubSubPeer]()
|
||||
gossipSub.fanout[topic] = initHashSet[PubSubPeer]()
|
||||
gossipSub.gossipsub[topic] = initHashSet[PubSubPeer]()
|
||||
var conns = newSeq[Connection]()
|
||||
|
||||
# generate mesh and fanout peers
|
||||
for i in 0..<30:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
let peer = gossipSub.getPubSubPeer(peerInfo.peerId)
|
||||
peer.handler = handler
|
||||
if i mod 2 == 0:
|
||||
gossipSub.fanout[topic].incl(peer)
|
||||
else:
|
||||
gossipSub.mesh[topic].incl(peer)
|
||||
|
||||
# generate gossipsub (free standing) peers
|
||||
for i in 0..<15:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
let peer = gossipSub.getPubSubPeer(peerInfo.peerId)
|
||||
peer.handler = handler
|
||||
gossipSub.gossipsub[topic].incl(peer)
|
||||
|
||||
# generate messages
|
||||
var seqno = 0'u64
|
||||
for i in 0..5:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
inc seqno
|
||||
let msg = Message.init(some(peerInfo), ("HELLO" & $i).toBytes(), topic, some(seqno), false)
|
||||
gossipSub.mcache.put(gossipSub.msgIdProvider(msg), msg)
|
||||
|
||||
check gossipSub.fanout[topic].len == 15
|
||||
check gossipSub.mesh[topic].len == 15
|
||||
check gossipSub.gossipsub[topic].len == 15
|
||||
|
||||
let peers = gossipSub.getGossipPeers()
|
||||
check peers.len == GossipSubD
|
||||
for p in peers.keys:
|
||||
check not gossipSub.fanout.hasPeerID(topic, p.peerId)
|
||||
check not gossipSub.mesh.hasPeerID(topic, p.peerId)
|
||||
|
||||
await allFuturesThrowing(conns.mapIt(it.close()))
|
||||
await gossipSub.switch.stop()
|
||||
|
||||
result = true
|
||||
|
||||
check:
|
||||
waitFor(testRun()) == true
|
||||
|
||||
test "`getGossipPeers` - should not crash on missing topics in mesh":
|
||||
proc testRun(): Future[bool] {.async.} =
|
||||
let gossipSub = TestGossipSub.init(newStandardSwitch())
|
||||
|
||||
proc handler(peer: PubSubPeer, msg: RPCMsg) {.async.} =
|
||||
discard
|
||||
|
||||
let topic = "foobar"
|
||||
gossipSub.fanout[topic] = initHashSet[PubSubPeer]()
|
||||
gossipSub.gossipsub[topic] = initHashSet[PubSubPeer]()
|
||||
var conns = newSeq[Connection]()
|
||||
for i in 0..<30:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
let peer = gossipSub.getPubSubPeer(peerInfo.peerId)
|
||||
peer.handler = handler
|
||||
if i mod 2 == 0:
|
||||
gossipSub.fanout[topic].incl(peer)
|
||||
else:
|
||||
gossipSub.gossipsub[topic].incl(peer)
|
||||
|
||||
# generate messages
|
||||
var seqno = 0'u64
|
||||
for i in 0..5:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
inc seqno
|
||||
let msg = Message.init(some(peerInfo), ("HELLO" & $i).toBytes(), topic, some(seqno), false)
|
||||
gossipSub.mcache.put(gossipSub.msgIdProvider(msg), msg)
|
||||
|
||||
let peers = gossipSub.getGossipPeers()
|
||||
check peers.len == GossipSubD
|
||||
|
||||
await allFuturesThrowing(conns.mapIt(it.close()))
|
||||
await gossipSub.switch.stop()
|
||||
|
||||
result = true
|
||||
|
||||
check:
|
||||
waitFor(testRun()) == true
|
||||
|
||||
test "`getGossipPeers` - should not crash on missing topics in fanout":
|
||||
proc testRun(): Future[bool] {.async.} =
|
||||
let gossipSub = TestGossipSub.init(newStandardSwitch())
|
||||
|
||||
proc handler(peer: PubSubPeer, msg: RPCMsg) {.async.} =
|
||||
discard
|
||||
|
||||
let topic = "foobar"
|
||||
gossipSub.mesh[topic] = initHashSet[PubSubPeer]()
|
||||
gossipSub.gossipsub[topic] = initHashSet[PubSubPeer]()
|
||||
var conns = newSeq[Connection]()
|
||||
for i in 0..<30:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
let peer = gossipSub.getPubSubPeer(peerInfo.peerId)
|
||||
peer.handler = handler
|
||||
if i mod 2 == 0:
|
||||
gossipSub.mesh[topic].incl(peer)
|
||||
else:
|
||||
gossipSub.gossipsub[topic].incl(peer)
|
||||
|
||||
# generate messages
|
||||
var seqno = 0'u64
|
||||
for i in 0..5:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
inc seqno
|
||||
let msg = Message.init(some(peerInfo), ("HELLO" & $i).toBytes(), topic, some(seqno), false)
|
||||
gossipSub.mcache.put(gossipSub.msgIdProvider(msg), msg)
|
||||
|
||||
let peers = gossipSub.getGossipPeers()
|
||||
check peers.len == GossipSubD
|
||||
|
||||
await allFuturesThrowing(conns.mapIt(it.close()))
|
||||
await gossipSub.switch.stop()
|
||||
|
||||
result = true
|
||||
|
||||
check:
|
||||
waitFor(testRun()) == true
|
||||
|
||||
test "`getGossipPeers` - should not crash on missing topics in gossip":
|
||||
proc testRun(): Future[bool] {.async.} =
|
||||
let gossipSub = TestGossipSub.init(newStandardSwitch())
|
||||
|
||||
proc handler(peer: PubSubPeer, msg: RPCMsg) {.async.} =
|
||||
discard
|
||||
|
||||
let topic = "foobar"
|
||||
gossipSub.mesh[topic] = initHashSet[PubSubPeer]()
|
||||
gossipSub.fanout[topic] = initHashSet[PubSubPeer]()
|
||||
var conns = newSeq[Connection]()
|
||||
for i in 0..<30:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
let peer = gossipSub.getPubSubPeer(peerInfo.peerId)
|
||||
peer.handler = handler
|
||||
if i mod 2 == 0:
|
||||
gossipSub.mesh[topic].incl(peer)
|
||||
else:
|
||||
gossipSub.fanout[topic].incl(peer)
|
||||
|
||||
# generate messages
|
||||
var seqno = 0'u64
|
||||
for i in 0..5:
|
||||
let conn = newBufferStream(noop)
|
||||
conns &= conn
|
||||
let peerInfo = randomPeerInfo()
|
||||
conn.peerInfo = peerInfo
|
||||
inc seqno
|
||||
let msg = Message.init(some(peerInfo), ("bar" & $i).toBytes(), topic, some(seqno), false)
|
||||
gossipSub.mcache.put(gossipSub.msgIdProvider(msg), msg)
|
||||
|
||||
let peers = gossipSub.getGossipPeers()
|
||||
check peers.len == 0
|
||||
|
||||
await allFuturesThrowing(conns.mapIt(it.close()))
|
||||
await gossipSub.switch.stop()
|
||||
|
||||
result = true
|
||||
|
||||
check:
|
||||
waitFor(testRun()) == true
|
||||
await allFuturesThrowing(conns.mapIt(it.close()))
|
||||
await gossipSub.switch.stop()
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -3,6 +3,8 @@ import chronos, stew/byteutils
|
|||
import ../libp2p/stream/bufferstream,
|
||||
../libp2p/stream/lpstream
|
||||
|
||||
import ./helpers
|
||||
|
||||
{.used.}
|
||||
|
||||
suite "BufferStream":
|
||||
|
@ -10,224 +12,154 @@ suite "BufferStream":
|
|||
# echo getTracker(BufferStreamTrackerName).dump()
|
||||
check getTracker(BufferStreamTrackerName).isLeaked() == false
|
||||
|
||||
test "push data to buffer":
|
||||
proc testpushData(): Future[bool] {.async.} =
|
||||
let buff = newBufferStream()
|
||||
check buff.len == 0
|
||||
var data = "12345"
|
||||
await buff.pushData(data.toBytes())
|
||||
check buff.len == 5
|
||||
result = true
|
||||
asyncTest "push data to buffer":
|
||||
let buff = newBufferStream()
|
||||
check buff.len == 0
|
||||
var data = "12345"
|
||||
await buff.pushData(data.toBytes())
|
||||
check buff.len == 5
|
||||
await buff.close()
|
||||
|
||||
await buff.close()
|
||||
asyncTest "push and wait":
|
||||
let buff = newBufferStream()
|
||||
check buff.len == 0
|
||||
|
||||
check:
|
||||
waitFor(testpushData()) == true
|
||||
let fut0 = buff.pushData("1234".toBytes())
|
||||
let fut1 = buff.pushData("5".toBytes())
|
||||
check buff.len == 4 # the second write should not be visible yet
|
||||
|
||||
test "push and wait":
|
||||
proc testpushData(): Future[bool] {.async.} =
|
||||
let buff = newBufferStream()
|
||||
check buff.len == 0
|
||||
var data: array[1, byte]
|
||||
check: 1 == await buff.readOnce(addr data[0], data.len)
|
||||
|
||||
let fut0 = buff.pushData("1234".toBytes())
|
||||
let fut1 = buff.pushData("5".toBytes())
|
||||
check buff.len == 4 # the second write should not be visible yet
|
||||
check ['1'] == string.fromBytes(data)
|
||||
await fut0
|
||||
await fut1
|
||||
check buff.len == 4
|
||||
await buff.close()
|
||||
|
||||
var data: array[1, byte]
|
||||
check: 1 == await buff.readOnce(addr data[0], data.len)
|
||||
asyncTest "read with size":
|
||||
let buff = newBufferStream()
|
||||
check buff.len == 0
|
||||
|
||||
check ['1'] == string.fromBytes(data)
|
||||
await fut0
|
||||
await fut1
|
||||
check buff.len == 4
|
||||
await buff.pushData("12345".toBytes())
|
||||
var data: array[3, byte]
|
||||
await buff.readExactly(addr data[0], data.len)
|
||||
check ['1', '2', '3'] == string.fromBytes(data)
|
||||
await buff.close()
|
||||
|
||||
result = true
|
||||
asyncTest "readExactly":
|
||||
let buff = newBufferStream()
|
||||
check buff.len == 0
|
||||
|
||||
await buff.close()
|
||||
await buff.pushData("12345".toBytes())
|
||||
check buff.len == 5
|
||||
var data: array[2, byte]
|
||||
await buff.readExactly(addr data[0], data.len)
|
||||
check string.fromBytes(data) == ['1', '2']
|
||||
await buff.close()
|
||||
|
||||
check:
|
||||
waitFor(testpushData()) == true
|
||||
asyncTest "readExactly raises":
|
||||
let buff = newBufferStream()
|
||||
check buff.len == 0
|
||||
|
||||
test "read with size":
|
||||
proc testRead(): Future[bool] {.async.} =
|
||||
let buff = newBufferStream()
|
||||
check buff.len == 0
|
||||
await buff.pushData("123".toBytes())
|
||||
var data: array[5, byte]
|
||||
var readFut = buff.readExactly(addr data[0], data.len)
|
||||
await buff.close()
|
||||
|
||||
await buff.pushData("12345".toBytes())
|
||||
var data: array[3, byte]
|
||||
await buff.readExactly(addr data[0], data.len)
|
||||
check ['1', '2', '3'] == string.fromBytes(data)
|
||||
expect LPStreamIncompleteError:
|
||||
await readFut
|
||||
|
||||
result = true
|
||||
asyncTest "readOnce":
|
||||
let buff = newBufferStream()
|
||||
check buff.len == 0
|
||||
|
||||
await buff.close()
|
||||
var data: array[3, byte]
|
||||
let readFut = buff.readOnce(addr data[0], data.len)
|
||||
await buff.pushData("123".toBytes())
|
||||
check buff.len == 3
|
||||
|
||||
check:
|
||||
waitFor(testRead()) == true
|
||||
check (await readFut) == 3
|
||||
check string.fromBytes(data) == ['1', '2', '3']
|
||||
await buff.close()
|
||||
|
||||
test "readExactly":
|
||||
proc testReadExactly(): Future[bool] {.async.} =
|
||||
let buff = newBufferStream()
|
||||
check buff.len == 0
|
||||
asyncTest "reads should happen in order":
|
||||
let buff = newBufferStream()
|
||||
check buff.len == 0
|
||||
|
||||
await buff.pushData("12345".toBytes())
|
||||
check buff.len == 5
|
||||
var data: array[2, byte]
|
||||
await buff.readExactly(addr data[0], data.len)
|
||||
check string.fromBytes(data) == ['1', '2']
|
||||
let w1 = buff.pushData("Msg 1".toBytes())
|
||||
let w2 = buff.pushData("Msg 2".toBytes())
|
||||
let w3 = buff.pushData("Msg 3".toBytes())
|
||||
|
||||
result = true
|
||||
var data: array[5, byte]
|
||||
await buff.readExactly(addr data[0], data.len)
|
||||
|
||||
await buff.close()
|
||||
check string.fromBytes(data) == "Msg 1"
|
||||
|
||||
check:
|
||||
waitFor(testReadExactly()) == true
|
||||
await buff.readExactly(addr data[0], data.len)
|
||||
check string.fromBytes(data) == "Msg 2"
|
||||
|
||||
test "readExactly raises":
|
||||
proc testReadExactly(): Future[bool] {.async.} =
|
||||
let buff = newBufferStream()
|
||||
check buff.len == 0
|
||||
await buff.readExactly(addr data[0], data.len)
|
||||
check string.fromBytes(data) == "Msg 3"
|
||||
|
||||
await buff.pushData("123".toBytes())
|
||||
var data: array[5, byte]
|
||||
var readFut = buff.readExactly(addr data[0], data.len)
|
||||
await buff.close()
|
||||
for f in [w1, w2, w3]: await f
|
||||
|
||||
try:
|
||||
await readFut
|
||||
except LPStreamIncompleteError:
|
||||
result = true
|
||||
let w4 = buff.pushData("Msg 4".toBytes())
|
||||
let w5 = buff.pushData("Msg 5".toBytes())
|
||||
let w6 = buff.pushData("Msg 6".toBytes())
|
||||
|
||||
check:
|
||||
waitFor(testReadExactly()) == true
|
||||
await buff.close()
|
||||
|
||||
test "readOnce":
|
||||
proc testReadOnce(): Future[bool] {.async.} =
|
||||
let buff = newBufferStream()
|
||||
check buff.len == 0
|
||||
await buff.readExactly(addr data[0], data.len)
|
||||
check string.fromBytes(data) == "Msg 4"
|
||||
|
||||
var data: array[3, byte]
|
||||
let readFut = buff.readOnce(addr data[0], data.len)
|
||||
await buff.pushData("123".toBytes())
|
||||
check buff.len == 3
|
||||
await buff.readExactly(addr data[0], data.len)
|
||||
check string.fromBytes(data) == "Msg 5"
|
||||
|
||||
check (await readFut) == 3
|
||||
check string.fromBytes(data) == ['1', '2', '3']
|
||||
await buff.readExactly(addr data[0], data.len)
|
||||
check string.fromBytes(data) == "Msg 6"
|
||||
for f in [w4, w5, w6]: await f
|
||||
|
||||
result = true
|
||||
asyncTest "small reads":
|
||||
let buff = newBufferStream()
|
||||
check buff.len == 0
|
||||
|
||||
await buff.close()
|
||||
var writes: seq[Future[void]]
|
||||
var str: string
|
||||
for i in 0..<10:
|
||||
writes.add buff.pushData("123".toBytes())
|
||||
str &= "123"
|
||||
await buff.close() # all data should still be read after close
|
||||
|
||||
check:
|
||||
waitFor(testReadOnce()) == true
|
||||
var str2: string
|
||||
var data: array[2, byte]
|
||||
expect LPStreamEOFError:
|
||||
while true:
|
||||
let x = await buff.readOnce(addr data[0], data.len)
|
||||
str2 &= string.fromBytes(data[0..<x])
|
||||
|
||||
test "reads should happen in order":
|
||||
proc testWritePtr(): Future[bool] {.async.} =
|
||||
let buff = newBufferStream()
|
||||
check buff.len == 0
|
||||
for f in writes: await f
|
||||
check str == str2
|
||||
await buff.close()
|
||||
|
||||
let w1 = buff.pushData("Msg 1".toBytes())
|
||||
let w2 = buff.pushData("Msg 2".toBytes())
|
||||
let w3 = buff.pushData("Msg 3".toBytes())
|
||||
asyncTest "shouldn't get stuck on close":
|
||||
var stream = newBufferStream()
|
||||
var
|
||||
fut = stream.pushData(toBytes("hello"))
|
||||
fut2 = stream.pushData(toBytes("again"))
|
||||
await stream.close()
|
||||
expect AsyncTimeoutError:
|
||||
await wait(fut, 100.milliseconds)
|
||||
await wait(fut2, 100.milliseconds)
|
||||
|
||||
var data: array[5, byte]
|
||||
await buff.readExactly(addr data[0], data.len)
|
||||
await stream.close()
|
||||
|
||||
check string.fromBytes(data) == "Msg 1"
|
||||
asyncTest "no push after close":
|
||||
var stream = newBufferStream()
|
||||
await stream.pushData("123".toBytes())
|
||||
var data: array[3, byte]
|
||||
await stream.readExactly(addr data[0], data.len)
|
||||
await stream.close()
|
||||
|
||||
await buff.readExactly(addr data[0], data.len)
|
||||
check string.fromBytes(data) == "Msg 2"
|
||||
|
||||
await buff.readExactly(addr data[0], data.len)
|
||||
check string.fromBytes(data) == "Msg 3"
|
||||
|
||||
for f in [w1, w2, w3]: await f
|
||||
|
||||
let w4 = buff.pushData("Msg 4".toBytes())
|
||||
let w5 = buff.pushData("Msg 5".toBytes())
|
||||
let w6 = buff.pushData("Msg 6".toBytes())
|
||||
|
||||
await buff.close()
|
||||
|
||||
await buff.readExactly(addr data[0], data.len)
|
||||
check string.fromBytes(data) == "Msg 4"
|
||||
|
||||
await buff.readExactly(addr data[0], data.len)
|
||||
check string.fromBytes(data) == "Msg 5"
|
||||
|
||||
await buff.readExactly(addr data[0], data.len)
|
||||
check string.fromBytes(data) == "Msg 6"
|
||||
|
||||
for f in [w4, w5, w6]: await f
|
||||
|
||||
result = true
|
||||
|
||||
check:
|
||||
waitFor(testWritePtr()) == true
|
||||
|
||||
test "small reads":
|
||||
proc testWritePtr(): Future[bool] {.async.} =
|
||||
let buff = newBufferStream()
|
||||
check buff.len == 0
|
||||
|
||||
var writes: seq[Future[void]]
|
||||
var str: string
|
||||
for i in 0..<10:
|
||||
writes.add buff.pushData("123".toBytes())
|
||||
str &= "123"
|
||||
await buff.close() # all data should still be read after close
|
||||
|
||||
var str2: string
|
||||
var data: array[2, byte]
|
||||
try:
|
||||
while true:
|
||||
let x = await buff.readOnce(addr data[0], data.len)
|
||||
str2 &= string.fromBytes(data[0..<x])
|
||||
except LPStreamEOFError:
|
||||
discard
|
||||
|
||||
for f in writes: await f
|
||||
|
||||
check str == str2
|
||||
|
||||
result = true
|
||||
|
||||
await buff.close()
|
||||
|
||||
check:
|
||||
waitFor(testWritePtr()) == true
|
||||
|
||||
test "shouldn't get stuck on close":
|
||||
proc closeTest(): Future[bool] {.async.} =
|
||||
var stream = newBufferStream()
|
||||
var
|
||||
fut = stream.pushData(toBytes("hello"))
|
||||
fut2 = stream.pushData(toBytes("again"))
|
||||
await stream.close()
|
||||
try:
|
||||
await wait(fut, 100.milliseconds)
|
||||
await wait(fut2, 100.milliseconds)
|
||||
result = true
|
||||
except AsyncTimeoutError:
|
||||
result = false
|
||||
|
||||
await stream.close()
|
||||
|
||||
check:
|
||||
waitFor(closeTest()) == true
|
||||
|
||||
test "no push after close":
|
||||
proc closeTest(): Future[bool] {.async.} =
|
||||
var stream = newBufferStream()
|
||||
expect LPStreamEOFError:
|
||||
await stream.pushData("123".toBytes())
|
||||
var data: array[3, byte]
|
||||
await stream.readExactly(addr data[0], data.len)
|
||||
await stream.close()
|
||||
|
||||
try:
|
||||
await stream.pushData("123".toBytes())
|
||||
except LPStreamClosedError:
|
||||
result = true
|
||||
|
||||
check:
|
||||
waitFor(closeTest()) == true
|
||||
|
|
|
@ -3,47 +3,29 @@ import chronos, nimcrypto/utils
|
|||
import ../libp2p/[stream/connection,
|
||||
stream/bufferstream]
|
||||
|
||||
import ./helpers
|
||||
|
||||
suite "Connection":
|
||||
test "close":
|
||||
proc test(): Future[bool] {.async.} =
|
||||
var conn = newBufferStream()
|
||||
await conn.close()
|
||||
check:
|
||||
conn.closed == true
|
||||
|
||||
result = true
|
||||
|
||||
asyncTest "close":
|
||||
var conn = newBufferStream()
|
||||
await conn.close()
|
||||
check:
|
||||
waitFor(test()) == true
|
||||
conn.closed == true
|
||||
|
||||
test "parent close":
|
||||
proc test(): Future[bool] {.async.} =
|
||||
var buf = newBufferStream()
|
||||
var conn = buf
|
||||
|
||||
await conn.close()
|
||||
check:
|
||||
conn.closed == true
|
||||
buf.closed == true
|
||||
|
||||
await sleepAsync(1.seconds)
|
||||
result = true
|
||||
asyncTest "parent close":
|
||||
var buf = newBufferStream()
|
||||
var conn = buf
|
||||
|
||||
await conn.close()
|
||||
check:
|
||||
waitFor(test()) == true
|
||||
conn.closed == true
|
||||
buf.closed == true
|
||||
|
||||
test "child close":
|
||||
proc test(): Future[bool] {.async.} =
|
||||
var buf = newBufferStream()
|
||||
var conn = buf
|
||||
|
||||
await buf.close()
|
||||
check:
|
||||
conn.closed == true
|
||||
buf.closed == true
|
||||
|
||||
await sleepAsync(1.seconds)
|
||||
result = true
|
||||
asyncTest "child close":
|
||||
var buf = newBufferStream()
|
||||
var conn = buf
|
||||
|
||||
await buf.close()
|
||||
check:
|
||||
waitFor(test()) == true
|
||||
conn.closed == true
|
||||
buf.closed == true
|
||||
|
|
|
@ -17,75 +17,68 @@ suite "Identify":
|
|||
teardown:
|
||||
checkTrackers()
|
||||
|
||||
test "handle identify message":
|
||||
proc testHandle(): Future[bool] {.async.} =
|
||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
let remoteSecKey = PrivateKey.random(ECDSA, rng[]).get()
|
||||
let remotePeerInfo = PeerInfo.init(remoteSecKey,
|
||||
[ma],
|
||||
["/test/proto1/1.0.0",
|
||||
"/test/proto2/1.0.0"])
|
||||
var serverFut: Future[void]
|
||||
let identifyProto1 = newIdentify(remotePeerInfo)
|
||||
let msListen = newMultistream()
|
||||
asyncTest "handle identify message":
|
||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
let remoteSecKey = PrivateKey.random(ECDSA, rng[]).get()
|
||||
let remotePeerInfo = PeerInfo.init(remoteSecKey,
|
||||
[ma],
|
||||
["/test/proto1/1.0.0",
|
||||
"/test/proto2/1.0.0"])
|
||||
var serverFut: Future[void]
|
||||
let identifyProto1 = newIdentify(remotePeerInfo)
|
||||
let msListen = newMultistream()
|
||||
|
||||
msListen.addHandler(IdentifyCodec, identifyProto1)
|
||||
proc connHandler(conn: Connection): Future[void] {.async, gcsafe.} =
|
||||
await msListen.handle(conn)
|
||||
msListen.addHandler(IdentifyCodec, identifyProto1)
|
||||
proc connHandler(conn: Connection): Future[void] {.async, gcsafe.} =
|
||||
await msListen.handle(conn)
|
||||
|
||||
var transport1 = TcpTransport.init()
|
||||
serverFut = await transport1.listen(ma, connHandler)
|
||||
var transport1 = TcpTransport.init()
|
||||
serverFut = await transport1.listen(ma, connHandler)
|
||||
|
||||
let msDial = newMultistream()
|
||||
let transport2: TcpTransport = TcpTransport.init()
|
||||
let conn = await transport2.dial(transport1.ma)
|
||||
let msDial = newMultistream()
|
||||
let transport2: TcpTransport = TcpTransport.init()
|
||||
let conn = await transport2.dial(transport1.ma)
|
||||
|
||||
var peerInfo = PeerInfo.init(PrivateKey.random(ECDSA, rng[]).get(), [ma])
|
||||
let identifyProto2 = newIdentify(peerInfo)
|
||||
discard await msDial.select(conn, IdentifyCodec)
|
||||
let id = await identifyProto2.identify(conn, remotePeerInfo)
|
||||
var peerInfo = PeerInfo.init(PrivateKey.random(ECDSA, rng[]).get(), [ma])
|
||||
let identifyProto2 = newIdentify(peerInfo)
|
||||
discard await msDial.select(conn, IdentifyCodec)
|
||||
let id = await identifyProto2.identify(conn, remotePeerInfo)
|
||||
|
||||
check id.pubKey.get() == remoteSecKey.getKey().get()
|
||||
check id.addrs[0] == ma
|
||||
check id.protoVersion.get() == ProtoVersion
|
||||
# check id.agentVersion.get() == AgentVersion
|
||||
check id.protos == @["/test/proto1/1.0.0", "/test/proto2/1.0.0"]
|
||||
check id.pubKey.get() == remoteSecKey.getKey().get()
|
||||
check id.addrs[0] == ma
|
||||
check id.protoVersion.get() == ProtoVersion
|
||||
# check id.agentVersion.get() == AgentVersion
|
||||
check id.protos == @["/test/proto1/1.0.0", "/test/proto2/1.0.0"]
|
||||
|
||||
await conn.close()
|
||||
await transport1.close()
|
||||
await serverFut
|
||||
await transport2.close()
|
||||
|
||||
asyncTest "handle failed identify":
|
||||
let ma = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
var remotePeerInfo = PeerInfo.init(PrivateKey.random(ECDSA, rng[]).get(), [ma])
|
||||
let identifyProto1 = newIdentify(remotePeerInfo)
|
||||
let msListen = newMultistream()
|
||||
|
||||
let done = newFuture[void]()
|
||||
|
||||
msListen.addHandler(IdentifyCodec, identifyProto1)
|
||||
proc connHandler(conn: Connection): Future[void] {.async, gcsafe.} =
|
||||
await msListen.handle(conn)
|
||||
await conn.close()
|
||||
await transport1.close()
|
||||
await serverFut
|
||||
done.complete()
|
||||
|
||||
result = true
|
||||
let transport1: TcpTransport = TcpTransport.init()
|
||||
asyncCheck transport1.listen(ma, connHandler)
|
||||
|
||||
await transport2.close()
|
||||
|
||||
check:
|
||||
waitFor(testHandle()) == true
|
||||
|
||||
test "handle failed identify":
|
||||
proc testHandleError() {.async.} =
|
||||
let ma = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
var remotePeerInfo = PeerInfo.init(PrivateKey.random(ECDSA, rng[]).get(), [ma])
|
||||
let identifyProto1 = newIdentify(remotePeerInfo)
|
||||
let msListen = newMultistream()
|
||||
|
||||
let done = newFuture[void]()
|
||||
|
||||
msListen.addHandler(IdentifyCodec, identifyProto1)
|
||||
proc connHandler(conn: Connection): Future[void] {.async, gcsafe.} =
|
||||
await msListen.handle(conn)
|
||||
await conn.close()
|
||||
done.complete()
|
||||
|
||||
let transport1: TcpTransport = TcpTransport.init()
|
||||
asyncCheck transport1.listen(ma, connHandler)
|
||||
|
||||
let msDial = newMultistream()
|
||||
let transport2: TcpTransport = TcpTransport.init()
|
||||
let conn = await transport2.dial(transport1.ma)
|
||||
var localPeerInfo = PeerInfo.init(PrivateKey.random(ECDSA, rng[]).get(), [ma])
|
||||
let identifyProto2 = newIdentify(localPeerInfo)
|
||||
let msDial = newMultistream()
|
||||
let transport2: TcpTransport = TcpTransport.init()
|
||||
let conn = await transport2.dial(transport1.ma)
|
||||
var localPeerInfo = PeerInfo.init(PrivateKey.random(ECDSA, rng[]).get(), [ma])
|
||||
let identifyProto2 = newIdentify(localPeerInfo)
|
||||
|
||||
expect IdentityNoMatchError:
|
||||
try:
|
||||
let pi2 = PeerInfo.init(PrivateKey.random(ECDSA, rng[]).get())
|
||||
discard await msDial.select(conn, IdentifyCodec)
|
||||
|
@ -95,6 +88,3 @@ suite "Identify":
|
|||
await conn.close()
|
||||
await transport2.close()
|
||||
await transport1.close()
|
||||
|
||||
expect IdentityNoMatchError:
|
||||
waitFor(testHandleError())
|
||||
|
|
|
@ -58,8 +58,7 @@ proc readLp*(s: StreamTransport): Future[seq[byte]] {.async, gcsafe.} =
|
|||
if size > 0.uint:
|
||||
await s.readExactly(addr result[0], int(size))
|
||||
|
||||
proc testPubSubDaemonPublish(gossip: bool = false,
|
||||
count: int = 1): Future[bool] {.async.} =
|
||||
proc testPubSubDaemonPublish(gossip: bool = false, count: int = 1) {.async.} =
|
||||
var pubsubData = "TEST MESSAGE"
|
||||
var testTopic = "test-topic"
|
||||
var msgData = pubsubData.toBytes()
|
||||
|
@ -120,14 +119,12 @@ proc testPubSubDaemonPublish(gossip: bool = false,
|
|||
|
||||
await wait(publisher(), 5.minutes) # should be plenty of time
|
||||
|
||||
result = true
|
||||
await nativeNode.stop()
|
||||
await pubsub.stop()
|
||||
await allFutures(awaiters)
|
||||
await daemonNode.close()
|
||||
|
||||
proc testPubSubNodePublish(gossip: bool = false,
|
||||
count: int = 1): Future[bool] {.async.} =
|
||||
proc testPubSubNodePublish(gossip: bool = false, count: int = 1) {.async.} =
|
||||
var pubsubData = "TEST MESSAGE"
|
||||
var testTopic = "test-topic"
|
||||
var msgData = pubsubData.toBytes()
|
||||
|
@ -187,7 +184,7 @@ proc testPubSubNodePublish(gossip: bool = false,
|
|||
|
||||
await wait(publisher(), 5.minutes) # should be plenty of time
|
||||
|
||||
result = finished
|
||||
check finished
|
||||
await nativeNode.stop()
|
||||
await pubsub.stop()
|
||||
await allFutures(awaiters)
|
||||
|
@ -199,268 +196,236 @@ suite "Interop":
|
|||
# and libp2p, so not sure which one it is,
|
||||
# need to investigate more
|
||||
# teardown:
|
||||
# for tracker in testTrackers():
|
||||
# # echo tracker.dump()
|
||||
# # check tracker.isLeaked() == false
|
||||
# checkTrackers()
|
||||
|
||||
# TODO: this test is failing sometimes on windows
|
||||
# For some reason we receive EOF before test 4 sometimes
|
||||
test "native -> daemon multiple reads and writes":
|
||||
proc runTests(): Future[bool] {.async.} =
|
||||
var protos = @["/test-stream"]
|
||||
asyncTest "native -> daemon multiple reads and writes":
|
||||
var protos = @["/test-stream"]
|
||||
|
||||
let nativeNode = newStandardSwitch(
|
||||
secureManagers = [SecureProtocol.Noise],
|
||||
outTimeout = 5.minutes)
|
||||
let nativeNode = newStandardSwitch(
|
||||
secureManagers = [SecureProtocol.Noise],
|
||||
outTimeout = 5.minutes)
|
||||
|
||||
let awaiters = await nativeNode.start()
|
||||
let daemonNode = await newDaemonApi()
|
||||
let daemonPeer = await daemonNode.identity()
|
||||
let awaiters = await nativeNode.start()
|
||||
let daemonNode = await newDaemonApi()
|
||||
let daemonPeer = await daemonNode.identity()
|
||||
|
||||
var testFuture = newFuture[void]("test.future")
|
||||
proc daemonHandler(api: DaemonAPI, stream: P2PStream) {.async.} =
|
||||
check string.fromBytes(await stream.transp.readLp()) == "test 1"
|
||||
discard await stream.transp.writeLp("test 2")
|
||||
check string.fromBytes(await stream.transp.readLp()) == "test 3"
|
||||
discard await stream.transp.writeLp("test 4")
|
||||
testFuture.complete()
|
||||
var testFuture = newFuture[void]("test.future")
|
||||
proc daemonHandler(api: DaemonAPI, stream: P2PStream) {.async.} =
|
||||
check string.fromBytes(await stream.transp.readLp()) == "test 1"
|
||||
discard await stream.transp.writeLp("test 2")
|
||||
check string.fromBytes(await stream.transp.readLp()) == "test 3"
|
||||
discard await stream.transp.writeLp("test 4")
|
||||
testFuture.complete()
|
||||
|
||||
await daemonNode.addHandler(protos, daemonHandler)
|
||||
let conn = await nativeNode.dial(NativePeerInfo.init(daemonPeer.peer,
|
||||
daemonPeer.addresses),
|
||||
protos[0])
|
||||
await conn.writeLp("test 1")
|
||||
check "test 2" == string.fromBytes((await conn.readLp(1024)))
|
||||
|
||||
await conn.writeLp("test 3")
|
||||
check "test 4" == string.fromBytes((await conn.readLp(1024)))
|
||||
await daemonNode.addHandler(protos, daemonHandler)
|
||||
let conn = await nativeNode.dial(NativePeerInfo.init(daemonPeer.peer,
|
||||
daemonPeer.addresses),
|
||||
protos[0])
|
||||
await conn.writeLp("test 1")
|
||||
check "test 2" == string.fromBytes((await conn.readLp(1024)))
|
||||
|
||||
await wait(testFuture, 10.secs)
|
||||
await conn.writeLp("test 3")
|
||||
check "test 4" == string.fromBytes((await conn.readLp(1024)))
|
||||
|
||||
await nativeNode.stop()
|
||||
await daemonNode.close()
|
||||
await allFutures(awaiters)
|
||||
await wait(testFuture, 10.secs)
|
||||
|
||||
await sleepAsync(1.seconds)
|
||||
result = true
|
||||
await nativeNode.stop()
|
||||
await daemonNode.close()
|
||||
await allFutures(awaiters)
|
||||
|
||||
check:
|
||||
waitFor(runTests()) == true
|
||||
await sleepAsync(1.seconds)
|
||||
|
||||
test "native -> daemon connection":
|
||||
proc runTests(): Future[bool] {.async.} =
|
||||
var protos = @["/test-stream"]
|
||||
var test = "TEST STRING"
|
||||
# We are preparing expect string, which should be prefixed with varint
|
||||
# length and do not have `\r\n` suffix, because we going to use
|
||||
# readLine().
|
||||
var buffer = initVBuffer()
|
||||
buffer.writeSeq(test & "\r\n")
|
||||
buffer.finish()
|
||||
var expect = newString(len(buffer) - 2)
|
||||
copyMem(addr expect[0], addr buffer.buffer[0], len(expect))
|
||||
asyncTest "native -> daemon connection":
|
||||
var protos = @["/test-stream"]
|
||||
var test = "TEST STRING"
|
||||
# We are preparing expect string, which should be prefixed with varint
|
||||
# length and do not have `\r\n` suffix, because we going to use
|
||||
# readLine().
|
||||
var buffer = initVBuffer()
|
||||
buffer.writeSeq(test & "\r\n")
|
||||
buffer.finish()
|
||||
var expect = newString(len(buffer) - 2)
|
||||
copyMem(addr expect[0], addr buffer.buffer[0], len(expect))
|
||||
|
||||
let nativeNode = newStandardSwitch(
|
||||
secureManagers = [SecureProtocol.Noise],
|
||||
outTimeout = 5.minutes)
|
||||
let nativeNode = newStandardSwitch(
|
||||
secureManagers = [SecureProtocol.Noise],
|
||||
outTimeout = 5.minutes)
|
||||
|
||||
let awaiters = await nativeNode.start()
|
||||
let awaiters = await nativeNode.start()
|
||||
|
||||
let daemonNode = await newDaemonApi()
|
||||
let daemonPeer = await daemonNode.identity()
|
||||
let daemonNode = await newDaemonApi()
|
||||
let daemonPeer = await daemonNode.identity()
|
||||
|
||||
var testFuture = newFuture[string]("test.future")
|
||||
proc daemonHandler(api: DaemonAPI, stream: P2PStream) {.async.} =
|
||||
# We should perform `readLp()` instead of `readLine()`. `readLine()`
|
||||
# here reads actually length prefixed string.
|
||||
var line = await stream.transp.readLine()
|
||||
check line == expect
|
||||
testFuture.complete(line)
|
||||
await stream.close()
|
||||
var testFuture = newFuture[string]("test.future")
|
||||
proc daemonHandler(api: DaemonAPI, stream: P2PStream) {.async.} =
|
||||
# We should perform `readLp()` instead of `readLine()`. `readLine()`
|
||||
# here reads actually length prefixed string.
|
||||
var line = await stream.transp.readLine()
|
||||
check line == expect
|
||||
testFuture.complete(line)
|
||||
await stream.close()
|
||||
|
||||
await daemonNode.addHandler(protos, daemonHandler)
|
||||
let conn = await nativeNode.dial(NativePeerInfo.init(daemonPeer.peer,
|
||||
daemonPeer.addresses),
|
||||
protos[0])
|
||||
await conn.writeLp(test & "\r\n")
|
||||
result = expect == (await wait(testFuture, 10.secs))
|
||||
await daemonNode.addHandler(protos, daemonHandler)
|
||||
let conn = await nativeNode.dial(NativePeerInfo.init(daemonPeer.peer,
|
||||
daemonPeer.addresses),
|
||||
protos[0])
|
||||
await conn.writeLp(test & "\r\n")
|
||||
check expect == (await wait(testFuture, 10.secs))
|
||||
|
||||
await conn.close()
|
||||
await nativeNode.stop()
|
||||
await allFutures(awaiters)
|
||||
await daemonNode.close()
|
||||
|
||||
asyncTest "daemon -> native connection":
|
||||
var protos = @["/test-stream"]
|
||||
var test = "TEST STRING"
|
||||
|
||||
var testFuture = newFuture[string]("test.future")
|
||||
proc nativeHandler(conn: Connection, proto: string) {.async.} =
|
||||
var line = string.fromBytes(await conn.readLp(1024))
|
||||
check line == test
|
||||
testFuture.complete(line)
|
||||
await conn.close()
|
||||
await nativeNode.stop()
|
||||
await allFutures(awaiters)
|
||||
await daemonNode.close()
|
||||
|
||||
check:
|
||||
waitFor(runTests()) == true
|
||||
# custom proto
|
||||
var proto = new LPProtocol
|
||||
proto.handler = nativeHandler
|
||||
proto.codec = protos[0] # codec
|
||||
|
||||
test "daemon -> native connection":
|
||||
proc runTests(): Future[bool] {.async.} =
|
||||
var protos = @["/test-stream"]
|
||||
var test = "TEST STRING"
|
||||
let nativeNode = newStandardSwitch(
|
||||
secureManagers = [SecureProtocol.Noise], outTimeout = 5.minutes)
|
||||
|
||||
var testFuture = newFuture[string]("test.future")
|
||||
proc nativeHandler(conn: Connection, proto: string) {.async.} =
|
||||
nativeNode.mount(proto)
|
||||
|
||||
let awaiters = await nativeNode.start()
|
||||
let nativePeer = nativeNode.peerInfo
|
||||
|
||||
let daemonNode = await newDaemonApi()
|
||||
await daemonNode.connect(nativePeer.peerId, nativePeer.addrs)
|
||||
var stream = await daemonNode.openStream(nativePeer.peerId, protos)
|
||||
discard await stream.transp.writeLp(test)
|
||||
|
||||
check test == (await wait(testFuture, 10.secs))
|
||||
|
||||
await stream.close()
|
||||
await nativeNode.stop()
|
||||
await allFutures(awaiters)
|
||||
await daemonNode.close()
|
||||
await sleepAsync(1.seconds)
|
||||
|
||||
asyncTest "daemon -> multiple reads and writes":
|
||||
var protos = @["/test-stream"]
|
||||
|
||||
var testFuture = newFuture[void]("test.future")
|
||||
proc nativeHandler(conn: Connection, proto: string) {.async.} =
|
||||
check "test 1" == string.fromBytes(await conn.readLp(1024))
|
||||
await conn.writeLp("test 2".toBytes())
|
||||
|
||||
check "test 3" == string.fromBytes(await conn.readLp(1024))
|
||||
await conn.writeLp("test 4".toBytes())
|
||||
|
||||
testFuture.complete()
|
||||
await conn.close()
|
||||
|
||||
# custom proto
|
||||
var proto = new LPProtocol
|
||||
proto.handler = nativeHandler
|
||||
proto.codec = protos[0] # codec
|
||||
|
||||
let nativeNode = newStandardSwitch(
|
||||
secureManagers = [SecureProtocol.Noise], outTimeout = 5.minutes)
|
||||
|
||||
nativeNode.mount(proto)
|
||||
|
||||
let awaiters = await nativeNode.start()
|
||||
let nativePeer = nativeNode.peerInfo
|
||||
|
||||
let daemonNode = await newDaemonApi()
|
||||
await daemonNode.connect(nativePeer.peerId, nativePeer.addrs)
|
||||
var stream = await daemonNode.openStream(nativePeer.peerId, protos)
|
||||
|
||||
asyncDiscard stream.transp.writeLp("test 1")
|
||||
check "test 2" == string.fromBytes(await stream.transp.readLp())
|
||||
|
||||
asyncDiscard stream.transp.writeLp("test 3")
|
||||
check "test 4" == string.fromBytes(await stream.transp.readLp())
|
||||
|
||||
await wait(testFuture, 10.secs)
|
||||
|
||||
await stream.close()
|
||||
await nativeNode.stop()
|
||||
await allFutures(awaiters)
|
||||
await daemonNode.close()
|
||||
|
||||
asyncTest "read write multiple":
|
||||
var protos = @["/test-stream"]
|
||||
var test = "TEST STRING"
|
||||
|
||||
var count = 0
|
||||
var testFuture = newFuture[int]("test.future")
|
||||
proc nativeHandler(conn: Connection, proto: string) {.async.} =
|
||||
while count < 10:
|
||||
var line = string.fromBytes(await conn.readLp(1024))
|
||||
check line == test
|
||||
testFuture.complete(line)
|
||||
await conn.close()
|
||||
await conn.writeLp(test.toBytes())
|
||||
count.inc()
|
||||
|
||||
# custom proto
|
||||
var proto = new LPProtocol
|
||||
proto.handler = nativeHandler
|
||||
proto.codec = protos[0] # codec
|
||||
testFuture.complete(count)
|
||||
await conn.close()
|
||||
|
||||
let nativeNode = newStandardSwitch(
|
||||
secureManagers = [SecureProtocol.Noise], outTimeout = 5.minutes)
|
||||
# custom proto
|
||||
var proto = new LPProtocol
|
||||
proto.handler = nativeHandler
|
||||
proto.codec = protos[0] # codec
|
||||
|
||||
nativeNode.mount(proto)
|
||||
let nativeNode = newStandardSwitch(
|
||||
secureManagers = [SecureProtocol.Noise], outTimeout = 5.minutes)
|
||||
|
||||
let awaiters = await nativeNode.start()
|
||||
let nativePeer = nativeNode.peerInfo
|
||||
nativeNode.mount(proto)
|
||||
|
||||
let daemonNode = await newDaemonApi()
|
||||
await daemonNode.connect(nativePeer.peerId, nativePeer.addrs)
|
||||
var stream = await daemonNode.openStream(nativePeer.peerId, protos)
|
||||
let awaiters = await nativeNode.start()
|
||||
let nativePeer = nativeNode.peerInfo
|
||||
|
||||
let daemonNode = await newDaemonApi()
|
||||
await daemonNode.connect(nativePeer.peerId, nativePeer.addrs)
|
||||
var stream = await daemonNode.openStream(nativePeer.peerId, protos)
|
||||
|
||||
var count2 = 0
|
||||
while count2 < 10:
|
||||
discard await stream.transp.writeLp(test)
|
||||
let line = await stream.transp.readLp()
|
||||
check test == string.fromBytes(line)
|
||||
inc(count2)
|
||||
|
||||
result = test == (await wait(testFuture, 10.secs))
|
||||
check 10 == (await wait(testFuture, 1.minutes))
|
||||
await stream.close()
|
||||
await nativeNode.stop()
|
||||
await allFutures(awaiters)
|
||||
await daemonNode.close()
|
||||
|
||||
await stream.close()
|
||||
await nativeNode.stop()
|
||||
await allFutures(awaiters)
|
||||
await daemonNode.close()
|
||||
await sleepAsync(1.seconds)
|
||||
asyncTest "floodsub: daemon publish one":
|
||||
await testPubSubDaemonPublish()
|
||||
|
||||
check:
|
||||
waitFor(runTests()) == true
|
||||
asyncTest "floodsub: daemon publish many":
|
||||
await testPubSubDaemonPublish(count = 10)
|
||||
|
||||
test "daemon -> multiple reads and writes":
|
||||
proc runTests(): Future[bool] {.async.} =
|
||||
var protos = @["/test-stream"]
|
||||
asyncTest "gossipsub: daemon publish one":
|
||||
await testPubSubDaemonPublish(gossip = true)
|
||||
|
||||
var testFuture = newFuture[void]("test.future")
|
||||
proc nativeHandler(conn: Connection, proto: string) {.async.} =
|
||||
check "test 1" == string.fromBytes(await conn.readLp(1024))
|
||||
await conn.writeLp("test 2".toBytes())
|
||||
asyncTest "gossipsub: daemon publish many":
|
||||
await testPubSubDaemonPublish(gossip = true, count = 10)
|
||||
|
||||
check "test 3" == string.fromBytes(await conn.readLp(1024))
|
||||
await conn.writeLp("test 4".toBytes())
|
||||
asyncTest "floodsub: node publish one":
|
||||
await testPubSubNodePublish()
|
||||
|
||||
testFuture.complete()
|
||||
await conn.close()
|
||||
asyncTest "floodsub: node publish many":
|
||||
await testPubSubNodePublish(count = 10)
|
||||
|
||||
# custom proto
|
||||
var proto = new LPProtocol
|
||||
proto.handler = nativeHandler
|
||||
proto.codec = protos[0] # codec
|
||||
asyncTest "gossipsub: node publish one":
|
||||
await testPubSubNodePublish(gossip = true)
|
||||
|
||||
let nativeNode = newStandardSwitch(
|
||||
secureManagers = [SecureProtocol.Noise], outTimeout = 5.minutes)
|
||||
|
||||
nativeNode.mount(proto)
|
||||
|
||||
let awaiters = await nativeNode.start()
|
||||
let nativePeer = nativeNode.peerInfo
|
||||
|
||||
let daemonNode = await newDaemonApi()
|
||||
await daemonNode.connect(nativePeer.peerId, nativePeer.addrs)
|
||||
var stream = await daemonNode.openStream(nativePeer.peerId, protos)
|
||||
|
||||
asyncDiscard stream.transp.writeLp("test 1")
|
||||
check "test 2" == string.fromBytes(await stream.transp.readLp())
|
||||
|
||||
asyncDiscard stream.transp.writeLp("test 3")
|
||||
check "test 4" == string.fromBytes(await stream.transp.readLp())
|
||||
|
||||
await wait(testFuture, 10.secs)
|
||||
|
||||
result = true
|
||||
await stream.close()
|
||||
await nativeNode.stop()
|
||||
await allFutures(awaiters)
|
||||
await daemonNode.close()
|
||||
|
||||
check:
|
||||
waitFor(runTests()) == true
|
||||
|
||||
test "read write multiple":
|
||||
proc runTests(): Future[bool] {.async.} =
|
||||
var protos = @["/test-stream"]
|
||||
var test = "TEST STRING"
|
||||
|
||||
var count = 0
|
||||
var testFuture = newFuture[int]("test.future")
|
||||
proc nativeHandler(conn: Connection, proto: string) {.async.} =
|
||||
while count < 10:
|
||||
var line = string.fromBytes(await conn.readLp(1024))
|
||||
check line == test
|
||||
await conn.writeLp(test.toBytes())
|
||||
count.inc()
|
||||
|
||||
testFuture.complete(count)
|
||||
await conn.close()
|
||||
|
||||
# custom proto
|
||||
var proto = new LPProtocol
|
||||
proto.handler = nativeHandler
|
||||
proto.codec = protos[0] # codec
|
||||
|
||||
let nativeNode = newStandardSwitch(
|
||||
secureManagers = [SecureProtocol.Noise], outTimeout = 5.minutes)
|
||||
|
||||
nativeNode.mount(proto)
|
||||
|
||||
let awaiters = await nativeNode.start()
|
||||
let nativePeer = nativeNode.peerInfo
|
||||
|
||||
let daemonNode = await newDaemonApi()
|
||||
await daemonNode.connect(nativePeer.peerId, nativePeer.addrs)
|
||||
var stream = await daemonNode.openStream(nativePeer.peerId, protos)
|
||||
|
||||
var count2 = 0
|
||||
while count2 < 10:
|
||||
discard await stream.transp.writeLp(test)
|
||||
let line = await stream.transp.readLp()
|
||||
check test == string.fromBytes(line)
|
||||
inc(count2)
|
||||
|
||||
result = 10 == (await wait(testFuture, 1.minutes))
|
||||
await stream.close()
|
||||
await nativeNode.stop()
|
||||
await allFutures(awaiters)
|
||||
await daemonNode.close()
|
||||
|
||||
check:
|
||||
waitFor(runTests()) == true
|
||||
|
||||
test "floodsub: daemon publish one":
|
||||
check:
|
||||
waitFor(testPubSubDaemonPublish()) == true
|
||||
|
||||
test "floodsub: daemon publish many":
|
||||
check:
|
||||
waitFor(testPubSubDaemonPublish(count = 10)) == true
|
||||
|
||||
test "gossipsub: daemon publish one":
|
||||
check:
|
||||
waitFor(testPubSubDaemonPublish(gossip = true)) == true
|
||||
|
||||
test "gossipsub: daemon publish many":
|
||||
check:
|
||||
waitFor(testPubSubDaemonPublish(gossip = true, count = 10)) == true
|
||||
|
||||
test "floodsub: node publish one":
|
||||
check:
|
||||
waitFor(testPubSubNodePublish()) == true
|
||||
|
||||
test "floodsub: node publish many":
|
||||
check:
|
||||
waitFor(testPubSubNodePublish(count = 10)) == true
|
||||
|
||||
test "gossipsub: node publish one":
|
||||
check:
|
||||
waitFor(testPubSubNodePublish(gossip = true)) == true
|
||||
|
||||
test "gossipsub: node publish many":
|
||||
check:
|
||||
waitFor(testPubSubNodePublish(gossip = true, count = 10)) == true
|
||||
asyncTest "gossipsub: node publish many":
|
||||
await testPubSubNodePublish(gossip = true, count = 10)
|
||||
|
|
|
@ -20,8 +20,8 @@ suite "Mplex":
|
|||
teardown:
|
||||
checkTrackers()
|
||||
|
||||
test "encode header with channel id 0":
|
||||
proc testEncodeHeader() {.async.} =
|
||||
suite "channel encoding":
|
||||
asyncTest "encode header with channel id 0":
|
||||
proc encHandler(msg: seq[byte]) {.async.} =
|
||||
check msg == fromHex("000873747265616d2031")
|
||||
|
||||
|
@ -29,10 +29,7 @@ suite "Mplex":
|
|||
await conn.writeMsg(0, MessageType.New, ("stream 1").toBytes)
|
||||
await conn.close()
|
||||
|
||||
waitFor(testEncodeHeader())
|
||||
|
||||
test "encode header with channel id other than 0":
|
||||
proc testEncodeHeader() {.async.} =
|
||||
asyncTest "encode header with channel id other than 0":
|
||||
proc encHandler(msg: seq[byte]) {.async.} =
|
||||
check msg == fromHex("88010873747265616d2031")
|
||||
|
||||
|
@ -40,10 +37,7 @@ suite "Mplex":
|
|||
await conn.writeMsg(17, MessageType.New, ("stream 1").toBytes)
|
||||
await conn.close()
|
||||
|
||||
waitFor(testEncodeHeader())
|
||||
|
||||
test "encode header and body with channel id 0":
|
||||
proc testEncodeHeaderBody() {.async.} =
|
||||
asyncTest "encode header and body with channel id 0":
|
||||
proc encHandler(msg: seq[byte]) {.async.} =
|
||||
check msg == fromHex("020873747265616d2031")
|
||||
|
||||
|
@ -51,10 +45,7 @@ suite "Mplex":
|
|||
await conn.writeMsg(0, MessageType.MsgOut, ("stream 1").toBytes)
|
||||
await conn.close()
|
||||
|
||||
waitFor(testEncodeHeaderBody())
|
||||
|
||||
test "encode header and body with channel id other than 0":
|
||||
proc testEncodeHeaderBody() {.async.} =
|
||||
asyncTest "encode header and body with channel id other than 0":
|
||||
proc encHandler(msg: seq[byte]) {.async.} =
|
||||
check msg == fromHex("8a010873747265616d2031")
|
||||
|
||||
|
@ -62,10 +53,7 @@ suite "Mplex":
|
|||
await conn.writeMsg(17, MessageType.MsgOut, ("stream 1").toBytes)
|
||||
await conn.close()
|
||||
|
||||
waitFor(testEncodeHeaderBody())
|
||||
|
||||
test "decode header with channel id 0":
|
||||
proc testDecodeHeader() {.async.} =
|
||||
asyncTest "decode header with channel id 0":
|
||||
let stream = newBufferStream()
|
||||
let conn = stream
|
||||
await stream.pushData(fromHex("000873747265616d2031"))
|
||||
|
@ -75,10 +63,7 @@ suite "Mplex":
|
|||
check msg.msgType == MessageType.New
|
||||
await conn.close()
|
||||
|
||||
waitFor(testDecodeHeader())
|
||||
|
||||
test "decode header and body with channel id 0":
|
||||
proc testDecodeHeader() {.async.} =
|
||||
asyncTest "decode header and body with channel id 0":
|
||||
let stream = newBufferStream()
|
||||
let conn = stream
|
||||
await stream.pushData(fromHex("021668656C6C6F2066726F6D206368616E6E656C20302121"))
|
||||
|
@ -89,10 +74,7 @@ suite "Mplex":
|
|||
check string.fromBytes(msg.data) == "hello from channel 0!!"
|
||||
await conn.close()
|
||||
|
||||
waitFor(testDecodeHeader())
|
||||
|
||||
test "decode header and body with channel id other than 0":
|
||||
proc testDecodeHeader() {.async.} =
|
||||
asyncTest "decode header and body with channel id other than 0":
|
||||
let stream = newBufferStream()
|
||||
let conn = stream
|
||||
await stream.pushData(fromHex("8a011668656C6C6F2066726F6D206368616E6E656C20302121"))
|
||||
|
@ -103,28 +85,21 @@ suite "Mplex":
|
|||
check string.fromBytes(msg.data) == "hello from channel 0!!"
|
||||
await conn.close()
|
||||
|
||||
waitFor(testDecodeHeader())
|
||||
|
||||
test "half closed (local close) - should close for write":
|
||||
proc testClosedForWrite(): Future[bool] {.async.} =
|
||||
suite "channel half-closed":
|
||||
asyncTest "(local close) - should close for write":
|
||||
proc writeHandler(data: seq[byte]) {.async, gcsafe.} = discard
|
||||
let
|
||||
conn = newBufferStream(writeHandler)
|
||||
chann = LPChannel.init(1, conn, true)
|
||||
|
||||
await chann.close()
|
||||
try:
|
||||
expect LPStreamClosedError:
|
||||
await chann.write("Hello")
|
||||
except LPStreamClosedError:
|
||||
result = true
|
||||
finally:
|
||||
await chann.reset()
|
||||
await conn.close()
|
||||
|
||||
check:
|
||||
waitFor(testClosedForWrite()) == true
|
||||
await chann.reset()
|
||||
await conn.close()
|
||||
|
||||
test "half closed (local close) - should allow reads until remote closes":
|
||||
proc testOpenForRead(): Future[bool] {.async.} =
|
||||
asyncTest "(local close) - should allow reads until remote closes":
|
||||
let
|
||||
conn = newBufferStream(
|
||||
proc (data: seq[byte]) {.gcsafe, async.} =
|
||||
|
@ -142,21 +117,16 @@ suite "Mplex":
|
|||
let closeFut = chann.pushEof()
|
||||
# should still allow reading until buffer EOF
|
||||
await chann.readExactly(addr data[3], 3)
|
||||
try:
|
||||
|
||||
expect LPStreamEOFError:
|
||||
# this should fail now
|
||||
await chann.readExactly(addr data[0], 3)
|
||||
except LPStreamEOFError:
|
||||
result = true
|
||||
finally:
|
||||
await chann.close()
|
||||
await conn.close()
|
||||
|
||||
await chann.close()
|
||||
await conn.close()
|
||||
await closeFut
|
||||
|
||||
check:
|
||||
waitFor(testOpenForRead()) == true
|
||||
|
||||
test "half closed (remote close) - channel should close for reading by remote":
|
||||
proc testClosedForRead(): Future[bool] {.async.} =
|
||||
asyncTest "(remote close) - channel should close for reading by remote":
|
||||
let
|
||||
conn = newBufferStream(
|
||||
proc (data: seq[byte]) {.gcsafe, async.} =
|
||||
|
@ -171,19 +141,14 @@ suite "Mplex":
|
|||
let closeFut = chann.pushEof() # closing channel
|
||||
let readFut = chann.readExactly(addr data[3], 3)
|
||||
await all(closeFut, readFut)
|
||||
try:
|
||||
|
||||
expect LPStreamEOFError:
|
||||
await chann.readExactly(addr data[0], 6) # this should fail now
|
||||
except LPStreamEOFError:
|
||||
result = true
|
||||
finally:
|
||||
await chann.close()
|
||||
await conn.close()
|
||||
|
||||
check:
|
||||
waitFor(testClosedForRead()) == true
|
||||
await chann.close()
|
||||
await conn.close()
|
||||
|
||||
test "half closed (remote close) - channel should allow writing on remote close":
|
||||
proc testClosedForRead(): Future[bool] {.async.} =
|
||||
asyncTest "(remote close) - channel should allow writing on remote close":
|
||||
let
|
||||
testData = "Hello!".toBytes
|
||||
conn = newBufferStream(
|
||||
|
@ -195,16 +160,11 @@ suite "Mplex":
|
|||
await chann.pushEof() # closing channel
|
||||
try:
|
||||
await chann.writeLp(testData)
|
||||
return true
|
||||
finally:
|
||||
await chann.reset() # there's nobody reading the EOF!
|
||||
await conn.close()
|
||||
|
||||
check:
|
||||
waitFor(testClosedForRead()) == true
|
||||
|
||||
test "should not allow pushing data to channel when remote end closed":
|
||||
proc testResetWrite(): Future[bool] {.async.} =
|
||||
asyncTest "should not allow pushing data to channel when remote end closed":
|
||||
proc writeHandler(data: seq[byte]) {.async, gcsafe.} = discard
|
||||
let
|
||||
conn = newBufferStream(writeHandler)
|
||||
|
@ -212,19 +172,16 @@ suite "Mplex":
|
|||
await chann.pushEof()
|
||||
var buf: array[1, byte]
|
||||
check: (await chann.readOnce(addr buf[0], 1)) == 0 # EOF marker read
|
||||
try:
|
||||
|
||||
expect LPStreamEOFError:
|
||||
await chann.pushData(@[byte(1)])
|
||||
except LPStreamEOFError:
|
||||
result = true
|
||||
finally:
|
||||
await chann.close()
|
||||
await conn.close()
|
||||
|
||||
check:
|
||||
waitFor(testResetWrite()) == true
|
||||
await chann.close()
|
||||
await conn.close()
|
||||
|
||||
test "reset - channel should fail reading":
|
||||
proc testResetRead(): Future[bool] {.async.} =
|
||||
suite "channel reset":
|
||||
|
||||
asyncTest "channel should fail reading":
|
||||
proc writeHandler(data: seq[byte]) {.async, gcsafe.} = discard
|
||||
let
|
||||
conn = newBufferStream(writeHandler)
|
||||
|
@ -232,18 +189,12 @@ suite "Mplex":
|
|||
|
||||
await chann.reset()
|
||||
var data = newSeq[byte](1)
|
||||
try:
|
||||
expect LPStreamEOFError:
|
||||
await chann.readExactly(addr data[0], 1)
|
||||
except LPStreamEOFError:
|
||||
result = true
|
||||
finally:
|
||||
await conn.close()
|
||||
|
||||
check:
|
||||
waitFor(testResetRead()) == true
|
||||
await conn.close()
|
||||
|
||||
test "reset - should complete read":
|
||||
proc testResetRead(): Future[bool] {.async.} =
|
||||
asyncTest "should complete read":
|
||||
proc writeHandler(data: seq[byte]) {.async, gcsafe.} = discard
|
||||
let
|
||||
conn = newBufferStream(writeHandler)
|
||||
|
@ -251,19 +202,14 @@ suite "Mplex":
|
|||
|
||||
var data = newSeq[byte](1)
|
||||
let fut = chann.readExactly(addr data[0], 1)
|
||||
|
||||
await chann.reset()
|
||||
try:
|
||||
expect LPStreamEOFError:
|
||||
await fut
|
||||
except LPStreamEOFError:
|
||||
result = true
|
||||
finally:
|
||||
await conn.close()
|
||||
|
||||
check:
|
||||
waitFor(testResetRead()) == true
|
||||
await conn.close()
|
||||
|
||||
test "reset - should complete pushData":
|
||||
proc testResetRead(): Future[bool] {.async.} =
|
||||
asyncTest "should complete pushData":
|
||||
proc writeHandler(data: seq[byte]) {.async, gcsafe.} = discard
|
||||
let
|
||||
conn = newBufferStream(writeHandler)
|
||||
|
@ -272,14 +218,10 @@ suite "Mplex":
|
|||
await chann.pushData(@[0'u8])
|
||||
let fut = chann.pushData(@[0'u8])
|
||||
await chann.reset()
|
||||
result = await fut.withTimeout(100.millis)
|
||||
check await fut.withTimeout(100.millis)
|
||||
await conn.close()
|
||||
|
||||
check:
|
||||
waitFor(testResetRead()) == true
|
||||
|
||||
test "reset - should complete both read and push":
|
||||
proc testResetRead(): Future[bool] {.async.} =
|
||||
asyncTest "should complete both read and push":
|
||||
proc writeHandler(data: seq[byte]) {.async, gcsafe.} = discard
|
||||
let
|
||||
conn = newBufferStream(writeHandler)
|
||||
|
@ -290,46 +232,33 @@ suite "Mplex":
|
|||
let wfut = chann.pushData(@[0'u8])
|
||||
let wfut2 = chann.pushData(@[0'u8])
|
||||
await chann.reset()
|
||||
result = await allFutures(rfut, wfut, wfut2).withTimeout(100.millis)
|
||||
check await allFutures(rfut, wfut, wfut2).withTimeout(100.millis)
|
||||
await conn.close()
|
||||
|
||||
check:
|
||||
waitFor(testResetRead()) == true
|
||||
|
||||
test "reset - channel should fail writing":
|
||||
proc testResetWrite(): Future[bool] {.async.} =
|
||||
asyncTest "channel should fail writing":
|
||||
proc writeHandler(data: seq[byte]) {.async, gcsafe.} = discard
|
||||
let
|
||||
conn = newBufferStream(writeHandler)
|
||||
chann = LPChannel.init(1, conn, true)
|
||||
await chann.reset()
|
||||
try:
|
||||
|
||||
expect LPStreamClosedError:
|
||||
await chann.write(("Hello!").toBytes)
|
||||
except LPStreamClosedError:
|
||||
result = true
|
||||
finally:
|
||||
await conn.close()
|
||||
|
||||
check:
|
||||
waitFor(testResetWrite()) == true
|
||||
await conn.close()
|
||||
|
||||
test "reset - channel should reset on timeout":
|
||||
proc testResetWrite(): Future[bool] {.async.} =
|
||||
asyncTest "channel should reset on timeout":
|
||||
proc writeHandler(data: seq[byte]) {.async, gcsafe.} = discard
|
||||
let
|
||||
conn = newBufferStream(writeHandler)
|
||||
chann = LPChannel.init(
|
||||
1, conn, true, timeout = 100.millis)
|
||||
|
||||
check await chann.closeEvent.wait().withTimeout(1.minutes)
|
||||
check await chann.join().withTimeout(1.minutes)
|
||||
await conn.close()
|
||||
result = true
|
||||
|
||||
check:
|
||||
waitFor(testResetWrite())
|
||||
|
||||
test "e2e - read/write receiver":
|
||||
proc testNewStream() {.async.} =
|
||||
suite "mplex e2e":
|
||||
asyncTest "read/write receiver":
|
||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
|
||||
var done = newFuture[void]()
|
||||
|
@ -364,12 +293,10 @@ suite "Mplex":
|
|||
await allFuturesThrowing(
|
||||
transport1.close(),
|
||||
transport2.close())
|
||||
|
||||
await listenFut
|
||||
|
||||
waitFor(testNewStream())
|
||||
|
||||
test "e2e - read/write receiver lazy":
|
||||
proc testNewStream() {.async.} =
|
||||
asyncTest "read/write receiver lazy":
|
||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
|
||||
var done = newFuture[void]()
|
||||
|
@ -407,10 +334,7 @@ suite "Mplex":
|
|||
transport2.close())
|
||||
await listenFut
|
||||
|
||||
waitFor(testNewStream())
|
||||
|
||||
test "e2e - write fragmented":
|
||||
proc testNewStream() {.async.} =
|
||||
asyncTest "write fragmented":
|
||||
let
|
||||
ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
listenJob = newFuture[void]()
|
||||
|
@ -449,10 +373,7 @@ suite "Mplex":
|
|||
let stream = await mplexDial.newStream()
|
||||
|
||||
await stream.writeLp(bigseq)
|
||||
try:
|
||||
await listenJob.wait(10.seconds)
|
||||
except AsyncTimeoutError:
|
||||
check false
|
||||
await listenJob.wait(10.seconds)
|
||||
|
||||
await stream.close()
|
||||
await conn.close()
|
||||
|
@ -460,12 +381,10 @@ suite "Mplex":
|
|||
await allFuturesThrowing(
|
||||
transport1.close(),
|
||||
transport2.close())
|
||||
|
||||
await listenFut
|
||||
|
||||
waitFor(testNewStream())
|
||||
|
||||
test "e2e - read/write initiator":
|
||||
proc testNewStream() {.async.} =
|
||||
asyncTest "read/write initiator":
|
||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
|
||||
let done = newFuture[void]()
|
||||
|
@ -501,10 +420,7 @@ suite "Mplex":
|
|||
transport2.close())
|
||||
await listenFut
|
||||
|
||||
waitFor(testNewStream())
|
||||
|
||||
test "e2e - multiple streams":
|
||||
proc testNewStream() {.async.} =
|
||||
asyncTest "multiple streams":
|
||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
|
||||
let done = newFuture[void]()
|
||||
|
@ -545,10 +461,7 @@ suite "Mplex":
|
|||
transport2.close())
|
||||
await listenFut
|
||||
|
||||
waitFor(testNewStream())
|
||||
|
||||
test "e2e - multiple read/write streams":
|
||||
proc testNewStream() {.async.} =
|
||||
asyncTest "multiple read/write streams":
|
||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
|
||||
let done = newFuture[void]()
|
||||
|
@ -592,10 +505,7 @@ suite "Mplex":
|
|||
transport2.close())
|
||||
await listenFut
|
||||
|
||||
waitFor(testNewStream())
|
||||
|
||||
test "e2e - channel closes listener with EOF":
|
||||
proc testNewStream() {.async.} =
|
||||
asyncTest "channel closes listener with EOF":
|
||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
|
||||
var listenStreams: seq[Connection]
|
||||
|
@ -641,10 +551,7 @@ suite "Mplex":
|
|||
transport2.close())
|
||||
await listenFut
|
||||
|
||||
waitFor(testNewStream())
|
||||
|
||||
test "e2e - channel closes dialer with EOF":
|
||||
proc testNewStream() {.async.} =
|
||||
asyncTest "channel closes dialer with EOF":
|
||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
|
||||
var listenStreams: seq[Connection]
|
||||
|
@ -707,10 +614,7 @@ suite "Mplex":
|
|||
transport2.close())
|
||||
await listenFut
|
||||
|
||||
waitFor(testNewStream())
|
||||
|
||||
test "e2e - dialing mplex closes both ends":
|
||||
proc testNewStream() {.async.} =
|
||||
asyncTest "dialing mplex closes both ends":
|
||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
|
||||
var listenStreams: seq[Connection]
|
||||
|
@ -750,10 +654,7 @@ suite "Mplex":
|
|||
transport2.close())
|
||||
await listenFut
|
||||
|
||||
waitFor(testNewStream())
|
||||
|
||||
test "e2e - listening mplex closes both ends":
|
||||
proc testNewStream() {.async.} =
|
||||
asyncTest "listening mplex closes both ends":
|
||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
|
||||
var mplexListen: Mplex
|
||||
|
@ -794,10 +695,7 @@ suite "Mplex":
|
|||
transport2.close())
|
||||
await listenFut
|
||||
|
||||
waitFor(testNewStream())
|
||||
|
||||
test "e2e - canceling mplex handler closes both ends":
|
||||
proc testNewStream() {.async.} =
|
||||
asyncTest "canceling mplex handler closes both ends":
|
||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
|
||||
var mplexHandle: Future[void]
|
||||
|
@ -839,10 +737,7 @@ suite "Mplex":
|
|||
transport2.close())
|
||||
await listenFut
|
||||
|
||||
waitFor(testNewStream())
|
||||
|
||||
test "e2e - closing dialing connection should close both ends":
|
||||
proc testNewStream() {.async.} =
|
||||
asyncTest "closing dialing connection should close both ends":
|
||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
|
||||
var listenStreams: seq[Connection]
|
||||
|
@ -882,10 +777,7 @@ suite "Mplex":
|
|||
transport2.close())
|
||||
await listenFut
|
||||
|
||||
waitFor(testNewStream())
|
||||
|
||||
test "e2e - canceling listening connection should close both ends":
|
||||
proc testNewStream() {.async.} =
|
||||
asyncTest "canceling listening connection should close both ends":
|
||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
|
||||
var listenConn: Connection
|
||||
|
@ -927,137 +819,130 @@ suite "Mplex":
|
|||
transport2.close())
|
||||
await listenFut
|
||||
|
||||
waitFor(testNewStream())
|
||||
suite "jitter":
|
||||
asyncTest "channel should be able to handle erratic read/writes":
|
||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
|
||||
test "jitter - channel should be able to handle erratic read/writes":
|
||||
proc test() {.async.} =
|
||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
var complete = newFuture[void]()
|
||||
const MsgSize = 1024
|
||||
proc connHandler(conn: Connection) {.async, gcsafe.} =
|
||||
let mplexListen = Mplex.init(conn)
|
||||
mplexListen.streamHandler = proc(stream: Connection)
|
||||
{.async, gcsafe.} =
|
||||
try:
|
||||
let msg = await stream.readLp(MsgSize)
|
||||
check msg.len == MsgSize
|
||||
except CatchableError as e:
|
||||
echo e.msg
|
||||
await stream.close()
|
||||
complete.complete()
|
||||
|
||||
var complete = newFuture[void]()
|
||||
const MsgSize = 1024
|
||||
proc connHandler(conn: Connection) {.async, gcsafe.} =
|
||||
let mplexListen = Mplex.init(conn)
|
||||
mplexListen.streamHandler = proc(stream: Connection)
|
||||
{.async, gcsafe.} =
|
||||
try:
|
||||
await mplexListen.handle()
|
||||
await mplexListen.close()
|
||||
|
||||
let transport1: TcpTransport = TcpTransport.init()
|
||||
let listenFut = await transport1.listen(ma, connHandler)
|
||||
|
||||
let transport2: TcpTransport = TcpTransport.init()
|
||||
let conn = await transport2.dial(transport1.ma)
|
||||
|
||||
let mplexDial = Mplex.init(conn)
|
||||
let mplexDialFut = mplexDial.handle()
|
||||
let stream = await mplexDial.newStream()
|
||||
var bigseq = newSeqOfCap[uint8](MaxMsgSize + 1)
|
||||
for _ in 0..<MsgSize: # write one less than max size
|
||||
bigseq.add(uint8(rand(uint('A')..uint('z'))))
|
||||
|
||||
## create length prefixed libp2p frame
|
||||
var buf = initVBuffer()
|
||||
buf.writeSeq(bigseq)
|
||||
buf.finish()
|
||||
|
||||
## create mplex header
|
||||
var mplexBuf = initVBuffer()
|
||||
mplexBuf.writePBVarint((1.uint shl 3) or ord(MessageType.MsgOut).uint)
|
||||
mplexBuf.writePBVarint(buf.buffer.len.uint) # size should be always sent
|
||||
|
||||
await conn.write(mplexBuf.buffer)
|
||||
proc writer() {.async.} =
|
||||
var sent = 0
|
||||
randomize()
|
||||
let total = buf.buffer.len
|
||||
const min = 20
|
||||
const max = 50
|
||||
while sent < total:
|
||||
var size = rand(min..max)
|
||||
size = if size > buf.buffer.len: buf.buffer.len else: size
|
||||
var send = buf.buffer[0..<size]
|
||||
await conn.write(send)
|
||||
sent += size
|
||||
buf.buffer = buf.buffer[size..^1]
|
||||
|
||||
await writer()
|
||||
await complete.wait(1.seconds)
|
||||
|
||||
await stream.close()
|
||||
await conn.close()
|
||||
|
||||
await mplexDialFut
|
||||
|
||||
await allFuturesThrowing(
|
||||
transport1.close(),
|
||||
transport2.close())
|
||||
await listenFut
|
||||
|
||||
asyncTest "channel should handle 1 byte read/write":
|
||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
|
||||
var complete = newFuture[void]()
|
||||
const MsgSize = 512
|
||||
proc connHandler(conn: Connection) {.async, gcsafe.} =
|
||||
let mplexListen = Mplex.init(conn)
|
||||
mplexListen.streamHandler = proc(stream: Connection)
|
||||
{.async, gcsafe.} =
|
||||
let msg = await stream.readLp(MsgSize)
|
||||
check msg.len == MsgSize
|
||||
except CatchableError as e:
|
||||
echo e.msg
|
||||
await stream.close()
|
||||
complete.complete()
|
||||
await stream.close()
|
||||
complete.complete()
|
||||
|
||||
await mplexListen.handle()
|
||||
await mplexListen.close()
|
||||
await mplexListen.handle()
|
||||
await mplexListen.close()
|
||||
|
||||
let transport1: TcpTransport = TcpTransport.init()
|
||||
let listenFut = await transport1.listen(ma, connHandler)
|
||||
let transport1: TcpTransport = TcpTransport.init()
|
||||
let listenFut = await transport1.listen(ma, connHandler)
|
||||
|
||||
let transport2: TcpTransport = TcpTransport.init()
|
||||
let conn = await transport2.dial(transport1.ma)
|
||||
let transport2: TcpTransport = TcpTransport.init()
|
||||
let conn = await transport2.dial(transport1.ma)
|
||||
|
||||
let mplexDial = Mplex.init(conn)
|
||||
let mplexDialFut = mplexDial.handle()
|
||||
let stream = await mplexDial.newStream()
|
||||
var bigseq = newSeqOfCap[uint8](MaxMsgSize + 1)
|
||||
for _ in 0..<MsgSize: # write one less than max size
|
||||
bigseq.add(uint8(rand(uint('A')..uint('z'))))
|
||||
let mplexDial = Mplex.init(conn)
|
||||
let stream = await mplexDial.newStream()
|
||||
let mplexDialFut = mplexDial.handle()
|
||||
var bigseq = newSeqOfCap[uint8](MsgSize + 1)
|
||||
for _ in 0..<MsgSize: # write one less than max size
|
||||
bigseq.add(uint8(rand(uint('A')..uint('z'))))
|
||||
|
||||
## create length prefixed libp2p frame
|
||||
var buf = initVBuffer()
|
||||
buf.writeSeq(bigseq)
|
||||
buf.finish()
|
||||
## create length prefixed libp2p frame
|
||||
var buf = initVBuffer()
|
||||
buf.writeSeq(bigseq)
|
||||
buf.finish()
|
||||
|
||||
## create mplex header
|
||||
var mplexBuf = initVBuffer()
|
||||
mplexBuf.writePBVarint((1.uint shl 3) or ord(MessageType.MsgOut).uint)
|
||||
mplexBuf.writePBVarint(buf.buffer.len.uint) # size should be always sent
|
||||
## create mplex header
|
||||
var mplexBuf = initVBuffer()
|
||||
mplexBuf.writePBVarint((1.uint shl 3) or ord(MessageType.MsgOut).uint)
|
||||
mplexBuf.writePBVarint(buf.buffer.len.uint) # size should be always sent
|
||||
|
||||
await conn.write(mplexBuf.buffer)
|
||||
proc writer() {.async.} =
|
||||
var sent = 0
|
||||
randomize()
|
||||
let total = buf.buffer.len
|
||||
const min = 20
|
||||
const max = 50
|
||||
while sent < total:
|
||||
var size = rand(min..max)
|
||||
size = if size > buf.buffer.len: buf.buffer.len else: size
|
||||
var send = buf.buffer[0..<size]
|
||||
await conn.write(send)
|
||||
sent += size
|
||||
buf.buffer = buf.buffer[size..^1]
|
||||
await conn.write(mplexBuf.buffer)
|
||||
proc writer() {.async.} =
|
||||
for i in buf.buffer:
|
||||
await conn.write(@[i])
|
||||
|
||||
await writer()
|
||||
await complete.wait(1.seconds)
|
||||
await writer()
|
||||
|
||||
await stream.close()
|
||||
await conn.close()
|
||||
|
||||
await mplexDialFut
|
||||
|
||||
await allFuturesThrowing(
|
||||
transport1.close(),
|
||||
transport2.close())
|
||||
await listenFut
|
||||
|
||||
waitFor(test())
|
||||
|
||||
test "jitter - channel should handle 1 byte read/write":
|
||||
proc test() {.async.} =
|
||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
|
||||
var complete = newFuture[void]()
|
||||
const MsgSize = 512
|
||||
proc connHandler(conn: Connection) {.async, gcsafe.} =
|
||||
let mplexListen = Mplex.init(conn)
|
||||
mplexListen.streamHandler = proc(stream: Connection)
|
||||
{.async, gcsafe.} =
|
||||
let msg = await stream.readLp(MsgSize)
|
||||
check msg.len == MsgSize
|
||||
await stream.close()
|
||||
complete.complete()
|
||||
|
||||
await mplexListen.handle()
|
||||
await mplexListen.close()
|
||||
|
||||
let transport1: TcpTransport = TcpTransport.init()
|
||||
let listenFut = await transport1.listen(ma, connHandler)
|
||||
|
||||
let transport2: TcpTransport = TcpTransport.init()
|
||||
let conn = await transport2.dial(transport1.ma)
|
||||
|
||||
let mplexDial = Mplex.init(conn)
|
||||
let stream = await mplexDial.newStream()
|
||||
let mplexDialFut = mplexDial.handle()
|
||||
var bigseq = newSeqOfCap[uint8](MsgSize + 1)
|
||||
for _ in 0..<MsgSize: # write one less than max size
|
||||
bigseq.add(uint8(rand(uint('A')..uint('z'))))
|
||||
|
||||
## create length prefixed libp2p frame
|
||||
var buf = initVBuffer()
|
||||
buf.writeSeq(bigseq)
|
||||
buf.finish()
|
||||
|
||||
## create mplex header
|
||||
var mplexBuf = initVBuffer()
|
||||
mplexBuf.writePBVarint((1.uint shl 3) or ord(MessageType.MsgOut).uint)
|
||||
mplexBuf.writePBVarint(buf.buffer.len.uint) # size should be always sent
|
||||
|
||||
await conn.write(mplexBuf.buffer)
|
||||
proc writer() {.async.} =
|
||||
for i in buf.buffer:
|
||||
await conn.write(@[i])
|
||||
|
||||
await writer()
|
||||
|
||||
await complete.wait(5.seconds)
|
||||
await stream.close()
|
||||
await conn.close()
|
||||
await mplexDialFut
|
||||
await allFuturesThrowing(
|
||||
transport1.close(),
|
||||
transport2.close())
|
||||
await listenFut
|
||||
|
||||
waitFor(test())
|
||||
await complete.wait(5.seconds)
|
||||
await stream.close()
|
||||
await conn.close()
|
||||
await mplexDialFut
|
||||
await allFuturesThrowing(
|
||||
transport1.close(),
|
||||
transport2.close())
|
||||
await listenFut
|
||||
|
|
|
@ -170,263 +170,217 @@ suite "Multistream select":
|
|||
teardown:
|
||||
checkTrackers()
|
||||
|
||||
test "test select custom proto":
|
||||
proc testSelect(): Future[bool] {.async.} =
|
||||
let ms = newMultistream()
|
||||
let conn = newTestSelectStream()
|
||||
result = (await ms.select(conn, @["/test/proto/1.0.0"])) == "/test/proto/1.0.0"
|
||||
asyncTest "test select custom proto":
|
||||
let ms = newMultistream()
|
||||
let conn = newTestSelectStream()
|
||||
check (await ms.select(conn, @["/test/proto/1.0.0"])) == "/test/proto/1.0.0"
|
||||
await conn.close()
|
||||
|
||||
asyncTest "test handle custom proto":
|
||||
let ms = newMultistream()
|
||||
let conn = newTestSelectStream()
|
||||
|
||||
var protocol: LPProtocol = new LPProtocol
|
||||
proc testHandler(conn: Connection,
|
||||
proto: string):
|
||||
Future[void] {.async, gcsafe.} =
|
||||
check proto == "/test/proto/1.0.0"
|
||||
await conn.close()
|
||||
|
||||
check:
|
||||
waitFor(testSelect()) == true
|
||||
protocol.handler = testHandler
|
||||
ms.addHandler("/test/proto/1.0.0", protocol)
|
||||
await ms.handle(conn)
|
||||
|
||||
test "test handle custom proto":
|
||||
proc testHandle(): Future[bool] {.async.} =
|
||||
let ms = newMultistream()
|
||||
let conn = newTestSelectStream()
|
||||
asyncTest "test handle `ls`":
|
||||
let ms = newMultistream()
|
||||
|
||||
var protocol: LPProtocol = new LPProtocol
|
||||
proc testHandler(conn: Connection,
|
||||
proto: string):
|
||||
Future[void] {.async, gcsafe.} =
|
||||
check proto == "/test/proto/1.0.0"
|
||||
await conn.close()
|
||||
proc testLsHandler(proto: seq[byte]) {.async, gcsafe.} # forward declaration
|
||||
let conn = Connection(newTestLsStream(testLsHandler))
|
||||
let done = newFuture[void]()
|
||||
proc testLsHandler(proto: seq[byte]) {.async, gcsafe.} =
|
||||
var strProto: string = string.fromBytes(proto)
|
||||
check strProto == "\x26/test/proto1/1.0.0\n/test/proto2/1.0.0\n"
|
||||
await conn.close()
|
||||
done.complete()
|
||||
|
||||
protocol.handler = testHandler
|
||||
ms.addHandler("/test/proto/1.0.0", protocol)
|
||||
await ms.handle(conn)
|
||||
result = true
|
||||
proc testHandler(conn: Connection, proto: string): Future[void]
|
||||
{.async, gcsafe.} = discard
|
||||
var protocol: LPProtocol = new LPProtocol
|
||||
protocol.handler = testHandler
|
||||
ms.addHandler("/test/proto1/1.0.0", protocol)
|
||||
ms.addHandler("/test/proto2/1.0.0", protocol)
|
||||
await ms.handle(conn)
|
||||
await done.wait(5.seconds)
|
||||
|
||||
check:
|
||||
waitFor(testHandle()) == true
|
||||
asyncTest "test handle `na`":
|
||||
let ms = newMultistream()
|
||||
|
||||
test "test handle `ls`":
|
||||
proc testLs(): Future[bool] {.async.} =
|
||||
let ms = newMultistream()
|
||||
proc testNaHandler(msg: string): Future[void] {.async, gcsafe.}
|
||||
let conn = newTestNaStream(testNaHandler)
|
||||
|
||||
proc testLsHandler(proto: seq[byte]) {.async, gcsafe.} # forward declaration
|
||||
let conn = Connection(newTestLsStream(testLsHandler))
|
||||
let done = newFuture[void]()
|
||||
proc testLsHandler(proto: seq[byte]) {.async, gcsafe.} =
|
||||
var strProto: string = string.fromBytes(proto)
|
||||
check strProto == "\x26/test/proto1/1.0.0\n/test/proto2/1.0.0\n"
|
||||
await conn.close()
|
||||
done.complete()
|
||||
|
||||
proc testHandler(conn: Connection, proto: string): Future[void]
|
||||
{.async, gcsafe.} = discard
|
||||
var protocol: LPProtocol = new LPProtocol
|
||||
protocol.handler = testHandler
|
||||
ms.addHandler("/test/proto1/1.0.0", protocol)
|
||||
ms.addHandler("/test/proto2/1.0.0", protocol)
|
||||
await ms.handle(conn)
|
||||
result = true
|
||||
|
||||
await done.wait(5.seconds)
|
||||
|
||||
check:
|
||||
waitFor(testLs()) == true
|
||||
|
||||
test "test handle `na`":
|
||||
proc testNa(): Future[bool] {.async.} =
|
||||
let ms = newMultistream()
|
||||
|
||||
proc testNaHandler(msg: string): Future[void] {.async, gcsafe.}
|
||||
let conn = newTestNaStream(testNaHandler)
|
||||
|
||||
proc testNaHandler(msg: string): Future[void] {.async, gcsafe.} =
|
||||
echo msg
|
||||
check msg == Na
|
||||
await conn.close()
|
||||
|
||||
var protocol: LPProtocol = new LPProtocol
|
||||
proc testHandler(conn: Connection,
|
||||
proto: string):
|
||||
Future[void] {.async, gcsafe.} = discard
|
||||
protocol.handler = testHandler
|
||||
ms.addHandler("/unabvailable/proto/1.0.0", protocol)
|
||||
|
||||
await ms.handle(conn)
|
||||
result = true
|
||||
|
||||
check:
|
||||
waitFor(testNa()) == true
|
||||
|
||||
test "e2e - handle":
|
||||
proc endToEnd(): Future[bool] {.async.} =
|
||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
|
||||
let
|
||||
handlerWait1 = newFuture[void]()
|
||||
handlerWait2 = newFuture[void]()
|
||||
|
||||
var protocol: LPProtocol = new LPProtocol
|
||||
proc testHandler(conn: Connection,
|
||||
proto: string):
|
||||
Future[void] {.async, gcsafe.} =
|
||||
check proto == "/test/proto/1.0.0"
|
||||
await conn.writeLp("Hello!")
|
||||
await conn.close()
|
||||
handlerWait1.complete()
|
||||
|
||||
protocol.handler = testHandler
|
||||
let msListen = newMultistream()
|
||||
msListen.addHandler("/test/proto/1.0.0", protocol)
|
||||
|
||||
proc connHandler(conn: Connection): Future[void] {.async, gcsafe.} =
|
||||
await msListen.handle(conn)
|
||||
await conn.close()
|
||||
handlerWait2.complete()
|
||||
|
||||
let transport1: TcpTransport = TcpTransport.init()
|
||||
asyncCheck transport1.listen(ma, connHandler)
|
||||
|
||||
let msDial = newMultistream()
|
||||
let transport2: TcpTransport = TcpTransport.init()
|
||||
let conn = await transport2.dial(transport1.ma)
|
||||
|
||||
check (await msDial.select(conn, "/test/proto/1.0.0")) == true
|
||||
|
||||
let hello = string.fromBytes(await conn.readLp(1024))
|
||||
result = hello == "Hello!"
|
||||
proc testNaHandler(msg: string): Future[void] {.async, gcsafe.} =
|
||||
echo msg
|
||||
check msg == Na
|
||||
await conn.close()
|
||||
|
||||
await transport2.close()
|
||||
await transport1.close()
|
||||
var protocol: LPProtocol = new LPProtocol
|
||||
proc testHandler(conn: Connection,
|
||||
proto: string):
|
||||
Future[void] {.async, gcsafe.} = discard
|
||||
protocol.handler = testHandler
|
||||
ms.addHandler("/unabvailable/proto/1.0.0", protocol)
|
||||
|
||||
await allFuturesThrowing(
|
||||
handlerWait1.wait(30.seconds),
|
||||
handlerWait2.wait(30.seconds))
|
||||
await ms.handle(conn)
|
||||
|
||||
check:
|
||||
waitFor(endToEnd()) == true
|
||||
asyncTest "e2e - handle":
|
||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
|
||||
test "e2e - ls":
|
||||
proc endToEnd(): Future[bool] {.async.} =
|
||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
|
||||
let
|
||||
handlerWait = newFuture[void]()
|
||||
|
||||
let msListen = newMultistream()
|
||||
var protocol: LPProtocol = new LPProtocol
|
||||
protocol.handler = proc(conn: Connection, proto: string) {.async, gcsafe.} =
|
||||
# never reached
|
||||
discard
|
||||
|
||||
proc testHandler(conn: Connection,
|
||||
proto: string):
|
||||
Future[void] {.async.} =
|
||||
# never reached
|
||||
discard
|
||||
|
||||
protocol.handler = testHandler
|
||||
msListen.addHandler("/test/proto1/1.0.0", protocol)
|
||||
msListen.addHandler("/test/proto2/1.0.0", protocol)
|
||||
|
||||
let transport1: TcpTransport = TcpTransport.init()
|
||||
proc connHandler(conn: Connection): Future[void] {.async, gcsafe.} =
|
||||
try:
|
||||
await msListen.handle(conn)
|
||||
except LPStreamEOFError:
|
||||
discard
|
||||
except LPStreamClosedError:
|
||||
discard
|
||||
finally:
|
||||
await conn.close()
|
||||
|
||||
let listenFut = transport1.listen(ma, connHandler)
|
||||
|
||||
let msDial = newMultistream()
|
||||
let transport2: TcpTransport = TcpTransport.init()
|
||||
let conn = await transport2.dial(transport1.ma)
|
||||
|
||||
let ls = await msDial.list(conn)
|
||||
let protos: seq[string] = @["/test/proto1/1.0.0", "/test/proto2/1.0.0"]
|
||||
|
||||
result = ls == protos
|
||||
let
|
||||
handlerWait1 = newFuture[void]()
|
||||
handlerWait2 = newFuture[void]()
|
||||
|
||||
var protocol: LPProtocol = new LPProtocol
|
||||
proc testHandler(conn: Connection,
|
||||
proto: string):
|
||||
Future[void] {.async, gcsafe.} =
|
||||
check proto == "/test/proto/1.0.0"
|
||||
await conn.writeLp("Hello!")
|
||||
await conn.close()
|
||||
await transport2.close()
|
||||
await transport1.close()
|
||||
discard await listenFut.wait(5.seconds)
|
||||
handlerWait1.complete()
|
||||
|
||||
check:
|
||||
waitFor(endToEnd()) == true
|
||||
|
||||
test "e2e - select one from a list with unsupported protos":
|
||||
proc endToEnd(): Future[bool] {.async.} =
|
||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
|
||||
var protocol: LPProtocol = new LPProtocol
|
||||
proc testHandler(conn: Connection,
|
||||
proto: string):
|
||||
Future[void] {.async, gcsafe.} =
|
||||
check proto == "/test/proto/1.0.0"
|
||||
await conn.writeLp("Hello!")
|
||||
await conn.close()
|
||||
|
||||
protocol.handler = testHandler
|
||||
let msListen = newMultistream()
|
||||
msListen.addHandler("/test/proto/1.0.0", protocol)
|
||||
|
||||
proc connHandler(conn: Connection): Future[void] {.async, gcsafe.} =
|
||||
await msListen.handle(conn)
|
||||
|
||||
let transport1: TcpTransport = TcpTransport.init()
|
||||
asyncCheck transport1.listen(ma, connHandler)
|
||||
|
||||
let msDial = newMultistream()
|
||||
let transport2: TcpTransport = TcpTransport.init()
|
||||
let conn = await transport2.dial(transport1.ma)
|
||||
|
||||
check (await msDial.select(conn,
|
||||
@["/test/proto/1.0.0", "/test/no/proto/1.0.0"])) == "/test/proto/1.0.0"
|
||||
|
||||
let hello = string.fromBytes(await conn.readLp(1024))
|
||||
result = hello == "Hello!"
|
||||
protocol.handler = testHandler
|
||||
let msListen = newMultistream()
|
||||
msListen.addHandler("/test/proto/1.0.0", protocol)
|
||||
|
||||
proc connHandler(conn: Connection): Future[void] {.async, gcsafe.} =
|
||||
await msListen.handle(conn)
|
||||
await conn.close()
|
||||
await transport2.close()
|
||||
await transport1.close()
|
||||
handlerWait2.complete()
|
||||
|
||||
let transport1: TcpTransport = TcpTransport.init()
|
||||
asyncCheck transport1.listen(ma, connHandler)
|
||||
|
||||
check:
|
||||
waitFor(endToEnd()) == true
|
||||
let msDial = newMultistream()
|
||||
let transport2: TcpTransport = TcpTransport.init()
|
||||
let conn = await transport2.dial(transport1.ma)
|
||||
|
||||
test "e2e - select one with both valid":
|
||||
proc endToEnd(): Future[bool] {.async.} =
|
||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
check (await msDial.select(conn, "/test/proto/1.0.0")) == true
|
||||
|
||||
var protocol: LPProtocol = new LPProtocol
|
||||
proc testHandler(conn: Connection,
|
||||
proto: string):
|
||||
Future[void] {.async, gcsafe.} =
|
||||
await conn.writeLp(&"Hello from {proto}!")
|
||||
await conn.close()
|
||||
let hello = string.fromBytes(await conn.readLp(1024))
|
||||
check hello == "Hello!"
|
||||
await conn.close()
|
||||
|
||||
protocol.handler = testHandler
|
||||
let msListen = newMultistream()
|
||||
msListen.addHandler("/test/proto1/1.0.0", protocol)
|
||||
msListen.addHandler("/test/proto2/1.0.0", protocol)
|
||||
await transport2.close()
|
||||
await transport1.close()
|
||||
|
||||
proc connHandler(conn: Connection): Future[void] {.async, gcsafe.} =
|
||||
await msListen.handle(conn)
|
||||
await allFuturesThrowing(
|
||||
handlerWait1.wait(30.seconds),
|
||||
handlerWait2.wait(30.seconds))
|
||||
|
||||
let transport1: TcpTransport = TcpTransport.init()
|
||||
asyncCheck transport1.listen(ma, connHandler)
|
||||
asyncTest "e2e - ls":
|
||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
|
||||
let msDial = newMultistream()
|
||||
let transport2: TcpTransport = TcpTransport.init()
|
||||
let conn = await transport2.dial(transport1.ma)
|
||||
let
|
||||
handlerWait = newFuture[void]()
|
||||
|
||||
check (await msDial.select(conn, @["/test/proto2/1.0.0", "/test/proto1/1.0.0"])) == "/test/proto2/1.0.0"
|
||||
let msListen = newMultistream()
|
||||
var protocol: LPProtocol = new LPProtocol
|
||||
protocol.handler = proc(conn: Connection, proto: string) {.async, gcsafe.} =
|
||||
# never reached
|
||||
discard
|
||||
|
||||
result = string.fromBytes(await conn.readLp(1024)) == "Hello from /test/proto2/1.0.0!"
|
||||
proc testHandler(conn: Connection,
|
||||
proto: string):
|
||||
Future[void] {.async.} =
|
||||
# never reached
|
||||
discard
|
||||
|
||||
protocol.handler = testHandler
|
||||
msListen.addHandler("/test/proto1/1.0.0", protocol)
|
||||
msListen.addHandler("/test/proto2/1.0.0", protocol)
|
||||
|
||||
let transport1: TcpTransport = TcpTransport.init()
|
||||
proc connHandler(conn: Connection): Future[void] {.async, gcsafe.} =
|
||||
await msListen.handle(conn)
|
||||
await conn.close()
|
||||
await transport2.close()
|
||||
await transport1.close()
|
||||
|
||||
check:
|
||||
waitFor(endToEnd()) == true
|
||||
let listenFut = transport1.listen(ma, connHandler)
|
||||
let msDial = newMultistream()
|
||||
let transport2: TcpTransport = TcpTransport.init()
|
||||
let conn = await transport2.dial(transport1.ma)
|
||||
|
||||
let ls = await msDial.list(conn)
|
||||
let protos: seq[string] = @["/test/proto1/1.0.0", "/test/proto2/1.0.0"]
|
||||
|
||||
check ls == protos
|
||||
|
||||
await conn.close()
|
||||
await transport2.close()
|
||||
await transport1.close()
|
||||
discard await listenFut.wait(5.seconds)
|
||||
|
||||
asyncTest "e2e - select one from a list with unsupported protos":
|
||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
var protocol: LPProtocol = new LPProtocol
|
||||
proc testHandler(conn: Connection,
|
||||
proto: string):
|
||||
Future[void] {.async, gcsafe.} =
|
||||
check proto == "/test/proto/1.0.0"
|
||||
await conn.writeLp("Hello!")
|
||||
await conn.close()
|
||||
|
||||
protocol.handler = testHandler
|
||||
let msListen = newMultistream()
|
||||
msListen.addHandler("/test/proto/1.0.0", protocol)
|
||||
|
||||
proc connHandler(conn: Connection): Future[void] {.async, gcsafe.} =
|
||||
await msListen.handle(conn)
|
||||
|
||||
let transport1: TcpTransport = TcpTransport.init()
|
||||
asyncCheck transport1.listen(ma, connHandler)
|
||||
|
||||
let msDial = newMultistream()
|
||||
let transport2: TcpTransport = TcpTransport.init()
|
||||
let conn = await transport2.dial(transport1.ma)
|
||||
|
||||
check (await msDial.select(conn,
|
||||
@["/test/proto/1.0.0", "/test/no/proto/1.0.0"])) == "/test/proto/1.0.0"
|
||||
|
||||
let hello = string.fromBytes(await conn.readLp(1024))
|
||||
check hello == "Hello!"
|
||||
|
||||
await conn.close()
|
||||
await transport2.close()
|
||||
await transport1.close()
|
||||
|
||||
asyncTest "e2e - select one with both valid":
|
||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
|
||||
var protocol: LPProtocol = new LPProtocol
|
||||
proc testHandler(conn: Connection,
|
||||
proto: string):
|
||||
Future[void] {.async, gcsafe.} =
|
||||
await conn.writeLp(&"Hello from {proto}!")
|
||||
await conn.close()
|
||||
|
||||
protocol.handler = testHandler
|
||||
let msListen = newMultistream()
|
||||
msListen.addHandler("/test/proto1/1.0.0", protocol)
|
||||
msListen.addHandler("/test/proto2/1.0.0", protocol)
|
||||
|
||||
proc connHandler(conn: Connection): Future[void] {.async, gcsafe.} =
|
||||
await msListen.handle(conn)
|
||||
|
||||
let transport1: TcpTransport = TcpTransport.init()
|
||||
asyncCheck transport1.listen(ma, connHandler)
|
||||
|
||||
let msDial = newMultistream()
|
||||
let transport2: TcpTransport = TcpTransport.init()
|
||||
let conn = await transport2.dial(transport1.ma)
|
||||
|
||||
check (await msDial.select(conn, @["/test/proto2/1.0.0", "/test/proto1/1.0.0"])) == "/test/proto2/1.0.0"
|
||||
check string.fromBytes(await conn.readLp(1024)) == "Hello from /test/proto2/1.0.0!"
|
||||
|
||||
await conn.close()
|
||||
await transport2.close()
|
||||
await transport1.close()
|
||||
|
|
|
@ -74,232 +74,199 @@ suite "Noise":
|
|||
teardown:
|
||||
checkTrackers()
|
||||
|
||||
test "e2e: handle write + noise":
|
||||
proc testListenerDialer(): Future[bool] {.async.} =
|
||||
let
|
||||
server = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
serverInfo = PeerInfo.init(PrivateKey.random(ECDSA, rng[]).get(), [server])
|
||||
serverNoise = newNoise(rng, serverInfo.privateKey, outgoing = false)
|
||||
asyncTest "e2e: handle write + noise":
|
||||
let
|
||||
server = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
serverInfo = PeerInfo.init(PrivateKey.random(ECDSA, rng[]).get(), [server])
|
||||
serverNoise = newNoise(rng, serverInfo.privateKey, outgoing = false)
|
||||
|
||||
proc connHandler(conn: Connection) {.async, gcsafe.} =
|
||||
let sconn = await serverNoise.secure(conn, false)
|
||||
try:
|
||||
await sconn.write("Hello!")
|
||||
finally:
|
||||
await sconn.close()
|
||||
await conn.close()
|
||||
proc connHandler(conn: Connection) {.async, gcsafe.} =
|
||||
let sconn = await serverNoise.secure(conn, false)
|
||||
try:
|
||||
await sconn.write("Hello!")
|
||||
finally:
|
||||
await sconn.close()
|
||||
await conn.close()
|
||||
|
||||
let
|
||||
transport1: TcpTransport = TcpTransport.init()
|
||||
asyncCheck await transport1.listen(server, connHandler)
|
||||
let
|
||||
transport1: TcpTransport = TcpTransport.init()
|
||||
asyncCheck await transport1.listen(server, connHandler)
|
||||
|
||||
let
|
||||
transport2: TcpTransport = TcpTransport.init()
|
||||
clientInfo = PeerInfo.init(PrivateKey.random(ECDSA, rng[]).get(), [transport1.ma])
|
||||
clientNoise = newNoise(rng, clientInfo.privateKey, outgoing = true)
|
||||
conn = await transport2.dial(transport1.ma)
|
||||
sconn = await clientNoise.secure(conn, true)
|
||||
let
|
||||
transport2: TcpTransport = TcpTransport.init()
|
||||
clientInfo = PeerInfo.init(PrivateKey.random(ECDSA, rng[]).get(), [transport1.ma])
|
||||
clientNoise = newNoise(rng, clientInfo.privateKey, outgoing = true)
|
||||
conn = await transport2.dial(transport1.ma)
|
||||
sconn = await clientNoise.secure(conn, true)
|
||||
|
||||
var msg = newSeq[byte](6)
|
||||
await sconn.readExactly(addr msg[0], 6)
|
||||
|
||||
await sconn.close()
|
||||
await conn.close()
|
||||
await transport1.close()
|
||||
await transport2.close()
|
||||
|
||||
check string.fromBytes(msg) == "Hello!"
|
||||
|
||||
asyncTest "e2e: handle write + noise (wrong prologue)":
|
||||
let
|
||||
server = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
serverInfo = PeerInfo.init(PrivateKey.random(ECDSA, rng[]).get(), [server])
|
||||
serverNoise = newNoise(rng, serverInfo.privateKey, outgoing = false)
|
||||
|
||||
proc connHandler(conn: Connection) {.async, gcsafe.} =
|
||||
let sconn = await serverNoise.secure(conn, false)
|
||||
try:
|
||||
await sconn.write("Hello!")
|
||||
finally:
|
||||
await sconn.close()
|
||||
await conn.close()
|
||||
|
||||
let
|
||||
transport1: TcpTransport = TcpTransport.init()
|
||||
asyncCheck await transport1.listen(server, connHandler)
|
||||
|
||||
let
|
||||
transport2: TcpTransport = TcpTransport.init()
|
||||
clientInfo = PeerInfo.init(PrivateKey.random(ECDSA, rng[]).get(), [transport1.ma])
|
||||
clientNoise = newNoise(rng, clientInfo.privateKey, outgoing = true, commonPrologue = @[1'u8, 2'u8, 3'u8])
|
||||
conn = await transport2.dial(transport1.ma)
|
||||
var sconn: Connection = nil
|
||||
expect(NoiseDecryptTagError):
|
||||
sconn = await clientNoise.secure(conn, true)
|
||||
|
||||
await conn.close()
|
||||
await transport1.close()
|
||||
await transport2.close()
|
||||
|
||||
asyncTest "e2e: handle read + noise":
|
||||
let
|
||||
server = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
serverInfo = PeerInfo.init(PrivateKey.random(ECDSA, rng[]).get(), [server])
|
||||
serverNoise = newNoise(rng, serverInfo.privateKey, outgoing = false)
|
||||
readTask = newFuture[void]()
|
||||
|
||||
proc connHandler(conn: Connection) {.async, gcsafe.} =
|
||||
let sconn = await serverNoise.secure(conn, false)
|
||||
defer:
|
||||
await sconn.close()
|
||||
await conn.close()
|
||||
var msg = newSeq[byte](6)
|
||||
await sconn.readExactly(addr msg[0], 6)
|
||||
check string.fromBytes(msg) == "Hello!"
|
||||
readTask.complete()
|
||||
|
||||
await sconn.close()
|
||||
await conn.close()
|
||||
await transport1.close()
|
||||
await transport2.close()
|
||||
let
|
||||
transport1: TcpTransport = TcpTransport.init()
|
||||
asyncCheck await transport1.listen(server, connHandler)
|
||||
|
||||
result = string.fromBytes(msg) == "Hello!"
|
||||
let
|
||||
transport2: TcpTransport = TcpTransport.init()
|
||||
clientInfo = PeerInfo.init(PrivateKey.random(ECDSA, rng[]).get(), [transport1.ma])
|
||||
clientNoise = newNoise(rng, clientInfo.privateKey, outgoing = true)
|
||||
conn = await transport2.dial(transport1.ma)
|
||||
sconn = await clientNoise.secure(conn, true)
|
||||
|
||||
check:
|
||||
waitFor(testListenerDialer()) == true
|
||||
await sconn.write("Hello!")
|
||||
await readTask
|
||||
await sconn.close()
|
||||
await conn.close()
|
||||
await transport1.close()
|
||||
await transport2.close()
|
||||
|
||||
test "e2e: handle write + noise (wrong prologue)":
|
||||
proc testListenerDialer(): Future[bool] {.async.} =
|
||||
let
|
||||
server = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
serverInfo = PeerInfo.init(PrivateKey.random(ECDSA, rng[]).get(), [server])
|
||||
serverNoise = newNoise(rng, serverInfo.privateKey, outgoing = false)
|
||||
asyncTest "e2e: handle read + noise fragmented":
|
||||
let
|
||||
server = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
serverInfo = PeerInfo.init(PrivateKey.random(ECDSA, rng[]).get(), [server])
|
||||
serverNoise = newNoise(rng, serverInfo.privateKey, outgoing = false)
|
||||
readTask = newFuture[void]()
|
||||
|
||||
proc connHandler(conn: Connection) {.async, gcsafe.} =
|
||||
let sconn = await serverNoise.secure(conn, false)
|
||||
try:
|
||||
await sconn.write("Hello!")
|
||||
finally:
|
||||
await sconn.close()
|
||||
await conn.close()
|
||||
var hugePayload = newSeq[byte](0xFFFFF)
|
||||
brHmacDrbgGenerate(rng[], hugePayload)
|
||||
trace "Sending huge payload", size = hugePayload.len
|
||||
|
||||
let
|
||||
transport1: TcpTransport = TcpTransport.init()
|
||||
asyncCheck await transport1.listen(server, connHandler)
|
||||
proc connHandler(conn: Connection) {.async, gcsafe.} =
|
||||
let sconn = await serverNoise.secure(conn, false)
|
||||
defer:
|
||||
await sconn.close()
|
||||
let msg = await sconn.readLp(1024*1024)
|
||||
check msg == hugePayload
|
||||
readTask.complete()
|
||||
|
||||
let
|
||||
transport2: TcpTransport = TcpTransport.init()
|
||||
clientInfo = PeerInfo.init(PrivateKey.random(ECDSA, rng[]).get(), [transport1.ma])
|
||||
clientNoise = newNoise(rng, clientInfo.privateKey, outgoing = true, commonPrologue = @[1'u8, 2'u8, 3'u8])
|
||||
conn = await transport2.dial(transport1.ma)
|
||||
var sconn: Connection = nil
|
||||
expect(NoiseDecryptTagError):
|
||||
sconn = await clientNoise.secure(conn, true)
|
||||
let
|
||||
transport1: TcpTransport = TcpTransport.init()
|
||||
listenFut = await transport1.listen(server, connHandler)
|
||||
|
||||
await conn.close()
|
||||
await transport1.close()
|
||||
await transport2.close()
|
||||
let
|
||||
transport2: TcpTransport = TcpTransport.init()
|
||||
clientInfo = PeerInfo.init(PrivateKey.random(ECDSA, rng[]).get(), [transport1.ma])
|
||||
clientNoise = newNoise(rng, clientInfo.privateKey, outgoing = true)
|
||||
conn = await transport2.dial(transport1.ma)
|
||||
sconn = await clientNoise.secure(conn, true)
|
||||
|
||||
result = true
|
||||
await sconn.writeLp(hugePayload)
|
||||
await readTask
|
||||
|
||||
check:
|
||||
waitFor(testListenerDialer()) == true
|
||||
await sconn.close()
|
||||
await conn.close()
|
||||
await transport2.close()
|
||||
await transport1.close()
|
||||
await listenFut
|
||||
|
||||
test "e2e: handle read + noise":
|
||||
proc testListenerDialer(): Future[bool] {.async.} =
|
||||
let
|
||||
server = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
serverInfo = PeerInfo.init(PrivateKey.random(ECDSA, rng[]).get(), [server])
|
||||
serverNoise = newNoise(rng, serverInfo.privateKey, outgoing = false)
|
||||
readTask = newFuture[void]()
|
||||
asyncTest "e2e use switch dial proto string":
|
||||
let ma1: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
let ma2: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
|
||||
proc connHandler(conn: Connection) {.async, gcsafe.} =
|
||||
let sconn = await serverNoise.secure(conn, false)
|
||||
defer:
|
||||
await sconn.close()
|
||||
await conn.close()
|
||||
var msg = newSeq[byte](6)
|
||||
await sconn.readExactly(addr msg[0], 6)
|
||||
check string.fromBytes(msg) == "Hello!"
|
||||
readTask.complete()
|
||||
var peerInfo1, peerInfo2: PeerInfo
|
||||
var switch1, switch2: Switch
|
||||
var awaiters: seq[Future[void]]
|
||||
|
||||
let
|
||||
transport1: TcpTransport = TcpTransport.init()
|
||||
asyncCheck await transport1.listen(server, connHandler)
|
||||
(switch1, peerInfo1) = createSwitch(ma1, false)
|
||||
|
||||
let
|
||||
transport2: TcpTransport = TcpTransport.init()
|
||||
clientInfo = PeerInfo.init(PrivateKey.random(ECDSA, rng[]).get(), [transport1.ma])
|
||||
clientNoise = newNoise(rng, clientInfo.privateKey, outgoing = true)
|
||||
conn = await transport2.dial(transport1.ma)
|
||||
sconn = await clientNoise.secure(conn, true)
|
||||
let testProto = new TestProto
|
||||
testProto.init()
|
||||
testProto.codec = TestCodec
|
||||
switch1.mount(testProto)
|
||||
(switch2, peerInfo2) = createSwitch(ma2, true)
|
||||
awaiters.add(await switch1.start())
|
||||
awaiters.add(await switch2.start())
|
||||
let conn = await switch2.dial(switch1.peerInfo, TestCodec)
|
||||
await conn.writeLp("Hello!")
|
||||
let msg = string.fromBytes(await conn.readLp(1024))
|
||||
check "Hello!" == msg
|
||||
await conn.close()
|
||||
|
||||
await sconn.write("Hello!")
|
||||
await readTask
|
||||
await sconn.close()
|
||||
await conn.close()
|
||||
await transport1.close()
|
||||
await transport2.close()
|
||||
await allFuturesThrowing(
|
||||
switch1.stop(),
|
||||
switch2.stop())
|
||||
await allFuturesThrowing(awaiters)
|
||||
|
||||
result = true
|
||||
asyncTest "e2e test wrong secure negotiation":
|
||||
let ma1: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
let ma2: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
|
||||
check:
|
||||
waitFor(testListenerDialer()) == true
|
||||
var peerInfo1, peerInfo2: PeerInfo
|
||||
var switch1, switch2: Switch
|
||||
var awaiters: seq[Future[void]]
|
||||
|
||||
test "e2e: handle read + noise fragmented":
|
||||
proc testListenerDialer(): Future[bool] {.async.} =
|
||||
let
|
||||
server = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
serverInfo = PeerInfo.init(PrivateKey.random(ECDSA, rng[]).get(), [server])
|
||||
serverNoise = newNoise(rng, serverInfo.privateKey, outgoing = false)
|
||||
readTask = newFuture[void]()
|
||||
(switch1, peerInfo1) = createSwitch(ma1, false)
|
||||
|
||||
var hugePayload = newSeq[byte](0xFFFFF)
|
||||
brHmacDrbgGenerate(rng[], hugePayload)
|
||||
trace "Sending huge payload", size = hugePayload.len
|
||||
|
||||
proc connHandler(conn: Connection) {.async, gcsafe.} =
|
||||
let sconn = await serverNoise.secure(conn, false)
|
||||
defer:
|
||||
await sconn.close()
|
||||
let msg = await sconn.readLp(1024*1024)
|
||||
check msg == hugePayload
|
||||
readTask.complete()
|
||||
|
||||
let
|
||||
transport1: TcpTransport = TcpTransport.init()
|
||||
listenFut = await transport1.listen(server, connHandler)
|
||||
|
||||
let
|
||||
transport2: TcpTransport = TcpTransport.init()
|
||||
clientInfo = PeerInfo.init(PrivateKey.random(ECDSA, rng[]).get(), [transport1.ma])
|
||||
clientNoise = newNoise(rng, clientInfo.privateKey, outgoing = true)
|
||||
conn = await transport2.dial(transport1.ma)
|
||||
sconn = await clientNoise.secure(conn, true)
|
||||
|
||||
await sconn.writeLp(hugePayload)
|
||||
await readTask
|
||||
|
||||
await sconn.close()
|
||||
await conn.close()
|
||||
await transport2.close()
|
||||
await transport1.close()
|
||||
await listenFut
|
||||
|
||||
result = true
|
||||
|
||||
check:
|
||||
waitFor(testListenerDialer()) == true
|
||||
|
||||
test "e2e use switch dial proto string":
|
||||
proc testSwitch(): Future[bool] {.async, gcsafe.} =
|
||||
let ma1: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
let ma2: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
|
||||
var peerInfo1, peerInfo2: PeerInfo
|
||||
var switch1, switch2: Switch
|
||||
var awaiters: seq[Future[void]]
|
||||
|
||||
(switch1, peerInfo1) = createSwitch(ma1, false)
|
||||
|
||||
let testProto = new TestProto
|
||||
testProto.init()
|
||||
testProto.codec = TestCodec
|
||||
switch1.mount(testProto)
|
||||
(switch2, peerInfo2) = createSwitch(ma2, true)
|
||||
awaiters.add(await switch1.start())
|
||||
awaiters.add(await switch2.start())
|
||||
let testProto = new TestProto
|
||||
testProto.init()
|
||||
testProto.codec = TestCodec
|
||||
switch1.mount(testProto)
|
||||
(switch2, peerInfo2) = createSwitch(ma2, true, true) # secio, we want to fail
|
||||
awaiters.add(await switch1.start())
|
||||
awaiters.add(await switch2.start())
|
||||
expect(UpgradeFailedError):
|
||||
let conn = await switch2.dial(switch1.peerInfo, TestCodec)
|
||||
await conn.writeLp("Hello!")
|
||||
let msg = string.fromBytes(await conn.readLp(1024))
|
||||
check "Hello!" == msg
|
||||
await conn.close()
|
||||
|
||||
await allFuturesThrowing(
|
||||
switch1.stop(),
|
||||
switch2.stop())
|
||||
await allFuturesThrowing(awaiters)
|
||||
result = true
|
||||
await allFuturesThrowing(
|
||||
switch1.stop(),
|
||||
switch2.stop())
|
||||
|
||||
check:
|
||||
waitFor(testSwitch()) == true
|
||||
|
||||
test "e2e test wrong secure negotiation":
|
||||
proc testSwitch(): Future[bool] {.async, gcsafe.} =
|
||||
let ma1: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
let ma2: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
|
||||
var peerInfo1, peerInfo2: PeerInfo
|
||||
var switch1, switch2: Switch
|
||||
var awaiters: seq[Future[void]]
|
||||
|
||||
(switch1, peerInfo1) = createSwitch(ma1, false)
|
||||
|
||||
let testProto = new TestProto
|
||||
testProto.init()
|
||||
testProto.codec = TestCodec
|
||||
switch1.mount(testProto)
|
||||
(switch2, peerInfo2) = createSwitch(ma2, true, true) # secio, we want to fail
|
||||
awaiters.add(await switch1.start())
|
||||
awaiters.add(await switch2.start())
|
||||
expect(UpgradeFailedError):
|
||||
let conn = await switch2.dial(switch1.peerInfo, TestCodec)
|
||||
|
||||
await allFuturesThrowing(
|
||||
switch1.stop(),
|
||||
switch2.stop())
|
||||
|
||||
await allFuturesThrowing(awaiters)
|
||||
|
||||
result = true
|
||||
|
||||
check:
|
||||
waitFor(testSwitch()) == true
|
||||
await allFuturesThrowing(awaiters)
|
||||
|
||||
# test "interop with rust noise":
|
||||
# when true: # disable cos in CI we got no interop server/client
|
||||
|
|
1187
tests/testswitch.nim
1187
tests/testswitch.nim
File diff suppressed because it is too large
Load Diff
|
@ -13,180 +13,156 @@ suite "TCP transport":
|
|||
teardown:
|
||||
checkTrackers()
|
||||
|
||||
test "test listener: handle write":
|
||||
proc testListener(): Future[bool] {.async, gcsafe.} =
|
||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
let handlerWait = newFuture[void]()
|
||||
proc connHandler(conn: Connection) {.async, gcsafe.} =
|
||||
await conn.write(cstring("Hello!"), 6)
|
||||
await conn.close()
|
||||
handlerWait.complete()
|
||||
asyncTest "test listener: handle write":
|
||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
let handlerWait = newFuture[void]()
|
||||
proc connHandler(conn: Connection) {.async, gcsafe.} =
|
||||
await conn.write(cstring("Hello!"), 6)
|
||||
await conn.close()
|
||||
handlerWait.complete()
|
||||
|
||||
let transport: TcpTransport = TcpTransport.init()
|
||||
let transport: TcpTransport = TcpTransport.init()
|
||||
|
||||
asyncCheck transport.listen(ma, connHandler)
|
||||
asyncCheck transport.listen(ma, connHandler)
|
||||
|
||||
let streamTransport = await connect(transport.ma)
|
||||
let streamTransport = await connect(transport.ma)
|
||||
|
||||
let msg = await streamTransport.read(6)
|
||||
let msg = await streamTransport.read(6)
|
||||
|
||||
await handlerWait.wait(5000.millis) # when no issues will not wait that long!
|
||||
await streamTransport.closeWait()
|
||||
await transport.close()
|
||||
await handlerWait.wait(5000.millis) # when no issues will not wait that long!
|
||||
await streamTransport.closeWait()
|
||||
await transport.close()
|
||||
|
||||
result = string.fromBytes(msg) == "Hello!"
|
||||
check string.fromBytes(msg) == "Hello!"
|
||||
|
||||
check:
|
||||
waitFor(testListener()) == true
|
||||
|
||||
test "test listener: handle read":
|
||||
proc testListener(): Future[bool] {.async.} =
|
||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
let handlerWait = newFuture[void]()
|
||||
proc connHandler(conn: Connection) {.async, gcsafe.} =
|
||||
var msg = newSeq[byte](6)
|
||||
await conn.readExactly(addr msg[0], 6)
|
||||
check string.fromBytes(msg) == "Hello!"
|
||||
await conn.close()
|
||||
handlerWait.complete()
|
||||
|
||||
let transport: TcpTransport = TcpTransport.init()
|
||||
asyncCheck await transport.listen(ma, connHandler)
|
||||
let streamTransport: StreamTransport = await connect(transport.ma)
|
||||
let sent = await streamTransport.write("Hello!", 6)
|
||||
|
||||
await handlerWait.wait(5000.millis) # when no issues will not wait that long!
|
||||
await streamTransport.closeWait()
|
||||
await transport.close()
|
||||
|
||||
result = sent == 6
|
||||
|
||||
check:
|
||||
waitFor(testListener()) == true
|
||||
|
||||
test "test dialer: handle write":
|
||||
proc testDialer(address: TransportAddress): Future[bool] {.async.} =
|
||||
let handlerWait = newFuture[void]()
|
||||
proc serveClient(server: StreamServer,
|
||||
transp: StreamTransport) {.async, gcsafe.} =
|
||||
var wstream = newAsyncStreamWriter(transp)
|
||||
await wstream.write("Hello!")
|
||||
await wstream.finish()
|
||||
await wstream.closeWait()
|
||||
await transp.closeWait()
|
||||
server.stop()
|
||||
server.close()
|
||||
handlerWait.complete()
|
||||
|
||||
var server = createStreamServer(address, serveClient, {ReuseAddr})
|
||||
server.start()
|
||||
|
||||
let ma: MultiAddress = MultiAddress.init(server.sock.getLocalAddress()).tryGet()
|
||||
let transport: TcpTransport = TcpTransport.init()
|
||||
let conn = await transport.dial(ma)
|
||||
asyncTest "test listener: handle read":
|
||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
let handlerWait = newFuture[void]()
|
||||
proc connHandler(conn: Connection) {.async, gcsafe.} =
|
||||
var msg = newSeq[byte](6)
|
||||
await conn.readExactly(addr msg[0], 6)
|
||||
result = string.fromBytes(msg) == "Hello!"
|
||||
|
||||
await handlerWait.wait(5000.millis) # when no issues will not wait that long!
|
||||
|
||||
check string.fromBytes(msg) == "Hello!"
|
||||
await conn.close()
|
||||
await transport.close()
|
||||
handlerWait.complete()
|
||||
|
||||
let transport: TcpTransport = TcpTransport.init()
|
||||
asyncCheck await transport.listen(ma, connHandler)
|
||||
let streamTransport: StreamTransport = await connect(transport.ma)
|
||||
let sent = await streamTransport.write("Hello!", 6)
|
||||
|
||||
await handlerWait.wait(5000.millis) # when no issues will not wait that long!
|
||||
await streamTransport.closeWait()
|
||||
await transport.close()
|
||||
|
||||
check sent == 6
|
||||
|
||||
asyncTest "test dialer: handle write":
|
||||
let address = initTAddress("0.0.0.0:0")
|
||||
let handlerWait = newFuture[void]()
|
||||
proc serveClient(server: StreamServer,
|
||||
transp: StreamTransport) {.async, gcsafe.} =
|
||||
var wstream = newAsyncStreamWriter(transp)
|
||||
await wstream.write("Hello!")
|
||||
await wstream.finish()
|
||||
await wstream.closeWait()
|
||||
await transp.closeWait()
|
||||
server.stop()
|
||||
server.close()
|
||||
await server.join()
|
||||
handlerWait.complete()
|
||||
|
||||
check:
|
||||
waitFor(testDialer(initTAddress("0.0.0.0:0"))) == true
|
||||
var server = createStreamServer(address, serveClient, {ReuseAddr})
|
||||
server.start()
|
||||
|
||||
test "test dialer: handle write":
|
||||
proc testDialer(address: TransportAddress): Future[bool] {.async, gcsafe.} =
|
||||
let handlerWait = newFuture[void]()
|
||||
proc serveClient(server: StreamServer,
|
||||
transp: StreamTransport) {.async, gcsafe.} =
|
||||
var rstream = newAsyncStreamReader(transp)
|
||||
let msg = await rstream.read(6)
|
||||
check string.fromBytes(msg) == "Hello!"
|
||||
let ma: MultiAddress = MultiAddress.init(server.sock.getLocalAddress()).tryGet()
|
||||
let transport: TcpTransport = TcpTransport.init()
|
||||
let conn = await transport.dial(ma)
|
||||
var msg = newSeq[byte](6)
|
||||
await conn.readExactly(addr msg[0], 6)
|
||||
check string.fromBytes(msg) == "Hello!"
|
||||
|
||||
await rstream.closeWait()
|
||||
await transp.closeWait()
|
||||
server.stop()
|
||||
server.close()
|
||||
handlerWait.complete()
|
||||
await handlerWait.wait(5000.millis) # when no issues will not wait that long!
|
||||
|
||||
var server = createStreamServer(address, serveClient, {ReuseAddr})
|
||||
server.start()
|
||||
await conn.close()
|
||||
await transport.close()
|
||||
|
||||
let ma: MultiAddress = MultiAddress.init(server.sock.getLocalAddress()).tryGet()
|
||||
let transport: TcpTransport = TcpTransport.init()
|
||||
let conn = await transport.dial(ma)
|
||||
server.stop()
|
||||
server.close()
|
||||
await server.join()
|
||||
|
||||
asyncTest "test dialer: handle write":
|
||||
let address = initTAddress("0.0.0.0:0")
|
||||
let handlerWait = newFuture[void]()
|
||||
proc serveClient(server: StreamServer,
|
||||
transp: StreamTransport) {.async, gcsafe.} =
|
||||
var rstream = newAsyncStreamReader(transp)
|
||||
let msg = await rstream.read(6)
|
||||
check string.fromBytes(msg) == "Hello!"
|
||||
|
||||
await rstream.closeWait()
|
||||
await transp.closeWait()
|
||||
server.stop()
|
||||
server.close()
|
||||
handlerWait.complete()
|
||||
|
||||
var server = createStreamServer(address, serveClient, {ReuseAddr})
|
||||
server.start()
|
||||
|
||||
let ma: MultiAddress = MultiAddress.init(server.sock.getLocalAddress()).tryGet()
|
||||
let transport: TcpTransport = TcpTransport.init()
|
||||
let conn = await transport.dial(ma)
|
||||
await conn.write(cstring("Hello!"), 6)
|
||||
|
||||
await handlerWait.wait(5000.millis) # when no issues will not wait that long!
|
||||
await conn.close()
|
||||
await transport.close()
|
||||
|
||||
server.stop()
|
||||
server.close()
|
||||
await server.join()
|
||||
|
||||
asyncTest "e2e: handle write":
|
||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
let handlerWait = newFuture[void]()
|
||||
proc connHandler(conn: Connection) {.async, gcsafe.} =
|
||||
await conn.write(cstring("Hello!"), 6)
|
||||
result = true
|
||||
|
||||
await handlerWait.wait(5000.millis) # when no issues will not wait that long!
|
||||
|
||||
await conn.close()
|
||||
await transport.close()
|
||||
handlerWait.complete()
|
||||
|
||||
server.stop()
|
||||
server.close()
|
||||
await server.join()
|
||||
check:
|
||||
waitFor(testDialer(initTAddress("0.0.0.0:0"))) == true
|
||||
let transport1: TcpTransport = TcpTransport.init()
|
||||
asyncCheck transport1.listen(ma, connHandler)
|
||||
|
||||
test "e2e: handle write":
|
||||
proc testListenerDialer(): Future[bool] {.async.} =
|
||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
let handlerWait = newFuture[void]()
|
||||
proc connHandler(conn: Connection) {.async, gcsafe.} =
|
||||
await conn.write(cstring("Hello!"), 6)
|
||||
await conn.close()
|
||||
handlerWait.complete()
|
||||
let transport2: TcpTransport = TcpTransport.init()
|
||||
let conn = await transport2.dial(transport1.ma)
|
||||
var msg = newSeq[byte](6)
|
||||
await conn.readExactly(addr msg[0], 6)
|
||||
|
||||
let transport1: TcpTransport = TcpTransport.init()
|
||||
asyncCheck transport1.listen(ma, connHandler)
|
||||
await handlerWait.wait(5000.millis) # when no issues will not wait that long!
|
||||
|
||||
let transport2: TcpTransport = TcpTransport.init()
|
||||
let conn = await transport2.dial(transport1.ma)
|
||||
await conn.close()
|
||||
await transport2.close()
|
||||
await transport1.close()
|
||||
|
||||
check string.fromBytes(msg) == "Hello!"
|
||||
|
||||
asyncTest "e2e: handle read":
|
||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
let handlerWait = newFuture[void]()
|
||||
proc connHandler(conn: Connection) {.async, gcsafe.} =
|
||||
var msg = newSeq[byte](6)
|
||||
await conn.readExactly(addr msg[0], 6)
|
||||
|
||||
await handlerWait.wait(5000.millis) # when no issues will not wait that long!
|
||||
|
||||
check string.fromBytes(msg) == "Hello!"
|
||||
await conn.close()
|
||||
await transport2.close()
|
||||
await transport1.close()
|
||||
handlerWait.complete()
|
||||
|
||||
result = string.fromBytes(msg) == "Hello!"
|
||||
let transport1: TcpTransport = TcpTransport.init()
|
||||
asyncCheck transport1.listen(ma, connHandler)
|
||||
|
||||
check:
|
||||
waitFor(testListenerDialer()) == true
|
||||
let transport2: TcpTransport = TcpTransport.init()
|
||||
let conn = await transport2.dial(transport1.ma)
|
||||
await conn.write(cstring("Hello!"), 6)
|
||||
|
||||
test "e2e: handle read":
|
||||
proc testListenerDialer(): Future[bool] {.async.} =
|
||||
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0").tryGet()
|
||||
let handlerWait = newFuture[void]()
|
||||
proc connHandler(conn: Connection) {.async, gcsafe.} =
|
||||
var msg = newSeq[byte](6)
|
||||
await conn.readExactly(addr msg[0], 6)
|
||||
check string.fromBytes(msg) == "Hello!"
|
||||
await conn.close()
|
||||
handlerWait.complete()
|
||||
await handlerWait.wait(5000.millis) # when no issues will not wait that long!
|
||||
|
||||
let transport1: TcpTransport = TcpTransport.init()
|
||||
asyncCheck transport1.listen(ma, connHandler)
|
||||
|
||||
let transport2: TcpTransport = TcpTransport.init()
|
||||
let conn = await transport2.dial(transport1.ma)
|
||||
await conn.write(cstring("Hello!"), 6)
|
||||
|
||||
await handlerWait.wait(5000.millis) # when no issues will not wait that long!
|
||||
|
||||
await conn.close()
|
||||
await transport2.close()
|
||||
await transport1.close()
|
||||
result = true
|
||||
|
||||
check:
|
||||
waitFor(testListenerDialer()) == true
|
||||
await conn.close()
|
||||
await transport2.close()
|
||||
await transport1.close()
|
||||
|
|
Loading…
Reference in New Issue