fix: isolate finite DB and Host execution ownership in fixtures
This commit is contained in:
@@ -119,7 +119,7 @@ async fn assignment_delivery_response_loss_returns_immutable_payload_after_progr
|
||||
.update_ticket_assignment_tracking("w", "tracking", &update, &source)
|
||||
.unwrap();
|
||||
drop(store);
|
||||
let store = SqliteWorkspaceStore::open(directory.path().join("workspace.db")).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(directory.path().join("workspace.db")).unwrap();
|
||||
assert_eq!(
|
||||
store
|
||||
.list_pending_ticket_assignment_deliveries("w", 100)
|
||||
@@ -180,7 +180,7 @@ async fn assignment_delivery_simultaneous_reservations_converge_to_one_receipt()
|
||||
let path = directory.path().join("workspace.db");
|
||||
let input = pending.input_event_id.clone();
|
||||
std::thread::spawn(move || {
|
||||
let store = SqliteWorkspaceStore::open(path).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(path).unwrap();
|
||||
barrier.wait();
|
||||
store
|
||||
.reserve_ticket_assignment_delivery("w", "a", &input, &tracking_store_source())
|
||||
@@ -540,7 +540,7 @@ async fn assignment_delivery_rendered_content_is_immutable_across_restart_and_co
|
||||
"original rendered prompt"
|
||||
);
|
||||
drop(store);
|
||||
let store = SqliteWorkspaceStore::open(directory.path().join("workspace.db")).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(directory.path().join("workspace.db")).unwrap();
|
||||
assert_eq!(
|
||||
store
|
||||
.prepare_ticket_assignment_delivery_content(
|
||||
@@ -606,7 +606,7 @@ fn assignment_delivery_schema92_upgrade_uses_reconciled_migration_evidence_not_l
|
||||
let operations = stored_fixture_rows(&conn, "ticket_assignment_operations");
|
||||
let tracking = stored_fixture_rows(&conn, "typed_ticket_assignment_tracking_history");
|
||||
drop(conn);
|
||||
let store = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
let pending = store
|
||||
.list_pending_ticket_assignment_deliveries("w", 100)
|
||||
.unwrap();
|
||||
@@ -656,7 +656,7 @@ async fn assignment_startup_simultaneous_reservations_admit_runtime_effects_once
|
||||
let barrier = barrier.clone();
|
||||
let path = directory.path().join("workspace.db");
|
||||
std::thread::spawn(move || {
|
||||
let store = SqliteWorkspaceStore::open(path).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(path).unwrap();
|
||||
barrier.wait();
|
||||
delivery_store_start_reserve(&store, "start-a", "a", &tracking_store_source())
|
||||
.unwrap()
|
||||
@@ -688,8 +688,8 @@ fn assignment_delivery_fresh_and_upgraded_operational_schemas_are_identical() {
|
||||
let conn = tracking_schema91_fixture(&path);
|
||||
migrate_ticket_tracking_v91_to_v92(&conn).unwrap();
|
||||
drop(conn);
|
||||
let upgraded = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let fresh = SqliteWorkspaceStore::in_memory().unwrap();
|
||||
let upgraded = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
let fresh = SqliteWorkspaceStore::in_memory_for_test().unwrap();
|
||||
let objects = |store: &SqliteWorkspaceStore| {
|
||||
store.with_conn(|conn| {
|
||||
let mut statement=conn.prepare("SELECT type,name,sql FROM sqlite_schema WHERE name LIKE 'ticket_assignment_delivery_%' OR name LIKE 'ticket_assignment_operation_fence%' ORDER BY name")?;
|
||||
@@ -713,7 +713,7 @@ async fn assignment_delivery_missing_immutable_request_guard_refuses_startup() {
|
||||
.unwrap();
|
||||
drop(store);
|
||||
assert!(
|
||||
matches!(SqliteWorkspaceStore::open(directory.path().join("workspace.db")),Err(Error::Store(message)) if message.contains("ticket_assignment_delivery_request_no_update"))
|
||||
matches!(SqliteWorkspaceStore::open_for_test(directory.path().join("workspace.db")),Err(Error::Store(message)) if message.contains("ticket_assignment_delivery_request_no_update"))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ async fn tracking_store_every_replay_fences_current_singleton_and_authenticated_
|
||||
);
|
||||
// Model the authority change after authenticated source capture, before
|
||||
// BEGIN IMMEDIATE on a second connection. Receipt presence cannot bypass it.
|
||||
let second = SqliteWorkspaceStore::open(directory.path().join("workspace.db")).unwrap();
|
||||
let second = SqliteWorkspaceStore::open_for_test(directory.path().join("workspace.db")).unwrap();
|
||||
second.with_conn_mut(|conn| {
|
||||
let tx=conn.transaction_with_behavior(TransactionBehavior::Immediate)?;
|
||||
match change {
|
||||
@@ -233,7 +233,7 @@ async fn tracking_store_same_principal_reissue_and_exact_retries_keep_original_r
|
||||
.is_err()
|
||||
);
|
||||
drop(store);
|
||||
let reopened = SqliteWorkspaceStore::open(directory.path().join("workspace.db")).unwrap();
|
||||
let reopened = SqliteWorkspaceStore::open_for_test(directory.path().join("workspace.db")).unwrap();
|
||||
assert_eq!(
|
||||
reopened
|
||||
.get_ticket_assignment_tracking("w", "tracking", "a")
|
||||
@@ -441,7 +441,7 @@ fn tracking_store_real_schema91_to92_retains_queue_cases_principals_audit_receip
|
||||
.collect::<Vec<_>>(),
|
||||
vec![92, 93]
|
||||
);
|
||||
let store = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
store
|
||||
.with_conn(|conn| {
|
||||
assert_eq!(current_schema_version(conn)?, 93);
|
||||
@@ -522,7 +522,7 @@ fn tracking_store_real_schema91_to92_retains_queue_cases_principals_audit_receip
|
||||
.list_ticket_assignment_tracking_history("w", "pending", "a-pending")
|
||||
.unwrap();
|
||||
drop(store);
|
||||
let reopened = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let reopened = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
assert_eq!(
|
||||
reopened
|
||||
.list_ticket_assignment_tracking_history("w", "pending", "a-pending")
|
||||
@@ -547,7 +547,7 @@ fn tracking_store_schema91_closed_unknown_assignment_uses_assign_audit_for_first
|
||||
let releases_before = stored_fixture_rows(&conn, "ticket_assignment_work_releases");
|
||||
drop(conn);
|
||||
|
||||
let store = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
let backend = ticket::SqliteTicketBackend::open_verified(&path, "w").unwrap();
|
||||
let reopen = || {
|
||||
let observed = backend.show("historical-done".into()).unwrap();
|
||||
@@ -642,7 +642,7 @@ fn tracking_store_schema91_closed_unknown_assignment_uses_assign_audit_for_first
|
||||
);
|
||||
// A second observer holds the same Assign baseline. Only the first
|
||||
// explicit writer may consume it; BEGIN IMMEDIATE serializes the CAS.
|
||||
let second = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let second = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
assert_eq!(
|
||||
second
|
||||
.get_ticket_assignment_tracking("w", "historical-done", "a-historical-done")
|
||||
@@ -737,7 +737,7 @@ fn tracking_store_schema91_closed_unknown_assignment_uses_assign_audit_for_first
|
||||
}).unwrap();
|
||||
drop(second);
|
||||
drop(store);
|
||||
let reopened_store = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let reopened_store = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
assert_eq!(
|
||||
reopened_store
|
||||
.get_ticket_assignment_tracking("w", "historical-done", "a-historical-done")
|
||||
@@ -793,7 +793,7 @@ fn tracking_store_schema91_missing_assign_audit_remains_unknown_without_cas_base
|
||||
)
|
||||
.unwrap();
|
||||
drop(conn);
|
||||
let store = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
let unknown = store
|
||||
.get_ticket_assignment_tracking("w", "historical-done", "a-historical-done")
|
||||
.unwrap()
|
||||
@@ -1065,7 +1065,7 @@ async fn orchestrator_assignment_all_runtime_retries_fence_singleton_and_binding
|
||||
&source,
|
||||
)
|
||||
.unwrap();
|
||||
let second = SqliteWorkspaceStore::open(directory.path().join("workspace.db")).unwrap();
|
||||
let second = SqliteWorkspaceStore::open_for_test(directory.path().join("workspace.db")).unwrap();
|
||||
second.with_conn_mut(|conn| {let tx=conn.transaction_with_behavior(TransactionBehavior::Immediate)?;match change {
|
||||
"replace" => {tx.execute("UPDATE worker_singleton_owners SET worker_id='replacement',generation=2 WHERE workspace_id='w'",[])?;},
|
||||
"revoke" => {tx.execute("UPDATE workspace_runtime_bindings SET revoked_at='revoked' WHERE workspace_id='w'",[])?;},
|
||||
|
||||
@@ -203,7 +203,7 @@ mod tests {
|
||||
})
|
||||
.unwrap();
|
||||
let store = Arc::new(
|
||||
SqliteWorkspaceStore::in_memory()
|
||||
SqliteWorkspaceStore::in_memory_for_test()
|
||||
.unwrap()
|
||||
.with_db_executor(executor),
|
||||
);
|
||||
|
||||
@@ -3241,7 +3241,7 @@ mod tests {
|
||||
async fn unfinished_dependencies_remain_diagnostic_without_disabling_manual_start() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let path = dir.path().join("workspace.db");
|
||||
let store = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
store
|
||||
.upsert_workspace(&WorkspaceRecord {
|
||||
workspace_id: "w".into(),
|
||||
@@ -3316,7 +3316,7 @@ mod tests {
|
||||
async fn manual_worker_eligibility_accepts_explicit_states_without_reviving_released_work() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let path = dir.path().join("workspace.db");
|
||||
let store = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
store
|
||||
.upsert_workspace(&WorkspaceRecord {
|
||||
workspace_id: "w".into(),
|
||||
@@ -3449,7 +3449,7 @@ mod tests {
|
||||
write_ticket(dir.path(), "00000000001J5", "Second ticket", "queued");
|
||||
write_ticket(dir.path(), "00000000001J6", "Third ticket", "planning");
|
||||
let db_path = dir.path().join("workspace.db");
|
||||
let store = SqliteWorkspaceStore::open(&db_path).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&db_path).unwrap();
|
||||
store
|
||||
.upsert_workspace(&WorkspaceRecord {
|
||||
workspace_id: "workspace-test".to_string(),
|
||||
@@ -3881,7 +3881,7 @@ VALUES ('workspace-test', 'ticket', 4);
|
||||
async fn objective_mutations_write_sqlite_records_and_audit_events() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let db_path = dir.path().join("workspace.db");
|
||||
let store = SqliteWorkspaceStore::open(&db_path).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&db_path).unwrap();
|
||||
store
|
||||
.upsert_workspace(&WorkspaceRecord {
|
||||
workspace_id: "workspace-test".to_string(),
|
||||
|
||||
@@ -795,7 +795,7 @@ mod tests {
|
||||
}
|
||||
|
||||
async fn open_store() -> SqliteWorkspaceStore {
|
||||
let store = SqliteWorkspaceStore::in_memory().unwrap();
|
||||
let store = SqliteWorkspaceStore::in_memory_for_test().unwrap();
|
||||
store.upsert_workspace(&workspace()).await.unwrap();
|
||||
store
|
||||
}
|
||||
@@ -1454,7 +1454,7 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn invalid_candidate_is_never_persisted() {
|
||||
let store = SqliteWorkspaceStore::in_memory().unwrap();
|
||||
let store = SqliteWorkspaceStore::in_memory_for_test().unwrap();
|
||||
store.upsert_workspace(&workspace()).await.unwrap();
|
||||
let current = store.load_workspace_config("w-config").unwrap().unwrap();
|
||||
let main = current.snapshot.get(&path(MAIN_CONFIG_ENTRYPOINT)).unwrap();
|
||||
@@ -1478,7 +1478,7 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn valid_candidate_commits_snapshot_content_and_provenance_atomically() {
|
||||
let store = SqliteWorkspaceStore::in_memory().unwrap();
|
||||
let store = SqliteWorkspaceStore::in_memory_for_test().unwrap();
|
||||
store.upsert_workspace(&workspace()).await.unwrap();
|
||||
let current = store.load_workspace_config("w-config").unwrap().unwrap();
|
||||
let committed = store
|
||||
@@ -1496,7 +1496,7 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn stale_cas_cannot_overwrite_newer_tree() {
|
||||
let store = SqliteWorkspaceStore::in_memory().unwrap();
|
||||
let store = SqliteWorkspaceStore::in_memory_for_test().unwrap();
|
||||
store.upsert_workspace(&workspace()).await.unwrap();
|
||||
let current = store.load_workspace_config("w-config").unwrap().unwrap();
|
||||
let request = commit_request(¤t, vec![update_main(¤t, "{ answer = 42; }")]);
|
||||
@@ -1514,7 +1514,7 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn committed_content_remains_retrievable_after_later_commit() {
|
||||
let store = SqliteWorkspaceStore::in_memory().unwrap();
|
||||
let store = SqliteWorkspaceStore::in_memory_for_test().unwrap();
|
||||
store.upsert_workspace(&workspace()).await.unwrap();
|
||||
let current = store.load_workspace_config("w-config").unwrap().unwrap();
|
||||
let first = store
|
||||
@@ -1772,7 +1772,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn migration_creates_config_authority_tables() {
|
||||
let store = SqliteWorkspaceStore::in_memory().unwrap();
|
||||
let store = SqliteWorkspaceStore::in_memory_for_test().unwrap();
|
||||
store
|
||||
.with_conn(|conn| {
|
||||
for table in [
|
||||
|
||||
@@ -818,7 +818,7 @@ mod current_authority {
|
||||
use super::*;
|
||||
|
||||
fn binding_store() -> (SqliteWorkspaceStore, WorkspaceRuntimeBinding) {
|
||||
let store = SqliteWorkspaceStore::in_memory().unwrap();
|
||||
let store = SqliteWorkspaceStore::in_memory_for_test().unwrap();
|
||||
let runtime_key =
|
||||
worker_runtime::auth::RuntimeIdentityMaterial::generate("runtime-key").unwrap();
|
||||
store.with_conn(|conn| {
|
||||
|
||||
@@ -6394,7 +6394,7 @@ mod tests {
|
||||
})
|
||||
.unwrap();
|
||||
let store = Arc::new(
|
||||
SqliteWorkspaceStore::in_memory()
|
||||
SqliteWorkspaceStore::in_memory_for_test()
|
||||
.unwrap()
|
||||
.with_db_executor(executor.clone()),
|
||||
);
|
||||
|
||||
@@ -32,7 +32,8 @@ struct Fixture {
|
||||
impl Fixture {
|
||||
async fn new() -> Self {
|
||||
let temp = tempfile::tempdir().unwrap();
|
||||
let store = Arc::new(SqliteWorkspaceStore::open(temp.path().join("server.db")).unwrap());
|
||||
let store =
|
||||
Arc::new(SqliteWorkspaceStore::open_for_test(temp.path().join("server.db")).unwrap());
|
||||
store
|
||||
.upsert_account(&AccountRecord {
|
||||
account_id: "owner".into(),
|
||||
|
||||
@@ -45,7 +45,7 @@ fn evidence_column_cutover_preserves_all_values_and_current_schema_names() {
|
||||
let artifacts = evidence_rows(&conn, "artifacts");
|
||||
let receipts = evidence_rows(&conn, "repository_secret_legacy_receipts");
|
||||
drop(conn);
|
||||
let upgraded = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let upgraded = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
upgraded
|
||||
.with_conn(|conn| {
|
||||
assert_eq!(current_schema_version(conn)?, LATEST_SCHEMA_VERSION);
|
||||
@@ -73,7 +73,7 @@ fn evidence_column_cutover_preserves_all_values_and_current_schema_names() {
|
||||
Ok(())
|
||||
})
|
||||
.unwrap();
|
||||
for store in [upgraded, SqliteWorkspaceStore::in_memory().unwrap()] {
|
||||
for store in [upgraded, SqliteWorkspaceStore::in_memory_for_test().unwrap()] {
|
||||
store.with_conn(|conn| {
|
||||
let mut stmt = conn.prepare("SELECT name,sql FROM sqlite_schema WHERE sql IS NOT NULL AND name NOT LIKE 'sqlite_%'")?;
|
||||
let objects = stmt.query_map([],|row|Ok((row.get::<_,String>(0)?,row.get::<_,String>(1)?)))?.collect::<rusqlite::Result<Vec<_>>>()?;
|
||||
|
||||
@@ -217,7 +217,7 @@ mod tests {
|
||||
async fn authority() -> (TempDir, SqliteWorkspaceAuthority) {
|
||||
let temp = TempDir::new().unwrap();
|
||||
let db_path = temp.path().join("workspace.db");
|
||||
let store = SqliteWorkspaceStore::open(&db_path).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&db_path).unwrap();
|
||||
store
|
||||
.upsert_workspace(&WorkspaceRecord {
|
||||
workspace_id: "workspace-test".to_string(),
|
||||
|
||||
@@ -32,7 +32,7 @@ fn opening_schema_84_with_uncertain_removal_preserves_old_server_recovery() {
|
||||
drop(conn);
|
||||
for attempt in 0..3 {
|
||||
let error = match attempt {
|
||||
0 => SqliteWorkspaceStore::open(&path).err().unwrap(),
|
||||
0 => SqliteWorkspaceStore::open_for_test(&path).err().unwrap(),
|
||||
1 => SqliteWorkspaceStore::migration_plan(&path).unwrap_err(),
|
||||
_ => SqliteWorkspaceStore::migrate_database(&path).unwrap_err(),
|
||||
};
|
||||
@@ -62,7 +62,7 @@ fn opening_schema_84_with_uncertain_removal_preserves_old_server_recovery() {
|
||||
)
|
||||
.unwrap();
|
||||
drop(conn);
|
||||
let store = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
store.with_conn(|conn| {
|
||||
assert_eq!(current_schema_version(conn)?, LATEST_SCHEMA_VERSION);
|
||||
assert_eq!(conn.query_row("SELECT input_fingerprint FROM worker_removal_operations WHERE operation_id='removal'",[],|r|r.get::<_,String>(0))?,"legacy-receipt");
|
||||
@@ -109,7 +109,7 @@ fn migration_dry_run_and_apply_share_the_original_repository_secret_authority()
|
||||
assert!(!table_exists(&conn, "server_secret_objects").unwrap());
|
||||
drop(conn);
|
||||
assert_eq!(SqliteWorkspaceStore::migrate_database(&path).unwrap(), plan);
|
||||
let store = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
store.with_conn(|conn| {
|
||||
assert_eq!(current_schema_version(conn)?,LATEST_SCHEMA_VERSION);
|
||||
let (nonce, mut sealed): (Vec<u8>,Vec<u8>) = conn.query_row(
|
||||
|
||||
@@ -2290,7 +2290,7 @@ mod tests {
|
||||
) {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let database = dir.path().join("server.db");
|
||||
let store = Arc::new(SqliteWorkspaceStore::open(&database).unwrap());
|
||||
let store = Arc::new(SqliteWorkspaceStore::open_for_test(&database).unwrap());
|
||||
let timestamp = now();
|
||||
for workspace_id in ["workspace-a", "workspace-b"] {
|
||||
futures::executor::block_on(store.upsert_workspace(&WorkspaceRecord {
|
||||
|
||||
@@ -1116,7 +1116,7 @@ mod tests {
|
||||
WorkerId::from_legacy_u64(1)
|
||||
}
|
||||
fn setup() -> SqliteWorkspaceStore {
|
||||
let s = SqliteWorkspaceStore::in_memory().unwrap();
|
||||
let s = SqliteWorkspaceStore::in_memory_for_test().unwrap();
|
||||
s.with_conn(|c| {
|
||||
c.execute(
|
||||
"INSERT INTO accounts(account_id,kind,handle,display_name,created_at,updated_at) \
|
||||
|
||||
@@ -38,8 +38,8 @@ fn fresh_and_upgraded_state_contract_schemas_enforce_the_same_constraints() {
|
||||
let temp = tempfile::tempdir().unwrap();
|
||||
let path = temp.path().join("upgraded.db");
|
||||
prepare_retained_schema(&path, 85);
|
||||
let upgraded = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let fresh = SqliteWorkspaceStore::in_memory().unwrap();
|
||||
let upgraded = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
let fresh = SqliteWorkspaceStore::in_memory_for_test().unwrap();
|
||||
let mut mismatches = Vec::new();
|
||||
for table in [
|
||||
"workspace_tags",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -68,7 +68,9 @@ pub(super) async fn retire_legacy_worker(api: &WorkspaceApi, subject_id: &str) -
|
||||
let job_api = api.clone();
|
||||
let subject_id = subject_id.to_owned();
|
||||
let key = format!("{SUBJEKTIV_CONSOLIDATION_SINGLETON_PREFIX}{subject_id}");
|
||||
let (worker, complete) = host_io_executor()?
|
||||
let (worker, complete) = api
|
||||
.host_executors
|
||||
.host()?
|
||||
.run(move || {
|
||||
let api = &job_api;
|
||||
let key = format!("{SUBJEKTIV_CONSOLIDATION_SINGLETON_PREFIX}{subject_id}");
|
||||
|
||||
@@ -54,7 +54,7 @@ async fn rejected_runtime_proofs_log_reason_and_verification_without_secrets_on_
|
||||
configure_runtime_request_auth(&mut api, &identity, "runtime-test");
|
||||
let revoked = RuntimeIdentityMaterial::generate("revoked-runtime-secret").unwrap();
|
||||
configure_runtime_request_auth(&mut api, &revoked, "revoked-runtime-secret");
|
||||
SqliteWorkspaceStore::open(&api.config.database_path)
|
||||
SqliteWorkspaceStore::open_for_test(&api.config.database_path)
|
||||
.unwrap()
|
||||
.revoke_workspace_runtime_binding(
|
||||
TEST_WORKSPACE_ID,
|
||||
@@ -70,7 +70,7 @@ async fn rejected_runtime_proofs_log_reason_and_verification_without_secrets_on_
|
||||
let body = "body-secret";
|
||||
let apps = [
|
||||
build_router(api.clone()),
|
||||
workspace_server_router(WorkspaceServerApi::new(
|
||||
workspace_server_router(WorkspaceServerApi::new_for_test(
|
||||
api.config.clone(),
|
||||
api.store.clone(),
|
||||
)),
|
||||
@@ -347,7 +347,7 @@ async fn repository_runtime_proof_401_keeps_generic_envelope_on_both_routers() {
|
||||
let path = format!("/api/w/{TEST_WORKSPACE_ID}/repositories");
|
||||
for app in [
|
||||
build_router(api.clone()),
|
||||
workspace_server_router(WorkspaceServerApi::new(
|
||||
workspace_server_router(WorkspaceServerApi::new_for_test(
|
||||
api.config.clone(),
|
||||
api.store.clone(),
|
||||
)),
|
||||
|
||||
@@ -40,7 +40,7 @@ async fn cached_drive_handle_rejects_mutation_after_deletion_reservation() {
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
let api = WorkspaceApi::new(config.clone(), store.clone())
|
||||
let api = WorkspaceApi::new_for_test(config.clone(), store.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
let cached = api.drive().await.unwrap();
|
||||
@@ -104,7 +104,7 @@ async fn deleting_workspace_reopens_fenced_drive_and_purges_blobs_before_feature
|
||||
// Use a separate embedded-runtime namespace for the first API: this test
|
||||
// reconstructs Drive authority in-process rather than spawning/restarting
|
||||
// product processes (runtime observers may retain their namespace).
|
||||
let first_api = WorkspaceApi::new(config.clone(), store.clone())
|
||||
let first_api = WorkspaceApi::new_for_test(config.clone(), store.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
// Merely constructing a Workspace API must not create blob storage.
|
||||
@@ -160,7 +160,7 @@ async fn deleting_workspace_reopens_fenced_drive_and_purges_blobs_before_feature
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
drop(first_api);
|
||||
let recovered = WorkspaceServerApi::new(config.clone(), store.clone());
|
||||
let recovered = WorkspaceServerApi::new_for_test(config.clone(), store.clone());
|
||||
let api = recovered
|
||||
.api_for_workspace(&config.workspace_id)
|
||||
.await
|
||||
|
||||
@@ -39,10 +39,10 @@ impl RealDriveFixture {
|
||||
let temp = tempfile::tempdir().unwrap();
|
||||
let mut config = test_server_config(temp.path());
|
||||
config.repositories.clear();
|
||||
let store = Arc::new(SqliteWorkspaceStore::open(&config.database_path).unwrap());
|
||||
let store = Arc::new(SqliteWorkspaceStore::open_for_test(&config.database_path).unwrap());
|
||||
let owner = seed_test_api_token(store.as_ref(), "drive-web-owner");
|
||||
let second = seed_test_api_token(store.as_ref(), "drive-web-second");
|
||||
let server_api = WorkspaceServerApi::new(config, store.clone());
|
||||
let server_api = WorkspaceServerApi::new_for_test(config, store.clone());
|
||||
let server = LoopbackServer::start(workspace_server_router(server_api.clone())).await;
|
||||
// Exercise T-717's real repositoryless Workspace bootstrap, not a
|
||||
// pre-existing test Workspace with its repository merely hidden in UI.
|
||||
|
||||
@@ -27,7 +27,7 @@ async fn subject_session_callback_completes_while_create_and_deletion_are_waitin
|
||||
)
|
||||
.unwrap();
|
||||
let worker_id = reserved.worker_id.to_string();
|
||||
let server = WorkspaceServerApi::new(api.config.clone(), api.store.clone());
|
||||
let server = WorkspaceServerApi::new_for_test(api.config.clone(), api.store.clone());
|
||||
// Reuse the fixture API, but exercise the real outer dispatcher and both auth layers.
|
||||
server
|
||||
.apis
|
||||
|
||||
@@ -144,7 +144,7 @@ impl LaunchFixture {
|
||||
async fn new(remote: bool) -> Self {
|
||||
let temp = tempfile::tempdir().unwrap();
|
||||
let config = test_server_config(temp.path());
|
||||
let store = SqliteWorkspaceStore::open(config.database_path.clone()).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(config.database_path.clone()).unwrap();
|
||||
let backend = Arc::new(LaunchExecutionBackend::default());
|
||||
let api =
|
||||
WorkspaceApi::new_with_execution_backend(config, Arc::new(store), backend.clone())
|
||||
|
||||
@@ -151,7 +151,7 @@ impl Fixture {
|
||||
let temp = tempfile::tempdir().unwrap();
|
||||
let mut config = test_server_config(temp.path());
|
||||
config.repositories.clear();
|
||||
let store = Arc::new(SqliteWorkspaceStore::open(&config.database_path).unwrap());
|
||||
let store = Arc::new(SqliteWorkspaceStore::open_for_test(&config.database_path).unwrap());
|
||||
let mut api = WorkspaceApi::new_with_execution_backend(
|
||||
config,
|
||||
store,
|
||||
|
||||
@@ -1329,8 +1329,9 @@ async fn restore_guard_internal_stale_conflict_retires_intent_for_later_explicit
|
||||
);
|
||||
assert_eq!(api.runtime.worker(&identity).unwrap().state, "stopped");
|
||||
// Retirement, unlike in-memory refresh, must survive caller journal restart.
|
||||
api.config_store =
|
||||
Arc::new(SqliteWorkspaceStore::open(api.config.database_path.clone()).unwrap());
|
||||
api.config_store = Arc::new(
|
||||
SqliteWorkspaceStore::open_for_test(api.config.database_path.clone()).unwrap(),
|
||||
);
|
||||
let fresh = api.runtime.worker(&identity).unwrap();
|
||||
let next = api
|
||||
.config_store
|
||||
@@ -1490,7 +1491,7 @@ async fn restore_guard_internal_intent_survives_client_store_restart_without_rep
|
||||
);
|
||||
// Reopen the durable caller journal, discarding all client-side memory of request identity.
|
||||
api.config_store =
|
||||
Arc::new(SqliteWorkspaceStore::open(api.config.database_path.clone()).unwrap());
|
||||
Arc::new(SqliteWorkspaceStore::open_for_test(api.config.database_path.clone()).unwrap());
|
||||
let pinned = api
|
||||
.config_store
|
||||
.pin_internal_worker_restore_intent(
|
||||
@@ -1599,7 +1600,7 @@ async fn restore_guard_cross_runtime_ssh_completion_retries_pinned_snapshot_at_w
|
||||
crate::repository_source::repository_source_fingerprint(&source);
|
||||
config.repositories[0].source = source;
|
||||
config.repositories[0].path = None;
|
||||
let store = SqliteWorkspaceStore::open(config.database_path.clone()).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(config.database_path.clone()).unwrap();
|
||||
let execution = Arc::new(DeterministicExecutionBackend::default());
|
||||
execution.accept_restores();
|
||||
let api = WorkspaceApi::new_with_execution_backend(config, Arc::new(store), execution.clone())
|
||||
|
||||
@@ -56,7 +56,7 @@ impl Fixture {
|
||||
api.runtime.register_or_replace(runtime);
|
||||
let now = Arc::new(AtomicI64::new(START));
|
||||
let clock = now.clone();
|
||||
let mut server = WorkspaceServerApi::new(api.config.clone(), api.store.clone());
|
||||
let mut server = WorkspaceServerApi::new_for_test(api.config.clone(), api.store.clone());
|
||||
server.proof_clock = Arc::new(move || clock.load(Ordering::SeqCst));
|
||||
server
|
||||
.apis
|
||||
|
||||
@@ -356,7 +356,9 @@ impl WorkspaceWorker {
|
||||
) -> ApiResult<InternalWorkerRestoreResult> {
|
||||
let guard = self.authorize_operation(context, "restore").await?;
|
||||
let worker = self.clone();
|
||||
host_io_executor()?
|
||||
self.api
|
||||
.host_executors
|
||||
.host()?
|
||||
.run(move || {
|
||||
let _guard = guard;
|
||||
worker.restore_internal(request)
|
||||
@@ -381,7 +383,10 @@ impl WorkspaceWorker {
|
||||
) -> ApiResult<WorkerLifecycleResult> {
|
||||
let guard = self.authorize_operation(context, "stop").await?;
|
||||
let worker = self.clone();
|
||||
let (result, guard) = host_io_executor()?
|
||||
let (result, guard) = self
|
||||
.api
|
||||
.host_executors
|
||||
.host()?
|
||||
.run(move || -> ApiResult<_> {
|
||||
let result = worker
|
||||
.api
|
||||
@@ -399,7 +404,9 @@ impl WorkspaceWorker {
|
||||
let session_guard = session_lock.lock_owned().await;
|
||||
close_current_worker_session_locked(&self.api, &self.identity).await?;
|
||||
let worker = self.clone();
|
||||
host_io_executor()?
|
||||
self.api
|
||||
.host_executors
|
||||
.host()?
|
||||
.run(move || -> ApiResult<_> {
|
||||
let (_control, _session) = (guard, session_guard);
|
||||
if let Some(record) = worker
|
||||
@@ -425,7 +432,9 @@ impl WorkspaceWorker {
|
||||
) -> ApiResult<WorkerLifecycleResult> {
|
||||
let guard = self.authorize_operation(context, "cancel").await?;
|
||||
let worker = self.clone();
|
||||
host_io_executor()?
|
||||
self.api
|
||||
.host_executors
|
||||
.host()?
|
||||
.run(move || -> ApiResult<_> {
|
||||
let _guard = guard;
|
||||
Ok(worker
|
||||
@@ -457,7 +466,9 @@ impl WorkspaceWorker {
|
||||
request.kind = WorkerInputKind::UserIfIdle;
|
||||
}
|
||||
let worker = self.clone();
|
||||
host_io_executor()?
|
||||
self.api
|
||||
.host_executors
|
||||
.host()?
|
||||
.run(move || -> ApiResult<_> {
|
||||
let (_control, _session) = (guard, session_guard);
|
||||
Ok(worker
|
||||
|
||||
@@ -593,7 +593,7 @@ async fn real_attention_worker_start_restore(lose_response: bool) {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
init_clean_git_workspace(dir.path());
|
||||
let config = test_server_config(dir.path());
|
||||
let store = Arc::new(SqliteWorkspaceStore::open(&config.database_path).unwrap());
|
||||
let store = Arc::new(SqliteWorkspaceStore::open_for_test(&config.database_path).unwrap());
|
||||
seed_test_registered_workspace(store.as_ref(), &config)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
@@ -700,7 +700,7 @@ async fn delivery_real_fixture(
|
||||
DeliveryScriptedClient,
|
||||
) {
|
||||
let config = test_server_config(root);
|
||||
let store = Arc::new(SqliteWorkspaceStore::open(&config.database_path).unwrap());
|
||||
let store = Arc::new(SqliteWorkspaceStore::open_for_test(&config.database_path).unwrap());
|
||||
seed_test_registered_workspace(store.as_ref(), &config)
|
||||
.await
|
||||
.unwrap();
|
||||
@@ -924,7 +924,7 @@ async fn assignment_real_worker_response_loss_restore_and_concurrent_scans_commi
|
||||
tokio::task::yield_now().await;
|
||||
let reopened = WorkspaceApi::new_with_execution_backend(
|
||||
config.clone(),
|
||||
Arc::new(SqliteWorkspaceStore::open(&config.database_path).unwrap()),
|
||||
Arc::new(SqliteWorkspaceStore::open_for_test(&config.database_path).unwrap()),
|
||||
execution.clone(),
|
||||
)
|
||||
.await
|
||||
|
||||
@@ -63,7 +63,7 @@ impl Fixture {
|
||||
backend_base_url: Some("http://localhost:8787".into()),
|
||||
};
|
||||
let store = Arc::new(
|
||||
SqliteWorkspaceStore::open(&config.database_path)
|
||||
SqliteWorkspaceStore::open_for_test(&config.database_path)
|
||||
.unwrap()
|
||||
.with_db_executor(executor.clone()),
|
||||
);
|
||||
@@ -90,10 +90,10 @@ impl Fixture {
|
||||
revoked_at: None,
|
||||
})
|
||||
.unwrap();
|
||||
let api = WorkspaceApi::new(config.clone(), store.clone())
|
||||
let api = WorkspaceApi::new_for_test(config.clone(), store.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
let server = WorkspaceServerApi::new(config, store);
|
||||
let server = WorkspaceServerApi::new_for_test(config, store);
|
||||
// Cache only the real inner router; avoid starting the unrelated hook.
|
||||
server
|
||||
.apis
|
||||
@@ -452,7 +452,9 @@ async fn ticket_create_waiting_for_sqlite_does_not_block_timer_or_control() {
|
||||
assert!(body["id"].is_string(), "{body}");
|
||||
// Ticket dispatch can call Runtime callbacks, so its operation owner is
|
||||
// the separate bounded host executor, not the store executor.
|
||||
observed(host_io_executor().unwrap().drain()).await.unwrap();
|
||||
observed(fixture.api.host_executors.host().unwrap().drain())
|
||||
.await
|
||||
.unwrap();
|
||||
fixture.executor.drain().await.unwrap();
|
||||
let count: i64 = reader.query_row("SELECT count(*) FROM typed_tickets WHERE workspace_id = ?1 AND title = 'locked Ticket'", [WORKSPACE], |row| row.get(0)).unwrap();
|
||||
assert_eq!(count, 1, "one accepted HTTP mutation must commit once");
|
||||
@@ -604,3 +606,86 @@ async fn cancelled_queued_http_mutation_keeps_capacity_until_commit_and_drain()
|
||||
"drain must release actual-job capacity"
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test(start_paused = true)]
|
||||
async fn saturated_cancelled_host_jobs_keep_their_budget_but_not_other_fixture_or_cleanup_admission()
|
||||
{
|
||||
use std::sync::{
|
||||
Condvar,
|
||||
atomic::{AtomicUsize, Ordering},
|
||||
};
|
||||
// A drop guard releases workers even when an assertion panics.
|
||||
struct Release(Arc<(Mutex<bool>, Condvar)>);
|
||||
impl Drop for Release {
|
||||
fn drop(&mut self) {
|
||||
*self.0.0.lock().unwrap() = true;
|
||||
self.0.1.notify_all();
|
||||
}
|
||||
}
|
||||
let owner = HostExecutors::default();
|
||||
let other = HostExecutors::default();
|
||||
let host = owner.host().unwrap();
|
||||
let gate = Arc::new((Mutex::new(false), Condvar::new()));
|
||||
let release = Release(gate.clone());
|
||||
let completed = Arc::new(AtomicUsize::new(0));
|
||||
let mut waiters = Vec::new();
|
||||
for _ in 0..2 {
|
||||
let host = host.clone();
|
||||
let gate = gate.clone();
|
||||
let completed = completed.clone();
|
||||
let (started, accepted) = tokio::sync::oneshot::channel();
|
||||
waiters.push(tokio::spawn(async move {
|
||||
host.run(move || {
|
||||
started.send(()).unwrap();
|
||||
let mut released = gate.0.lock().unwrap();
|
||||
while !*released {
|
||||
released = gate.1.wait(released).unwrap();
|
||||
}
|
||||
completed.fetch_add(1, Ordering::SeqCst);
|
||||
Ok::<_, Error>(())
|
||||
})
|
||||
.await
|
||||
}));
|
||||
accepted.await.unwrap();
|
||||
}
|
||||
for _ in 0..16 {
|
||||
let completed = completed.clone();
|
||||
host.dispatch(move || {
|
||||
completed.fetch_add(1, Ordering::SeqCst);
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
for waiter in waiters {
|
||||
waiter.abort();
|
||||
assert!(waiter.await.unwrap_err().is_cancelled());
|
||||
}
|
||||
assert!(matches!(
|
||||
host.run(|| Ok::<_, Error>(())).await,
|
||||
Err(Error::DbCapacityExceeded)
|
||||
));
|
||||
// Paused Tokio time can advance without completing or releasing actual Host
|
||||
// work. Neither another fixture nor cleanup needs this saturated Host lane.
|
||||
tokio::time::advance(std::time::Duration::from_secs(31)).await;
|
||||
assert_eq!(completed.load(Ordering::SeqCst), 0);
|
||||
other
|
||||
.host()
|
||||
.unwrap()
|
||||
.run(|| Ok::<_, Error>(()))
|
||||
.await
|
||||
.unwrap();
|
||||
owner
|
||||
.cleanup()
|
||||
.unwrap()
|
||||
.run(|| Ok::<_, Error>(()))
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(matches!(
|
||||
host.run(|| Ok::<_, Error>(())).await,
|
||||
Err(Error::DbCapacityExceeded)
|
||||
));
|
||||
drop(release);
|
||||
host.drain().await.unwrap();
|
||||
assert_eq!(completed.load(Ordering::SeqCst), 18);
|
||||
host.run(|| Ok::<_, Error>(())).await.unwrap();
|
||||
host.drain().await.unwrap();
|
||||
}
|
||||
|
||||
@@ -724,7 +724,7 @@ async fn catalog_case_dispatch_authenticates_and_routes_the_canonical_workspace_
|
||||
reason: ticket::TicketClosureReason::Completed,
|
||||
},
|
||||
);
|
||||
let catalog = WorkspaceServerApi::new(api.config.clone(), api.store.clone());
|
||||
let catalog = WorkspaceServerApi::new_for_test(api.config.clone(), api.store.clone());
|
||||
// Retain only this in-process fixture: do not create a real Runtime or a
|
||||
// background Orchestrator hook while testing catalog authentication/routing.
|
||||
catalog
|
||||
|
||||
@@ -529,7 +529,7 @@ async fn runtime_tag_mutations_reject_invalid_proofs_and_changed_binding_authori
|
||||
*tampered.body_mut() = Body::from(format!("{} ", input));
|
||||
runtime_tag_response(app.clone(), tampered, StatusCode::UNAUTHORIZED).await;
|
||||
}
|
||||
let store = SqliteWorkspaceStore::open(&api.config.database_path).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&api.config.database_path).unwrap();
|
||||
let original = api
|
||||
.store
|
||||
.get_workspace_runtime_binding(TEST_WORKSPACE_ID, "runtime-tags")
|
||||
|
||||
@@ -634,7 +634,7 @@ pub(super) async fn commit(
|
||||
// a DB worker or an open SQL transaction.
|
||||
let (complete, publication) = tokio::sync::oneshot::channel();
|
||||
let runtime = persistence_api.runtime.clone();
|
||||
let admission = host_io_executor().and_then(|executor| {
|
||||
let admission = persistence_api.host_executors.host().and_then(|executor| {
|
||||
executor.dispatch(move || {
|
||||
let _guard = guard;
|
||||
let _diagnostics = runtime
|
||||
@@ -681,7 +681,9 @@ pub(super) async fn create_grant(
|
||||
let guard = lock(api, &worker).await?;
|
||||
let runtime = api.runtime.clone();
|
||||
let lookup_worker = worker.clone();
|
||||
let (summary, guard) = host_io_executor()
|
||||
let (summary, guard) = api
|
||||
.host_executors
|
||||
.host()
|
||||
.map_err(pre_error)?
|
||||
.run(move || {
|
||||
Ok::<_, Error>((|| {
|
||||
|
||||
@@ -318,7 +318,7 @@ mod workspace_config_integration {
|
||||
};
|
||||
for scoped in [false, true] {
|
||||
let app = if scoped {
|
||||
workspace_server_router(WorkspaceServerApi::new(
|
||||
workspace_server_router(WorkspaceServerApi::new_for_test(
|
||||
api.config.clone(),
|
||||
api.store.clone(),
|
||||
))
|
||||
@@ -1385,7 +1385,7 @@ mod workspace_config_integration {
|
||||
let api = &fixture.api;
|
||||
let granted = grant(api, &fixture.worker, Access::ReadWrite).await;
|
||||
let attached = attach(api, &fixture.worker).await;
|
||||
let restarted = SqliteWorkspaceStore::open(&api.config.database_path).unwrap();
|
||||
let restarted = SqliteWorkspaceStore::open_for_test(&api.config.database_path).unwrap();
|
||||
assert_eq!(
|
||||
restarted
|
||||
.get_workspace_config_grant(TEST_WORKSPACE_ID, &granted.grant_id)
|
||||
|
||||
@@ -800,7 +800,7 @@ async fn workspace_config_actual_remote_and_embedded_clients_use_authenticated_w
|
||||
let base = format!("http://{addr}");
|
||||
let mut config = test_server_config(root.path());
|
||||
config.backend_base_url = Some("server-test".into());
|
||||
let store = Arc::new(SqliteWorkspaceStore::open(&config.database_path).unwrap());
|
||||
let store = Arc::new(SqliteWorkspaceStore::open_for_test(&config.database_path).unwrap());
|
||||
let captured = Arc::new(Mutex::new(None));
|
||||
let abort = Arc::new(Mutex::new(None));
|
||||
let factory = ConfigCaptureFactory {
|
||||
|
||||
@@ -2278,13 +2278,40 @@ impl SqliteWorkspaceStore {
|
||||
}
|
||||
|
||||
pub fn from_connection(conn: Connection) -> Result<Self> {
|
||||
Self::from_connection_with_executor(conn, crate::db_executor::DbExecutor::shared())
|
||||
}
|
||||
|
||||
fn from_connection_with_executor(
|
||||
conn: Connection,
|
||||
db_executor: crate::db_executor::DbExecutor,
|
||||
) -> Result<Self> {
|
||||
prepare_connection(&conn)?;
|
||||
Ok(Self {
|
||||
conn: Arc::new(Mutex::new(conn)),
|
||||
db_executor: crate::db_executor::DbExecutor::shared(),
|
||||
db_executor,
|
||||
})
|
||||
}
|
||||
|
||||
// Ordinary fixtures own the same finite budget as production, not another
|
||||
// fixture's admission/SQL/drain lifetime or a permanent global worker.
|
||||
#[cfg(test)]
|
||||
pub(crate) fn open_for_test(path: impl AsRef<Path>) -> Result<Self> {
|
||||
Self::from_connection_for_test(Connection::open(path)?)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) fn in_memory_for_test() -> Result<Self> {
|
||||
Self::from_connection_for_test(Connection::open_in_memory()?)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) fn from_connection_for_test(conn: Connection) -> Result<Self> {
|
||||
Self::from_connection_with_executor(
|
||||
conn,
|
||||
crate::db_executor::DbExecutor::new(crate::db_executor::DbExecutorLimits::default())?,
|
||||
)
|
||||
}
|
||||
|
||||
/// Override execution limits for a hermetic fixture; subsequent clones share it.
|
||||
pub fn with_db_executor(mut self, executor: crate::db_executor::DbExecutor) -> Self {
|
||||
self.db_executor = executor;
|
||||
@@ -14861,7 +14888,7 @@ mod tests {
|
||||
fn drive_grants_migrate_and_preserve_audit_through_revoke_worker_delete_and_restart() {
|
||||
let t = tempfile::tempdir().unwrap();
|
||||
let path = t.path().join("server.db");
|
||||
let store = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
let legacy = Connection::open_in_memory().unwrap();
|
||||
configure_sqlite(&legacy).unwrap();
|
||||
legacy.execute_batch("CREATE TABLE workspaces(workspace_id TEXT PRIMARY KEY);
|
||||
@@ -14951,7 +14978,7 @@ mod tests {
|
||||
Some(other)
|
||||
);
|
||||
drop(store);
|
||||
let store = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
assert_eq!(
|
||||
store
|
||||
.get_workspace_drive_grant("drive-ws", &first.grant_id)
|
||||
@@ -14986,7 +15013,7 @@ mod tests {
|
||||
}
|
||||
#[test]
|
||||
fn drive_grants_baseline_constraints_and_worker_lifetime_fail_closed() {
|
||||
let store = SqliteWorkspaceStore::in_memory().unwrap();
|
||||
let store = SqliteWorkspaceStore::in_memory_for_test().unwrap();
|
||||
let proposed = drive_grant_fixture(&store);
|
||||
let first = store.create_workspace_drive_grant(&proposed).unwrap();
|
||||
store.with_conn(|c| {
|
||||
@@ -15022,7 +15049,7 @@ mod tests {
|
||||
fn schema_v74_migrates_historical_worker_projection_rows_without_counter_state() {
|
||||
let temp = tempfile::tempdir().unwrap();
|
||||
let path = temp.path().join("workspace.db");
|
||||
drop(SqliteWorkspaceStore::open(&path).unwrap());
|
||||
drop(SqliteWorkspaceStore::open_for_test(&path).unwrap());
|
||||
let conn = Connection::open(&path).unwrap();
|
||||
configure_sqlite(&conn).unwrap();
|
||||
conn.execute_batch(
|
||||
@@ -15347,7 +15374,7 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn external_workdir_grant_persists_typed_source_and_fences_generations() {
|
||||
let store = SqliteWorkspaceStore::in_memory().unwrap();
|
||||
let store = SqliteWorkspaceStore::in_memory_for_test().unwrap();
|
||||
store
|
||||
.upsert_account(&AccountRecord {
|
||||
account_id: "owner".to_string(),
|
||||
@@ -15719,7 +15746,7 @@ mod tests {
|
||||
|
||||
fn runtime_removal_test_store() -> (tempfile::TempDir, SqliteWorkspaceStore) {
|
||||
let temp = tempfile::tempdir().unwrap();
|
||||
let store = SqliteWorkspaceStore::open(temp.path().join("server.db")).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(temp.path().join("server.db")).unwrap();
|
||||
store
|
||||
.with_conn(|conn| {
|
||||
conn.execute_batch(
|
||||
@@ -16103,7 +16130,7 @@ mod tests {
|
||||
let path = temp.path().join("server.db");
|
||||
prepare_retained_schema(&path, 59);
|
||||
|
||||
let migrated = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let migrated = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
migrated
|
||||
.with_conn(|conn| {
|
||||
let table_count: i64 = conn.query_row(
|
||||
@@ -16139,7 +16166,7 @@ mod tests {
|
||||
let path = temp.path().join("server.db");
|
||||
prepare_retained_schema(&path, 60);
|
||||
|
||||
drop(SqliteWorkspaceStore::open(&path).unwrap());
|
||||
drop(SqliteWorkspaceStore::open_for_test(&path).unwrap());
|
||||
let conn = Connection::open(&path).unwrap();
|
||||
assert_eq!(
|
||||
current_schema_version(&conn).unwrap(),
|
||||
@@ -16169,7 +16196,7 @@ mod tests {
|
||||
#[test]
|
||||
fn schema_v59_runtime_removal_migration_rolls_back_partial_ddl_and_marker() {
|
||||
let temp = tempfile::tempdir().unwrap();
|
||||
let store = SqliteWorkspaceStore::open(temp.path().join("server.db")).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(temp.path().join("server.db")).unwrap();
|
||||
store
|
||||
.with_conn(|conn| {
|
||||
let trigger_names = {
|
||||
@@ -16433,7 +16460,7 @@ mod tests {
|
||||
fn fresh_database_uses_only_the_canonical_workspace_baseline() {
|
||||
let temp = tempfile::tempdir().unwrap();
|
||||
let path = temp.path().join("server.db");
|
||||
let store = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
store
|
||||
.with_conn(|conn| {
|
||||
let migrations = conn
|
||||
@@ -16581,7 +16608,7 @@ CREATE UNIQUE INDEX ticket_current_worker_role_idx
|
||||
.collect::<Vec<_>>(),
|
||||
(83..=LATEST_SCHEMA_VERSION).collect::<Vec<_>>()
|
||||
);
|
||||
let store = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
let assignment = store
|
||||
.get_active_ticket_worker_assignment("workspace-a", "ticket")
|
||||
.unwrap()
|
||||
@@ -17052,7 +17079,7 @@ CREATE UNIQUE INDEX ticket_current_worker_role_idx
|
||||
|
||||
let applied = SqliteWorkspaceStore::migrate_database(&path).unwrap();
|
||||
assert_eq!(applied, plan);
|
||||
let store = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
store
|
||||
.with_conn(|conn| {
|
||||
assert_eq!(current_schema_version(conn)?, LATEST_SCHEMA_VERSION);
|
||||
@@ -17601,7 +17628,7 @@ CREATE UNIQUE INDEX ticket_current_worker_role_idx
|
||||
"migrated databases must reject incomplete singleton leases"
|
||||
);
|
||||
drop(conn);
|
||||
let store = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
let legacy = RuntimeWorkerRef::new("legacy-runtime", "legacy-orchestrator");
|
||||
let lease = store
|
||||
.require_current_worker_singleton_owner("workspace-a", &legacy)
|
||||
@@ -17789,7 +17816,7 @@ CREATE UNIQUE INDEX ticket_current_worker_role_idx
|
||||
.unwrap();
|
||||
drop(conn);
|
||||
|
||||
let store = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
store
|
||||
.with_conn(|conn| {
|
||||
assert_eq!(current_schema_version(conn)?, LATEST_SCHEMA_VERSION);
|
||||
@@ -17890,7 +17917,7 @@ CREATE UNIQUE INDEX ticket_current_worker_role_idx
|
||||
.unwrap();
|
||||
drop(conn);
|
||||
|
||||
let error = SqliteWorkspaceStore::open(&path)
|
||||
let error = SqliteWorkspaceStore::open_for_test(&path)
|
||||
.err()
|
||||
.expect("migration must fail")
|
||||
.to_string();
|
||||
@@ -17915,7 +17942,7 @@ CREATE UNIQUE INDEX ticket_current_worker_role_idx
|
||||
fn runtime_binding_identity_and_trust_uniqueness_are_workspace_scoped() {
|
||||
let temp = tempfile::tempdir().unwrap();
|
||||
let path = temp.path().join("server.db");
|
||||
let store = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
store
|
||||
.with_conn(|conn| {
|
||||
conn.execute_batch(
|
||||
@@ -18017,7 +18044,7 @@ CREATE UNIQUE INDEX ticket_current_worker_role_idx
|
||||
);
|
||||
drop(store);
|
||||
|
||||
let reopened = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let reopened = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
assert!(
|
||||
reopened
|
||||
.list_workspace_runtime_bindings("workspace-a", false)
|
||||
@@ -18067,7 +18094,7 @@ CREATE UNIQUE INDEX ticket_current_worker_role_idx
|
||||
fn workspace_runtime_connection_persists_without_authentication_evidence() {
|
||||
let temp = tempfile::tempdir().unwrap();
|
||||
let path = temp.path().join("server.db");
|
||||
let store = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
store
|
||||
.with_conn(|conn| {
|
||||
conn.execute_batch(
|
||||
@@ -18112,7 +18139,7 @@ CREATE UNIQUE INDEX ticket_current_worker_role_idx
|
||||
.unwrap();
|
||||
assert!(store.workspace_runtime_binding_matches(&persisted).unwrap());
|
||||
drop(store);
|
||||
let reopened = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let reopened = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
assert_eq!(
|
||||
reopened
|
||||
.get_workspace_runtime_binding("workspace-a", "runtime-a")
|
||||
@@ -18366,7 +18393,7 @@ CREATE UNIQUE INDEX ticket_current_worker_role_idx
|
||||
|
||||
#[test]
|
||||
fn runtime_binding_key_mutations_are_identity_guarded_idempotent_and_audited() {
|
||||
let store = SqliteWorkspaceStore::in_memory().unwrap();
|
||||
let store = SqliteWorkspaceStore::in_memory_for_test().unwrap();
|
||||
store
|
||||
.with_conn(|conn| {
|
||||
conn.execute_batch(
|
||||
@@ -18504,7 +18531,7 @@ CREATE UNIQUE INDEX ticket_current_worker_role_idx
|
||||
|
||||
#[test]
|
||||
fn embedded_runtime_binding_can_explicitly_rotate_restart_identity() {
|
||||
let store = SqliteWorkspaceStore::in_memory().unwrap();
|
||||
let store = SqliteWorkspaceStore::in_memory_for_test().unwrap();
|
||||
store
|
||||
.with_conn(|conn| {
|
||||
conn.execute_batch(
|
||||
@@ -18604,7 +18631,7 @@ CREATE UNIQUE INDEX ticket_current_worker_role_idx
|
||||
conn.execute_batch("DROP TABLE typed_ticket_artifacts")
|
||||
.unwrap();
|
||||
|
||||
let result = SqliteWorkspaceStore::from_connection(conn);
|
||||
let result = SqliteWorkspaceStore::from_connection_for_test(conn);
|
||||
let error = match result {
|
||||
Ok(_) => panic!("schema drift unexpectedly passed startup verification"),
|
||||
Err(error) => error,
|
||||
@@ -18616,7 +18643,7 @@ CREATE UNIQUE INDEX ticket_current_worker_role_idx
|
||||
async fn workspace_schema_rejects_cross_workspace_ticket_repository_reference_at_write_time() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let database_path = dir.path().join("workspace.sqlite");
|
||||
let store = SqliteWorkspaceStore::open(&database_path).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&database_path).unwrap();
|
||||
for workspace_id in ["workspace-a", "workspace-b"] {
|
||||
store
|
||||
.upsert_workspace(&WorkspaceRecord {
|
||||
@@ -18670,14 +18697,14 @@ CREATE UNIQUE INDEX ticket_current_worker_role_idx
|
||||
);
|
||||
drop(backend);
|
||||
|
||||
SqliteWorkspaceStore::open(&database_path).unwrap();
|
||||
SqliteWorkspaceStore::open_for_test(&database_path).unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn migrates_sqlite_and_preserves_workspace_record() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let db = dir.path().join("control-plane.sqlite");
|
||||
let store = SqliteWorkspaceStore::open(&db).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&db).unwrap();
|
||||
|
||||
assert_eq!(store.schema_version().await.unwrap(), LATEST_SCHEMA_VERSION);
|
||||
assert!(
|
||||
@@ -18695,7 +18722,7 @@ CREATE UNIQUE INDEX ticket_current_worker_role_idx
|
||||
};
|
||||
store.upsert_workspace(&record).await.unwrap();
|
||||
|
||||
let reopened = SqliteWorkspaceStore::open(&db).unwrap();
|
||||
let reopened = SqliteWorkspaceStore::open_for_test(&db).unwrap();
|
||||
assert_eq!(
|
||||
reopened.schema_version().await.unwrap(),
|
||||
LATEST_SCHEMA_VERSION
|
||||
@@ -18710,7 +18737,7 @@ CREATE UNIQUE INDEX ticket_current_worker_role_idx
|
||||
async fn workspace_display_name_update_is_timestamp_guarded_and_preserves_identity() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let database_path = dir.path().join("server.db");
|
||||
let store = SqliteWorkspaceStore::open(&database_path).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&database_path).unwrap();
|
||||
let record = WorkspaceRecord {
|
||||
workspace_id: "workspace-a".to_string(),
|
||||
owner_account_id: "owner-account".to_string(),
|
||||
@@ -18749,7 +18776,7 @@ CREATE UNIQUE INDEX ticket_current_worker_role_idx
|
||||
updated
|
||||
);
|
||||
drop(store);
|
||||
let reopened = SqliteWorkspaceStore::open(database_path).unwrap();
|
||||
let reopened = SqliteWorkspaceStore::open_for_test(database_path).unwrap();
|
||||
assert_eq!(
|
||||
reopened
|
||||
.get_workspace(&record.workspace_id)
|
||||
@@ -18763,7 +18790,7 @@ CREATE UNIQUE INDEX ticket_current_worker_role_idx
|
||||
#[tokio::test]
|
||||
async fn objective_creation_allocates_and_resolves_workspace_resource_key() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let store = SqliteWorkspaceStore::open(dir.path().join("server.db")).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(dir.path().join("server.db")).unwrap();
|
||||
store
|
||||
.upsert_workspace(&WorkspaceRecord {
|
||||
workspace_id: "workspace-a".into(),
|
||||
@@ -18809,7 +18836,7 @@ CREATE UNIQUE INDEX ticket_current_worker_role_idx
|
||||
#[tokio::test]
|
||||
async fn worker_create_reservation_allocates_uuid_before_runtime_and_replays_exact_input() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let store = SqliteWorkspaceStore::open(dir.path().join("server.db")).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(dir.path().join("server.db")).unwrap();
|
||||
store
|
||||
.upsert_workspace(&WorkspaceRecord {
|
||||
workspace_id: "workspace-a".to_string(),
|
||||
@@ -19113,7 +19140,7 @@ CREATE UNIQUE INDEX ticket_current_worker_role_idx
|
||||
async fn worker_singleton_restart_retry_replays_exact_workdir_intent_and_rejects_changes() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let database = dir.path().join("server.db");
|
||||
let store = SqliteWorkspaceStore::open(&database).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&database).unwrap();
|
||||
store
|
||||
.upsert_workspace(&WorkspaceRecord {
|
||||
workspace_id: "workspace-a".to_string(),
|
||||
@@ -19173,7 +19200,7 @@ CREATE UNIQUE INDEX ticket_current_worker_role_idx
|
||||
.unwrap();
|
||||
drop(store);
|
||||
|
||||
let reopened = SqliteWorkspaceStore::open(&database).unwrap();
|
||||
let reopened = SqliteWorkspaceStore::open_for_test(&database).unwrap();
|
||||
let retried = reopened
|
||||
.reserve_worker_create(
|
||||
"workspace-a",
|
||||
@@ -19217,7 +19244,7 @@ CREATE UNIQUE INDEX ticket_current_worker_role_idx
|
||||
async fn worker_singleton_ownership_is_workspace_scoped_durable_and_fences_old_generations() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let database = dir.path().join("server.db");
|
||||
let store = SqliteWorkspaceStore::open(&database).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&database).unwrap();
|
||||
for workspace_id in ["workspace-a", "workspace-b"] {
|
||||
store
|
||||
.upsert_workspace(&WorkspaceRecord {
|
||||
@@ -19330,7 +19357,7 @@ CREATE UNIQUE INDEX ticket_current_worker_role_idx
|
||||
);
|
||||
drop(store);
|
||||
|
||||
let reopened = SqliteWorkspaceStore::open(database).unwrap();
|
||||
let reopened = SqliteWorkspaceStore::open_for_test(database).unwrap();
|
||||
assert_eq!(
|
||||
reopened
|
||||
.current_worker_singleton_owner("workspace-a", key)
|
||||
@@ -19343,7 +19370,7 @@ CREATE UNIQUE INDEX ticket_current_worker_role_idx
|
||||
async fn concurrent_worker_singleton_reservations_have_one_winner() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let database = dir.path().join("server.db");
|
||||
let store = SqliteWorkspaceStore::open(&database).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&database).unwrap();
|
||||
store
|
||||
.upsert_workspace(&WorkspaceRecord {
|
||||
workspace_id: "workspace-a".to_string(),
|
||||
@@ -19363,7 +19390,7 @@ CREATE UNIQUE INDEX ticket_current_worker_role_idx
|
||||
let database = database.clone();
|
||||
let barrier = barrier.clone();
|
||||
std::thread::spawn(move || {
|
||||
let store = SqliteWorkspaceStore::open(database).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(database).unwrap();
|
||||
let memory = store.get_workspace_memory_settings("workspace-a").unwrap();
|
||||
barrier.wait();
|
||||
store.reserve_worker_create(
|
||||
@@ -19383,7 +19410,7 @@ CREATE UNIQUE INDEX ticket_current_worker_role_idx
|
||||
.collect::<Vec<_>>();
|
||||
assert_eq!(results.iter().filter(|result| result.is_ok()).count(), 1);
|
||||
assert_eq!(results.iter().filter(|result| result.is_err()).count(), 1);
|
||||
let store = SqliteWorkspaceStore::open(database).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(database).unwrap();
|
||||
let owner = store
|
||||
.current_worker_singleton_owner("workspace-a", "shared-key")
|
||||
.unwrap()
|
||||
@@ -19399,7 +19426,7 @@ CREATE UNIQUE INDEX ticket_current_worker_role_idx
|
||||
#[tokio::test]
|
||||
async fn workspace_flow_sources_pin_content_and_builtins_stay_resources() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let store = SqliteWorkspaceStore::open(dir.path().join("server.db")).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(dir.path().join("server.db")).unwrap();
|
||||
store
|
||||
.upsert_workspace(&WorkspaceRecord {
|
||||
workspace_id: "workspace-a".to_string(),
|
||||
@@ -19492,7 +19519,7 @@ CREATE UNIQUE INDEX ticket_current_worker_role_idx
|
||||
"returning to earlier content must reuse the immutable content"
|
||||
);
|
||||
drop(store);
|
||||
let reopened = SqliteWorkspaceStore::open(dir.path().join("server.db")).unwrap();
|
||||
let reopened = SqliteWorkspaceStore::open_for_test(dir.path().join("server.db")).unwrap();
|
||||
assert_eq!(
|
||||
reopened
|
||||
.get_flow_source_content(
|
||||
@@ -19748,7 +19775,7 @@ CREATE UNIQUE INDEX ticket_current_worker_role_idx
|
||||
}
|
||||
);
|
||||
drop(conn);
|
||||
let store = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
let backend = ticket::SqliteTicketBackend::open_verified(&path, "case-workspace").unwrap();
|
||||
store
|
||||
.with_conn(|conn| {
|
||||
@@ -19915,7 +19942,7 @@ CREATE UNIQUE INDEX ticket_current_worker_role_idx
|
||||
);
|
||||
drop(store);
|
||||
drop(backend);
|
||||
let reopened = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let reopened = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
reopened
|
||||
.with_conn(|conn| {
|
||||
assert_eq!(current_schema_version(conn)?, LATEST_SCHEMA_VERSION);
|
||||
@@ -19982,7 +20009,7 @@ CREATE UNIQUE INDEX ticket_current_worker_role_idx
|
||||
before
|
||||
);
|
||||
drop(conn);
|
||||
let store = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
let backend = ticket::SqliteTicketBackend::open_verified(&path, "case-workspace").unwrap();
|
||||
assert_eq!(
|
||||
backend
|
||||
@@ -20116,8 +20143,8 @@ CREATE UNIQUE INDEX ticket_current_worker_role_idx
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let path = dir.path().join("equivalence.db");
|
||||
prepare_retained_schema(&path, 90);
|
||||
let upgraded = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let fresh = SqliteWorkspaceStore::in_memory().unwrap();
|
||||
let upgraded = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
let fresh = SqliteWorkspaceStore::in_memory_for_test().unwrap();
|
||||
for object in [
|
||||
"workspace_tags",
|
||||
"typed_ticket_tags",
|
||||
@@ -20170,7 +20197,7 @@ CREATE UNIQUE INDEX ticket_current_worker_role_idx
|
||||
|
||||
#[test]
|
||||
fn schema_v91_case_constraint_verification_rejects_legacy_view_predicates() {
|
||||
let store = SqliteWorkspaceStore::in_memory().unwrap();
|
||||
let store = SqliteWorkspaceStore::in_memory_for_test().unwrap();
|
||||
store.with_conn(|conn| {
|
||||
conn.execute_batch("DROP VIEW ticket_active_worker_assignments;
|
||||
CREATE VIEW ticket_active_worker_assignments AS
|
||||
@@ -20331,7 +20358,7 @@ CREATE UNIQUE INDEX ticket_current_worker_role_idx
|
||||
// boundary under test. Targets need not be materialized by a Runtime.
|
||||
async fn manual_worker_start_store() -> (tempfile::TempDir, SqliteWorkspaceStore) {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let store = SqliteWorkspaceStore::open(dir.path().join("workspace.db")).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(dir.path().join("workspace.db")).unwrap();
|
||||
store
|
||||
.upsert_workspace(&WorkspaceRecord {
|
||||
workspace_id: "w".into(),
|
||||
@@ -20419,7 +20446,8 @@ CREATE UNIQUE INDEX ticket_current_worker_role_idx
|
||||
let threads = (0..2)
|
||||
.map(|index| {
|
||||
let store =
|
||||
SqliteWorkspaceStore::open(dir.path().join("workspace.db")).unwrap();
|
||||
SqliteWorkspaceStore::open_for_test(dir.path().join("workspace.db"))
|
||||
.unwrap();
|
||||
let barrier = barrier.clone();
|
||||
std::thread::spawn(move || {
|
||||
barrier.wait();
|
||||
@@ -20784,7 +20812,8 @@ CREATE UNIQUE INDEX ticket_current_worker_role_idx
|
||||
.retain_ticket_claim_recovery("w", "claim", &fingerprint, &changed)
|
||||
.is_err()
|
||||
);
|
||||
let reopened = SqliteWorkspaceStore::open(dir.path().join("workspace.db")).unwrap();
|
||||
let reopened =
|
||||
SqliteWorkspaceStore::open_for_test(dir.path().join("workspace.db")).unwrap();
|
||||
assert_eq!(
|
||||
reopened.get_ticket_claim_recovery("w", "claim").unwrap(),
|
||||
Some(recovery)
|
||||
@@ -20842,7 +20871,8 @@ CREATE UNIQUE INDEX ticket_current_worker_role_idx
|
||||
store
|
||||
.rollback_ticket_assignment_operation("w", "claim")
|
||||
.unwrap();
|
||||
let reopened = SqliteWorkspaceStore::open(dir.path().join("workspace.db")).unwrap();
|
||||
let reopened =
|
||||
SqliteWorkspaceStore::open_for_test(dir.path().join("workspace.db")).unwrap();
|
||||
let receipt = reopened
|
||||
.get_ticket_assignment_operation("w", "claim")
|
||||
.unwrap()
|
||||
@@ -21062,7 +21092,7 @@ CREATE UNIQUE INDEX ticket_current_worker_role_idx
|
||||
use ticket::TicketBackend;
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let path = dir.path().join("workspace.db");
|
||||
let store = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
store
|
||||
.upsert_workspace(&WorkspaceRecord {
|
||||
workspace_id: "w".into(),
|
||||
@@ -21190,7 +21220,7 @@ CREATE UNIQUE INDEX ticket_current_worker_role_idx
|
||||
async fn ticket_worker_assignment_replaces_current_and_preserves_audit_history() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let db = dir.path().join("server.db");
|
||||
let store = SqliteWorkspaceStore::open(&db).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&db).unwrap();
|
||||
store
|
||||
.upsert_workspace(&WorkspaceRecord {
|
||||
workspace_id: "workspace-a".to_string(),
|
||||
@@ -21379,7 +21409,7 @@ INSERT INTO worker_registry (
|
||||
)
|
||||
.unwrap();
|
||||
drop(store);
|
||||
let store = SqliteWorkspaceStore::open(&db).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&db).unwrap();
|
||||
let pending = store
|
||||
.get_ticket_assignment_operation("workspace-a", "reserved-operation")
|
||||
.unwrap()
|
||||
@@ -21503,7 +21533,7 @@ INSERT INTO worker_registry (
|
||||
async fn role_assignment_routes_and_manual_start_are_state_fenced_atomically() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let db_path = dir.path().join("workspace.db");
|
||||
let store = SqliteWorkspaceStore::open(&db_path).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&db_path).unwrap();
|
||||
store
|
||||
.upsert_workspace(&WorkspaceRecord {
|
||||
workspace_id: "workspace-role".to_string(),
|
||||
@@ -21792,7 +21822,7 @@ INSERT INTO worker_registry (
|
||||
fn startup_rejects_missing_workspace_resource_constraint_trigger() {
|
||||
let temp = tempfile::tempdir().unwrap();
|
||||
let path = temp.path().join("server.db");
|
||||
let store = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
store
|
||||
.with_conn(|conn| {
|
||||
conn.execute_batch("DROP TRIGGER ticket_worker_assignments_validate_insert")?;
|
||||
@@ -21801,7 +21831,7 @@ INSERT INTO worker_registry (
|
||||
.unwrap();
|
||||
drop(store);
|
||||
|
||||
let error = match SqliteWorkspaceStore::open(&path) {
|
||||
let error = match SqliteWorkspaceStore::open_for_test(&path) {
|
||||
Ok(_) => panic!("missing assignment constraint trigger must fail closed"),
|
||||
Err(error) => error,
|
||||
};
|
||||
@@ -21817,7 +21847,7 @@ INSERT INTO worker_registry (
|
||||
fn startup_accepts_retained_assignment_history_after_parent_cleanup() {
|
||||
let temp = tempfile::tempdir().unwrap();
|
||||
let path = temp.path().join("server.db");
|
||||
let store = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
store
|
||||
.with_conn(|conn| {
|
||||
conn.execute_batch(
|
||||
@@ -21881,7 +21911,7 @@ INSERT INTO worker_registry (
|
||||
.unwrap();
|
||||
drop(store);
|
||||
|
||||
let reopened = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let reopened = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
reopened
|
||||
.with_conn(|conn| {
|
||||
let retained: i64 = conn.query_row(
|
||||
@@ -21909,7 +21939,7 @@ INSERT INTO worker_registry (
|
||||
|
||||
#[tokio::test]
|
||||
async fn workspace_bootstrap_validates_key_and_rejects_duplicate_workspace() {
|
||||
let store = SqliteWorkspaceStore::in_memory().unwrap();
|
||||
let store = SqliteWorkspaceStore::in_memory_for_test().unwrap();
|
||||
store
|
||||
.upsert_account(&AccountRecord {
|
||||
account_id: "owner-account".to_string(),
|
||||
@@ -22041,7 +22071,7 @@ INSERT INTO worker_registry (
|
||||
|
||||
#[tokio::test]
|
||||
async fn repository_records_round_trip() {
|
||||
let store = SqliteWorkspaceStore::in_memory().unwrap();
|
||||
let store = SqliteWorkspaceStore::in_memory_for_test().unwrap();
|
||||
assert_eq!(store.schema_version().await.unwrap(), LATEST_SCHEMA_VERSION);
|
||||
let workspace = WorkspaceRecord {
|
||||
workspace_id: "local-dev".to_string(),
|
||||
@@ -22122,7 +22152,7 @@ INSERT INTO worker_registry (
|
||||
|
||||
#[tokio::test]
|
||||
async fn memory_authority_records_round_trip_and_close_staging() {
|
||||
let store = SqliteWorkspaceStore::in_memory().unwrap();
|
||||
let store = SqliteWorkspaceStore::in_memory_for_test().unwrap();
|
||||
assert_eq!(store.schema_version().await.unwrap(), LATEST_SCHEMA_VERSION);
|
||||
let workspace = WorkspaceRecord {
|
||||
workspace_id: "local-dev".to_string(),
|
||||
@@ -22197,7 +22227,7 @@ INSERT INTO worker_registry (
|
||||
|
||||
#[tokio::test]
|
||||
async fn legacy_memory_reset_is_atomic_scoped_idempotent_and_exact() {
|
||||
let store = SqliteWorkspaceStore::in_memory().unwrap();
|
||||
let store = SqliteWorkspaceStore::in_memory_for_test().unwrap();
|
||||
for (workspace_id, display_name) in [
|
||||
("local-dev", "Local Dev"),
|
||||
("other-workspace", "Other Workspace"),
|
||||
@@ -22364,7 +22394,7 @@ INSERT INTO worker_registry (
|
||||
async fn worker_workdir_registry_round_trips_and_preserves_pinned_retention() {
|
||||
let temp = tempfile::tempdir().unwrap();
|
||||
let db = temp.path().join("workspace.db");
|
||||
let store = SqliteWorkspaceStore::open(&db).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&db).unwrap();
|
||||
let workspace = WorkspaceRecord {
|
||||
workspace_id: "local-dev".to_string(),
|
||||
owner_account_id: "owner-account".to_string(),
|
||||
@@ -22733,7 +22763,7 @@ INSERT INTO worker_registry (
|
||||
);
|
||||
}
|
||||
drop(store);
|
||||
let store = SqliteWorkspaceStore::open(&db).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&db).unwrap();
|
||||
assert_eq!(
|
||||
store
|
||||
.list_worker_workdir_links_page("local-dev", &worker.worker, 1, 0, None)
|
||||
@@ -22763,7 +22793,7 @@ INSERT INTO worker_registry (
|
||||
let workdir_conflict = store.attach_worker_workdir(&workdir_conflict).unwrap();
|
||||
|
||||
drop(store);
|
||||
let reopened = SqliteWorkspaceStore::open(&db).unwrap();
|
||||
let reopened = SqliteWorkspaceStore::open_for_test(&db).unwrap();
|
||||
assert_eq!(
|
||||
reopened
|
||||
.list_worker_workdir_links("local-dev", &worker.worker)
|
||||
@@ -22781,7 +22811,7 @@ INSERT INTO worker_registry (
|
||||
#[tokio::test]
|
||||
async fn worker_projection_preserves_equal_local_ids_from_distinct_runtimes() {
|
||||
let temp = tempfile::tempdir().unwrap();
|
||||
let store = SqliteWorkspaceStore::open(temp.path().join("workspace.db")).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(temp.path().join("workspace.db")).unwrap();
|
||||
store
|
||||
.upsert_workspace(&WorkspaceRecord {
|
||||
workspace_id: "local-dev".to_string(),
|
||||
@@ -22907,7 +22937,7 @@ INSERT INTO worker_registry (
|
||||
#[tokio::test]
|
||||
async fn worker_projection_reconciles_snapshots_and_preserves_unavailable_lifecycle() {
|
||||
let temp = tempfile::tempdir().unwrap();
|
||||
let store = SqliteWorkspaceStore::open(temp.path().join("workspace.db")).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(temp.path().join("workspace.db")).unwrap();
|
||||
store
|
||||
.upsert_workspace(&WorkspaceRecord {
|
||||
workspace_id: "local-dev".to_string(),
|
||||
@@ -23082,7 +23112,7 @@ INSERT INTO worker_registry (
|
||||
#[tokio::test]
|
||||
async fn late_runtime_event_does_not_recreate_retention_deleted_catalog_worker() {
|
||||
let temp = tempfile::tempdir().unwrap();
|
||||
let store = SqliteWorkspaceStore::open(temp.path().join("workspace.db")).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(temp.path().join("workspace.db")).unwrap();
|
||||
store
|
||||
.upsert_workspace(&WorkspaceRecord {
|
||||
workspace_id: "local-dev".to_string(),
|
||||
@@ -23177,7 +23207,7 @@ INSERT INTO worker_registry (
|
||||
async fn worker_control_grants_are_idempotent_scoped_and_support_internal_invalidation() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let database = dir.path().join("control-grants.db");
|
||||
let store = SqliteWorkspaceStore::open(&database).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&database).unwrap();
|
||||
store
|
||||
.upsert_workspace(&WorkspaceRecord {
|
||||
workspace_id: "workspace-control".to_string(),
|
||||
@@ -23247,7 +23277,7 @@ INSERT INTO worker_registry (
|
||||
);
|
||||
|
||||
drop(store);
|
||||
let store = SqliteWorkspaceStore::open(&database).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&database).unwrap();
|
||||
assert_eq!(
|
||||
store
|
||||
.list_active_worker_control_grants(
|
||||
@@ -23305,7 +23335,7 @@ INSERT INTO worker_registry (
|
||||
|
||||
#[tokio::test]
|
||||
async fn account_and_login_records_round_trip() {
|
||||
let store = SqliteWorkspaceStore::in_memory().unwrap();
|
||||
let store = SqliteWorkspaceStore::in_memory_for_test().unwrap();
|
||||
assert_eq!(store.schema_version().await.unwrap(), LATEST_SCHEMA_VERSION);
|
||||
let now = "2026-07-22T00:00:00Z".to_string();
|
||||
let account = AccountRecord {
|
||||
@@ -23664,9 +23694,9 @@ INSERT INTO worker_registry (
|
||||
async fn backend_job_resource_reserve_converges_across_connections_without_changing_input() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let path = dir.path().join("resource-jobs.sqlite");
|
||||
let store = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
seed_resource_job_workspace(&store).await;
|
||||
let other = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let other = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
let requests = [
|
||||
resource_job_request("first", "subject-a", "candidate-1"),
|
||||
resource_job_request("followup", "subject-a", "candidate-2"),
|
||||
@@ -23782,7 +23812,7 @@ INSERT INTO worker_registry (
|
||||
async fn backend_job_resource_retry_and_unknown_are_fenced_by_durable_cleanup() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let path = dir.path().join("cleanup-jobs.sqlite");
|
||||
let store = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
seed_resource_job_workspace(&store).await;
|
||||
let request = resource_job_request("failed", "subject-a", "candidate-1");
|
||||
let first = store
|
||||
@@ -23888,7 +23918,7 @@ INSERT INTO worker_registry (
|
||||
.unwrap();
|
||||
finish_resource_job_cleanup(&store, &second);
|
||||
drop(store);
|
||||
let restarted = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let restarted = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
let active = restarted
|
||||
.find_active_backend_job_for_resource(
|
||||
"resource-workspace",
|
||||
@@ -23948,7 +23978,7 @@ INSERT INTO worker_registry (
|
||||
async fn backend_job_resource_retry_races_new_intent_atomically_and_remains_bounded() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let path = dir.path().join("retry-race.sqlite");
|
||||
let store = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
seed_resource_job_workspace(&store).await;
|
||||
// Generic resources use the same common reservation API without domain grants.
|
||||
let mut request = resource_job_request("generic", "subject-a", "candidate-1");
|
||||
@@ -23971,7 +24001,7 @@ INSERT INTO worker_registry (
|
||||
let mut followup = request.clone();
|
||||
followup.job_id = "generic-followup".into();
|
||||
followup.input = serde_json::json!({"candidate": "new"});
|
||||
let other = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let other = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
let barrier = std::sync::Barrier::new(2);
|
||||
let (retry, reserve) = std::thread::scope(|scope| {
|
||||
let a = scope.spawn(|| {
|
||||
@@ -24057,7 +24087,7 @@ INSERT INTO worker_registry (
|
||||
|
||||
#[tokio::test]
|
||||
async fn backend_job_all_older_attempt_cleanups_fence_retry_and_resource_release() {
|
||||
let store = SqliteWorkspaceStore::in_memory().unwrap();
|
||||
let store = SqliteWorkspaceStore::in_memory_for_test().unwrap();
|
||||
seed_resource_job_workspace(&store).await;
|
||||
let mut request = resource_job_request("legacy-overlap", "subject-a", "candidate-1");
|
||||
request.limits.max_attempts = 3;
|
||||
@@ -24181,7 +24211,7 @@ INSERT INTO worker_registry (
|
||||
|
||||
#[tokio::test]
|
||||
async fn backend_job_empty_batch_surface_refresh_locks_subject_and_defers_candidates() {
|
||||
let store = SqliteWorkspaceStore::in_memory().unwrap();
|
||||
let store = SqliteWorkspaceStore::in_memory_for_test().unwrap();
|
||||
seed_resource_job_workspace(&store).await;
|
||||
for surface_state in ["ungenerated", "stale", "failed"] {
|
||||
let subject = format!("subject-{surface_state}");
|
||||
@@ -24301,7 +24331,7 @@ INSERT INTO worker_registry (
|
||||
|
||||
#[tokio::test]
|
||||
async fn backend_job_completed_resource_releases_only_after_worker_cleanup() {
|
||||
let store = SqliteWorkspaceStore::in_memory().unwrap();
|
||||
let store = SqliteWorkspaceStore::in_memory_for_test().unwrap();
|
||||
seed_resource_job_workspace(&store).await;
|
||||
let request = resource_job_request("completed", "subject-a", "candidate-1");
|
||||
let first = store
|
||||
@@ -24355,7 +24385,7 @@ INSERT INTO worker_registry (
|
||||
|
||||
#[tokio::test]
|
||||
async fn backend_jobs_fence_results_project_ownership_and_bound_retries() {
|
||||
let store = SqliteWorkspaceStore::in_memory().unwrap();
|
||||
let store = SqliteWorkspaceStore::in_memory_for_test().unwrap();
|
||||
let workspace_id = "workspace-job";
|
||||
store
|
||||
.upsert_account(&AccountRecord {
|
||||
|
||||
@@ -263,7 +263,7 @@ fn assert_retained_classification_upgrade(workspace_version: i64, component: i64
|
||||
let tags_before = retained.as_ref().map(|_| classification_rows(&conn));
|
||||
let auth_before = fixture_auth_rows(&conn);
|
||||
drop(conn);
|
||||
let store = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
store.with_conn(|conn| {
|
||||
assert_eq!(current_schema_version(conn)?,93);
|
||||
assert_eq!(conn.query_row("SELECT MAX(version) FROM ticket_schema_migrations",[],|row|row.get::<_,i64>(0))?,11);
|
||||
@@ -490,7 +490,7 @@ fn workspace90_cases9_add_classification_without_reinterpreting_reasoned_history
|
||||
let metadata_before = stored_fixture_rows(&conn, "typed_ticket_case_metadata");
|
||||
let auth_before = fixture_auth_rows(&conn);
|
||||
drop(conn);
|
||||
let store = SqliteWorkspaceStore::open(&path).unwrap();
|
||||
let store = SqliteWorkspaceStore::open_for_test(&path).unwrap();
|
||||
store
|
||||
.with_conn(|conn| {
|
||||
assert_eq!(current_schema_version(conn)?,93);
|
||||
|
||||
@@ -750,7 +750,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn retry_keeps_resolved_config_and_credential_candidates_after_fallback_moves() {
|
||||
let store = SqliteWorkspaceStore::in_memory().unwrap();
|
||||
let store = SqliteWorkspaceStore::in_memory_for_test().unwrap();
|
||||
futures::executor::block_on(store.upsert_workspace(&WorkspaceRecord {
|
||||
workspace_id: "workspace".to_string(),
|
||||
owner_account_id: "owner-account".to_string(),
|
||||
|
||||
@@ -925,7 +925,7 @@ mod tests {
|
||||
}
|
||||
|
||||
async fn seeded_store() -> (SqliteWorkspaceStore, WorkdirRegistryRecord) {
|
||||
let store = SqliteWorkspaceStore::in_memory().unwrap();
|
||||
let store = SqliteWorkspaceStore::in_memory_for_test().unwrap();
|
||||
store
|
||||
.upsert_account(&AccountRecord {
|
||||
account_id: "account-a".to_string(),
|
||||
|
||||
@@ -463,7 +463,7 @@ mod tests {
|
||||
) {
|
||||
let temp = tempfile::tempdir().unwrap();
|
||||
let store = Arc::new(
|
||||
SqliteWorkspaceStore::open(temp.path().join("workspace.db"))
|
||||
SqliteWorkspaceStore::open_for_test(temp.path().join("workspace.db"))
|
||||
.unwrap()
|
||||
.with_db_executor(crate::db_executor::DbExecutor::new(Default::default()).unwrap()),
|
||||
);
|
||||
|
||||
@@ -392,7 +392,7 @@ mod tests {
|
||||
})
|
||||
.unwrap();
|
||||
let store = Arc::new(
|
||||
SqliteWorkspaceStore::open(&db_path)
|
||||
SqliteWorkspaceStore::open_for_test(&db_path)
|
||||
.unwrap()
|
||||
.with_db_executor(executor),
|
||||
);
|
||||
|
||||
@@ -285,7 +285,7 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn create_is_atomic_and_exact_retries_converge() {
|
||||
let store = Arc::new(SqliteWorkspaceStore::in_memory().unwrap());
|
||||
let store = Arc::new(SqliteWorkspaceStore::in_memory_for_test().unwrap());
|
||||
let service = WorkspaceCatalogService::new(
|
||||
store.clone(),
|
||||
Arc::new(
|
||||
@@ -339,7 +339,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn create_rejects_noncanonical_repository_keys_without_persisting_a_workspace() {
|
||||
let store = Arc::new(SqliteWorkspaceStore::in_memory().unwrap());
|
||||
let store = Arc::new(SqliteWorkspaceStore::in_memory_for_test().unwrap());
|
||||
let service = WorkspaceCatalogService::new(
|
||||
store.clone(),
|
||||
Arc::new(
|
||||
@@ -378,7 +378,7 @@ mod tests {
|
||||
for with_repository in [false, true] {
|
||||
let temp = tempfile::tempdir().unwrap();
|
||||
let database_path = temp.path().join("server.db");
|
||||
let store = Arc::new(SqliteWorkspaceStore::open(&database_path).unwrap());
|
||||
let store = Arc::new(SqliteWorkspaceStore::open_for_test(&database_path).unwrap());
|
||||
let owner_account_id = owner_account(store.as_ref());
|
||||
let materials = Arc::new(InMemoryWorkspaceSigningMaterialStore::default());
|
||||
let service = WorkspaceCatalogService::new(
|
||||
@@ -418,7 +418,7 @@ mod tests {
|
||||
|
||||
drop(service);
|
||||
drop(store);
|
||||
let store = Arc::new(SqliteWorkspaceStore::open(&database_path).unwrap());
|
||||
let store = Arc::new(SqliteWorkspaceStore::open_for_test(&database_path).unwrap());
|
||||
let restarted = WorkspaceCatalogService::new(store.clone(), materials);
|
||||
let created = restarted.create(request, owner_account_id).unwrap();
|
||||
let identity = store
|
||||
@@ -435,7 +435,7 @@ mod tests {
|
||||
for with_repository in [false, true] {
|
||||
let temp = tempfile::tempdir().unwrap();
|
||||
let database_path = temp.path().join("server.db");
|
||||
let store = Arc::new(SqliteWorkspaceStore::open(&database_path).unwrap());
|
||||
let store = Arc::new(SqliteWorkspaceStore::open_for_test(&database_path).unwrap());
|
||||
let owner_account_id = owner_account(store.as_ref());
|
||||
let materials = Arc::new(InMemoryWorkspaceSigningMaterialStore::default());
|
||||
let service = WorkspaceCatalogService::new(store.clone(), materials.clone());
|
||||
@@ -486,7 +486,7 @@ mod tests {
|
||||
|
||||
drop(service);
|
||||
drop(store);
|
||||
let store = Arc::new(SqliteWorkspaceStore::open(&database_path).unwrap());
|
||||
let store = Arc::new(SqliteWorkspaceStore::open_for_test(&database_path).unwrap());
|
||||
let restarted = WorkspaceCatalogService::new(store.clone(), materials);
|
||||
let created = restarted.create(request, owner_account_id).unwrap();
|
||||
let identity = store
|
||||
@@ -500,7 +500,7 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn idempotency_key_reuse_with_different_payload_is_rejected() {
|
||||
let store = Arc::new(SqliteWorkspaceStore::in_memory().unwrap());
|
||||
let store = Arc::new(SqliteWorkspaceStore::in_memory_for_test().unwrap());
|
||||
let owner_account_id = owner_account(store.as_ref());
|
||||
let service = WorkspaceCatalogService::new(
|
||||
store,
|
||||
@@ -532,7 +532,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn repository_free_create_initializes_authority_and_concurrent_retries_converge() {
|
||||
let store = Arc::new(SqliteWorkspaceStore::in_memory().unwrap());
|
||||
let store = Arc::new(SqliteWorkspaceStore::in_memory_for_test().unwrap());
|
||||
let owner = owner_account(store.as_ref());
|
||||
let service = WorkspaceCatalogService::new(
|
||||
store.clone(),
|
||||
@@ -611,7 +611,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn replay_reads_current_repository_at_initial_key_and_never_recreates_it() {
|
||||
let store = Arc::new(SqliteWorkspaceStore::in_memory().unwrap());
|
||||
let store = Arc::new(SqliteWorkspaceStore::in_memory_for_test().unwrap());
|
||||
let owner = owner_account(store.as_ref());
|
||||
let service = WorkspaceCatalogService::new(
|
||||
store.clone(),
|
||||
@@ -673,13 +673,13 @@ mod tests {
|
||||
repository: None,
|
||||
};
|
||||
let (owner, created) = {
|
||||
let store = Arc::new(SqliteWorkspaceStore::open(&database).unwrap());
|
||||
let store = Arc::new(SqliteWorkspaceStore::open_for_test(&database).unwrap());
|
||||
let owner = owner_account(store.as_ref());
|
||||
let service = WorkspaceCatalogService::new(store, materials.clone());
|
||||
let created = service.create(request.clone(), owner.clone()).unwrap();
|
||||
(owner, created)
|
||||
};
|
||||
let store = Arc::new(SqliteWorkspaceStore::open(&database).unwrap());
|
||||
let store = Arc::new(SqliteWorkspaceStore::open_for_test(&database).unwrap());
|
||||
let reopened = WorkspaceCatalogService::new(store.clone(), materials);
|
||||
let replay = reopened.create(request, owner).unwrap();
|
||||
assert_eq!(replay.workspace, created.workspace);
|
||||
@@ -739,7 +739,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn create_rejects_non_user_account_owners() {
|
||||
let store = Arc::new(SqliteWorkspaceStore::in_memory().unwrap());
|
||||
let store = Arc::new(SqliteWorkspaceStore::in_memory_for_test().unwrap());
|
||||
store
|
||||
.upsert_account(&AccountRecord {
|
||||
account_id: "organization-owner".to_string(),
|
||||
@@ -777,7 +777,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn catalog_list_is_scoped_to_the_required_owner_account() {
|
||||
let store = Arc::new(SqliteWorkspaceStore::in_memory().unwrap());
|
||||
let store = Arc::new(SqliteWorkspaceStore::in_memory_for_test().unwrap());
|
||||
let owner_a = owner_account(store.as_ref());
|
||||
let owner_b = "account-owner-b".to_string();
|
||||
store
|
||||
@@ -845,7 +845,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn remote_repository_creation_persists_typed_source_without_auth_metadata() {
|
||||
let store = Arc::new(SqliteWorkspaceStore::in_memory().unwrap());
|
||||
let store = Arc::new(SqliteWorkspaceStore::in_memory_for_test().unwrap());
|
||||
let owner_account_id = owner_account(store.as_ref());
|
||||
let service = WorkspaceCatalogService::new(
|
||||
store.clone(),
|
||||
|
||||
@@ -922,7 +922,7 @@ mod tests {
|
||||
use tempfile::tempdir;
|
||||
|
||||
fn setup() -> (SqliteWorkspaceStore, String, String) {
|
||||
seed_workspaces(SqliteWorkspaceStore::in_memory().expect("store"))
|
||||
seed_workspaces(SqliteWorkspaceStore::in_memory_for_test().expect("store"))
|
||||
}
|
||||
|
||||
fn seed_workspaces(store: SqliteWorkspaceStore) -> (SqliteWorkspaceStore, String, String) {
|
||||
@@ -989,7 +989,7 @@ mod tests {
|
||||
let dir = tempdir().expect("tempdir");
|
||||
let path = dir.path().join("server.db");
|
||||
let (store, owner, workspace_id) =
|
||||
seed_workspaces(SqliteWorkspaceStore::open(&path).expect("store"));
|
||||
seed_workspaces(SqliteWorkspaceStore::open_for_test(&path).expect("store"));
|
||||
for workspace in ["workspace-a", "workspace-b"] {
|
||||
let backend = ticket::SqliteTicketBackend::open_verified(&path, workspace).unwrap();
|
||||
let initial = backend
|
||||
|
||||
@@ -780,7 +780,7 @@ mod tests {
|
||||
|
||||
let temp = tempfile::tempdir().unwrap();
|
||||
let database_path = temp.path().join("server.db");
|
||||
let store = Arc::new(SqliteWorkspaceStore::open(&database_path).unwrap());
|
||||
let store = Arc::new(SqliteWorkspaceStore::open_for_test(&database_path).unwrap());
|
||||
store
|
||||
.upsert_account(&AccountRecord {
|
||||
account_id: "account-1".to_string(),
|
||||
@@ -833,7 +833,7 @@ mod tests {
|
||||
|
||||
drop(failing_service);
|
||||
drop(store);
|
||||
let store = Arc::new(SqliteWorkspaceStore::open(&database_path).unwrap());
|
||||
let store = Arc::new(SqliteWorkspaceStore::open_for_test(&database_path).unwrap());
|
||||
let service = WorkspaceSigningIdentityService::new(store.clone(), materials.clone());
|
||||
let provisioned = service
|
||||
.provision_existing("workspace-1", "account-1")
|
||||
@@ -962,7 +962,7 @@ mod tests {
|
||||
);
|
||||
drop(service);
|
||||
drop(store);
|
||||
let store = Arc::new(SqliteWorkspaceStore::open(&database_path).unwrap());
|
||||
let store = Arc::new(SqliteWorkspaceStore::open_for_test(&database_path).unwrap());
|
||||
let restarted = WorkspaceSigningIdentityService::new(store.clone(), materials.clone());
|
||||
let recovered = restarted
|
||||
.provision_existing("workspace-2", "account-1")
|
||||
|
||||
@@ -738,10 +738,11 @@ mod tests {
|
||||
AccountRecord, ControlPlaneStore, SqliteWorkspaceStore, WorkerRegistryRecord,
|
||||
WorkspaceRecord,
|
||||
};
|
||||
let store =
|
||||
std::sync::Arc::new(SqliteWorkspaceStore::in_memory().unwrap().with_db_executor(
|
||||
crate::db_executor::DbExecutor::new(Default::default()).unwrap(),
|
||||
));
|
||||
let store = std::sync::Arc::new(
|
||||
SqliteWorkspaceStore::in_memory_for_test()
|
||||
.unwrap()
|
||||
.with_db_executor(crate::db_executor::DbExecutor::new(Default::default()).unwrap()),
|
||||
);
|
||||
store
|
||||
.upsert_account(&AccountRecord {
|
||||
account_id: "owner".into(),
|
||||
|
||||
Reference in New Issue
Block a user