|
|
|
@ -34,7 +34,7 @@ use {
|
|
|
|
|
ql::{
|
|
|
|
|
ast,
|
|
|
|
|
ddl::crt::{CreateModel, CreateSpace},
|
|
|
|
|
dml::ins::InsertStatement,
|
|
|
|
|
dml::{ins::InsertStatement, upd::UpdateStatement},
|
|
|
|
|
tests::lex_insecure,
|
|
|
|
|
},
|
|
|
|
|
storage::common::interface::fs_test::VirtualFS,
|
|
|
|
@ -61,6 +61,12 @@ fn run_insert(global: &TestGlobal<VirtualFS>, insert: &str) -> QueryResult<()> {
|
|
|
|
|
dml::insert(global, insert)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn run_update(global: &TestGlobal<VirtualFS>, update: &str) -> QueryResult<()> {
|
|
|
|
|
let tokens = lex_insecure(update.as_bytes()).unwrap();
|
|
|
|
|
let insert: UpdateStatement = ast::parse_ast_node_full(&tokens[1..]).unwrap();
|
|
|
|
|
dml::update(global, insert)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn empty_model_data() {
|
|
|
|
|
test_utils::with_variable("empty_model_data", |log_name| {
|
|
|
|
@ -81,9 +87,21 @@ fn empty_model_data() {
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn create_test_kv(change_count: usize) -> Vec<(String, String)> {
|
|
|
|
|
(1..=change_count)
|
|
|
|
|
.map(|i| {
|
|
|
|
|
(
|
|
|
|
|
format!("user-{i:0>change_count$}"),
|
|
|
|
|
format!("password-{i:0>change_count$}"),
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
.collect()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn model_data_deltas() {
|
|
|
|
|
test_utils::with_variable(("model_data_deltas", 1000), |(log_name, change_count)| {
|
|
|
|
|
fn model_data_inserts() {
|
|
|
|
|
test_utils::with_variable(("model_data_inserts", 1000), |(log_name, change_count)| {
|
|
|
|
|
let key_values = create_test_kv(change_count);
|
|
|
|
|
// create, insert and close
|
|
|
|
|
{
|
|
|
|
|
let mut global = TestGlobal::new_with_vfs_driver(log_name);
|
|
|
|
@ -93,15 +111,15 @@ fn model_data_deltas() {
|
|
|
|
|
"create model apps.social(user_name: string, password: string)",
|
|
|
|
|
)
|
|
|
|
|
.unwrap();
|
|
|
|
|
for i in 1..=change_count {
|
|
|
|
|
for (username, password) in key_values.iter() {
|
|
|
|
|
run_insert(
|
|
|
|
|
&global,
|
|
|
|
|
&format!("insert into apps.social('user-{i:0>1000}', 'password-{i:0>1000}')"),
|
|
|
|
|
&format!("insert into apps.social('{username}', '{password}')"),
|
|
|
|
|
)
|
|
|
|
|
.unwrap();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// reopen and verify a 100 times
|
|
|
|
|
// reopen and verify 100 times
|
|
|
|
|
test_utils::multi_run(100, || {
|
|
|
|
|
let global = TestGlobal::new_with_vfs_driver(log_name);
|
|
|
|
|
global.load_model_drivers().unwrap();
|
|
|
|
@ -109,21 +127,19 @@ fn model_data_deltas() {
|
|
|
|
|
.state()
|
|
|
|
|
.with_model(EntityIDRef::new("apps", "social"), |model| {
|
|
|
|
|
let g = pin();
|
|
|
|
|
for i in 1..=change_count {
|
|
|
|
|
for (username, password) in key_values.iter() {
|
|
|
|
|
assert_eq!(
|
|
|
|
|
model
|
|
|
|
|
.primary_index()
|
|
|
|
|
.select(Lit::new_string(format!("user-{i:0>1000}")), &g)
|
|
|
|
|
.select(Lit::new_str(username.as_str()), &g)
|
|
|
|
|
.unwrap()
|
|
|
|
|
.d_data()
|
|
|
|
|
.read()
|
|
|
|
|
.fields()
|
|
|
|
|
.get("password")
|
|
|
|
|
.cloned()
|
|
|
|
|
.unwrap()
|
|
|
|
|
.into_str()
|
|
|
|
|
.unwrap(),
|
|
|
|
|
format!("password-{i:0>1000}")
|
|
|
|
|
.str(),
|
|
|
|
|
password.as_str()
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
Ok(())
|
|
|
|
@ -132,3 +148,90 @@ fn model_data_deltas() {
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn model_data_updates() {
|
|
|
|
|
test_utils::with_variable(("model_data_updates", 50), |(log_name, n)| {
|
|
|
|
|
let key_values = create_test_kv(n);
|
|
|
|
|
/*
|
|
|
|
|
- we first open the log and then insert n values
|
|
|
|
|
- we then reopen the log 100 times, changing n / 100 values every time (we set the string to an empty one)
|
|
|
|
|
- we finally reopen the log and check if all the keys have empty string as the password
|
|
|
|
|
*/
|
|
|
|
|
{
|
|
|
|
|
// insert n values
|
|
|
|
|
let mut global = TestGlobal::new_with_vfs_driver(log_name);
|
|
|
|
|
global.set_max_data_pressure(n);
|
|
|
|
|
let _ = create_model_and_space(
|
|
|
|
|
&global,
|
|
|
|
|
"create model apps.social(user_name: string, password: string)",
|
|
|
|
|
)
|
|
|
|
|
.unwrap();
|
|
|
|
|
for (username, password) in key_values.iter() {
|
|
|
|
|
run_insert(
|
|
|
|
|
&global,
|
|
|
|
|
&format!("insert into apps.social('{username}', '{password}')"),
|
|
|
|
|
)
|
|
|
|
|
.unwrap();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
{
|
|
|
|
|
// reopen and update multiple times
|
|
|
|
|
// this effectively opens the log 100 times
|
|
|
|
|
let changes_per_cycle = n / 10;
|
|
|
|
|
let reopen_count = n / changes_per_cycle;
|
|
|
|
|
// now update values
|
|
|
|
|
let mut actual_position = 0;
|
|
|
|
|
for _ in 0..reopen_count {
|
|
|
|
|
let mut global = TestGlobal::new_with_vfs_driver(log_name);
|
|
|
|
|
global.set_max_data_pressure(changes_per_cycle);
|
|
|
|
|
global.load_model_drivers().unwrap();
|
|
|
|
|
let mut j = 0;
|
|
|
|
|
for _ in 0..changes_per_cycle {
|
|
|
|
|
let (username, _) = &key_values[actual_position];
|
|
|
|
|
run_update(
|
|
|
|
|
&global,
|
|
|
|
|
&format!(
|
|
|
|
|
"update apps.social set password = '' where user_name = '{username}'"
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
.unwrap();
|
|
|
|
|
actual_position += 1;
|
|
|
|
|
j += 1;
|
|
|
|
|
}
|
|
|
|
|
assert_eq!(j, changes_per_cycle);
|
|
|
|
|
drop(global);
|
|
|
|
|
}
|
|
|
|
|
assert_eq!(actual_position, n);
|
|
|
|
|
}
|
|
|
|
|
{
|
|
|
|
|
let global = TestGlobal::new_with_vfs_driver(log_name);
|
|
|
|
|
global.load_model_drivers().unwrap();
|
|
|
|
|
for (txn_id, (username, _)) in key_values
|
|
|
|
|
.iter()
|
|
|
|
|
.enumerate()
|
|
|
|
|
.map(|(i, x)| ((i + n) as u64, x))
|
|
|
|
|
{
|
|
|
|
|
global
|
|
|
|
|
.state()
|
|
|
|
|
.with_model(EntityIDRef::new("apps", "social"), |model| {
|
|
|
|
|
let g = pin();
|
|
|
|
|
let row = model
|
|
|
|
|
.primary_index()
|
|
|
|
|
.select(Lit::new_str(username.as_str()), &g)
|
|
|
|
|
.unwrap()
|
|
|
|
|
.d_data()
|
|
|
|
|
.read();
|
|
|
|
|
let pass = row.fields().get("password").unwrap().str();
|
|
|
|
|
assert!(
|
|
|
|
|
pass.is_empty(),
|
|
|
|
|
"failed for {username} because pass is {pass}",
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(row.get_txn_revised().value_u64(), txn_id);
|
|
|
|
|
Ok(())
|
|
|
|
|
})
|
|
|
|
|
.unwrap();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|