Add more tests for update

next
Sayan Nandan 1 year ago
parent 4580b76d55
commit dbc7128c41
No known key found for this signature in database
GPG Key ID: 42EEDF4AE9D96B54

@ -39,6 +39,8 @@ use crate::{
util::compiler,
};
#[cfg(test)]
pub use upd::collect_trace_path as update_flow_trace;
pub use {del::delete, ins::insert, sel::select_custom, upd::update};
impl ModelData {

@ -24,6 +24,8 @@
*
*/
#[cfg(test)]
use std::cell::RefCell;
use {
crate::{
engine::{
@ -211,6 +213,24 @@ const fn opc(opr: TagClass, ope: AssignmentOperator) -> usize {
(AssignmentOperator::count() * opr.word()) + ope.word()
}
#[cfg(test)]
thread_local! {
pub(super) static ROUTE_TRACE: RefCell<Vec<&'static str>> = RefCell::new(Vec::new());
}
#[inline(always)]
fn input_trace(v: &'static str) {
#[cfg(test)]
{
ROUTE_TRACE.with(|rcv| rcv.borrow_mut().push(v))
}
let _ = v;
}
#[cfg(test)]
pub fn collect_trace_path() -> Vec<&'static str> {
ROUTE_TRACE.with(|v| v.borrow().iter().cloned().collect())
}
pub fn update(gns: &GlobalNS, mut update: UpdateStatement) -> DatabaseResult<()> {
gns.with_model(update.entity(), |mdl| {
let mut ret = Ok(());
@ -247,6 +267,7 @@ pub fn update(gns: &GlobalNS, mut update: UpdateStatement) -> DatabaseResult<()>
field_data = fdata;
}
_ => {
input_trace("fieldnotfound");
rollback_now = true;
ret = Err(DatabaseError::FieldNotFound);
break;
@ -262,6 +283,7 @@ pub fn update(gns: &GlobalNS, mut update: UpdateStatement) -> DatabaseResult<()>
let (okay, new) = unsafe { OPERATOR[opc(tag_a, operator_fn)](field_data, rhs) };
rollback_now &= !okay;
rollback_data.push((lhs.as_str(), mem::replace(field_data, new)));
input_trace("sametag;nonnull");
}
(tag_a, tag_b)
if (tag_a == tag_b)
@ -269,13 +291,15 @@ pub fn update(gns: &GlobalNS, mut update: UpdateStatement) -> DatabaseResult<()>
& (operator_fn == AssignmentOperator::Assign) =>
{
rollback_data.push((lhs.as_str(), mem::replace(field_data, rhs.into())));
input_trace("sametag;orignull");
}
(TagClass::List, tag_b) => {
(TagClass::List, tag_b) if operator_fn == AssignmentOperator::AddAssign => {
if field_definition.layers()[1].tag().tag_class() == tag_b {
unsafe {
// UNSAFE(@ohsayan): matched tags
let mut list = field_data.read_list().write();
if list.try_reserve(1).is_ok() {
input_trace("list;sametag");
list.push(rhs.into());
} else {
rollback_now = true;
@ -284,12 +308,14 @@ pub fn update(gns: &GlobalNS, mut update: UpdateStatement) -> DatabaseResult<()>
}
}
} else {
input_trace("list;badtag");
rollback_now = true;
ret = Err(DatabaseError::DmlConstraintViolationFieldTypedef);
break;
}
}
_ => {
input_trace("unknown_reason;exitmainloop");
ret = Err(DatabaseError::DmlConstraintViolationFieldTypedef);
rollback_now = true;
break;
@ -297,6 +323,7 @@ pub fn update(gns: &GlobalNS, mut update: UpdateStatement) -> DatabaseResult<()>
}
}
if compiler::unlikely(rollback_now) {
input_trace("rollback");
rollback_data
.into_iter()
.for_each(|(field_id, restored_data)| {

@ -24,7 +24,11 @@
*
*/
use crate::engine::{core::GlobalNS, data::cell::Datacell, error::DatabaseError};
use crate::engine::{
core::{dml, GlobalNS},
data::cell::Datacell,
error::DatabaseError,
};
#[test]
fn simple() {
@ -39,6 +43,10 @@ fn simple() {
).unwrap(),
intovec!["sayan", "sn@example.com", 200_000_u64, 85_u64],
);
assert_eq!(
dml::update_flow_trace(),
["sametag;nonnull", "sametag;nonnull", "sametag;nonnull"]
);
}
#[test]
@ -55,6 +63,47 @@ fn with_null() {
.unwrap(),
intovec!["sayan", "pass123", "sayan@example.com"]
);
assert_eq!(dml::update_flow_trace(), ["sametag;orignull"]);
}
#[test]
fn with_list() {
let gns = GlobalNS::empty();
assert_eq!(
super::exec_update(
&gns,
"create model myspace.mymodel(link: string, click_ids: list { type: string })",
"insert into myspace.mymodel('example.com', [])",
"update myspace.mymodel set click_ids += 'ios_client_uuid' where link = 'example.com'",
"select * from myspace.mymodel where link = 'example.com'"
)
.unwrap(),
intovec![
"example.com",
Datacell::new_list(intovec!["ios_client_uuid"])
]
);
assert_eq!(dml::update_flow_trace(), ["list;sametag"]);
}
#[test]
fn fail_operation_on_null() {
let gns = GlobalNS::empty();
assert_eq!(
super::exec_update(
&gns,
"create model myspace.mymodel(username: string, password: string, null email: string)",
"insert into myspace.mymodel('sayan', 'pass123', null)",
"update myspace.mymodel set email += '.com' where username = 'sayan'",
"select * from myspace.mymodel where username='sayan'"
)
.unwrap_err(),
DatabaseError::DmlConstraintViolationFieldTypedef
);
assert_eq!(
dml::update_flow_trace(),
["unknown_reason;exitmainloop", "rollback"]
);
}
#[test]
@ -71,6 +120,7 @@ fn fail_unknown_fields() {
.unwrap_err(),
DatabaseError::FieldNotFound
);
assert_eq!(dml::update_flow_trace(), ["fieldnotfound", "rollback"]);
// verify integrity
assert_eq!(
super::exec_select_only(&gns, "select * from myspace.mymodel where username='sayan'")
@ -93,6 +143,10 @@ fn fail_typedef_violation() {
.unwrap_err(),
DatabaseError::DmlConstraintViolationFieldTypedef
);
assert_eq!(
dml::update_flow_trace(),
["sametag;nonnull", "unknown_reason;exitmainloop", "rollback"]
);
// verify integrity
assert_eq!(
super::exec_select_only(

Loading…
Cancel
Save