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