Compare commits

...

19 Commits

Author SHA1 Message Date
Jacek Sieka
5a0cd8de6b
chore: v0.2.1 (#6) 2025-12-11 12:14:30 +01:00
Slava
378ef63e26
fix: add CMAKE_POLICY_VERSION_MINIMUM=3.31 to make it working with cmake 4.0 (#4) 2025-04-01 14:44:25 +03:00
Ben Bierens
bd9b8394a7
Update to nim 2 x (#3)
* Change the LevelDbCmakeFlags option case

* Add nimbledeps to ignored files

* Increase version

* Add Nim 2.0.12 to the matrix

* Fixes STD_REGEX issue introduced by gtest/benchmark submodule

* Revert "Fixes STD_REGEX issue introduced by gtest/benchmark submodule"

This reverts commit b4db94d75300f9d638869279ab736571eda632e6.

* Disables building benchmark tests

---------

Co-authored-by: Arnaud <arnaud@status.im>
2025-02-11 12:06:00 +01:00
Ben
4da61d231a
version 0.1.6 2024-08-15 10:45:56 +02:00
Ben
3805148c2f
Skip building leveldb if already built 2024-08-15 10:33:33 +02:00
Ben
9e89afa856
bump to 0.1.5 2024-08-14 11:24:58 +02:00
Ben
37c92f69b5
Keeps the build folder 2024-08-14 11:23:45 +02:00
Ben
c70c51f5b3
Concurrent iterator tests 2024-05-28 10:56:16 +02:00
Ben
3cb21890d4
bumps to 0.1.4 2024-05-23 08:58:28 +02:00
Ben Bierens
5f0a4ea871
Symbol checks (#2)
* sets up checkers

* updates raw.nim

* Removes prints

* Removes automatic symbol check

* update

* Attempt to run cmake on every build

* Restores build.sh

* Updates readme

* Removes unnecessary include dir

* updates
2024-05-22 09:41:07 -07:00
Ben
f0d18f6d35
Adds raise-lists to Iter callbacks. 2024-05-22 09:29:58 +02:00
benbierens
06947b4b60
bumps to 0.1.13 2024-05-20 09:07:33 +02:00
benbierens
ec4754b7a7
Implements proper iter dispose 2024-05-20 08:41:36 +02:00
ThatBen
dfe142f00a example setup of checking c symbols at compile time 2024-05-15 11:29:38 +02:00
ThatBen
986ad266eb Fixes path in build.sh 2024-05-15 09:33:30 +02:00
Ben
f51e61c5ce
bump to 0.1.2 2024-05-14 09:49:07 +02:00
Ben
9dc532b856
Adds support for skips and limits to queryIter 2024-05-14 09:48:46 +02:00
Ben
e6ba737764
bumps to 0.1.1 2024-05-14 09:24:17 +02:00
Ben
760acd2767
implements query-iterator object 2024-05-14 09:23:08 +02:00
11 changed files with 493 additions and 128 deletions

View File

@ -8,14 +8,15 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest, macOS-latest, windows-latest]
nim: [stable, 1.6.18]
nim: [stable, 1.6.18, 2.0.12]
steps:
- uses: actions/checkout@v2
with:
submodules: true
- uses: iffy/install-nim@v4
- uses: jiro4989/setup-nim-action@v2
with:
version: ${{ matrix.nim }}
nim-version: ${{matrix.nim}}
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Build
run: nimble install -y
- name: Test

3
.gitignore vendored
View File

@ -8,4 +8,5 @@ leveldbtool
*.html
*.css
build
nimbledeps
*.exe

View File

@ -6,6 +6,8 @@ Original nim LevelDB wrapper: [HERE](https://github.com/zielmicha/leveldb.nim)
Replacing of system library dependency with self-contained C/CPP interoperability by (Codex.Storage)[https://codex.storage]
## Usage
Create a database:
```Nim
import leveldbstatic
@ -49,3 +51,25 @@ Iterate over subset of database content:
db.close()
```
## Compiling with optimizations
CMake is used during compilation to determine which of the following optimization options are enabled. You can set the following nim compiler flags to 0 or 1 to override them:
- fdatasync from <unistd.h> `--passC:-DHAVE_FDATASYNC=1`
- F_FULLSYNC from <fcntl.h> `--passC:-DHAVE_FULLFSYNC=1`
- O_CLOEXEC from <fcntl.h> `--passC:-DHAVE_O_CLOEXEC=1`
- crc32c from <crc32c/crc32c.h> `--passC:-DHAVE_CRC32C=1`
- snappy from <snappy.h> `--passC:-DHAVE_SNAPPY=1`
- zstd from <zstd.h> `--passC:-DHAVE_ZSTD=1`
## Updating
When you want to update this library to a new version of LevelDB, follow these steps:
- Update LevelDB submodule to new version.
- Run 'build.sh'.
- Run 'nimble build' and 'nimble test'.
- Make sure everything's working.
- Increment version of this library in 'leveldbstatic.nimble'.
- Commit the changes.
- Tag the commit with the new version number.
- Push.

View File

@ -21,7 +21,7 @@ rm -Rf "${sourceDir}/benchmarks"
rm "${sourceDir}/util/testutil.cc"
# Prelude:
cat "${root}/leveldb/prelude.nim" > "${output}"
cat "${root}/leveldbstatic/prelude.nim" > "${output}"
echo >> "${output}"
# assemble files to be compiled:
@ -47,10 +47,8 @@ toast \
--includeDirs="${sourceDir}/helpers/memenv" \
--includeDirs="${sourceDir}/port" \
--includeDirs="${sourceDir}/include" \
--includeDirs="${buildDir}/include" \
"${sourceDir}/include/leveldb/c.h" >> "${output}"
sed -i 's/\bpassC\b/passc/g' "${output}"
sed -i 's/{\.compile\:\ \"\./{\.compile\:\ root\ \&\ \"/g' "${output}"
sed -i 's/{\.passc\:\ \"-I\./{\.passc\:\ \"-I\"\ \&\ root\ \&\ \"/g' "${output}"

0
build/.gitkeep Normal file
View File

View File

@ -1,38 +0,0 @@
// Copyright 2017 The LevelDB Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.
#ifndef STORAGE_LEVELDB_PORT_PORT_CONFIG_H_
#define STORAGE_LEVELDB_PORT_PORT_CONFIG_H_
// Define to 1 if you have a definition for fdatasync() in <unistd.h>.
#if !defined(HAVE_FDATASYNC)
#define HAVE_FDATASYNC 1
#endif // !defined(HAVE_FDATASYNC)
// Define to 1 if you have a definition for F_FULLFSYNC in <fcntl.h>.
#if !defined(HAVE_FULLFSYNC)
#define HAVE_FULLFSYNC 0
#endif // !defined(HAVE_FULLFSYNC)
// Define to 1 if you have a definition for O_CLOEXEC in <fcntl.h>.
#if !defined(HAVE_O_CLOEXEC)
#define HAVE_O_CLOEXEC 1
#endif // !defined(HAVE_O_CLOEXEC)
// Define to 1 if you have Google CRC32C.
#if !defined(HAVE_CRC32C)
#define HAVE_CRC32C 0
#endif // !defined(HAVE_CRC32C)
// Define to 1 if you have Google Snappy.
#if !defined(HAVE_SNAPPY)
#define HAVE_SNAPPY 0
#endif // !defined(HAVE_SNAPPY)
// Define to 1 if you have Zstd.
#if !defined(HAVE_Zstd)
#define HAVE_ZSTD 0
#endif // !defined(HAVE_ZSTD)
#endif // STORAGE_LEVELDB_PORT_PORT_CONFIG_H_

View File

@ -76,6 +76,13 @@ type
LevelDbException* = object of CatchableError
IterNext* = proc(): (string, string) {.gcsafe, closure, raises: [LevelDbException].}
IterDispose* = proc() {.gcsafe, closure, raises: [].}
LevelDbQueryIter* = ref object
finished*: bool
next*: IterNext
dispose*: IterDispose
const
version* = block:
const configFile = "leveldbstatic.nimble"
@ -406,6 +413,81 @@ iterator iterRange*(self: LevelDb, start, limit: string): (string, string) =
break
yield (key, value)
proc getIterKey(iterPtr: ptr leveldb_iterator_t): string =
var len: csize_t
var str: cstring
str = leveldb_iter_key(iterPtr, addr len)
return newString(str, len)
proc getIterValue(iterPtr: ptr leveldb_iterator_t): string =
var len: csize_t
var str: cstring
str = leveldb_iter_value(iterPtr, addr len)
return newString(str, len)
proc seekToQueryStart(iterPtr: ptr leveldb_iterator_t, prefix: string, skip: int) =
if prefix.len > 0:
leveldb_iter_seek(iterPtr, prefix, prefix.len.csize_t)
else:
leveldb_iter_seek_to_first(iterPtr)
for i in 0..<skip:
leveldb_iter_next(iterPtr)
proc closeIter(iter: LevelDbQueryIter, iterPtr: ptr leveldb_iterator_t) =
iter.finished = true
leveldb_iter_destroy(iterPtr)
proc queryIter*(self: LevelDb, prefix: string = "", keysOnly: bool = false, skip: int = 0, limit: int = 0): LevelDbQueryIter =
var iterPtr = leveldb_create_iterator(self.db, self.readOptions)
seekToQueryStart(iterPtr, prefix, skip)
var
iter = LevelDbQueryIter()
remaining = limit
let emptyResponse = ("", "")
proc getNext(): (string, string) {.gcsafe, closure.} =
if iter.finished:
return emptyResponse
if leveldb_iter_valid(iterPtr) == levelDbFalse or (limit > 0 and remaining == 0):
iter.closeIter(iterPtr)
return emptyResponse
if limit > 0:
dec remaining
let
keyStr = getIterKey(iterPtr)
valueStr = if keysOnly: "" else: getIterValue(iterPtr)
var err: cstring = nil
leveldb_iter_get_error(iterPtr, addr err)
checkError(err)
leveldb_iter_next(iterPtr)
if prefix.len > 0:
if keyStr.startsWith(prefix):
return (keyStr, valueStr)
else:
iter.closeIter(iterPtr)
return emptyResponse
else:
return (keyStr, valueStr)
proc dispose() {.gcsafe, closure.} =
if not iter.finished:
iter.closeIter(iterPtr)
iter.finished = false
iter.next = getNext
iter.dispose = dispose
return iter
proc removeDb*(name: string) =
## Remove the database `name`.
var err: cstring = nil

View File

@ -1,6 +1,6 @@
# Package
version = "0.1.0"
version = "0.2.1"
author = "leveldbstatic authors"
description = "Statically linked LevelDB wrapper for Nim"
license = "MIT"

View File

@ -1,8 +1,46 @@
import os
const root = currentSourcePath.parentDir.parentDir
const envWindows = root/"vendor"/"util"/"env_windows.cc"
const envPosix = root/"vendor"/"util"/"env_posix.cc"
const
root = currentSourcePath.parentDir.parentDir
envWindows = root/"vendor"/"util"/"env_windows.cc"
envPosix = root/"vendor"/"util"/"env_posix.cc"
LevelDbCMakeFlags {.strdefine.} =
when defined(macosx):
"-DCMAKE_BUILD_TYPE=Release -DLEVELDB_BUILD_BENCHMARKS=OFF"
elif defined(windows):
"-G\"MSYS Makefiles\" -DCMAKE_BUILD_TYPE=Release -DLEVELDB_BUILD_BENCHMARKS=OFF"
else:
"-DCMAKE_BUILD_TYPE=Release -DLEVELDB_BUILD_BENCHMARKS=OFF"
LevelDbCMakeCommonFlags = " -DCMAKE_POLICY_VERSION_MINIMUM=3.31"
LevelDbDir {.strdefine.} = $(root/"vendor")
buildDir = $(root/"build")
proc buildLevelDb() =
if fileExists(buildDir/"Makefile"):
echo "LevelDB already build. Delete '" & buildDir & "' to force rebuild."
return
echo "Initializing submodule..."
discard gorge "git submodule deinit -f \"" & root & "\""
discard gorge "git submodule update --init --recursive --checkout \"" & root & "\""
echo "\nClean dir: \"" & buildDir & "\""
discard gorge "rm -rf " & buildDir
discard gorge "mkdir -p " & buildDir
let cmd = "cmake -S \"" & LevelDbDir & "\" -B \"" & buildDir & "\" " & LevelDbCMakeFlags & LevelDbCMakeCommonFlags
echo "\nBuilding LevelDB: " & cmd
let (output, exitCode) = gorgeEx cmd
if exitCode != 0:
discard gorge "rm -rf " & buildDir
echo output
raise (ref Defect)(msg: "Failed to build LevelDB")
static:
buildLevelDb()
when defined(windows):
{.compile: envWindows.}
@ -13,13 +51,3 @@ when defined(windows):
when defined(posix):
{.compile: envPosix.}
{.passc: "-DLEVELDB_PLATFORM_POSIX".}
{.passc: "-DHAVE_FDATASYNC=0".}
{.passc: "-DHAVE_FULLFSYNC=0".}
{.passc: "-DHAVE_O_CLOEXEC=0".}
{.passc: "-DHAVE_CRC32C=0".}
{.passc: "-DHAVE_SNAPPY=0".}
{.passc: "-DHAVE_ZSTD=0".}
{.passc: "-DHAVE_Zstd=0".}

View File

@ -1,8 +1,46 @@
import os
const root = currentSourcePath.parentDir.parentDir
const envWindows = root/"vendor"/"util"/"env_windows.cc"
const envPosix = root/"vendor"/"util"/"env_posix.cc"
const
root = currentSourcePath.parentDir.parentDir
envWindows = root/"vendor"/"util"/"env_windows.cc"
envPosix = root/"vendor"/"util"/"env_posix.cc"
LevelDbCMakeFlags {.strdefine.} =
when defined(macosx):
"-DCMAKE_BUILD_TYPE=Release -DLEVELDB_BUILD_BENCHMARKS=OFF"
elif defined(windows):
"-G\"MSYS Makefiles\" -DCMAKE_BUILD_TYPE=Release -DLEVELDB_BUILD_BENCHMARKS=OFF"
else:
"-DCMAKE_BUILD_TYPE=Release -DLEVELDB_BUILD_BENCHMARKS=OFF"
LevelDbCMakeCommonFlags = " -DCMAKE_POLICY_VERSION_MINIMUM=3.31"
LevelDbDir {.strdefine.} = $(root/"vendor")
buildDir = $(root/"build")
proc buildLevelDb() =
if fileExists(buildDir/"Makefile"):
echo "LevelDB already build. Delete '" & buildDir & "' to force rebuild."
return
echo "Initializing submodule..."
discard gorge "git submodule deinit -f \"" & root & "\""
discard gorge "git submodule update --init --recursive --checkout \"" & root & "\""
echo "\nClean dir: \"" & buildDir & "\""
discard gorge "rm -rf " & buildDir
discard gorge "mkdir -p " & buildDir
let cmd = "cmake -S \"" & LevelDbDir & "\" -B \"" & buildDir & "\" " & LevelDbCMakeFlags & LevelDbCMakeCommonFlags
echo "\nBuilding LevelDB: " & cmd
let (output, exitCode) = gorgeEx cmd
if exitCode != 0:
discard gorge "rm -rf " & buildDir
echo output
raise (ref Defect)(msg: "Failed to build LevelDB")
static:
buildLevelDb()
when defined(windows):
{.compile: envWindows.}
@ -14,19 +52,9 @@ when defined(posix):
{.compile: envPosix.}
{.passc: "-DLEVELDB_PLATFORM_POSIX".}
{.passc: "-DHAVE_FDATASYNC=0".}
{.passc: "-DHAVE_FULLFSYNC=0".}
{.passc: "-DHAVE_O_CLOEXEC=0".}
{.passc: "-DHAVE_CRC32C=0".}
{.passc: "-DHAVE_SNAPPY=0".}
{.passc: "-DHAVE_ZSTD=0".}
{.passc: "-DHAVE_Zstd=0".}
# Generated @ 2024-05-13T12:00:58+02:00
# Generated @ 2024-12-09T16:35:09+01:00
# Command line:
# /home/ben/.nimble/pkgs/nimterop-0.6.13/nimterop/toast --compile=./vendor/db/log_writer.cc --compile=./vendor/db/db_impl.cc --compile=./vendor/db/db_iter.cc --compile=./vendor/db/dumpfile.cc --compile=./vendor/db/c.cc --compile=./vendor/db/builder.cc --compile=./vendor/db/filename.cc --compile=./vendor/db/write_batch.cc --compile=./vendor/db/table_cache.cc --compile=./vendor/db/version_edit.cc --compile=./vendor/db/dbformat.cc --compile=./vendor/db/log_reader.cc --compile=./vendor/db/memtable.cc --compile=./vendor/db/version_set.cc --compile=./vendor/db/repair.cc --compile=./vendor/table/block.cc --compile=./vendor/table/two_level_iterator.cc --compile=./vendor/table/table_builder.cc --compile=./vendor/table/iterator.cc --compile=./vendor/table/block_builder.cc --compile=./vendor/table/merger.cc --compile=./vendor/table/format.cc --compile=./vendor/table/filter_block.cc --compile=./vendor/table/table.cc --compile=./vendor/util/hash.cc --compile=./vendor/util/arena.cc --compile=./vendor/util/options.cc --compile=./vendor/util/histogram.cc --compile=./vendor/util/crc32c.cc --compile=./vendor/util/env.cc --compile=./vendor/util/filter_policy.cc --compile=./vendor/util/bloom.cc --compile=./vendor/util/logging.cc --compile=./vendor/util/coding.cc --compile=./vendor/util/status.cc --compile=./vendor/util/cache.cc --compile=./vendor/util/comparator.cc --compile=./vendor/helpers/memenv/memenv.cc --pnim --preprocess --noHeader --includeDirs=./vendor --includeDirs=./vendor/helpers --includeDirs=./vendor/helpers/memenv --includeDirs=./vendor/port --includeDirs=./vendor/include --includeDirs=./build/include ./vendor/include/leveldb/c.h
# /home/arnaud/.nimble/pkgs2/nimterop-0.6.13-a93246b2ad5531db11e51de7b2d188c42d95576a/nimterop/toast --compile=./vendor/util/bloom.cc --compile=./vendor/util/arena.cc --compile=./vendor/util/env.cc --compile=./vendor/util/filter_policy.cc --compile=./vendor/util/histogram.cc --compile=./vendor/util/hash.cc --compile=./vendor/util/comparator.cc --compile=./vendor/util/options.cc --compile=./vendor/util/logging.cc --compile=./vendor/util/status.cc --compile=./vendor/util/coding.cc --compile=./vendor/util/cache.cc --compile=./vendor/util/crc32c.cc --compile=./vendor/table/table.cc --compile=./vendor/table/format.cc --compile=./vendor/table/table_builder.cc --compile=./vendor/table/block_builder.cc --compile=./vendor/table/merger.cc --compile=./vendor/table/block.cc --compile=./vendor/table/filter_block.cc --compile=./vendor/table/iterator.cc --compile=./vendor/table/two_level_iterator.cc --compile=./vendor/helpers/memenv/memenv.cc --compile=./vendor/db/filename.cc --compile=./vendor/db/dbformat.cc --compile=./vendor/db/c.cc --compile=./vendor/db/memtable.cc --compile=./vendor/db/version_set.cc --compile=./vendor/db/repair.cc --compile=./vendor/db/builder.cc --compile=./vendor/db/write_batch.cc --compile=./vendor/db/version_edit.cc --compile=./vendor/db/dumpfile.cc --compile=./vendor/db/db_impl.cc --compile=./vendor/db/log_reader.cc --compile=./vendor/db/table_cache.cc --compile=./vendor/db/db_iter.cc --compile=./vendor/db/log_writer.cc --pnim --preprocess --noHeader --includeDirs=./vendor --includeDirs=./vendor/helpers --includeDirs=./vendor/helpers/memenv --includeDirs=./vendor/port --includeDirs=./vendor/include ./vendor/include/leveldb/c.h
{.push hint[ConvFromXtoItselfNotNeeded]: off.}
import macros
@ -79,45 +107,44 @@ macro defineEnum(typ: untyped): untyped =
{.passc: "-I" & root & "/vendor/helpers/memenv".}
{.passc: "-I" & root & "/vendor/port".}
{.passc: "-I" & root & "/vendor/include".}
{.passc: "-I" & root & "/build/include".}
{.compile: root & "/vendor/db/log_writer.cc".}
{.compile: root & "/vendor/db/db_impl.cc".}
{.compile: root & "/vendor/db/db_iter.cc".}
{.compile: root & "/vendor/db/dumpfile.cc".}
{.compile: root & "/vendor/db/c.cc".}
{.compile: root & "/vendor/db/builder.cc".}
{.compile: root & "/vendor/util/bloom.cc".}
{.compile: root & "/vendor/util/arena.cc".}
{.compile: root & "/vendor/util/env.cc".}
{.compile: root & "/vendor/util/filter_policy.cc".}
{.compile: root & "/vendor/util/histogram.cc".}
{.compile: root & "/vendor/util/hash.cc".}
{.compile: root & "/vendor/util/comparator.cc".}
{.compile: root & "/vendor/util/options.cc".}
{.compile: root & "/vendor/util/logging.cc".}
{.compile: root & "/vendor/util/status.cc".}
{.compile: root & "/vendor/util/coding.cc".}
{.compile: root & "/vendor/util/cache.cc".}
{.compile: root & "/vendor/util/crc32c.cc".}
{.compile: root & "/vendor/table/table.cc".}
{.compile: root & "/vendor/table/format.cc".}
{.compile: root & "/vendor/table/table_builder.cc".}
{.compile: root & "/vendor/table/block_builder.cc".}
{.compile: root & "/vendor/table/merger.cc".}
{.compile: root & "/vendor/table/block.cc".}
{.compile: root & "/vendor/table/filter_block.cc".}
{.compile: root & "/vendor/table/iterator.cc".}
{.compile: root & "/vendor/table/two_level_iterator.cc".}
{.compile: root & "/vendor/helpers/memenv/memenv.cc".}
{.compile: root & "/vendor/db/filename.cc".}
{.compile: root & "/vendor/db/write_batch.cc".}
{.compile: root & "/vendor/db/table_cache.cc".}
{.compile: root & "/vendor/db/version_edit.cc".}
{.compile: root & "/vendor/db/dbformat.cc".}
{.compile: root & "/vendor/db/log_reader.cc".}
{.compile: root & "/vendor/db/c.cc".}
{.compile: root & "/vendor/db/memtable.cc".}
{.compile: root & "/vendor/db/version_set.cc".}
{.compile: root & "/vendor/db/repair.cc".}
{.compile: root & "/vendor/table/block.cc".}
{.compile: root & "/vendor/table/two_level_iterator.cc".}
{.compile: root & "/vendor/table/table_builder.cc".}
{.compile: root & "/vendor/table/iterator.cc".}
{.compile: root & "/vendor/table/block_builder.cc".}
{.compile: root & "/vendor/table/merger.cc".}
{.compile: root & "/vendor/table/format.cc".}
{.compile: root & "/vendor/table/filter_block.cc".}
{.compile: root & "/vendor/table/table.cc".}
{.compile: root & "/vendor/util/hash.cc".}
{.compile: root & "/vendor/util/arena.cc".}
{.compile: root & "/vendor/util/options.cc".}
{.compile: root & "/vendor/util/histogram.cc".}
{.compile: root & "/vendor/util/crc32c.cc".}
{.compile: root & "/vendor/util/env.cc".}
{.compile: root & "/vendor/util/filter_policy.cc".}
{.compile: root & "/vendor/util/bloom.cc".}
{.compile: root & "/vendor/util/logging.cc".}
{.compile: root & "/vendor/util/coding.cc".}
{.compile: root & "/vendor/util/status.cc".}
{.compile: root & "/vendor/util/cache.cc".}
{.compile: root & "/vendor/util/comparator.cc".}
{.compile: root & "/vendor/helpers/memenv/memenv.cc".}
{.compile: root & "/vendor/db/builder.cc".}
{.compile: root & "/vendor/db/write_batch.cc".}
{.compile: root & "/vendor/db/version_edit.cc".}
{.compile: root & "/vendor/db/dumpfile.cc".}
{.compile: root & "/vendor/db/db_impl.cc".}
{.compile: root & "/vendor/db/log_reader.cc".}
{.compile: root & "/vendor/db/table_cache.cc".}
{.compile: root & "/vendor/db/db_iter.cc".}
{.compile: root & "/vendor/db/log_writer.cc".}
defineEnum(Enum_ch1)
const
leveldb_no_compression* = (0).cint

View File

@ -21,7 +21,10 @@ proc execNimble(args: varargs[string]): tuple[output: string, exitCode: int] =
quotedArgs.insert("-y")
quotedArgs.insert("--nimbleDir:" & tmpNimbleDir)
quotedArgs.insert("nimble")
quotedArgs = quotedArgs.map(proc (x: string): string = "\"" & x & "\"")
quotedArgs = quotedArgs.map(
proc(x: string): string =
"\"" & x & "\""
)
let cmd = quotedArgs.join(" ")
result = execCmdEx(cmd)
@ -33,7 +36,10 @@ proc execTool(args: varargs[string]): tuple[output: string, exitCode: int] =
quotedArgs.insert(tmpDbDir)
quotedArgs.insert("--database")
quotedArgs.insert(findExe(tmpNimbleDir / "bin" / "leveldbtool"))
quotedArgs = quotedArgs.map(proc (x: string): string = "\"" & x & "\"")
quotedArgs = quotedArgs.map(
proc(x: string): string =
"\"" & x & "\""
)
if not dirExists(tmpDbDir):
createDir(tmpDbDir)
@ -44,7 +50,6 @@ proc execTool(args: varargs[string]): tuple[output: string, exitCode: int] =
checkpoint(result.output)
suite "leveldb":
setup:
let env = leveldb_create_default_env()
let dbName = $(leveldb_env_get_test_directory(env))
@ -97,33 +102,27 @@ suite "leveldb":
test "iter reverse":
initData(db)
check(toSeq(db.iter(reverse = true)) ==
@[("bb", "3"), ("ba", "2"), ("aa", "1")])
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")])
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")])
check(toSeq(db.iter(seek = "ab", reverse = true)) == @[("ba", "2"), ("aa", "1")])
test "iter prefix":
initData(db)
check(toSeq(db.iterPrefix(prefix = "b")) ==
@[("ba", "2"), ("bb", "3")])
check(toSeq(db.iterPrefix(prefix = "b")) == @[("ba", "2"), ("bb", "3")])
test "iter range":
initData(db)
check(toSeq(db.iterRange(start = "a", limit = "ba")) ==
@[("aa", "1"), ("ba", "2")])
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")])
check(toSeq(db.iterRange(start = "bb", limit = "b")) == @[("bb", "3"), ("ba", "2")])
test "iter with 0x00":
db.put("\0z1", "\0ff")
@ -201,21 +200,265 @@ suite "leveldb":
test "no compress":
db.close()
let nc = leveldb.open(dbName, compressionType = ctNoCompression)
defer: nc.close()
defer:
nc.close()
nc.put("a", "1")
check(toSeq(nc.iter()) == @[("a", "1")])
suite "package":
suite "leveldb queryIter":
setup:
let env = leveldb_create_default_env()
let dbName = $(leveldb_env_get_test_directory(env))
let db = leveldb.open(dbName)
let
k1 = "k1"
k2 = "k2"
k3 = "l3"
v1 = "v1"
v2 = "v2"
v3 = "v3"
empty = ("", "")
db.put(k1, v1)
db.put(k2, v2)
db.put(k3, v3)
teardown:
db.close()
removeDb(dbName)
test "iterates all keys and values":
let iter = db.queryIter()
check:
not iter.finished
iter.next() == (k1, v1)
not iter.finished
iter.next() == (k2, v2)
not iter.finished
iter.next() == (k3, v3)
not iter.finished
iter.next() == empty
iter.finished
test "iterate until disposed":
let iter = db.queryIter()
check:
not iter.finished
iter.next() == (k1, v1)
not iter.finished
iter.next() == (k2, v2)
not iter.finished
iter.dispose()
check:
iter.finished
iter.next() == empty
iter.finished
test "skip":
let iter = db.queryIter(skip = 1)
check:
not iter.finished
iter.next() == (k2, v2)
not iter.finished
iter.next() == (k3, v3)
not iter.finished
iter.next() == empty
iter.finished
test "limit":
let iter = db.queryIter(limit = 2)
check:
not iter.finished
iter.next() == (k1, v1)
not iter.finished
iter.next() == (k2, v2)
not iter.finished
iter.next() == empty
iter.finished
test "iterates only keys":
let iter = db.queryIter(keysOnly = true)
check:
not iter.finished
iter.next() == (k1, "")
not iter.finished
iter.next() == (k2, "")
not iter.finished
iter.next() == (k3, "")
not iter.finished
iter.next() == empty
iter.finished
test "iterates only 'k', both keys and values":
let iter = db.queryIter(prefix = "k")
check:
not iter.finished
iter.next() == (k1, v1)
not iter.finished
iter.next() == (k2, v2)
not iter.finished
iter.next() == empty
iter.finished
test "iterates only 'k', skip":
let iter = db.queryIter(prefix = "k", skip = 1)
check:
not iter.finished
iter.next() == (k2, v2)
not iter.finished
iter.next() == empty
iter.finished
test "iterate only 'k', limit":
let iter = db.queryIter(prefix = "k", limit = 1)
check:
not iter.finished
iter.next() == (k1, v1)
not iter.finished
iter.next() == empty
iter.finished
test "iterates only 'k', only keys":
let iter = db.queryIter(prefix = "k", keysOnly = true)
check:
not iter.finished
iter.next() == (k1, "")
not iter.finished
iter.next() == (k2, "")
not iter.finished
iter.next() == empty
iter.finished
test "concurrent iterators - 1":
let
iter1 = db.queryIter()
iter2 = db.queryIter()
check:
# 1, then 2
not iter1.finished
iter1.next() == (k1, v1)
not iter2.finished
iter2.next() == (k1, v1)
# 1, 1, then 2, 2
not iter1.finished
iter1.next() == (k2, v2)
not iter1.finished
iter1.next() == (k3, v3)
not iter2.finished
iter2.next() == (k2, v2)
not iter2.finished
iter2.next() == (k3, v3)
# finish 1, then finish 2
not iter1.finished
iter1.next() == empty
not iter2.finished
iter2.next() == empty
iter1.finished
iter2.finished
test "concurrent iterators - 2":
let
iter1 = db.queryIter()
iter2 = db.queryIter()
check:
# 1, then 2
not iter1.finished
iter1.next() == (k1, v1)
not iter2.finished
iter2.next() == (k1, v1)
# finish 1
not iter1.finished
iter1.next() == (k2, v2)
not iter1.finished
iter1.next() == (k3, v3)
not iter1.finished
iter1.next() == empty
iter1.finished
# finish 2
not iter2.finished
iter2.next() == (k2, v2)
not iter2.finished
iter2.next() == (k3, v3)
not iter2.finished
iter2.next() == empty
iter2.finished
test "concurrent iterators - dispose":
let
iter1 = db.queryIter()
iter2 = db.queryIter()
check:
# 1, then 2
not iter1.finished
iter1.next() == (k1, v1)
not iter2.finished
iter2.next() == (k1, v1)
# dispose 1
iter1.dispose()
check:
iter1.finished
iter1.next() == empty
iter1.finished
# finish 2
not iter2.finished
iter2.next() == (k2, v2)
not iter2.finished
iter2.next() == (k3, v3)
not iter2.finished
iter2.next() == empty
iter2.finished
test "modify while iterating":
let iter = db.queryIter()
check:
not iter.finished
iter.next() == (k1, v1)
not iter.finished
iter.next() == (k2, v2)
# insert
let
k4 = "k4"
v4 = "v4"
db.put(k4, v4)
check:
not iter.finished
iter.next() == (k3, v3)
not iter.finished
iter.next() == empty
iter.finished
suite "package":
setup:
removeDir(tmpDir)
test "import as package":
let (output, exitCode) = execNimble("install")
check exitCode == QuitSuccess
check output.contains("leveldbstatic installed successfully.")
check output.contains("leveldbstatic installed successfully.") or
output.contains("LevelDB already build")
cd "tests"/"packagetest":
cd "tests" / "packagetest":
var (output, exitCode) = execNimble("build")
check exitCode == QuitSuccess
check output.contains("Building")
@ -226,7 +469,6 @@ suite "package":
check output.contains("leveldb works.")
suite "tool":
setup:
removeDir(tmpDir)