test: add isolated backend fixture seeding

This commit is contained in:
2026-10-24 12:15:10 +09:00
parent 1639be9841
commit b8f2fa479c
4 changed files with 732 additions and 4 deletions
+4
View File
@@ -10,6 +10,10 @@ autobins = false
name = "yoi-server"
path = "src/main.rs"
[features]
# Offline fixture preparation only; build product binaries without this feature.
test-support = []
[dependencies]
api-macros = { workspace = true, features = ["axum"] }
async-trait.workspace = true
+2
View File
@@ -25,6 +25,8 @@ pub mod runtime_subscription;
pub mod server;
pub mod skills;
pub mod store;
#[cfg(feature = "test-support")]
pub use store::fixture_support as test_support;
pub mod subjektiv;
#[cfg(test)]
mod ticket_browse_performance_tests;
+38 -4
View File
@@ -2589,6 +2589,10 @@ pub struct SqliteWorkspaceStore {
db_executor: crate::db_executor::DbExecutor,
}
#[cfg(feature = "test-support")]
#[path = "test_support.rs"]
pub mod fixture_support;
impl SqliteWorkspaceStore {
pub fn open(path: impl AsRef<Path>) -> Result<Self> {
let conn = Connection::open(path)?;
@@ -2900,6 +2904,33 @@ impl SqliteWorkspaceStore {
request_fingerprint: &str,
singleton_key: Option<&str>,
current_memory_settings: &WorkspaceMemorySettingsRecord,
) -> Result<WorkerCreateReservation> {
self.reserve_worker_create_with(
workspace_id,
runtime_id,
allocation_key,
request_fingerprint,
singleton_key,
current_memory_settings,
|_| Ok(None),
|_, _| Ok(()),
)
}
// Keep reservation validation, Memory binding and writes in one transaction. The
// nondefault test-support module supplies fixed identity / offline catalog hooks;
// ordinary creation always supplies a newly generated ID and no completion hook.
#[allow(clippy::too_many_arguments)]
fn reserve_worker_create_with(
&self,
workspace_id: &str,
runtime_id: &str,
allocation_key: &str,
request_fingerprint: &str,
singleton_key: Option<&str>,
current_memory_settings: &WorkspaceMemorySettingsRecord,
prepare: impl FnOnce(&rusqlite::Transaction<'_>) -> Result<Option<WorkerId>>,
complete: impl FnOnce(&rusqlite::Transaction<'_>, &WorkerCreateReservation) -> Result<()>,
) -> Result<WorkerCreateReservation> {
if allocation_key.trim().is_empty() || request_fingerprint.trim().is_empty() {
return Err(Error::InvalidInput(
@@ -2912,6 +2943,7 @@ impl SqliteWorkspaceStore {
validate_workspace_memory_settings_record(current_memory_settings, workspace_id)?;
self.with_conn_mut(|conn| {
let tx = conn.transaction_with_behavior(TransactionBehavior::Immediate)?;
let fixed_worker_id = prepare(&tx)?;
let existing = tx
.query_row(
"SELECT worker_id, runtime_id, request_fingerprint, create_fingerprint, \
@@ -3094,7 +3126,7 @@ impl SqliteWorkspaceStore {
validate_workspace_memory_settings_snapshot(&snapshot, workspace_id)?;
let create_fingerprint =
bound_worker_create_fingerprint(request_fingerprint, &snapshot);
let worker_id = WorkerId::now_v7();
let worker_id = fixed_worker_id.unwrap_or_else(WorkerId::now_v7);
let worker_id_text = worker_id.to_string();
let now = chrono::Utc::now().to_rfc3339();
let singleton_generation = match singleton_owner.as_ref() {
@@ -3183,13 +3215,15 @@ impl SqliteWorkspaceStore {
));
}
}
tx.commit()?;
Ok(WorkerCreateReservation {
let reservation = WorkerCreateReservation {
worker_id,
create_fingerprint,
memory_settings: snapshot,
singleton,
})
};
complete(&tx, &reservation)?;
tx.commit()?;
Ok(reservation)
})
}
+688
View File
@@ -0,0 +1,688 @@
//! Offline Backend fixture preparation, available only with `test-support`.
//!
//! Use a new isolated database and the existing account, Workspace signing-identity /
//! `ControlPlaneStore::create_workspace_bootstrap`, and Runtime binding APIs first.
//! Generate fresh account credentials and signing keys for each environment; no fixture
//! credentials are accepted here. Install Profile configuration through the existing
//! config-source mechanisms before starting the product processes.
//!
//! This module seeds Backend ownership only. It neither writes Runtime storage nor
//! launches a Worker, fabricates Runtime observations, changes authorization, or sends
//! initial input. The caller must separately install the matching stopped Runtime
//! fixture. Build product binaries in a separate Cargo invocation **without** this
//! feature (Cargo features unify within an invocation).
use super::*;
use crate::hosts::{WorkerSpawnIntent, WorkerSpawnRequest, worker_spawn_create_fingerprint};
use worker_runtime::catalog::ProfileSelector;
/// One ordinary, attachment-free Worker from an externally validated fixture.
///
/// IDs must match the Runtime fixture. `request` is the unresolved canonical create
/// intent, not a Runtime launch request containing credentials or execution grants.
/// The Profile selector must already be installed by the harness. `initial_submit`
/// must be empty: saved Session contents belong to the Runtime fixture, not new input.
/// Singleton/service, Ticket-assigned and attachment-bearing Workers are deliberately
/// unsupported.
pub struct FixedWorkerSeed<'a> {
pub workspace_id: &'a str,
pub runtime_id: &'a str,
pub worker_id: WorkerId,
pub allocation_key: &'a str,
pub request: &'a WorkerSpawnRequest,
}
/// Insert a fixed Worker catalog entry and completed creation reservation atomically.
///
/// Uses the normal reservation validators, authoritative Memory snapshot, fingerprint
/// binding, resource-key allocator and immediate transaction. Even an exact repeat is
/// rejected: this is not an upsert/import/recovery API. Existing allocations, Worker
/// identities and residual lifecycle/attachment records are never adopted or repaired.
/// Returns the creation binding needed to check the corresponding Runtime fixture.
pub fn seed_fixed_worker(
store: &SqliteWorkspaceStore,
seed: FixedWorkerSeed<'_>,
) -> Result<WorkerCreateReservation> {
validate_identifier("workspace_id", seed.workspace_id)?;
validate_identifier("runtime_id", seed.runtime_id)?;
let request = seed.request;
if !request.initial_submit.is_empty() {
return Err(Error::InvalidInput(
"fixture Worker cannot contain initial_submit; offline seeding accepts no new input"
.into(),
));
}
if !matches!(request.intent, WorkerSpawnIntent::WorkspaceCoding)
|| request.singleton_key.is_some()
|| request.ticket_assignment.is_some()
|| request.resolved_subjektiv_attached
|| !request.workdir_attachment_requests.is_empty()
|| !request.resolved_workdir_attachment_requests.is_empty()
|| !request.resolved_workdir_attachments.is_empty()
|| request.resolved_config_bundle.is_some()
|| request.resolved_workspace_api.is_some()
|| request.resolved_memory_settings.is_some()
|| request.resolved_worker_observation_enabled
|| !request.resolved_worker_observation_grants.is_empty()
|| request.resolved_control_operation.is_some()
|| request.resolved_execution_grant.is_some()
{
return Err(Error::InvalidInput(
"fixture Worker must be ordinary unresolved create intent without singleton, assignments, attachments or grants".into(),
));
}
// Builtin selectors already carry their canonical `builtin:` prefix.
let profile = match &request.profile {
ProfileSelector::Builtin(name) | ProfileSelector::Named(name) => name,
};
validate_non_empty("fixture Profile selector", profile)?;
let worker_id = seed.worker_id.to_string();
let display_name = request
.requested_worker_name
.as_deref()
.unwrap_or(&worker_id);
validate_non_empty("fixture Worker display name", display_name)?;
let fingerprint = worker_spawn_create_fingerprint(request).map_err(Error::InvalidInput)?;
let memory = store.get_workspace_memory_settings(seed.workspace_id)?;
store.reserve_worker_create_with(
seed.workspace_id,
seed.runtime_id,
seed.allocation_key,
&fingerprint,
None,
&memory,
|tx| {
require_seed_target(tx, &seed)?;
Ok(Some(seed.worker_id))
},
|tx, reservation| {
let now = chrono::Utc::now().to_rfc3339();
tx.execute(
"INSERT INTO worker_registry (
workspace_id, runtime_id, worker_id, display_name, profile,
retention_state, created_at, updated_at
) VALUES (?1, ?2, ?3, ?4, ?5, 'normal', ?6, ?6)",
params![seed.workspace_id, seed.runtime_id, worker_id, display_name, profile, now],
)?;
let changed = tx.execute(
"UPDATE worker_create_reservations SET state = 'created', updated_at = ?4
WHERE workspace_id = ?1 AND runtime_id = ?2 AND worker_id = ?3 AND state = 'reserved'",
params![seed.workspace_id, seed.runtime_id, reservation.worker_id.to_string(), now],
)?;
if changed != 1 {
return Err(Error::Store("fixture creation reservation disappeared".into()));
}
Ok(())
},
)
}
fn require_seed_target(tx: &rusqlite::Transaction<'_>, seed: &FixedWorkerSeed<'_>) -> Result<()> {
let active: bool = tx.query_row(
"SELECT EXISTS(SELECT 1 FROM workspaces w
JOIN workspace_runtime_bindings r ON r.workspace_id = w.workspace_id
JOIN workspace_signing_identities s ON s.workspace_id = w.workspace_id
WHERE w.workspace_id = ?1 AND w.state = 'active'
AND r.runtime_id = ?2 AND r.revoked_at IS NULL
AND r.authentication_mode = 'workspace_identity' AND s.state = 'active')",
params![seed.workspace_id, seed.runtime_id],
|row| row.get(0),
)?;
if !active {
return Err(Error::InvalidInput(
"fixture requires an active bootstrapped Workspace and authenticated Runtime binding"
.into(),
));
}
let worker_id = seed.worker_id.to_string();
let allocation_exists: bool = tx.query_row(
"SELECT EXISTS(SELECT 1 FROM worker_create_reservations
WHERE workspace_id = ?1 AND allocation_key = ?2)",
params![seed.workspace_id, seed.allocation_key],
|row| row.get(0),
)?;
if allocation_exists {
return Err(Error::InvalidInput(
"fixture Worker allocation already exists".into(),
));
}
// Check by WorkerId, not just the proposed Runtime tuple: orphaned and terminal
// ownership is still a collision. These tables are owned by this store schema.
for table in [
"worker_create_reservations",
"worker_registry",
"worker_registry_observations",
"worker_registry_projection_removals",
"worker_removal_operations",
"worker_singleton_owners",
"worker_workdir_links",
"worker_restore_intents",
"worker_tombstones",
"worker_orphan_diagnostics",
"worker_registry_projection_diagnostics",
"worker_session_archives",
"worker_diagnostics_archives",
"ticket_assignment_worker_tombstones",
] {
let exists: bool = tx.query_row(
&format!("SELECT EXISTS(SELECT 1 FROM {table} WHERE worker_id = ?1)"),
[&worker_id],
|row| row.get(0),
)?;
if exists {
return Err(Error::InvalidInput(format!(
"fixture Worker identity already exists in {table}"
)));
}
}
// A resource key without a catalog/reservation must not be silently reused.
let mut statement = tx.prepare(
"SELECT resource_id FROM workspace_resource_keys WHERE resource_kind = 'worker'",
)?;
let resources = statement.query_map([], |row| row.get::<_, String>(0))?;
for resource in resources {
let resource = resource?;
let existing = resource
.is_ascii()
.then(|| parse_worker_resource_id(&resource))
.flatten()
.ok_or_else(|| {
Error::InvalidInput("unknown fixture Worker resource identity collision".into())
})?;
if existing.worker_id == worker_id {
return Err(Error::InvalidInput(
"fixture Worker resource identity already exists".into(),
));
}
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use crate::hosts::{
WorkerSpawnAcceptanceRequirement, WorkerSpawnWorkingDirectoryAttachmentRequest,
WorkerSpawnWorkingDirectoryRequest,
};
use crate::workspace_signing_identity::{
InMemoryWorkspaceSigningMaterialStore, WorkspaceSigningIdentityService,
};
const WORKSPACE: &str = "0197a949-4b6b-7f2a-9d9a-1f87e3a4c501";
const RUNTIME: &str = "fixture-runtime";
const WORKER: &str = "0197a949-4b6b-7f2a-9d9a-1f87e3a4c502";
// Exercises the same public bootstrap APIs the offline harness uses. All account
// and key identities are newly generated, even across stores with fixed fixture IDs.
fn bootstrap() -> SqliteWorkspaceStore {
let store = SqliteWorkspaceStore::in_memory_for_test().unwrap();
let account = AccountRecord {
account_id: format!("fixture-account-{}", Uuid::now_v7()),
kind: "user".into(),
handle: format!("fixture-{}", Uuid::now_v7()),
display_name: "Fixture owner".into(),
created_at: "2026-10-24T00:00:00Z".into(),
updated_at: "2026-10-24T00:00:00Z".into(),
};
store.upsert_account(&account).unwrap();
let identities = WorkspaceSigningIdentityService::new(
Arc::new(store.clone()),
Arc::new(InMemoryWorkspaceSigningMaterialStore::default()),
);
let (identity, operation) = identities
.prepare_workspace_creation(
"fixture-bootstrap",
"fixture-bootstrap",
WORKSPACE,
&account.account_id,
)
.unwrap();
store
.create_workspace_bootstrap(
&WorkspaceBootstrapRecord {
operation_key: "fixture-bootstrap".into(),
request_fingerprint: "fixture-bootstrap".into(),
workspace: WorkspaceRecord {
workspace_id: WORKSPACE.into(),
owner_account_id: account.account_id,
display_name: "Fixture".into(),
state: "active".into(),
created_at: account.created_at,
updated_at: account.updated_at,
},
repository: None,
},
&identity,
&operation,
)
.unwrap();
let runtime_key = worker_runtime::auth::RuntimeIdentityMaterial::generate(RUNTIME).unwrap();
store
.upsert_workspace_runtime_binding(
WorkspaceRuntimeBinding {
workspace_id: WORKSPACE.into(),
runtime_id: RUNTIME.into(),
display_name: "Fixture Runtime".into(),
base_url: "http://127.0.0.1:12345".into(),
public_key: runtime_key.public_key,
public_key_fingerprint: String::new(),
binding_id: String::new(),
authentication_mode: WorkspaceRuntimeAuthenticationMode::WorkspaceIdentity,
created_at: "2026-10-24T00:00:00Z".into(),
updated_at: "2026-10-24T00:00:00Z".into(),
revoked_at: None,
},
false,
)
.unwrap();
store
}
fn request() -> WorkerSpawnRequest {
WorkerSpawnRequest {
intent: WorkerSpawnIntent::WorkspaceCoding,
requested_worker_name: Some("Fixture Worker".into()),
singleton_key: None,
acceptance: WorkerSpawnAcceptanceRequirement::SocketReady,
profile: ProfileSelector::Builtin("builtin:coder".into()),
ticket_assignment: None,
initial_submit: Vec::new(),
workdir_attachment_requests: Vec::new(),
resolved_workdir_attachment_requests: Vec::new(),
resolved_workdir_attachments: Vec::new(),
resolved_config_bundle: None,
resolved_workspace_api: None,
resolved_memory_settings: None,
resolved_subjektiv_attached: false,
resolved_worker_observation_enabled: false,
resolved_worker_observation_grants: Vec::new(),
resolved_control_operation: None,
resolved_execution_grant: None,
}
}
fn seed(request: &WorkerSpawnRequest) -> FixedWorkerSeed<'_> {
FixedWorkerSeed {
workspace_id: WORKSPACE,
runtime_id: RUNTIME,
worker_id: WORKER.parse().unwrap(),
allocation_key: "fixture-allocation",
request,
}
}
fn worker() -> RuntimeWorkerRef {
RuntimeWorkerRef::new(RUNTIME, WORKER)
}
#[test]
fn fixed_ids_are_isolated_and_seed_has_no_runtime_observation() {
let a = bootstrap();
let b = bootstrap();
let request = request();
let first = seed_fixed_worker(&a, seed(&request)).unwrap();
let second = seed_fixed_worker(&b, seed(&request)).unwrap();
assert_eq!(first, second);
assert_eq!(first.worker_id.to_string(), WORKER);
assert_eq!(first.memory_settings.workspace_id, WORKSPACE);
assert_eq!(first.memory_settings.language, "English");
assert!(first.singleton.is_none());
assert_ne!(
a.get_workspace_signing_identity(WORKSPACE)
.unwrap()
.unwrap()
.public_key,
b.get_workspace_signing_identity(WORKSPACE)
.unwrap()
.unwrap()
.public_key
);
assert_ne!(
a.get_workspace_runtime_binding(WORKSPACE, RUNTIME)
.unwrap()
.unwrap()
.public_key,
b.get_workspace_runtime_binding(WORKSPACE, RUNTIME)
.unwrap()
.unwrap()
.public_key
);
for store in [&a, &b] {
assert_eq!(
store
.worker_resource_key(WORKSPACE, &worker())
.unwrap()
.as_deref(),
Some("W-1")
);
assert_eq!(
store
.resolve_worker_resource_reference(WORKSPACE, "W-1")
.unwrap(),
Some(worker())
);
assert!(
!store
.has_active_worker_create_reservation(WORKSPACE, &worker())
.unwrap()
);
let registry = store
.get_worker_registry(WORKSPACE, &worker())
.unwrap()
.unwrap();
assert_eq!(registry.profile.as_deref(), Some("builtin:coder"));
assert_eq!(registry.display_name, "Fixture Worker");
assert_eq!(registry.retention_state, "normal");
let projection = store
.with_conn(|conn| read_worker_registry_projection(conn, WORKSPACE, &worker()))
.unwrap()
.unwrap();
assert!(projection.observation.is_none());
assert!(projection.job.is_none());
}
}
#[test]
fn initial_submit_is_refused_without_registration_or_allocation() {
let store = bootstrap();
let mut request = request();
// Even an empty text segment is new input; the vector itself must be empty.
for text in ["new input must not be seeded", ""] {
request.initial_submit = vec![protocol::Segment::text(text)];
let error = seed_fixed_worker(&store, seed(&request)).unwrap_err();
assert!(
matches!(error, Error::InvalidInput(ref message) if message.contains("initial_submit"))
);
assert!(
store
.get_worker_registry(WORKSPACE, &worker())
.unwrap()
.is_none()
);
assert!(
store
.worker_resource_key(WORKSPACE, &worker())
.unwrap()
.is_none()
);
assert!(
!store
.has_active_worker_create_reservation(WORKSPACE, &worker())
.unwrap()
);
}
// The rejected attempts must not consume the allocation or resource counter.
request.initial_submit.clear();
seed_fixed_worker(&store, seed(&request)).unwrap();
assert_eq!(
store
.worker_resource_key(WORKSPACE, &worker())
.unwrap()
.as_deref(),
Some("W-1")
);
}
#[test]
fn exact_replay_changed_input_and_cross_runtime_identity_are_refused() {
let store = bootstrap();
let mut request = request();
seed_fixed_worker(&store, seed(&request)).unwrap();
let before = store.get_worker_registry(WORKSPACE, &worker()).unwrap();
assert!(seed_fixed_worker(&store, seed(&request)).is_err());
request.requested_worker_name = Some("Must not overwrite".into());
assert!(seed_fixed_worker(&store, seed(&request)).is_err());
let mut new_allocation = seed(&request);
new_allocation.allocation_key = "another-allocation";
assert!(seed_fixed_worker(&store, new_allocation).is_err());
let mut same_allocation = seed(&request);
same_allocation.worker_id = WorkerId::now_v7();
assert!(seed_fixed_worker(&store, same_allocation).is_err());
assert_eq!(
store.get_worker_registry(WORKSPACE, &worker()).unwrap(),
before
);
let other = bootstrap();
let mut record = before.unwrap();
record.worker.runtime_id = "different-runtime".into();
other.upsert_worker_registry(&record).unwrap();
assert!(seed_fixed_worker(&other, seed(&request)).is_err());
assert!(
other
.get_worker_registry(WORKSPACE, &worker())
.unwrap()
.is_none()
);
}
#[test]
fn reserved_and_orphaned_resource_identities_are_not_adopted() {
let store = bootstrap();
let request = request();
let memory = store.get_workspace_memory_settings(WORKSPACE).unwrap();
let ordinary = store
.reserve_worker_create(WORKSPACE, RUNTIME, "ordinary", "fingerprint", None, &memory)
.unwrap();
let mut collision = seed(&request);
collision.worker_id = ordinary.worker_id;
assert!(seed_fixed_worker(&store, collision).is_err());
// Store-level fault setup only: the external harness never writes SQL.
store
.with_conn(|conn| {
allocate_resource_key(
conn,
WORKSPACE,
WorkspaceResourceKind::Worker,
&worker_resource_id(&worker()),
"now",
)?;
Ok(())
})
.unwrap();
assert!(seed_fixed_worker(&store, seed(&request)).is_err());
assert!(
store
.get_worker_registry(WORKSPACE, &worker())
.unwrap()
.is_none()
);
}
#[test]
fn unknown_resource_identity_and_retained_removal_fence_are_refused() {
let request = request();
let malformed = bootstrap();
malformed
.with_conn(|conn| {
allocate_resource_key(
conn,
WORKSPACE,
WorkspaceResourceKind::Worker,
"unknown-identity",
"now",
)?;
Ok(())
})
.unwrap();
assert!(matches!(
seed_fixed_worker(&malformed, seed(&request)),
Err(Error::InvalidInput(_))
));
assert!(
malformed
.get_worker_registry(WORKSPACE, &worker())
.unwrap()
.is_none()
);
let removed = bootstrap();
removed.with_conn(|conn| {
conn.execute(
"INSERT INTO worker_registry_projection_removals(workspace_id, runtime_id, worker_id) VALUES (?1, ?2, ?3)",
params![WORKSPACE, RUNTIME, WORKER],
)?;
Ok(())
}).unwrap();
assert!(matches!(
seed_fixed_worker(&removed, seed(&request)),
Err(Error::InvalidInput(_))
));
assert!(
removed
.worker_resource_key(WORKSPACE, &worker())
.unwrap()
.is_none()
);
}
#[test]
fn unknown_workspace_runtime_and_revoked_binding_are_refused() {
let store = bootstrap();
let request = request();
let mut unknown = seed(&request);
unknown.workspace_id = "unknown";
assert!(seed_fixed_worker(&store, unknown).is_err());
let mut unknown = seed(&request);
unknown.runtime_id = "unknown";
assert!(seed_fixed_worker(&store, unknown).is_err());
store
.revoke_workspace_runtime_binding(WORKSPACE, RUNTIME, "2026-10-24T01:00:00Z")
.unwrap();
assert!(seed_fixed_worker(&store, seed(&request)).is_err());
assert!(
store
.worker_resource_key(WORKSPACE, &worker())
.unwrap()
.is_none()
);
}
#[test]
fn unsupported_intent_is_refused_without_partial_registration() {
let store = bootstrap();
let base = request();
let mut requests = Vec::new();
let mut request = base.clone();
request.singleton_key = Some("fixture-singleton".into());
requests.push(request);
let mut request = base.clone();
request.intent = WorkerSpawnIntent::WorkspaceOrchestrator;
requests.push(request);
let mut request = base.clone();
request.resolved_subjektiv_attached = true;
requests.push(request);
let mut request = base.clone();
request
.workdir_attachment_requests
.push(WorkerSpawnWorkingDirectoryAttachmentRequest {
alias: workdir::WorkdirAttachmentAlias::new("repo").unwrap(),
working_directory: WorkerSpawnWorkingDirectoryRequest {
repository_key: "repo".into(),
selector: None,
},
});
requests.push(request);
for request in requests {
assert!(seed_fixed_worker(&store, seed(&request)).is_err());
}
assert!(
store
.get_worker_registry(WORKSPACE, &worker())
.unwrap()
.is_none()
);
assert!(
store
.worker_resource_key(WORKSPACE, &worker())
.unwrap()
.is_none()
);
assert_eq!(
seed_fixed_worker(&store, seed(&base))
.unwrap()
.worker_id
.to_string(),
WORKER
);
}
#[test]
fn late_catalog_failure_rolls_back_reservation_and_resource_allocation() {
let store = bootstrap();
let request = request();
store
.with_conn(|conn| {
conn.execute_batch(
"CREATE TEMP TRIGGER fail_fixture_catalog BEFORE INSERT ON worker_registry
BEGIN SELECT RAISE(ABORT, 'injected catalog failure'); END",
)?;
Ok(())
})
.unwrap();
assert!(seed_fixed_worker(&store, seed(&request)).is_err());
assert!(
!store
.has_active_worker_create_reservation(WORKSPACE, &worker())
.unwrap()
);
assert!(
store
.worker_resource_key(WORKSPACE, &worker())
.unwrap()
.is_none()
);
store
.with_conn(|conn| {
conn.execute_batch("DROP TRIGGER fail_fixture_catalog")?;
Ok(())
})
.unwrap();
seed_fixed_worker(&store, seed(&request)).unwrap();
assert_eq!(
store
.worker_resource_key(WORKSPACE, &worker())
.unwrap()
.as_deref(),
Some("W-1")
);
}
#[test]
fn ordinary_creation_still_allocates_and_replays_without_catalog_insertion() {
let store = bootstrap();
let memory = store.get_workspace_memory_settings(WORKSPACE).unwrap();
let reserve = |key| {
store
.reserve_worker_create(WORKSPACE, RUNTIME, key, "fingerprint", None, &memory)
.unwrap()
};
let first = reserve("ordinary-one");
assert_eq!(first, reserve("ordinary-one"));
let second = reserve("ordinary-two");
assert_ne!(first.worker_id, second.worker_id);
assert_ne!(first.worker_id.to_string(), WORKER);
assert_eq!(
first.worker_id.as_uuid().get_version(),
Some(uuid::Version::SortRand)
);
let worker = RuntimeWorkerRef::new(RUNTIME, first.worker_id.to_string());
assert!(
store
.has_active_worker_create_reservation(WORKSPACE, &worker)
.unwrap()
);
assert!(
store
.get_worker_registry(WORKSPACE, &worker)
.unwrap()
.is_none()
);
assert!(
store
.reserve_worker_create(WORKSPACE, RUNTIME, "ordinary-one", "changed", None, &memory)
.is_err()
);
}
}