2024-04-15 13:28:35 +00:00
|
|
|
{.used.}
|
|
|
|
|
|
|
|
import
|
|
|
|
std/[options, strscans],
|
|
|
|
testutils/unittests,
|
|
|
|
chronicles,
|
|
|
|
chronos,
|
|
|
|
libp2p/crypto/crypto
|
|
|
|
|
|
|
|
import
|
2024-07-05 22:03:38 +00:00
|
|
|
waku/[
|
2024-04-15 13:28:35 +00:00
|
|
|
node/peer_manager,
|
2024-07-16 13:46:21 +00:00
|
|
|
common/rate_limit/setting,
|
2024-04-15 13:28:35 +00:00
|
|
|
waku_core,
|
|
|
|
waku_lightpush,
|
|
|
|
waku_lightpush/client,
|
|
|
|
waku_lightpush/common,
|
|
|
|
waku_lightpush/protocol_metrics,
|
|
|
|
waku_lightpush/rpc,
|
|
|
|
waku_lightpush/rpc_codec,
|
|
|
|
],
|
|
|
|
../testlib/[assertions, wakucore, testasync, futures, testutils],
|
|
|
|
./lightpush_utils,
|
|
|
|
../resources/[pubsub_topics, content_topics, payloads]
|
|
|
|
|
|
|
|
suite "Rate limited push service":
|
|
|
|
asyncTest "push message with rate limit not violated":
|
|
|
|
## Setup
|
|
|
|
let
|
|
|
|
serverSwitch = newTestSwitch()
|
|
|
|
clientSwitch = newTestSwitch()
|
|
|
|
|
|
|
|
await allFutures(serverSwitch.start(), clientSwitch.start())
|
|
|
|
|
|
|
|
## Given
|
|
|
|
var handlerFuture = newFuture[(string, WakuMessage)]()
|
|
|
|
let handler: PushMessageHandler = proc(
|
|
|
|
peer: PeerId, pubsubTopic: PubsubTopic, message: WakuMessage
|
|
|
|
): Future[WakuLightPushResult[void]] {.async.} =
|
|
|
|
handlerFuture.complete((pubsubTopic, message))
|
|
|
|
return ok()
|
|
|
|
|
|
|
|
let
|
|
|
|
tokenPeriod = 500.millis
|
|
|
|
server =
|
|
|
|
await newTestWakuLightpushNode(serverSwitch, handler, some((3, tokenPeriod)))
|
|
|
|
client = newTestWakuLightpushClient(clientSwitch)
|
|
|
|
|
|
|
|
let serverPeerId = serverSwitch.peerInfo.toRemotePeerInfo()
|
|
|
|
|
|
|
|
let sendMsgProc = proc(): Future[void] {.async.} =
|
|
|
|
let message = fakeWakuMessage()
|
|
|
|
|
|
|
|
handlerFuture = newFuture[(string, WakuMessage)]()
|
|
|
|
let requestRes =
|
|
|
|
await client.publish(DefaultPubsubTopic, message, peer = serverPeerId)
|
|
|
|
|
|
|
|
check await handlerFuture.withTimeout(50.millis)
|
|
|
|
|
|
|
|
assert requestRes.isOk(), requestRes.error
|
|
|
|
check handlerFuture.finished()
|
|
|
|
|
|
|
|
let (handledMessagePubsubTopic, handledMessage) = handlerFuture.read()
|
|
|
|
|
|
|
|
check:
|
|
|
|
handledMessagePubsubTopic == DefaultPubsubTopic
|
|
|
|
handledMessage == message
|
|
|
|
|
|
|
|
let waitInBetweenFor = 20.millis
|
|
|
|
|
|
|
|
# Test cannot be too explicit about the time when the TokenBucket resets
|
|
|
|
# the internal timer, although in normal use there is no use case to care about it.
|
|
|
|
var firstWaitExtend = 300.millis
|
|
|
|
|
|
|
|
for runCnt in 0 ..< 3:
|
|
|
|
let startTime = Moment.now()
|
|
|
|
for testCnt in 0 ..< 3:
|
|
|
|
await sendMsgProc()
|
|
|
|
await sleepAsync(20.millis)
|
|
|
|
|
|
|
|
var endTime = Moment.now()
|
|
|
|
var elapsed: Duration = (endTime - startTime)
|
|
|
|
await sleepAsync(tokenPeriod - elapsed + firstWaitExtend)
|
|
|
|
firstWaitEXtend = 100.millis
|
|
|
|
|
|
|
|
## Cleanup
|
|
|
|
await allFutures(clientSwitch.stop(), serverSwitch.stop())
|
|
|
|
|
|
|
|
asyncTest "push message with rate limit reject":
|
|
|
|
## Setup
|
|
|
|
let
|
|
|
|
serverSwitch = newTestSwitch()
|
|
|
|
clientSwitch = newTestSwitch()
|
|
|
|
|
|
|
|
await allFutures(serverSwitch.start(), clientSwitch.start())
|
|
|
|
|
|
|
|
## Given
|
|
|
|
var handlerFuture = newFuture[(string, WakuMessage)]()
|
|
|
|
let handler = proc(
|
|
|
|
peer: PeerId, pubsubTopic: PubsubTopic, message: WakuMessage
|
|
|
|
): Future[WakuLightPushResult[void]] {.async.} =
|
|
|
|
handlerFuture.complete((pubsubTopic, message))
|
|
|
|
return ok()
|
|
|
|
|
|
|
|
let
|
|
|
|
server =
|
|
|
|
await newTestWakuLightpushNode(serverSwitch, handler, some((3, 500.millis)))
|
|
|
|
client = newTestWakuLightpushClient(clientSwitch)
|
|
|
|
|
|
|
|
let serverPeerId = serverSwitch.peerInfo.toRemotePeerInfo()
|
|
|
|
let topic = DefaultPubsubTopic
|
|
|
|
|
|
|
|
let successProc = proc(): Future[void] {.async.} =
|
|
|
|
let message = fakeWakuMessage()
|
|
|
|
handlerFuture = newFuture[(string, WakuMessage)]()
|
|
|
|
let requestRes =
|
|
|
|
await client.publish(DefaultPubsubTopic, message, peer = serverPeerId)
|
|
|
|
discard await handlerFuture.withTimeout(10.millis)
|
|
|
|
|
|
|
|
check:
|
|
|
|
requestRes.isOk()
|
|
|
|
handlerFuture.finished()
|
|
|
|
let (handledMessagePubsubTopic, handledMessage) = handlerFuture.read()
|
|
|
|
check:
|
|
|
|
handledMessagePubsubTopic == DefaultPubsubTopic
|
|
|
|
handledMessage == message
|
|
|
|
|
|
|
|
let rejectProc = proc(): Future[void] {.async.} =
|
|
|
|
let message = fakeWakuMessage()
|
|
|
|
handlerFuture = newFuture[(string, WakuMessage)]()
|
|
|
|
let requestRes =
|
|
|
|
await client.publish(DefaultPubsubTopic, message, peer = serverPeerId)
|
|
|
|
discard await handlerFuture.withTimeout(10.millis)
|
|
|
|
|
|
|
|
check:
|
|
|
|
requestRes.isErr()
|
|
|
|
requestRes.error == "TOO_MANY_REQUESTS"
|
|
|
|
|
|
|
|
for testCnt in 0 .. 2:
|
|
|
|
await successProc()
|
|
|
|
await sleepAsync(20.millis)
|
|
|
|
|
|
|
|
await rejectProc()
|
|
|
|
|
|
|
|
await sleepAsync(500.millis)
|
|
|
|
|
|
|
|
## next one shall succeed due to the rate limit time window has passed
|
|
|
|
await successProc()
|
|
|
|
|
|
|
|
## Cleanup
|
|
|
|
await allFutures(clientSwitch.stop(), serverSwitch.stop())
|