2022-10-03 22:00:00 +00:00
|
|
|
{.used.}
|
|
|
|
|
2023-05-18 08:24:17 +00:00
|
|
|
# Nim-Libp2p
|
|
|
|
# Copyright (c) 2023 Status Research & Development GmbH
|
|
|
|
# Licensed under either of
|
|
|
|
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
|
|
|
|
# * MIT license ([LICENSE-MIT](LICENSE-MIT))
|
|
|
|
# at your option.
|
|
|
|
# This file may not be copied, modified, or distributed except according to
|
|
|
|
# those terms.
|
|
|
|
|
2022-10-03 22:00:00 +00:00
|
|
|
import options, chronos, sets
|
|
|
|
import
|
|
|
|
../libp2p/[
|
|
|
|
protocols/rendezvous,
|
|
|
|
switch,
|
|
|
|
builders,
|
|
|
|
discovery/discoverymngr,
|
|
|
|
discovery/rendezvousinterface,
|
|
|
|
]
|
2024-08-14 15:39:32 +00:00
|
|
|
import ./helpers, ./asyncunit, ./utils/[async, assertions, futures]
|
2022-10-03 22:00:00 +00:00
|
|
|
|
|
|
|
proc createSwitch(rdv: RendezVous = RendezVous.new()): Switch =
|
|
|
|
SwitchBuilder
|
|
|
|
.new()
|
|
|
|
.withRng(newRng())
|
|
|
|
.withAddresses(@[MultiAddress.init("/ip4/0.0.0.0/tcp/0").tryGet()])
|
|
|
|
.withTcpTransport()
|
|
|
|
.withMplex()
|
|
|
|
.withNoise()
|
|
|
|
.withRendezVous(rdv)
|
|
|
|
.build()
|
|
|
|
|
|
|
|
suite "Discovery":
|
2024-08-07 19:06:13 +00:00
|
|
|
const
|
|
|
|
namespace = "foo"
|
|
|
|
rdvNamespace = RdvNamespace(namespace)
|
|
|
|
|
|
|
|
var
|
|
|
|
rdvA {.threadvar.}: RendezVous
|
|
|
|
rdvB {.threadvar.}: RendezVous
|
|
|
|
rdvRemote {.threadvar.}: RendezVous
|
|
|
|
clientA {.threadvar.}: Switch
|
|
|
|
clientB {.threadvar.}: Switch
|
|
|
|
remoteNode {.threadvar.}: Switch
|
|
|
|
dmA {.threadvar.}: DiscoveryManager
|
|
|
|
dmB {.threadvar.}: DiscoveryManager
|
|
|
|
|
|
|
|
asyncSetup:
|
|
|
|
rdvA = RendezVous.new()
|
|
|
|
rdvB = RendezVous.new()
|
|
|
|
rdvRemote = RendezVous.new()
|
|
|
|
clientA = createSwitch(rdvA)
|
|
|
|
clientB = createSwitch(rdvB)
|
|
|
|
remoteNode = createSwitch(rdvRemote)
|
|
|
|
dmA = DiscoveryManager()
|
|
|
|
dmB = DiscoveryManager()
|
|
|
|
|
2022-10-03 22:00:00 +00:00
|
|
|
dmA.add(RendezVousInterface.new(rdvA, ttr = 500.milliseconds))
|
|
|
|
dmB.add(RendezVousInterface.new(rdvB))
|
|
|
|
await allFutures(clientA.start(), clientB.start(), remoteNode.start())
|
|
|
|
|
|
|
|
await clientB.connect(remoteNode.peerInfo.peerId, remoteNode.peerInfo.addrs)
|
|
|
|
await clientA.connect(remoteNode.peerInfo.peerId, remoteNode.peerInfo.addrs)
|
|
|
|
|
2024-08-07 19:06:13 +00:00
|
|
|
asyncTeardown:
|
|
|
|
await allFutures(clientA.stop(), clientB.stop(), remoteNode.stop())
|
|
|
|
checkTrackers()
|
|
|
|
|
|
|
|
asyncTest "RendezVous test":
|
|
|
|
dmB.advertise(rdvNamespace)
|
2022-10-03 22:00:00 +00:00
|
|
|
|
|
|
|
let
|
2024-08-07 19:06:13 +00:00
|
|
|
query = dmA.request(rdvNamespace)
|
2022-10-03 22:00:00 +00:00
|
|
|
res = await query.getPeer()
|
|
|
|
check:
|
|
|
|
res{PeerId}.get() == clientB.peerInfo.peerId
|
|
|
|
res[PeerId] == clientB.peerInfo.peerId
|
|
|
|
res.getAll(PeerId) == @[clientB.peerInfo.peerId]
|
|
|
|
toHashSet(res.getAll(MultiAddress)) == toHashSet(clientB.peerInfo.addrs)
|
2024-08-07 19:06:42 +00:00
|
|
|
|
|
|
|
asyncTest "Subscribe and unsubscribe":
|
|
|
|
dmB.advertise(rdvNamespace)
|
|
|
|
let
|
|
|
|
query1 = dmA.request(rdvNamespace)
|
|
|
|
res1 = await query1.getPeer().waitForResult(1.seconds)
|
|
|
|
|
|
|
|
res1.assertIsOk()
|
|
|
|
check res1.value{PeerId}.get() == clientB.peerInfo.peerId
|
|
|
|
|
|
|
|
await rdvB.unsubscribe(namespace)
|
|
|
|
var
|
|
|
|
query2 = dmA.request(rdvNamespace)
|
|
|
|
res2 = await query2.getPeer().waitForResult(1.seconds)
|
|
|
|
|
|
|
|
res2.assertIsErr()
|
|
|
|
|
2024-08-14 15:39:32 +00:00
|
|
|
asyncTest "Frequent sub/unsub":
|
2024-08-07 19:06:42 +00:00
|
|
|
for i in 0 ..< 10:
|
|
|
|
dmB.advertise(rdvNamespace)
|
|
|
|
let
|
|
|
|
query1 = dmA.request(rdvNamespace)
|
|
|
|
res1 = await query1.getPeer().waitForResult(1.seconds)
|
|
|
|
|
|
|
|
res1.assertIsOk()
|
|
|
|
check res1.value{PeerId}.get() == clientB.peerInfo.peerId
|
|
|
|
|
|
|
|
await rdvB.unsubscribe(namespace)
|
2024-08-26 17:37:04 +00:00
|
|
|
await sleepAsync(DURATION_TIMEOUT_EXTENDED)
|
2024-08-07 19:06:42 +00:00
|
|
|
var
|
|
|
|
query2 = dmA.request(rdvNamespace)
|
|
|
|
res2 = await query2.getPeer().waitForResult(1.seconds)
|
|
|
|
|
|
|
|
res2.assertIsErr()
|
2024-08-14 15:39:32 +00:00
|
|
|
|
|
|
|
asyncTest "Frequent sub/unsub with multiple clients":
|
|
|
|
let
|
|
|
|
rdvC = RendezVous.new()
|
|
|
|
clientC = createSwitch(rdvC)
|
|
|
|
dmC = DiscoveryManager()
|
|
|
|
|
|
|
|
dmC.add(RendezVousInterface.new(rdvC))
|
|
|
|
await clientC.start()
|
|
|
|
|
|
|
|
await clientC.connect(remoteNode.peerInfo.peerId, remoteNode.peerInfo.addrs)
|
|
|
|
|
|
|
|
for i in 0 ..< 10:
|
|
|
|
dmB.advertise(rdvNamespace)
|
|
|
|
dmC.advertise(rdvNamespace)
|
|
|
|
let peerIds =
|
|
|
|
@[clientB.peerInfo.peerId, clientC.peerInfo.peerId]
|
|
|
|
# peerIds = @[clientB.peerInfo.peerId]
|
|
|
|
|
|
|
|
let
|
|
|
|
query1 = dmA.request(rdvNamespace)
|
|
|
|
res1 = await query1.getPeer().waitForResult(1.seconds)
|
|
|
|
|
|
|
|
res1.assertIsOk()
|
|
|
|
check res1.value{PeerId}.get() in peerIds
|
|
|
|
|
|
|
|
await rdvB.unsubscribe(namespace)
|
|
|
|
await rdvC.unsubscribe(namespace)
|
2024-08-26 17:37:04 +00:00
|
|
|
await sleepAsync(DURATION_TIMEOUT_EXTENDED)
|
2024-08-14 15:39:32 +00:00
|
|
|
var
|
|
|
|
query2 = dmA.request(rdvNamespace)
|
|
|
|
res2 = await query2.getPeer().waitForResult(1.seconds)
|
|
|
|
|
|
|
|
res2.assertIsErr()
|
|
|
|
|
|
|
|
await clientC.stop()
|