2023-02-10 14:17:50 +00:00
|
|
|
{.used.}
|
|
|
|
|
|
|
|
import
|
|
|
|
std/[options, sequtils, strutils],
|
|
|
|
stew/shims/net as stewNet,
|
|
|
|
testutils/unittests,
|
|
|
|
chronicles,
|
|
|
|
chronos,
|
|
|
|
libp2p/protocols/pubsub/pubsub,
|
|
|
|
libp2p/protocols/pubsub/rpc/messages
|
|
|
|
import
|
|
|
|
../../../waku/v2/node/peer_manager,
|
|
|
|
../../../waku/v2/protocol/waku_message,
|
|
|
|
../../../waku/v2/protocol/waku_relay,
|
2023-02-13 10:43:49 +00:00
|
|
|
../testlib/common,
|
2023-04-05 14:01:51 +00:00
|
|
|
../testlib/wakucore
|
2023-02-10 14:17:50 +00:00
|
|
|
|
|
|
|
|
|
|
|
proc noopRawHandler(): PubsubRawHandler =
|
|
|
|
var handler: PubsubRawHandler
|
|
|
|
handler = proc(pubsubTopic: PubsubTopic, data: seq[byte]): Future[void] {.gcsafe, noSideEffect.} = discard
|
|
|
|
handler
|
|
|
|
|
|
|
|
|
|
|
|
proc newTestWakuRelay(switch = newTestSwitch(), self = true): Future[WakuRelay] {.async.} =
|
|
|
|
let proto = WakuRelay.new(switch, triggerSelf = self).tryGet()
|
|
|
|
await proto.start()
|
|
|
|
|
|
|
|
let protocolMatcher = proc(proto: string): bool {.gcsafe.} =
|
|
|
|
return proto.startsWith(WakuRelayCodec)
|
|
|
|
|
|
|
|
switch.mount(proto, protocolMatcher)
|
|
|
|
|
|
|
|
return proto
|
|
|
|
|
|
|
|
|
|
|
|
suite "Waku Relay":
|
|
|
|
|
|
|
|
asyncTest "subscribe and add handler to topics":
|
|
|
|
## Setup
|
|
|
|
let nodeA = await newTestWakuRelay()
|
|
|
|
|
|
|
|
## Given
|
|
|
|
let
|
|
|
|
networkA = "test-network1"
|
|
|
|
networkB = "test-network2"
|
|
|
|
|
|
|
|
## when
|
|
|
|
nodeA.subscribe(networkA, noopRawHandler())
|
|
|
|
nodeA.subscribe(networkB, noopRawHandler())
|
|
|
|
|
|
|
|
## Then
|
|
|
|
check:
|
|
|
|
nodeA.isSubscribed(networkA)
|
|
|
|
nodeA.isSubscribed(networkB)
|
|
|
|
|
|
|
|
let subscribedTopics = toSeq(nodeA.subscribedTopics)
|
|
|
|
check:
|
|
|
|
subscribedTopics.len == 2
|
|
|
|
subscribedTopics.contains(networkA)
|
|
|
|
subscribedTopics.contains(networkB)
|
|
|
|
|
|
|
|
## Cleanup
|
|
|
|
await nodeA.stop()
|
|
|
|
|
|
|
|
asyncTest "unsubscribe all handlers from topic":
|
|
|
|
## Setup
|
|
|
|
let nodeA = await newTestWakuRelay()
|
|
|
|
|
|
|
|
## Given
|
|
|
|
let
|
|
|
|
networkA = "test-network1"
|
|
|
|
networkB = "test-network2"
|
|
|
|
networkC = "test-network3"
|
|
|
|
|
|
|
|
nodeA.subscribe(networkA, noopRawHandler())
|
|
|
|
nodeA.subscribe(networkB, noopRawHandler())
|
|
|
|
nodeA.subscribe(networkC, noopRawHandler())
|
|
|
|
|
|
|
|
let topics = toSeq(nodeA.subscribedTopics)
|
|
|
|
require:
|
|
|
|
topics.len == 3
|
|
|
|
topics.contains(networkA)
|
|
|
|
topics.contains(networkB)
|
|
|
|
topics.contains(networkC)
|
|
|
|
|
|
|
|
## When
|
|
|
|
nodeA.unsubscribeAll(networkA)
|
|
|
|
|
|
|
|
## Then
|
|
|
|
check:
|
|
|
|
nodeA.isSubscribed(networkB)
|
|
|
|
nodeA.isSubscribed(networkC)
|
|
|
|
not nodeA.isSubscribed(networkA)
|
|
|
|
|
|
|
|
let subscribedTopics = toSeq(nodeA.subscribedTopics)
|
|
|
|
check:
|
|
|
|
subscribedTopics.len == 2
|
|
|
|
subscribedTopics.contains(networkB)
|
|
|
|
subscribedTopics.contains(networkC)
|
|
|
|
not subscribedTopics.contains(networkA)
|
|
|
|
|
|
|
|
## Cleanup
|
|
|
|
await nodeA.stop()
|
|
|
|
|
|
|
|
asyncTest "publish a message into a topic":
|
|
|
|
## Setup
|
|
|
|
let
|
|
|
|
srcSwitch = newTestSwitch()
|
|
|
|
srcPeerManager = PeerManager.new(srcSwitch)
|
|
|
|
srcNode = await newTestWakuRelay(srcSwitch)
|
|
|
|
dstSwitch = newTestSwitch()
|
|
|
|
dstPeerManager = PeerManager.new(dstSwitch)
|
|
|
|
dstNode = await newTestWakuRelay(dstSwitch)
|
|
|
|
|
|
|
|
await allFutures(srcSwitch.start(), dstSwitch.start())
|
|
|
|
|
|
|
|
let dstPeerInfo = dstPeerManager.switch.peerInfo.toRemotePeerInfo()
|
2023-03-28 11:29:48 +00:00
|
|
|
let connOk = await srcPeerManager.connectRelay(dstPeerInfo)
|
2023-02-10 14:17:50 +00:00
|
|
|
require:
|
2023-03-28 11:29:48 +00:00
|
|
|
connOk == true
|
2023-02-10 14:17:50 +00:00
|
|
|
|
|
|
|
## Given
|
|
|
|
let networkTopic = "test-network1"
|
|
|
|
let message = fakeWakuMessage()
|
|
|
|
|
|
|
|
# Self subscription (triggerSelf = true)
|
|
|
|
let srcSubsFut = newFuture[(PubsubTopic, WakuMessage)]()
|
|
|
|
proc srcSubsHandler(topic: PubsubTopic, message: WakuMessage) {.async, gcsafe.} =
|
|
|
|
srcSubsFut.complete((topic, message))
|
|
|
|
|
|
|
|
srcNode.subscribe(networkTopic, srcSubsHandler)
|
|
|
|
|
|
|
|
# Subscription
|
|
|
|
let dstSubsFut = newFuture[(PubsubTopic, WakuMessage)]()
|
|
|
|
proc dstSubsHandler(topic: PubsubTopic, message: WakuMessage) {.async, gcsafe.} =
|
|
|
|
dstSubsFut.complete((topic, message))
|
|
|
|
|
|
|
|
dstNode.subscribe(networkTopic, dstSubsHandler)
|
|
|
|
|
|
|
|
await sleepAsync(500.millis)
|
|
|
|
|
|
|
|
## When
|
|
|
|
discard await srcNode.publish(networkTopic, message)
|
|
|
|
|
|
|
|
## Then
|
|
|
|
require:
|
|
|
|
await srcSubsFut.withTimeout(5.seconds)
|
|
|
|
await dstSubsFut.withTimeout(5.seconds)
|
|
|
|
|
|
|
|
let (srcTopic, srcMsg) = srcSubsFut.read()
|
|
|
|
check:
|
|
|
|
srcTopic == networkTopic
|
|
|
|
srcMsg == message
|
|
|
|
|
|
|
|
let (dstTopic, dstMsg) = dstSubsFut.read()
|
|
|
|
check:
|
|
|
|
dstTopic == networkTopic
|
|
|
|
dstMsg == message
|
|
|
|
|
|
|
|
## Cleanup
|
|
|
|
await allFutures(srcSwitch.stop(), dstSwitch.stop())
|
|
|
|
|
|
|
|
asyncTest "content topic validator as a message subscription filter":
|
|
|
|
## Setup
|
|
|
|
let
|
|
|
|
srcSwitch = newTestSwitch()
|
|
|
|
srcPeerManager = PeerManager.new(srcSwitch)
|
|
|
|
srcNode = await newTestWakuRelay(srcSwitch)
|
|
|
|
dstSwitch = newTestSwitch()
|
|
|
|
dstPeerManager = PeerManager.new(dstSwitch)
|
|
|
|
dstNode = await newTestWakuRelay(dstSwitch)
|
|
|
|
|
|
|
|
await allFutures(srcSwitch.start(), dstSwitch.start())
|
|
|
|
|
|
|
|
let dstPeerInfo = dstPeerManager.switch.peerInfo.toRemotePeerInfo()
|
2023-03-28 11:29:48 +00:00
|
|
|
let connOk = await srcPeerManager.connectRelay(dstPeerInfo)
|
2023-02-10 14:17:50 +00:00
|
|
|
require:
|
2023-03-28 11:29:48 +00:00
|
|
|
connOk == true
|
2023-02-10 14:17:50 +00:00
|
|
|
|
|
|
|
## Given
|
|
|
|
let networkTopic = "test-network1"
|
|
|
|
let contentTopic = "test-content1"
|
|
|
|
|
|
|
|
let message = fakeWakuMessage(contentTopic=contentTopic)
|
|
|
|
let messages = @[
|
|
|
|
fakeWakuMessage(contentTopic="any"),
|
|
|
|
fakeWakuMessage(contentTopic="any"),
|
|
|
|
fakeWakuMessage(contentTopic="any"),
|
|
|
|
message,
|
|
|
|
fakeWakuMessage(contentTopic="any"),
|
|
|
|
]
|
|
|
|
|
|
|
|
# Subscription
|
|
|
|
let dstSubsFut = newFuture[(PubsubTopic, WakuMessage)]()
|
|
|
|
proc dstSubsHandler(topic: PubsubTopic, message: WakuMessage) {.async, gcsafe.} =
|
|
|
|
dstSubsFut.complete((topic, message))
|
|
|
|
|
|
|
|
dstNode.subscribe(networkTopic, dstSubsHandler)
|
|
|
|
|
|
|
|
await sleepAsync(500.millis)
|
|
|
|
|
|
|
|
# Validator
|
|
|
|
proc validator(topic: PubsubTopic, msg: Message): Future[ValidationResult] {.async.} =
|
|
|
|
let msg = WakuMessage.decode(msg.data)
|
|
|
|
if msg.isErr():
|
|
|
|
return ValidationResult.Ignore
|
|
|
|
|
|
|
|
# only relay messages with contentTopic1
|
|
|
|
if msg.value.contentTopic != contentTopic:
|
|
|
|
return ValidationResult.Reject
|
|
|
|
|
|
|
|
return ValidationResult.Accept
|
|
|
|
|
|
|
|
dstNode.addValidator(networkTopic, validator)
|
|
|
|
|
|
|
|
## When
|
|
|
|
for msg in messages:
|
|
|
|
discard await srcNode.publish(networkTopic, msg)
|
|
|
|
|
|
|
|
## Then
|
|
|
|
require:
|
|
|
|
await dstSubsFut.withTimeout(5.seconds)
|
|
|
|
|
|
|
|
let (dstTopic, dstMsg) = dstSubsFut.read()
|
|
|
|
check:
|
|
|
|
dstTopic == networkTopic
|
|
|
|
dstMsg == message
|
|
|
|
|
|
|
|
## Cleanup
|
|
|
|
await allFutures(srcSwitch.stop(), dstSwitch.stop())
|