use super::*; #[test] fn bounded_cache_never_evicts_an_active_tenant_pool() { let directory = Directory::new(); runtime() .run(async |scope| { let registry = Registry::prepare(&directory.0, settings(true, 1), &bindings(), scope) .await .unwrap(); registry.migrate_tenant(scope, 1).await.unwrap(); registry.migrate_tenant(scope, 2).await.unwrap(); let mut first = Context::new(registry.clone()); first.select_tenant(scope, 1).await.unwrap(); first.on(0, scope).await.unwrap(); let mut second = Context::new(registry.clone()); assert_eq!( second.select_tenant(scope, 2).await.unwrap_err().kind, Kind::PoolExhausted ); assert_eq!( registry.migrate_tenant(scope, 1).await.unwrap_err().kind, Kind::Pool ); drop(first); second.select_tenant(scope, 2).await.unwrap(); second.on(0, scope).await.unwrap(); drop(second); registry.close().await; }) .unwrap(); } #[test] fn stale_or_missing_markers_and_files_never_fall_back_or_recreate_storage() { let directory = Directory::new(); runtime() .run(async |scope| { let registry = Registry::prepare(&directory.0, settings(true, 1), &bindings(), scope) .await .unwrap(); registry.migrate_tenant(scope, 1).await.unwrap(); let mut context = Context::new(registry.clone()); context.select_tenant(scope, 1).await.unwrap(); context .on(0, scope) .await .unwrap() .execute( scope, "UPDATE _dever_tenant_ready SET fingerprint='wrong'", vec![], ) .await .unwrap(); drop(context); let mut next = Context::new(registry.clone()); assert_eq!( next.select_tenant(scope, 1).await.unwrap_err().kind, Kind::Migration ); registry.migrate_tenant(scope, 1).await.unwrap(); next.control(scope) .await .unwrap() .execute(scope, "UPDATE _dever_tenant_storage SET ready=0", vec![]) .await .unwrap(); assert!(next.select_tenant(scope, 1).await.is_err()); assert!(registry.queue_tenants(0, scope).await.unwrap().is_empty()); registry.migrate_tenant(scope, 1).await.unwrap(); std::fs::remove_file(directory.0.join("tenants/1.db")).unwrap(); assert!(next.select_tenant(scope, 1).await.is_err()); assert!(!directory.0.join("tenants/1.db").exists()); for id in [0, -1] { assert_eq!( registry.migrate_tenant(scope, id).await.unwrap_err().kind, Kind::InvalidData ); } registry.close().await; }) .unwrap(); } #[test] fn failed_schema_migration_stays_unready_and_never_becomes_a_cached_success() { let directory = Directory::new(); runtime().run(async |scope| { let registry = Registry::prepare(&directory.0, settings(true, 2), &bindings(), scope).await.unwrap(); registry.migrate_tenant(scope, 1).await.unwrap(); registry.close().await; drop(registry); let mut changed = bindings(); changed[0].schema = Sql::same("CREATE TABLE items(id BIGINT PRIMARY KEY, value TEXT NOT NULL, changed BIGINT NOT NULL)"); let registry = Registry::prepare(&directory.0, settings(true, 2), &changed, scope).await.unwrap(); let mut context = Context::new(registry.clone()); assert!(context.select_tenant(scope, 1).await.is_err()); assert_eq!(registry.migrate_tenant(scope, 1).await.unwrap_err().kind, Kind::Migration); assert!(context.select_tenant(scope, 1).await.is_err()); assert!(registry.queue_tenants(0, scope).await.unwrap().is_empty()); registry.close().await; }).unwrap(); }