macro_rules! simulation_test {
($name:ident, |$sim:ident| $body:expr) => {
simulation_test!(
$name,
options = crate::support::simulation_test::engine::SimulationOptions::default(),
|$sim| $body
);
};
($name:ident, options = $options:expr, |$sim:ident| $body:expr) => {
simulation_test!(@single $name, base, Base, $options, |$sim| $body);
#[cfg(feature = "all-simulations")]
simulation_test!(
@single $name,
tracked_state_rebuild,
TrackedStateRebuild,
$options,
|$sim| $body
);
};
(@single $name:ident, $simulation:ident, $mode:ident, $options:expr, |$sim:ident| $body:expr) => {
paste::paste! {
#[test]
fn [<$name _ $simulation>]() {
let simulation_mode =
crate::support::simulation_test::engine::SimulationMode::$mode;
let simulation_name = stringify!($simulation);
let timeout_secs = std::env::var("LIX_SIMULATION_TEST_TIMEOUT_SECS")
.ok()
.and_then(|raw| raw.parse::<u64>().ok())
.unwrap_or(120);
let case_id = concat!(module_path!(), "::", stringify!($name));
let (result_tx, result_rx) = std::sync::mpsc::sync_channel(1);
let thread = std::thread::Builder::new()
.name(format!("{}_{}", stringify!($name), simulation_name))
.stack_size(32 * 1024 * 1024)
.spawn(move || {
let run_result =
std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
let runtime = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.expect("failed to build tokio runtime");
runtime.block_on(async {
crate::support::simulation_test::engine::run_simulation_test(
simulation_mode,
$options,
case_id,
|$sim| $body,
)
.await;
});
}));
let _ = result_tx.send(run_result);
})
.expect(concat!(
"failed to spawn ",
stringify!($name),
" simulation_test thread"
));
match result_rx.recv_timeout(std::time::Duration::from_secs(timeout_secs)) {
Ok(Ok(())) => {
thread.join().expect(concat!(
stringify!($name),
" simulation_test thread panicked"
));
}
Ok(Err(payload)) => {
let _ = thread.join();
std::panic::resume_unwind(payload);
}
Err(std::sync::mpsc::RecvTimeoutError::Timeout) => {
panic!(
"simulation_test timed out after {}s (simulation={}, case={})",
timeout_secs, simulation_name, case_id
);
}
Err(std::sync::mpsc::RecvTimeoutError::Disconnected) => {
if let Err(payload) = thread.join() {
std::panic::resume_unwind(payload);
}
panic!(
"simulation_test thread exited without reporting result (simulation={}, case={})",
simulation_name, case_id
);
}
}
}
}
};
}
mod checkpoint;
mod delete_returning;
mod diff_commands;
mod diff_relation;
mod errors;
mod history_conformance;
mod information_schema;
mod index_lifecycle;
mod lix_branch;
mod lix_change;
mod lix_commit;
mod lix_directory;
mod lix_directory_history;
mod lix_file;
mod lix_file_history;
mod lix_json;
mod lix_key_value;
mod lix_registered_schema;
mod mainline;
mod metadata;
mod read_only;
mod row_ref;
mod schema_history;
mod schema_expression_amendment;
mod schema_view;
mod state_at;
mod temporal_arguments;
mod subquery_reads;
mod subquery_writes;
mod udfs;
mod untracked_current_state;
mod write_returning;
use lix::ExecuteResult;
use lix::Value;
async fn select_rows(
session: &crate::support::simulation_test::engine::SimSession,
sql: &str,
) -> Vec<Vec<Value>> {
let result = session
.execute(sql, &[])
.await
.expect("SELECT should succeed");
rows_from_result(result)
}
fn assert_rows_eq(result: ExecuteResult, expected: Vec<Vec<Value>>) {
assert_eq!(rows_from_result(result), expected);
}
fn rows_from_result(result: ExecuteResult) -> Vec<Vec<Value>> {
let row_set = result;
row_set
.rows()
.iter()
.map(|row| row.values().to_vec())
.collect()
}
mod index_schema_amendment;