285 lines
7.6 KiB
Nim
285 lines
7.6 KiB
Nim
# Nim-RocksDB
|
|
# Copyright 2018-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.}
|
|
|
|
import
|
|
std/os,
|
|
tempfile,
|
|
unittest2,
|
|
../rocksdb/rocksdb,
|
|
./test_helper
|
|
|
|
suite "RocksDbRef Tests":
|
|
const
|
|
CF_DEFAULT = "default"
|
|
CF_OTHER = "other"
|
|
|
|
let
|
|
key = @[byte(1), 2, 3, 4, 5]
|
|
otherKey = @[byte(1), 2, 3, 4, 5, 6]
|
|
val = @[byte(1), 2, 3, 4, 5]
|
|
|
|
setup:
|
|
let
|
|
dbPath = mkdtemp() / "data"
|
|
db = initReadWriteDb(dbPath, columnFamilyNames = @[CF_DEFAULT, CF_OTHER])
|
|
|
|
teardown:
|
|
db.close()
|
|
removeDir($dbPath)
|
|
|
|
test "Basic operations":
|
|
|
|
var s = db.put(key, val)
|
|
check s.isOk()
|
|
|
|
var bytes: seq[byte]
|
|
check db.get(key, proc(data: openArray[byte]) = bytes = @data)[]
|
|
check not db.get(otherkey, proc(data: openArray[byte]) = bytes = @data)[]
|
|
|
|
var r1 = db.get(key)
|
|
check r1.isOk() and r1.value == val
|
|
|
|
var r2 = db.get(otherKey)
|
|
# there's no error string for missing keys
|
|
check r2.isOk() == false and r2.error.len == 0
|
|
|
|
var e1 = db.keyExists(key)
|
|
check e1.isOk() and e1.value == true
|
|
|
|
var e2 = db.keyExists(otherKey)
|
|
check e2.isOk() and e2.value == false
|
|
|
|
var d = db.delete(key)
|
|
check d.isOk()
|
|
|
|
e1 = db.keyExists(key)
|
|
check e1.isOk() and e1.value == false
|
|
|
|
d = db.delete(otherKey)
|
|
check d.isOk()
|
|
|
|
close(db)
|
|
check db.isClosed()
|
|
|
|
# Open database in read only mode
|
|
block:
|
|
var
|
|
readOnlyDb = initReadOnlyDb(dbPath)
|
|
r = readOnlyDb.keyExists(key)
|
|
check r.isOk() and r.value == false
|
|
|
|
# This won't compile as designed:
|
|
# var r2 = readOnlyDb.put(key, @[123.byte])
|
|
# check r2.isErr()
|
|
|
|
readOnlyDb.close()
|
|
check readOnlyDb.isClosed()
|
|
|
|
test "Basic operations - default column family":
|
|
|
|
var s = db.put(key, val, CF_DEFAULT)
|
|
check s.isOk()
|
|
|
|
var bytes: seq[byte]
|
|
check db.get(key, proc(data: openArray[byte]) = bytes = @data, CF_DEFAULT)[]
|
|
check not db.get(otherkey, proc(data: openArray[byte]) = bytes = @data, CF_DEFAULT)[]
|
|
|
|
var r1 = db.get(key)
|
|
check r1.isOk() and r1.value == val
|
|
|
|
var r2 = db.get(otherKey)
|
|
# there's no error string for missing keys
|
|
check r2.isOk() == false and r2.error.len == 0
|
|
|
|
var e1 = db.keyExists(key, CF_DEFAULT)
|
|
check e1.isOk() and e1.value == true
|
|
|
|
var e2 = db.keyExists(otherKey, CF_DEFAULT)
|
|
check e2.isOk() and e2.value == false
|
|
|
|
var d = db.delete(key, CF_DEFAULT)
|
|
check d.isOk()
|
|
|
|
e1 = db.keyExists(key, CF_DEFAULT)
|
|
check e1.isOk() and e1.value == false
|
|
|
|
d = db.delete(otherKey, CF_DEFAULT)
|
|
check d.isOk()
|
|
|
|
close(db)
|
|
check db.isClosed()
|
|
|
|
# Open database in read only mode
|
|
block:
|
|
var
|
|
readOnlyDb = initReadOnlyDb(dbPath, columnFamilyNames = @[CF_DEFAULT])
|
|
r = readOnlyDb.keyExists(key, CF_DEFAULT)
|
|
check r.isOk() and r.value == false
|
|
|
|
# Won't compile as designed:
|
|
# var r2 = readOnlyDb.put(key, @[123.byte], CF_DEFAULT)
|
|
# check r2.isErr()
|
|
|
|
readOnlyDb.close()
|
|
check readOnlyDb.isClosed()
|
|
|
|
test "Basic operations - multiple column families":
|
|
|
|
var s = db.put(key, val, CF_DEFAULT)
|
|
check s.isOk()
|
|
|
|
var s2 = db.put(otherKey, val, CF_OTHER)
|
|
check s2.isOk()
|
|
|
|
var bytes: seq[byte]
|
|
check db.get(key, proc(data: openArray[byte]) = bytes = @data, CF_DEFAULT)[]
|
|
check not db.get(otherkey, proc(data: openArray[byte]) = bytes = @data, CF_DEFAULT)[]
|
|
|
|
var bytes2: seq[byte]
|
|
check db.get(otherKey, proc(data: openArray[byte]) = bytes2 = @data, CF_OTHER)[]
|
|
check not db.get(key, proc(data: openArray[byte]) = bytes2 = @data, CF_OTHER)[]
|
|
|
|
var e1 = db.keyExists(key, CF_DEFAULT)
|
|
check e1.isOk() and e1.value == true
|
|
var e2 = db.keyExists(otherKey, CF_DEFAULT)
|
|
check e2.isOk() and e2.value == false
|
|
|
|
var e3 = db.keyExists(key, CF_OTHER)
|
|
check e3.isOk() and e3.value == false
|
|
var e4 = db.keyExists(otherKey, CF_OTHER)
|
|
check e4.isOk() and e4.value == true
|
|
|
|
var d = db.delete(key, CF_DEFAULT)
|
|
check d.isOk()
|
|
e1 = db.keyExists(key, CF_DEFAULT)
|
|
check e1.isOk() and e1.value == false
|
|
d = db.delete(otherKey, CF_DEFAULT)
|
|
check d.isOk()
|
|
|
|
var d2 = db.delete(key, CF_OTHER)
|
|
check d2.isOk()
|
|
e3 = db.keyExists(key, CF_OTHER)
|
|
check e3.isOk() and e3.value == false
|
|
d2 = db.delete(otherKey, CF_OTHER)
|
|
check d2.isOk()
|
|
d2 = db.delete(otherKey, CF_OTHER)
|
|
check d2.isOk()
|
|
|
|
db.close()
|
|
check db.isClosed()
|
|
|
|
# Open database in read only mode
|
|
block:
|
|
var
|
|
readOnlyDb = initReadOnlyDb(dbPath, columnFamilyNames = @[CF_DEFAULT, CF_OTHER])
|
|
|
|
var r = readOnlyDb.keyExists(key, CF_OTHER)
|
|
check r.isOk() and r.value == false
|
|
|
|
# Does not compile as designed:
|
|
# var r2 = readOnlyDb.put(key, @[123.byte], CF_OTHER)
|
|
# check r2.isErr()
|
|
|
|
readOnlyDb.close()
|
|
check readOnlyDb.isClosed()
|
|
|
|
test "Close multiple times":
|
|
|
|
check not db.isClosed()
|
|
db.close()
|
|
check db.isClosed()
|
|
db.close()
|
|
check db.isClosed()
|
|
|
|
test "Unknown column family":
|
|
const CF_UNKNOWN = "unknown"
|
|
|
|
let r = db.put(key, val, CF_UNKNOWN)
|
|
check r.isErr() and r.error() == "rocksdb: unknown column family"
|
|
|
|
var bytes: seq[byte]
|
|
let r2 = db.get(key, proc(data: openArray[byte]) = bytes = @data, CF_UNKNOWN)
|
|
check r2.isErr() and r2.error() == "rocksdb: unknown column family"
|
|
|
|
let r3 = db.keyExists(key, CF_UNKNOWN)
|
|
check r3.isErr() and r3.error() == "rocksdb: unknown column family"
|
|
|
|
let r4 = db.delete(key, CF_UNKNOWN)
|
|
check r4.isErr() and r4.error() == "rocksdb: unknown column family"
|
|
|
|
test "Test missing key and values":
|
|
let
|
|
key1 = @[byte(1)] # exists with non empty value
|
|
val1 = @[byte(1)]
|
|
key2 = @[byte(2)] # exists with empty seq value
|
|
val2: seq[byte] = @[]
|
|
key3 = @[byte(3)] # exists with empty array value
|
|
val3: array[0, byte] = []
|
|
key4 = @[byte(4)] # deleted key
|
|
key5 = @[byte(5)] # key not created
|
|
|
|
check:
|
|
db.put(key1, val1).isOk()
|
|
db.put(key2, val2).isOk()
|
|
db.put(key3, val3).isOk()
|
|
db.delete(key4).isOk()
|
|
|
|
db.keyExists(key1).get() == true
|
|
db.keyExists(key2).get() == true
|
|
db.keyExists(key3).get() == true
|
|
db.keyExists(key4).get() == false
|
|
db.keyExists(key5).get() == false
|
|
|
|
block:
|
|
var v: seq[byte]
|
|
let r = db.get(key1, proc(data: openArray[byte]) = v = @data)
|
|
check:
|
|
r.isOk()
|
|
r.value() == true
|
|
v == val1
|
|
db.get(key1).isOk()
|
|
|
|
block:
|
|
var v: seq[byte]
|
|
let r = db.get(key2, proc(data: openArray[byte]) = v = @data)
|
|
check:
|
|
r.isOk()
|
|
r.value() == true
|
|
v.len() == 0
|
|
db.get(key2).isOk()
|
|
|
|
block:
|
|
var v: seq[byte]
|
|
let r = db.get(key3, proc(data: openArray[byte]) = v = @data)
|
|
check:
|
|
r.isOk()
|
|
r.value() == true
|
|
v.len() == 0
|
|
db.get(key3).isOk()
|
|
|
|
block:
|
|
var v: seq[byte]
|
|
let r = db.get(key4, proc(data: openArray[byte]) = v = @data)
|
|
check:
|
|
r.isOk()
|
|
r.value() == false
|
|
v.len() == 0
|
|
db.get(key4).isErr()
|
|
|
|
block:
|
|
var v: seq[byte]
|
|
let r = db.get(key5, proc(data: openArray[byte]) = v = @data)
|
|
check:
|
|
r.isOk()
|
|
r.value() == false
|
|
v.len() == 0
|
|
db.get(key5).isErr()
|