use {
super::storage::{
TestPartition,
TestPartitions,
TestRecord,
TestRecordData,
},
crate::{
Ident,
database::{
chunk::RecordWriter,
PartitionKey,
},
scheduler::lanes::DEFAULT_LANE,
},
macro_rules_attribute::apply,
smol_macros::test,
std::sync::Arc,
};
fn test_scheduler() -> (
std::sync::Arc<
crate::scheduler::Scheduler<
TestPartitions,
crate::server::LaburnumLanguageServer,
>,
>,
crate::connect::ipc::Connection,
) {
let (server_conn, client_conn) = crate::connect::ipc::Connection::memory();
let filesystems = std::sync::Arc::new(parking_lot::RwLock::new(Vec::new()));
let source_cache =
std::sync::Arc::new(parking_lot::RwLock::new(crate::SourceCache::new()));
let scheduler = crate::scheduler::Scheduler::new_with_worker_count(
server_conn,
Arc::new(crate::server::LaburnumLanguageServer),
filesystems,
source_cache,
1,
);
(scheduler, client_conn)
}
fn partition_key() -> Ident {
TestPartition::KEY
}
#[apply(test!)]
async fn test_basic_module() {
let (scheduler, _conn) = test_scheduler();
let module_name = "main_module".to_string();
let exports = vec![Ident::new("export1"), Ident::new("export2")];
let module_id = Ident::new(&module_name);
let exports_clone = exports.clone();
let module_name_clone = module_name.clone();
scheduler.queue(
move |_ctx| {
let task_id = module_id;
let name = module_name_clone.clone();
let exp = exports_clone.clone();
async move {
let mut writer = RecordWriter::new(task_id);
writer.insert::<TestPartition, _>(name.clone(), TestRecordData::Module {
exports: exp,
});
Some(writer)
}
},
DEFAULT_LANE,
);
scheduler.spawn_workers();
let (tx, rx) = async_channel::unbounded();
scheduler.queue(
move |mut ctx| {
async move {
let query_client = ctx.query_client();
let results = query_client
.get_record(partition_key(), module_name.clone())
.await;
let success = if !results.is_empty()
&& results.len() == 1
&& let Some(record) = results.get(&results.records()[0])
&& let TestRecord::Test(TestRecordData::Module { exports: exp }) = record
{
exp.len() == 2 && exports.as_slice() == exp
} else {
false
};
let _ = tx.send(success).await;
None
}
},
DEFAULT_LANE,
);
let result = rx
.recv()
.await
.expect("Verification task should send result");
assert!(result, "Module should have been written with correct data");
}
#[apply(test!)]
async fn test_module_with_function() {
let (scheduler, _conn) = test_scheduler();
let module_name = "math_module".to_string();
let module_id = Ident::new(&module_name);
let function_name = "add".to_string();
let function_id = Ident::new(&function_name);
let function_name_for_module = function_name.clone();
let function_name_for_task = function_name.clone();
let function_name_for_verify = function_name.clone();
scheduler.queue(
move |_ctx| {
let task_id = module_id;
let name = module_name.clone();
let fn_name = function_name_for_module.clone();
async move {
let mut writer = RecordWriter::new(task_id);
writer.insert::<TestPartition, _>(name, TestRecordData::Module {
exports: vec![Ident::new(&fn_name)],
});
Some(writer)
}
},
DEFAULT_LANE,
);
scheduler.queue(
move |_ctx| {
let task_id = function_id;
let name = function_name_for_task.clone();
async move {
let mut writer = RecordWriter::new(task_id);
writer.insert::<TestPartition, _>(name, TestRecordData::Function {
params: vec![Ident::new("a"), Ident::new("b")],
return_type: "i32".to_string(),
});
Some(writer)
}
},
DEFAULT_LANE,
);
scheduler.spawn_workers();
let (tx, rx) = async_channel::unbounded();
scheduler.queue(
move |mut ctx| {
async move {
let query_client = ctx.query_client();
let results = query_client
.get_record(partition_key(), function_name_for_verify.clone())
.await;
let success = if !results.is_empty()
&& results.len() == 1
&& let Some(record) = results.get(&results.records()[0])
&& let TestRecord::Test(TestRecordData::Function {
params,
return_type,
}) = record
{
params.len() == 2 && return_type == "i32"
} else {
false
};
let _ = tx.send(success).await;
None
}
},
DEFAULT_LANE,
);
let result = rx
.recv()
.await
.expect("Verification task should send result");
assert!(
result,
"Function should have been written with correct data"
);
}
#[apply(test!)]
async fn test_struct_record() {
let (scheduler, _conn) = test_scheduler();
let struct_name = "Point".to_string();
let struct_id = Ident::new(&struct_name);
let fields = vec![
(Ident::new("x"), "f64".to_string()),
(Ident::new("y"), "f64".to_string()),
];
let fields_clone = fields.clone();
let struct_name_clone = struct_name.clone();
scheduler.queue(
move |_ctx| {
let task_id = struct_id;
let name = struct_name_clone.clone();
let flds = fields_clone.clone();
async move {
let mut writer = RecordWriter::new(task_id);
writer.insert::<TestPartition, _>(name, TestRecordData::Struct { fields: flds });
Some(writer)
}
},
DEFAULT_LANE,
);
scheduler.spawn_workers();
let (tx, rx) = async_channel::unbounded();
scheduler.queue(
move |mut ctx| {
async move {
let query_client = ctx.query_client();
let results = query_client
.get_record(partition_key(), struct_name.clone())
.await;
let success = if !results.is_empty()
&& results.len() == 1
&& let Some(record) = results.get(&results.records()[0])
&& let TestRecord::Test(TestRecordData::Struct { fields: flds }) = record
{
flds.len() == 2 && fields.as_slice() == flds
} else {
false
};
let _ = tx.send(success).await;
None
}
},
DEFAULT_LANE,
);
let result = rx
.recv()
.await
.expect("Verification task should send result");
assert!(result, "Struct should have been written with correct data");
}