2021-11-04 11:17:50 +00:00
|
|
|
# Nimbus
|
|
|
|
# Copyright (c) 2018-2019 Status Research & Development GmbH
|
|
|
|
# Licensed under either of
|
|
|
|
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
|
|
|
# http://www.apache.org/licenses/LICENSE-2.0)
|
|
|
|
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or
|
|
|
|
# http://opensource.org/licenses/MIT)
|
|
|
|
# at your option. This file may not be copied, modified, or distributed except
|
|
|
|
# according to those terms.
|
|
|
|
|
|
|
|
import
|
|
|
|
std/[algorithm, sequtils, strformat, tables],
|
|
|
|
../stew/sorted_set,
|
|
|
|
unittest
|
|
|
|
|
|
|
|
const
|
|
|
|
keyList = [
|
|
|
|
185, 208, 53, 54, 196, 189, 187, 117, 94, 29, 6, 173, 207, 45, 31,
|
|
|
|
208, 127, 106, 117, 49, 40, 171, 6, 94, 84, 60, 125, 87, 168, 183,
|
|
|
|
200, 155, 34, 27, 67, 107, 108, 223, 249, 4, 113, 9, 205, 100, 77,
|
|
|
|
224, 19, 196, 14, 83, 145, 154, 95, 56, 236, 97, 115, 140, 134, 97,
|
|
|
|
153, 167, 23, 17, 182, 116, 253, 32, 108, 148, 135, 169, 178, 124, 147,
|
|
|
|
231, 236, 174, 211, 247, 22, 118, 144, 224, 68, 124, 200, 92, 63, 183,
|
|
|
|
56, 107, 45, 180, 113, 233, 59, 246, 29, 212, 172, 161, 183, 207, 189,
|
|
|
|
56, 198, 130, 62, 28, 53, 122]
|
|
|
|
|
|
|
|
let
|
|
|
|
noisy = defined(debug)
|
|
|
|
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
# Helpers
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
iterator fwdItems(sl: var SortedSet[int,int]): int =
|
|
|
|
var rc = sl.ge(0)
|
|
|
|
while rc.isOk:
|
|
|
|
yield rc.value.key
|
|
|
|
rc = sl.gt(rc.value.key)
|
|
|
|
|
|
|
|
iterator revItems(sl: var SortedSet[int,int]): int =
|
|
|
|
var rc = sl.le(int.high)
|
|
|
|
while rc.isOk:
|
|
|
|
yield rc.value.key
|
|
|
|
rc = sl.lt(rc.value.key)
|
|
|
|
|
|
|
|
iterator fwdWalk(sl: var SortedSet[int,int]): int =
|
|
|
|
var
|
|
|
|
w = SortedSetWalkRef[int,int].init(sl)
|
|
|
|
rc = w.first
|
|
|
|
while rc.isOk:
|
|
|
|
yield rc.value.key
|
|
|
|
rc = w.next
|
|
|
|
w.destroy
|
|
|
|
|
|
|
|
iterator revWalk(sl: var SortedSet[int,int]): int =
|
|
|
|
var
|
|
|
|
w = SortedSetWalkRef[int,int].init(sl)
|
|
|
|
var
|
|
|
|
rc = w.last
|
|
|
|
while rc.isOk:
|
|
|
|
yield rc.value.key
|
|
|
|
rc = w.prev
|
|
|
|
w.destroy
|
|
|
|
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
# Test Runners
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
let
|
|
|
|
numUniqeKeys = keyList.toSeq.mapIt((it,false)).toTable.len
|
|
|
|
numKeyDups = keyList.len - numUniqeKeys
|
|
|
|
|
|
|
|
suite "SortedSet: Sorted list based on red-black tree":
|
|
|
|
var
|
|
|
|
sl = SortedSet[int,int].init
|
|
|
|
rej: seq[int]
|
|
|
|
|
|
|
|
test &"Insert {keyList.len} items, reject {numKeyDups} duplicates":
|
|
|
|
for n in keyList:
|
|
|
|
let rc = sl.insert(n)
|
|
|
|
if rc.isErr:
|
|
|
|
rej.add n
|
|
|
|
else:
|
|
|
|
rc.value.data = -n
|
|
|
|
let check = sl.verify
|
|
|
|
if check.isErr:
|
|
|
|
check check.error[1] == rbOk # force message
|
|
|
|
check sl.len == numUniqeKeys
|
|
|
|
check rej.len == numKeyDups
|
|
|
|
check sl.len + rej.len == keyList.len
|
|
|
|
|
|
|
|
test &"Verify increasing/decreasing traversals":
|
|
|
|
check toSeq(sl.fwdItems) == toSeq(sl.fwdWalk)
|
|
|
|
check toSeq(sl.revItems) == toSeq(sl.revWalk)
|
|
|
|
check toSeq(sl.fwdItems) == toSeq(sl.revWalk).reversed
|
|
|
|
check toSeq(sl.revItems) == toSeq(sl.fwdWalk).reversed
|
|
|
|
|
|
|
|
# check `sLstEq()`
|
|
|
|
block:
|
|
|
|
var rc = sl.ge(0)
|
|
|
|
while rc.isOk:
|
|
|
|
check rc == sl.eq(rc.value.key)
|
|
|
|
rc = sl.gt(rc.value.key)
|
|
|
|
|
|
|
|
# check `sLstThis()`
|
|
|
|
block:
|
|
|
|
var
|
|
|
|
w = SortedSetWalkRef[int,int].init(sl)
|
|
|
|
rc = w.first
|
|
|
|
while rc.isOk:
|
|
|
|
check rc == w.this
|
|
|
|
rc = w.next
|
|
|
|
w.destroy
|
|
|
|
|
|
|
|
test "Delete items":
|
|
|
|
var seen: seq[int]
|
|
|
|
let sub7 = keyList.len div 7
|
2021-12-02 15:24:02 +00:00
|
|
|
for n in toSeq(countup(0,sub7)).concat(toSeq(countup(3*sub7,4*sub7))):
|
2021-11-04 11:17:50 +00:00
|
|
|
let
|
|
|
|
key = keyList[n]
|
|
|
|
canDeleteOk = (key notin seen)
|
|
|
|
|
|
|
|
data = sl.delete(key)
|
|
|
|
slCheck = sl.verify
|
|
|
|
|
|
|
|
if key notin seen:
|
|
|
|
seen.add key
|
|
|
|
|
|
|
|
if slCheck.isErr:
|
|
|
|
check slCheck.error[1] == rbOk # force message
|
|
|
|
check data.isOk == canDeleteOk
|
|
|
|
|
|
|
|
if canDeleteOk:
|
|
|
|
check data.value.key == key
|
|
|
|
|
|
|
|
check seen.len + sl.len + rej.len == keyList.len
|
|
|
|
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
# End
|
|
|
|
# ------------------------------------------------------------------------------
|