Add persistence tests for lists

next
Sayan Nandan 3 years ago
parent 4af6bef7de
commit f446feaac6
No known key found for this signature in database
GPG Key ID: 8BC07A0A4D41DD52

@ -1,5 +1,5 @@
/*
* Created on Thu Mar 17 2022
* Created on Sat Mar 19 2022
*
* This file is a part of Skytable
* Skytable (formerly known as TerrabaseDB or Skybase) is a free and open-source
@ -24,79 +24,19 @@
*
*/
use super::{persist_load, persist_store, PERSIST_TEST_SET_SIZE};
use sky_macros::dbtest_func as dbtest;
use skytable::{aio::Connection, query, types::RawString, Element, Query, RespCode};
const PERIST_TEST_SET_SIZE: usize = 4;
trait AsQueryItem {
fn push_into_query(&self, query: &mut Query);
fn as_element(&self) -> Element;
}
impl AsQueryItem for &'static [u8] {
fn push_into_query(&self, query: &mut Query) {
query.push(RawString::from(self.to_vec()));
}
fn as_element(&self) -> Element {
Element::Binstr(self.to_vec())
}
}
impl AsQueryItem for &'static str {
fn push_into_query(&self, query: &mut Query) {
query.push(*self);
}
fn as_element(&self) -> Element {
Element::String(self.to_string())
}
}
async fn persist_store<K: AsQueryItem, V: AsQueryItem>(
con: &mut Connection,
table_id: &str,
declaration: &str,
input: [(K, V); PERIST_TEST_SET_SIZE],
) {
create_table_and_switch!(con, table_id, declaration);
for (key, value) in input {
let mut query = Query::from("set");
key.push_into_query(&mut query);
value.push_into_query(&mut query);
runeq!(con, query, Element::RespCode(RespCode::Okay))
}
}
async fn persist_load<K: AsQueryItem, V: AsQueryItem>(
con: &mut Connection,
table_id: &str,
input: [(K, V); PERIST_TEST_SET_SIZE],
) {
switch_entity!(con, table_id);
for (key, value) in input {
let mut q = Query::from("get");
key.push_into_query(&mut q);
runeq!(con, q, value.as_element());
}
// now delete this table, freeing it up for the next suite run
switch_entity!(con, "default:default");
runeq!(
con,
query!("drop", "table", table_id),
Element::RespCode(RespCode::Okay)
);
}
const PERSIST_CFG_KEYMAP_BIN_BIN_TABLE: &str = "testsuite:persist_bin_bin_tbl";
const PERSIST_DATA_KEYMAP_BIN_BIN_TABLE: [(&[u8], &[u8]); PERIST_TEST_SET_SIZE] = [
(b"mykey1\xF0\x90\x80", b"myval1\xF0\x90\x80"),
(b"mykey2\xF0\x90\x80", b"myval2\xF0\x90\x80"),
(b"mykey3\xF0\x90\x80", b"myval3\xF0\x90\x80"),
(b"mykey4\xF0\x90\x80", b"myval4\xF0\x90\x80"),
const PERSIST_DATA_KEYMAP_BIN_BIN_TABLE: [(&[u8], &[u8]); PERSIST_TEST_SET_SIZE] = [
(bin!(b"mykey1"), bin!(b"myval1")),
(bin!(b"mykey2"), bin!(b"myval2")),
(bin!(b"mykey3"), bin!(b"myval3")),
(bin!(b"mykey4"), bin!(b"myval4")),
];
#[dbtest(skip_if_cfg = "persist-suite", norun = true)]
async fn persist_store_keymap_bin_bin() {
async fn store_keymap_bin_bin() {
persist_store(
&mut con,
PERSIST_CFG_KEYMAP_BIN_BIN_TABLE,
@ -107,7 +47,7 @@ async fn persist_store_keymap_bin_bin() {
}
#[dbtest(run_if_cfg = "persist-suite", norun = true)]
async fn persist_load_keymap_bin_bin() {
async fn load_keymap_bin_bin() {
persist_load(
&mut con,
PERSIST_CFG_KEYMAP_BIN_BIN_TABLE,
@ -117,15 +57,15 @@ async fn persist_load_keymap_bin_bin() {
}
const PERSIST_CFG_KEYMAP_BIN_STR_TABLE: &str = "testsuite:persist_bin_str_tbl";
const PERSIST_DATA_KEYMAP_BIN_STR_TABLE: [(&[u8], &str); PERIST_TEST_SET_SIZE] = [
(b"mykey1\xF0\x90\x80", "myval1"),
(b"mykey2\xF0\x90\x80", "myval2"),
(b"mykey3\xF0\x90\x80", "myval3"),
(b"mykey4\xF0\x90\x80", "myval4"),
const PERSIST_DATA_KEYMAP_BIN_STR_TABLE: [(&[u8], &str); PERSIST_TEST_SET_SIZE] = [
(bin!(b"mykey1"), "myval1"),
(bin!(b"mykey2"), "myval2"),
(bin!(b"mykey3"), "myval3"),
(bin!(b"mykey4"), "myval4"),
];
#[dbtest(skip_if_cfg = "persist-suite", norun = true)]
async fn persist_store_keymap_bin_str() {
async fn store_keymap_bin_str() {
persist_store(
&mut con,
PERSIST_CFG_KEYMAP_BIN_STR_TABLE,
@ -136,7 +76,7 @@ async fn persist_store_keymap_bin_str() {
}
#[dbtest(run_if_cfg = "persist-suite", norun = true)]
async fn persist_load_keymap_bin_str() {
async fn load_keymap_bin_str() {
persist_load(
&mut con,
PERSIST_CFG_KEYMAP_BIN_STR_TABLE,
@ -146,7 +86,7 @@ async fn persist_load_keymap_bin_str() {
}
const PERSIST_CFG_KEYMAP_STR_STR_TABLE: &str = "testsuite:persist_str_str_tbl";
const PERSIST_DATA_KEYMAP_STR_STR_TABLE: [(&str, &str); PERIST_TEST_SET_SIZE] = [
const PERSIST_DATA_KEYMAP_STR_STR_TABLE: [(&str, &str); PERSIST_TEST_SET_SIZE] = [
("mykey1", "myval1"),
("mykey2", "myval2"),
("mykey3", "myval3"),
@ -154,7 +94,7 @@ const PERSIST_DATA_KEYMAP_STR_STR_TABLE: [(&str, &str); PERIST_TEST_SET_SIZE] =
];
#[dbtest(skip_if_cfg = "persist-suite", norun = true)]
async fn persist_store_keymap_str_str() {
async fn store_keymap_str_str() {
persist_store(
&mut con,
PERSIST_CFG_KEYMAP_STR_STR_TABLE,
@ -165,7 +105,7 @@ async fn persist_store_keymap_str_str() {
}
#[dbtest(run_if_cfg = "persist-suite", norun = true)]
async fn persist_load_keymap_str_str() {
async fn load_keymap_str_str() {
persist_load(
&mut con,
PERSIST_CFG_KEYMAP_STR_STR_TABLE,
@ -175,15 +115,15 @@ async fn persist_load_keymap_str_str() {
}
const PERSIST_CFG_KEYMAP_STR_BIN_TABLE: &str = "testsuite:persist_str_bin_tbl";
const PERSIST_DATA_KEYMAP_STR_BIN_TABLE: [(&str, &[u8]); PERIST_TEST_SET_SIZE] = [
("mykey1", b"myval1\xF0\x90\x80"),
("mykey2", b"myval2\xF0\x90\x80"),
("mykey3", b"myval3\xF0\x90\x80"),
("mykey4", b"myval4\xF0\x90\x80"),
const PERSIST_DATA_KEYMAP_STR_BIN_TABLE: [(&str, &[u8]); PERSIST_TEST_SET_SIZE] = [
("mykey1", bin!(b"myval1")),
("mykey2", bin!(b"myval2")),
("mykey3", bin!(b"myval3")),
("mykey4", bin!(b"myval4")),
];
#[dbtest(skip_if_cfg = "persist-suite", norun = true)]
async fn persist_store_keymap_str_bin() {
async fn store_keymap_str_bin() {
persist_store(
&mut con,
PERSIST_CFG_KEYMAP_STR_BIN_TABLE,
@ -194,7 +134,7 @@ async fn persist_store_keymap_str_bin() {
}
#[dbtest(run_if_cfg = "persist-suite", norun = true)]
async fn persist_load_keymap_str_bin() {
async fn load_keymap_str_bin() {
persist_load(
&mut con,
PERSIST_CFG_KEYMAP_STR_BIN_TABLE,

@ -0,0 +1,166 @@
/*
* Created on Sat Mar 19 2022
*
* This file is a part of Skytable
* Skytable (formerly known as TerrabaseDB or Skybase) is a free and open-source
* NoSQL database written by Sayan Nandan ("the Author") with the
* vision to provide flexibility in data modelling without compromising
* on performance, queryability or scalability.
*
* Copyright (c) 2022, Sayan Nandan <ohsayan@outlook.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
use super::{persist_load, persist_store, Bin, ListIDBin, ListIDStr, Str, PERSIST_TEST_SET_SIZE};
use sky_macros::dbtest_func as dbtest;
type ListData<K, V> = [(K, [V; PERSIST_TEST_SET_SIZE]); PERSIST_TEST_SET_SIZE];
macro_rules! listdata {
(
$(
$listid:expr => $element:expr
),*
) => {
[
$(
(
$listid,
$element
),
)*
]
};
}
macro_rules! binid {
($id:expr) => {
ListIDBin(bin!($id))
};
}
macro_rules! binlist {
($($elem:expr),*) => {
[
$(
bin!($elem),
)*
]
};
}
// bin,list<bin>
const DATA_BIN_LISTBIN: ListData<ListIDBin, Bin> = listdata!(
binid!(b"list1") => binlist!(b"e1", b"e2", b"e3", b"e4"),
binid!(b"list2") => binlist!(b"e1", b"e2", b"e3", b"e4"),
binid!(b"list3") => binlist!(b"e1", b"e2", b"e3", b"e4"),
binid!(b"list4") => binlist!(b"e1", b"e2", b"e3", b"e4")
);
const TABLE_BIN_LISTBIN: &str = "testsuite:persist_bin_listbin";
#[dbtest(skip_if_cfg = "persist-suite", norun = true)]
async fn store_bin_bin() {
persist_store(
&mut con,
TABLE_BIN_LISTBIN,
"keymap(binstr,list<binstr>)",
DATA_BIN_LISTBIN,
)
.await;
}
#[dbtest(run_if_cfg = "persist-suite", norun = true)]
async fn load_bin_bin() {
persist_load(&mut con, TABLE_BIN_LISTBIN, DATA_BIN_LISTBIN).await;
}
// bin,list<str>
const DATA_BIN_LISTSTR: ListData<ListIDBin, Str> = listdata!(
binid!(b"list1") => ["e1", "e2", "e3", "e4"],
binid!(b"list2") => ["e1", "e2", "e3", "e4"],
binid!(b"list3") => ["e1", "e2", "e3", "e4"],
binid!(b"list4") => ["e1", "e2", "e3", "e4"]
);
const TABLE_BIN_LISTSTR: &str = "testsuite:persist_bin_liststr";
#[dbtest(skip_if_cfg = "persist-suite", norun = true)]
async fn store_bin_str() {
persist_store(
&mut con,
TABLE_BIN_LISTSTR,
"keymap(binstr,list<str>)",
DATA_BIN_LISTSTR,
)
.await;
}
#[dbtest(run_if_cfg = "persist-suite", norun = true)]
async fn load_bin_str() {
persist_load(&mut con, TABLE_BIN_LISTSTR, DATA_BIN_LISTSTR).await;
}
// str,list<bin>
const DATA_STR_LISTBIN: ListData<ListIDStr, Bin> = listdata!(
ListIDStr("list1") => binlist!(b"e1", b"e2", b"e3", b"e4"),
ListIDStr("list2") => binlist!(b"e1", b"e2", b"e3", b"e4"),
ListIDStr("list3") => binlist!(b"e1", b"e2", b"e3", b"e4"),
ListIDStr("list4") => binlist!(b"e1", b"e2", b"e3", b"e4")
);
const TABLE_STR_LISTBIN: &str = "testsuite:persist_str_listbin";
#[dbtest(skip_if_cfg = "persist-suite", norun = true)]
async fn store_str_bin() {
persist_store(
&mut con,
TABLE_STR_LISTBIN,
"keymap(str,list<binstr>)",
DATA_STR_LISTBIN,
)
.await;
}
#[dbtest(run_if_cfg = "persist-suite", norun = true)]
async fn load_str_bin() {
persist_load(&mut con, TABLE_STR_LISTBIN, DATA_STR_LISTBIN).await;
}
// str,list<str>
const DATA_STR_LISTSTR: ListData<ListIDStr, Str> = listdata!(
ListIDStr("list1") => ["e1", "e2", "e3", "e4"],
ListIDStr("list2") => ["e1", "e2", "e3", "e4"],
ListIDStr("list3") => ["e1", "e2", "e3", "e4"],
ListIDStr("list4") => ["e1", "e2", "e3", "e4"]
);
const TABLE_STR_LISTSTR: &str = "testsuite:persist_str_liststr";
#[dbtest(skip_if_cfg = "persist-suite", norun = true)]
async fn store_str_str() {
persist_store(
&mut con,
TABLE_STR_LISTSTR,
"keymap(str,list<str>)",
DATA_STR_LISTSTR,
)
.await;
}
#[dbtest(run_if_cfg = "persist-suite", norun = true)]
async fn load_str_str() {
persist_load(&mut con, TABLE_STR_LISTSTR, DATA_STR_LISTSTR).await;
}

@ -0,0 +1,217 @@
/*
* Created on Thu Mar 17 2022
*
* This file is a part of Skytable
* Skytable (formerly known as TerrabaseDB or Skybase) is a free and open-source
* NoSQL database written by Sayan Nandan ("the Author") with the
* vision to provide flexibility in data modelling without compromising
* on performance, queryability or scalability.
*
* Copyright (c) 2022, Sayan Nandan <ohsayan@outlook.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
use skytable::{
aio::Connection,
query,
types::{Array, RawString},
Element, Query, RespCode,
};
macro_rules! bin {
($input:expr) => {{
const INVALID_SEQ: [u8; 2] = *b"\x80\x81";
const RETLEN: usize = 2 + $input.len();
const RET0: [u8; RETLEN] = {
let mut iret: [u8; RETLEN] = [0u8; RETLEN];
let mut idx = 0;
while idx < $input.len() {
iret[idx] = $input[idx];
idx += 1;
}
iret[RETLEN - 2] = INVALID_SEQ[0];
iret[RETLEN - 1] = INVALID_SEQ[1];
iret
};
&RET0
}};
}
mod kv;
mod kvlist;
const PERSIST_TEST_SET_SIZE: usize = 4;
trait PushIntoQuery {
fn push_into(&self, query: &mut Query);
}
impl PushIntoQuery for &str {
fn push_into(&self, q: &mut Query) {
q.push(*self);
}
}
impl PushIntoQuery for &[u8] {
fn push_into(&self, q: &mut Query) {
q.push(RawString::from(self.to_vec()))
}
}
impl<T: PushIntoQuery, const N: usize> PushIntoQuery for [T; N] {
fn push_into(&self, q: &mut Query) {
for element in self {
element.push_into(q)
}
}
}
impl<T: PushIntoQuery> PushIntoQuery for &[T] {
fn push_into(&self, q: &mut Query) {
for element in self.iter() {
element.push_into(q)
}
}
}
trait PersistKey: PushIntoQuery {
fn action_store() -> &'static str;
fn action_load() -> &'static str;
}
macro_rules! impl_persist_key {
($($ty:ty => ($store:expr, $load:expr)),*) => {
$(impl PersistKey for $ty {
fn action_store() -> &'static str {
$store
}
fn action_load() -> &'static str {
$load
}
})*
};
}
impl_persist_key!(
&str => ("set", "get"),
&[u8] => ("set", "get"),
ListIDBin => ("lset", "lget"),
ListIDStr => ("lset", "lget")
);
trait PersistValue: PushIntoQuery {
fn response_store(&self) -> Element;
fn response_load(&self) -> Element;
}
impl PersistValue for &str {
fn response_store(&self) -> Element {
Element::RespCode(RespCode::Okay)
}
fn response_load(&self) -> Element {
Element::String(self.to_string())
}
}
impl PersistValue for &[u8] {
fn response_store(&self) -> Element {
Element::RespCode(RespCode::Okay)
}
fn response_load(&self) -> Element {
Element::Binstr(self.to_vec())
}
}
impl<const N: usize> PersistValue for [&[u8]; N] {
fn response_store(&self) -> Element {
Element::RespCode(RespCode::Okay)
}
fn response_load(&self) -> Element {
let mut flat = Vec::with_capacity(N);
for item in self {
flat.push(Some(item.to_vec()));
}
Element::Array(Array::Bin(flat))
}
}
impl<const N: usize> PersistValue for [&str; N] {
fn response_store(&self) -> Element {
Element::RespCode(RespCode::Okay)
}
fn response_load(&self) -> Element {
let mut flat = Vec::with_capacity(N);
for item in self {
flat.push(Some(item.to_string()));
}
Element::Array(Array::Str(flat))
}
}
type Bin = &'static [u8];
type Str = &'static str;
#[derive(Debug)]
struct ListIDStr(Str);
#[derive(Debug)]
struct ListIDBin(Bin);
impl PushIntoQuery for ListIDStr {
fn push_into(&self, q: &mut Query) {
self.0.push_into(q)
}
}
impl PushIntoQuery for ListIDBin {
fn push_into(&self, q: &mut Query) {
self.0.push_into(q)
}
}
async fn persist_store<K: PersistKey, V: PersistValue>(
con: &mut Connection,
table_id: &str,
declaration: &str,
input: [(K, V); PERSIST_TEST_SET_SIZE],
) {
create_table_and_switch!(con, table_id, declaration);
for (key, value) in input {
let mut query = Query::from(K::action_store());
key.push_into(&mut query);
value.push_into(&mut query);
runeq!(con, query, value.response_store())
}
}
async fn persist_load<K: PersistKey, V: PersistValue>(
con: &mut Connection,
table_id: &str,
input: [(K, V); PERSIST_TEST_SET_SIZE],
) {
switch_entity!(con, table_id);
for (key, value) in input {
let mut q = Query::from(K::action_load());
key.push_into(&mut q);
runeq!(con, q, value.response_load());
}
// now delete this table, freeing it up for the next suite run
switch_entity!(con, "default:default");
runeq!(
con,
query!("drop", "table", table_id),
Element::RespCode(RespCode::Okay)
);
}
Loading…
Cancel
Save