mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-15 05:26:47 +00:00
compiletest: consistently use {Utf8Path,Utf8PathBuf}
Since compiletest already assumes UTF-8 paths and does not try to be robust against non-UTF-8 paths.
This commit is contained in:
parent
b203d40367
commit
e24b0c8e0a
@ -1,18 +1,17 @@
|
||||
use std::collections::{BTreeSet, HashMap, HashSet};
|
||||
use std::ffi::OsString;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
use std::str::FromStr;
|
||||
use std::sync::OnceLock;
|
||||
use std::{fmt, iter};
|
||||
|
||||
use build_helper::git::GitConfig;
|
||||
use camino::{Utf8Path, Utf8PathBuf};
|
||||
use semver::Version;
|
||||
use serde::de::{Deserialize, Deserializer, Error as _};
|
||||
|
||||
pub use self::Mode::*;
|
||||
use crate::executor::{ColorConfig, OutputFormat};
|
||||
use crate::util::{PathBufExt, add_dylib_path};
|
||||
use crate::util::{Utf8PathBufExt, add_dylib_path};
|
||||
|
||||
macro_rules! string_enum {
|
||||
($(#[$meta:meta])* $vis:vis enum $name:ident { $($variant:ident => $repr:expr,)* }) => {
|
||||
@ -183,25 +182,25 @@ pub struct Config {
|
||||
pub fail_fast: bool,
|
||||
|
||||
/// The library paths required for running the compiler.
|
||||
pub compile_lib_path: PathBuf,
|
||||
pub compile_lib_path: Utf8PathBuf,
|
||||
|
||||
/// The library paths required for running compiled programs.
|
||||
pub run_lib_path: PathBuf,
|
||||
pub run_lib_path: Utf8PathBuf,
|
||||
|
||||
/// The rustc executable.
|
||||
pub rustc_path: PathBuf,
|
||||
pub rustc_path: Utf8PathBuf,
|
||||
|
||||
/// The cargo executable.
|
||||
pub cargo_path: Option<PathBuf>,
|
||||
pub cargo_path: Option<Utf8PathBuf>,
|
||||
|
||||
/// Rustc executable used to compile run-make recipes.
|
||||
pub stage0_rustc_path: Option<PathBuf>,
|
||||
pub stage0_rustc_path: Option<Utf8PathBuf>,
|
||||
|
||||
/// The rustdoc executable.
|
||||
pub rustdoc_path: Option<PathBuf>,
|
||||
pub rustdoc_path: Option<Utf8PathBuf>,
|
||||
|
||||
/// The coverage-dump executable.
|
||||
pub coverage_dump_path: Option<PathBuf>,
|
||||
pub coverage_dump_path: Option<Utf8PathBuf>,
|
||||
|
||||
/// The Python executable to use for LLDB and htmldocck.
|
||||
pub python: String,
|
||||
@ -213,27 +212,27 @@ pub struct Config {
|
||||
pub jsondoclint_path: Option<String>,
|
||||
|
||||
/// The LLVM `FileCheck` binary path.
|
||||
pub llvm_filecheck: Option<PathBuf>,
|
||||
pub llvm_filecheck: Option<Utf8PathBuf>,
|
||||
|
||||
/// Path to LLVM's bin directory.
|
||||
pub llvm_bin_dir: Option<PathBuf>,
|
||||
pub llvm_bin_dir: Option<Utf8PathBuf>,
|
||||
|
||||
/// The path to the Clang executable to run Clang-based tests with. If
|
||||
/// `None` then these tests will be ignored.
|
||||
pub run_clang_based_tests_with: Option<String>,
|
||||
|
||||
/// The directory containing the sources.
|
||||
pub src_root: PathBuf,
|
||||
pub src_root: Utf8PathBuf,
|
||||
/// The directory containing the test suite sources. Must be a subdirectory of `src_root`.
|
||||
pub src_test_suite_root: PathBuf,
|
||||
pub src_test_suite_root: Utf8PathBuf,
|
||||
|
||||
/// Root build directory (e.g. `build/`).
|
||||
pub build_root: PathBuf,
|
||||
pub build_root: Utf8PathBuf,
|
||||
/// Test suite specific build directory (e.g. `build/host/test/ui/`).
|
||||
pub build_test_suite_root: PathBuf,
|
||||
pub build_test_suite_root: Utf8PathBuf,
|
||||
|
||||
/// The directory containing the compiler sysroot
|
||||
pub sysroot_base: PathBuf,
|
||||
pub sysroot_base: Utf8PathBuf,
|
||||
|
||||
/// The number of the stage under test.
|
||||
pub stage: u32,
|
||||
@ -301,7 +300,7 @@ pub struct Config {
|
||||
pub host: String,
|
||||
|
||||
/// Path to / name of the Microsoft Console Debugger (CDB) executable
|
||||
pub cdb: Option<OsString>,
|
||||
pub cdb: Option<Utf8PathBuf>,
|
||||
|
||||
/// Version of CDB
|
||||
pub cdb_version: Option<[u16; 4]>,
|
||||
@ -322,7 +321,7 @@ pub struct Config {
|
||||
pub system_llvm: bool,
|
||||
|
||||
/// Path to the android tools
|
||||
pub android_cross_path: PathBuf,
|
||||
pub android_cross_path: Utf8PathBuf,
|
||||
|
||||
/// Extra parameter to run adb on arm-linux-androideabi
|
||||
pub adb_path: String,
|
||||
@ -346,7 +345,7 @@ pub struct Config {
|
||||
pub color: ColorConfig,
|
||||
|
||||
/// where to find the remote test client process, if we're using it
|
||||
pub remote_test_client: Option<PathBuf>,
|
||||
pub remote_test_client: Option<Utf8PathBuf>,
|
||||
|
||||
/// mode describing what file the actual ui output will be compared to
|
||||
pub compare_mode: Option<CompareMode>,
|
||||
@ -414,7 +413,7 @@ pub struct Config {
|
||||
/// Path to minicore aux library, used for `no_core` tests that need `core` stubs in
|
||||
/// cross-compilation scenarios that do not otherwise want/need to `-Zbuild-std`. Used in e.g.
|
||||
/// ABI tests.
|
||||
pub minicore_path: PathBuf,
|
||||
pub minicore_path: Utf8PathBuf,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
@ -804,8 +803,8 @@ fn serde_parse_u32<'de, D: Deserializer<'de>>(deserializer: D) -> Result<u32, D:
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TestPaths {
|
||||
pub file: PathBuf, // e.g., compile-test/foo/bar/baz.rs
|
||||
pub relative_dir: PathBuf, // e.g., foo/bar
|
||||
pub file: Utf8PathBuf, // e.g., compile-test/foo/bar/baz.rs
|
||||
pub relative_dir: Utf8PathBuf, // e.g., foo/bar
|
||||
}
|
||||
|
||||
/// Used by `ui` tests to generate things like `foo.stderr` from `foo.rs`.
|
||||
@ -814,7 +813,7 @@ pub fn expected_output_path(
|
||||
revision: Option<&str>,
|
||||
compare_mode: &Option<CompareMode>,
|
||||
kind: &str,
|
||||
) -> PathBuf {
|
||||
) -> Utf8PathBuf {
|
||||
assert!(UI_EXTENSIONS.contains(&kind));
|
||||
let mut parts = Vec::new();
|
||||
|
||||
@ -865,7 +864,7 @@ pub const UI_COVERAGE_MAP: &str = "cov-map";
|
||||
/// ```
|
||||
///
|
||||
/// This is created early when tests are collected to avoid race conditions.
|
||||
pub fn output_relative_path(config: &Config, relative_dir: &Path) -> PathBuf {
|
||||
pub fn output_relative_path(config: &Config, relative_dir: &Utf8Path) -> Utf8PathBuf {
|
||||
config.build_test_suite_root.join(relative_dir)
|
||||
}
|
||||
|
||||
@ -874,10 +873,10 @@ pub fn output_testname_unique(
|
||||
config: &Config,
|
||||
testpaths: &TestPaths,
|
||||
revision: Option<&str>,
|
||||
) -> PathBuf {
|
||||
) -> Utf8PathBuf {
|
||||
let mode = config.compare_mode.as_ref().map_or("", |m| m.to_str());
|
||||
let debugger = config.debugger.as_ref().map_or("", |m| m.to_str());
|
||||
PathBuf::from(&testpaths.file.file_stem().unwrap())
|
||||
Utf8PathBuf::from(&testpaths.file.file_stem().unwrap())
|
||||
.with_extra_extension(config.mode.output_dir_disambiguator())
|
||||
.with_extra_extension(revision.unwrap_or(""))
|
||||
.with_extra_extension(mode)
|
||||
@ -887,7 +886,11 @@ pub fn output_testname_unique(
|
||||
/// Absolute path to the directory where all output for the given
|
||||
/// test/revision should reside. Example:
|
||||
/// /path/to/build/host-tuple/test/ui/relative/testname.revision.mode/
|
||||
pub fn output_base_dir(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> PathBuf {
|
||||
pub fn output_base_dir(
|
||||
config: &Config,
|
||||
testpaths: &TestPaths,
|
||||
revision: Option<&str>,
|
||||
) -> Utf8PathBuf {
|
||||
output_relative_path(config, &testpaths.relative_dir)
|
||||
.join(output_testname_unique(config, testpaths, revision))
|
||||
}
|
||||
@ -895,12 +898,20 @@ pub fn output_base_dir(config: &Config, testpaths: &TestPaths, revision: Option<
|
||||
/// Absolute path to the base filename used as output for the given
|
||||
/// test/revision. Example:
|
||||
/// /path/to/build/host-tuple/test/ui/relative/testname.revision.mode/testname
|
||||
pub fn output_base_name(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> PathBuf {
|
||||
pub fn output_base_name(
|
||||
config: &Config,
|
||||
testpaths: &TestPaths,
|
||||
revision: Option<&str>,
|
||||
) -> Utf8PathBuf {
|
||||
output_base_dir(config, testpaths, revision).join(testpaths.file.file_stem().unwrap())
|
||||
}
|
||||
|
||||
/// Absolute path to the directory to use for incremental compilation. Example:
|
||||
/// /path/to/build/host-tuple/test/ui/relative/testname.mode/testname.inc
|
||||
pub fn incremental_dir(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> PathBuf {
|
||||
pub fn incremental_dir(
|
||||
config: &Config,
|
||||
testpaths: &TestPaths,
|
||||
revision: Option<&str>,
|
||||
) -> Utf8PathBuf {
|
||||
output_base_name(config, testpaths, revision).with_extension("inc")
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
use std::collections::VecDeque;
|
||||
use std::fs::{File, FileType};
|
||||
use std::path::Path;
|
||||
|
||||
use camino::Utf8Path;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum DiffLine {
|
||||
@ -112,8 +113,8 @@ pub(crate) fn write_diff(expected: &str, actual: &str, context_size: usize) -> S
|
||||
/// Returns whether any data was actually written.
|
||||
pub(crate) fn write_filtered_diff<Filter>(
|
||||
diff_filename: &str,
|
||||
out_dir: &Path,
|
||||
compare_dir: &Path,
|
||||
out_dir: &Utf8Path,
|
||||
compare_dir: &Utf8Path,
|
||||
verbose: bool,
|
||||
filter: Filter,
|
||||
) -> bool
|
||||
@ -123,19 +124,21 @@ where
|
||||
use std::io::{Read, Write};
|
||||
let mut diff_output = File::create(diff_filename).unwrap();
|
||||
let mut wrote_data = false;
|
||||
for entry in walkdir::WalkDir::new(out_dir) {
|
||||
for entry in walkdir::WalkDir::new(out_dir.as_std_path()) {
|
||||
let entry = entry.expect("failed to read file");
|
||||
let extension = entry.path().extension().and_then(|p| p.to_str());
|
||||
if filter(entry.file_type(), extension) {
|
||||
let expected_path = compare_dir.join(entry.path().strip_prefix(&out_dir).unwrap());
|
||||
let expected_path = compare_dir
|
||||
.as_std_path()
|
||||
.join(entry.path().strip_prefix(&out_dir.as_std_path()).unwrap());
|
||||
let expected = if let Ok(s) = std::fs::read(&expected_path) { s } else { continue };
|
||||
let actual_path = entry.path();
|
||||
let actual = std::fs::read(&actual_path).unwrap();
|
||||
let diff = unified_diff::diff(
|
||||
&expected,
|
||||
&expected_path.to_string_lossy(),
|
||||
&expected_path.to_str().unwrap(),
|
||||
&actual,
|
||||
&actual_path.to_string_lossy(),
|
||||
&actual_path.to_str().unwrap(),
|
||||
3,
|
||||
);
|
||||
wrote_data |= !diff.is_empty();
|
||||
|
@ -1,9 +1,9 @@
|
||||
use std::env;
|
||||
use std::ffi::OsString;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
use std::sync::Arc;
|
||||
|
||||
use camino::{Utf8Path, Utf8PathBuf};
|
||||
|
||||
use crate::common::{Config, Debugger};
|
||||
|
||||
pub(crate) fn configure_cdb(config: &Config) -> Option<Arc<Config>> {
|
||||
@ -78,12 +78,15 @@ fn is_pc_windows_msvc_target(target: &str) -> bool {
|
||||
target.ends_with("-pc-windows-msvc")
|
||||
}
|
||||
|
||||
fn find_cdb(target: &str) -> Option<OsString> {
|
||||
fn find_cdb(target: &str) -> Option<Utf8PathBuf> {
|
||||
if !(cfg!(windows) && is_pc_windows_msvc_target(target)) {
|
||||
return None;
|
||||
}
|
||||
|
||||
let pf86 = env::var_os("ProgramFiles(x86)").or_else(|| env::var_os("ProgramFiles"))?;
|
||||
let pf86 = Utf8PathBuf::from_path_buf(
|
||||
env::var_os("ProgramFiles(x86)").or_else(|| env::var_os("ProgramFiles"))?.into(),
|
||||
)
|
||||
.unwrap();
|
||||
let cdb_arch = if cfg!(target_arch = "x86") {
|
||||
"x86"
|
||||
} else if cfg!(target_arch = "x86_64") {
|
||||
@ -96,8 +99,7 @@ fn find_cdb(target: &str) -> Option<OsString> {
|
||||
return None; // No compatible CDB.exe in the Windows 10 SDK
|
||||
};
|
||||
|
||||
let mut path = PathBuf::new();
|
||||
path.push(pf86);
|
||||
let mut path = pf86;
|
||||
path.push(r"Windows Kits\10\Debuggers"); // We could check 8.1 etc. too?
|
||||
path.push(cdb_arch);
|
||||
path.push(r"cdb.exe");
|
||||
@ -106,15 +108,15 @@ fn find_cdb(target: &str) -> Option<OsString> {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(path.into_os_string())
|
||||
Some(path)
|
||||
}
|
||||
|
||||
/// Returns Path to CDB
|
||||
pub(crate) fn analyze_cdb(
|
||||
cdb: Option<String>,
|
||||
target: &str,
|
||||
) -> (Option<OsString>, Option<[u16; 4]>) {
|
||||
let cdb = cdb.map(OsString::from).or_else(|| find_cdb(target));
|
||||
) -> (Option<Utf8PathBuf>, Option<[u16; 4]>) {
|
||||
let cdb = cdb.map(Utf8PathBuf::from).or_else(|| find_cdb(target));
|
||||
|
||||
let mut version = None;
|
||||
if let Some(cdb) = cdb.as_ref() {
|
||||
@ -143,7 +145,7 @@ pub(crate) fn extract_cdb_version(full_version_line: &str) -> Option<[u16; 4]> {
|
||||
pub(crate) fn analyze_gdb(
|
||||
gdb: Option<String>,
|
||||
target: &str,
|
||||
android_cross_path: &Path,
|
||||
android_cross_path: &Utf8Path,
|
||||
) -> (Option<String>, Option<u32>) {
|
||||
#[cfg(not(windows))]
|
||||
const GDB_FALLBACK: &str = "gdb";
|
||||
@ -152,10 +154,7 @@ pub(crate) fn analyze_gdb(
|
||||
|
||||
let fallback_gdb = || {
|
||||
if is_android_gdb_target(target) {
|
||||
let mut gdb_path = match android_cross_path.to_str() {
|
||||
Some(x) => x.to_owned(),
|
||||
None => panic!("cannot find android cross path"),
|
||||
};
|
||||
let mut gdb_path = android_cross_path.to_string();
|
||||
gdb_path.push_str("/bin/gdb");
|
||||
gdb_path
|
||||
} else {
|
||||
|
@ -2,9 +2,9 @@ use std::fmt;
|
||||
use std::fs::File;
|
||||
use std::io::BufReader;
|
||||
use std::io::prelude::*;
|
||||
use std::path::Path;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
use camino::Utf8Path;
|
||||
use regex::Regex;
|
||||
use tracing::*;
|
||||
|
||||
@ -102,8 +102,8 @@ impl Error {
|
||||
///
|
||||
/// If revision is not None, then we look
|
||||
/// for `//[X]~` instead, where `X` is the current revision.
|
||||
pub fn load_errors(testfile: &Path, revision: Option<&str>) -> Vec<Error> {
|
||||
let rdr = BufReader::new(File::open(testfile).unwrap());
|
||||
pub fn load_errors(testfile: &Utf8Path, revision: Option<&str>) -> Vec<Error> {
|
||||
let rdr = BufReader::new(File::open(testfile.as_std_path()).unwrap());
|
||||
|
||||
// `last_nonfollow_error` tracks the most recently seen
|
||||
// line with an error template that did not use the
|
||||
|
@ -3,9 +3,9 @@ use std::env;
|
||||
use std::fs::File;
|
||||
use std::io::BufReader;
|
||||
use std::io::prelude::*;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
|
||||
use camino::{Utf8Path, Utf8PathBuf};
|
||||
use semver::Version;
|
||||
use tracing::*;
|
||||
|
||||
@ -45,12 +45,12 @@ pub struct EarlyProps {
|
||||
}
|
||||
|
||||
impl EarlyProps {
|
||||
pub fn from_file(config: &Config, testfile: &Path) -> Self {
|
||||
let file = File::open(testfile).expect("open test file to parse earlyprops");
|
||||
pub fn from_file(config: &Config, testfile: &Utf8Path) -> Self {
|
||||
let file = File::open(testfile.as_std_path()).expect("open test file to parse earlyprops");
|
||||
Self::from_reader(config, testfile, file)
|
||||
}
|
||||
|
||||
pub fn from_reader<R: Read>(config: &Config, testfile: &Path, rdr: R) -> Self {
|
||||
pub fn from_reader<R: Read>(config: &Config, testfile: &Utf8Path, rdr: R) -> Self {
|
||||
let mut props = EarlyProps::default();
|
||||
let mut poisoned = false;
|
||||
iter_header(
|
||||
@ -66,7 +66,7 @@ impl EarlyProps {
|
||||
);
|
||||
|
||||
if poisoned {
|
||||
eprintln!("errors encountered during EarlyProps parsing: {}", testfile.display());
|
||||
eprintln!("errors encountered during EarlyProps parsing: {}", testfile);
|
||||
panic!("errors encountered during EarlyProps parsing");
|
||||
}
|
||||
|
||||
@ -88,7 +88,7 @@ pub struct TestProps {
|
||||
pub doc_flags: Vec<String>,
|
||||
// If present, the name of a file that this test should match when
|
||||
// pretty-printed
|
||||
pub pp_exact: Option<PathBuf>,
|
||||
pub pp_exact: Option<Utf8PathBuf>,
|
||||
/// Auxiliary crates that should be built and made available to this test.
|
||||
pub(crate) aux: AuxProps,
|
||||
// Environment settings to use for compiling
|
||||
@ -134,7 +134,7 @@ pub struct TestProps {
|
||||
// not set by end-users; rather it is set by the incremental
|
||||
// testing harness and used when generating compilation
|
||||
// arguments. (In particular, it propagates to the aux-builds.)
|
||||
pub incremental_dir: Option<PathBuf>,
|
||||
pub incremental_dir: Option<Utf8PathBuf>,
|
||||
// If `true`, this test will use incremental compilation.
|
||||
//
|
||||
// This can be set manually with the `incremental` header, or implicitly
|
||||
@ -311,7 +311,12 @@ impl TestProps {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_aux_file(&self, testfile: &Path, revision: Option<&str>, config: &Config) -> Self {
|
||||
pub fn from_aux_file(
|
||||
&self,
|
||||
testfile: &Utf8Path,
|
||||
revision: Option<&str>,
|
||||
config: &Config,
|
||||
) -> Self {
|
||||
let mut props = TestProps::new();
|
||||
|
||||
// copy over select properties to the aux build:
|
||||
@ -322,10 +327,10 @@ impl TestProps {
|
||||
props
|
||||
}
|
||||
|
||||
pub fn from_file(testfile: &Path, revision: Option<&str>, config: &Config) -> Self {
|
||||
pub fn from_file(testfile: &Utf8Path, revision: Option<&str>, config: &Config) -> Self {
|
||||
let mut props = TestProps::new();
|
||||
props.load_from(testfile, revision, config);
|
||||
props.exec_env.push(("RUSTC".to_string(), config.rustc_path.display().to_string()));
|
||||
props.exec_env.push(("RUSTC".to_string(), config.rustc_path.to_string()));
|
||||
|
||||
match (props.pass_mode, props.fail_mode) {
|
||||
(None, None) if config.mode == Mode::Ui => props.fail_mode = Some(FailMode::Check),
|
||||
@ -340,10 +345,10 @@ impl TestProps {
|
||||
/// tied to a particular revision `foo` (indicated by writing
|
||||
/// `//@[foo]`), then the property is ignored unless `test_revision` is
|
||||
/// `Some("foo")`.
|
||||
fn load_from(&mut self, testfile: &Path, test_revision: Option<&str>, config: &Config) {
|
||||
fn load_from(&mut self, testfile: &Utf8Path, test_revision: Option<&str>, config: &Config) {
|
||||
let mut has_edition = false;
|
||||
if !testfile.is_dir() {
|
||||
let file = File::open(testfile).unwrap();
|
||||
let file = File::open(testfile.as_std_path()).unwrap();
|
||||
|
||||
let mut poisoned = false;
|
||||
|
||||
@ -600,7 +605,7 @@ impl TestProps {
|
||||
);
|
||||
|
||||
if poisoned {
|
||||
eprintln!("errors encountered during TestProps parsing: {}", testfile.display());
|
||||
eprintln!("errors encountered during TestProps parsing: {}", testfile);
|
||||
panic!("errors encountered during TestProps parsing");
|
||||
}
|
||||
}
|
||||
@ -871,7 +876,7 @@ fn iter_header(
|
||||
mode: Mode,
|
||||
_suite: &str,
|
||||
poisoned: &mut bool,
|
||||
testfile: &Path,
|
||||
testfile: &Utf8Path,
|
||||
rdr: impl Read,
|
||||
it: &mut dyn FnMut(DirectiveLine<'_>),
|
||||
) {
|
||||
@ -923,9 +928,7 @@ fn iter_header(
|
||||
|
||||
eprintln!(
|
||||
"error: detected unknown compiletest test directive `{}` in {}:{}",
|
||||
directive_line.raw_directive,
|
||||
testfile.display(),
|
||||
line_number,
|
||||
directive_line.raw_directive, testfile, line_number,
|
||||
);
|
||||
|
||||
return;
|
||||
@ -937,10 +940,7 @@ fn iter_header(
|
||||
eprintln!(
|
||||
"error: detected trailing compiletest test directive `{}` in {}:{}\n \
|
||||
help: put the trailing directive in it's own line: `//@ {}`",
|
||||
trailing_directive,
|
||||
testfile.display(),
|
||||
line_number,
|
||||
trailing_directive,
|
||||
trailing_directive, testfile, line_number, trailing_directive,
|
||||
);
|
||||
|
||||
return;
|
||||
@ -952,7 +952,12 @@ fn iter_header(
|
||||
}
|
||||
|
||||
impl Config {
|
||||
fn parse_and_update_revisions(&self, testfile: &Path, line: &str, existing: &mut Vec<String>) {
|
||||
fn parse_and_update_revisions(
|
||||
&self,
|
||||
testfile: &Utf8Path,
|
||||
line: &str,
|
||||
existing: &mut Vec<String>,
|
||||
) {
|
||||
const FORBIDDEN_REVISION_NAMES: [&str; 2] = [
|
||||
// `//@ revisions: true false` Implying `--cfg=true` and `--cfg=false` makes it very
|
||||
// weird for the test, since if the test writer wants a cfg of the same revision name
|
||||
@ -965,26 +970,19 @@ impl Config {
|
||||
|
||||
if let Some(raw) = self.parse_name_value_directive(line, "revisions") {
|
||||
if self.mode == Mode::RunMake {
|
||||
panic!("`run-make` tests do not support revisions: {}", testfile.display());
|
||||
panic!("`run-make` tests do not support revisions: {}", testfile);
|
||||
}
|
||||
|
||||
let mut duplicates: HashSet<_> = existing.iter().cloned().collect();
|
||||
for revision in raw.split_whitespace() {
|
||||
if !duplicates.insert(revision.to_string()) {
|
||||
panic!(
|
||||
"duplicate revision: `{}` in line `{}`: {}",
|
||||
revision,
|
||||
raw,
|
||||
testfile.display()
|
||||
);
|
||||
panic!("duplicate revision: `{}` in line `{}`: {}", revision, raw, testfile);
|
||||
}
|
||||
|
||||
if FORBIDDEN_REVISION_NAMES.contains(&revision) {
|
||||
panic!(
|
||||
"revision name `{revision}` is not permitted: `{}` in line `{}`: {}",
|
||||
revision,
|
||||
raw,
|
||||
testfile.display()
|
||||
revision, raw, testfile
|
||||
);
|
||||
}
|
||||
|
||||
@ -995,8 +993,7 @@ impl Config {
|
||||
"revision name `{revision}` is not permitted in a test suite that uses \
|
||||
`FileCheck` annotations as it is confusing when used as custom `FileCheck` \
|
||||
prefix: `{revision}` in line `{}`: {}",
|
||||
raw,
|
||||
testfile.display()
|
||||
raw, testfile
|
||||
);
|
||||
}
|
||||
|
||||
@ -1016,11 +1013,11 @@ impl Config {
|
||||
(name.to_owned(), value.to_owned())
|
||||
}
|
||||
|
||||
fn parse_pp_exact(&self, line: &str, testfile: &Path) -> Option<PathBuf> {
|
||||
fn parse_pp_exact(&self, line: &str, testfile: &Utf8Path) -> Option<Utf8PathBuf> {
|
||||
if let Some(s) = self.parse_name_value_directive(line, "pp-exact") {
|
||||
Some(PathBuf::from(&s))
|
||||
Some(Utf8PathBuf::from(&s))
|
||||
} else if self.parse_name_directive(line, "pp-exact") {
|
||||
testfile.file_name().map(PathBuf::from)
|
||||
testfile.file_name().map(Utf8PathBuf::from)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -1126,20 +1123,19 @@ fn expand_variables(mut value: String, config: &Config) -> String {
|
||||
|
||||
if value.contains(CWD) {
|
||||
let cwd = env::current_dir().unwrap();
|
||||
value = value.replace(CWD, &cwd.to_string_lossy());
|
||||
value = value.replace(CWD, &cwd.to_str().unwrap());
|
||||
}
|
||||
|
||||
if value.contains(SRC_BASE) {
|
||||
value = value.replace(SRC_BASE, &config.src_test_suite_root.to_str().unwrap());
|
||||
value = value.replace(SRC_BASE, &config.src_test_suite_root.as_str());
|
||||
}
|
||||
|
||||
if value.contains(TEST_SUITE_BUILD_BASE) {
|
||||
value =
|
||||
value.replace(TEST_SUITE_BUILD_BASE, &config.build_test_suite_root.to_str().unwrap());
|
||||
value = value.replace(TEST_SUITE_BUILD_BASE, &config.build_test_suite_root.as_str());
|
||||
}
|
||||
|
||||
if value.contains(SYSROOT_BASE) {
|
||||
value = value.replace(SYSROOT_BASE, &config.sysroot_base.to_str().unwrap());
|
||||
value = value.replace(SYSROOT_BASE, &config.sysroot_base.as_str());
|
||||
}
|
||||
|
||||
if value.contains(TARGET_LINKER) {
|
||||
@ -1152,9 +1148,9 @@ fn expand_variables(mut value: String, config: &Config) -> String {
|
||||
|
||||
if value.contains(RUST_SRC_BASE) {
|
||||
let src_base = config.sysroot_base.join("lib/rustlib/src/rust");
|
||||
src_base.try_exists().expect(&*format!("{} should exists", src_base.display()));
|
||||
let src_base = src_base.read_link().unwrap_or(src_base);
|
||||
value = value.replace(RUST_SRC_BASE, &src_base.to_string_lossy());
|
||||
src_base.try_exists().expect(&*format!("{} should exists", src_base));
|
||||
let src_base = src_base.read_link_utf8().unwrap_or(src_base);
|
||||
value = value.replace(RUST_SRC_BASE, &src_base.as_str());
|
||||
}
|
||||
|
||||
value
|
||||
@ -1257,14 +1253,14 @@ pub fn llvm_has_libzstd(config: &Config) -> bool {
|
||||
// contains a path to that static lib, and that it exists.
|
||||
//
|
||||
// See compiler/rustc_llvm/build.rs for more details and similar expectations.
|
||||
fn is_zstd_in_config(llvm_bin_dir: &Path) -> Option<()> {
|
||||
fn is_zstd_in_config(llvm_bin_dir: &Utf8Path) -> Option<()> {
|
||||
let llvm_config_path = llvm_bin_dir.join("llvm-config");
|
||||
let output = Command::new(llvm_config_path).arg("--system-libs").output().ok()?;
|
||||
assert!(output.status.success(), "running llvm-config --system-libs failed");
|
||||
|
||||
let libs = String::from_utf8(output.stdout).ok()?;
|
||||
for lib in libs.split_whitespace() {
|
||||
if lib.ends_with("libzstd.a") && Path::new(lib).exists() {
|
||||
if lib.ends_with("libzstd.a") && Utf8Path::new(lib).exists() {
|
||||
return Some(());
|
||||
}
|
||||
}
|
||||
@ -1282,7 +1278,7 @@ pub fn llvm_has_libzstd(config: &Config) -> bool {
|
||||
// `lld` supports it. If not, an error will be emitted: "LLVM was not built with
|
||||
// LLVM_ENABLE_ZSTD or did not find zstd at build time".
|
||||
#[cfg(unix)]
|
||||
fn is_lld_built_with_zstd(llvm_bin_dir: &Path) -> Option<()> {
|
||||
fn is_lld_built_with_zstd(llvm_bin_dir: &Utf8Path) -> Option<()> {
|
||||
let lld_path = llvm_bin_dir.join("lld");
|
||||
if lld_path.exists() {
|
||||
// We can't call `lld` as-is, it expects to be invoked by a compiler driver using a
|
||||
@ -1318,7 +1314,7 @@ pub fn llvm_has_libzstd(config: &Config) -> bool {
|
||||
}
|
||||
|
||||
#[cfg(not(unix))]
|
||||
fn is_lld_built_with_zstd(_llvm_bin_dir: &Path) -> Option<()> {
|
||||
fn is_lld_built_with_zstd(_llvm_bin_dir: &Utf8Path) -> Option<()> {
|
||||
None
|
||||
}
|
||||
|
||||
@ -1385,7 +1381,7 @@ pub(crate) fn make_test_description<R: Read>(
|
||||
config: &Config,
|
||||
cache: &HeadersCache,
|
||||
name: String,
|
||||
path: &Path,
|
||||
path: &Utf8Path,
|
||||
src: R,
|
||||
test_revision: Option<&str>,
|
||||
poisoned: &mut bool,
|
||||
@ -1416,7 +1412,7 @@ pub(crate) fn make_test_description<R: Read>(
|
||||
ignore_message = Some(reason.into());
|
||||
}
|
||||
IgnoreDecision::Error { message } => {
|
||||
eprintln!("error: {}:{line_number}: {message}", path.display());
|
||||
eprintln!("error: {}:{line_number}: {message}", path);
|
||||
*poisoned = true;
|
||||
return;
|
||||
}
|
||||
@ -1446,7 +1442,7 @@ pub(crate) fn make_test_description<R: Read>(
|
||||
);
|
||||
|
||||
if local_poisoned {
|
||||
eprintln!("errors encountered when trying to make test description: {}", path.display());
|
||||
eprintln!("errors encountered when trying to make test description: {}", path);
|
||||
panic!("errors encountered when trying to make test description");
|
||||
}
|
||||
|
||||
@ -1555,7 +1551,7 @@ fn ignore_lldb(config: &Config, line: &str) -> IgnoreDecision {
|
||||
IgnoreDecision::Continue
|
||||
}
|
||||
|
||||
fn ignore_llvm(config: &Config, path: &Path, line: &str) -> IgnoreDecision {
|
||||
fn ignore_llvm(config: &Config, path: &Utf8Path, line: &str) -> IgnoreDecision {
|
||||
if let Some(needed_components) =
|
||||
config.parse_name_value_directive(line, "needs-llvm-components")
|
||||
{
|
||||
@ -1567,8 +1563,7 @@ fn ignore_llvm(config: &Config, path: &Path, line: &str) -> IgnoreDecision {
|
||||
if env::var_os("COMPILETEST_REQUIRE_ALL_LLVM_COMPONENTS").is_some() {
|
||||
panic!(
|
||||
"missing LLVM component {}, and COMPILETEST_REQUIRE_ALL_LLVM_COMPONENTS is set: {}",
|
||||
missing_component,
|
||||
path.display()
|
||||
missing_component, path
|
||||
);
|
||||
}
|
||||
return IgnoreDecision::Ignore {
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::io::Read;
|
||||
use std::path::Path;
|
||||
|
||||
use camino::Utf8Path;
|
||||
use semver::Version;
|
||||
|
||||
use super::{
|
||||
@ -13,7 +13,7 @@ use crate::executor::{CollectedTestDesc, ShouldPanic};
|
||||
fn make_test_description<R: Read>(
|
||||
config: &Config,
|
||||
name: String,
|
||||
path: &Path,
|
||||
path: &Utf8Path,
|
||||
src: R,
|
||||
revision: Option<&str>,
|
||||
) -> CollectedTestDesc {
|
||||
@ -230,12 +230,12 @@ fn cfg() -> ConfigBuilder {
|
||||
|
||||
fn parse_rs(config: &Config, contents: &str) -> EarlyProps {
|
||||
let bytes = contents.as_bytes();
|
||||
EarlyProps::from_reader(config, Path::new("a.rs"), bytes)
|
||||
EarlyProps::from_reader(config, Utf8Path::new("a.rs"), bytes)
|
||||
}
|
||||
|
||||
fn check_ignore(config: &Config, contents: &str) -> bool {
|
||||
let tn = String::new();
|
||||
let p = Path::new("a.rs");
|
||||
let p = Utf8Path::new("a.rs");
|
||||
let d = make_test_description(&config, tn, p, std::io::Cursor::new(contents), None);
|
||||
d.ignore
|
||||
}
|
||||
@ -244,7 +244,7 @@ fn check_ignore(config: &Config, contents: &str) -> bool {
|
||||
fn should_fail() {
|
||||
let config: Config = cfg().build();
|
||||
let tn = String::new();
|
||||
let p = Path::new("a.rs");
|
||||
let p = Utf8Path::new("a.rs");
|
||||
|
||||
let d = make_test_description(&config, tn.clone(), p, std::io::Cursor::new(""), None);
|
||||
assert_eq!(d.should_panic, ShouldPanic::No);
|
||||
@ -784,7 +784,7 @@ fn threads_support() {
|
||||
}
|
||||
}
|
||||
|
||||
fn run_path(poisoned: &mut bool, path: &Path, buf: &[u8]) {
|
||||
fn run_path(poisoned: &mut bool, path: &Utf8Path, buf: &[u8]) {
|
||||
let rdr = std::io::Cursor::new(&buf);
|
||||
iter_header(Mode::Ui, "ui", poisoned, path, rdr, &mut |_| {});
|
||||
}
|
||||
@ -794,7 +794,7 @@ fn test_unknown_directive_check() {
|
||||
let mut poisoned = false;
|
||||
run_path(
|
||||
&mut poisoned,
|
||||
Path::new("a.rs"),
|
||||
Utf8Path::new("a.rs"),
|
||||
include_bytes!("./test-auxillary/unknown_directive.rs"),
|
||||
);
|
||||
assert!(poisoned);
|
||||
@ -805,7 +805,7 @@ fn test_known_directive_check_no_error() {
|
||||
let mut poisoned = false;
|
||||
run_path(
|
||||
&mut poisoned,
|
||||
Path::new("a.rs"),
|
||||
Utf8Path::new("a.rs"),
|
||||
include_bytes!("./test-auxillary/known_directive.rs"),
|
||||
);
|
||||
assert!(!poisoned);
|
||||
@ -816,7 +816,7 @@ fn test_error_annotation_no_error() {
|
||||
let mut poisoned = false;
|
||||
run_path(
|
||||
&mut poisoned,
|
||||
Path::new("a.rs"),
|
||||
Utf8Path::new("a.rs"),
|
||||
include_bytes!("./test-auxillary/error_annotation.rs"),
|
||||
);
|
||||
assert!(!poisoned);
|
||||
@ -827,7 +827,7 @@ fn test_non_rs_unknown_directive_not_checked() {
|
||||
let mut poisoned = false;
|
||||
run_path(
|
||||
&mut poisoned,
|
||||
Path::new("a.Makefile"),
|
||||
Utf8Path::new("a.Makefile"),
|
||||
include_bytes!("./test-auxillary/not_rs.Makefile"),
|
||||
);
|
||||
assert!(!poisoned);
|
||||
@ -836,21 +836,21 @@ fn test_non_rs_unknown_directive_not_checked() {
|
||||
#[test]
|
||||
fn test_trailing_directive() {
|
||||
let mut poisoned = false;
|
||||
run_path(&mut poisoned, Path::new("a.rs"), b"//@ only-x86 only-arm");
|
||||
run_path(&mut poisoned, Utf8Path::new("a.rs"), b"//@ only-x86 only-arm");
|
||||
assert!(poisoned);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_trailing_directive_with_comment() {
|
||||
let mut poisoned = false;
|
||||
run_path(&mut poisoned, Path::new("a.rs"), b"//@ only-x86 only-arm with comment");
|
||||
run_path(&mut poisoned, Utf8Path::new("a.rs"), b"//@ only-x86 only-arm with comment");
|
||||
assert!(poisoned);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_not_trailing_directive() {
|
||||
let mut poisoned = false;
|
||||
run_path(&mut poisoned, Path::new("a.rs"), b"//@ revisions: incremental");
|
||||
run_path(&mut poisoned, Utf8Path::new("a.rs"), b"//@ revisions: incremental");
|
||||
assert!(!poisoned);
|
||||
}
|
||||
|
||||
|
@ -22,16 +22,15 @@ pub mod util;
|
||||
|
||||
use core::panic;
|
||||
use std::collections::HashSet;
|
||||
use std::ffi::OsString;
|
||||
use std::fmt::Write;
|
||||
use std::io::{self, ErrorKind};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::{Command, Stdio};
|
||||
use std::sync::{Arc, OnceLock};
|
||||
use std::time::SystemTime;
|
||||
use std::{env, fs, vec};
|
||||
|
||||
use build_helper::git::{get_git_modified_files, get_git_untracked_files};
|
||||
use camino::{Utf8Path, Utf8PathBuf};
|
||||
use getopts::Options;
|
||||
use tracing::*;
|
||||
use walkdir::WalkDir;
|
||||
@ -230,15 +229,19 @@ pub fn parse_config(args: Vec<String>) -> Config {
|
||||
panic!()
|
||||
}
|
||||
|
||||
fn opt_path(m: &getopts::Matches, nm: &str) -> PathBuf {
|
||||
match m.opt_str(nm) {
|
||||
Some(s) => PathBuf::from(&s),
|
||||
None => panic!("no option (=path) found for {}", nm),
|
||||
fn make_absolute(path: Utf8PathBuf) -> Utf8PathBuf {
|
||||
if path.is_relative() {
|
||||
Utf8PathBuf::try_from(env::current_dir().unwrap()).unwrap().join(path)
|
||||
} else {
|
||||
path
|
||||
}
|
||||
}
|
||||
|
||||
fn make_absolute(path: PathBuf) -> PathBuf {
|
||||
if path.is_relative() { env::current_dir().unwrap().join(path) } else { path }
|
||||
fn opt_path(m: &getopts::Matches, nm: &str) -> Utf8PathBuf {
|
||||
match m.opt_str(nm) {
|
||||
Some(s) => Utf8PathBuf::from(&s),
|
||||
None => panic!("no option (=path) found for {}", nm),
|
||||
}
|
||||
}
|
||||
|
||||
let target = opt_str2(matches.opt_str("target"));
|
||||
@ -279,12 +282,12 @@ pub fn parse_config(args: Vec<String>) -> Config {
|
||||
.free
|
||||
.iter()
|
||||
.map(|f| {
|
||||
let path = Path::new(f);
|
||||
let path = Utf8Path::new(f);
|
||||
let mut iter = path.iter().skip(1);
|
||||
|
||||
// We skip the test folder and check if the user passed `rmake.rs`.
|
||||
if iter.next().is_some_and(|s| s == "rmake.rs") && iter.next().is_none() {
|
||||
path.parent().unwrap().to_str().unwrap().to_string()
|
||||
path.parent().unwrap().to_string()
|
||||
} else {
|
||||
f.to_string()
|
||||
}
|
||||
@ -316,8 +319,8 @@ pub fn parse_config(args: Vec<String>) -> Config {
|
||||
assert!(
|
||||
src_test_suite_root.starts_with(&src_root),
|
||||
"`src-root` must be a parent of `src-test-suite-root`: `src-root`=`{}`, `src-test-suite-root` = `{}`",
|
||||
src_root.display(),
|
||||
src_test_suite_root.display()
|
||||
src_root,
|
||||
src_test_suite_root
|
||||
);
|
||||
|
||||
let build_root = opt_path(matches, "build-root");
|
||||
@ -332,16 +335,16 @@ pub fn parse_config(args: Vec<String>) -> Config {
|
||||
compile_lib_path: make_absolute(opt_path(matches, "compile-lib-path")),
|
||||
run_lib_path: make_absolute(opt_path(matches, "run-lib-path")),
|
||||
rustc_path: opt_path(matches, "rustc-path"),
|
||||
cargo_path: matches.opt_str("cargo-path").map(PathBuf::from),
|
||||
stage0_rustc_path: matches.opt_str("stage0-rustc-path").map(PathBuf::from),
|
||||
rustdoc_path: matches.opt_str("rustdoc-path").map(PathBuf::from),
|
||||
coverage_dump_path: matches.opt_str("coverage-dump-path").map(PathBuf::from),
|
||||
cargo_path: matches.opt_str("cargo-path").map(Utf8PathBuf::from),
|
||||
stage0_rustc_path: matches.opt_str("stage0-rustc-path").map(Utf8PathBuf::from),
|
||||
rustdoc_path: matches.opt_str("rustdoc-path").map(Utf8PathBuf::from),
|
||||
coverage_dump_path: matches.opt_str("coverage-dump-path").map(Utf8PathBuf::from),
|
||||
python: matches.opt_str("python").unwrap(),
|
||||
jsondocck_path: matches.opt_str("jsondocck-path"),
|
||||
jsondoclint_path: matches.opt_str("jsondoclint-path"),
|
||||
run_clang_based_tests_with: matches.opt_str("run-clang-based-tests-with"),
|
||||
llvm_filecheck: matches.opt_str("llvm-filecheck").map(PathBuf::from),
|
||||
llvm_bin_dir: matches.opt_str("llvm-bin-dir").map(PathBuf::from),
|
||||
llvm_filecheck: matches.opt_str("llvm-filecheck").map(Utf8PathBuf::from),
|
||||
llvm_bin_dir: matches.opt_str("llvm-bin-dir").map(Utf8PathBuf::from),
|
||||
|
||||
src_root,
|
||||
src_test_suite_root,
|
||||
@ -407,7 +410,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
|
||||
},
|
||||
only_modified: matches.opt_present("only-modified"),
|
||||
color,
|
||||
remote_test_client: matches.opt_str("remote-test-client").map(PathBuf::from),
|
||||
remote_test_client: matches.opt_str("remote-test-client").map(Utf8PathBuf::from),
|
||||
compare_mode,
|
||||
rustfix_coverage: matches.opt_present("rustfix-coverage"),
|
||||
has_html_tidy,
|
||||
@ -450,19 +453,19 @@ pub fn parse_config(args: Vec<String>) -> Config {
|
||||
pub fn log_config(config: &Config) {
|
||||
let c = config;
|
||||
logv(c, "configuration:".to_string());
|
||||
logv(c, format!("compile_lib_path: {:?}", config.compile_lib_path));
|
||||
logv(c, format!("run_lib_path: {:?}", config.run_lib_path));
|
||||
logv(c, format!("rustc_path: {:?}", config.rustc_path.display()));
|
||||
logv(c, format!("compile_lib_path: {}", config.compile_lib_path));
|
||||
logv(c, format!("run_lib_path: {}", config.run_lib_path));
|
||||
logv(c, format!("rustc_path: {}", config.rustc_path));
|
||||
logv(c, format!("cargo_path: {:?}", config.cargo_path));
|
||||
logv(c, format!("rustdoc_path: {:?}", config.rustdoc_path));
|
||||
|
||||
logv(c, format!("src_root: {}", config.src_root.display()));
|
||||
logv(c, format!("src_test_suite_root: {}", config.src_test_suite_root.display()));
|
||||
logv(c, format!("src_root: {}", config.src_root));
|
||||
logv(c, format!("src_test_suite_root: {}", config.src_test_suite_root));
|
||||
|
||||
logv(c, format!("build_root: {}", config.build_root.display()));
|
||||
logv(c, format!("build_test_suite_root: {}", config.build_test_suite_root.display()));
|
||||
logv(c, format!("build_root: {}", config.build_root));
|
||||
logv(c, format!("build_test_suite_root: {}", config.build_test_suite_root));
|
||||
|
||||
logv(c, format!("sysroot_base: {}", config.sysroot_base.display()));
|
||||
logv(c, format!("sysroot_base: {}", config.sysroot_base));
|
||||
|
||||
logv(c, format!("stage: {}", config.stage));
|
||||
logv(c, format!("stage_id: {}", config.stage_id));
|
||||
@ -480,16 +483,16 @@ pub fn log_config(config: &Config) {
|
||||
logv(c, format!("target-rustcflags: {:?}", config.target_rustcflags));
|
||||
logv(c, format!("target: {}", config.target));
|
||||
logv(c, format!("host: {}", config.host));
|
||||
logv(c, format!("android-cross-path: {:?}", config.android_cross_path.display()));
|
||||
logv(c, format!("adb_path: {:?}", config.adb_path));
|
||||
logv(c, format!("adb_test_dir: {:?}", config.adb_test_dir));
|
||||
logv(c, format!("android-cross-path: {}", config.android_cross_path));
|
||||
logv(c, format!("adb_path: {}", config.adb_path));
|
||||
logv(c, format!("adb_test_dir: {}", config.adb_test_dir));
|
||||
logv(c, format!("adb_device_status: {}", config.adb_device_status));
|
||||
logv(c, format!("ar: {}", config.ar));
|
||||
logv(c, format!("target-linker: {:?}", config.target_linker));
|
||||
logv(c, format!("host-linker: {:?}", config.host_linker));
|
||||
logv(c, format!("verbose: {}", config.verbose));
|
||||
logv(c, format!("format: {:?}", config.format));
|
||||
logv(c, format!("minicore_path: {:?}", config.minicore_path.display()));
|
||||
logv(c, format!("minicore_path: {}", config.minicore_path));
|
||||
logv(c, "\n".to_string());
|
||||
}
|
||||
|
||||
@ -517,7 +520,7 @@ pub fn run_tests(config: Arc<Config>) {
|
||||
coverage_file_path.push("rustfix_missing_coverage.txt");
|
||||
if coverage_file_path.exists() {
|
||||
if let Err(e) = fs::remove_file(&coverage_file_path) {
|
||||
panic!("Could not delete {} due to {}", coverage_file_path.display(), e)
|
||||
panic!("Could not delete {} due to {}", coverage_file_path, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -619,13 +622,13 @@ struct TestCollectorCx {
|
||||
config: Arc<Config>,
|
||||
cache: HeadersCache,
|
||||
common_inputs_stamp: Stamp,
|
||||
modified_tests: Vec<PathBuf>,
|
||||
modified_tests: Vec<Utf8PathBuf>,
|
||||
}
|
||||
|
||||
/// Mutable state used during test collection.
|
||||
struct TestCollector {
|
||||
tests: Vec<CollectedTest>,
|
||||
found_path_stems: HashSet<PathBuf>,
|
||||
found_path_stems: HashSet<Utf8PathBuf>,
|
||||
poisoned: bool,
|
||||
}
|
||||
|
||||
@ -635,14 +638,13 @@ struct TestCollector {
|
||||
/// regardless of whether any filters/tests were specified on the command-line,
|
||||
/// because filtering is handled later by libtest.
|
||||
pub(crate) fn collect_and_make_tests(config: Arc<Config>) -> Vec<CollectedTest> {
|
||||
debug!("making tests from {}", config.src_test_suite_root.display());
|
||||
debug!("making tests from {}", config.src_test_suite_root);
|
||||
let common_inputs_stamp = common_inputs_stamp(&config);
|
||||
let modified_tests =
|
||||
modified_tests(&config, &config.src_test_suite_root).unwrap_or_else(|err| {
|
||||
panic!(
|
||||
"modified_tests got error from dir: {}, error: {}",
|
||||
config.src_test_suite_root.display(),
|
||||
err
|
||||
config.src_test_suite_root, err
|
||||
)
|
||||
});
|
||||
let cache = HeadersCache::load(&config);
|
||||
@ -651,12 +653,9 @@ pub(crate) fn collect_and_make_tests(config: Arc<Config>) -> Vec<CollectedTest>
|
||||
let mut collector =
|
||||
TestCollector { tests: vec![], found_path_stems: HashSet::new(), poisoned: false };
|
||||
|
||||
collect_tests_from_dir(&cx, &mut collector, &cx.config.src_test_suite_root, Path::new(""))
|
||||
collect_tests_from_dir(&cx, &mut collector, &cx.config.src_test_suite_root, Utf8Path::new(""))
|
||||
.unwrap_or_else(|reason| {
|
||||
panic!(
|
||||
"Could not read tests from {}: {reason}",
|
||||
cx.config.src_test_suite_root.display()
|
||||
)
|
||||
panic!("Could not read tests from {}: {reason}", cx.config.src_test_suite_root)
|
||||
});
|
||||
|
||||
let TestCollector { tests, found_path_stems, poisoned } = collector;
|
||||
@ -725,24 +724,29 @@ fn common_inputs_stamp(config: &Config) -> Stamp {
|
||||
/// the `--only-modified` flag is in use.
|
||||
///
|
||||
/// (Might be inaccurate in some cases.)
|
||||
fn modified_tests(config: &Config, dir: &Path) -> Result<Vec<PathBuf>, String> {
|
||||
fn modified_tests(config: &Config, dir: &Utf8Path) -> Result<Vec<Utf8PathBuf>, String> {
|
||||
// If `--only-modified` wasn't passed, the list of modified tests won't be
|
||||
// used for anything, so avoid some work and just return an empty list.
|
||||
if !config.only_modified {
|
||||
return Ok(vec![]);
|
||||
}
|
||||
|
||||
let files =
|
||||
get_git_modified_files(&config.git_config(), Some(dir), &vec!["rs", "stderr", "fixed"])?;
|
||||
let files = get_git_modified_files(
|
||||
&config.git_config(),
|
||||
Some(dir.as_std_path()),
|
||||
&vec!["rs", "stderr", "fixed"],
|
||||
)?;
|
||||
// Add new test cases to the list, it will be convenient in daily development.
|
||||
let untracked_files = get_git_untracked_files(&config.git_config(), None)?.unwrap_or(vec![]);
|
||||
|
||||
let all_paths = [&files[..], &untracked_files[..]].concat();
|
||||
let full_paths = {
|
||||
let mut full_paths: Vec<PathBuf> = all_paths
|
||||
let mut full_paths: Vec<Utf8PathBuf> = all_paths
|
||||
.into_iter()
|
||||
.map(|f| PathBuf::from(f).with_extension("").with_extension("rs"))
|
||||
.filter_map(|f| if Path::new(&f).exists() { f.canonicalize().ok() } else { None })
|
||||
.map(|f| Utf8PathBuf::from(f).with_extension("").with_extension("rs"))
|
||||
.filter_map(
|
||||
|f| if Utf8Path::new(&f).exists() { f.canonicalize_utf8().ok() } else { None },
|
||||
)
|
||||
.collect();
|
||||
full_paths.dedup();
|
||||
full_paths.sort_unstable();
|
||||
@ -756,8 +760,8 @@ fn modified_tests(config: &Config, dir: &Path) -> Result<Vec<PathBuf>, String> {
|
||||
fn collect_tests_from_dir(
|
||||
cx: &TestCollectorCx,
|
||||
collector: &mut TestCollector,
|
||||
dir: &Path,
|
||||
relative_dir_path: &Path,
|
||||
dir: &Utf8Path,
|
||||
relative_dir_path: &Utf8Path,
|
||||
) -> io::Result<()> {
|
||||
// Ignore directories that contain a file named `compiletest-ignore-dir`.
|
||||
if dir.join("compiletest-ignore-dir").exists() {
|
||||
@ -790,16 +794,16 @@ fn collect_tests_from_dir(
|
||||
// subdirectories we find, except for `auxiliary` directories.
|
||||
// FIXME: this walks full tests tree, even if we have something to ignore
|
||||
// use walkdir/ignore like in tidy?
|
||||
for file in fs::read_dir(dir)? {
|
||||
for file in fs::read_dir(dir.as_std_path())? {
|
||||
let file = file?;
|
||||
let file_path = file.path();
|
||||
let file_name = file.file_name();
|
||||
let file_path = Utf8PathBuf::try_from(file.path()).unwrap();
|
||||
let file_name = file_path.file_name().unwrap();
|
||||
|
||||
if is_test(&file_name)
|
||||
if is_test(file_name)
|
||||
&& (!cx.config.only_modified || cx.modified_tests.contains(&file_path))
|
||||
{
|
||||
// We found a test file, so create the corresponding libtest structures.
|
||||
debug!("found test file: {:?}", file_path.display());
|
||||
debug!(%file_path, "found test file");
|
||||
|
||||
// Record the stem of the test file, to check for overlaps later.
|
||||
let rel_test_path = relative_dir_path.join(file_path.file_stem().unwrap());
|
||||
@ -810,22 +814,20 @@ fn collect_tests_from_dir(
|
||||
make_test(cx, collector, &paths);
|
||||
} else if file_path.is_dir() {
|
||||
// Recurse to find more tests in a subdirectory.
|
||||
let relative_file_path = relative_dir_path.join(file.file_name());
|
||||
if &file_name != "auxiliary" {
|
||||
debug!("found directory: {:?}", file_path.display());
|
||||
let relative_file_path = relative_dir_path.join(file_name);
|
||||
if file_name != "auxiliary" {
|
||||
debug!(%file_path, "found directory");
|
||||
collect_tests_from_dir(cx, collector, &file_path, &relative_file_path)?;
|
||||
}
|
||||
} else {
|
||||
debug!("found other file/directory: {:?}", file_path.display());
|
||||
debug!(%file_path, "found other file/directory");
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Returns true if `file_name` looks like a proper test file name.
|
||||
pub fn is_test(file_name: &OsString) -> bool {
|
||||
let file_name = file_name.to_str().unwrap();
|
||||
|
||||
pub fn is_test(file_name: &str) -> bool {
|
||||
if !file_name.ends_with(".rs") {
|
||||
return false;
|
||||
}
|
||||
@ -844,7 +846,7 @@ fn make_test(cx: &TestCollectorCx, collector: &mut TestCollector, testpaths: &Te
|
||||
let test_path = if cx.config.mode == Mode::RunMake {
|
||||
testpaths.file.join("rmake.rs")
|
||||
} else {
|
||||
PathBuf::from(&testpaths.file)
|
||||
testpaths.file.clone()
|
||||
};
|
||||
|
||||
// Scan the test file to discover its revisions, if any.
|
||||
@ -899,7 +901,7 @@ fn make_test(cx: &TestCollectorCx, collector: &mut TestCollector, testpaths: &Te
|
||||
|
||||
/// The path of the `stamp` file that gets created or updated whenever a
|
||||
/// particular test completes successfully.
|
||||
fn stamp_file_path(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> PathBuf {
|
||||
fn stamp_file_path(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> Utf8PathBuf {
|
||||
output_base_dir(config, testpaths, revision).join("stamp")
|
||||
}
|
||||
|
||||
@ -912,7 +914,7 @@ fn files_related_to_test(
|
||||
testpaths: &TestPaths,
|
||||
props: &EarlyProps,
|
||||
revision: Option<&str>,
|
||||
) -> Vec<PathBuf> {
|
||||
) -> Vec<Utf8PathBuf> {
|
||||
let mut related = vec![];
|
||||
|
||||
if testpaths.file.is_dir() {
|
||||
@ -920,7 +922,7 @@ fn files_related_to_test(
|
||||
for entry in WalkDir::new(&testpaths.file) {
|
||||
let path = entry.unwrap().into_path();
|
||||
if path.is_file() {
|
||||
related.push(path);
|
||||
related.push(Utf8PathBuf::try_from(path).unwrap());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -991,7 +993,7 @@ struct Stamp {
|
||||
|
||||
impl Stamp {
|
||||
/// Creates a timestamp holding the last-modified time of the specified file.
|
||||
fn from_path(path: &Path) -> Self {
|
||||
fn from_path(path: &Utf8Path) -> Self {
|
||||
let mut stamp = Stamp { time: SystemTime::UNIX_EPOCH };
|
||||
stamp.add_path(path);
|
||||
stamp
|
||||
@ -999,8 +1001,8 @@ impl Stamp {
|
||||
|
||||
/// Updates this timestamp to the last-modified time of the specified file,
|
||||
/// if it is later than the currently-stored timestamp.
|
||||
fn add_path(&mut self, path: &Path) {
|
||||
let modified = fs::metadata(path)
|
||||
fn add_path(&mut self, path: &Utf8Path) {
|
||||
let modified = fs::metadata(path.as_std_path())
|
||||
.and_then(|metadata| metadata.modified())
|
||||
.unwrap_or(SystemTime::UNIX_EPOCH);
|
||||
self.time = self.time.max(modified);
|
||||
@ -1009,7 +1011,8 @@ impl Stamp {
|
||||
/// Updates this timestamp to the most recent last-modified time of all files
|
||||
/// recursively contained in the given directory, if it is later than the
|
||||
/// currently-stored timestamp.
|
||||
fn add_dir(&mut self, path: &Path) {
|
||||
fn add_dir(&mut self, path: &Utf8Path) {
|
||||
let path = path.as_std_path();
|
||||
for entry in WalkDir::new(path) {
|
||||
let entry = entry.unwrap();
|
||||
if entry.file_type().is_file() {
|
||||
@ -1042,7 +1045,7 @@ fn make_test_name(config: &Config, testpaths: &TestPaths, revision: Option<&str>
|
||||
config.mode,
|
||||
debugger,
|
||||
mode_suffix,
|
||||
path.display(),
|
||||
path,
|
||||
revision.map_or("".to_string(), |rev| format!("#{}", rev))
|
||||
)
|
||||
}
|
||||
@ -1064,7 +1067,7 @@ fn make_test_name(config: &Config, testpaths: &TestPaths, revision: Option<&str>
|
||||
/// To avoid problems, we forbid test names from overlapping in this way.
|
||||
///
|
||||
/// See <https://github.com/rust-lang/rust/pull/109509> for more context.
|
||||
fn check_for_overlapping_test_paths(found_path_stems: &HashSet<PathBuf>) {
|
||||
fn check_for_overlapping_test_paths(found_path_stems: &HashSet<Utf8PathBuf>) {
|
||||
let mut collisions = Vec::new();
|
||||
for path in found_path_stems {
|
||||
for ancestor in path.ancestors().skip(1) {
|
||||
@ -1077,7 +1080,7 @@ fn check_for_overlapping_test_paths(found_path_stems: &HashSet<PathBuf>) {
|
||||
collisions.sort();
|
||||
let collisions: String = collisions
|
||||
.into_iter()
|
||||
.map(|(path, check_parent)| format!("test {path:?} clashes with {check_parent:?}\n"))
|
||||
.map(|(path, check_parent)| format!("test {path} clashes with {check_parent}\n"))
|
||||
.collect();
|
||||
panic!(
|
||||
"{collisions}\n\
|
||||
|
@ -1,15 +1,15 @@
|
||||
use std::borrow::Cow;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::ffi::OsString;
|
||||
use std::fs::{self, File, create_dir_all};
|
||||
use std::hash::{DefaultHasher, Hash, Hasher};
|
||||
use std::io::prelude::*;
|
||||
use std::io::{self, BufReader};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::{Child, Command, ExitStatus, Output, Stdio};
|
||||
use std::sync::Arc;
|
||||
use std::{env, iter, str};
|
||||
|
||||
use camino::{Utf8Path, Utf8PathBuf};
|
||||
use colored::Colorize;
|
||||
use regex::{Captures, Regex};
|
||||
use tracing::*;
|
||||
@ -25,7 +25,7 @@ use crate::compute_diff::{DiffLine, make_diff, write_diff, write_filtered_diff};
|
||||
use crate::errors::{self, Error, ErrorKind};
|
||||
use crate::header::TestProps;
|
||||
use crate::read2::{Truncated, read2_abbreviated};
|
||||
use crate::util::{PathBufExt, add_dylib_path, logv, static_regex};
|
||||
use crate::util::{Utf8PathBufExt, add_dylib_path, logv, static_regex};
|
||||
use crate::{ColorConfig, json, stamp_file_path};
|
||||
|
||||
mod debugger;
|
||||
@ -131,7 +131,7 @@ pub fn run(config: Arc<Config>, testpaths: &TestPaths, revision: Option<&str>) {
|
||||
// We're going to be dumping a lot of info. Start on a new line.
|
||||
print!("\n\n");
|
||||
}
|
||||
debug!("running {:?}", testpaths.file.display());
|
||||
debug!("running {}", testpaths.file);
|
||||
let mut props = TestProps::from_file(&testpaths.file, revision, &config);
|
||||
|
||||
// For non-incremental (i.e. regular UI) tests, the incremental directory
|
||||
@ -144,7 +144,7 @@ pub fn run(config: Arc<Config>, testpaths: &TestPaths, revision: Option<&str>) {
|
||||
let cx = TestCx { config: &config, props: &props, testpaths, revision };
|
||||
|
||||
if let Err(e) = create_dir_all(&cx.output_base_dir()) {
|
||||
panic!("failed to create output base directory {}: {e}", cx.output_base_dir().display());
|
||||
panic!("failed to create output base directory {}: {e}", cx.output_base_dir());
|
||||
}
|
||||
|
||||
if props.incremental {
|
||||
@ -207,7 +207,8 @@ pub fn compute_stamp_hash(config: &Config) -> String {
|
||||
format!("{:x}", hash.finish())
|
||||
}
|
||||
|
||||
fn remove_and_create_dir_all(path: &Path) {
|
||||
fn remove_and_create_dir_all(path: &Utf8Path) {
|
||||
let path = path.as_std_path();
|
||||
let _ = fs::remove_dir_all(path);
|
||||
fs::create_dir_all(path).unwrap();
|
||||
}
|
||||
@ -423,7 +424,7 @@ impl<'test> TestCx<'test> {
|
||||
let aux_dir = self.aux_output_dir_name();
|
||||
let input: &str = match read_from {
|
||||
ReadFrom::Stdin(_) => "-",
|
||||
ReadFrom::Path => self.testpaths.file.to_str().unwrap(),
|
||||
ReadFrom::Path => self.testpaths.file.as_str(),
|
||||
};
|
||||
|
||||
let mut rustc = Command::new(&self.config.rustc_path);
|
||||
@ -590,10 +591,7 @@ impl<'test> TestCx<'test> {
|
||||
// FIXME(#65865)
|
||||
return;
|
||||
} else {
|
||||
self.fatal(&format!(
|
||||
"no error pattern specified in {:?}",
|
||||
self.testpaths.file.display()
|
||||
));
|
||||
self.fatal(&format!("no error pattern specified in {}", self.testpaths.file));
|
||||
}
|
||||
}
|
||||
|
||||
@ -697,17 +695,17 @@ impl<'test> TestCx<'test> {
|
||||
}
|
||||
|
||||
// On Windows, translate all '\' path separators to '/'
|
||||
let file_name = format!("{}", self.testpaths.file.display()).replace(r"\", "/");
|
||||
let file_name = self.testpaths.file.to_string().replace(r"\", "/");
|
||||
|
||||
// On Windows, keep all '\' path separators to match the paths reported in the JSON output
|
||||
// from the compiler
|
||||
let diagnostic_file_name = if self.props.remap_src_base {
|
||||
let mut p = PathBuf::from(FAKE_SRC_BASE);
|
||||
let mut p = Utf8PathBuf::from(FAKE_SRC_BASE);
|
||||
p.push(&self.testpaths.relative_dir);
|
||||
p.push(self.testpaths.file.file_name().unwrap());
|
||||
p.display().to_string()
|
||||
p.to_string()
|
||||
} else {
|
||||
self.testpaths.file.display().to_string()
|
||||
self.testpaths.file.to_string()
|
||||
};
|
||||
|
||||
let expect_help = expected_errors.iter().any(|ee| ee.kind == Some(ErrorKind::Help));
|
||||
@ -887,7 +885,7 @@ impl<'test> TestCx<'test> {
|
||||
|
||||
/// `root_out_dir` and `root_testpaths` refer to the parameters of the actual test being run.
|
||||
/// Auxiliaries, no matter how deep, have the same root_out_dir and root_testpaths.
|
||||
fn document(&self, root_out_dir: &Path, root_testpaths: &TestPaths) -> ProcRes {
|
||||
fn document(&self, root_out_dir: &Utf8Path, root_testpaths: &TestPaths) -> ProcRes {
|
||||
if self.props.build_aux_docs {
|
||||
for rel_ab in &self.props.aux.builds {
|
||||
let aux_testpaths = self.compute_aux_test_paths(root_testpaths, rel_ab);
|
||||
@ -916,13 +914,13 @@ impl<'test> TestCx<'test> {
|
||||
|
||||
// actual --out-dir given to the auxiliary or test, as opposed to the root out dir for the entire
|
||||
// test
|
||||
let out_dir: Cow<'_, Path> = if self.props.unique_doc_out_dir {
|
||||
let out_dir: Cow<'_, Utf8Path> = if self.props.unique_doc_out_dir {
|
||||
let file_name = self.testpaths.file.file_stem().expect("file name should not be empty");
|
||||
let out_dir = PathBuf::from_iter([
|
||||
let out_dir = Utf8PathBuf::from_iter([
|
||||
root_out_dir,
|
||||
Path::new("docs"),
|
||||
Path::new(file_name),
|
||||
Path::new("doc"),
|
||||
Utf8Path::new("docs"),
|
||||
Utf8Path::new(file_name),
|
||||
Utf8Path::new("doc"),
|
||||
]);
|
||||
create_dir_all(&out_dir).unwrap();
|
||||
Cow::Owned(out_dir)
|
||||
@ -935,7 +933,7 @@ impl<'test> TestCx<'test> {
|
||||
rustdoc.current_dir(current_dir);
|
||||
rustdoc
|
||||
.arg("-L")
|
||||
.arg(self.config.run_lib_path.to_str().unwrap())
|
||||
.arg(self.config.run_lib_path.as_path())
|
||||
.arg("-L")
|
||||
.arg(aux_dir)
|
||||
.arg("-o")
|
||||
@ -1073,7 +1071,7 @@ impl<'test> TestCx<'test> {
|
||||
let test_ab =
|
||||
of.file.parent().expect("test file path has no parent").join("auxiliary").join(rel_ab);
|
||||
if !test_ab.exists() {
|
||||
self.fatal(&format!("aux-build `{}` source not found", test_ab.display()))
|
||||
self.fatal(&format!("aux-build `{}` source not found", test_ab))
|
||||
}
|
||||
|
||||
TestPaths {
|
||||
@ -1110,7 +1108,7 @@ impl<'test> TestCx<'test> {
|
||||
|| !self.props.aux.proc_macros.is_empty()
|
||||
}
|
||||
|
||||
fn aux_output_dir(&self) -> PathBuf {
|
||||
fn aux_output_dir(&self) -> Utf8PathBuf {
|
||||
let aux_dir = self.aux_output_dir_name();
|
||||
|
||||
if !self.props.aux.builds.is_empty() {
|
||||
@ -1126,7 +1124,7 @@ impl<'test> TestCx<'test> {
|
||||
aux_dir
|
||||
}
|
||||
|
||||
fn build_all_auxiliary(&self, of: &TestPaths, aux_dir: &Path, rustc: &mut Command) {
|
||||
fn build_all_auxiliary(&self, of: &TestPaths, aux_dir: &Utf8Path, rustc: &mut Command) {
|
||||
for rel_ab in &self.props.aux.builds {
|
||||
self.build_auxiliary(of, rel_ab, &aux_dir, None);
|
||||
}
|
||||
@ -1146,12 +1144,7 @@ impl<'test> TestCx<'test> {
|
||||
|rustc: &mut Command, aux_name: &str, aux_path: &str, aux_type: AuxType| {
|
||||
let lib_name = get_lib_name(&path_to_crate_name(aux_path), aux_type);
|
||||
if let Some(lib_name) = lib_name {
|
||||
rustc.arg("--extern").arg(format!(
|
||||
"{}={}/{}",
|
||||
aux_name,
|
||||
aux_dir.display(),
|
||||
lib_name
|
||||
));
|
||||
rustc.arg("--extern").arg(format!("{}={}/{}", aux_name, aux_dir, lib_name));
|
||||
}
|
||||
};
|
||||
|
||||
@ -1172,7 +1165,7 @@ impl<'test> TestCx<'test> {
|
||||
let aux_type = self.build_auxiliary(of, aux_file, aux_dir, None);
|
||||
if let Some(lib_name) = get_lib_name(aux_file.trim_end_matches(".rs"), aux_type) {
|
||||
let lib_path = aux_dir.join(&lib_name);
|
||||
rustc.arg(format!("-Zcodegen-backend={}", lib_path.display()));
|
||||
rustc.arg(format!("-Zcodegen-backend={}", lib_path));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1188,7 +1181,7 @@ impl<'test> TestCx<'test> {
|
||||
if self.props.add_core_stubs {
|
||||
let minicore_path = self.build_minicore();
|
||||
rustc.arg("--extern");
|
||||
rustc.arg(&format!("minicore={}", minicore_path.to_str().unwrap()));
|
||||
rustc.arg(&format!("minicore={}", minicore_path));
|
||||
}
|
||||
|
||||
let aux_dir = self.aux_output_dir();
|
||||
@ -1206,7 +1199,7 @@ impl<'test> TestCx<'test> {
|
||||
|
||||
/// Builds `minicore`. Returns the path to the minicore rlib within the base test output
|
||||
/// directory.
|
||||
fn build_minicore(&self) -> PathBuf {
|
||||
fn build_minicore(&self) -> Utf8PathBuf {
|
||||
let output_file_path = self.output_base_dir().join("libminicore.rlib");
|
||||
let mut rustc = self.make_compile_args(
|
||||
&self.config.minicore_path,
|
||||
@ -1223,10 +1216,7 @@ impl<'test> TestCx<'test> {
|
||||
let res = self.compose_and_run(rustc, self.config.compile_lib_path.as_path(), None, None);
|
||||
if !res.status.success() {
|
||||
self.fatal_proc_rec(
|
||||
&format!(
|
||||
"auxiliary build of {:?} failed to compile: ",
|
||||
self.config.minicore_path.display()
|
||||
),
|
||||
&format!("auxiliary build of {} failed to compile: ", self.config.minicore_path),
|
||||
&res,
|
||||
);
|
||||
}
|
||||
@ -1241,7 +1231,7 @@ impl<'test> TestCx<'test> {
|
||||
&self,
|
||||
of: &TestPaths,
|
||||
source_path: &str,
|
||||
aux_dir: &Path,
|
||||
aux_dir: &Utf8Path,
|
||||
aux_type: Option<AuxType>,
|
||||
) -> AuxType {
|
||||
let aux_testpaths = self.compute_aux_test_paths(of, source_path);
|
||||
@ -1338,10 +1328,7 @@ impl<'test> TestCx<'test> {
|
||||
);
|
||||
if !auxres.status.success() {
|
||||
self.fatal_proc_rec(
|
||||
&format!(
|
||||
"auxiliary build of {:?} failed to compile: ",
|
||||
aux_testpaths.file.display()
|
||||
),
|
||||
&format!("auxiliary build of {} failed to compile: ", aux_testpaths.file),
|
||||
&auxres,
|
||||
);
|
||||
}
|
||||
@ -1350,8 +1337,8 @@ impl<'test> TestCx<'test> {
|
||||
|
||||
fn read2_abbreviated(&self, child: Child) -> (Output, Truncated) {
|
||||
let mut filter_paths_from_len = Vec::new();
|
||||
let mut add_path = |path: &Path| {
|
||||
let path = path.display().to_string();
|
||||
let mut add_path = |path: &Utf8Path| {
|
||||
let path = path.to_string();
|
||||
let windows = path.replace("\\", "\\\\");
|
||||
if windows != path {
|
||||
filter_paths_from_len.push(windows);
|
||||
@ -1373,8 +1360,8 @@ impl<'test> TestCx<'test> {
|
||||
fn compose_and_run(
|
||||
&self,
|
||||
mut command: Command,
|
||||
lib_path: &Path,
|
||||
aux_path: Option<&Path>,
|
||||
lib_path: &Utf8Path,
|
||||
aux_path: Option<&Utf8Path>,
|
||||
input: Option<String>,
|
||||
) -> ProcRes {
|
||||
let cmdline = {
|
||||
@ -1419,9 +1406,9 @@ impl<'test> TestCx<'test> {
|
||||
matches!(self.config.suite.as_str(), "rustdoc-ui" | "rustdoc-js" | "rustdoc-json")
|
||||
}
|
||||
|
||||
fn get_mir_dump_dir(&self) -> PathBuf {
|
||||
fn get_mir_dump_dir(&self) -> Utf8PathBuf {
|
||||
let mut mir_dump_dir = self.config.build_test_suite_root.clone();
|
||||
debug!("input_file: {:?}", self.testpaths.file);
|
||||
debug!("input_file: {}", self.testpaths.file);
|
||||
mir_dump_dir.push(&self.testpaths.relative_dir);
|
||||
mir_dump_dir.push(self.testpaths.file.file_stem().unwrap());
|
||||
mir_dump_dir
|
||||
@ -1429,7 +1416,7 @@ impl<'test> TestCx<'test> {
|
||||
|
||||
fn make_compile_args(
|
||||
&self,
|
||||
input_file: &Path,
|
||||
input_file: &Utf8Path,
|
||||
output_file: TargetLocation,
|
||||
emit: Emit,
|
||||
allow_unused: AllowUnused,
|
||||
@ -1470,7 +1457,7 @@ impl<'test> TestCx<'test> {
|
||||
// Similarly, vendored sources shouldn't be shown when running from a dist tarball.
|
||||
rustc.arg("-Z").arg(format!(
|
||||
"ignore-directory-in-diagnostics-source-blocks={}",
|
||||
self.config.src_root.join("vendor").to_str().unwrap(),
|
||||
self.config.src_root.join("vendor"),
|
||||
));
|
||||
|
||||
// Optionally prevent default --sysroot if specified in test compile-flags.
|
||||
@ -1494,7 +1481,7 @@ impl<'test> TestCx<'test> {
|
||||
|
||||
if !is_rustdoc {
|
||||
if let Some(ref incremental_dir) = self.props.incremental_dir {
|
||||
rustc.args(&["-C", &format!("incremental={}", incremental_dir.display())]);
|
||||
rustc.args(&["-C", &format!("incremental={}", incremental_dir)]);
|
||||
rustc.args(&["-Z", "incremental-verify-ich"]);
|
||||
}
|
||||
|
||||
@ -1538,7 +1525,7 @@ impl<'test> TestCx<'test> {
|
||||
let mir_dump_dir = self.get_mir_dump_dir();
|
||||
remove_and_create_dir_all(&mir_dump_dir);
|
||||
let mut dir_opt = "-Zdump-mir-dir=".to_string();
|
||||
dir_opt.push_str(mir_dump_dir.to_str().unwrap());
|
||||
dir_opt.push_str(mir_dump_dir.as_str());
|
||||
debug!("dir_opt: {:?}", dir_opt);
|
||||
rustc.arg(dir_opt);
|
||||
};
|
||||
@ -1631,8 +1618,7 @@ impl<'test> TestCx<'test> {
|
||||
if self.props.remap_src_base {
|
||||
rustc.arg(format!(
|
||||
"--remap-path-prefix={}={}",
|
||||
self.config.src_test_suite_root.to_str().unwrap(),
|
||||
FAKE_SRC_BASE,
|
||||
self.config.src_test_suite_root, FAKE_SRC_BASE,
|
||||
));
|
||||
}
|
||||
|
||||
@ -1755,7 +1741,7 @@ impl<'test> TestCx<'test> {
|
||||
rustc
|
||||
}
|
||||
|
||||
fn make_exe_name(&self) -> PathBuf {
|
||||
fn make_exe_name(&self) -> Utf8PathBuf {
|
||||
// Using a single letter here to keep the path length down for
|
||||
// Windows. Some test names get very long. rustc creates `rcgu`
|
||||
// files with the module name appended to it which can more than
|
||||
@ -1806,7 +1792,7 @@ impl<'test> TestCx<'test> {
|
||||
}
|
||||
}
|
||||
|
||||
fn make_cmdline(&self, command: &Command, libpath: &Path) -> String {
|
||||
fn make_cmdline(&self, command: &Command, libpath: &Utf8Path) -> String {
|
||||
use crate::util;
|
||||
|
||||
// Linux and mac don't require adjusting the library search path
|
||||
@ -1819,7 +1805,7 @@ impl<'test> TestCx<'test> {
|
||||
format!("{}=\"{}\"", util::lib_path_env_var(), util::make_new_path(path))
|
||||
}
|
||||
|
||||
format!("{} {:?}", lib_path_cmd_prefix(libpath.to_str().unwrap()), command)
|
||||
format!("{} {:?}", lib_path_cmd_prefix(libpath.as_str()), command)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1833,20 +1819,19 @@ impl<'test> TestCx<'test> {
|
||||
return;
|
||||
}
|
||||
|
||||
let path = Path::new(proc_name);
|
||||
let path = Utf8Path::new(proc_name);
|
||||
let proc_name = if path.file_stem().is_some_and(|p| p == "rmake") {
|
||||
OsString::from_iter(
|
||||
String::from_iter(
|
||||
path.parent()
|
||||
.unwrap()
|
||||
.file_name()
|
||||
.into_iter()
|
||||
.chain(Some(OsStr::new("/")))
|
||||
.chain(Some("/"))
|
||||
.chain(path.file_name()),
|
||||
)
|
||||
} else {
|
||||
path.file_name().unwrap().into()
|
||||
};
|
||||
let proc_name = proc_name.to_string_lossy();
|
||||
println!("------{proc_name} stdout------------------------------");
|
||||
println!("{}", out);
|
||||
println!("------{proc_name} stderr------------------------------");
|
||||
@ -1856,18 +1841,18 @@ impl<'test> TestCx<'test> {
|
||||
|
||||
fn dump_output_file(&self, out: &str, extension: &str) {
|
||||
let outfile = self.make_out_name(extension);
|
||||
fs::write(&outfile, out).unwrap();
|
||||
fs::write(outfile.as_std_path(), out).unwrap();
|
||||
}
|
||||
|
||||
/// Creates a filename for output with the given extension.
|
||||
/// E.g., `/.../testname.revision.mode/testname.extension`.
|
||||
fn make_out_name(&self, extension: &str) -> PathBuf {
|
||||
fn make_out_name(&self, extension: &str) -> Utf8PathBuf {
|
||||
self.output_base_name().with_extension(extension)
|
||||
}
|
||||
|
||||
/// Gets the directory where auxiliary files are written.
|
||||
/// E.g., `/.../testname.revision.mode/auxiliary/`.
|
||||
fn aux_output_dir_name(&self) -> PathBuf {
|
||||
fn aux_output_dir_name(&self) -> Utf8PathBuf {
|
||||
self.output_base_dir()
|
||||
.join("auxiliary")
|
||||
.with_extra_extension(self.config.mode.aux_dir_disambiguator())
|
||||
@ -1875,12 +1860,12 @@ impl<'test> TestCx<'test> {
|
||||
|
||||
/// Gets the directory where auxiliary binaries are written.
|
||||
/// E.g., `/.../testname.revision.mode/auxiliary/bin`.
|
||||
fn aux_bin_output_dir_name(&self) -> PathBuf {
|
||||
fn aux_bin_output_dir_name(&self) -> Utf8PathBuf {
|
||||
self.aux_output_dir_name().join("bin")
|
||||
}
|
||||
|
||||
/// Generates a unique name for the test, such as `testname.revision.mode`.
|
||||
fn output_testname_unique(&self) -> PathBuf {
|
||||
fn output_testname_unique(&self) -> Utf8PathBuf {
|
||||
output_testname_unique(self.config, self.testpaths, self.safe_revision())
|
||||
}
|
||||
|
||||
@ -1893,14 +1878,14 @@ impl<'test> TestCx<'test> {
|
||||
/// Gets the absolute path to the directory where all output for the given
|
||||
/// test/revision should reside.
|
||||
/// E.g., `/path/to/build/host-tuple/test/ui/relative/testname.revision.mode/`.
|
||||
fn output_base_dir(&self) -> PathBuf {
|
||||
fn output_base_dir(&self) -> Utf8PathBuf {
|
||||
output_base_dir(self.config, self.testpaths, self.safe_revision())
|
||||
}
|
||||
|
||||
/// Gets the absolute path to the base filename used as output for the given
|
||||
/// test/revision.
|
||||
/// E.g., `/.../relative/testname.revision.mode/testname`.
|
||||
fn output_base_name(&self) -> PathBuf {
|
||||
fn output_base_name(&self) -> Utf8PathBuf {
|
||||
output_base_name(self.config, self.testpaths, self.safe_revision())
|
||||
}
|
||||
|
||||
@ -1935,7 +1920,7 @@ impl<'test> TestCx<'test> {
|
||||
|
||||
// codegen tests (using FileCheck)
|
||||
|
||||
fn compile_test_and_save_ir(&self) -> (ProcRes, PathBuf) {
|
||||
fn compile_test_and_save_ir(&self) -> (ProcRes, Utf8PathBuf) {
|
||||
let output_path = self.output_base_name().with_extension("ll");
|
||||
let input_file = &self.testpaths.file;
|
||||
let rustc = self.make_compile_args(
|
||||
@ -1951,7 +1936,7 @@ impl<'test> TestCx<'test> {
|
||||
(proc_res, output_path)
|
||||
}
|
||||
|
||||
fn verify_with_filecheck(&self, output: &Path) -> ProcRes {
|
||||
fn verify_with_filecheck(&self, output: &Utf8Path) -> ProcRes {
|
||||
let mut filecheck = Command::new(self.config.llvm_filecheck.as_ref().unwrap());
|
||||
filecheck.arg("--input-file").arg(output).arg(&self.testpaths.file);
|
||||
|
||||
@ -1981,7 +1966,7 @@ impl<'test> TestCx<'test> {
|
||||
filecheck.args(&self.props.filecheck_flags);
|
||||
|
||||
// FIXME(jieyouxu): don't pass an empty Path
|
||||
self.compose_and_run(filecheck, Path::new(""), None, None)
|
||||
self.compose_and_run(filecheck, Utf8Path::new(""), None, None)
|
||||
}
|
||||
|
||||
fn charset() -> &'static str {
|
||||
@ -1989,7 +1974,7 @@ impl<'test> TestCx<'test> {
|
||||
if cfg!(target_os = "freebsd") { "ISO-8859-1" } else { "UTF-8" }
|
||||
}
|
||||
|
||||
fn compare_to_default_rustdoc(&mut self, out_dir: &Path) {
|
||||
fn compare_to_default_rustdoc(&mut self, out_dir: &Utf8Path) {
|
||||
if !self.config.has_html_tidy {
|
||||
return;
|
||||
}
|
||||
@ -2141,12 +2126,8 @@ impl<'test> TestCx<'test> {
|
||||
};
|
||||
}
|
||||
|
||||
fn get_lines<P: AsRef<Path>>(
|
||||
&self,
|
||||
path: &P,
|
||||
mut other_files: Option<&mut Vec<String>>,
|
||||
) -> Vec<usize> {
|
||||
let content = fs::read_to_string(&path).unwrap();
|
||||
fn get_lines(&self, path: &Utf8Path, mut other_files: Option<&mut Vec<String>>) -> Vec<usize> {
|
||||
let content = fs::read_to_string(path.as_std_path()).unwrap();
|
||||
let mut ignore = false;
|
||||
content
|
||||
.lines()
|
||||
@ -2192,8 +2173,8 @@ impl<'test> TestCx<'test> {
|
||||
for other_file in other_files {
|
||||
let mut path = self.testpaths.file.clone();
|
||||
path.set_file_name(&format!("{}.rs", other_file));
|
||||
let path = fs::canonicalize(path).expect("failed to canonicalize");
|
||||
let normalized = path.to_str().unwrap().replace('\\', "/");
|
||||
let path = path.canonicalize_utf8().expect("failed to canonicalize");
|
||||
let normalized = path.as_str().replace('\\', "/");
|
||||
files.insert(normalized, self.get_lines(&path, None));
|
||||
}
|
||||
|
||||
@ -2377,26 +2358,24 @@ impl<'test> TestCx<'test> {
|
||||
|
||||
let mut normalized = output.to_string();
|
||||
|
||||
let mut normalize_path = |from: &Path, to: &str| {
|
||||
let mut from = from.display().to_string();
|
||||
if json {
|
||||
from = from.replace("\\", "\\\\");
|
||||
}
|
||||
normalized = normalized.replace(&from, to);
|
||||
let mut normalize_path = |from: &Utf8Path, to: &str| {
|
||||
let from = if json { &from.as_str().replace("\\", "\\\\") } else { from.as_str() };
|
||||
|
||||
normalized = normalized.replace(from, to);
|
||||
};
|
||||
|
||||
let parent_dir = self.testpaths.file.parent().unwrap();
|
||||
normalize_path(parent_dir, "$DIR");
|
||||
|
||||
if self.props.remap_src_base {
|
||||
let mut remapped_parent_dir = PathBuf::from(FAKE_SRC_BASE);
|
||||
if self.testpaths.relative_dir != Path::new("") {
|
||||
let mut remapped_parent_dir = Utf8PathBuf::from(FAKE_SRC_BASE);
|
||||
if self.testpaths.relative_dir != Utf8Path::new("") {
|
||||
remapped_parent_dir.push(&self.testpaths.relative_dir);
|
||||
}
|
||||
normalize_path(&remapped_parent_dir, "$DIR");
|
||||
}
|
||||
|
||||
let base_dir = Path::new("/rustc/FAKE_PREFIX");
|
||||
let base_dir = Utf8Path::new("/rustc/FAKE_PREFIX");
|
||||
// Fake paths into the libstd/libcore
|
||||
normalize_path(&base_dir.join("library"), "$SRC_DIR");
|
||||
// `ui-fulldeps` tests can show paths to the compiler source when testing macros from
|
||||
@ -2406,8 +2385,8 @@ impl<'test> TestCx<'test> {
|
||||
|
||||
// Real paths into the libstd/libcore
|
||||
let rust_src_dir = &self.config.sysroot_base.join("lib/rustlib/src/rust");
|
||||
rust_src_dir.try_exists().expect(&*format!("{} should exists", rust_src_dir.display()));
|
||||
let rust_src_dir = rust_src_dir.read_link().unwrap_or(rust_src_dir.to_path_buf());
|
||||
rust_src_dir.try_exists().expect(&*format!("{} should exists", rust_src_dir));
|
||||
let rust_src_dir = rust_src_dir.read_link_utf8().unwrap_or(rust_src_dir.to_path_buf());
|
||||
normalize_path(&rust_src_dir.join("library"), "$SRC_DIR_REAL");
|
||||
|
||||
// eg.
|
||||
@ -2547,7 +2526,7 @@ impl<'test> TestCx<'test> {
|
||||
.replace("\r\n", "\n")
|
||||
}
|
||||
|
||||
fn expected_output_path(&self, kind: &str) -> PathBuf {
|
||||
fn expected_output_path(&self, kind: &str) -> Utf8PathBuf {
|
||||
let mut path =
|
||||
expected_output_path(&self.testpaths, self.revision, &self.config.compare_mode, kind);
|
||||
|
||||
@ -2576,19 +2555,18 @@ impl<'test> TestCx<'test> {
|
||||
}
|
||||
}
|
||||
|
||||
fn load_expected_output_from_path(&self, path: &Path) -> Result<String, String> {
|
||||
fs::read_to_string(path).map_err(|err| {
|
||||
format!("failed to load expected output from `{}`: {}", path.display(), err)
|
||||
})
|
||||
fn load_expected_output_from_path(&self, path: &Utf8Path) -> Result<String, String> {
|
||||
fs::read_to_string(path)
|
||||
.map_err(|err| format!("failed to load expected output from `{}`: {}", path, err))
|
||||
}
|
||||
|
||||
fn delete_file(&self, file: &Path) {
|
||||
fn delete_file(&self, file: &Utf8Path) {
|
||||
if !file.exists() {
|
||||
// Deleting a nonexistent file would error.
|
||||
return;
|
||||
}
|
||||
if let Err(e) = fs::remove_file(file) {
|
||||
self.fatal(&format!("failed to delete `{}`: {}", file.display(), e,));
|
||||
if let Err(e) = fs::remove_file(file.as_std_path()) {
|
||||
self.fatal(&format!("failed to delete `{}`: {}", file, e,));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2694,8 +2672,8 @@ impl<'test> TestCx<'test> {
|
||||
fn show_diff(
|
||||
&self,
|
||||
stream: &str,
|
||||
expected_path: &Path,
|
||||
actual_path: &Path,
|
||||
expected_path: &Utf8Path,
|
||||
actual_path: &Utf8Path,
|
||||
expected: &str,
|
||||
actual: &str,
|
||||
actual_unnormalized: &str,
|
||||
@ -2834,7 +2812,7 @@ impl<'test> TestCx<'test> {
|
||||
fs::create_dir_all(&incremental_dir).unwrap();
|
||||
|
||||
if self.config.verbose {
|
||||
println!("init_incremental_test: incremental_dir={}", incremental_dir.display());
|
||||
println!("init_incremental_test: incremental_dir={incremental_dir}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2892,8 +2870,8 @@ impl ProcRes {
|
||||
|
||||
#[derive(Debug)]
|
||||
enum TargetLocation {
|
||||
ThisFile(PathBuf),
|
||||
ThisDirectory(PathBuf),
|
||||
ThisFile(Utf8PathBuf),
|
||||
ThisDirectory(Utf8PathBuf),
|
||||
}
|
||||
|
||||
enum AllowUnused {
|
||||
|
@ -1,4 +1,4 @@
|
||||
use std::path::PathBuf;
|
||||
use camino::Utf8PathBuf;
|
||||
|
||||
use super::{AllowUnused, Emit, LinkToAux, ProcRes, TargetLocation, TestCx};
|
||||
|
||||
@ -19,7 +19,7 @@ impl TestCx<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
fn compile_test_and_save_assembly(&self) -> (ProcRes, PathBuf) {
|
||||
fn compile_test_and_save_assembly(&self) -> (ProcRes, Utf8PathBuf) {
|
||||
// This works with both `--emit asm` (as default output name for the assembly)
|
||||
// and `ptx-linker` because the latter can write output at requested location.
|
||||
let output_path = self.output_base_name().with_extension("s");
|
||||
|
@ -26,9 +26,7 @@ impl TestCx<'_> {
|
||||
.stdout
|
||||
.lines()
|
||||
.filter(|line| line.starts_with(PREFIX))
|
||||
.map(|line| {
|
||||
line.replace(&self.testpaths.file.display().to_string(), "TEST_PATH").to_string()
|
||||
})
|
||||
.map(|line| line.replace(&self.testpaths.file.as_str(), "TEST_PATH").to_string())
|
||||
.map(|line| str_to_mono_item(&line, true))
|
||||
.collect();
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
//! Code specific to the coverage test suites.
|
||||
|
||||
use std::ffi::OsStr;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
|
||||
use camino::{Utf8Path, Utf8PathBuf};
|
||||
use glob::glob;
|
||||
|
||||
use crate::common::{UI_COVERAGE, UI_COVERAGE_MAP};
|
||||
@ -11,7 +11,7 @@ use crate::runtest::{Emit, ProcRes, TestCx, WillExecute};
|
||||
use crate::util::static_regex;
|
||||
|
||||
impl<'test> TestCx<'test> {
|
||||
fn coverage_dump_path(&self) -> &Path {
|
||||
fn coverage_dump_path(&self) -> &Utf8Path {
|
||||
self.config
|
||||
.coverage_dump_path
|
||||
.as_deref()
|
||||
@ -79,10 +79,8 @@ impl<'test> TestCx<'test> {
|
||||
std::fs::remove_file(&profdata_path).unwrap();
|
||||
}
|
||||
|
||||
let proc_res = self.exec_compiled_test_general(
|
||||
&[("LLVM_PROFILE_FILE", &profraw_path.to_str().unwrap())],
|
||||
false,
|
||||
);
|
||||
let proc_res =
|
||||
self.exec_compiled_test_general(&[("LLVM_PROFILE_FILE", profraw_path.as_str())], false);
|
||||
if self.props.failure_status.is_some() {
|
||||
self.check_correct_failure_status(&proc_res);
|
||||
} else if !proc_res.status.success() {
|
||||
@ -158,8 +156,8 @@ impl<'test> TestCx<'test> {
|
||||
/// `.profraw` files and doctest executables to the given vectors.
|
||||
fn run_doctests_for_coverage(
|
||||
&self,
|
||||
profraw_paths: &mut Vec<PathBuf>,
|
||||
bin_paths: &mut Vec<PathBuf>,
|
||||
profraw_paths: &mut Vec<Utf8PathBuf>,
|
||||
bin_paths: &mut Vec<Utf8PathBuf>,
|
||||
) {
|
||||
// Put .profraw files and doctest executables in dedicated directories,
|
||||
// to make it easier to glob them all later.
|
||||
@ -204,10 +202,9 @@ impl<'test> TestCx<'test> {
|
||||
self.fatal_proc_rec("rustdoc --test failed!", &proc_res)
|
||||
}
|
||||
|
||||
fn glob_iter(path: impl AsRef<Path>) -> impl Iterator<Item = PathBuf> {
|
||||
let path_str = path.as_ref().to_str().unwrap();
|
||||
let iter = glob(path_str).unwrap();
|
||||
iter.map(Result::unwrap)
|
||||
fn glob_iter(path: impl AsRef<Utf8Path>) -> impl Iterator<Item = Utf8PathBuf> {
|
||||
let iter = glob(path.as_ref().as_str()).unwrap();
|
||||
iter.map(Result::unwrap).map(Utf8PathBuf::try_from).map(Result::unwrap)
|
||||
}
|
||||
|
||||
// Find all profraw files in the profraw directory.
|
||||
|
@ -1,7 +1,8 @@
|
||||
use std::fmt::Write;
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use camino::{Utf8Path, Utf8PathBuf};
|
||||
|
||||
use crate::common::Config;
|
||||
use crate::runtest::ProcRes;
|
||||
@ -15,11 +16,15 @@ pub(super) struct DebuggerCommands {
|
||||
/// Contains the source line number to check and the line itself
|
||||
check_lines: Vec<(usize, String)>,
|
||||
/// Source file name
|
||||
file: PathBuf,
|
||||
file: Utf8PathBuf,
|
||||
}
|
||||
|
||||
impl DebuggerCommands {
|
||||
pub fn parse_from(file: &Path, config: &Config, debugger_prefix: &str) -> Result<Self, String> {
|
||||
pub fn parse_from(
|
||||
file: &Utf8Path,
|
||||
config: &Config,
|
||||
debugger_prefix: &str,
|
||||
) -> Result<Self, String> {
|
||||
let command_directive = format!("{debugger_prefix}-command");
|
||||
let check_directive = format!("{debugger_prefix}-check");
|
||||
|
||||
@ -27,7 +32,7 @@ impl DebuggerCommands {
|
||||
let mut commands = vec![];
|
||||
let mut check_lines = vec![];
|
||||
let mut counter = 0;
|
||||
let reader = BufReader::new(File::open(file).unwrap());
|
||||
let reader = BufReader::new(File::open(file.as_std_path()).unwrap());
|
||||
for (line_no, line) in reader.lines().enumerate() {
|
||||
counter += 1;
|
||||
let line = line.map_err(|e| format!("Error while parsing debugger commands: {}", e))?;
|
||||
@ -50,7 +55,7 @@ impl DebuggerCommands {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Self { commands, breakpoint_lines, check_lines, file: file.to_owned() })
|
||||
Ok(Self { commands, breakpoint_lines, check_lines, file: file.to_path_buf() })
|
||||
}
|
||||
|
||||
/// Given debugger output and lines to check, ensure that every line is
|
||||
@ -81,10 +86,10 @@ impl DebuggerCommands {
|
||||
if missing.is_empty() {
|
||||
Ok(())
|
||||
} else {
|
||||
let fname = self.file.file_name().unwrap().to_string_lossy();
|
||||
let fname = self.file.file_name().unwrap();
|
||||
let mut msg = format!(
|
||||
"check directive(s) from `{}` not found in debugger output. errors:",
|
||||
self.file.display()
|
||||
self.file
|
||||
);
|
||||
|
||||
for (src_lineno, err_line) in missing {
|
||||
|
@ -1,9 +1,9 @@
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader, Read};
|
||||
use std::path::Path;
|
||||
use std::process::{Command, Output, Stdio};
|
||||
|
||||
use camino::Utf8Path;
|
||||
use tracing::debug;
|
||||
|
||||
use super::debugger::DebuggerCommands;
|
||||
@ -73,11 +73,11 @@ impl TestCx<'_> {
|
||||
let mut js_extension = self.testpaths.file.clone();
|
||||
js_extension.set_extension("cdb.js");
|
||||
if js_extension.exists() {
|
||||
script_str.push_str(&format!(".scriptload \"{}\"\n", js_extension.to_string_lossy()));
|
||||
script_str.push_str(&format!(".scriptload \"{}\"\n", js_extension));
|
||||
}
|
||||
|
||||
// Set breakpoints on every line that contains the string "#break"
|
||||
let source_file_name = self.testpaths.file.file_name().unwrap().to_string_lossy();
|
||||
let source_file_name = self.testpaths.file.file_name().unwrap();
|
||||
for line in &dbg_cmds.breakpoint_lines {
|
||||
script_str.push_str(&format!("bp `{}:{}`\n", source_file_name, line));
|
||||
}
|
||||
@ -151,16 +151,11 @@ impl TestCx<'_> {
|
||||
if is_android_gdb_target(&self.config.target) {
|
||||
cmds = cmds.replace("run", "continue");
|
||||
|
||||
let tool_path = match self.config.android_cross_path.to_str() {
|
||||
Some(x) => x.to_owned(),
|
||||
None => self.fatal("cannot find android cross path"),
|
||||
};
|
||||
|
||||
// write debugger script
|
||||
let mut script_str = String::with_capacity(2048);
|
||||
script_str.push_str(&format!("set charset {}\n", Self::charset()));
|
||||
script_str.push_str(&format!("set sysroot {}\n", tool_path));
|
||||
script_str.push_str(&format!("file {}\n", exe_file.to_str().unwrap()));
|
||||
script_str.push_str(&format!("set sysroot {}\n", &self.config.android_cross_path));
|
||||
script_str.push_str(&format!("file {}\n", exe_file));
|
||||
script_str.push_str("target remote :5039\n");
|
||||
script_str.push_str(&format!(
|
||||
"set solib-search-path \
|
||||
@ -169,12 +164,8 @@ impl TestCx<'_> {
|
||||
));
|
||||
for line in &dbg_cmds.breakpoint_lines {
|
||||
script_str.push_str(
|
||||
format!(
|
||||
"break {:?}:{}\n",
|
||||
self.testpaths.file.file_name().unwrap().to_string_lossy(),
|
||||
*line
|
||||
)
|
||||
.as_str(),
|
||||
format!("break {}:{}\n", self.testpaths.file.file_name().unwrap(), *line)
|
||||
.as_str(),
|
||||
);
|
||||
}
|
||||
script_str.push_str(&cmds);
|
||||
@ -203,7 +194,7 @@ impl TestCx<'_> {
|
||||
self.config.adb_test_dir.clone(),
|
||||
if self.config.target.contains("aarch64") { "64" } else { "" },
|
||||
self.config.adb_test_dir.clone(),
|
||||
exe_file.file_name().unwrap().to_str().unwrap()
|
||||
exe_file.file_name().unwrap()
|
||||
);
|
||||
|
||||
debug!("adb arg: {}", adb_arg);
|
||||
@ -242,7 +233,7 @@ impl TestCx<'_> {
|
||||
let mut gdb = Command::new(&format!("{}-gdb", self.config.target));
|
||||
gdb.args(debugger_opts);
|
||||
// FIXME(jieyouxu): don't pass an empty Path
|
||||
let cmdline = self.make_cmdline(&gdb, Path::new(""));
|
||||
let cmdline = self.make_cmdline(&gdb, Utf8Path::new(""));
|
||||
logv(self.config, format!("executing {}", cmdline));
|
||||
cmdline
|
||||
};
|
||||
@ -259,7 +250,6 @@ impl TestCx<'_> {
|
||||
}
|
||||
} else {
|
||||
let rust_pp_module_abs_path = self.config.src_root.join("src").join("etc");
|
||||
let rust_pp_module_abs_path = rust_pp_module_abs_path.to_str().unwrap();
|
||||
// write debugger script
|
||||
let mut script_str = String::with_capacity(2048);
|
||||
script_str.push_str(&format!("set charset {}\n", Self::charset()));
|
||||
@ -274,17 +264,15 @@ impl TestCx<'_> {
|
||||
// GDB's script auto loading safe path
|
||||
script_str.push_str(&format!(
|
||||
"add-auto-load-safe-path {}\n",
|
||||
rust_pp_module_abs_path.replace(r"\", r"\\")
|
||||
rust_pp_module_abs_path.as_str().replace(r"\", r"\\")
|
||||
));
|
||||
|
||||
let output_base_dir = self.output_base_dir().to_str().unwrap().to_owned();
|
||||
|
||||
// Add the directory containing the output binary to
|
||||
// include embedded pretty printers to GDB's script
|
||||
// auto loading safe path
|
||||
script_str.push_str(&format!(
|
||||
"add-auto-load-safe-path {}\n",
|
||||
output_base_dir.replace(r"\", r"\\")
|
||||
self.output_base_dir().as_str().replace(r"\", r"\\")
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -301,12 +289,13 @@ impl TestCx<'_> {
|
||||
script_str.push_str("set print pretty off\n");
|
||||
|
||||
// Add the pretty printer directory to GDB's source-file search path
|
||||
script_str
|
||||
.push_str(&format!("directory {}\n", rust_pp_module_abs_path.replace(r"\", r"\\")));
|
||||
script_str.push_str(&format!(
|
||||
"directory {}\n",
|
||||
rust_pp_module_abs_path.as_str().replace(r"\", r"\\")
|
||||
));
|
||||
|
||||
// Load the target executable
|
||||
script_str
|
||||
.push_str(&format!("file {}\n", exe_file.to_str().unwrap().replace(r"\", r"\\")));
|
||||
script_str.push_str(&format!("file {}\n", exe_file.as_str().replace(r"\", r"\\")));
|
||||
|
||||
// Force GDB to print values in the Rust format.
|
||||
script_str.push_str("set language rust\n");
|
||||
@ -315,7 +304,7 @@ impl TestCx<'_> {
|
||||
for line in &dbg_cmds.breakpoint_lines {
|
||||
script_str.push_str(&format!(
|
||||
"break '{}':{}\n",
|
||||
self.testpaths.file.file_name().unwrap().to_string_lossy(),
|
||||
self.testpaths.file.file_name().unwrap(),
|
||||
*line
|
||||
));
|
||||
}
|
||||
@ -410,14 +399,14 @@ impl TestCx<'_> {
|
||||
|
||||
script_str.push_str(&format!(
|
||||
"command script import {}/lldb_lookup.py\n",
|
||||
rust_pp_module_abs_path.to_str().unwrap()
|
||||
rust_pp_module_abs_path
|
||||
));
|
||||
File::open(rust_pp_module_abs_path.join("lldb_commands"))
|
||||
.and_then(|mut file| file.read_to_string(&mut script_str))
|
||||
.expect("Failed to read lldb_commands");
|
||||
|
||||
// Set breakpoints on every line that contains the string "#break"
|
||||
let source_file_name = self.testpaths.file.file_name().unwrap().to_string_lossy();
|
||||
let source_file_name = self.testpaths.file.file_name().unwrap();
|
||||
for line in &dbg_cmds.breakpoint_lines {
|
||||
script_str.push_str(&format!(
|
||||
"breakpoint set --file '{}' --line {}\n",
|
||||
@ -451,7 +440,7 @@ impl TestCx<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
fn run_lldb(&self, test_executable: &Path, debugger_script: &Path) -> ProcRes {
|
||||
fn run_lldb(&self, test_executable: &Utf8Path, debugger_script: &Utf8Path) -> ProcRes {
|
||||
// Prepare the lldb_batchmode which executes the debugger script
|
||||
let lldb_script_path = self.config.src_root.join("src/etc/lldb_batchmode.py");
|
||||
let pythonpath = if let Ok(pp) = std::env::var("PYTHONPATH") {
|
||||
|
@ -9,8 +9,7 @@ impl TestCx<'_> {
|
||||
|
||||
self.document(&out_dir, &self.testpaths);
|
||||
|
||||
let file_stem =
|
||||
self.testpaths.file.file_stem().and_then(|f| f.to_str()).expect("no file stem");
|
||||
let file_stem = self.testpaths.file.file_stem().expect("no file stem");
|
||||
let res = self.run_command_to_procres(
|
||||
Command::new(&nodejs)
|
||||
.arg(self.config.src_root.join("src/tools/rustdoc-js/tester.js"))
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use camino::{Utf8Path, Utf8PathBuf};
|
||||
use glob::glob;
|
||||
use miropt_test_tools::{MiroptTest, MiroptTestFile, files_for_miropt_test};
|
||||
use tracing::debug;
|
||||
@ -14,7 +14,7 @@ impl TestCx<'_> {
|
||||
let should_run = self.should_run(pm);
|
||||
|
||||
let mut test_info = files_for_miropt_test(
|
||||
&self.testpaths.file,
|
||||
&self.testpaths.file.as_std_path(),
|
||||
self.config.get_pointer_width(),
|
||||
self.config.target_cfg().panic.for_miropt_test_tools(),
|
||||
);
|
||||
@ -38,20 +38,15 @@ impl TestCx<'_> {
|
||||
|
||||
fn check_mir_dump(&self, test_info: MiroptTest) {
|
||||
let test_dir = self.testpaths.file.parent().unwrap();
|
||||
let test_crate =
|
||||
self.testpaths.file.file_stem().unwrap().to_str().unwrap().replace('-', "_");
|
||||
let test_crate = self.testpaths.file.file_stem().unwrap().replace('-', "_");
|
||||
|
||||
let MiroptTest { run_filecheck, suffix, files, passes: _ } = test_info;
|
||||
|
||||
if self.config.bless {
|
||||
for e in
|
||||
glob(&format!("{}/{}.*{}.mir", test_dir.display(), test_crate, suffix)).unwrap()
|
||||
{
|
||||
for e in glob(&format!("{}/{}.*{}.mir", test_dir, test_crate, suffix)).unwrap() {
|
||||
fs::remove_file(e.unwrap()).unwrap();
|
||||
}
|
||||
for e in
|
||||
glob(&format!("{}/{}.*{}.diff", test_dir.display(), test_crate, suffix)).unwrap()
|
||||
{
|
||||
for e in glob(&format!("{}/{}.*{}.diff", test_dir, test_crate, suffix)).unwrap() {
|
||||
fs::remove_file(e.unwrap()).unwrap();
|
||||
}
|
||||
}
|
||||
@ -60,19 +55,15 @@ impl TestCx<'_> {
|
||||
let dumped_string = if let Some(after) = to_file {
|
||||
self.diff_mir_files(from_file.into(), after.into())
|
||||
} else {
|
||||
let mut output_file = PathBuf::new();
|
||||
let mut output_file = Utf8PathBuf::new();
|
||||
output_file.push(self.get_mir_dump_dir());
|
||||
output_file.push(&from_file);
|
||||
debug!(
|
||||
"comparing the contents of: {} with {}",
|
||||
output_file.display(),
|
||||
expected_file.display()
|
||||
);
|
||||
debug!("comparing the contents of: {} with {:?}", output_file, expected_file);
|
||||
if !output_file.exists() {
|
||||
panic!(
|
||||
"Output file `{}` from test does not exist, available files are in `{}`",
|
||||
output_file.display(),
|
||||
output_file.parent().unwrap().display()
|
||||
output_file,
|
||||
output_file.parent().unwrap()
|
||||
);
|
||||
}
|
||||
self.check_mir_test_timestamp(&from_file, &output_file);
|
||||
@ -107,21 +98,20 @@ impl TestCx<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
fn diff_mir_files(&self, before: PathBuf, after: PathBuf) -> String {
|
||||
let to_full_path = |path: PathBuf| {
|
||||
fn diff_mir_files(&self, before: Utf8PathBuf, after: Utf8PathBuf) -> String {
|
||||
let to_full_path = |path: Utf8PathBuf| {
|
||||
let full = self.get_mir_dump_dir().join(&path);
|
||||
if !full.exists() {
|
||||
panic!(
|
||||
"the mir dump file for {} does not exist (requested in {})",
|
||||
path.display(),
|
||||
self.testpaths.file.display(),
|
||||
path, self.testpaths.file,
|
||||
);
|
||||
}
|
||||
full
|
||||
};
|
||||
let before = to_full_path(before);
|
||||
let after = to_full_path(after);
|
||||
debug!("comparing the contents of: {} with {}", before.display(), after.display());
|
||||
debug!("comparing the contents of: {} with {}", before, after);
|
||||
let before = fs::read_to_string(before).unwrap();
|
||||
let after = fs::read_to_string(after).unwrap();
|
||||
let before = self.normalize_output(&before, &[]);
|
||||
@ -138,8 +128,8 @@ impl TestCx<'_> {
|
||||
dumped_string
|
||||
}
|
||||
|
||||
fn check_mir_test_timestamp(&self, test_name: &str, output_file: &Path) {
|
||||
let t = |file| fs::metadata(file).unwrap().modified().unwrap();
|
||||
fn check_mir_test_timestamp(&self, test_name: &str, output_file: &Utf8Path) {
|
||||
let t = |file: &Utf8Path| fs::metadata(file.as_std_path()).unwrap().modified().unwrap();
|
||||
let source_file = &self.testpaths.file;
|
||||
let output_time = t(output_file);
|
||||
let source_time = t(source_file);
|
||||
@ -147,8 +137,7 @@ impl TestCx<'_> {
|
||||
debug!("source file time: {:?} output file time: {:?}", source_time, output_time);
|
||||
panic!(
|
||||
"test source file `{}` is newer than potentially stale output file `{}`.",
|
||||
source_file.display(),
|
||||
test_name
|
||||
source_file, test_name
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
use std::path::Path;
|
||||
use std::process::{Command, Output, Stdio};
|
||||
use std::{env, fs};
|
||||
|
||||
use build_helper::fs::{ignore_not_found, recursive_remove};
|
||||
use camino::{Utf8Path, Utf8PathBuf};
|
||||
|
||||
use super::{ProcRes, TestCx, disable_error_reporting};
|
||||
use crate::util::{copy_dir_all, dylib_env_var};
|
||||
@ -39,14 +39,16 @@ impl TestCx<'_> {
|
||||
// Copy all input files (apart from rmake.rs) to the temporary directory,
|
||||
// so that the input directory structure from `tests/run-make/<test>` is mirrored
|
||||
// to the `rmake_out` directory.
|
||||
for path in walkdir::WalkDir::new(&self.testpaths.file).min_depth(1) {
|
||||
let path = path.unwrap().path().to_path_buf();
|
||||
for entry in walkdir::WalkDir::new(&self.testpaths.file).min_depth(1) {
|
||||
let entry = entry.unwrap();
|
||||
let path = entry.path();
|
||||
let path = <&Utf8Path>::try_from(path).unwrap();
|
||||
if path.file_name().is_some_and(|s| s != "rmake.rs") {
|
||||
let target = rmake_out_dir.join(path.strip_prefix(&self.testpaths.file).unwrap());
|
||||
if path.is_dir() {
|
||||
copy_dir_all(&path, target).unwrap();
|
||||
copy_dir_all(&path, &target).unwrap();
|
||||
} else {
|
||||
fs::copy(&path, target).unwrap();
|
||||
fs::copy(path.as_std_path(), target).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -83,8 +85,10 @@ impl TestCx<'_> {
|
||||
// on some linux distros.
|
||||
// 2. Specific library paths in `self.config.compile_lib_path` needed for running rustc.
|
||||
|
||||
let base_dylib_search_paths =
|
||||
Vec::from_iter(env::split_paths(&env::var(dylib_env_var()).unwrap()));
|
||||
let base_dylib_search_paths = Vec::from_iter(
|
||||
env::split_paths(&env::var(dylib_env_var()).unwrap())
|
||||
.map(|p| Utf8PathBuf::try_from(p).expect("dylib env var contains non-UTF8 paths")),
|
||||
);
|
||||
|
||||
// Calculate the paths of the recipe binary. As previously discussed, this is placed at
|
||||
// `<base_dir>/<bin_name>` with `bin_name` being `rmake` or `rmake.exe` depending on
|
||||
@ -113,13 +117,13 @@ impl TestCx<'_> {
|
||||
.arg("-o")
|
||||
.arg(&recipe_bin)
|
||||
// Specify library search paths for `run_make_support`.
|
||||
.arg(format!("-Ldependency={}", &support_lib_path.parent().unwrap().to_string_lossy()))
|
||||
.arg(format!("-Ldependency={}", &support_lib_deps.to_string_lossy()))
|
||||
.arg(format!("-Ldependency={}", &support_lib_deps_deps.to_string_lossy()))
|
||||
.arg(format!("-Ldependency={}", &support_lib_path.parent().unwrap()))
|
||||
.arg(format!("-Ldependency={}", &support_lib_deps))
|
||||
.arg(format!("-Ldependency={}", &support_lib_deps_deps))
|
||||
// Provide `run_make_support` as extern prelude, so test writers don't need to write
|
||||
// `extern run_make_support;`.
|
||||
.arg("--extern")
|
||||
.arg(format!("run_make_support={}", &support_lib_path.to_string_lossy()))
|
||||
.arg(format!("run_make_support={}", &support_lib_path))
|
||||
.arg("--edition=2021")
|
||||
.arg(&self.testpaths.file.join("rmake.rs"))
|
||||
.arg("-Cprefer-dynamic");
|
||||
@ -240,7 +244,7 @@ impl TestCx<'_> {
|
||||
if self.config.target.contains("msvc") && !self.config.cc.is_empty() {
|
||||
// We need to pass a path to `lib.exe`, so assume that `cc` is `cl.exe`
|
||||
// and that `lib.exe` lives next to it.
|
||||
let lib = Path::new(&self.config.cc).parent().unwrap().join("lib.exe");
|
||||
let lib = Utf8Path::new(&self.config.cc).parent().unwrap().join("lib.exe");
|
||||
|
||||
// MSYS doesn't like passing flags of the form `/foo` as it thinks it's
|
||||
// a path and instead passes `C:\msys64\foo`, so convert all
|
||||
@ -262,8 +266,8 @@ impl TestCx<'_> {
|
||||
|
||||
cmd.env("IS_MSVC", "1")
|
||||
.env("IS_WINDOWS", "1")
|
||||
.env("MSVC_LIB", format!("'{}' -nologo", lib.display()))
|
||||
.env("MSVC_LIB_PATH", format!("{}", lib.display()))
|
||||
.env("MSVC_LIB", format!("'{}' -nologo", lib))
|
||||
.env("MSVC_LIB_PATH", &lib)
|
||||
// Note: we diverge from legacy run_make and don't lump `CC` the compiler and
|
||||
// default flags together.
|
||||
.env("CC_DEFAULT_FLAGS", &cflags)
|
||||
|
@ -68,7 +68,7 @@ impl TestCx<'_> {
|
||||
{
|
||||
let mut coverage_file_path = self.config.build_test_suite_root.clone();
|
||||
coverage_file_path.push("rustfix_missing_coverage.txt");
|
||||
debug!("coverage_file_path: {}", coverage_file_path.display());
|
||||
debug!("coverage_file_path: {}", coverage_file_path);
|
||||
|
||||
let mut file = OpenOptions::new()
|
||||
.create(true)
|
||||
@ -76,8 +76,8 @@ impl TestCx<'_> {
|
||||
.open(coverage_file_path.as_path())
|
||||
.expect("could not create or open file");
|
||||
|
||||
if let Err(e) = writeln!(file, "{}", self.testpaths.file.display()) {
|
||||
panic!("couldn't write to {}: {e:?}", coverage_file_path.display());
|
||||
if let Err(e) = writeln!(file, "{}", self.testpaths.file) {
|
||||
panic!("couldn't write to {}: {e:?}", coverage_file_path);
|
||||
}
|
||||
}
|
||||
} else if self.props.run_rustfix {
|
||||
@ -119,7 +119,7 @@ impl TestCx<'_> {
|
||||
self.testpaths.relative_dir.join(self.testpaths.file.file_name().unwrap());
|
||||
println!(
|
||||
"To only update this specific test, also pass `--test-args {}`",
|
||||
relative_path_to_file.display(),
|
||||
relative_path_to_file,
|
||||
);
|
||||
self.fatal_proc_rec(
|
||||
&format!("{} errors occurred comparing output.", errors),
|
||||
@ -211,8 +211,6 @@ impl TestCx<'_> {
|
||||
let crate_name =
|
||||
self.testpaths.file.file_stem().expect("test must have a file stem");
|
||||
// crate name must be alphanumeric or `_`.
|
||||
let crate_name =
|
||||
crate_name.to_str().expect("crate name implies file name must be valid UTF-8");
|
||||
// replace `a.foo` -> `a__foo` for crate name purposes.
|
||||
// replace `revision-name-with-dashes` -> `revision_name_with_underscore`
|
||||
let crate_name = crate_name.replace('.', "__");
|
||||
|
@ -1,5 +1,3 @@
|
||||
use std::ffi::OsString;
|
||||
|
||||
use crate::debuggers::{extract_gdb_version, extract_lldb_version};
|
||||
use crate::is_test;
|
||||
|
||||
@ -60,11 +58,11 @@ fn test_extract_lldb_version() {
|
||||
|
||||
#[test]
|
||||
fn is_test_test() {
|
||||
assert!(is_test(&OsString::from("a_test.rs")));
|
||||
assert!(!is_test(&OsString::from(".a_test.rs")));
|
||||
assert!(!is_test(&OsString::from("a_cat.gif")));
|
||||
assert!(!is_test(&OsString::from("#a_dog_gif")));
|
||||
assert!(!is_test(&OsString::from("~a_temp_file")));
|
||||
assert!(is_test("a_test.rs"));
|
||||
assert!(!is_test(".a_test.rs"));
|
||||
assert!(!is_test("a_cat.gif"));
|
||||
assert!(!is_test("#a_dog_gif"));
|
||||
assert!(!is_test("~a_temp_file"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1,8 +1,7 @@
|
||||
use std::env;
|
||||
use std::ffi::OsStr;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
|
||||
use camino::{Utf8Path, Utf8PathBuf};
|
||||
use tracing::*;
|
||||
|
||||
use crate::common::Config;
|
||||
@ -34,21 +33,21 @@ pub fn logv(config: &Config, s: String) {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait PathBufExt {
|
||||
pub trait Utf8PathBufExt {
|
||||
/// Append an extension to the path, even if it already has one.
|
||||
fn with_extra_extension<S: AsRef<OsStr>>(&self, extension: S) -> PathBuf;
|
||||
fn with_extra_extension(&self, extension: &str) -> Utf8PathBuf;
|
||||
}
|
||||
|
||||
impl PathBufExt for PathBuf {
|
||||
fn with_extra_extension<S: AsRef<OsStr>>(&self, extension: S) -> PathBuf {
|
||||
if extension.as_ref().is_empty() {
|
||||
impl Utf8PathBufExt for Utf8PathBuf {
|
||||
fn with_extra_extension(&self, extension: &str) -> Utf8PathBuf {
|
||||
if extension.is_empty() {
|
||||
self.clone()
|
||||
} else {
|
||||
let mut fname = self.file_name().unwrap().to_os_string();
|
||||
if !extension.as_ref().to_str().unwrap().starts_with('.') {
|
||||
fname.push(".");
|
||||
let mut fname = self.file_name().unwrap().to_string();
|
||||
if !extension.starts_with('.') {
|
||||
fname.push_str(".");
|
||||
}
|
||||
fname.push(extension);
|
||||
fname.push_str(extension);
|
||||
self.with_file_name(fname)
|
||||
}
|
||||
}
|
||||
@ -71,22 +70,27 @@ pub fn dylib_env_var() -> &'static str {
|
||||
|
||||
/// Adds a list of lookup paths to `cmd`'s dynamic library lookup path.
|
||||
/// If the dylib_path_var is already set for this cmd, the old value will be overwritten!
|
||||
pub fn add_dylib_path(cmd: &mut Command, paths: impl Iterator<Item = impl Into<PathBuf>>) {
|
||||
pub fn add_dylib_path(
|
||||
cmd: &mut Command,
|
||||
paths: impl Iterator<Item = impl Into<std::path::PathBuf>>,
|
||||
) {
|
||||
let path_env = env::var_os(dylib_env_var());
|
||||
let old_paths = path_env.as_ref().map(env::split_paths);
|
||||
let new_paths = paths.map(Into::into).chain(old_paths.into_iter().flatten());
|
||||
cmd.env(dylib_env_var(), env::join_paths(new_paths).unwrap());
|
||||
}
|
||||
|
||||
pub fn copy_dir_all(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> std::io::Result<()> {
|
||||
std::fs::create_dir_all(&dst)?;
|
||||
for entry in std::fs::read_dir(src)? {
|
||||
pub fn copy_dir_all(src: &Utf8Path, dst: &Utf8Path) -> std::io::Result<()> {
|
||||
std::fs::create_dir_all(dst.as_std_path())?;
|
||||
for entry in std::fs::read_dir(src.as_std_path())? {
|
||||
let entry = entry?;
|
||||
let path = Utf8PathBuf::try_from(entry.path()).unwrap();
|
||||
let file_name = path.file_name().unwrap();
|
||||
let ty = entry.file_type()?;
|
||||
if ty.is_dir() {
|
||||
copy_dir_all(entry.path(), dst.as_ref().join(entry.file_name()))?;
|
||||
copy_dir_all(&path, &dst.join(file_name))?;
|
||||
} else {
|
||||
std::fs::copy(entry.path(), dst.as_ref().join(entry.file_name()))?;
|
||||
std::fs::copy(path.as_std_path(), dst.join(file_name).as_std_path())?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
@ -3,12 +3,12 @@ use super::*;
|
||||
#[test]
|
||||
fn path_buf_with_extra_extension_test() {
|
||||
assert_eq!(
|
||||
PathBuf::from("foo.rs.stderr"),
|
||||
PathBuf::from("foo.rs").with_extra_extension("stderr")
|
||||
Utf8PathBuf::from("foo.rs.stderr"),
|
||||
Utf8PathBuf::from("foo.rs").with_extra_extension("stderr")
|
||||
);
|
||||
assert_eq!(
|
||||
PathBuf::from("foo.rs.stderr"),
|
||||
PathBuf::from("foo.rs").with_extra_extension(".stderr")
|
||||
Utf8PathBuf::from("foo.rs.stderr"),
|
||||
Utf8PathBuf::from("foo.rs").with_extra_extension(".stderr")
|
||||
);
|
||||
assert_eq!(PathBuf::from("foo.rs"), PathBuf::from("foo.rs").with_extra_extension(""));
|
||||
assert_eq!(Utf8PathBuf::from("foo.rs"), Utf8PathBuf::from("foo.rs").with_extra_extension(""));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user