2020-02-23 20:13:32 +08:00
|
|
|
import unittest, options, os, osproc, sequtils, strutils, sugar
|
2019-12-18 13:18:05 +00:00
|
|
|
import leveldb, leveldbpkg/raw
|
2019-11-09 15:52:46 +08:00
|
|
|
|
2020-02-23 20:13:32 +08:00
|
|
|
template cd*(dir: string, body: untyped) =
|
|
|
|
|
## Sets the current dir to ``dir``, executes ``body`` and restores the
|
|
|
|
|
## previous working dir.
|
|
|
|
|
block:
|
|
|
|
|
let lastDir = getCurrentDir()
|
|
|
|
|
setCurrentDir(dir)
|
|
|
|
|
body
|
|
|
|
|
setCurrentDir(lastDir)
|
|
|
|
|
|
|
|
|
|
proc execNimble(args: varargs[string]): tuple[output: string, exitCode: int] =
|
|
|
|
|
const tmpNimbleDir = "/tmp/testnimble"
|
|
|
|
|
var quotedArgs = @args
|
|
|
|
|
quotedArgs.insert("-y")
|
|
|
|
|
quotedArgs.insert("--nimbleDir:" & tmpNimbleDir)
|
|
|
|
|
quotedArgs.insert("nimble")
|
|
|
|
|
quotedArgs = quotedArgs.map((x: string) => ("\"" & x & "\""))
|
|
|
|
|
|
|
|
|
|
let cmd = quotedArgs.join(" ")
|
|
|
|
|
result = execCmdEx(cmd)
|
|
|
|
|
checkpoint(cmd)
|
|
|
|
|
checkpoint(result.output)
|
|
|
|
|
|
2019-11-09 15:52:46 +08:00
|
|
|
suite "leveldb":
|
|
|
|
|
|
|
|
|
|
setup:
|
|
|
|
|
let env = leveldb_create_default_env()
|
|
|
|
|
let dbName = $(leveldb_env_get_test_directory(env))
|
|
|
|
|
let db = leveldb.open(dbName)
|
|
|
|
|
|
|
|
|
|
teardown:
|
|
|
|
|
db.close()
|
|
|
|
|
removeDb(dbName)
|
|
|
|
|
|
|
|
|
|
test "version":
|
2019-11-11 01:02:57 +08:00
|
|
|
let (major, minor) = getLibVersion()
|
2019-11-09 15:52:46 +08:00
|
|
|
check(major > 0)
|
|
|
|
|
check(minor > 0)
|
|
|
|
|
|
|
|
|
|
test "get nothing":
|
|
|
|
|
check(db.get("nothing") == none(string))
|
|
|
|
|
|
|
|
|
|
test "put and get":
|
|
|
|
|
db.put("hello", "world")
|
|
|
|
|
check(db.get("hello") == some("world"))
|
|
|
|
|
|
|
|
|
|
test "delete":
|
|
|
|
|
db.put("hello", "world")
|
|
|
|
|
db.delete("hello")
|
|
|
|
|
check(db.get("hello") == none(string))
|
|
|
|
|
|
2019-11-16 20:24:33 +08:00
|
|
|
test "get value with 0x00":
|
|
|
|
|
db.put("\0key", "\0ff")
|
|
|
|
|
check(db.get("\0key") == some("\0ff"))
|
|
|
|
|
|
2019-12-14 18:05:05 +08:00
|
|
|
test "get empty value":
|
|
|
|
|
db.put("a", "")
|
|
|
|
|
check(db.get("a") == some(""))
|
|
|
|
|
|
|
|
|
|
test "get empty key":
|
|
|
|
|
db.put("", "a")
|
|
|
|
|
check(db.get("") == some("a"))
|
|
|
|
|
|
2019-11-09 15:52:46 +08:00
|
|
|
proc initData(db: LevelDb) =
|
|
|
|
|
db.put("aa", "1")
|
|
|
|
|
db.put("ba", "2")
|
|
|
|
|
db.put("bb", "3")
|
|
|
|
|
|
|
|
|
|
test "iter":
|
|
|
|
|
initData(db)
|
|
|
|
|
check(toSeq(db.iter()) == @[("aa", "1"), ("ba", "2"), ("bb", "3")])
|
|
|
|
|
|
|
|
|
|
test "iter reverse":
|
|
|
|
|
initData(db)
|
|
|
|
|
check(toSeq(db.iter(reverse = true)) ==
|
|
|
|
|
@[("bb", "3"), ("ba", "2"), ("aa", "1")])
|
|
|
|
|
|
|
|
|
|
test "iter seek":
|
|
|
|
|
initData(db)
|
|
|
|
|
check(toSeq(db.iter(seek = "ab")) ==
|
|
|
|
|
@[("ba", "2"), ("bb", "3")])
|
|
|
|
|
|
|
|
|
|
test "iter seek reverse":
|
|
|
|
|
initData(db)
|
|
|
|
|
check(toSeq(db.iter(seek = "ab", reverse = true)) ==
|
|
|
|
|
@[("ba", "2"), ("aa", "1")])
|
2019-11-16 17:42:40 +08:00
|
|
|
|
|
|
|
|
test "iter prefix":
|
|
|
|
|
initData(db)
|
|
|
|
|
check(toSeq(db.iterPrefix(prefix = "b")) ==
|
|
|
|
|
@[("ba", "2"), ("bb", "3")])
|
2019-11-16 17:42:48 +08:00
|
|
|
|
|
|
|
|
test "iter range":
|
|
|
|
|
initData(db)
|
|
|
|
|
check(toSeq(db.iterRange(start = "a", limit = "ba")) ==
|
|
|
|
|
@[("aa", "1"), ("ba", "2")])
|
|
|
|
|
|
|
|
|
|
test "iter range reverse":
|
|
|
|
|
initData(db)
|
|
|
|
|
check(toSeq(db.iterRange(start = "bb", limit = "b")) ==
|
|
|
|
|
@[("bb", "3"), ("ba", "2")])
|
2019-11-16 20:24:33 +08:00
|
|
|
|
|
|
|
|
test "iter with 0x00":
|
|
|
|
|
db.put("\0z1", "\0ff")
|
|
|
|
|
db.put("z2\0", "ff\0")
|
|
|
|
|
check(toSeq(db.iter()) == @[("\0z1", "\0ff"), ("z2\0", "ff\0")])
|
2019-12-14 18:11:20 +08:00
|
|
|
|
2019-12-14 18:05:05 +08:00
|
|
|
test "iter empty value":
|
|
|
|
|
db.put("a", "")
|
|
|
|
|
check(toSeq(db.iter()) == @[("a", "")])
|
|
|
|
|
|
|
|
|
|
test "iter empty key":
|
|
|
|
|
db.put("", "a")
|
|
|
|
|
check(toSeq(db.iter()) == @[("", "a")])
|
|
|
|
|
|
2020-02-12 23:29:11 +08:00
|
|
|
test "repair database":
|
|
|
|
|
initData(db)
|
|
|
|
|
db.close()
|
|
|
|
|
repairDb(dbName)
|
|
|
|
|
|
2019-12-14 18:11:20 +08:00
|
|
|
test "batch":
|
|
|
|
|
db.put("a", "1")
|
|
|
|
|
db.put("b", "2")
|
|
|
|
|
let batch = newBatch()
|
|
|
|
|
batch.put("a", "10")
|
|
|
|
|
batch.put("c", "30")
|
|
|
|
|
batch.delete("b")
|
|
|
|
|
db.write(batch)
|
|
|
|
|
check(toSeq(db.iter()) == @[("a", "10"), ("c", "30")])
|
|
|
|
|
|
|
|
|
|
test "batch append":
|
|
|
|
|
let batch = newBatch()
|
|
|
|
|
let batch2 = newBatch()
|
|
|
|
|
batch.put("a", "1")
|
|
|
|
|
batch2.put("b", "2")
|
|
|
|
|
batch2.delete("a")
|
|
|
|
|
batch.append(batch2)
|
|
|
|
|
db.write(batch)
|
|
|
|
|
check(toSeq(db.iter()) == @[("b", "2")])
|
|
|
|
|
|
|
|
|
|
test "batch clear":
|
|
|
|
|
let batch = newBatch()
|
|
|
|
|
batch.put("a", "1")
|
|
|
|
|
batch.clear()
|
|
|
|
|
batch.put("b", "2")
|
|
|
|
|
db.write(batch)
|
|
|
|
|
check(toSeq(db.iter()) == @[("b", "2")])
|
2019-12-14 18:11:56 +08:00
|
|
|
|
|
|
|
|
test "open with cache":
|
|
|
|
|
let ldb = leveldb.open(dbName & "-cache", cacheCapacity = 100000)
|
2020-02-12 23:29:11 +08:00
|
|
|
defer:
|
|
|
|
|
ldb.close()
|
|
|
|
|
removeDb(ldb.path)
|
2019-12-14 18:11:56 +08:00
|
|
|
ldb.put("a", "1")
|
|
|
|
|
check(toSeq(ldb.iter()) == @[("a", "1")])
|
2020-02-12 23:29:23 +08:00
|
|
|
|
|
|
|
|
test "open but no create":
|
|
|
|
|
expect LevelDbException:
|
|
|
|
|
let failed = leveldb.open(dbName & "-nocreate", create = false)
|
|
|
|
|
defer:
|
|
|
|
|
failed.close()
|
|
|
|
|
removeDb(failed.path)
|
|
|
|
|
|
|
|
|
|
test "open but no reuse":
|
|
|
|
|
let old = leveldb.open(dbName & "-noreuse", reuse = true)
|
|
|
|
|
defer:
|
|
|
|
|
old.close()
|
|
|
|
|
removeDb(old.path)
|
|
|
|
|
|
|
|
|
|
expect LevelDbException:
|
|
|
|
|
let failed = leveldb.open(old.path, reuse = false)
|
|
|
|
|
defer:
|
|
|
|
|
failed.close()
|
|
|
|
|
removeDb(failed.path)
|
2020-02-12 23:29:32 +08:00
|
|
|
|
|
|
|
|
test "no compress":
|
|
|
|
|
db.close()
|
|
|
|
|
let nc = leveldb.open(dbName, compressionType = ctNoCompression)
|
|
|
|
|
defer: nc.close()
|
|
|
|
|
nc.put("a", "1")
|
|
|
|
|
check(toSeq(nc.iter()) == @[("a", "1")])
|
2020-02-23 20:13:32 +08:00
|
|
|
|
|
|
|
|
suite "package":
|
|
|
|
|
|
|
|
|
|
test "import as package":
|
|
|
|
|
let (output, exitCode) = execNimble("install")
|
|
|
|
|
check exitCode == QuitSuccess
|
|
|
|
|
check output.contains("leveldb installed successfully.")
|
|
|
|
|
|
|
|
|
|
cd "tests/packagetest":
|
|
|
|
|
var (output, exitCode) = execNimble("build")
|
|
|
|
|
check exitCode == QuitSuccess
|
|
|
|
|
check output.contains("Building")
|
|
|
|
|
|
|
|
|
|
(output, exitCode) = execCmdEx("./packagetest")
|
|
|
|
|
checkpoint output
|
|
|
|
|
check exitCode == QuitSuccess
|
|
|
|
|
check output.contains("leveldb works.")
|