Adds tests for source overlays.

This commit is contained in:
Joe Neeman 2024-06-10 14:12:05 -05:00
parent 04c963a993
commit ba9dd1ea2e
4 changed files with 326 additions and 1 deletions

View file

@ -877,6 +877,17 @@ impl Execs {
self
}
pub fn overlay_registry(&mut self, url: &Url, path: &str) -> &mut Self {
if let Some(ref mut p) = self.process_builder {
let env_value = format!("{}={}", url, path);
p.env(
"__CARGO_TEST_DEPENDENCY_CONFUSION_VULNERABILITY_DO_NOT_USE_THIS",
env_value,
);
}
self
}
pub fn enable_split_debuginfo_packed(&mut self) -> &mut Self {
self.env("CARGO_PROFILE_DEV_SPLIT_DEBUGINFO", "packed")
.env("CARGO_PROFILE_TEST_SPLIT_DEBUGINFO", "packed")

View file

@ -1649,7 +1649,12 @@ impl Package {
/// Returns the path to the compressed package file.
pub fn archive_dst(&self) -> PathBuf {
if self.local {
registry_path().join(format!("{}-{}.crate", self.name, self.vers))
let path = if self.alternative {
alt_registry_path()
} else {
registry_path()
};
path.join(format!("{}-{}.crate", self.name, self.vers))
} else if self.alternative {
alt_dl_path()
.join(&self.name)

View file

@ -152,6 +152,7 @@ mod publish_lockfile;
mod read_manifest;
mod registry;
mod registry_auth;
mod registry_overlay;
mod rename_deps;
mod replace;
mod required_features;

View file

@ -0,0 +1,308 @@
//! Tests for local-registry sources.
use cargo_test_support::project;
use cargo_test_support::registry::{Package, RegistryBuilder, TestRegistry};
fn setup() -> (TestRegistry, String) {
let alt = RegistryBuilder::new().alternative().build();
(
RegistryBuilder::new().http_index().build(),
alt.index_url()
.to_file_path()
.unwrap()
.into_os_string()
.into_string()
.unwrap(),
)
}
#[cargo_test]
fn overlay_hit() {
let (reg, alt_path) = setup();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
edition = "2015"
authors = []
[dependencies]
baz = "0.1.0"
"#,
)
.file("src/main.rs", "fn main() {}")
.build();
// baz is only in the local registry, but it gets found
Package::new("baz", "0.1.1")
.alternative(true)
.local(true)
.publish();
p.cargo("check")
.overlay_registry(&reg.index_url(), &alt_path)
.run();
}
#[cargo_test]
fn registry_version_wins() {
let (reg, alt_path) = setup();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
edition = "2015"
authors = []
[dependencies]
baz = "0.1.0"
"#,
)
.file("src/main.rs", "fn main() {}")
.build();
// The latest one is in the main registry, so it will get chosen.
Package::new("baz", "0.1.1").publish();
Package::new("baz", "0.1.0")
.alternative(true)
.local(true)
.publish();
p.cargo("check")
.overlay_registry(&reg.index_url(), &alt_path)
.with_stderr_data(
"\
[UPDATING] [..]
[LOCKING] 2 packages to latest compatible versions
[DOWNLOADING] crates ...
[DOWNLOADED] baz v0.1.1 (registry [..])
[CHECKING] baz v0.1.1
[CHECKING] foo v0.0.1 ([ROOT]/foo)
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
",
)
.run();
}
#[cargo_test]
fn overlay_version_wins() {
let (reg, alt_path) = setup();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
edition = "2015"
authors = []
[dependencies]
baz = "0.1.0"
"#,
)
.file("src/main.rs", "fn main() {}")
.build();
// The latest one is in the overlay registry, so it will get chosen.
Package::new("baz", "0.1.0").publish();
Package::new("baz", "0.1.1")
.alternative(true)
.local(true)
.publish();
p.cargo("check")
.overlay_registry(&reg.index_url(), &alt_path)
.with_stderr_data(
"\
[UPDATING] [..]
[LOCKING] 2 packages to latest compatible versions
[UNPACKING] baz v0.1.1 (registry [..])
[CHECKING] baz v0.1.1
[CHECKING] foo v0.0.1 ([ROOT]/foo)
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
",
)
.run();
}
#[cargo_test]
fn version_collision() {
let (reg, alt_path) = setup();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
edition = "2015"
authors = []
[dependencies]
baz = "0.1.0"
"#,
)
.file("src/main.rs", "fn main() {}")
.build();
// The one we want is in the main registry.
Package::new("baz", "0.1.1").publish();
Package::new("baz", "0.1.1")
.alternative(true)
.local(true)
.publish();
p.cargo("check")
.overlay_registry(&reg.index_url(), &alt_path)
.with_status(101)
.with_stderr_data(
"\
[UPDATING] [..]
[ERROR] failed to get `baz` [..]
Caused by:
failed to query replaced source registry `crates-io`
Caused by:
found a package in the remote registry and the local overlay: baz@0.1.1
",
)
.run();
}
#[cargo_test]
fn local_depends_on_old_registry_package() {
let (reg, alt_path) = setup();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
edition = "2015"
authors = []
[dependencies]
baz = "0.1.0"
"#,
)
.file("src/main.rs", "fn main() {}")
.build();
Package::new("baz", "0.0.1").publish();
// A new local package can depend on an older version in the registry.
Package::new("baz", "0.1.1")
.dep("baz", "=0.0.1")
.alternative(true)
.local(true)
.publish();
p.cargo("check")
.overlay_registry(&reg.index_url(), &alt_path)
.run();
}
#[cargo_test]
fn registry_dep_depends_on_new_local_package() {
let (reg, alt_path) = setup();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
edition = "2015"
authors = []
[dependencies]
registry-package = "0.1.0"
workspace-package = "0.0.1"
"#,
)
.file("src/main.rs", "fn main() {}")
.build();
Package::new("registry-package", "0.1.0")
.dep("workspace-package", "0.1.0")
.publish();
// The local overlay contains an updated version of workspace-package
Package::new("workspace-package", "0.1.1")
.alternative(true)
.local(true)
.publish();
// The registry contains older versions of workspace-package (one of which
// we depend on directly).
Package::new("workspace-package", "0.1.0").publish();
Package::new("workspace-package", "0.0.1").publish();
p.cargo("check")
.overlay_registry(&reg.index_url(), &alt_path)
.with_stderr_data(
"\
[UPDATING] [..]
[LOCKING] 4 packages to latest compatible versions
[ADDING] workspace-package v0.0.1 (latest: v0.1.1)
[DOWNLOADING] crates ...
[UNPACKING] [..]
[DOWNLOADED] [..]
[DOWNLOADED] [..]
[CHECKING] workspace-package v0.1.1
[CHECKING] workspace-package v0.0.1
[CHECKING] registry-package v0.1.0
[CHECKING] foo v0.0.1 [..]
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
",
)
.run();
}
// Test that we can overlay on top of alternate registries, not just crates-io.
// Since the test framework only supports a single alternate registry, we repurpose
// the dummy crates-io as the registry to overlay on top.
#[cargo_test]
fn alt_registry() {
let alt = RegistryBuilder::new().http_index().alternative().build();
let crates_io = RegistryBuilder::new().build();
let crates_io_path = crates_io
.index_url()
.to_file_path()
.unwrap()
.into_os_string()
.into_string()
.unwrap();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
edition = "2015"
authors = []
[dependencies]
baz = { version = "0.1.0", registry = "alternative" }
"#,
)
.file("src/main.rs", "fn main() {}")
.build();
// This package isn't used, but publishing it forces the creation of the registry index.
Package::new("bar", "0.0.1").local(true).publish();
Package::new("baz", "0.1.1").alternative(true).publish();
p.cargo("check")
.overlay_registry(&alt.index_url(), &crates_io_path)
.run();
}