2020-10-30 19:00:14 +00:00
|
|
|
{.used.}
|
2022-07-25 11:01:37 +00:00
|
|
|
|
2020-10-20 02:20:44 +00:00
|
|
|
import
|
2022-11-08 15:10:23 +00:00
|
|
|
std/[options, sequtils, algorithm],
|
2022-07-25 11:01:37 +00:00
|
|
|
testutils/unittests,
|
|
|
|
libp2p/protobuf/minprotobuf
|
|
|
|
import
|
2022-11-08 15:10:23 +00:00
|
|
|
../../waku/v2/node/message_store/queue_store/queue_store {.all.},
|
|
|
|
../../waku/v2/node/message_store/queue_store/index,
|
2022-07-25 11:01:37 +00:00
|
|
|
../../waku/v2/protocol/waku_store,
|
|
|
|
../../waku/v2/protocol/waku_message,
|
2022-10-21 13:01:39 +00:00
|
|
|
../../waku/v2/utils/time,
|
|
|
|
./testlib/common
|
2022-08-01 10:37:45 +00:00
|
|
|
|
|
|
|
|
|
|
|
proc getTestStoreQueue(numMessages: int): StoreQueueRef =
|
|
|
|
let testStoreQueue = StoreQueueRef.new(numMessages)
|
2022-02-17 10:00:45 +00:00
|
|
|
|
2020-11-09 04:48:09 +00:00
|
|
|
var data {.noinit.}: array[32, byte]
|
|
|
|
for x in data.mitems: x = 1
|
2022-02-17 10:00:45 +00:00
|
|
|
|
2022-08-01 10:37:45 +00:00
|
|
|
for i in 0..<numMessages:
|
|
|
|
let msg = IndexedWakuMessage(
|
2022-11-08 15:10:23 +00:00
|
|
|
msg: WakuMessage(payload: @[byte i], timestamp: Timestamp(i)),
|
2022-08-01 10:37:45 +00:00
|
|
|
index: Index(
|
|
|
|
receiverTime: Timestamp(i),
|
|
|
|
senderTime: Timestamp(i),
|
2022-11-08 15:10:23 +00:00
|
|
|
digest: MessageDigest(data: data)
|
2022-08-01 10:37:45 +00:00
|
|
|
)
|
|
|
|
)
|
|
|
|
discard testStoreQueue.add(msg)
|
2022-02-17 10:00:45 +00:00
|
|
|
|
|
|
|
return testStoreQueue
|
2020-11-09 04:48:09 +00:00
|
|
|
|
2020-10-20 02:20:44 +00:00
|
|
|
|
2022-11-08 15:10:23 +00:00
|
|
|
procSuite "Queue store - pagination":
|
|
|
|
let store = getTestStoreQueue(10)
|
|
|
|
let
|
|
|
|
indexList: seq[Index] = toSeq(store.fwdIterator()).mapIt(it[0])
|
|
|
|
msgList: seq[WakuMessage] = toSeq(store.fwdIterator()).mapIt(it[1].msg)
|
2020-11-09 04:48:09 +00:00
|
|
|
|
2022-11-08 15:10:23 +00:00
|
|
|
test "Forward pagination - normal pagination":
|
|
|
|
## Given
|
|
|
|
let
|
|
|
|
pageSize: uint64 = 2
|
|
|
|
cursor: Option[Index] = some(indexList[3])
|
|
|
|
forward: bool = true
|
|
|
|
|
|
|
|
## When
|
|
|
|
let page = store.getPage(pageSize=pageSize, forward=forward, cursor=cursor)
|
|
|
|
|
|
|
|
## Then
|
|
|
|
let data = page.tryGet().mapIt(it[1])
|
2020-11-09 04:48:09 +00:00
|
|
|
check:
|
|
|
|
data.len == 2
|
|
|
|
data == msgList[4..5]
|
|
|
|
|
2022-11-08 15:10:23 +00:00
|
|
|
test "Forward pagination - initial pagination request with an empty cursor":
|
|
|
|
## Given
|
|
|
|
let
|
|
|
|
pageSize: uint64 = 2
|
|
|
|
cursor: Option[Index] = none(Index)
|
|
|
|
forward: bool = true
|
|
|
|
|
|
|
|
## When
|
|
|
|
let page = store.getPage(pageSize=pageSize, forward=forward, cursor=cursor)
|
|
|
|
|
|
|
|
## Then
|
|
|
|
let data = page.tryGet().mapIt(it[1])
|
2020-11-09 04:48:09 +00:00
|
|
|
check:
|
|
|
|
data.len == 2
|
|
|
|
data == msgList[0..1]
|
2021-04-12 17:29:09 +00:00
|
|
|
|
2022-11-08 15:10:23 +00:00
|
|
|
test "Forward pagination - initial pagination request with an empty cursor to fetch the entire history":
|
|
|
|
## Given
|
|
|
|
let
|
|
|
|
pageSize: uint64 = 13
|
|
|
|
cursor: Option[Index] = none(Index)
|
|
|
|
forward: bool = true
|
|
|
|
|
|
|
|
## When
|
|
|
|
let page = store.getPage(pageSize=pageSize, forward=forward, cursor=cursor)
|
|
|
|
|
|
|
|
## Then
|
|
|
|
let data = page.tryGet().mapIt(it[1])
|
2021-04-12 17:29:09 +00:00
|
|
|
check:
|
|
|
|
data.len == 10
|
|
|
|
data == msgList[0..9]
|
2020-11-09 04:48:09 +00:00
|
|
|
|
2022-11-08 15:10:23 +00:00
|
|
|
test "Forward pagination - empty msgList":
|
|
|
|
## Given
|
|
|
|
let store = getTestStoreQueue(0)
|
|
|
|
let
|
|
|
|
pageSize: uint64 = 2
|
|
|
|
cursor: Option[Index] = none(Index)
|
|
|
|
forward: bool = true
|
|
|
|
|
|
|
|
## When
|
|
|
|
let page = store.getPage(pageSize=pageSize, forward=forward, cursor=cursor)
|
|
|
|
|
|
|
|
## Then
|
|
|
|
let data = page.tryGet().mapIt(it[1])
|
2020-11-09 04:48:09 +00:00
|
|
|
check:
|
|
|
|
data.len == 0
|
|
|
|
|
2022-11-08 15:10:23 +00:00
|
|
|
test "Forward pagination - page size larger than the remaining messages":
|
|
|
|
## Given
|
|
|
|
let
|
|
|
|
pageSize: uint64 = 10
|
|
|
|
cursor: Option[Index] = some(indexList[3])
|
|
|
|
forward: bool = true
|
|
|
|
|
|
|
|
## When
|
|
|
|
let page = store.getPage(pageSize=pageSize, forward=forward, cursor=cursor)
|
|
|
|
|
|
|
|
## Then
|
|
|
|
let data = page.tryGet().mapIt(it[1])
|
2020-11-09 04:48:09 +00:00
|
|
|
check:
|
|
|
|
data.len == 6
|
|
|
|
data == msgList[4..9]
|
|
|
|
|
2022-11-08 15:10:23 +00:00
|
|
|
test "Forward pagination - page size larger than the maximum allowed page size":
|
|
|
|
## Given
|
|
|
|
let
|
|
|
|
pageSize: uint64 = MaxPageSize + 1
|
|
|
|
cursor: Option[Index] = some(indexList[3])
|
|
|
|
forward: bool = true
|
|
|
|
|
|
|
|
## When
|
|
|
|
let page = store.getPage(pageSize=pageSize, forward=forward, cursor=cursor)
|
|
|
|
|
|
|
|
## Then
|
|
|
|
let data = page.tryGet().mapIt(it[1])
|
2020-11-09 04:48:09 +00:00
|
|
|
check:
|
2021-04-09 10:04:21 +00:00
|
|
|
uint64(data.len) <= MaxPageSize
|
2020-11-09 04:48:09 +00:00
|
|
|
|
2022-11-08 15:10:23 +00:00
|
|
|
test "Forward pagination - cursor pointing to the end of the message list":
|
|
|
|
## Given
|
|
|
|
let
|
|
|
|
pageSize: uint64 = 10
|
|
|
|
cursor: Option[Index] = some(indexList[9])
|
|
|
|
forward: bool = true
|
|
|
|
|
|
|
|
## When
|
|
|
|
let page = store.getPage(pageSize=pageSize, forward=forward, cursor=cursor)
|
|
|
|
|
|
|
|
## Then
|
|
|
|
let data = page.tryGet().mapIt(it[1])
|
2020-11-09 04:48:09 +00:00
|
|
|
check:
|
|
|
|
data.len == 0
|
|
|
|
|
2022-11-08 15:10:23 +00:00
|
|
|
test "Forward pagination - invalid cursor":
|
|
|
|
## Given
|
2022-11-09 17:50:18 +00:00
|
|
|
let msg = fakeWakuMessage(payload= @[byte 10])
|
|
|
|
let index = HistoryCursor(
|
|
|
|
pubsubTopic: DefaultPubsubTopic,
|
|
|
|
senderTime: msg.timestamp,
|
|
|
|
storeTime: msg.timestamp,
|
|
|
|
digest: computeDigest(msg)
|
|
|
|
).toIndex()
|
|
|
|
|
2022-11-08 15:10:23 +00:00
|
|
|
let
|
|
|
|
pageSize: uint64 = 10
|
|
|
|
cursor: Option[Index] = some(index)
|
|
|
|
forward: bool = true
|
2021-04-12 17:29:09 +00:00
|
|
|
|
2022-11-08 15:10:23 +00:00
|
|
|
## When
|
|
|
|
let page = store.getPage(pageSize=pageSize, forward=forward, cursor=cursor)
|
|
|
|
|
|
|
|
## Then
|
|
|
|
let error = page.tryError()
|
|
|
|
check:
|
|
|
|
error == StoreQueueErrorKind.INVALID_CURSOR
|
|
|
|
|
|
|
|
test "Forward pagination - initial paging query over a message list with one message":
|
|
|
|
## Given
|
|
|
|
let store = getTestStoreQueue(1)
|
|
|
|
let
|
|
|
|
pageSize: uint64 = 10
|
|
|
|
cursor: Option[Index] = none(Index)
|
|
|
|
forward: bool = true
|
|
|
|
|
|
|
|
## When
|
|
|
|
let page = store.getPage(pageSize=pageSize, forward=forward, cursor=cursor)
|
|
|
|
|
|
|
|
## Then
|
|
|
|
let data = page.tryGet().mapIt(it[1])
|
2021-04-12 17:29:09 +00:00
|
|
|
check:
|
|
|
|
data.len == 1
|
|
|
|
|
2022-11-08 15:10:23 +00:00
|
|
|
test "Forward pagination - pagination over a message list with one message":
|
|
|
|
## Given
|
|
|
|
let store = getTestStoreQueue(1)
|
|
|
|
let
|
|
|
|
pageSize: uint64 = 10
|
|
|
|
cursor: Option[Index] = some(indexList[0])
|
|
|
|
forward: bool = true
|
|
|
|
|
|
|
|
## When
|
|
|
|
let page = store.getPage(pageSize=pageSize, forward=forward, cursor=cursor)
|
|
|
|
|
|
|
|
## Then
|
|
|
|
let data = page.tryGet().mapIt(it[1])
|
2021-04-12 17:29:09 +00:00
|
|
|
check:
|
|
|
|
data.len == 0
|
|
|
|
|
2022-11-08 15:10:23 +00:00
|
|
|
test "Forward pagination - with pradicate":
|
|
|
|
## Given
|
2022-09-27 19:10:11 +00:00
|
|
|
let
|
2022-11-08 15:10:23 +00:00
|
|
|
pageSize: uint64 = 3
|
|
|
|
cursor: Option[Index] = none(Index)
|
|
|
|
forward = true
|
|
|
|
|
|
|
|
proc onlyEvenTimes(i: IndexedWakuMessage): bool = i.msg.timestamp.int64 mod 2 == 0
|
|
|
|
|
|
|
|
## When
|
|
|
|
let page = store.getPage(pageSize=pageSize, forward=forward, cursor=cursor, predicate=onlyEvenTimes)
|
2022-09-27 19:10:11 +00:00
|
|
|
|
2022-11-08 15:10:23 +00:00
|
|
|
## Then
|
|
|
|
let data = page.tryGet().mapIt(it[1])
|
|
|
|
check:
|
|
|
|
data.mapIt(it.timestamp.int) == @[0, 2, 4]
|
|
|
|
|
2020-11-09 04:48:09 +00:00
|
|
|
|
2022-11-08 15:10:23 +00:00
|
|
|
test "Backward pagination - normal pagination":
|
|
|
|
## Given
|
|
|
|
let
|
|
|
|
pageSize: uint64 = 2
|
|
|
|
cursor: Option[Index] = some(indexList[3])
|
|
|
|
forward: bool = false
|
|
|
|
|
|
|
|
## When
|
|
|
|
let page = store.getPage(pageSize=pageSize, forward=forward, cursor=cursor)
|
|
|
|
|
|
|
|
## Then
|
|
|
|
let data = page.tryGet().mapIt(it[1])
|
2020-11-09 04:48:09 +00:00
|
|
|
check:
|
2022-10-03 15:36:17 +00:00
|
|
|
data == msgList[1..2].reversed
|
2020-11-09 04:48:09 +00:00
|
|
|
|
2022-11-08 15:10:23 +00:00
|
|
|
test "Backward pagination - empty msgList":
|
|
|
|
## Given
|
|
|
|
let store = getTestStoreQueue(0)
|
|
|
|
let
|
|
|
|
pageSize: uint64 = 2
|
|
|
|
cursor: Option[Index] = none(Index)
|
|
|
|
forward: bool = false
|
|
|
|
|
|
|
|
## When
|
|
|
|
let page = store.getPage(pageSize=pageSize, forward=forward, cursor=cursor)
|
|
|
|
|
|
|
|
## Then
|
|
|
|
let data = page.tryGet().mapIt(it[1])
|
2020-11-09 04:48:09 +00:00
|
|
|
check:
|
|
|
|
data.len == 0
|
|
|
|
|
2022-11-08 15:10:23 +00:00
|
|
|
test "Backward pagination - initial pagination request with an empty cursor":
|
|
|
|
## Given
|
|
|
|
let
|
|
|
|
pageSize: uint64 = 2
|
|
|
|
cursor: Option[Index] = none(Index)
|
|
|
|
forward: bool = false
|
|
|
|
|
|
|
|
## When
|
|
|
|
let page = store.getPage(pageSize=pageSize, forward=forward, cursor=cursor)
|
|
|
|
|
|
|
|
## Then
|
|
|
|
let data = page.tryGet().mapIt(it[1])
|
2020-11-09 04:48:09 +00:00
|
|
|
check:
|
|
|
|
data.len == 2
|
2022-10-03 15:36:17 +00:00
|
|
|
data == msgList[8..9].reversed
|
2021-04-12 17:29:09 +00:00
|
|
|
|
2022-11-08 15:10:23 +00:00
|
|
|
test "Backward pagination - initial pagination request with an empty cursor to fetch the entire history":
|
|
|
|
## Given
|
|
|
|
let
|
|
|
|
pageSize: uint64 = 13
|
|
|
|
cursor: Option[Index] = none(Index)
|
|
|
|
forward: bool = false
|
|
|
|
|
|
|
|
## When
|
|
|
|
let page = store.getPage(pageSize=pageSize, forward=forward, cursor=cursor)
|
|
|
|
|
|
|
|
## Then
|
|
|
|
let data = page.tryGet().mapIt(it[1])
|
2021-04-12 17:29:09 +00:00
|
|
|
check:
|
|
|
|
data.len == 10
|
2022-10-03 15:36:17 +00:00
|
|
|
data == msgList[0..9].reversed
|
2020-11-09 04:48:09 +00:00
|
|
|
|
2022-11-08 15:10:23 +00:00
|
|
|
test "Backward pagination - page size larger than the remaining messages":
|
|
|
|
## Given
|
|
|
|
let
|
|
|
|
pageSize: uint64 = 5
|
|
|
|
cursor: Option[Index] = some(indexList[3])
|
|
|
|
forward: bool = false
|
|
|
|
|
|
|
|
## When
|
|
|
|
let page = store.getPage(pageSize=pageSize, forward=forward, cursor=cursor)
|
|
|
|
|
|
|
|
## Then
|
|
|
|
let data = page.tryGet().mapIt(it[1])
|
2020-11-09 04:48:09 +00:00
|
|
|
check:
|
2022-10-03 15:36:17 +00:00
|
|
|
data == msgList[0..2].reversed
|
2020-11-09 04:48:09 +00:00
|
|
|
|
2022-11-08 15:10:23 +00:00
|
|
|
test "Backward pagination - page size larger than the Maximum allowed page size":
|
|
|
|
## Given
|
|
|
|
let
|
|
|
|
pageSize: uint64 = MaxPageSize + 1
|
|
|
|
cursor: Option[Index] = some(indexList[3])
|
|
|
|
forward: bool = false
|
|
|
|
|
|
|
|
## When
|
|
|
|
let page = store.getPage(pageSize=pageSize, forward=forward, cursor=cursor)
|
|
|
|
|
|
|
|
## Then
|
|
|
|
let data = page.tryGet().mapIt(it[1])
|
2020-11-09 04:48:09 +00:00
|
|
|
check:
|
2021-04-09 10:04:21 +00:00
|
|
|
uint64(data.len) <= MaxPageSize
|
2020-11-09 04:48:09 +00:00
|
|
|
|
2022-11-08 15:10:23 +00:00
|
|
|
test "Backward pagination - cursor pointing to the begining of the message list":
|
|
|
|
## Given
|
|
|
|
let
|
|
|
|
pageSize: uint64 = 5
|
|
|
|
cursor: Option[Index] = some(indexList[0])
|
|
|
|
forward: bool = false
|
|
|
|
|
|
|
|
## When
|
|
|
|
let page = store.getPage(pageSize=pageSize, forward=forward, cursor=cursor)
|
|
|
|
|
|
|
|
## Then
|
|
|
|
let data = page.tryGet().mapIt(it[1])
|
2020-11-09 04:48:09 +00:00
|
|
|
check:
|
|
|
|
data.len == 0
|
|
|
|
|
2022-11-08 15:10:23 +00:00
|
|
|
test "Backward pagination - invalid cursor":
|
|
|
|
## Given
|
2022-11-09 17:50:18 +00:00
|
|
|
let msg = fakeWakuMessage(payload= @[byte 10])
|
|
|
|
let index = HistoryCursor(
|
|
|
|
pubsubTopic: DefaultPubsubTopic,
|
|
|
|
senderTime: msg.timestamp,
|
|
|
|
storeTime: msg.timestamp,
|
|
|
|
digest: computeDigest(msg)
|
|
|
|
).toIndex()
|
|
|
|
|
2022-11-08 15:10:23 +00:00
|
|
|
let
|
|
|
|
pageSize: uint64 = 2
|
|
|
|
cursor: Option[Index] = some(index)
|
|
|
|
forward: bool = false
|
|
|
|
|
|
|
|
## When
|
|
|
|
let page = store.getPage(pageSize=pageSize, forward=forward, cursor=cursor)
|
|
|
|
|
|
|
|
## Then
|
|
|
|
let error = page.tryError()
|
2020-11-09 04:48:09 +00:00
|
|
|
check:
|
2022-11-08 15:10:23 +00:00
|
|
|
error == StoreQueueErrorKind.INVALID_CURSOR
|
|
|
|
|
|
|
|
test "Backward pagination - initial paging query over a message list with one message":
|
|
|
|
## Given
|
|
|
|
let store = getTestStoreQueue(1)
|
|
|
|
let
|
|
|
|
pageSize: uint64 = 10
|
|
|
|
cursor: Option[Index] = none(Index)
|
|
|
|
forward: bool = false
|
|
|
|
|
|
|
|
## When
|
|
|
|
let page = store.getPage(pageSize=pageSize, forward=forward, cursor=cursor)
|
2021-04-12 17:29:09 +00:00
|
|
|
|
2022-11-08 15:10:23 +00:00
|
|
|
## Then
|
|
|
|
let data = page.tryGet().mapIt(it[1])
|
2021-04-12 17:29:09 +00:00
|
|
|
check:
|
|
|
|
data.len == 1
|
|
|
|
|
2022-11-08 15:10:23 +00:00
|
|
|
test "Backward pagination - paging query over a message list with one message":
|
|
|
|
## Given
|
|
|
|
let store = getTestStoreQueue(1)
|
|
|
|
let
|
|
|
|
pageSize: uint64 = 10
|
|
|
|
cursor: Option[Index] = some(indexList[0])
|
|
|
|
forward: bool = false
|
|
|
|
|
|
|
|
## When
|
|
|
|
let page = store.getPage(pageSize=pageSize, forward=forward, cursor=cursor)
|
|
|
|
|
|
|
|
## Then
|
|
|
|
let data = page.tryGet().mapIt(it[1])
|
2021-04-12 17:29:09 +00:00
|
|
|
check:
|
|
|
|
data.len == 0
|
2022-11-08 15:10:23 +00:00
|
|
|
|
|
|
|
test "Backward pagination - with predicate":
|
|
|
|
## Given
|
|
|
|
let
|
|
|
|
pageSize: uint64 = 3
|
|
|
|
cursor: Option[Index] = none(Index)
|
|
|
|
forward = false
|
|
|
|
|
|
|
|
proc onlyOddTimes(i: IndexedWakuMessage): bool = i.msg.timestamp.int64 mod 2 != 0
|
|
|
|
|
|
|
|
## When
|
|
|
|
let page = store.getPage(pageSize=pageSize, forward=forward, cursor=cursor, predicate=onlyOddTimes)
|
|
|
|
|
|
|
|
## Then
|
|
|
|
let data = page.tryGet().mapIt(it[1])
|
|
|
|
check:
|
|
|
|
data.mapIt(it.timestamp.int) == @[5, 7,9].reversed
|