Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 68 additions & 25 deletions crates/socket-patch-cli/tests/e2e_bun_lockb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,22 @@ fn scan(project: &Path, server: &MockServer, mode: &str, extra: &[&str]) -> Valu
cli(project, &args)
}

/// How many patch-record views the mock API has served: a vendor eject
/// reads each hosted pin's record through this endpoint.
async fn record_views(server: &MockServer) -> usize {
server
.received_requests()
.await
.unwrap_or_default()
.iter()
.filter(|r| {
r.url
.path()
.starts_with(&format!("/v0/orgs/{ORG}/patches/view/"))
})
.count()
}

fn snapshot(root: &Path) -> BTreeMap<PathBuf, Vec<u8>> {
fn walk(root: &Path, dir: &Path, result: &mut BTreeMap<PathBuf, Vec<u8>>) {
for entry in std::fs::read_dir(dir).unwrap() {
Expand Down Expand Up @@ -899,17 +915,19 @@ async fn native_binary_hosted_vendored_takeover_roundtrip() {
);
std::fs::rename(&modules, project.join("node_modules")).unwrap();

// Hosted -> vendored: v5 restores a hosted pin's upstream entry before
// vendoring over it, re-resolving the registry record from the npm
// registry — which an OFFLINE takeover cannot do, so it is REFUSED (dry
// and wet alike, nothing written) with the checkout remedy. Online, the
// takeover rebuilds the binary registry record exactly and vendors over
// it; `vendor --revert` then gives back the original bytes. After that
// Hosted -> vendored: v5 ejects a hosted pin from its patch record and
// the npm registry's upstream entry, neither of which an OFFLINE run can
// fetch, so it is REFUSED up front (dry and wet alike, nothing written)
// with the re-run-online remedy and no request at all. Online, the eject
// reads the pin's record from the patch API and vendors it in place of
// the hosted entry, recording the registry record exactly;
// `vendor --revert` then gives back the original bytes. After that
// (equivalently, after `git checkout -- bun.lockb`) the offline vendor
// proceeds, with a truthful dry run and exact rerun state.
fixture.stage();
let uri = server.uri();
let before = snapshot(project);
let requests = server.received_requests().await.unwrap_or_default().len();
for extra in [&["--dry-run"][..], &[][..]] {
let mut args = vec!["vendor", "--offline", "--patch-server-url", &uri];
args.extend_from_slice(extra);
Expand All @@ -918,27 +936,26 @@ async fn native_binary_hosted_vendored_takeover_roundtrip() {
code, 1,
"vendor {extra:?} over a binary hosted pin: {refused}"
);
let failed = refused["events"]
.as_array()
.and_then(|events| {
events
.iter()
.find(|e| e["errorCode"] == "redirect_revert_failed")
})
.unwrap_or_else(|| panic!("expected redirect_revert_failed: {refused}"));
assert_eq!(failed["purl"], PURL, "{refused}");
assert_eq!(
refused["error"]["code"], "offline_eject_unavailable",
"{refused}"
);
assert!(
failed["error"].as_str().is_some_and(|e| {
e.contains("cannot vendor over the live hosted pin")
&& e.contains("git checkout -- bun.lockb")
}),
refused["error"]["message"]
.as_str()
.is_some_and(|e| e.contains("re-run without --offline")),
"{refused}"
);
assert_eq!(
snapshot(project),
before,
"refused vendor {extra:?} wrote nothing"
);
assert_eq!(
server.received_requests().await.unwrap_or_default().len(),
requests,
"refused vendor {extra:?} made no request"
);
}
// The npm registry's version document for minimist@1.2.2 (the public
// registry's values, which the original lock pins), served locally.
Expand All @@ -960,10 +977,17 @@ async fn native_binary_hosted_vendored_takeover_roundtrip() {
"integrity": integrity}})))
.mount(&server)
.await;
let views = record_views(&server).await;
let taken_over = cli_env(
project,
&[
"vendor",
"--api-url",
&uri,
"--api-token",
"fake",
"--org",
ORG,
"--patch-server-url",
&uri,
"--vendor-source",
Expand All @@ -975,11 +999,17 @@ async fn native_binary_hosted_vendored_takeover_roundtrip() {
taken_over["summary"]["applied"], 1,
"online vendor over the binary hosted pin: {taken_over}"
);
// An eject vendors the pin's own patch record in place of the hosted
// entry; there is no separate takeover-revert step to report.
assert!(
taken_over["events"].as_array().is_some_and(|events| events
taken_over["events"].as_array().is_some_and(|events| !events
.iter()
.any(|e| e["errorCode"] == "vendor_takeover_reverted_redirect")),
"the takeover is reported: {taken_over}"
"the eject reports no takeover revert: {taken_over}"
);
assert!(
record_views(&server).await > views,
"the eject read the pin's record from the mock API: {taken_over}"
);
let vendor_lock = fixture.lock();
assert!(
Expand Down Expand Up @@ -1119,8 +1149,8 @@ async fn native_binary_hosted_vendored_takeover_roundtrip() {
/// tarball. The hosted scan wires that record for the regular install
/// (warning that the bundled copy stays unpatched); the pin it wrote must
/// then be listed and unwound like any other: `list` succeeds, the online
/// hosted → vendored takeover restores the registry record and vendors over
/// it, and `vendor --revert` gives back the pre-hosted bytes exactly.
/// hosted → vendored eject vendors the pin's patch record over it, and
/// `vendor --revert` gives back the pre-hosted bytes exactly.
#[tokio::test(flavor = "multi_thread")]
#[serial_test::serial]
async fn binary_shared_bundled_record_hosted_pin_is_managed() {
Expand Down Expand Up @@ -1172,10 +1202,17 @@ async fn binary_shared_bundled_record_hosted_pin_is_managed() {
.mount(&server)
.await;
fixture.stage();
let views = record_views(&server).await;
let taken_over = cli_env(
project,
&[
"vendor",
"--api-url",
&uri,
"--api-token",
"fake",
"--org",
ORG,
"--patch-server-url",
&uri,
"--vendor-source",
Expand All @@ -1187,11 +1224,17 @@ async fn binary_shared_bundled_record_hosted_pin_is_managed() {
taken_over["summary"]["applied"], 1,
"online vendor over the shared hosted pin: {taken_over}"
);
// An eject vendors the pin's own patch record in place of the hosted
// entry; there is no separate takeover-revert step to report.
assert!(
taken_over["events"].as_array().is_some_and(|events| events
taken_over["events"].as_array().is_some_and(|events| !events
.iter()
.any(|e| e["errorCode"] == "vendor_takeover_reverted_redirect")),
"the takeover is reported: {taken_over}"
"the eject reports no takeover revert: {taken_over}"
);
assert!(
record_views(&server).await > views,
"the eject read the pin's record from the mock API: {taken_over}"
);
assert!(
!taken_over
Expand Down
Loading