|
| 1 | +#![allow(clippy::uninlined_format_args)] |
| 2 | + |
| 3 | +use std::env::current_dir; |
| 4 | +use std::path::{Path, PathBuf}; |
| 5 | +use std::process::Command; |
| 6 | + |
| 7 | +use lang_tester::LangTester; |
| 8 | +use tempfile::TempDir; |
| 9 | + |
| 10 | +fn compile_and_run_cmds( |
| 11 | + compiler_args: Vec<String>, |
| 12 | + test_target: &Option<String>, |
| 13 | + exe: &Path, |
| 14 | +) -> Vec<(&'static str, Command)> { |
| 15 | + let mut compiler = Command::new("rustc"); |
| 16 | + compiler.args(compiler_args); |
| 17 | + |
| 18 | + // Test command 2: run `tempdir/x`. |
| 19 | + if test_target.is_some() { |
| 20 | + let mut env_path = std::env::var("PATH").unwrap_or_default(); |
| 21 | + // TODO(antoyo): find a better way to add the PATH necessary locally. |
| 22 | + env_path = format!("/opt/m68k-unknown-linux-gnu/bin:{}", env_path); |
| 23 | + compiler.env("PATH", env_path); |
| 24 | + |
| 25 | + let vm_parent_dir = std::env::var("CG_GCC_VM_DIR") |
| 26 | + .map(PathBuf::from) |
| 27 | + .unwrap_or_else(|_| std::env::current_dir().unwrap()); |
| 28 | + let vm_dir = "vm"; |
| 29 | + let exe_filename = exe.file_name().unwrap(); |
| 30 | + let vm_home_dir = vm_parent_dir.join(vm_dir).join("home"); |
| 31 | + let vm_exe_path = vm_home_dir.join(exe_filename); |
| 32 | + // FIXME(antoyo): panicking here makes the test pass. |
| 33 | + let inside_vm_exe_path = PathBuf::from("/home").join(exe_filename); |
| 34 | + let mut copy = Command::new("sudo"); |
| 35 | + copy.arg("cp"); |
| 36 | + copy.args([exe, &vm_exe_path]); |
| 37 | + |
| 38 | + let mut runtime = Command::new("sudo"); |
| 39 | + runtime.args(["chroot", vm_dir, "qemu-m68k-static"]); |
| 40 | + runtime.arg(inside_vm_exe_path); |
| 41 | + runtime.current_dir(vm_parent_dir); |
| 42 | + vec![("Compiler", compiler), ("Copy", copy), ("Run-time", runtime)] |
| 43 | + } else { |
| 44 | + let runtime = Command::new(exe); |
| 45 | + vec![("Compiler", compiler), ("Run-time", runtime)] |
| 46 | + } |
| 47 | +} |
| 48 | + |
| 49 | +fn run_tests(tempdir: PathBuf, current_dir: String, is_debug: bool) { |
| 50 | + fn rust_filter(path: &Path) -> bool { |
| 51 | + path.is_file() && path.extension().expect("extension").to_str().expect("to_str") == "rs" |
| 52 | + } |
| 53 | + |
| 54 | + #[cfg(feature = "master")] |
| 55 | + fn filter(filename: &Path) -> bool { |
| 56 | + rust_filter(filename) |
| 57 | + } |
| 58 | + |
| 59 | + #[cfg(not(feature = "master"))] |
| 60 | + fn filter(filename: &Path) -> bool { |
| 61 | + if let Some(filename) = filename.to_str() |
| 62 | + && filename.ends_with("gep.rs") |
| 63 | + { |
| 64 | + return false; |
| 65 | + } |
| 66 | + rust_filter(filename) |
| 67 | + } |
| 68 | + |
| 69 | + if is_debug { |
| 70 | + println!("=== [DEBUG] lang tests ==="); |
| 71 | + } else { |
| 72 | + println!("=== [RELEASE] lang tests ==="); |
| 73 | + } |
| 74 | + |
| 75 | + LangTester::new() |
| 76 | + .test_dir("tests/run") |
| 77 | + .test_path_filter(filter) |
| 78 | + .test_extract(|path| { |
| 79 | + std::fs::read_to_string(path) |
| 80 | + .expect("read file") |
| 81 | + .lines() |
| 82 | + .skip_while(|l| !l.starts_with("//")) |
| 83 | + .take_while(|l| l.starts_with("//")) |
| 84 | + .map(|l| &l[2..]) |
| 85 | + .collect::<Vec<_>>() |
| 86 | + .join("\n") |
| 87 | + }) |
| 88 | + .test_cmds(move |path| { |
| 89 | + // Test command 1: Compile `x.rs` into `tempdir/x`. |
| 90 | + let mut exe = PathBuf::new(); |
| 91 | + exe.push(&tempdir); |
| 92 | + exe.push(path.file_stem().expect("file_stem")); |
| 93 | + let mut compiler_args = vec![ |
| 94 | + format!("-Zcodegen-backend={}/target/debug/librustc_codegen_gcc.so", current_dir), |
| 95 | + "--sysroot".into(), |
| 96 | + format!("{}/build/build_sysroot/sysroot/", current_dir), |
| 97 | + "-C".into(), |
| 98 | + "link-arg=-lc".into(), |
| 99 | + "--extern".into(), |
| 100 | + "mini_core=target/out/libmini_core.rlib".into(), |
| 101 | + "-o".into(), |
| 102 | + exe.to_str().expect("to_str").into(), |
| 103 | + path.to_str().expect("to_str").into(), |
| 104 | + ]; |
| 105 | + // TODO(antoyo): find a way to send this via a cli argument. |
| 106 | + let test_target = std::env::var("CG_GCC_TEST_TARGET").ok(); |
| 107 | + |
| 108 | + if let Some(ref target) = test_target { |
| 109 | + compiler_args.extend_from_slice(&["--target".into(), target.into()]); |
| 110 | + |
| 111 | + let linker = format!("{}-gcc", target); |
| 112 | + compiler_args.push(format!("-Clinker={}", linker)); |
| 113 | + } |
| 114 | + |
| 115 | + if let Some(flags) = option_env!("TEST_FLAGS") { |
| 116 | + for flag in flags.split_whitespace() { |
| 117 | + compiler_args.push(flag.into()); |
| 118 | + } |
| 119 | + } |
| 120 | + |
| 121 | + if is_debug { |
| 122 | + compiler_args |
| 123 | + .extend_from_slice(&["-C".to_string(), "llvm-args=sanitize-undefined".into()]); |
| 124 | + if test_target.is_none() { |
| 125 | + // m68k doesn't have lubsan for now |
| 126 | + compiler_args.extend_from_slice(&["-C".into(), "link-args=-lubsan".into()]); |
| 127 | + } |
| 128 | + } else { |
| 129 | + compiler_args.extend_from_slice(&[ |
| 130 | + "-C".into(), |
| 131 | + "opt-level=3".into(), |
| 132 | + "-C".into(), |
| 133 | + "lto=no".into(), |
| 134 | + ]); |
| 135 | + } |
| 136 | + |
| 137 | + compile_and_run_cmds(compiler_args, &test_target, &exe) |
| 138 | + }) |
| 139 | + .run(); |
| 140 | +} |
| 141 | + |
| 142 | +fn main() { |
| 143 | + let tempdir = TempDir::new().expect("temp dir"); |
| 144 | + let current_dir = current_dir().expect("current dir"); |
| 145 | + let current_dir = current_dir.to_str().expect("current dir").to_string(); |
| 146 | + |
| 147 | + let tempdir_path: PathBuf = tempdir.as_ref().into(); |
| 148 | + run_tests(tempdir_path.clone(), current_dir.clone(), true); |
| 149 | + run_tests(tempdir_path, current_dir, false); |
| 150 | +} |
0 commit comments