mirror of
https://github.com/kanidm/kanidm.git
synced 2025-02-23 20:47:01 +01:00
Allow multiple backends to run in parallel for repl tests (#1346)
This commit is contained in:
parent
723c428e37
commit
08ebcc7901
|
@ -98,6 +98,100 @@ pub(crate) fn qs_test(_args: &TokenStream, item: TokenStream, with_init: bool) -
|
|||
result.into()
|
||||
}
|
||||
|
||||
pub(crate) fn qs_pair_test(_args: &TokenStream, item: TokenStream, with_init: bool) -> TokenStream {
|
||||
let input: syn::ItemFn = match syn::parse(item.clone()) {
|
||||
Ok(it) => it,
|
||||
Err(e) => return token_stream_with_error(item, e),
|
||||
};
|
||||
|
||||
if let Some(attr) = input.attrs.iter().find(|attr| attr.path.is_ident("test")) {
|
||||
let msg = "second test attribute is supplied";
|
||||
return token_stream_with_error(item, syn::Error::new_spanned(attr, msg));
|
||||
};
|
||||
|
||||
if input.sig.asyncness.is_none() {
|
||||
let msg = "the `async` keyword is missing from the function declaration";
|
||||
return token_stream_with_error(item, syn::Error::new_spanned(input.sig.fn_token, msg));
|
||||
}
|
||||
|
||||
// If type mismatch occurs, the current rustc points to the last statement.
|
||||
let (last_stmt_start_span, _last_stmt_end_span) = {
|
||||
let mut last_stmt = input
|
||||
.block
|
||||
.stmts
|
||||
.last()
|
||||
.map(ToTokens::into_token_stream)
|
||||
.unwrap_or_default()
|
||||
.into_iter();
|
||||
// `Span` on stable Rust has a limitation that only points to the first
|
||||
// token, not the whole tokens. We can work around this limitation by
|
||||
// using the first/last span of the tokens like
|
||||
// `syn::Error::new_spanned` does.
|
||||
let start = last_stmt.next().map_or_else(Span::call_site, |t| t.span());
|
||||
let end = last_stmt.last().map_or(start, |t| t.span());
|
||||
(start, end)
|
||||
};
|
||||
|
||||
let rt = quote_spanned! {last_stmt_start_span=>
|
||||
tokio::runtime::Builder::new_current_thread()
|
||||
};
|
||||
|
||||
let header = quote! {
|
||||
#[::core::prelude::v1::test]
|
||||
};
|
||||
|
||||
let init = if with_init {
|
||||
quote! {
|
||||
server_a.initialise_helper(duration_from_epoch_now())
|
||||
.await
|
||||
.expect("init_a failed!");
|
||||
server_b.initialise_helper(duration_from_epoch_now())
|
||||
.await
|
||||
.expect("init_b failed!");
|
||||
}
|
||||
} else {
|
||||
quote! {}
|
||||
};
|
||||
|
||||
let test_fn = &input.sig.ident;
|
||||
let test_driver = Ident::new(&format!("qs_{}", test_fn), input.sig.span());
|
||||
|
||||
// Effectively we are just injecting a real test function around this which we will
|
||||
// call.
|
||||
|
||||
let result = quote! {
|
||||
#input
|
||||
|
||||
#header
|
||||
fn #test_driver() {
|
||||
let body = async {
|
||||
let (server_a, server_b) = crate::testkit::setup_pair_test().await;
|
||||
|
||||
#init
|
||||
|
||||
#test_fn(&server_a, &server_b).await;
|
||||
|
||||
// Any needed teardown?
|
||||
// Make sure there are no errors.
|
||||
let verifications_a = server_a.verify().await;
|
||||
let verifications_b = server_b.verify().await;
|
||||
trace!("Verification result: {:?}, {:?}", verifications_a, verifications_b);
|
||||
assert!(verifications_a.len() + verifications_b.len() == 0);
|
||||
};
|
||||
#[allow(clippy::expect_used, clippy::diverging_sub_expression)]
|
||||
{
|
||||
return #rt
|
||||
.enable_all()
|
||||
.build()
|
||||
.expect("Failed building the Runtime")
|
||||
.block_on(body);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
result.into()
|
||||
}
|
||||
|
||||
pub(crate) fn idm_test(_args: &TokenStream, item: TokenStream) -> TokenStream {
|
||||
let input: syn::ItemFn = match syn::parse(item.clone()) {
|
||||
Ok(it) => it,
|
||||
|
|
|
@ -22,6 +22,11 @@ pub fn qs_test(args: TokenStream, item: TokenStream) -> TokenStream {
|
|||
entry::qs_test(&args, item, true)
|
||||
}
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn qs_pair_test(args: TokenStream, item: TokenStream) -> TokenStream {
|
||||
entry::qs_pair_test(&args, item, true)
|
||||
}
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn qs_test_no_init(args: TokenStream, item: TokenStream) -> TokenStream {
|
||||
entry::qs_test(&args, item, false)
|
||||
|
|
|
@ -99,16 +99,19 @@ impl TryFrom<IdRawEntry> for IdSqliteEntry {
|
|||
#[derive(Clone)]
|
||||
pub struct IdlSqlite {
|
||||
pool: Pool<SqliteConnectionManager>,
|
||||
db_name: &'static str,
|
||||
}
|
||||
|
||||
pub struct IdlSqliteReadTransaction {
|
||||
committed: bool,
|
||||
conn: r2d2::PooledConnection<SqliteConnectionManager>,
|
||||
db_name: &'static str,
|
||||
}
|
||||
|
||||
pub struct IdlSqliteWriteTransaction {
|
||||
committed: bool,
|
||||
conn: r2d2::PooledConnection<SqliteConnectionManager>,
|
||||
db_name: &'static str,
|
||||
}
|
||||
|
||||
pub trait IdlSqliteTransaction {
|
||||
|
@ -561,7 +564,7 @@ pub trait IdlSqliteTransaction {
|
|||
|
||||
impl IdlSqliteTransaction for IdlSqliteReadTransaction {
|
||||
fn get_db_name(&self) -> &str {
|
||||
"main"
|
||||
self.db_name
|
||||
}
|
||||
|
||||
fn get_conn(&self) -> &r2d2::PooledConnection<r2d2_sqlite::SqliteConnectionManager> {
|
||||
|
@ -585,7 +588,10 @@ impl Drop for IdlSqliteReadTransaction {
|
|||
}
|
||||
|
||||
impl IdlSqliteReadTransaction {
|
||||
pub fn new(conn: r2d2::PooledConnection<SqliteConnectionManager>) -> Self {
|
||||
pub fn new(
|
||||
conn: r2d2::PooledConnection<SqliteConnectionManager>,
|
||||
db_name: &'static str,
|
||||
) -> Self {
|
||||
// Start the transaction
|
||||
//
|
||||
// I'm happy for this to be an expect, because this is a huge failure
|
||||
|
@ -599,13 +605,14 @@ impl IdlSqliteReadTransaction {
|
|||
IdlSqliteReadTransaction {
|
||||
committed: false,
|
||||
conn,
|
||||
db_name,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl IdlSqliteTransaction for IdlSqliteWriteTransaction {
|
||||
fn get_db_name(&self) -> &str {
|
||||
"main"
|
||||
self.db_name
|
||||
}
|
||||
|
||||
fn get_conn(&self) -> &r2d2::PooledConnection<r2d2_sqlite::SqliteConnectionManager> {
|
||||
|
@ -626,7 +633,10 @@ impl Drop for IdlSqliteWriteTransaction {
|
|||
}
|
||||
|
||||
impl IdlSqliteWriteTransaction {
|
||||
pub fn new(conn: r2d2::PooledConnection<SqliteConnectionManager>) -> Self {
|
||||
pub fn new(
|
||||
conn: r2d2::PooledConnection<SqliteConnectionManager>,
|
||||
db_name: &'static str,
|
||||
) -> Self {
|
||||
// Start the transaction
|
||||
#[allow(clippy::expect_used)]
|
||||
conn.execute("BEGIN EXCLUSIVE TRANSACTION", [])
|
||||
|
@ -634,6 +644,7 @@ impl IdlSqliteWriteTransaction {
|
|||
IdlSqliteWriteTransaction {
|
||||
committed: false,
|
||||
conn,
|
||||
db_name,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -656,7 +667,7 @@ impl IdlSqliteWriteTransaction {
|
|||
.conn
|
||||
.prepare(&format!(
|
||||
"SELECT MAX(id) as id_max FROM {}.id2entry",
|
||||
"main"
|
||||
self.get_db_name(),
|
||||
))
|
||||
.map_err(sqlite_error)?;
|
||||
// This exists checks for if any rows WERE returned
|
||||
|
@ -724,7 +735,7 @@ impl IdlSqliteWriteTransaction {
|
|||
.conn
|
||||
.prepare(&format!(
|
||||
"INSERT OR REPLACE INTO {}.id2entry (id, data) VALUES(:id, :data)",
|
||||
"main"
|
||||
self.get_db_name()
|
||||
))
|
||||
.map_err(sqlite_error)?;
|
||||
|
||||
|
@ -781,7 +792,10 @@ impl IdlSqliteWriteTransaction {
|
|||
pub fn delete_identry(&self, id: u64) -> Result<(), OperationError> {
|
||||
let mut stmt = self
|
||||
.conn
|
||||
.prepare(&format!("DELETE FROM {}.id2entry WHERE id = :id", "main"))
|
||||
.prepare(&format!(
|
||||
"DELETE FROM {}.id2entry WHERE id = :id",
|
||||
self.get_db_name()
|
||||
))
|
||||
.map_err(sqlite_error)?;
|
||||
|
||||
let iid: i64 = id
|
||||
|
@ -812,7 +826,7 @@ impl IdlSqliteWriteTransaction {
|
|||
// Delete this idx_key from the table.
|
||||
let query = format!(
|
||||
"DELETE FROM {}.idx_{}_{} WHERE key = :key",
|
||||
"main",
|
||||
self.get_db_name(),
|
||||
itype.as_idx_str(),
|
||||
attr
|
||||
);
|
||||
|
@ -828,7 +842,7 @@ impl IdlSqliteWriteTransaction {
|
|||
// update or create it.
|
||||
let query = format!(
|
||||
"INSERT OR REPLACE INTO {}.idx_{}_{} (key, idl) VALUES(:key, :idl)",
|
||||
"main",
|
||||
self.get_db_name(),
|
||||
itype.as_idx_str(),
|
||||
attr
|
||||
);
|
||||
|
@ -850,7 +864,7 @@ impl IdlSqliteWriteTransaction {
|
|||
pub fn create_name2uuid(&self) -> Result<(), OperationError> {
|
||||
self.conn
|
||||
.execute(
|
||||
&format!("CREATE TABLE IF NOT EXISTS {}.idx_name2uuid (name TEXT PRIMARY KEY, uuid TEXT)", "main"),
|
||||
&format!("CREATE TABLE IF NOT EXISTS {}.idx_name2uuid (name TEXT PRIMARY KEY, uuid TEXT)", self.get_db_name()),
|
||||
[],
|
||||
)
|
||||
.map(|_| ())
|
||||
|
@ -863,7 +877,7 @@ impl IdlSqliteWriteTransaction {
|
|||
self.conn
|
||||
.prepare(&format!(
|
||||
"INSERT OR REPLACE INTO {}.idx_name2uuid (name, uuid) VALUES(:name, :uuid)",
|
||||
"main"
|
||||
self.get_db_name()
|
||||
))
|
||||
.and_then(|mut stmt| {
|
||||
stmt.execute(named_params! {
|
||||
|
@ -879,7 +893,7 @@ impl IdlSqliteWriteTransaction {
|
|||
self.conn
|
||||
.prepare(&format!(
|
||||
"DELETE FROM {}.idx_name2uuid WHERE name = :name",
|
||||
"main"
|
||||
self.get_db_name()
|
||||
))
|
||||
.and_then(|mut stmt| stmt.execute(&[(":name", &name)]))
|
||||
.map(|_| ())
|
||||
|
@ -889,7 +903,7 @@ impl IdlSqliteWriteTransaction {
|
|||
pub fn create_externalid2uuid(&self) -> Result<(), OperationError> {
|
||||
self.conn
|
||||
.execute(
|
||||
&format!("CREATE TABLE IF NOT EXISTS {}.idx_externalid2uuid (eid TEXT PRIMARY KEY, uuid TEXT)", "main"),
|
||||
&format!("CREATE TABLE IF NOT EXISTS {}.idx_externalid2uuid (eid TEXT PRIMARY KEY, uuid TEXT)", self.get_db_name()),
|
||||
[],
|
||||
)
|
||||
.map(|_| ())
|
||||
|
@ -902,7 +916,7 @@ impl IdlSqliteWriteTransaction {
|
|||
self.conn
|
||||
.prepare(&format!(
|
||||
"INSERT OR REPLACE INTO {}.idx_externalid2uuid (eid, uuid) VALUES(:eid, :uuid)",
|
||||
"main"
|
||||
self.get_db_name()
|
||||
))
|
||||
.and_then(|mut stmt| {
|
||||
stmt.execute(named_params! {
|
||||
|
@ -918,7 +932,7 @@ impl IdlSqliteWriteTransaction {
|
|||
self.conn
|
||||
.prepare(&format!(
|
||||
"DELETE FROM {}.idx_externalid2uuid WHERE eid = :eid",
|
||||
"main"
|
||||
self.get_db_name()
|
||||
))
|
||||
.and_then(|mut stmt| stmt.execute(&[(":eid", &name)]))
|
||||
.map(|_| ())
|
||||
|
@ -930,7 +944,7 @@ impl IdlSqliteWriteTransaction {
|
|||
.execute(
|
||||
&format!(
|
||||
"CREATE TABLE IF NOT EXISTS {}.idx_uuid2spn (uuid TEXT PRIMARY KEY, spn BLOB)",
|
||||
"main"
|
||||
self.get_db_name()
|
||||
),
|
||||
[],
|
||||
)
|
||||
|
@ -972,7 +986,7 @@ impl IdlSqliteWriteTransaction {
|
|||
self.conn
|
||||
.prepare(&format!(
|
||||
"INSERT OR REPLACE INTO {}.idx_uuid2spn (uuid, spn) VALUES(:uuid, :spn)",
|
||||
"main"
|
||||
self.get_db_name()
|
||||
))
|
||||
.and_then(|mut stmt| {
|
||||
stmt.execute(named_params! {
|
||||
|
@ -987,7 +1001,7 @@ impl IdlSqliteWriteTransaction {
|
|||
.conn
|
||||
.prepare(&format!(
|
||||
"DELETE FROM {}.idx_uuid2spn WHERE uuid = :uuid",
|
||||
"main"
|
||||
self.get_db_name()
|
||||
))
|
||||
.and_then(|mut stmt| stmt.execute(&[(":uuid", &uuids)]))
|
||||
.map(|_| ())
|
||||
|
@ -1000,7 +1014,7 @@ impl IdlSqliteWriteTransaction {
|
|||
.execute(
|
||||
&format!(
|
||||
"CREATE TABLE IF NOT EXISTS {}.idx_uuid2rdn (uuid TEXT PRIMARY KEY, rdn TEXT)",
|
||||
"main"
|
||||
self.get_db_name()
|
||||
),
|
||||
[],
|
||||
)
|
||||
|
@ -1015,7 +1029,7 @@ impl IdlSqliteWriteTransaction {
|
|||
.conn
|
||||
.prepare(&format!(
|
||||
"INSERT OR REPLACE INTO {}.idx_uuid2rdn (uuid, rdn) VALUES(:uuid, :rdn)",
|
||||
"main"
|
||||
self.get_db_name()
|
||||
))
|
||||
.and_then(|mut stmt| stmt.execute(&[(":uuid", &uuids), (":rdn", k)]))
|
||||
.map(|_| ())
|
||||
|
@ -1024,7 +1038,7 @@ impl IdlSqliteWriteTransaction {
|
|||
.conn
|
||||
.prepare(&format!(
|
||||
"DELETE FROM {}.idx_uuid2rdn WHERE uuid = :uuid",
|
||||
"main"
|
||||
self.get_db_name()
|
||||
))
|
||||
.and_then(|mut stmt| stmt.execute(&[(":uuid", &uuids)]))
|
||||
.map(|_| ())
|
||||
|
@ -1039,7 +1053,7 @@ impl IdlSqliteWriteTransaction {
|
|||
// We could also re-design our idl storage.
|
||||
let idx_stmt = format!(
|
||||
"CREATE TABLE IF NOT EXISTS {}.idx_{}_{} (key TEXT PRIMARY KEY, idl BLOB)",
|
||||
"main",
|
||||
self.get_db_name(),
|
||||
itype.as_idx_str(),
|
||||
attr
|
||||
);
|
||||
|
@ -1057,7 +1071,7 @@ impl IdlSqliteWriteTransaction {
|
|||
idx_table_list.iter().try_for_each(|idx_table| {
|
||||
trace!(table = ?idx_table, "removing idx_table");
|
||||
self.conn
|
||||
.prepare(format!("DROP TABLE {}.{}", "main", idx_table).as_str())
|
||||
.prepare(format!("DROP TABLE {}.{}", self.get_db_name(), idx_table).as_str())
|
||||
.and_then(|mut stmt| stmt.execute([]).map(|_| ()))
|
||||
.map_err(sqlite_error)
|
||||
})
|
||||
|
@ -1074,7 +1088,7 @@ impl IdlSqliteWriteTransaction {
|
|||
id TEXT PRIMARY KEY,
|
||||
slope INTEGER
|
||||
)",
|
||||
"main"
|
||||
self.get_db_name()
|
||||
),
|
||||
[],
|
||||
)
|
||||
|
@ -1083,7 +1097,10 @@ impl IdlSqliteWriteTransaction {
|
|||
|
||||
// Remove any data if it exists.
|
||||
self.conn
|
||||
.execute(&format!("DELETE FROM {}.idxslope_analysis", "main"), [])
|
||||
.execute(
|
||||
&format!("DELETE FROM {}.idxslope_analysis", self.get_db_name()),
|
||||
[],
|
||||
)
|
||||
.map(|_| ())
|
||||
.map_err(sqlite_error)?;
|
||||
|
||||
|
@ -1091,7 +1108,7 @@ impl IdlSqliteWriteTransaction {
|
|||
let key = format!("idx_{}_{}", k.itype.as_idx_str(), k.attr);
|
||||
self.conn
|
||||
.execute(
|
||||
&format!("INSERT OR REPLACE INTO {}.idxslope_analysis (id, slope) VALUES(:id, :slope)", "main"),
|
||||
&format!("INSERT OR REPLACE INTO {}.idxslope_analysis (id, slope) VALUES(:id, :slope)", self.get_db_name()),
|
||||
named_params! {
|
||||
":id": &key,
|
||||
":slope": &v,
|
||||
|
@ -1124,7 +1141,7 @@ impl IdlSqliteWriteTransaction {
|
|||
.get_conn()
|
||||
.prepare(&format!(
|
||||
"SELECT slope FROM {}.idxslope_analysis WHERE id = :id",
|
||||
"main"
|
||||
self.get_db_name()
|
||||
))
|
||||
.map_err(sqlite_error)?;
|
||||
|
||||
|
@ -1140,7 +1157,7 @@ impl IdlSqliteWriteTransaction {
|
|||
|
||||
pub unsafe fn purge_id2entry(&self) -> Result<(), OperationError> {
|
||||
self.conn
|
||||
.execute(&format!("DELETE FROM {}.id2entry", "main"), [])
|
||||
.execute(&format!("DELETE FROM {}.id2entry", self.get_db_name()), [])
|
||||
.map(|_| ())
|
||||
.map_err(sqlite_error)
|
||||
}
|
||||
|
@ -1156,7 +1173,7 @@ impl IdlSqliteWriteTransaction {
|
|||
.execute(
|
||||
&format!(
|
||||
"INSERT OR REPLACE INTO {}.db_sid (id, data) VALUES(:id, :sid)",
|
||||
"main"
|
||||
self.get_db_name()
|
||||
),
|
||||
named_params! {
|
||||
":id": &2,
|
||||
|
@ -1182,7 +1199,7 @@ impl IdlSqliteWriteTransaction {
|
|||
.execute(
|
||||
&format!(
|
||||
"INSERT OR REPLACE INTO {}.db_did (id, data) VALUES(:id, :did)",
|
||||
"main"
|
||||
self.get_db_name()
|
||||
),
|
||||
named_params! {
|
||||
":id": &2,
|
||||
|
@ -1208,7 +1225,7 @@ impl IdlSqliteWriteTransaction {
|
|||
.execute(
|
||||
&format!(
|
||||
"INSERT OR REPLACE INTO {}.db_op_ts (id, data) VALUES(:id, :did)",
|
||||
"main"
|
||||
self.get_db_name()
|
||||
),
|
||||
named_params! {
|
||||
":id": &1,
|
||||
|
@ -1228,7 +1245,10 @@ impl IdlSqliteWriteTransaction {
|
|||
fn get_db_version_key(&self, key: &str) -> i64 {
|
||||
self.conn
|
||||
.query_row(
|
||||
&format!("SELECT version FROM {}.db_version WHERE id = :id", "main"),
|
||||
&format!(
|
||||
"SELECT version FROM {}.db_version WHERE id = :id",
|
||||
self.get_db_name()
|
||||
),
|
||||
&[(":id", &key)],
|
||||
|row| row.get(0),
|
||||
)
|
||||
|
@ -1243,7 +1263,7 @@ impl IdlSqliteWriteTransaction {
|
|||
.execute(
|
||||
&format!(
|
||||
"INSERT OR REPLACE INTO {}.db_version (id, version) VALUES(:id, :dbv_id2entry)",
|
||||
"main"
|
||||
self.get_db_name()
|
||||
),
|
||||
named_params! {
|
||||
":id": &key,
|
||||
|
@ -1266,6 +1286,16 @@ impl IdlSqliteWriteTransaction {
|
|||
}
|
||||
|
||||
pub fn setup(&self) -> Result<(), OperationError> {
|
||||
// If the db_name is NOT main, we MAY need to create it as we are in
|
||||
// a test!
|
||||
if self.get_db_name() != "main" {
|
||||
warn!("Using non-default db-name - this database content WILL be lost!");
|
||||
// we need to attach the DB!
|
||||
self.conn
|
||||
.execute(&format!("ATTACH DATABASE '' AS {}", self.get_db_name()), [])
|
||||
.map_err(sqlite_error)?;
|
||||
};
|
||||
|
||||
// This stores versions of components. For example:
|
||||
// ----------------------
|
||||
// | id | version |
|
||||
|
@ -1286,7 +1316,7 @@ impl IdlSqliteWriteTransaction {
|
|||
version INTEGER
|
||||
)
|
||||
",
|
||||
"main"
|
||||
self.get_db_name()
|
||||
),
|
||||
[],
|
||||
)
|
||||
|
@ -1306,7 +1336,7 @@ impl IdlSqliteWriteTransaction {
|
|||
data BLOB NOT NULL
|
||||
)
|
||||
",
|
||||
"main"
|
||||
self.get_db_name()
|
||||
),
|
||||
[],
|
||||
)
|
||||
|
@ -1318,7 +1348,7 @@ impl IdlSqliteWriteTransaction {
|
|||
data BLOB NOT NULL
|
||||
)
|
||||
",
|
||||
"main"
|
||||
self.get_db_name()
|
||||
),
|
||||
[],
|
||||
)
|
||||
|
@ -1339,7 +1369,7 @@ impl IdlSqliteWriteTransaction {
|
|||
data BLOB NOT NULL
|
||||
)
|
||||
",
|
||||
"main"
|
||||
self.get_db_name()
|
||||
),
|
||||
[],
|
||||
)
|
||||
|
@ -1358,7 +1388,7 @@ impl IdlSqliteWriteTransaction {
|
|||
data BLOB NOT NULL
|
||||
)
|
||||
",
|
||||
"main"
|
||||
self.get_db_name()
|
||||
),
|
||||
[],
|
||||
)
|
||||
|
@ -1505,7 +1535,10 @@ impl IdlSqlite {
|
|||
OperationError::SqliteError
|
||||
})?;
|
||||
|
||||
Ok(IdlSqlite { pool })
|
||||
Ok(IdlSqlite {
|
||||
pool,
|
||||
db_name: cfg.db_name,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn get_allids_count(&self) -> Result<u64, OperationError> {
|
||||
|
@ -1526,7 +1559,7 @@ impl IdlSqlite {
|
|||
.pool
|
||||
.try_get()
|
||||
.expect("Unable to get connection from pool!!!");
|
||||
IdlSqliteReadTransaction::new(conn)
|
||||
IdlSqliteReadTransaction::new(conn, self.db_name)
|
||||
}
|
||||
|
||||
pub fn write(&self) -> IdlSqliteWriteTransaction {
|
||||
|
@ -1535,7 +1568,7 @@ impl IdlSqlite {
|
|||
.pool
|
||||
.try_get()
|
||||
.expect("Unable to get connection from pool!!!");
|
||||
IdlSqliteWriteTransaction::new(conn)
|
||||
IdlSqliteWriteTransaction::new(conn, self.db_name)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1547,7 +1580,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_idl_sqlite_verify() {
|
||||
let _ = sketching::test_init();
|
||||
let cfg = BackendConfig::new_test();
|
||||
let cfg = BackendConfig::new_test("main");
|
||||
let be = IdlSqlite::new(&cfg, false).unwrap();
|
||||
let be_w = be.write();
|
||||
let r = be_w.verify();
|
||||
|
|
|
@ -108,6 +108,7 @@ impl IdxMeta {
|
|||
pub struct BackendConfig {
|
||||
path: String,
|
||||
pool_size: u32,
|
||||
db_name: &'static str,
|
||||
fstype: FsType,
|
||||
// Cachesizes?
|
||||
arcsize: Option<usize>,
|
||||
|
@ -118,15 +119,17 @@ impl BackendConfig {
|
|||
BackendConfig {
|
||||
pool_size,
|
||||
path: path.to_string(),
|
||||
db_name: "main",
|
||||
fstype,
|
||||
arcsize,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn new_test() -> Self {
|
||||
pub(crate) fn new_test(db_name: &'static str) -> Self {
|
||||
BackendConfig {
|
||||
pool_size: 1,
|
||||
path: "".to_string(),
|
||||
db_name,
|
||||
fstype: FsType::Generic,
|
||||
arcsize: Some(1024),
|
||||
}
|
||||
|
@ -1834,7 +1837,7 @@ mod tests {
|
|||
},
|
||||
];
|
||||
|
||||
let be = Backend::new(BackendConfig::new_test(), idxmeta, false)
|
||||
let be = Backend::new(BackendConfig::new_test("main"), idxmeta, false)
|
||||
.expect("Failed to setup backend");
|
||||
|
||||
let mut be_txn = be.write();
|
||||
|
@ -3164,4 +3167,68 @@ mod tests {
|
|||
assert!(res == Err(OperationError::ResourceLimit));
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_be_mulitple_create() {
|
||||
let _ = sketching::test_init();
|
||||
|
||||
// This is a demo idxmeta, purely for testing.
|
||||
let idxmeta = vec![IdxKey {
|
||||
attr: AttrString::from("uuid"),
|
||||
itype: IndexType::Equality,
|
||||
}];
|
||||
|
||||
let be_a = Backend::new(BackendConfig::new_test("main"), idxmeta.clone(), false)
|
||||
.expect("Failed to setup backend");
|
||||
|
||||
let be_b = Backend::new(BackendConfig::new_test("db_2"), idxmeta, false)
|
||||
.expect("Failed to setup backend");
|
||||
|
||||
let mut be_a_txn = be_a.write();
|
||||
let mut be_b_txn = be_b.write();
|
||||
|
||||
assert!(be_a_txn.get_db_s_uuid() != be_b_txn.get_db_s_uuid());
|
||||
|
||||
// Create into A
|
||||
let mut e: Entry<EntryInit, EntryNew> = Entry::new();
|
||||
e.add_ava("userid", Value::from("william"));
|
||||
e.add_ava("uuid", Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d1"));
|
||||
let e = unsafe { e.into_sealed_new() };
|
||||
|
||||
let single_result = be_a_txn.create(&CID_ZERO, vec![e.clone()]);
|
||||
|
||||
assert!(single_result.is_ok());
|
||||
|
||||
// Assert it's in A but not B.
|
||||
let filt = unsafe { filter_resolved!(f_eq("userid", PartialValue::new_utf8s("william"))) };
|
||||
|
||||
let lims = Limits::unlimited();
|
||||
|
||||
let r = be_a_txn.search(&lims, &filt);
|
||||
assert!(r.expect("Search failed!").len() == 1);
|
||||
|
||||
let r = be_b_txn.search(&lims, &filt);
|
||||
assert!(r.expect("Search failed!").len() == 0);
|
||||
|
||||
// Create into B
|
||||
let mut e: Entry<EntryInit, EntryNew> = Entry::new();
|
||||
e.add_ava("userid", Value::from("claire"));
|
||||
e.add_ava("uuid", Value::from("0c680959-0944-47d6-9dea-53304d124266"));
|
||||
let e = unsafe { e.into_sealed_new() };
|
||||
|
||||
let single_result = be_b_txn.create(&CID_ZERO, vec![e.clone()]);
|
||||
|
||||
assert!(single_result.is_ok());
|
||||
|
||||
// Assert it's in B but not A
|
||||
let filt = unsafe { filter_resolved!(f_eq("userid", PartialValue::new_utf8s("claire"))) };
|
||||
|
||||
let lims = Limits::unlimited();
|
||||
|
||||
let r = be_a_txn.search(&lims, &filt);
|
||||
assert!(r.expect("Search failed!").len() == 0);
|
||||
|
||||
let r = be_b_txn.search(&lims, &filt);
|
||||
assert!(r.expect("Search failed!").len() == 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,8 +9,8 @@ macro_rules! setup_test {
|
|||
let schema_txn = schema_outer.write_blocking();
|
||||
schema_txn.reload_idxmeta()
|
||||
};
|
||||
let be =
|
||||
Backend::new(BackendConfig::new_test(), idxmeta, false).expect("Failed to init BE");
|
||||
let be = Backend::new(BackendConfig::new_test("main"), idxmeta, false)
|
||||
.expect("Failed to init BE");
|
||||
|
||||
let qs = QueryServer::new(be, schema_outer, "example.com".to_string());
|
||||
async_std::task::block_on(qs.initialise_helper(duration_from_epoch_now()))
|
||||
|
@ -30,8 +30,8 @@ macro_rules! setup_test {
|
|||
let schema_txn = schema_outer.write();
|
||||
schema_txn.reload_idxmeta()
|
||||
};
|
||||
let be =
|
||||
Backend::new(BackendConfig::new_test(), idxmeta, false).expect("Failed to init BE");
|
||||
let be = Backend::new(BackendConfig::new_test("main"), idxmeta, false)
|
||||
.expect("Failed to init BE");
|
||||
|
||||
let qs = QueryServer::new(be, schema_outer, "example.com".to_string());
|
||||
async_std::task::block_on(qs.initialise_helper(duration_from_epoch_now()))
|
||||
|
|
7
kanidmd/lib/src/repl/tests.rs
Normal file
7
kanidmd/lib/src/repl/tests.rs
Normal file
|
@ -0,0 +1,7 @@
|
|||
use crate::prelude::*;
|
||||
|
||||
#[tokio::test]
|
||||
async fn multiple_qs_setup() {
|
||||
assert!(true);
|
||||
}
|
||||
|
|
@ -168,8 +168,7 @@ mod tests {
|
|||
let filt = filter!(f_eq("name", PartialValue::new_iname("testperson")));
|
||||
let admin = server_txn.internal_search_uuid(UUID_ADMIN).expect("failed");
|
||||
|
||||
let se1 = unsafe { SearchEvent::new_impersonate_entry(admin.clone(), filt.clone()) };
|
||||
let se2 = unsafe { SearchEvent::new_impersonate_entry(admin, filt) };
|
||||
let se1 = unsafe { SearchEvent::new_impersonate_entry(admin, filt) };
|
||||
|
||||
let mut e = entry_init!(
|
||||
("class", Value::new_class("object")),
|
||||
|
@ -193,7 +192,7 @@ mod tests {
|
|||
let cr = server_txn.create(&ce);
|
||||
assert!(cr.is_ok());
|
||||
|
||||
let r2 = server_txn.search(&se2).expect("search failure");
|
||||
let r2 = server_txn.search(&se1).expect("search failure");
|
||||
debug!("--> {:?}", r2);
|
||||
assert!(r2.len() == 1);
|
||||
|
||||
|
@ -210,4 +209,51 @@ mod tests {
|
|||
|
||||
assert!(server_txn.commit().is_ok());
|
||||
}
|
||||
|
||||
#[qs_pair_test]
|
||||
async fn test_pair_create_user(server_a: &QueryServer, server_b: &QueryServer) {
|
||||
let mut server_a_txn = server_a.write(duration_from_epoch_now()).await;
|
||||
let mut server_b_txn = server_b.write(duration_from_epoch_now()).await;
|
||||
|
||||
// Create on server a
|
||||
let filt = filter!(f_eq("name", PartialValue::new_iname("testperson")));
|
||||
|
||||
let admin = server_a_txn
|
||||
.internal_search_uuid(UUID_ADMIN)
|
||||
.expect("failed");
|
||||
let se_a = unsafe { SearchEvent::new_impersonate_entry(admin, filt.clone()) };
|
||||
|
||||
let admin = server_b_txn
|
||||
.internal_search_uuid(UUID_ADMIN)
|
||||
.expect("failed");
|
||||
let se_b = unsafe { SearchEvent::new_impersonate_entry(admin, filt) };
|
||||
|
||||
let e = entry_init!(
|
||||
("class", Value::new_class("person")),
|
||||
("class", Value::new_class("account")),
|
||||
("name", Value::new_iname("testperson")),
|
||||
("description", Value::new_utf8s("testperson")),
|
||||
("displayname", Value::new_utf8s("testperson"))
|
||||
);
|
||||
|
||||
let cr = server_a_txn.internal_create(vec![e.clone()]);
|
||||
assert!(cr.is_ok());
|
||||
|
||||
let r1 = server_a_txn.search(&se_a).expect("search failure");
|
||||
assert!(!r1.is_empty());
|
||||
|
||||
// Not on sb
|
||||
let r2 = server_b_txn.search(&se_b).expect("search failure");
|
||||
assert!(r2.is_empty());
|
||||
|
||||
let cr = server_b_txn.internal_create(vec![e.clone()]);
|
||||
assert!(cr.is_ok());
|
||||
|
||||
// Now is present
|
||||
let r2 = server_b_txn.search(&se_b).expect("search failure");
|
||||
assert!(!r2.is_empty());
|
||||
|
||||
assert!(server_a_txn.commit().is_ok());
|
||||
assert!(server_b_txn.commit().is_ok());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,12 +14,48 @@ pub async fn setup_test() -> QueryServer {
|
|||
let schema_txn = schema_outer.write();
|
||||
schema_txn.reload_idxmeta()
|
||||
};
|
||||
let be = Backend::new(BackendConfig::new_test(), idxmeta, false).expect("Failed to init BE");
|
||||
let be =
|
||||
Backend::new(BackendConfig::new_test("main"), idxmeta, false).expect("Failed to init BE");
|
||||
|
||||
// Init is called via the proc macro
|
||||
QueryServer::new(be, schema_outer, "example.com".to_string())
|
||||
}
|
||||
|
||||
#[allow(clippy::expect_used)]
|
||||
pub async fn setup_pair_test() -> (QueryServer, QueryServer) {
|
||||
sketching::test_init();
|
||||
|
||||
let qs_a = {
|
||||
// Create an in memory BE
|
||||
let schema_outer = Schema::new().expect("Failed to init schema");
|
||||
let idxmeta = {
|
||||
let schema_txn = schema_outer.write();
|
||||
schema_txn.reload_idxmeta()
|
||||
};
|
||||
let be = Backend::new(BackendConfig::new_test("db_a"), idxmeta, false)
|
||||
.expect("Failed to init BE");
|
||||
|
||||
// Init is called via the proc macro
|
||||
QueryServer::new(be, schema_outer, "example.com".to_string())
|
||||
};
|
||||
|
||||
let qs_b = {
|
||||
// Create an in memory BE
|
||||
let schema_outer = Schema::new().expect("Failed to init schema");
|
||||
let idxmeta = {
|
||||
let schema_txn = schema_outer.write();
|
||||
schema_txn.reload_idxmeta()
|
||||
};
|
||||
let be = Backend::new(BackendConfig::new_test("db_b"), idxmeta, false)
|
||||
.expect("Failed to init BE");
|
||||
|
||||
// Init is called via the proc macro
|
||||
QueryServer::new(be, schema_outer, "example.com".to_string())
|
||||
};
|
||||
|
||||
(qs_a, qs_b)
|
||||
}
|
||||
|
||||
#[allow(clippy::expect_used)]
|
||||
pub async fn setup_idm_test() -> (IdmServer, IdmServerDelayed) {
|
||||
let qs = setup_test().await;
|
||||
|
|
Loading…
Reference in a new issue