import std/options import std/sequtils from std/algorithm import sort, reversed import pkg/asynctest import pkg/chronos import pkg/stew/results import pkg/stew/byteutils import pkg/datastore template queryTests*(ds: Datastore, extended = true) {.dirty.} = var key1: Key key2: Key key3: Key val1: seq[byte] val2: seq[byte] val3: seq[byte] setupAll: key1 = Key.init("/a").tryGet key2 = Key.init("/a/b").tryGet key3 = Key.init("/a/b/c").tryGet val1 = "value for 1".toBytes val2 = "value for 2".toBytes val3 = "value for 3".toBytes test "Key should query all keys and all it's children": let q = Query.init(key1) (await ds.put(key1, val1)).tryGet (await ds.put(key2, val2)).tryGet (await ds.put(key3, val3)).tryGet let iter = (await ds.query(q)).tryGet var res: seq[QueryResponse] while not iter.finished: let val = await iter.next() let qr = val.tryGet() if qr.key.isSome: res.add qr check: res.len == 3 res[0].key.get == key1 res[0].data == val1 res[1].key.get == key2 res[1].data == val2 res[2].key.get == key3 res[2].data == val3 (await iter.dispose()).tryGet # test "Key should query all keys without values": # let # q = Query.init(key1, value = false) # (await ds.put(key1, val1)).tryGet # (await ds.put(key2, val2)).tryGet # (await ds.put(key3, val3)).tryGet # let # res = tryGet(await ds.query(q).waitForAllQueryResults()) # check: # res.len == 3 # res[0].key.get == key1 # res[0].data.len == 0 # res[1].key.get == key2 # res[1].data.len == 0 # res[2].key.get == key3 # res[2].data.len == 0 # test "Key should not query parent": # let # q = Query.init(key2) # (await ds.put(key1, val1)).tryGet # (await ds.put(key2, val2)).tryGet # (await ds.put(key3, val3)).tryGet # let # res = tryGet(await ds.query(q).waitForAllQueryResults()) # check: # res.len == 2 # res[0].key.get == key2 # res[0].data == val2 # res[1].key.get == key3 # res[1].data == val3 # test "Key should all list all keys at the same level": # let # queryKey = Key.init("/a").tryGet # q = Query.init(queryKey) # (await ds.put(key1, val1)).tryGet # (await ds.put(key2, val2)).tryGet # (await ds.put(key3, val3)).tryGet # let # iter = (await ds.query(q)).tryGet # var # res = tryGet(await ds.query(q).waitForAllQueryResults()) # res.sort do (a, b: QueryResponse) -> int: # cmp(a.key.get.id, b.key.get.id) # check: # res.len == 3 # res[0].key.get == key1 # res[0].data == val1 # res[1].key.get == key2 # res[1].data == val2 # res[2].key.get == key3 # res[2].data == val3 # (await iter.dispose()).tryGet # if extended: # test "Should apply limit": # let # key = Key.init("/a").tryGet # q = Query.init(key, limit = 10) # for i in 0..<100: # let # key = Key.init(key, Key.init("/" & $i).tryGet).tryGet # val = ("val " & $i).toBytes # (await ds.put(key, val)).tryGet # let # res = tryGet(await ds.query(q).waitForAllQueryResults()) # check: # res.len == 10 # test "Should not apply offset": # let # key = Key.init("/a").tryGet # q = Query.init(key, offset = 90) # for i in 0..<100: # let # key = Key.init(key, Key.init("/" & $i).tryGet).tryGet # val = ("val " & $i).toBytes # (await ds.put(key, val)).tryGet # let # res = tryGet(await ds.query(q).waitForAllQueryResults()) # check: # res.len == 10 # test "Should not apply offset and limit": # let # key = Key.init("/a").tryGet # q = Query.init(key, offset = 95, limit = 5) # for i in 0..<100: # let # key = Key.init(key, Key.init("/" & $i).tryGet).tryGet # val = ("val " & $i).toBytes # (await ds.put(key, val)).tryGet # let # res = tryGet(await ds.query(q).waitForAllQueryResults()) # check: # res.len == 5 # for i in 0.. int: # cmp(a.key.get.id, b.key.get.id) # kvs = kvs.reversed # let # res = tryGet(await ds.query(q).waitForAllQueryResults()) # check: # res.len == 100 # for i, r in res[1..^1]: # check: # res[i].key.get == kvs[i].key.get # res[i].data == kvs[i].data