nim-datastore/tests/datastore/sql/testsqliteds.nim

352 lines
7.8 KiB
Nim
Raw Normal View History

2022-09-16 21:15:08 -06:00
import std/options
import std/os
import std/sequtils
from std/algorithm import sort, reversed
2022-09-16 21:15:08 -06:00
2023-09-20 22:12:53 -07:00
import pkg/unittest2
2022-09-16 21:15:08 -06:00
import pkg/chronos
import pkg/stew/results
import pkg/stew/byteutils
import pkg/datastore/sql/sqliteds
2023-09-20 22:12:53 -07:00
import pkg/datastore/key
2022-09-16 21:15:08 -06:00
import ../dscommontests
2022-09-19 15:53:38 -06:00
2023-09-25 17:49:17 -07:00
proc testBasic[K, V](
ds: SQLiteBackend[K,V],
2023-09-20 23:07:52 -07:00
key: K,
bytes: V,
otherBytes: V,
2023-09-25 17:49:17 -07:00
batch: seq[DbBatchEntry[K, V]],
2023-09-25 19:03:59 -07:00
extended = true
2023-09-20 22:49:11 -07:00
) =
2022-09-19 15:53:38 -06:00
2023-09-20 22:12:53 -07:00
test "put":
ds.put(key, bytes).tryGet()
2022-09-16 21:15:08 -06:00
2023-09-20 22:12:53 -07:00
test "get":
check:
ds.get(key).tryGet() == bytes
2022-09-16 21:15:08 -06:00
2023-09-20 22:12:53 -07:00
test "put update":
ds.put(key, otherBytes).tryGet()
2022-09-16 21:15:08 -06:00
2023-09-20 22:12:53 -07:00
test "get updated":
check:
ds.get(key).tryGet() == otherBytes
2022-09-20 09:21:41 -06:00
2023-09-20 22:12:53 -07:00
test "delete":
ds.delete(key).tryGet()
2022-09-16 21:15:08 -06:00
2023-09-20 22:12:53 -07:00
test "contains":
2023-09-20 22:23:18 -07:00
check key notin ds
2022-09-16 21:15:08 -06:00
2023-09-20 22:12:53 -07:00
test "put batch":
2022-09-16 21:15:08 -06:00
2023-09-20 22:12:53 -07:00
ds.put(batch).tryGet
2022-09-16 21:15:08 -06:00
2023-09-20 23:28:50 -07:00
for (k, v) in batch:
check: ds.has(k).tryGet
2022-09-16 21:15:08 -06:00
2023-09-20 22:12:53 -07:00
test "delete batch":
2023-09-20 23:28:50 -07:00
var keys: seq[K]
for (k, v) in batch:
keys.add(k)
2022-09-16 21:15:08 -06:00
2023-09-20 23:28:50 -07:00
ds.delete(keys).tryGet
2022-09-16 21:15:08 -06:00
2023-09-20 23:28:50 -07:00
for (k, v) in batch:
2023-09-20 22:12:53 -07:00
check: not ds.has(k).tryGet
test "handle missing key":
2023-09-25 17:49:17 -07:00
when K is KeyId:
let key = KeyId.new Key.init("/missing/key").tryGet().id()
elif K is string:
let key = $KeyId.new Key.init("/missing/key").tryGet().id()
2022-09-16 21:15:08 -06:00
2023-09-20 22:12:53 -07:00
expect(DatastoreKeyNotFound):
discard ds.get(key).tryGet() # non existing key
2023-09-20 22:49:11 -07:00
suite "Test Basic SQLiteDatastore":
let
2023-09-25 17:49:17 -07:00
ds = newSQLiteBackend[string, seq[byte]](path=Memory).tryGet()
2023-09-20 22:49:11 -07:00
keyFull = Key.init("a:b/c/d:e").tryGet()
key = keyFull.id()
bytes = "some bytes".toBytes
otherBytes = "some other bytes".toBytes
2023-09-20 23:16:24 -07:00
var batch: seq[tuple[key: string, data: seq[byte]]]
for k in 0..<100:
let kk = Key.init(key, $k).tryGet().id()
batch.add( (kk, @[k.byte]) )
2023-09-20 22:49:11 -07:00
suiteTeardown:
ds.close().tryGet()
2023-09-20 23:07:52 -07:00
2023-09-25 17:49:17 -07:00
testBasic(ds, key, bytes, otherBytes, batch)
2023-09-20 23:07:52 -07:00
2023-09-20 23:28:50 -07:00
suite "Test DataBuffer SQLiteDatastore":
let
2023-09-25 17:35:37 -07:00
ds = newSQLiteBackend[KeyId, DataBuffer](Memory).tryGet()
2023-09-20 23:28:50 -07:00
keyFull = Key.init("a:b/c/d:e").tryGet()
key = KeyId.new keyFull.id()
bytes = DataBuffer.new "some bytes"
otherBytes = DataBuffer.new "some other bytes"
var batch: seq[tuple[key: KeyId, data: DataBuffer]]
for k in 0..<100:
let kk = Key.init(keyFull.id(), $k).tryGet().id()
batch.add( (KeyId.new kk, DataBuffer.new @[k.byte]) )
2023-09-20 23:16:24 -07:00
2023-09-20 23:28:50 -07:00
suiteTeardown:
ds.close().tryGet()
2023-09-20 23:44:09 -07:00
2023-09-20 23:28:50 -07:00
testBasic(ds, key, bytes, otherBytes, batch)
2023-09-21 18:49:08 -07:00
suite "queryTests":
setup:
2023-09-25 20:02:01 -07:00
let
ds = newSQLiteBackend[KeyId, DataBuffer](Memory).tryGet()
key1 = KeyId.new "/a"
key2 = KeyId.new "/a/b"
key3 = KeyId.new "/a/b/c"
val1 = DataBuffer.new "value for 1"
val2 = DataBuffer.new "value for 2"
val3 = DataBuffer.new "value for 3"
2023-09-21 18:49:08 -07:00
test "Key should query all keys and all it's children":
let
2023-09-25 19:58:03 -07:00
q = dbQuery(key=key1, value=true)
2023-09-21 18:49:08 -07:00
ds.put(key1, val1).tryGet
ds.put(key2, val2).tryGet
ds.put(key3, val3).tryGet
2023-09-25 15:54:07 -07:00
var
handle = ds.query(q).tryGet
2023-09-25 19:14:10 -07:00
res = handle.iter().toSeq().mapIt(it.tryGet())
2023-09-21 18:49:08 -07:00
check:
res.len == 3
res[0].key.get == key1
2023-09-25 15:43:27 -07:00
res[0].data == val1
2023-09-21 18:49:08 -07:00
2023-09-25 16:08:59 -07:00
res[1].key.get == key2
res[1].data == val2
2023-09-21 18:49:08 -07:00
2023-09-25 16:08:59 -07:00
res[2].key.get == key3
res[2].data == val3
2023-09-21 18:49:08 -07:00
2023-09-25 16:15:35 -07:00
test "query should cancel":
let
2023-09-25 19:58:03 -07:00
q = dbQuery(key= key1, value= true)
2023-09-25 16:15:35 -07:00
ds.put(key1, val1).tryGet
ds.put(key2, val2).tryGet
ds.put(key3, val3).tryGet
var
handle = ds.query(q).tryGet
2023-09-25 18:12:48 -07:00
var res: seq[DbQueryResponse[KeyId, DataBuffer]]
2023-09-25 16:15:35 -07:00
var cnt = 0
for item in handle.iter():
cnt.inc
res.insert(item.tryGet(), 0)
if cnt > 1:
handle.cancel = true
check:
handle.cancel == true
handle.closed == true
res.len == 2
res[0].key.get == key2
res[0].data == val2
2023-09-25 19:14:10 -07:00
res[1].key.get == key1
res[1].data == val1
2023-09-25 16:15:35 -07:00
2023-09-25 18:05:35 -07:00
test "Key should query all keys without values":
let
2023-09-25 19:58:03 -07:00
q = dbQuery(key= key1, value= false)
2023-09-21 18:49:08 -07:00
2023-09-25 18:05:35 -07:00
ds.put(key1, val1).tryGet
ds.put(key2, val2).tryGet
ds.put(key3, val3).tryGet
2023-09-21 18:49:08 -07:00
2023-09-25 18:05:35 -07:00
var
handle = ds.query(q).tryGet
let
2023-09-25 19:14:10 -07:00
res = handle.iter().toSeq().mapIt(it.tryGet())
2023-09-25 18:05:35 -07:00
check:
res.len == 3
res[0].key.get == key1
res[0].data.len == 0
2023-09-21 18:49:08 -07:00
2023-09-25 18:05:35 -07:00
res[1].key.get == key2
res[1].data.len == 0
2023-09-21 18:49:08 -07:00
2023-09-25 18:05:35 -07:00
res[2].key.get == key3
res[2].data.len == 0
2023-09-21 18:49:08 -07:00
2023-09-25 18:12:48 -07:00
test "Key should not query parent":
let
2023-09-25 19:58:03 -07:00
q = dbQuery(key= key2, value= true)
2023-09-21 18:49:08 -07:00
2023-09-25 18:12:48 -07:00
ds.put(key1, val1).tryGet
ds.put(key2, val2).tryGet
ds.put(key3, val3).tryGet
2023-09-21 18:49:08 -07:00
2023-09-25 18:12:48 -07:00
var
handle = ds.query(q).tryGet
let
2023-09-25 19:14:10 -07:00
res = handle.iter().toSeq().mapIt(it.tryGet())
2023-09-21 18:49:08 -07:00
2023-09-25 18:12:48 -07:00
check:
res.len == 2
res[0].key.get == key2
res[0].data == val2
res[1].key.get == key3
res[1].data == val3
2023-09-21 18:49:08 -07:00
2023-09-25 18:59:03 -07:00
test "Key should all list all keys at the same level":
let
queryKey = Key.init("/a").tryGet
2023-09-25 19:58:03 -07:00
q = dbQuery(key= key1, value= true)
2023-09-21 18:49:08 -07:00
2023-09-25 18:59:03 -07:00
ds.put(key1, val1).tryGet
ds.put(key2, val2).tryGet
ds.put(key3, val3).tryGet
2023-09-21 18:49:08 -07:00
2023-09-25 18:59:03 -07:00
var
handle = ds.query(q).tryGet
2023-09-25 19:14:10 -07:00
res = handle.iter().toSeq().mapIt(it.tryGet())
2023-09-21 18:49:08 -07:00
2023-09-25 18:59:03 -07:00
res.sort do (a, b: DbQueryResponse[KeyId, DataBuffer]) -> int:
cmp($a.key.get, $b.key.get)
2023-09-21 18:49:08 -07:00
2023-09-25 18:59:03 -07:00
check:
res.len == 3
res[0].key.get == key1
res[0].data == val1
2023-09-21 18:49:08 -07:00
2023-09-25 18:59:03 -07:00
res[1].key.get == key2
res[1].data == val2
2023-09-21 18:49:08 -07:00
2023-09-25 18:59:03 -07:00
res[2].key.get == key3
res[2].data == val3
2023-09-21 18:49:08 -07:00
2023-09-25 19:03:59 -07:00
test "Should apply limit":
let
key = Key.init("/a").tryGet
2023-09-25 19:58:03 -07:00
q = dbQuery(key= key1, limit= 10, value= false)
2023-09-21 18:49:08 -07:00
2023-09-25 19:03:59 -07:00
for i in 0..<100:
let
key = KeyId.new $Key.init(key, Key.init("/" & $i).tryGet).tryGet
val = DataBuffer.new("val " & $i)
2023-09-21 18:49:08 -07:00
2023-09-25 19:03:59 -07:00
ds.put(key, val).tryGet
2023-09-21 18:49:08 -07:00
2023-09-25 19:03:59 -07:00
var
handle = ds.query(q).tryGet
let
2023-09-25 19:14:10 -07:00
res = handle.iter().toSeq().mapIt(it.tryGet())
2023-09-21 18:49:08 -07:00
2023-09-25 19:03:59 -07:00
check:
res.len == 10
2023-09-21 18:49:08 -07:00
2023-09-25 19:54:22 -07:00
test "Should not apply offset":
let
key = Key.init("/a").tryGet
keyId = KeyId.new $key
2023-09-25 19:58:03 -07:00
q = dbQuery(key= keyId, offset= 90)
2023-09-21 18:49:08 -07:00
2023-09-25 19:54:22 -07:00
for i in 0..<100:
let
key = KeyId.new $Key.init(key, Key.init("/" & $i).tryGet).tryGet
val = DataBuffer.new("val " & $i)
2023-09-21 18:49:08 -07:00
2023-09-25 19:54:22 -07:00
ds.put(key, val).tryGet
2023-09-21 18:49:08 -07:00
2023-09-25 19:54:22 -07:00
var
qr = ds.query(q)
2023-09-25 20:19:33 -07:00
# echo "RES: ", qr.repr
2023-09-21 18:49:08 -07:00
2023-09-25 19:54:22 -07:00
var
handle = ds.query(q).tryGet
let
res = handle.iter().toSeq().mapIt(it.tryGet())
2023-09-25 20:19:33 -07:00
# echo "RES: ", res.mapIt(it.key)
2023-09-25 19:54:22 -07:00
check:
res.len == 10
2023-09-21 18:49:08 -07:00
2023-09-25 20:20:37 -07:00
test "Should not apply offset and limit":
let
key = Key.init("/a").tryGet
keyId = KeyId.new $key
q = dbQuery(key= keyId, offset= 95, limit= 5)
2023-09-21 18:49:08 -07:00
2023-09-25 20:20:37 -07:00
for i in 0..<100:
let
key = KeyId.new $Key.init(key, Key.init("/" & $i).tryGet).tryGet
val = DataBuffer.new("val " & $i)
2023-09-21 18:49:08 -07:00
2023-09-25 20:20:37 -07:00
ds.put(key, val).tryGet
2023-09-21 18:49:08 -07:00
2023-09-25 20:20:37 -07:00
var
handle = ds.query(q).tryGet
2023-09-25 20:24:25 -07:00
res = handle.iter().toSeq().mapIt(it.tryGet())
2023-09-21 18:49:08 -07:00
2023-09-25 20:20:37 -07:00
check:
res.len == 5
2023-09-21 18:49:08 -07:00
2023-09-25 20:20:37 -07:00
for i in 0..<res.high:
let
val = DataBuffer.new("val " & $(i + 95))
key = KeyId.new $Key.init(key, Key.init("/" & $(i + 95)).tryGet).tryGet
2023-09-21 18:49:08 -07:00
2023-09-25 20:20:37 -07:00
check:
res[i].key.get == key
2023-09-25 20:24:25 -07:00
# res[i].data == val
2023-09-21 18:49:08 -07:00
2023-09-21 19:08:19 -07:00
# test "Should apply sort order - descending":
# let
# key = Key.init("/a").tryGet
# keyId = KeyId.new $key
# q = DbQuery(key: keyId, sort: SortOrder.Descending)
2023-09-21 18:49:08 -07:00
2023-09-21 19:08:19 -07:00
# var kvs: seq[DbQueryResponse]
# for i in 0..<100:
# let
# k = KeyId.new $Key.init(key, Key.init("/" & $i).tryGet).tryGet
# val = DataBuffer.new ("val " & $i)
2023-09-21 18:49:08 -07:00
2023-09-21 19:08:19 -07:00
# kvs.add((k.some, val))
# ds.put(k, val).tryGet
2023-09-21 18:49:08 -07:00
2023-09-21 19:08:19 -07:00
# # lexicographic sort, as it comes from the backend
# kvs.sort do (a, b: DbQueryResponse) -> int:
# cmp($a.key.get, $b.key.get)
2023-09-21 18:49:08 -07:00
2023-09-21 19:08:19 -07:00
# kvs = kvs.reversed
# let
# (handle, iter) = ds.query(q).tryGet
# res = iter.mapIt(it.tryGet())
2023-09-21 18:49:08 -07:00
2023-09-21 19:08:19 -07:00
# check:
# res.len == 100
2023-09-21 18:49:08 -07:00
2023-09-21 19:08:19 -07:00
# for i, r in res[1..^1]:
# check:
# res[i].key.get == kvs[i].key.get
# res[i].data == kvs[i].data