Skip to content

Commit f729331

Browse files
committed
Correctly import dependencies instead of exposing all transitive dependencies to tests
1 parent fcfe4d1 commit f729331

File tree

7 files changed

+183
-45
lines changed

7 files changed

+183
-45
lines changed

test-cargo-miri/Cargo.toml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,6 @@ issue_1760 = { path = "issue-1760" }
1818
issue_rust_86261 = { path = "issue-rust-86261" }
1919

2020
[dev-dependencies]
21-
rand = { version = "0.8", features = ["small_rng"] }
22-
getrandom_1 = { package = "getrandom", version = "0.1" }
23-
getrandom_2 = { package = "getrandom", version = "0.2" }
2421
serde_derive = "1.0" # not actually used, but exercises some unique code path (`--extern` .so file)
2522
page_size = "0.4.1"
2623

test-cargo-miri/tests/test.rs

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -20,28 +20,6 @@ fn does_not_work_on_miri() {
2020
assert!(&x as *const _ as usize % 4 < 4);
2121
}
2222

23-
// We also use this to test some external crates, that we cannot depend on in the compiletest suite.
24-
25-
#[test]
26-
fn entropy_rng() {
27-
// Test `getrandom` directly (in multiple different versions).
28-
let mut data = vec![0; 16];
29-
getrandom_1::getrandom(&mut data).unwrap();
30-
getrandom_2::getrandom(&mut data).unwrap();
31-
32-
// Try seeding with "real" entropy.
33-
let mut rng = SmallRng::from_entropy();
34-
let _val = rng.gen::<i32>();
35-
let _val = rng.gen::<isize>();
36-
let _val = rng.gen::<i128>();
37-
38-
// Also try per-thread RNG.
39-
let mut rng = rand::thread_rng();
40-
let _val = rng.gen::<i32>();
41-
let _val = rng.gen::<isize>();
42-
let _val = rng.gen::<i128>();
43-
}
44-
4523
#[test]
4624
fn cargo_env() {
4725
assert_eq!(env!("CARGO_PKG_NAME"), "cargo-miri-test");

test_dependencies/Cargo.lock

Lines changed: 68 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test_dependencies/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,8 @@ edition = "2021"
1212
tokio = { version = "1.0", features = ["full"] }
1313
libc = "0.2"
1414

15+
getrandom_1 = { package = "getrandom", version = "0.1" }
16+
getrandom_2 = { package = "getrandom", version = "0.2" }
17+
rand = { version = "0.8", features = ["small_rng"] }
18+
1519
[workspace]

tests/pass/random.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
use rand::{rngs::SmallRng, Rng, SeedableRng};
2+
3+
fn main() {
4+
// Test `getrandom` directly (in multiple different versions).
5+
let mut data = vec![0; 16];
6+
getrandom_1::getrandom(&mut data).unwrap();
7+
getrandom_2::getrandom(&mut data).unwrap();
8+
9+
// Try seeding with "real" entropy.
10+
let mut rng = SmallRng::from_entropy();
11+
let _val = rng.gen::<i32>();
12+
let _val = rng.gen::<isize>();
13+
let _val = rng.gen::<i128>();
14+
15+
// Also try per-thread RNG.
16+
let mut rng = rand::thread_rng();
17+
let _val = rng.gen::<i32>();
18+
let _val = rng.gen::<isize>();
19+
let _val = rng.gen::<i128>();
20+
}

ui_test/src/dependencies.rs

Lines changed: 87 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,49 @@
11
use color_eyre::eyre::{bail, Result};
22
use std::{
3+
collections::{HashMap, HashSet},
34
path::{Path, PathBuf},
45
process::Command,
56
};
67

78
use crate::Config;
89

10+
#[derive(Default, Debug)]
11+
pub struct Dependencies {
12+
/// All paths that must be imported with `-L dependency=`. This is for
13+
/// finding proc macros run on the host and dependencies for the target.
14+
pub import_paths: Vec<PathBuf>,
15+
/// The name as chosen in the `Cargo.toml` and its corresponding rmeta file.
16+
pub dependencies: Vec<(String, PathBuf)>,
17+
}
18+
919
/// Compiles dependencies and returns the crate names and corresponding rmeta files.
10-
pub fn build_dependencies(config: &Config) -> Result<Vec<(String, PathBuf)>> {
20+
pub fn build_dependencies(config: &Config) -> Result<Dependencies> {
1121
let manifest_path = match &config.dependencies_crate_manifest_path {
1222
Some(path) => path,
13-
None => return Ok(vec![]),
23+
None => return Ok(Default::default()),
1424
};
1525
let (program, args, envs): (&Path, &[_], &[_]) = match &config.dependency_builder {
1626
Some(db) => (&db.program, &db.args, &db.envs),
1727
None => (Path::new("cargo"), &[], &[]),
1828
};
1929
let mut build = Command::new(program);
20-
21-
// Avoid poisoning the target directory and causing unnecessary rebuilds.
22-
build.env_remove("RUSTFLAGS");
23-
24-
build.envs(envs.iter().map(|(k, v)| (k, v)));
2530
build.args(args);
2631
build.arg("run");
27-
if let Some(target) = &config.target {
28-
build.arg(format!("--target={target}"));
29-
}
32+
33+
// Reusable closure for setting up the environment both for artifact generation and `cargo_metadata`
34+
let setup_command = |cmd: &mut Command| {
35+
// Avoid poisoning the target directory and causing unnecessary rebuilds.
36+
cmd.env_remove("RUSTFLAGS");
37+
38+
cmd.envs(envs.iter().map(|(k, v)| (k, v)));
39+
if let Some(target) = &config.target {
40+
cmd.arg(format!("--target={target}"));
41+
}
42+
cmd.arg(format!("--manifest-path={}", manifest_path.display()));
43+
};
44+
45+
setup_command(&mut build);
3046
build
31-
.arg(format!("--manifest-path={}", manifest_path.display()))
3247
.arg("--target-dir=target/test_dependencies")
3348
.arg("--message-format=json")
3449
.arg("-Zunstable-options");
@@ -41,24 +56,79 @@ pub fn build_dependencies(config: &Config) -> Result<Vec<(String, PathBuf)>> {
4156
bail!("failed to compile dependencies:\nstderr:\n{stderr}\n\nstdout:{stdout}");
4257
}
4358

59+
// Collect all artifacts generated
4460
let output = output.stdout;
4561
let output = String::from_utf8(output)?;
46-
Ok(output
62+
let mut import_paths: HashSet<PathBuf> = HashSet::new();
63+
let mut artifacts: HashMap<_, _> = output
4764
.lines()
4865
.filter_map(|line| {
4966
let message = serde_json::from_str::<cargo_metadata::Message>(line).ok()?;
5067
if let cargo_metadata::Message::CompilerArtifact(artifact) = message {
68+
for filename in &artifact.filenames {
69+
import_paths.insert(filename.parent().unwrap().into());
70+
}
5171
let filename = artifact
5272
.filenames
5373
.into_iter()
5474
.find(|filename| filename.extension() == Some("rmeta"))?;
55-
Some((
56-
artifact.package_id.repr.split_once(' ').unwrap().0.to_string(),
57-
filename.into_std_path_buf(),
58-
))
75+
Some((artifact.package_id, filename.into_std_path_buf()))
5976
} else {
6077
None
6178
}
6279
})
63-
.collect())
80+
.collect();
81+
82+
// Check which crates are mentioned in the crate itself
83+
let mut metadata = cargo_metadata::MetadataCommand::new().cargo_command();
84+
setup_command(&mut metadata);
85+
let output = metadata.output()?;
86+
87+
if !output.status.success() {
88+
let stdout = String::from_utf8(output.stdout)?;
89+
let stderr = String::from_utf8(output.stderr)?;
90+
bail!("failed to run cargo-metadata:\nstderr:\n{stderr}\n\nstdout:{stdout}");
91+
}
92+
93+
let output = output.stdout;
94+
let output = String::from_utf8(output)?;
95+
96+
for line in output.lines() {
97+
if !line.starts_with('{') {
98+
continue;
99+
}
100+
let metadata: cargo_metadata::Metadata = serde_json::from_str(line)?;
101+
// Only take artifacts that are defined in the Cargo.toml
102+
103+
// First, find the root artifact
104+
let root = metadata
105+
.packages
106+
.iter()
107+
.find(|package| package.manifest_path.as_std_path() == manifest_path)
108+
.unwrap();
109+
110+
// Then go over all of its dependencies
111+
let dependencies = root
112+
.dependencies
113+
.iter()
114+
.map(|package| {
115+
// Get the id for the package matching the version requirement of the dep
116+
let id = &metadata
117+
.packages
118+
.iter()
119+
.find(|&dep| dep.name == package.name && package.req.matches(&dep.version))
120+
.expect("dependency does not exist")
121+
.id;
122+
// Return the name chosen in `Cargo.toml` and the path to the corresponding artifact
123+
(
124+
package.rename.clone().unwrap_or_else(|| package.name.clone()),
125+
artifacts.remove(id).expect("package without artifact"),
126+
)
127+
})
128+
.collect();
129+
let import_paths = import_paths.into_iter().collect();
130+
return Ok(Dependencies { dependencies, import_paths });
131+
}
132+
133+
bail!("no json found in cargo-metadata output")
64134
}

ui_test/src/lib.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,13 @@ pub fn run_tests(mut config: Config) -> Result<()> {
7575
let target = config.target.clone().unwrap_or_else(|| config.get_host());
7676

7777
let dependencies = build_dependencies(&config)?;
78-
for (name, dependency) in dependencies {
78+
for (name, dependency) in dependencies.dependencies {
7979
config.args.push("--extern".into());
8080
config.args.push(format!("{name}={}", dependency.display()).into());
81+
}
82+
for import_path in dependencies.import_paths {
8183
config.args.push("-L".into());
82-
config.args.push(dependency.parent().unwrap().display().to_string().into());
84+
config.args.push(import_path.into());
8385
}
8486
let config = config;
8587

0 commit comments

Comments
 (0)