diff --git a/server/src/engine/txn/gns/tests/full_chain.rs b/server/src/engine/txn/gns/tests/full_chain.rs index 604c9023..4ea29bcf 100644 --- a/server/src/engine/txn/gns/tests/full_chain.rs +++ b/server/src/engine/txn/gns/tests/full_chain.rs @@ -31,6 +31,7 @@ use crate::engine::{ GlobalNS, }, data::{cell::Datacell, tag::TagSelector, uuid::Uuid, DictEntryGeneric}, + error::DatabaseError, idx::STIndex, ql::{ ast::parse_ast_node_full, @@ -41,9 +42,10 @@ use crate::engine::{ txn::gns::GNSTransactionDriverVFS, }; -fn double_run(f: impl FnOnce() + Copy) { - f(); - f(); +fn multirun(f: impl FnOnce() + Copy) { + for _ in 0..10 { + f() + } } fn with_variable(var: T, f: impl FnOnce(T)) { @@ -80,7 +82,7 @@ fn create_space() { uuid = init_space(&gns, &mut driver, "myspace", "{ SAYAN_MAX: 65536 }"); // good lord that doesn't sound like a good variable driver.close().unwrap(); } - double_run(|| { + multirun(|| { let gns = GlobalNS::empty(); let driver = init_txn_driver(&gns, log_name); assert_eq!( @@ -112,7 +114,7 @@ fn alter_space() { Space::transactional_exec_alter(&gns, &mut driver, stmt).unwrap(); driver.close().unwrap(); } - double_run(|| { + multirun(|| { let gns = GlobalNS::empty(); let driver = init_txn_driver(&gns, log_name); assert_eq!( @@ -141,7 +143,7 @@ fn drop_space() { Space::transactional_exec_drop(&gns, &mut driver, stmt).unwrap(); driver.close().unwrap(); } - double_run(|| { + multirun(|| { let gns = GlobalNS::empty(); let driver = init_txn_driver(&gns, log_name); assert_eq!(gns.spaces().read().get("myspace"), None); @@ -188,7 +190,7 @@ fn create_model() { uuid_model = init_default_model(&gns, &mut driver); driver.close().unwrap(); } - double_run(|| { + multirun(|| { let gns = GlobalNS::empty(); let driver = init_txn_driver(&gns, log_name); gns.with_model(("myspace", "mymodel"), |model| { @@ -228,24 +230,126 @@ fn alter_model_add() { Model::transactional_exec_alter(&gns, &mut driver, stmt).unwrap(); driver.close().unwrap(); } + multirun(|| { + let gns = GlobalNS::empty(); + let driver = init_txn_driver(&gns, log_name); + gns.with_model(("myspace", "mymodel"), |model| { + assert_eq!( + model + .intent_read_model() + .fields() + .st_get("profile_pic") + .unwrap(), + &Field::new([Layer::bin()].into(), true) + ); + Ok(()) + }) + .unwrap(); + driver.close().unwrap(); + }) + }) +} + +#[test] +fn alter_model_remove() { + with_variable("alter_model_remove_test.gns.db-tlog", |log_name| { + { + let gns = GlobalNS::empty(); + let mut driver = init_txn_driver(&gns, log_name); + init_space(&gns, &mut driver, "myspace", "{}"); + init_model( + &gns, + &mut driver, + "myspace", + "mymodel", + "username: string, password: binary, null profile_pic: binary, null has_2fa: bool, null has_secure_key: bool, is_dumb: bool", + ); + let stmt = lex_insecure( + "alter model myspace.mymodel remove (has_secure_key, is_dumb)".as_bytes(), + ) + .unwrap(); + let stmt = parse_ast_node_full(&stmt[2..]).unwrap(); + Model::transactional_exec_alter(&gns, &mut driver, stmt).unwrap(); + driver.close().unwrap() + } + multirun(|| { + let gns = GlobalNS::empty(); + let driver = init_txn_driver(&gns, log_name); + gns.with_model(("myspace", "mymodel"), |model| { + let irm = model.intent_read_model(); + assert!(irm.fields().st_get("has_secure_key").is_none()); + assert!(irm.fields().st_get("is_dumb").is_none()); + Ok(()) + }) + .unwrap(); + driver.close().unwrap() + }) + }) +} + +#[test] +fn alter_model_update() { + with_variable("alter_model_update_test.gns.db-tlog", |log_name| { { - double_run(|| { - let gns = GlobalNS::empty(); - let driver = init_txn_driver(&gns, log_name); - gns.with_model(("myspace", "mymodel"), |model| { - assert_eq!( - model - .intent_read_model() - .fields() - .st_get("profile_pic") - .unwrap(), - &Field::new([Layer::bin()].into(), true) - ); - Ok(()) - }) - .unwrap(); - driver.close().unwrap(); + let gns = GlobalNS::empty(); + let mut driver = init_txn_driver(&gns, log_name); + init_space(&gns, &mut driver, "myspace", "{}"); + init_model( + &gns, + &mut driver, + "myspace", + "mymodel", + "username: string, password: binary, profile_pic: binary", + ); + let stmt = + lex_insecure(b"alter model myspace.mymodel update profile_pic { nullable: true }") + .unwrap(); + let stmt = parse_ast_node_full(&stmt[2..]).unwrap(); + Model::transactional_exec_alter(&gns, &mut driver, stmt).unwrap(); + driver.close().unwrap(); + } + multirun(|| { + let gns = GlobalNS::empty(); + let driver = init_txn_driver(&gns, log_name); + gns.with_model(("myspace", "mymodel"), |model| { + assert_eq!( + model + .intent_read_model() + .fields() + .st_get("profile_pic") + .unwrap(), + &Field::new([Layer::bin()].into(), true) + ); + Ok(()) }) + .unwrap(); + driver.close().unwrap(); + }) + }) +} + +#[test] +fn drop_model() { + with_variable("drop_model_test.gns.db-tlog", |log_name| { + { + let gns = GlobalNS::empty(); + let mut driver = init_txn_driver(&gns, log_name); + init_space(&gns, &mut driver, "myspace", "{}"); + init_default_model(&gns, &mut driver); + let stmt = lex_insecure(b"drop model myspace.mymodel").unwrap(); + let stmt = parse_ast_node_full(&stmt[2..]).unwrap(); + Model::transactional_exec_drop(&gns, &mut driver, stmt).unwrap(); + driver.close().unwrap(); } + multirun(|| { + let gns = GlobalNS::empty(); + let driver = init_txn_driver(&gns, log_name); + assert_eq!( + gns.with_model(("myspace", "mymodel"), |_| { Ok(()) }) + .unwrap_err(), + DatabaseError::DdlModelNotFound + ); + driver.close().unwrap(); + }) }) }