use super::*;
#[test]
fn builds_control_authority_preflight_request() {
let plan = subtree_plan();
let request = plan.control_authority_preflight_request();
assert_eq!(request.plan_id, "plan-001");
assert_eq!(request.run_id, "run-001");
assert_eq!(request.root_canister_id, ROOT);
assert!(request.requires_root_controller);
assert_eq!(request.targets.len(), 1);
assert_eq!(request.targets[0].canister_id, APP);
assert_eq!(request.targets[0].role.as_deref(), Some("app"));
assert_eq!(request.targets[0].declared_authority, proven_root_control());
}
#[test]
fn builds_snapshot_read_authority_preflight_request() {
let plan = subtree_plan();
let request = plan.snapshot_read_authority_preflight_request();
assert_eq!(request.plan_id, "plan-001");
assert_eq!(request.run_id, "run-001");
assert_eq!(request.root_canister_id, ROOT);
assert_eq!(request.targets.len(), 1);
assert_eq!(request.targets[0].canister_id, APP);
assert_eq!(request.targets[0].role.as_deref(), Some("app"));
assert_eq!(request.targets[0].declared_authority, proven_root_read());
}
#[test]
fn builds_topology_preflight_request() {
let plan = subtree_plan();
let request = plan.topology_preflight_request();
assert_eq!(request.plan_id, "plan-001");
assert_eq!(request.run_id, "run-001");
assert_eq!(request.selected_subtree_root.as_deref(), Some(APP));
assert_eq!(request.selected_scope_kind, BackupScopeKind::Subtree);
assert_eq!(
request.topology_hash_before_quiesce,
plan.topology_hash_before_quiesce
);
assert_eq!(request.targets.len(), 1);
assert_eq!(request.targets[0].canister_id, APP);
assert_eq!(request.targets[0].parent_canister_id.as_deref(), Some(ROOT));
assert_eq!(request.targets[0].depth, 1);
}
#[test]
fn builds_quiescence_preflight_request() {
let plan = subtree_plan();
let request = plan.quiescence_preflight_request();
assert_eq!(request.plan_id, "plan-001");
assert_eq!(request.run_id, "run-001");
assert_eq!(request.selected_subtree_root.as_deref(), Some(APP));
assert_eq!(request.quiescence_policy, QuiescencePolicy::RootCoordinated);
assert_eq!(request.targets.len(), 1);
assert_eq!(request.targets[0].canister_id, APP);
assert_eq!(request.targets[0].role.as_deref(), Some("app"));
}
#[test]
fn preflight_requests_require_exact_current_optional_fields() {
let plan = subtree_plan();
let request = plan.control_authority_preflight_request();
for field in ["role", "parent_canister_id"] {
let mut value =
serde_json::to_value(&request.targets[0]).expect("serialize control target");
value
.as_object_mut()
.expect("control target object")
.remove(field);
let err = serde_json::from_value::<ControlAuthorityPreflightTarget>(value)
.expect_err("current control target field must be present");
assert!(err.is_data());
}
let request = plan.snapshot_read_authority_preflight_request();
for field in ["role", "parent_canister_id"] {
let mut value = serde_json::to_value(&request.targets[0]).expect("serialize read target");
value
.as_object_mut()
.expect("read target object")
.remove(field);
let err = serde_json::from_value::<SnapshotReadAuthorityPreflightTarget>(value)
.expect_err("current read target field must be present");
assert!(err.is_data());
}
let request = plan.topology_preflight_request();
let mut value = serde_json::to_value(&request).expect("serialize topology request");
value
.as_object_mut()
.expect("topology request object")
.remove("selected_subtree_root");
let err = serde_json::from_value::<TopologyPreflightRequest>(value)
.expect_err("current selected_subtree_root field must be present");
assert!(err.is_data());
let mut value = serde_json::to_value(&request.targets[0]).expect("serialize topology target");
value
.as_object_mut()
.expect("topology target object")
.remove("parent_canister_id");
let err = serde_json::from_value::<TopologyPreflightTarget>(value)
.expect_err("current parent_canister_id field must be present");
assert!(err.is_data());
let request = plan.quiescence_preflight_request();
let mut value = serde_json::to_value(&request).expect("serialize quiescence request");
value
.as_object_mut()
.expect("quiescence request object")
.remove("selected_subtree_root");
let err = serde_json::from_value::<QuiescencePreflightRequest>(value)
.expect_err("current selected_subtree_root field must be present");
assert!(err.is_data());
for field in ["role", "parent_canister_id"] {
let mut value =
serde_json::to_value(&request.targets[0]).expect("serialize quiescence target");
value
.as_object_mut()
.expect("quiescence target object")
.remove(field);
let err = serde_json::from_value::<QuiescencePreflightTarget>(value)
.expect_err("current quiescence target field must be present");
assert!(err.is_data());
}
}