2024-03-05 03:12:37 +00:00
|
|
|
# Nim-RocksDB
|
|
|
|
# Copyright 2024 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)
|
|
|
|
# * GPL license, version 2.0, ([LICENSE-GPLv2](LICENSE-GPLv2) or https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
|
|
|
|
#
|
|
|
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
|
|
|
|
|
|
|
{.used.}
|
|
|
|
|
2024-06-26 15:00:10 +00:00
|
|
|
import std/os, tempfile, unittest2, ../rocksdb/[rocksdb, rocksiterator], ./test_helper
|
2024-03-05 03:12:37 +00:00
|
|
|
|
|
|
|
suite "RocksIteratorRef Tests":
|
|
|
|
const
|
|
|
|
CF_DEFAULT = "default"
|
|
|
|
CF_OTHER = "other"
|
|
|
|
CF_EMPTY = "empty"
|
|
|
|
|
|
|
|
let
|
|
|
|
key1 = @[byte(1)]
|
|
|
|
val1 = @[byte(1)]
|
|
|
|
key2 = @[byte(2)]
|
|
|
|
val2 = @[byte(2)]
|
|
|
|
key3 = @[byte(3)]
|
|
|
|
val3 = @[byte(3)]
|
|
|
|
|
|
|
|
setup:
|
|
|
|
let
|
|
|
|
dbPath = mkdtemp() / "data"
|
2024-06-26 15:00:10 +00:00
|
|
|
db =
|
|
|
|
initReadWriteDb(dbPath, columnFamilyNames = @[CF_DEFAULT, CF_OTHER, CF_EMPTY])
|
2024-06-26 17:31:39 +00:00
|
|
|
defaultCfHandle = db.getColFamilyHandle(CF_DEFAULT).get()
|
|
|
|
otherCfHandle = db.getColFamilyHandle(CF_OTHER).get()
|
|
|
|
emptyCfHandle = db.getColFamilyHandle(CF_EMPTY).get()
|
2024-03-05 03:12:37 +00:00
|
|
|
|
|
|
|
doAssert db.put(key1, val1).isOk()
|
|
|
|
doAssert db.put(key2, val2).isOk()
|
|
|
|
doAssert db.put(key3, val3).isOk()
|
2024-06-26 17:31:39 +00:00
|
|
|
doAssert db.put(key1, val1, otherCfHandle).isOk()
|
|
|
|
doAssert db.put(key2, val2, otherCfHandle).isOk()
|
|
|
|
doAssert db.put(key3, val3, otherCfHandle).isOk()
|
2024-03-05 03:12:37 +00:00
|
|
|
|
|
|
|
teardown:
|
|
|
|
db.close()
|
|
|
|
removeDir($dbPath)
|
|
|
|
|
|
|
|
test "Iterate forwards using default column family":
|
2024-06-26 17:31:39 +00:00
|
|
|
let res = db.openIterator(defaultCfHandle)
|
2024-03-05 03:12:37 +00:00
|
|
|
check res.isOk()
|
|
|
|
|
|
|
|
var iter = res.get()
|
2024-06-26 15:00:10 +00:00
|
|
|
defer:
|
|
|
|
iter.close()
|
2024-03-05 03:12:37 +00:00
|
|
|
|
|
|
|
iter.seekToFirst()
|
|
|
|
check iter.isValid()
|
|
|
|
|
|
|
|
var expected = byte(1)
|
|
|
|
while iter.isValid():
|
|
|
|
let
|
|
|
|
key = iter.key()
|
|
|
|
val = iter.value()
|
|
|
|
|
|
|
|
check:
|
|
|
|
key == @[expected]
|
|
|
|
val == @[expected]
|
|
|
|
|
|
|
|
inc expected
|
|
|
|
iter.next()
|
|
|
|
|
|
|
|
check expected == byte(4)
|
|
|
|
|
|
|
|
test "Iterate backwards using other column family":
|
2024-06-26 17:31:39 +00:00
|
|
|
let res = db.openIterator(otherCfHandle)
|
2024-03-05 03:12:37 +00:00
|
|
|
check res.isOk()
|
|
|
|
|
|
|
|
var iter = res.get()
|
2024-06-26 15:00:10 +00:00
|
|
|
defer:
|
|
|
|
iter.close()
|
2024-03-05 03:12:37 +00:00
|
|
|
|
|
|
|
iter.seekToLast()
|
|
|
|
check iter.isValid()
|
|
|
|
|
|
|
|
var expected = byte(3)
|
|
|
|
while iter.isValid():
|
|
|
|
var key: seq[byte]
|
2024-06-26 15:00:10 +00:00
|
|
|
iter.key(
|
|
|
|
proc(data: openArray[byte]) =
|
|
|
|
key = @data
|
|
|
|
)
|
2024-03-05 03:12:37 +00:00
|
|
|
var val: seq[byte]
|
2024-06-26 15:00:10 +00:00
|
|
|
iter.value(
|
|
|
|
proc(data: openArray[byte]) =
|
|
|
|
val = @data
|
|
|
|
)
|
2024-03-05 03:12:37 +00:00
|
|
|
|
|
|
|
check:
|
|
|
|
key == @[expected]
|
|
|
|
val == @[expected]
|
|
|
|
|
|
|
|
dec expected
|
|
|
|
iter.prev()
|
|
|
|
|
|
|
|
check expected == byte(0)
|
|
|
|
iter.close()
|
|
|
|
|
|
|
|
test "Open two iterators on the same column family":
|
2024-06-26 17:31:39 +00:00
|
|
|
let res1 = db.openIterator(defaultCfHandle)
|
2024-03-05 03:12:37 +00:00
|
|
|
check res1.isOk()
|
|
|
|
var iter1 = res1.get()
|
2024-06-26 15:00:10 +00:00
|
|
|
defer:
|
|
|
|
iter1.close()
|
2024-06-26 17:31:39 +00:00
|
|
|
let res2 = db.openIterator(defaultCfHandle)
|
2024-03-05 03:12:37 +00:00
|
|
|
check res2.isOk()
|
|
|
|
var iter2 = res2.get()
|
2024-06-26 15:00:10 +00:00
|
|
|
defer:
|
|
|
|
iter2.close()
|
2024-03-05 03:12:37 +00:00
|
|
|
|
|
|
|
iter1.seekToFirst()
|
|
|
|
check iter1.isValid()
|
|
|
|
iter2.seekToLast()
|
|
|
|
check iter2.isValid()
|
|
|
|
|
|
|
|
check:
|
|
|
|
iter1.key() == @[byte(1)]
|
|
|
|
iter1.value() == @[byte(1)]
|
|
|
|
iter2.key() == @[byte(3)]
|
|
|
|
iter2.value() == @[byte(3)]
|
|
|
|
|
|
|
|
test "Open two iterators on different column families":
|
2024-06-26 17:31:39 +00:00
|
|
|
let res1 = db.openIterator(defaultCfHandle)
|
2024-03-05 03:12:37 +00:00
|
|
|
check res1.isOk()
|
|
|
|
var iter1 = res1.get()
|
2024-06-26 15:00:10 +00:00
|
|
|
defer:
|
|
|
|
iter1.close()
|
2024-06-26 17:31:39 +00:00
|
|
|
let res2 = db.openIterator(otherCfHandle)
|
2024-03-05 03:12:37 +00:00
|
|
|
check res2.isOk()
|
|
|
|
var iter2 = res2.get()
|
2024-06-26 15:00:10 +00:00
|
|
|
defer:
|
|
|
|
iter2.close()
|
2024-03-05 03:12:37 +00:00
|
|
|
|
|
|
|
iter1.seekToFirst()
|
|
|
|
check iter1.isValid()
|
|
|
|
iter2.seekToLast()
|
|
|
|
check iter2.isValid()
|
|
|
|
|
|
|
|
check:
|
|
|
|
iter1.key() == @[byte(1)]
|
|
|
|
iter1.value() == @[byte(1)]
|
|
|
|
iter2.key() == @[byte(3)]
|
|
|
|
iter2.value() == @[byte(3)]
|
|
|
|
|
2024-06-28 02:04:37 +00:00
|
|
|
test "Iterate forwards using seek to key":
|
|
|
|
let res = db.openIterator(defaultCfHandle)
|
|
|
|
check res.isOk()
|
|
|
|
|
|
|
|
var iter = res.get()
|
|
|
|
defer:
|
|
|
|
iter.close()
|
|
|
|
|
|
|
|
iter.seekToKey(key2)
|
|
|
|
check:
|
|
|
|
iter.isValid()
|
|
|
|
iter.key() == key2
|
|
|
|
iter.value() == val2
|
|
|
|
|
2024-07-08 14:18:30 +00:00
|
|
|
test "Seek to empty key":
|
|
|
|
let empty: seq[byte] = @[]
|
|
|
|
check db.put(empty, val1).isOk()
|
|
|
|
|
|
|
|
let iter = db.openIterator().get()
|
|
|
|
defer:
|
|
|
|
iter.close()
|
|
|
|
|
|
|
|
iter.seekToKey(empty)
|
|
|
|
check:
|
|
|
|
iter.isValid()
|
|
|
|
iter.key() == empty
|
|
|
|
iter.value() == val1
|
|
|
|
|
2024-03-05 03:12:37 +00:00
|
|
|
test "Empty column family":
|
2024-06-26 17:31:39 +00:00
|
|
|
let res = db.openIterator(emptyCfHandle)
|
2024-03-05 03:12:37 +00:00
|
|
|
check res.isOk()
|
|
|
|
var iter = res.get()
|
2024-06-26 15:00:10 +00:00
|
|
|
defer:
|
|
|
|
iter.close()
|
2024-03-05 03:12:37 +00:00
|
|
|
|
|
|
|
iter.seekToFirst()
|
|
|
|
check not iter.isValid()
|
|
|
|
|
|
|
|
iter.seekToLast()
|
|
|
|
check not iter.isValid()
|
|
|
|
|
|
|
|
test "Test status":
|
2024-06-26 17:31:39 +00:00
|
|
|
let res = db.openIterator(emptyCfHandle)
|
2024-03-05 03:12:37 +00:00
|
|
|
check res.isOk()
|
|
|
|
var iter = res.get()
|
2024-06-26 15:00:10 +00:00
|
|
|
defer:
|
|
|
|
iter.close()
|
2024-03-05 03:12:37 +00:00
|
|
|
|
|
|
|
check iter.status().isOk()
|
|
|
|
iter.seekToLast()
|
|
|
|
check iter.status().isOk()
|
|
|
|
|
|
|
|
test "Test pairs iterator":
|
2024-06-26 17:31:39 +00:00
|
|
|
let res = db.openIterator(defaultCfHandle)
|
2024-03-05 03:12:37 +00:00
|
|
|
check res.isOk()
|
|
|
|
var iter = res.get()
|
|
|
|
|
|
|
|
var expected = byte(1)
|
|
|
|
for k, v in iter:
|
|
|
|
check:
|
|
|
|
k == @[expected]
|
|
|
|
v == @[expected]
|
|
|
|
inc expected
|
|
|
|
check iter.isClosed()
|
|
|
|
|
|
|
|
test "Test close":
|
|
|
|
let res = db.openIterator()
|
|
|
|
check res.isOk()
|
|
|
|
var iter = res.get()
|
|
|
|
|
|
|
|
check not iter.isClosed()
|
|
|
|
iter.close()
|
|
|
|
check iter.isClosed()
|
|
|
|
iter.close()
|
|
|
|
check iter.isClosed()
|