Skip to content

Commit 1eb2d54

Browse files
committed
test(workspace): assert unsupported refresh rollback
1 parent 2fc2a33 commit 1eb2d54

1 file changed

Lines changed: 78 additions & 0 deletions

File tree

crates/localityd/tests/workspace_archive.rs

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ use locality_protocol::{
2626
canonical_writable_metadata_sha256,
2727
};
2828
use localityd::remote_truth::{ReplicaArchive, ReplicaArchiveEncoding};
29+
#[cfg(not(all(
30+
unix,
31+
any(target_vendor = "apple", target_os = "linux", target_os = "android")
32+
)))]
33+
use localityd::replica_materializer::ReplicaMaterializationError;
2934
use localityd::workspace_archive::{
3035
WorkspaceArchiveLimits, WorkspaceArchiveSink, validate_workspace_tar,
3136
};
@@ -1488,6 +1493,10 @@ fn marker_forged_after_journal_is_rejected_immediately_before_exchange() {
14881493
);
14891494
}
14901495

1496+
#[cfg(all(
1497+
unix,
1498+
any(target_vendor = "apple", target_os = "linux", target_os = "android")
1499+
))]
14911500
#[test]
14921501
fn marker_forged_after_exchange_is_rejected_before_cleanup() {
14931502
let fixture = fixture();
@@ -1532,6 +1541,75 @@ fn marker_forged_after_exchange_is_rejected_before_cleanup() {
15321541
);
15331542
}
15341543

1544+
#[cfg(not(all(
1545+
unix,
1546+
any(target_vendor = "apple", target_os = "linux", target_os = "android")
1547+
)))]
1548+
#[test]
1549+
fn post_exchange_marker_hook_fails_closed_when_exchange_is_unsupported() {
1550+
let fixture = fixture();
1551+
let contract = contract(&fixture);
1552+
let directory = TestDirectory::new("unsupported-forged-marker-before-cleanup");
1553+
materialize_workspace_archive_durable(
1554+
ReplicaArchive::new(
1555+
ReplicaArchiveEncoding::Identity,
1556+
Cursor::new(archive(&fixture, &contract.control)),
1557+
),
1558+
&directory.root(),
1559+
WorkspaceMaterializationLimits::default(),
1560+
&contract.session,
1561+
&contract.offer,
1562+
)
1563+
.expect("publish old generation");
1564+
let active_receipt = load_workspace_publication_receipt(&directory.root())
1565+
.expect("load active receipt")
1566+
.expect("active receipt");
1567+
let staged = stage_workspace_archive(
1568+
ReplicaArchive::new(
1569+
ReplicaArchiveEncoding::Identity,
1570+
Cursor::new(archive(&fixture, &contract.control)),
1571+
),
1572+
&directory.root(),
1573+
WorkspaceMaterializationLimits::default(),
1574+
&contract.session,
1575+
&contract.offer,
1576+
)
1577+
.expect("stage replacement");
1578+
let staging_path = staged.staging_path().to_path_buf();
1579+
let mut forge = ForgeMarkerAt {
1580+
checkpoint: WorkspacePublicationCheckpoint::ReceiptDurable,
1581+
generation: staging_path.clone(),
1582+
};
1583+
1584+
let error = publish_staged_workspace_with_hooks(staged, &directory.root(), &mut forge)
1585+
.expect_err("platform must fail closed before a post-exchange hook");
1586+
match error {
1587+
WorkspaceMaterializationError::Filesystem(ReplicaMaterializationError::Publish(source)) => {
1588+
assert_eq!(source.kind(), io::ErrorKind::Unsupported)
1589+
}
1590+
other => panic!("expected typed unsupported exchange error, got {other:?}"),
1591+
}
1592+
1593+
assert_eq!(
1594+
load_workspace_publication_receipt(&directory.root())
1595+
.expect("reload active receipt")
1596+
.expect("active receipt survives"),
1597+
active_receipt
1598+
);
1599+
assert_eq!(
1600+
fs::read(directory.root().join("Sales/README.md")).expect("active root survives"),
1601+
b"Public\n"
1602+
);
1603+
assert!(!staging_path.exists(), "recovery removes unused staging");
1604+
assert!(
1605+
!directory
1606+
.0
1607+
.join(".locality-Locality.publication.json")
1608+
.exists(),
1609+
"recovery clears the failed publication journal"
1610+
);
1611+
}
1612+
15351613
#[test]
15361614
fn reissued_same_profile_secret_recovers_but_rotated_key_fails_closed() {
15371615
let fixture = fixture();

0 commit comments

Comments
 (0)