1 use super::build_sysroot;
3 use super::path::{Dirs, RelPath};
4 use super::prepare::GitRepo;
5 use super::rustc_info::{get_cargo_path, get_wrapper_file_name};
7 hyperfine_command, spawn_and_wait, spawn_and_wait_with_input, CargoProject, Compiler,
9 use super::SysrootKind;
14 use std::process::Command;
16 static BUILD_EXAMPLE_OUT_DIR: RelPath = RelPath::BUILD.join("example");
20 func: &'static dyn Fn(&TestRunner),
24 const fn new(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self {
29 const NO_SYSROOT_SUITE: &[TestCase] = &[
30 TestCase::new("build.mini_core", &|runner| {
32 "example/mini_core.rs",
38 &runner.target_compiler.triple,
41 TestCase::new("build.example", &|runner| {
47 &runner.target_compiler.triple,
50 TestCase::new("jit.mini_core_hello_world", &|runner| {
51 let mut jit_cmd = runner.rustc_command([
53 "-Cllvm-args=mode=jit",
55 "example/mini_core_hello_world.rs",
59 &runner.target_compiler.triple,
61 jit_cmd.env("CG_CLIF_JIT_ARGS", "abc bcd");
62 spawn_and_wait(jit_cmd);
64 eprintln!("[JIT-lazy] mini_core_hello_world");
65 let mut jit_cmd = runner.rustc_command([
67 "-Cllvm-args=mode=jit-lazy",
69 "example/mini_core_hello_world.rs",
73 &runner.target_compiler.triple,
75 jit_cmd.env("CG_CLIF_JIT_ARGS", "abc bcd");
76 spawn_and_wait(jit_cmd);
78 TestCase::new("aot.mini_core_hello_world", &|runner| {
80 "example/mini_core_hello_world.rs",
82 "mini_core_hello_world",
87 &runner.target_compiler.triple,
89 runner.run_out_command("mini_core_hello_world", ["abc", "bcd"]);
93 const BASE_SYSROOT_SUITE: &[TestCase] = &[
94 TestCase::new("aot.arbitrary_self_types_pointers_and_wrappers", &|runner| {
96 "example/arbitrary_self_types_pointers_and_wrappers.rs",
98 "arbitrary_self_types_pointers_and_wrappers",
102 &runner.target_compiler.triple,
104 runner.run_out_command("arbitrary_self_types_pointers_and_wrappers", []);
106 TestCase::new("aot.issue_91827_extern_types", &|runner| {
108 "example/issue-91827-extern-types.rs",
110 "issue_91827_extern_types",
114 &runner.target_compiler.triple,
116 runner.run_out_command("issue_91827_extern_types", []);
118 TestCase::new("build.alloc_system", &|runner| {
120 "example/alloc_system.rs",
124 &runner.target_compiler.triple,
127 TestCase::new("aot.alloc_example", &|runner| {
129 "example/alloc_example.rs",
133 &runner.target_compiler.triple,
135 runner.run_out_command("alloc_example", []);
137 TestCase::new("jit.std_example", &|runner| {
139 "-Zunstable-options",
140 "-Cllvm-args=mode=jit",
142 "example/std_example.rs",
144 &runner.target_compiler.triple,
147 eprintln!("[JIT-lazy] std_example");
149 "-Zunstable-options",
150 "-Cllvm-args=mode=jit-lazy",
152 "example/std_example.rs",
154 &runner.target_compiler.triple,
157 TestCase::new("aot.std_example", &|runner| {
159 "example/std_example.rs",
163 &runner.target_compiler.triple,
165 runner.run_out_command("std_example", ["arg"]);
167 TestCase::new("aot.dst_field_align", &|runner| {
169 "example/dst-field-align.rs",
175 &runner.target_compiler.triple,
177 runner.run_out_command("dst_field_align", []);
179 TestCase::new("aot.subslice-patterns-const-eval", &|runner| {
181 "example/subslice-patterns-const-eval.rs",
186 &runner.target_compiler.triple,
188 runner.run_out_command("subslice-patterns-const-eval", []);
190 TestCase::new("aot.track-caller-attribute", &|runner| {
192 "example/track-caller-attribute.rs",
197 &runner.target_compiler.triple,
199 runner.run_out_command("track-caller-attribute", []);
201 TestCase::new("aot.float-minmax-pass", &|runner| {
203 "example/float-minmax-pass.rs",
208 &runner.target_compiler.triple,
210 runner.run_out_command("float-minmax-pass", []);
212 TestCase::new("aot.mod_bench", &|runner| {
214 "example/mod_bench.rs",
218 &runner.target_compiler.triple,
220 runner.run_out_command("mod_bench", []);
222 TestCase::new("aot.issue-72793", &|runner| {
224 "example/issue-72793.rs",
228 &runner.target_compiler.triple,
230 runner.run_out_command("issue-72793", []);
234 pub(crate) static RAND_REPO: GitRepo =
235 GitRepo::github("rust-random", "rand", "0f933f9c7176e53b2a3c7952ded484e1783f0bf1", "rand");
237 static RAND: CargoProject = CargoProject::new(&RAND_REPO.source_dir(), "rand");
239 pub(crate) static REGEX_REPO: GitRepo =
240 GitRepo::github("rust-lang", "regex", "341f207c1071f7290e3f228c710817c280c8dca1", "regex");
242 static REGEX: CargoProject = CargoProject::new(®EX_REPO.source_dir(), "regex");
244 pub(crate) static PORTABLE_SIMD_REPO: GitRepo = GitRepo::github(
247 "d5cd4a8112d958bd3a252327e0d069a6363249bd",
251 static PORTABLE_SIMD: CargoProject =
252 CargoProject::new(&PORTABLE_SIMD_REPO.source_dir(), "portable_simd");
254 pub(crate) static SIMPLE_RAYTRACER_REPO: GitRepo = GitRepo::github(
257 "804a7a21b9e673a482797aa289a18ed480e4d813",
261 pub(crate) static SIMPLE_RAYTRACER: CargoProject =
262 CargoProject::new(&SIMPLE_RAYTRACER_REPO.source_dir(), "simple_raytracer");
264 static LIBCORE_TESTS: CargoProject =
265 CargoProject::new(&RelPath::BUILD_SYSROOT.join("sysroot_src/library/core/tests"), "core_tests");
267 const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[
268 TestCase::new("test.rust-random/rand", &|runner| {
269 spawn_and_wait(RAND.clean(&runner.target_compiler.cargo, &runner.dirs));
271 if runner.is_native {
272 eprintln!("[TEST] rust-random/rand");
273 let mut test_cmd = RAND.test(&runner.target_compiler, &runner.dirs);
274 test_cmd.arg("--workspace");
275 spawn_and_wait(test_cmd);
277 eprintln!("[AOT] rust-random/rand");
278 let mut build_cmd = RAND.build(&runner.target_compiler, &runner.dirs);
279 build_cmd.arg("--workspace").arg("--tests");
280 spawn_and_wait(build_cmd);
283 TestCase::new("bench.simple-raytracer", &|runner| {
284 let run_runs = env::var("RUN_RUNS").unwrap_or("10".to_string()).parse().unwrap();
286 if runner.is_native {
287 eprintln!("[BENCH COMPILE] ebobby/simple-raytracer");
288 let cargo_clif = RelPath::DIST
289 .to_path(&runner.dirs)
290 .join(get_wrapper_file_name("cargo-clif", "bin"));
291 let manifest_path = SIMPLE_RAYTRACER.manifest_path(&runner.dirs);
292 let target_dir = SIMPLE_RAYTRACER.target_dir(&runner.dirs);
294 let clean_cmd = format!(
295 "cargo clean --manifest-path {manifest_path} --target-dir {target_dir}",
296 manifest_path = manifest_path.display(),
297 target_dir = target_dir.display(),
299 let llvm_build_cmd = format!(
300 "cargo build --manifest-path {manifest_path} --target-dir {target_dir}",
301 manifest_path = manifest_path.display(),
302 target_dir = target_dir.display(),
304 let clif_build_cmd = format!(
305 "{cargo_clif} build --manifest-path {manifest_path} --target-dir {target_dir}",
306 cargo_clif = cargo_clif.display(),
307 manifest_path = manifest_path.display(),
308 target_dir = target_dir.display(),
312 hyperfine_command(1, run_runs, Some(&clean_cmd), &llvm_build_cmd, &clif_build_cmd);
314 spawn_and_wait(bench_compile);
316 eprintln!("[BENCH RUN] ebobby/simple-raytracer");
318 target_dir.join("debug").join("main"),
319 RelPath::BUILD.to_path(&runner.dirs).join("raytracer_cg_clif"),
324 hyperfine_command(0, run_runs, None, "./raytracer_cg_llvm", "./raytracer_cg_clif");
325 bench_run.current_dir(RelPath::BUILD.to_path(&runner.dirs));
326 spawn_and_wait(bench_run);
328 spawn_and_wait(SIMPLE_RAYTRACER.clean(&runner.target_compiler.cargo, &runner.dirs));
329 eprintln!("[BENCH COMPILE] ebobby/simple-raytracer (skipped)");
330 eprintln!("[COMPILE] ebobby/simple-raytracer");
331 spawn_and_wait(SIMPLE_RAYTRACER.build(&runner.target_compiler, &runner.dirs));
332 eprintln!("[BENCH RUN] ebobby/simple-raytracer (skipped)");
335 TestCase::new("test.libcore", &|runner| {
336 spawn_and_wait(LIBCORE_TESTS.clean(&runner.host_compiler.cargo, &runner.dirs));
338 if runner.is_native {
339 spawn_and_wait(LIBCORE_TESTS.test(&runner.target_compiler, &runner.dirs));
341 eprintln!("Cross-Compiling: Not running tests");
342 let mut build_cmd = LIBCORE_TESTS.build(&runner.target_compiler, &runner.dirs);
343 build_cmd.arg("--tests");
344 spawn_and_wait(build_cmd);
347 TestCase::new("test.regex-shootout-regex-dna", &|runner| {
348 spawn_and_wait(REGEX.clean(&runner.target_compiler.cargo, &runner.dirs));
350 // newer aho_corasick versions throw a deprecation warning
351 let lint_rust_flags = format!("{} --cap-lints warn", runner.target_compiler.rustflags);
353 let mut build_cmd = REGEX.build(&runner.target_compiler, &runner.dirs);
354 build_cmd.arg("--example").arg("shootout-regex-dna");
355 build_cmd.env("RUSTFLAGS", lint_rust_flags.clone());
356 spawn_and_wait(build_cmd);
358 if runner.is_native {
359 let mut run_cmd = REGEX.run(&runner.target_compiler, &runner.dirs);
360 run_cmd.arg("--example").arg("shootout-regex-dna");
361 run_cmd.env("RUSTFLAGS", lint_rust_flags);
363 let input = fs::read_to_string(
364 REGEX.source_dir(&runner.dirs).join("examples").join("regexdna-input.txt"),
368 REGEX.source_dir(&runner.dirs).join("examples").join("regexdna-output.txt");
369 let expected = fs::read_to_string(&expected_path).unwrap();
371 let output = spawn_and_wait_with_input(run_cmd, input);
372 // Make sure `[codegen mono items] start` doesn't poison the diff
375 .filter(|line| !line.contains("codegen mono items"))
376 .chain(Some("")) // This just adds the trailing newline
377 .collect::<Vec<&str>>()
380 let output_matches = expected.lines().eq(output.lines());
382 let res_path = REGEX.source_dir(&runner.dirs).join("res.txt");
383 fs::write(&res_path, &output).unwrap();
386 println!("Output files don't match!");
387 println!("Expected Output:\n{}", expected);
388 println!("Actual Output:\n{}", output);
390 let mut diff = Command::new("diff");
393 diff.arg(expected_path);
394 spawn_and_wait(diff);
397 std::process::exit(1);
401 TestCase::new("test.regex", &|runner| {
402 spawn_and_wait(REGEX.clean(&runner.host_compiler.cargo, &runner.dirs));
404 // newer aho_corasick versions throw a deprecation warning
405 let lint_rust_flags = format!("{} --cap-lints warn", runner.target_compiler.rustflags);
407 if runner.is_native {
408 let mut run_cmd = REGEX.test(&runner.target_compiler, &runner.dirs);
412 "--exclude-should-panic",
415 "-Zunstable-options",
418 run_cmd.env("RUSTFLAGS", lint_rust_flags);
419 spawn_and_wait(run_cmd);
421 eprintln!("Cross-Compiling: Not running tests");
422 let mut build_cmd = REGEX.build(&runner.target_compiler, &runner.dirs);
423 build_cmd.arg("--tests");
424 build_cmd.env("RUSTFLAGS", lint_rust_flags.clone());
425 spawn_and_wait(build_cmd);
428 TestCase::new("test.portable-simd", &|runner| {
429 spawn_and_wait(PORTABLE_SIMD.clean(&runner.host_compiler.cargo, &runner.dirs));
431 let mut build_cmd = PORTABLE_SIMD.build(&runner.target_compiler, &runner.dirs);
432 build_cmd.arg("--all-targets");
433 spawn_and_wait(build_cmd);
435 if runner.is_native {
436 let mut test_cmd = PORTABLE_SIMD.test(&runner.target_compiler, &runner.dirs);
438 spawn_and_wait(test_cmd);
443 pub(crate) fn run_tests(
446 sysroot_kind: SysrootKind,
447 cg_clif_dylib: &Path,
451 let runner = TestRunner::new(dirs.clone(), host_triple.to_string(), target_triple.to_string());
453 if config::get_bool("testsuite.no_sysroot") {
454 build_sysroot::build_sysroot(
463 BUILD_EXAMPLE_OUT_DIR.ensure_fresh(dirs);
464 runner.run_testsuite(NO_SYSROOT_SUITE);
466 eprintln!("[SKIP] no_sysroot tests");
469 let run_base_sysroot = config::get_bool("testsuite.base_sysroot");
470 let run_extended_sysroot = config::get_bool("testsuite.extended_sysroot");
472 if run_base_sysroot || run_extended_sysroot {
473 build_sysroot::build_sysroot(
483 if run_base_sysroot {
484 runner.run_testsuite(BASE_SYSROOT_SUITE);
486 eprintln!("[SKIP] base_sysroot tests");
489 if run_extended_sysroot {
490 runner.run_testsuite(EXTENDED_SYSROOT_SUITE);
492 eprintln!("[SKIP] extended_sysroot tests");
500 host_compiler: Compiler,
501 target_compiler: Compiler,
505 pub fn new(dirs: Dirs, host_triple: String, target_triple: String) -> Self {
506 let is_native = host_triple == target_triple;
508 target_triple.contains("x86_64") && is_native && !host_triple.contains("windows");
511 RelPath::DIST.to_path(&dirs).join(get_wrapper_file_name("rustc-clif", "bin"));
513 RelPath::DIST.to_path(&dirs).join(get_wrapper_file_name("rustdoc-clif", "bin"));
515 let mut rustflags = env::var("RUSTFLAGS").ok().unwrap_or("".to_string());
516 let mut runner = vec![];
519 match target_triple.as_str() {
520 "aarch64-unknown-linux-gnu" => {
521 // We are cross-compiling for aarch64. Use the correct linker and run tests in qemu.
522 rustflags = format!("-Clinker=aarch64-linux-gnu-gcc{}", rustflags);
524 "qemu-aarch64".to_owned(),
526 "/usr/aarch64-linux-gnu".to_owned(),
529 "s390x-unknown-linux-gnu" => {
530 // We are cross-compiling for s390x. Use the correct linker and run tests in qemu.
531 rustflags = format!("-Clinker=s390x-linux-gnu-gcc{}", rustflags);
533 "qemu-s390x".to_owned(),
535 "/usr/s390x-linux-gnu".to_owned(),
538 "x86_64-pc-windows-gnu" => {
539 // We are cross-compiling for Windows. Run tests in wine.
540 runner = vec!["wine".to_owned()];
543 println!("Unknown non-native platform");
548 // FIXME fix `#[linkage = "extern_weak"]` without this
549 if target_triple.contains("darwin") {
550 rustflags = format!("{} -Clink-arg=-undefined -Clink-arg=dynamic_lookup", rustflags);
553 let host_compiler = Compiler {
554 cargo: get_cargo_path(),
555 rustc: rustc_clif.clone(),
556 rustdoc: rustdoc_clif.clone(),
557 rustflags: String::new(),
558 rustdocflags: String::new(),
563 let target_compiler = Compiler {
564 cargo: get_cargo_path(),
566 rustdoc: rustdoc_clif,
567 rustflags: rustflags.clone(),
568 rustdocflags: rustflags,
569 triple: target_triple,
573 Self { is_native, jit_supported, dirs, host_compiler, target_compiler }
576 pub fn run_testsuite(&self, tests: &[TestCase]) {
577 for &TestCase { config, func } in tests {
578 let (tag, testname) = config.split_once('.').unwrap();
579 let tag = tag.to_uppercase();
580 let is_jit_test = tag == "JIT";
582 if !config::get_bool(config) || (is_jit_test && !self.jit_supported) {
583 eprintln!("[{tag}] {testname} (skipped)");
586 eprintln!("[{tag}] {testname}");
594 fn rustc_command<I, S>(&self, args: I) -> Command
596 I: IntoIterator<Item = S>,
599 let mut cmd = Command::new(&self.target_compiler.rustc);
600 cmd.args(self.target_compiler.rustflags.split_whitespace());
602 cmd.arg(format!("crate={}", BUILD_EXAMPLE_OUT_DIR.to_path(&self.dirs).display()));
603 cmd.arg("--out-dir");
604 cmd.arg(format!("{}", BUILD_EXAMPLE_OUT_DIR.to_path(&self.dirs).display()));
605 cmd.arg("-Cdebuginfo=2");
610 fn run_rustc<I, S>(&self, args: I)
612 I: IntoIterator<Item = S>,
615 spawn_and_wait(self.rustc_command(args));
618 fn run_out_command<'a, I>(&self, name: &str, args: I)
620 I: IntoIterator<Item = &'a str>,
622 let mut full_cmd = vec![];
624 // Prepend the RUN_WRAPPER's
625 if !self.target_compiler.runner.is_empty() {
626 full_cmd.extend(self.target_compiler.runner.iter().cloned());
630 BUILD_EXAMPLE_OUT_DIR.to_path(&self.dirs).join(name).to_str().unwrap().to_string(),
633 for arg in args.into_iter() {
634 full_cmd.push(arg.to_string());
637 let mut cmd_iter = full_cmd.into_iter();
638 let first = cmd_iter.next().unwrap();
640 let mut cmd = Command::new(first);