2018-12-10 03:21:28 +00:00
|
|
|
//! This file will run at build time to autogenerate the Emscripten tests
|
|
|
|
//! It will compile the files indicated in TESTS, to:executable and .wasm
|
|
|
|
//! - Compile using cc and get the output from it (expected output)
|
|
|
|
//! - Compile using emcc and get the .wasm from it (wasm)
|
|
|
|
//! - Generate the test that will compare the output of running the .wasm file
|
|
|
|
//! with wasmer with the expected output
|
2018-12-27 07:43:38 +00:00
|
|
|
use glob::glob;
|
2019-05-17 19:09:31 +00:00
|
|
|
use std::collections::HashSet;
|
2018-12-10 03:21:28 +00:00
|
|
|
use std::fs;
|
2018-12-27 07:43:38 +00:00
|
|
|
use std::path::Path;
|
2018-12-10 03:21:28 +00:00
|
|
|
use std::path::PathBuf;
|
2018-12-11 01:06:55 +00:00
|
|
|
use std::process::Command;
|
|
|
|
|
2018-12-27 07:43:38 +00:00
|
|
|
use std::fs::File;
|
|
|
|
use std::io::prelude::*;
|
|
|
|
use std::io::BufReader;
|
|
|
|
|
2018-12-10 03:21:28 +00:00
|
|
|
static BANNER: &str = "// Rust test file autogenerated with cargo build (build/emtests.rs).
|
|
|
|
// Please do NOT modify it by hand, as it will be reseted on next build.\n";
|
|
|
|
|
2018-12-27 07:43:38 +00:00
|
|
|
const EXTENSIONS: [&str; 2] = ["c", "cpp"];
|
2018-12-28 11:42:41 +00:00
|
|
|
const EXCLUDES: [&str; 0] = [];
|
2018-12-10 03:21:28 +00:00
|
|
|
|
2019-05-17 19:09:31 +00:00
|
|
|
pub fn compile(file: &str, ignores: &HashSet<String>) -> Option<String> {
|
2018-12-11 01:06:55 +00:00
|
|
|
let mut output_path = PathBuf::from(file);
|
|
|
|
output_path.set_extension("out");
|
2018-12-27 07:43:38 +00:00
|
|
|
// let output_str = output_path.to_str().unwrap();
|
2018-12-15 06:46:11 +00:00
|
|
|
|
2018-12-11 01:06:55 +00:00
|
|
|
// Compile to .out
|
2018-12-27 07:43:38 +00:00
|
|
|
// Command::new("cc")
|
|
|
|
// .arg(file)
|
|
|
|
// .arg("-o")
|
|
|
|
// .arg(output_str)
|
|
|
|
// .output()
|
|
|
|
// .expect("failed to execute process");
|
2018-12-11 01:06:55 +00:00
|
|
|
|
|
|
|
// Get the result of .out
|
2018-12-27 07:43:38 +00:00
|
|
|
// let output = Command::new(output_str)
|
|
|
|
// .arg(output_str)
|
|
|
|
// .output()
|
|
|
|
// .expect("failed to execute process");
|
2018-12-11 01:06:55 +00:00
|
|
|
|
|
|
|
// Remove executable
|
2018-12-27 07:43:38 +00:00
|
|
|
// fs::remove_file(output_str).unwrap();
|
2018-12-11 01:06:55 +00:00
|
|
|
|
|
|
|
let mut output_path = PathBuf::from(file);
|
|
|
|
output_path.set_extension("js");
|
|
|
|
let output_str = output_path.to_str().unwrap();
|
|
|
|
|
2019-04-05 18:24:27 +00:00
|
|
|
let wasm_file_metadata = {
|
|
|
|
let mut wasm_file_path = PathBuf::from(file);
|
|
|
|
wasm_file_path.set_extension("wasm");
|
2019-05-17 19:09:31 +00:00
|
|
|
File::open(wasm_file_path).and_then(|wf| wf.metadata()).ok()
|
2019-04-05 18:24:27 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
let real_file = File::open(file).unwrap();
|
|
|
|
let file_metadata = real_file.metadata().unwrap();
|
|
|
|
if wasm_file_metadata.is_none()
|
|
|
|
|| file_metadata.modified().unwrap() >= wasm_file_metadata.unwrap().modified().unwrap()
|
|
|
|
{
|
|
|
|
// Compile to wasm
|
|
|
|
let _wasm_compilation = Command::new("emcc")
|
|
|
|
.arg(file)
|
|
|
|
.arg("-s")
|
|
|
|
.arg("WASM=1")
|
|
|
|
.arg("-o")
|
|
|
|
.arg(output_str)
|
|
|
|
.output()
|
|
|
|
.expect("failed to execute process");
|
|
|
|
|
|
|
|
// panic!("{:?}", wasm_compilation);
|
|
|
|
// if output.stderr {
|
|
|
|
// panic!("{}", output.stderr);
|
|
|
|
// }
|
|
|
|
// Remove js file
|
|
|
|
|
|
|
|
if Path::new(output_str).is_file() {
|
|
|
|
fs::remove_file(output_str).unwrap();
|
|
|
|
} else {
|
|
|
|
println!("Output JS not found: {}", output_str);
|
|
|
|
}
|
2018-12-27 07:43:38 +00:00
|
|
|
}
|
2018-12-11 01:06:55 +00:00
|
|
|
|
|
|
|
let mut output_path = PathBuf::from(file);
|
|
|
|
output_path.set_extension("output");
|
2018-12-15 06:46:11 +00:00
|
|
|
let module_name = output_path
|
|
|
|
.file_stem()
|
|
|
|
.unwrap()
|
|
|
|
.to_str()
|
|
|
|
.unwrap()
|
|
|
|
.to_owned();
|
|
|
|
|
2018-12-27 07:43:38 +00:00
|
|
|
//
|
|
|
|
// let output_str = output_path.to_str().unwrap();
|
2018-12-11 01:06:55 +00:00
|
|
|
|
|
|
|
// Write the output to file
|
2018-12-27 07:43:38 +00:00
|
|
|
// fs::write(output_str, output.stdout).expect("Unable to write file");
|
2018-12-11 01:06:55 +00:00
|
|
|
|
2018-12-27 07:43:38 +00:00
|
|
|
let rs_module_name = module_name.to_lowercase();
|
2018-12-11 02:42:23 +00:00
|
|
|
let rust_test_filepath = format!(
|
2019-01-11 05:37:59 +00:00
|
|
|
concat!(env!("CARGO_MANIFEST_DIR"), "/tests/emtests/{}.rs"),
|
2018-12-27 07:43:38 +00:00
|
|
|
rs_module_name.as_str()
|
2018-12-11 02:42:23 +00:00
|
|
|
);
|
|
|
|
|
2018-12-27 07:43:38 +00:00
|
|
|
let output_extension = if file.ends_with("c") || module_name.starts_with("test_") {
|
|
|
|
"out"
|
|
|
|
} else {
|
|
|
|
"txt"
|
|
|
|
};
|
|
|
|
|
2019-05-17 19:09:31 +00:00
|
|
|
let ignored = if ignores.contains(&module_name.to_lowercase()) {
|
2018-12-27 07:43:38 +00:00
|
|
|
"\n#[ignore]"
|
|
|
|
} else {
|
|
|
|
""
|
|
|
|
};
|
|
|
|
|
|
|
|
let module_path = format!("emtests/{}.wasm", module_name);
|
|
|
|
let test_output_path = format!("emtests/{}.{}", module_name, output_extension);
|
|
|
|
if !Path::new(&module_path).is_file() {
|
|
|
|
println!("Path not found to test module: {}", module_path);
|
|
|
|
None
|
|
|
|
} else if !Path::new(&test_output_path).is_file() {
|
|
|
|
println!("Path not found to test output: {}", module_path);
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
let contents = format!(
|
|
|
|
"#[test]{ignore}
|
|
|
|
fn test_{rs_module_name}() {{
|
2018-12-27 20:25:47 +00:00
|
|
|
assert_emscripten_output!(
|
|
|
|
\"../../{module_path}\",
|
|
|
|
\"{rs_module_name}\",
|
|
|
|
vec![],
|
|
|
|
\"../../{test_output_path}\"
|
|
|
|
);
|
2018-12-11 02:42:23 +00:00
|
|
|
}}
|
2018-12-27 07:43:38 +00:00
|
|
|
",
|
|
|
|
ignore = ignored,
|
|
|
|
module_path = module_path,
|
|
|
|
rs_module_name = rs_module_name,
|
|
|
|
test_output_path = test_output_path
|
|
|
|
);
|
2018-12-11 02:42:23 +00:00
|
|
|
|
2018-12-27 07:43:38 +00:00
|
|
|
fs::write(&rust_test_filepath, contents.as_bytes()).unwrap();
|
2018-12-15 06:46:11 +00:00
|
|
|
|
2018-12-27 07:43:38 +00:00
|
|
|
Some(rs_module_name)
|
|
|
|
}
|
2018-12-11 01:06:55 +00:00
|
|
|
// panic!("OUTPUT: {:?}", output);
|
|
|
|
}
|
2018-12-10 03:21:28 +00:00
|
|
|
|
|
|
|
pub fn build() {
|
2019-01-11 05:46:02 +00:00
|
|
|
let rust_test_modpath = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/emtests/mod.rs");
|
2018-12-10 03:21:28 +00:00
|
|
|
|
|
|
|
let mut modules: Vec<String> = Vec::new();
|
|
|
|
// modules.reserve_exact(TESTS.len());
|
2018-12-27 07:43:38 +00:00
|
|
|
|
|
|
|
let ignores = read_ignore_list();
|
|
|
|
|
|
|
|
for ext in EXTENSIONS.iter() {
|
|
|
|
for entry in glob(&format!("emtests/*.{}", ext)).unwrap() {
|
|
|
|
match entry {
|
|
|
|
Ok(path) => {
|
|
|
|
let test = path.to_str().unwrap();
|
|
|
|
if !EXCLUDES.iter().any(|e| test.ends_with(e)) {
|
|
|
|
if let Some(module_name) = compile(test, &ignores) {
|
2018-12-27 20:25:47 +00:00
|
|
|
modules.push(module_name);
|
2018-12-27 07:43:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Err(e) => println!("{:?}", e),
|
|
|
|
}
|
|
|
|
}
|
2018-12-11 01:06:55 +00:00
|
|
|
}
|
2018-12-27 20:25:47 +00:00
|
|
|
modules.sort();
|
|
|
|
let mut modules: Vec<String> = modules.iter().map(|m| format!("mod {};", m)).collect();
|
2018-12-27 07:43:38 +00:00
|
|
|
assert!(modules.len() > 0, "Expected > 0 modules found");
|
|
|
|
|
2018-12-10 03:21:28 +00:00
|
|
|
modules.insert(0, BANNER.to_string());
|
2018-12-11 02:42:23 +00:00
|
|
|
modules.insert(1, "// The _common module is not autogenerated, as it provides common macros for the emtests\n#[macro_use]\nmod _common;".to_string());
|
2018-12-10 03:21:28 +00:00
|
|
|
// We add an empty line
|
|
|
|
modules.push("".to_string());
|
|
|
|
|
|
|
|
let modfile: String = modules.join("\n");
|
|
|
|
let source = fs::read(&rust_test_modpath).unwrap();
|
|
|
|
// We only modify the mod file if has changed
|
|
|
|
if source != modfile.as_bytes() {
|
|
|
|
fs::write(&rust_test_modpath, modfile.as_bytes()).unwrap();
|
|
|
|
}
|
|
|
|
}
|
2018-12-27 07:43:38 +00:00
|
|
|
|
2019-05-17 19:09:31 +00:00
|
|
|
fn read_ignore_list() -> HashSet<String> {
|
2018-12-27 07:43:38 +00:00
|
|
|
let f = File::open("emtests/ignores.txt").unwrap();
|
|
|
|
let f = BufReader::new(f);
|
2019-05-17 19:09:31 +00:00
|
|
|
f.lines()
|
|
|
|
.filter_map(Result::ok)
|
|
|
|
.map(|v| v.to_lowercase())
|
|
|
|
.collect()
|
2018-12-27 07:43:38 +00:00
|
|
|
}
|