nimbus-eth2/tests/test_sync_manager.nim

216 lines
7.0 KiB
Nim

{.used.}
import unittest
import chronos
import ../beacon_chain/sync_manager
suite "SyncManager test suite":
proc createChain(start, finish: Slot): seq[SignedBeaconBlock] =
doAssert(start <= finish)
let count = int(finish - start + 1'u64)
result = newSeq[SignedBeaconBlock](count)
var curslot = start
for item in result.mitems():
item.message.slot = curslot
curslot = curslot + 1'u64
test "[SyncQueue] Start and finish slots equal":
var queue = SyncQueue.init(Slot(0), Slot(0), 1'u64, nil)
check len(queue) == 1
var r11 = queue.pop(Slot(0))
check len(queue) == 0
queue.push(r11)
check len(queue) == 1
var r11e = queue.pop(Slot(0))
check:
len(queue) == 0
r11e == r11
r11.slot == Slot(0) and r11.count == 1'u64 and r11.step == 1'u64
test "[SyncQueue] Two full requests success/fail":
var queue = SyncQueue.init(Slot(0), Slot(1), 1'u64, nil)
check len(queue) == 2
var r21 = queue.pop(Slot(1))
check len(queue) == 1
var r22 = queue.pop(Slot(1))
check len(queue) == 0
queue.push(r22)
check len(queue) == 1
queue.push(r21)
check len(queue) == 2
var r21e = queue.pop(Slot(1))
check len(queue) == 1
var r22e = queue.pop(Slot(1))
check:
len(queue) == 0
r21 == r21e
r22 == r22e
r21.slot == Slot(0) and r21.count == 1'u64 and r21.step == 1'u64
r22.slot == Slot(1) and r22.count == 1'u64 and r22.step == 1'u64
test "[SyncQueue] Full and incomplete success/fail start from zero":
var queue = SyncQueue.init(Slot(0), Slot(4), 2'u64, nil)
check len(queue) == 5
var r31 = queue.pop(Slot(4))
check len(queue) == 3
var r32 = queue.pop(Slot(4))
check len(queue) == 1
var r33 = queue.pop(Slot(4))
check len(queue) == 0
queue.push(r33)
check len(queue) == 1
queue.push(r32)
check len(queue) == 3
queue.push(r31)
check len(queue) == 5
var r31e = queue.pop(Slot(4))
check len(queue) == 3
var r32e = queue.pop(Slot(4))
check len(queue) == 1
var r33e = queue.pop(Slot(4))
check:
len(queue) == 0
r31 == r31e
r32 == r32e
r33 == r33e
r31.slot == Slot(0) and r31.count == 2'u64 and r31.step == 1'u64
r32.slot == Slot(2) and r32.count == 2'u64 and r32.step == 1'u64
r33.slot == Slot(4) and r33.count == 1'u64 and r33.step == 1'u64
test "[SyncQueue] Full and incomplete success/fail start from non-zero":
var queue = SyncQueue.init(Slot(1), Slot(5), 3'u64, nil)
check len(queue) == 5
var r41 = queue.pop(Slot(5))
check len(queue) == 2
var r42 = queue.pop(Slot(5))
check len(queue) == 0
queue.push(r42)
check len(queue) == 2
queue.push(r41)
check len(queue) == 5
var r41e = queue.pop(Slot(5))
check len(queue) == 2
var r42e = queue.pop(Slot(5))
check:
len(queue) == 0
r41 == r41e
r42 == r42e
r41.slot == Slot(1) and r41.count == 3'u64 and r41.step == 1'u64
r42.slot == Slot(4) and r42.count == 2'u64 and r42.step == 1'u64
test "[SyncQueue] Smart and stupid success/fail":
var queue = SyncQueue.init(Slot(0), Slot(4), 5'u64, nil)
check len(queue) == 5
var r51 = queue.pop(Slot(3))
check len(queue) == 1
var r52 = queue.pop(Slot(4))
check len(queue) == 0
queue.push(r52)
check len(queue) == 1
queue.push(r51)
check len(queue) == 5
var r51e = queue.pop(Slot(3))
check len(queue) == 1
var r52e = queue.pop(Slot(4))
check:
len(queue) == 0
r51 == r51e
r52 == r52e
r51.slot == Slot(0) and r51.count == 4'u64 and r51.step == 1'u64
r52.slot == Slot(4) and r52.count == 1'u64 and r52.step == 1'u64
test "[SyncQueue] One smart and one stupid + debt split + empty":
var queue = SyncQueue.init(Slot(0), Slot(4), 5'u64, nil)
check len(queue) == 5
var r61 = queue.pop(Slot(4))
check len(queue) == 0
queue.push(r61)
var r61e = queue.pop(Slot(2))
check len(queue) == 2
var r62e = queue.pop(Slot(2))
check len(queue) == 2
check r62e.isEmpty()
var r63e = queue.pop(Slot(3))
check len(queue) == 1
var r64e = queue.pop(Slot(4))
check:
len(queue) == 0
r61.slot == Slot(0) and r61.count == 5'u64 and r61.step == 1'u64
r61e.slot == Slot(0) and r61e.count == 3'u64 and r61e.step == 1'u64
r62e.isEmpty()
r63e.slot == Slot(3) and r63e.count == 1'u64 and r63e.step == 1'u64
r64e.slot == Slot(4) and r64e.count == 1'u64 and r64e.step == 1'u64
test "[SyncQueue] Async unordered push start from zero":
proc test(): Future[bool] {.async.} =
var counter = 0
proc receiver(list: openarray[SignedBeaconBlock]): bool =
result = true
for item in list:
if item.message.slot == Slot(counter):
inc(counter)
else:
result = false
break
var chain = createChain(Slot(0), Slot(2))
var queue = SyncQueue.init(Slot(0), Slot(2), 1'u64, receiver, 1)
var r11 = queue.pop(Slot(2))
var r12 = queue.pop(Slot(2))
var r13 = queue.pop(Slot(2))
var f13 = queue.push(r13, @[chain[2]])
var f12 = queue.push(r12, @[chain[1]])
await sleepAsync(100.milliseconds)
doAssert(f12.finished == false)
doAssert(f13.finished == false)
doAssert(counter == 0)
var f11 = queue.push(r11, @[chain[0]])
doAssert(counter == 1)
doAssert(f11.finished == true and f11.failed == false)
await sleepAsync(100.milliseconds)
doAssert(f12.finished == true and f12.failed == false)
doAssert(f13.finished == true and f13.failed == false)
doAssert(counter == 3)
result = true
check waitFor(test())
test "[SyncQueue] Async unordered push with not full start from non-zero":
proc test(): Future[bool] {.async.} =
var counter = 5
proc receiver(list: openarray[SignedBeaconBlock]): bool =
result = true
for item in list:
if item.message.slot == Slot(counter):
inc(counter)
else:
result = false
break
var chain = createChain(Slot(5), Slot(11))
var queue = SyncQueue.init(Slot(5), Slot(11), 2'u64, receiver, 2)
var r21 = queue.pop(Slot(11))
var r22 = queue.pop(Slot(11))
var r23 = queue.pop(Slot(11))
var r24 = queue.pop(Slot(11))
var f24 = queue.push(r24, @[chain[6]])
var f22 = queue.push(r22, @[chain[2], chain[3]])
doAssert(f24.finished == false)
doAssert(f22.finished == true and f22.failed == false)
doAssert(counter == 5)
var f21 = queue.push(r21, @[chain[0], chain[1]])
doAssert(f21.finished == true and f21.failed == false)
await sleepAsync(100.milliseconds)
doAssert(f24.finished == true and f24.failed == false)
doAssert(counter == 9)
var f23 = queue.push(r23, @[chain[4], chain[5]])
doAssert(f23.finished == true and f23.failed == false)
doAssert(counter == 12)
await sleepAsync(100.milliseconds)
doAssert(counter == 12)
result = true
check waitFor(test())