1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
|
//! The common code for `tests/lang_tests_*.rs`
use std::env::{self, current_dir};
use std::path::{Path, PathBuf};
use std::process::Command;
use boml::Toml;
use lang_tester::LangTester;
use tempfile::TempDir;
/// Controls the compile options (e.g., optimization level) used to compile
/// test code.
#[allow(dead_code)] // Each test crate picks one variant
pub enum Profile {
Debug,
Release,
}
pub fn main_inner(profile: Profile) {
let tempdir = TempDir::new().expect("temp dir");
let current_dir = current_dir().expect("current dir");
let current_dir = current_dir.to_str().expect("current dir").to_string();
let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR"));
let gcc_path = std::fs::read_to_string(manifest_dir.join("config.toml"))
.ok()
.and_then(|v| {
let toml = Toml::parse(&v).expect("Failed to parse `config.toml`");
toml.get_string("gcc-path").map(PathBuf::from).ok()
})
.unwrap_or_else(|| {
// then we try to retrieve it from the `target` folder.
let commit = include_str!("../libgccjit.version").trim();
Path::new("build/libgccjit").join(commit)
});
let gcc_path = Path::new(&gcc_path)
.canonicalize()
.expect("failed to get absolute path of `gcc-path`")
.display()
.to_string();
env::set_var("LD_LIBRARY_PATH", gcc_path);
fn rust_filter(path: &Path) -> bool {
path.is_file() && path.extension().expect("extension").to_str().expect("to_str") == "rs"
}
#[cfg(feature = "master")]
fn filter(filename: &Path) -> bool {
rust_filter(filename)
}
#[cfg(not(feature = "master"))]
fn filter(filename: &Path) -> bool {
if let Some(filename) = filename.to_str() {
if filename.ends_with("gep.rs") {
return false;
}
}
rust_filter(filename)
}
LangTester::new()
.test_dir("tests/run")
.test_path_filter(filter)
.test_extract(|path| {
let lines = std::fs::read_to_string(path)
.expect("read file")
.lines()
.skip_while(|l| !l.starts_with("//"))
.take_while(|l| l.starts_with("//"))
.map(|l| &l[2..])
.collect::<Vec<_>>()
.join("\n");
lines
})
.test_cmds(move |path| {
// Test command 1: Compile `x.rs` into `tempdir/x`.
let mut exe = PathBuf::new();
exe.push(&tempdir);
exe.push(path.file_stem().expect("file_stem"));
let mut compiler = Command::new("rustc");
compiler.args([
&format!("-Zcodegen-backend={}/target/debug/librustc_codegen_gcc.so", current_dir),
"--sysroot",
&format!("{}/build/build_sysroot/sysroot/", current_dir),
"-C",
"link-arg=-lc",
"--extern",
"mini_core=target/out/libmini_core.rlib",
"-o",
exe.to_str().expect("to_str"),
path.to_str().expect("to_str"),
]);
// TODO(antoyo): find a way to send this via a cli argument.
let test_target = std::env::var("CG_GCC_TEST_TARGET");
if let Ok(ref target) = test_target {
compiler.args(["--target", target]);
let linker = format!("{}-gcc", target);
compiler.args(&[format!("-Clinker={}", linker)]);
let mut env_path = std::env::var("PATH").unwrap_or_default();
// TODO(antoyo): find a better way to add the PATH necessary locally.
env_path = format!("/opt/m68k-unknown-linux-gnu/bin:{}", env_path);
compiler.env("PATH", env_path);
}
if let Some(flags) = option_env!("TEST_FLAGS") {
for flag in flags.split_whitespace() {
compiler.arg(flag);
}
}
match profile {
Profile::Debug => {}
Profile::Release => {
compiler.args(["-C", "opt-level=3", "-C", "lto=no"]);
}
}
// Test command 2: run `tempdir/x`.
if test_target.is_ok() {
let vm_parent_dir = std::env::var("CG_GCC_VM_DIR")
.map(PathBuf::from)
.unwrap_or_else(|_| std::env::current_dir().unwrap());
let vm_dir = "vm";
let exe_filename = exe.file_name().unwrap();
let vm_home_dir = vm_parent_dir.join(vm_dir).join("home");
let vm_exe_path = vm_home_dir.join(exe_filename);
// FIXME(antoyo): panicking here makes the test pass.
let inside_vm_exe_path = PathBuf::from("/home").join(exe_filename);
let mut copy = Command::new("sudo");
copy.arg("cp");
copy.args([&exe, &vm_exe_path]);
let mut runtime = Command::new("sudo");
runtime.args(["chroot", vm_dir, "qemu-m68k-static"]);
runtime.arg(inside_vm_exe_path);
runtime.current_dir(vm_parent_dir);
vec![("Compiler", compiler), ("Copy", copy), ("Run-time", runtime)]
} else {
let runtime = Command::new(exe);
vec![("Compiler", compiler), ("Run-time", runtime)]
}
})
.run();
}
|