nwaku/tests/v2/test_waku_store_queue.nim
G 21cac6d491
Refactoring timestamps (#842)
* Refactor timestamps type from float64 to int64 (milliseconds resolution)

* Revert epochs to float64

* Update 00002_addSenderTimeStamp.up.sql

* Update quicksim2.nim

* Add files via upload

* Delete 00003_convertTimestampsToInts.up.sql

* Add files via upload

* Rename 00003_convertTimestampsToInts.up.sql to 00003_addTimestampsToInts.up.sql

* Delete 00003_addTimestampsToInts.up.sql

* Rln-relay integration into chat2 (#835)

* adds ProofMetadata

* adds EPOCH_INTERVAL

* adds messageLog field

* adds updateLog, toEpoch, fromEpoch, getEpoch, compareTo

* adds unit test for toEpoch and fromEpoch

* adds unit test for Epoch comparison

* adds result codes for updateLog

* adds unit test for update log

* renames epoch related consts

* modifies updateLog with new return type and new logic of spam detection

* adds unit text for the modified updateLog

* changes max epoch gap type size

* splits updateLog into two procs isSpam and updateLog

* updates unittests

* fixes a bug, returns false when the message is not spam

* renames messageLog to nullifierLog

* renames isSpam to hasDuplicate

* updates the rln validator, adds comments

* adds appendRLNProof proc plus some code beatification

* unit test for validate message

* adds unhappy test to validateMessage unit test

* renames EPOCH_UNIT_SECONDS

* renames MAX_CLOCK_GAP_SECONDS

* WIP: integration test

* fixes compile errors

* sets a real epoch value

* updates on old unittests

* adds comments to the rln relay tests

* adds more comments

* makes rln import conditional

* adds todos

* adds more todos

* adds rln-relay mount process into chat2

* further todos

* logs contentTopic

* introduces rln relay configs

* changes default pubsub topic

* adds contentTopic config

* imports rln relay dependencies

* consolidates imports

* removes module identifier from ContentTopic

* adds contentTopic field

* adds contentTopic argument to mountRlnRelay calls

* appends rln proof to chat2 messages

* changes the default chat2 contentTopic

* adds missing content topic fields

* fixes a bug

* adds a new logic about empty content topics

* appends proof only when rln flag is active

* removes unnecessary todos

* fixes an indentation issue

* adds log messages

* verifies the proof against the concatenation of msg payload and content topic

* a bug fix

* removes duplicate epoch time calculation

* updates log level to trace

* updates default rln-relay content topic

* adds support for empty content topics

* updates changelog

* changelog updates

* removes a commented code block

* updates addRLNRelayValidator string doc

* Squashed commit of the following:

commit bc36c99ab202d07baa0a5f0100bd10d1d76fdfa1
Merge: dc2b2946 5a77d6e2
Author: G <28568419+s1fr0@users.noreply.github.com>
Date:   Sat Feb 5 01:10:06 2022 +0100

    Merge branch 'master' into int64-timestamps-ns

commit dc2b294667bb5770cc32b93cc560638cf5ce7087
Author: s1fr0 <28568419+s1fr0@users.noreply.github.com>
Date:   Sat Feb 5 00:24:45 2022 +0100

    Fix

commit f97b95a036a197938df38a5adaea46fca778016d
Author: s1fr0 <28568419+s1fr0@users.noreply.github.com>
Date:   Sat Feb 5 00:13:18 2022 +0100

    Missing import

commit 060c4f8d64e1b6e7c0593540fa8fa7f4cadf6df7
Author: s1fr0 <28568419+s1fr0@users.noreply.github.com>
Date:   Sat Feb 5 00:10:36 2022 +0100

    Fixed typo

commit 08ca99b6f692d3df6d4c7c2312c7cada05fc0041
Author: s1fr0 <28568419+s1fr0@users.noreply.github.com>
Date:   Fri Feb 4 23:59:20 2022 +0100

    Time util file

commit 2b5c360746990936dec256e90d08dae3c3e35a94
Author: s1fr0 <28568419+s1fr0@users.noreply.github.com>
Date:   Fri Feb 4 23:33:20 2022 +0100

    Moved time utility functions to utils/time

commit fdaf121f089aa011855303cc8dd1ce52aec506ad
Author: s1fr0 <28568419+s1fr0@users.noreply.github.com>
Date:   Fri Feb 4 23:10:25 2022 +0100

    Fix comment

commit c7e06ab4e7618d9a3fe8aa744dd48bf3f7d8754c
Author: s1fr0 <28568419+s1fr0@users.noreply.github.com>
Date:   Fri Feb 4 23:04:13 2022 +0100

    Restore previous migration script

commit 80282db1d79df676255d4b8e6e09d9f8a2b00fd3
Author: s1fr0 <28568419+s1fr0@users.noreply.github.com>
Date:   Fri Feb 4 22:54:15 2022 +0100

    Typo

commit b9d67f89b0eea11a8362dbb10b5f9d6894343352
Author: s1fr0 <28568419+s1fr0@users.noreply.github.com>
Date:   Fri Feb 4 22:49:29 2022 +0100

    Added utilities to get int64 nanosecond, microsecond, millisecond time resolution from float

commit 0130d496e694a01cfc9eeb90b7cbc77764490bf9
Author: s1fr0 <28568419+s1fr0@users.noreply.github.com>
Date:   Fri Feb 4 22:36:35 2022 +0100

    Switched to nanoseconds support.

* Update CHANGELOG.md

* Create 00003_convertTimestampsToInt64.up.sql

Migration script

* Moved migration script to right location

* Update waku_rln_relay_utils.nim

* Update waku_rln_relay_utils.nim

* Addressed reviewers' comments

* Update default fleet metrics dashboard (#844)

* Fix

* No need for float

* Aligning master to changes in PR

* Further fixes

Co-authored-by: Sanaz Taheri Boshrooyeh <35961250+staheri14@users.noreply.github.com>
Co-authored-by: Hanno Cornelius <68783915+jm-clius@users.noreply.github.com>
2022-02-17 16:00:15 +01:00

300 lines
10 KiB
Nim

{.used.}
import
std/sequtils,
testutils/unittests,
../../waku/v2/protocol/waku_store/waku_store_types,
../../waku/v2/utils/time
procSuite "Sorted store queue":
# Helper functions
proc genIndexedWakuMessage(i: int8): IndexedWakuMessage =
## Use i to generate an IndexedWakuMessage
var data {.noinit.}: array[32, byte]
for x in data.mitems: x = i.byte
return IndexedWakuMessage(msg: WakuMessage(payload: @[byte i], timestamp: Timestamp(i)),
index: Index(receiverTime: Timestamp(i), senderTime: Timestamp(i), digest: MDigest[256](data: data)))
# Test variables
let
capacity = 5
unsortedSet = [5,1,3,2,4]
var testStoreQueue = StoreQueueRef.new(capacity)
for i in unsortedSet:
discard testStoreQueue.add(genIndexedWakuMessage(i.int8))
test "Store queue can be created with limited capacity":
var stQ = StoreQueueRef.new(capacity)
check:
stQ.len == 0 # Empty when initialised
for i in 1..capacity: # Fill up the queue
check:
stQ.add(genIndexedWakuMessage(i.int8)).isOk()
check:
stQ.len == capacity
# Add one more. Capacity should not be exceeded.
check:
stQ.add(genIndexedWakuMessage(capacity.int8 + 1)).isOk()
check:
stQ.len == capacity
test "Store queue sort-on-insert works":
# Walk forward through the set and verify ascending order
var prevSmaller = genIndexedWakuMessage(min(unsortedSet).int8 - 1).index
for i in testStoreQueue.fwdIterator:
let (index, indexedWakuMessage) = i
check cmp(index, prevSmaller) > 0
prevSmaller = index
# Walk backward through the set and verify descending order
var prevLarger = genIndexedWakuMessage(max(unsortedSet).int8 + 1).index
for i in testStoreQueue.bwdIterator:
let (index, indexedWakuMessage) = i
check cmp(index, prevLarger) < 0
prevLarger = index
test "Can access first item from store queue":
let first = testStoreQueue.first()
check:
first.isOk()
first.get().msg.timestamp == Timestamp(1)
# Error condition
let emptyQ = StoreQueueRef.new(capacity)
check:
emptyQ.first().isErr()
test "Can access last item from store queue":
let last = testStoreQueue.last()
check:
last.isOk()
last.get().msg.timestamp == Timestamp(5)
# Error condition
let emptyQ = StoreQueueRef.new(capacity)
check:
emptyQ.last().isErr()
test "Store queue forward pagination works":
proc predicate(i: IndexedWakuMessage): bool = true # no filtering
var (res, pInfo, err) = testStoreQueue.getPage(predicate,
PagingInfo(pageSize: 3,
direction: PagingDirection.FORWARD))
check:
# First page
pInfo.pageSize == 3
pInfo.direction == PagingDirection.FORWARD
pInfo.cursor.senderTime == Timestamp(3)
err == HistoryResponseError.NONE
res.mapIt(it.timestamp.int) == @[1,2,3]
(res, pInfo, err) = testStoreQueue.getPage(predicate,
pInfo)
check:
# Second page
pInfo.pageSize == 2
pInfo.direction == PagingDirection.FORWARD
pInfo.cursor.senderTime == Timestamp(5)
err == HistoryResponseError.NONE
res.mapIt(it.timestamp.int) == @[4,5]
(res, pInfo, err) = testStoreQueue.getPage(predicate,
pInfo)
check:
# Empty last page
pInfo.pageSize == 0
pInfo.direction == PagingDirection.FORWARD
pInfo.cursor.senderTime == Timestamp(5)
err == HistoryResponseError.NONE
res.len == 0
test "Store queue backward pagination works":
proc predicate(i: IndexedWakuMessage): bool = true # no filtering
var (res, pInfo, err) = testStoreQueue.getPage(predicate,
PagingInfo(pageSize: 3,
direction: PagingDirection.BACKWARD))
check:
# First page
pInfo.pageSize == 3
pInfo.direction == PagingDirection.BACKWARD
pInfo.cursor.senderTime == Timestamp(3)
err == HistoryResponseError.NONE
res.mapIt(it.timestamp.int) == @[3,4,5]
(res, pInfo, err) = testStoreQueue.getPage(predicate,
pInfo)
check:
# Second page
pInfo.pageSize == 2
pInfo.direction == PagingDirection.BACKWARD
pInfo.cursor.senderTime == Timestamp(1)
err == HistoryResponseError.NONE
res.mapIt(it.timestamp.int) == @[1,2]
(res, pInfo, err) = testStoreQueue.getPage(predicate,
pInfo)
check:
# Empty last page
pInfo.pageSize == 0
pInfo.direction == PagingDirection.BACKWARD
pInfo.cursor.senderTime == Timestamp(1)
err == HistoryResponseError.NONE
res.len == 0
test "Store queue pagination works with predicate":
proc onlyEvenTimes(i: IndexedWakuMessage): bool = i.msg.timestamp.int64 mod 2 == 0
proc onlyOddTimes(i: IndexedWakuMessage): bool = i.msg.timestamp.int64 mod 2 != 0
## Forward pagination: only even timestamped messages
var (res, pInfo, err) = testStoreQueue.getPage(onlyEvenTimes,
PagingInfo(pageSize: 2,
direction: PagingDirection.FORWARD))
check:
# First page
pInfo.pageSize == 2
pInfo.direction == PagingDirection.FORWARD
pInfo.cursor.senderTime == Timestamp(4)
err == HistoryResponseError.NONE
res.mapIt(it.timestamp.int) == @[2,4]
(res, pInfo, err) = testStoreQueue.getPage(onlyEvenTimes,
pInfo)
check:
# Empty next page
pInfo.pageSize == 0
pInfo.direction == PagingDirection.FORWARD
pInfo.cursor.senderTime == Timestamp(4)
err == HistoryResponseError.NONE
res.len == 0
## Backward pagination: only odd timestamped messages
(res, pInfo, err) = testStoreQueue.getPage(onlyOddTimes,
PagingInfo(pageSize: 2,
direction: PagingDirection.BACKWARD))
check:
# First page
pInfo.pageSize == 2
pInfo.direction == PagingDirection.BACKWARD
pInfo.cursor.senderTime == Timestamp(3)
err == HistoryResponseError.NONE
res.mapIt(it.timestamp.int) == @[3,5]
(res, pInfo, err) = testStoreQueue.getPage(onlyOddTimes,
pInfo)
check:
# Next page
pInfo.pageSize == 1
pInfo.direction == PagingDirection.BACKWARD
pInfo.cursor.senderTime == Timestamp(1)
err == HistoryResponseError.NONE
res.mapIt(it.timestamp.int) == @[1]
(res, pInfo, err) = testStoreQueue.getPage(onlyOddTimes,
pInfo)
check:
# Empty last page
pInfo.pageSize == 0
pInfo.direction == PagingDirection.BACKWARD
pInfo.cursor.senderTime == Timestamp(1)
err == HistoryResponseError.NONE
res.len == 0
test "Store queue pagination handles invalid cursor":
proc predicate(i: IndexedWakuMessage): bool = true # no filtering
# Invalid cursor in backwards direction
var (res, pInfo, err) = testStoreQueue.getPage(predicate,
PagingInfo(pageSize: 3,
cursor: Index(receiverTime: Timestamp(3), senderTime: Timestamp(3), digest: MDigest[256]()),
direction: PagingDirection.BACKWARD))
check:
# Empty response with error
pInfo.pageSize == 0
pInfo.direction == PagingDirection.BACKWARD
pInfo.cursor.senderTime == Timestamp(3)
err == HistoryResponseError.INVALID_CURSOR
res.len == 0
# Same test, but forward direction
(res, pInfo, err) = testStoreQueue.getPage(predicate,
PagingInfo(pageSize: 3,
cursor: Index(receiverTime: Timestamp(3), senderTime: Timestamp(3), digest: MDigest[256]()),
direction: PagingDirection.FORWARD))
check:
# Empty response with error
pInfo.pageSize == 0
pInfo.direction == PagingDirection.FORWARD
pInfo.cursor.senderTime == Timestamp(3)
err == HistoryResponseError.INVALID_CURSOR
res.len == 0
test "Store queue pagination works on empty list":
var stQ = StoreQueueRef.new(capacity)
check:
stQ.len == 0 # Empty when initialised
proc predicate(i: IndexedWakuMessage): bool = true # no filtering
# Get page from empty queue in bwd dir
var (res, pInfo, err) = stQ.getPage(predicate,
PagingInfo(pageSize: 3,
direction: PagingDirection.BACKWARD))
check:
# Empty response
pInfo.pageSize == 0
pInfo.direction == PagingDirection.BACKWARD
pInfo.cursor.senderTime == Timestamp(0)
err == HistoryResponseError.NONE
res.len == 0
# Get page from empty queue in fwd dir
(res, pInfo, err) = stQ.getPage(predicate,
PagingInfo(pageSize: 3,
direction: PagingDirection.FORWARD))
check:
# Empty response
pInfo.pageSize == 0
pInfo.direction == PagingDirection.FORWARD
pInfo.cursor.senderTime == Timestamp(0)
err == HistoryResponseError.NONE
res.len == 0
test "Can verify if store queue contains an index":
let
existingIndex = genIndexedWakuMessage(4).index
nonExistingIndex = genIndexedWakuMessage(99).index
check:
testStoreQueue.contains(existingIndex) == true
testStoreQueue.contains(nonExistingIndex) == false