Skip to content

WIP: use ui_test dependency builder for test dependencies #14883

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
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
8 changes: 0 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,6 @@ itertools = "0.12"
pulldown-cmark = { version = "0.11", default-features = false, features = ["html"] }
askama = { version = "0.13", default-features = false, features = ["alloc", "config", "derive"] }

# UI test dependencies
if_chain = "1.0"
quote = "1.0.25"
syn = { version = "2.0", features = ["full"] }
futures = "0.3"
parking_lot = "0.12"
tokio = { version = "1", features = ["io-util"] }

[build-dependencies]
rustc_tools_util = { path = "rustc_tools_util", version = "0.4.2" }

Expand Down
15 changes: 15 additions & 0 deletions clippy_test_deps/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "clippy_test_deps"
version = "0.1.0"
edition = "2021"

# Add dependencies here to make them available in ui tests.

[dependencies]
if_chain = "1.0"
quote = "1.0.25"
syn = { version = "2.0", features = ["full"] }
futures = "0.3"
parking_lot = "0.12"
tokio = { version = "1", features = ["io-util"] }
itertools = "0.12"
1 change: 1 addition & 0 deletions clippy_test_deps/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fn main() {}
103 changes: 13 additions & 90 deletions tests/compile-test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,110 +16,25 @@ use test_utils::IS_RUSTC_TEST_SUITE;
use ui_test::custom_flags::Flag;
use ui_test::custom_flags::edition::Edition;
use ui_test::custom_flags::rustfix::RustfixMode;
use ui_test::dependencies::DependencyBuilder;
use ui_test::spanned::Spanned;
use ui_test::{Args, CommandBuilder, Config, Match, error_on_output_conflict, status_emitter};

use std::collections::{BTreeMap, HashMap};
use std::collections::HashMap;
use std::env::{self, set_var, var_os};
use std::ffi::{OsStr, OsString};
use std::fmt::Write;
use std::path::{Path, PathBuf};
use std::sync::mpsc::{Sender, channel};
use std::{fs, iter, thread};

// Test dependencies may need an `extern crate` here to ensure that they show up
// in the depinfo file (otherwise cargo thinks they are unused)
extern crate futures;
extern crate if_chain;
extern crate itertools;
extern crate parking_lot;
extern crate quote;
extern crate syn;
extern crate tokio;

mod test_utils;

/// All crates used in UI tests are listed here
static TEST_DEPENDENCIES: &[&str] = &[
"clippy_config",
"clippy_lints",
"clippy_utils",
"futures",
"if_chain",
"itertools",
"parking_lot",
"quote",
"regex",
"serde_derive",
"serde",
"syn",
"tokio",
];

/// Produces a string with an `--extern` flag for all UI test crate
/// dependencies.
///
/// The dependency files are located by parsing the depinfo file for this test
/// module. This assumes the `-Z binary-dep-depinfo` flag is enabled. All test
/// dependencies must be added to Cargo.toml at the project root. Test
/// dependencies that are not *directly* used by this test module require an
/// `extern crate` declaration.
fn extern_flags() -> Vec<String> {
let current_exe_depinfo = {
let mut path = env::current_exe().unwrap();
path.set_extension("d");
fs::read_to_string(path).unwrap()
};
let mut crates = BTreeMap::<&str, &str>::new();
for line in current_exe_depinfo.lines() {
// each dependency is expected to have a Makefile rule like `/path/to/crate-hash.rlib:`
let parse_name_path = || {
if line.starts_with(char::is_whitespace) {
return None;
}
let path_str = line.strip_suffix(':')?;
let path = Path::new(path_str);
if !matches!(path.extension()?.to_str()?, "rlib" | "so" | "dylib" | "dll") {
return None;
}
let (name, _hash) = path.file_stem()?.to_str()?.rsplit_once('-')?;
// the "lib" prefix is not present for dll files
let name = name.strip_prefix("lib").unwrap_or(name);
Some((name, path_str))
};
if let Some((name, path)) = parse_name_path()
&& TEST_DEPENDENCIES.contains(&name)
{
// A dependency may be listed twice if it is available in sysroot,
// and the sysroot dependencies are listed first. As of the writing,
// this only seems to apply to if_chain.
crates.insert(name, path);
}
}
let not_found: Vec<&str> = TEST_DEPENDENCIES
.iter()
.copied()
.filter(|n| !crates.contains_key(n))
.collect();
assert!(
not_found.is_empty(),
"dependencies not found in depinfo: {not_found:?}\n\
help: Make sure the `-Z binary-dep-depinfo` rust flag is enabled\n\
help: Try adding to dev-dependencies in Cargo.toml\n\
help: Be sure to also add `extern crate ...;` to tests/compile-test.rs",
);
crates
.into_iter()
.map(|(name, path)| format!("--extern={name}={path}"))
.collect()
}

// whether to run internal tests or not
const RUN_INTERNAL_TESTS: bool = cfg!(feature = "internal");

struct TestContext {
args: Args,
extern_flags: Vec<String>,
diagnostic_collector: Option<DiagnosticCollector>,
collector_thread: Option<thread::JoinHandle<()>>,
}
Expand All @@ -134,7 +49,6 @@ impl TestContext {
.unzip();
Self {
args,
extern_flags: extern_flags(),
diagnostic_collector,
collector_thread,
}
Expand All @@ -158,6 +72,17 @@ impl TestContext {
};
let defaults = config.comment_defaults.base();
defaults.set_custom("edition", Edition("2024".into()));
defaults.set_custom(
"dependencies",
DependencyBuilder {
program: CommandBuilder {
..CommandBuilder::cargo()
},
crate_manifest_path: Path::new("clippy_test_deps").join("Cargo.toml"),
build_std: None,
bless_lockfile: self.args.bless,
},
);
defaults.exit_status = None.into();
if mandatory_annotations {
defaults.require_annotations = Some(Spanned::dummy(true)).into();
Expand All @@ -182,12 +107,10 @@ impl TestContext {
"-Zui-testing",
"-Zdeduplicate-diagnostics=no",
"-Dwarnings",
&format!("-Ldependency={}", deps_path.display()),
]
.map(OsString::from),
);

config.program.args.extend(self.extern_flags.iter().map(OsString::from));
// Prevent rustc from creating `rustc-ice-*` files the console output is enough.
config.program.envs.push(("RUSTC_ICE".into(), Some("0".into())));

Expand Down
Loading