2018-07-24 11:27:06 -07:00
|
|
|
use std::env;
|
|
|
|
use std::ffi::OsString;
|
|
|
|
use std::fs;
|
|
|
|
use std::path::Path;
|
|
|
|
use std::process::Command;
|
|
|
|
|
|
|
|
use failure::{ResultExt, Error};
|
|
|
|
|
|
|
|
pub fn execute(module: &str, tmpdir: &Path, args: &[OsString], tests: &[String])
|
|
|
|
-> Result<(), Error>
|
|
|
|
{
|
|
|
|
let mut js_to_execute = format!(r#"
|
|
|
|
const {{ exit }} = require('process');
|
|
|
|
|
|
|
|
let cx = null;
|
|
|
|
|
|
|
|
// override `console.log` and `console.error` before we import tests to
|
|
|
|
// ensure they're bound correctly in wasm. This'll allow us to intercept
|
|
|
|
// all these calls and capture the output of tests
|
|
|
|
const prev_log = console.log;
|
|
|
|
console.log = function() {{
|
|
|
|
if (cx === null) {{
|
|
|
|
prev_log.apply(null, arguments);
|
|
|
|
}} else {{
|
|
|
|
cx.console_log(prev_log, arguments);
|
|
|
|
}}
|
|
|
|
}};
|
|
|
|
const prev_error = console.error;
|
|
|
|
console.error = function() {{
|
|
|
|
if (cx === null) {{
|
|
|
|
prev_error.apply(null, arguments);
|
|
|
|
}} else {{
|
|
|
|
cx.console_error(prev_error, arguments);
|
|
|
|
}}
|
|
|
|
}};
|
|
|
|
|
|
|
|
function main(tests) {{
|
|
|
|
const support = require("./{0}");
|
|
|
|
const wasm = require("./{0}_bg");
|
|
|
|
|
|
|
|
cx = new support.Context();
|
|
|
|
|
|
|
|
// Forward runtime arguments. These arguments are also arguments to the
|
|
|
|
// `wasm-bindgen-test-runner` which forwards them to node which we
|
|
|
|
// forward to the test harness. this is basically only used for test
|
|
|
|
// filters for now.
|
|
|
|
cx.args(process.argv.slice(2));
|
|
|
|
|
|
|
|
if (!cx.run(tests.map(n => wasm[n])))
|
|
|
|
exit(1);
|
|
|
|
}}
|
|
|
|
|
|
|
|
const tests = [];
|
|
|
|
"#,
|
|
|
|
module
|
|
|
|
);
|
|
|
|
|
|
|
|
// Note that we're collecting *JS objects* that represent the functions to
|
|
|
|
// execute, and then those objects are passed into wasm for it to execute
|
|
|
|
// when it sees fit.
|
|
|
|
for test in tests {
|
|
|
|
js_to_execute.push_str(&format!("tests.push('{}')\n", test));
|
|
|
|
}
|
|
|
|
// And as a final addendum, exit with a nonzero code if any tests fail.
|
|
|
|
js_to_execute.push_str("
|
|
|
|
main(tests)
|
|
|
|
");
|
|
|
|
|
|
|
|
let js_path = tmpdir.join("run.js");
|
|
|
|
fs::write(&js_path, js_to_execute)
|
|
|
|
.context("failed to write JS file")?;
|
|
|
|
|
2018-07-26 18:49:20 -07:00
|
|
|
// Augment `NODE_PATH` so things like `require("tests/my-custom.js")` work
|
|
|
|
// and Rust code can import from custom JS shims. This is a bit of a hack
|
|
|
|
// and should probably be removed at some point.
|
2018-07-24 11:27:06 -07:00
|
|
|
let path = env::var("NODE_PATH").unwrap_or_default();
|
|
|
|
let mut path = env::split_paths(&path).collect::<Vec<_>>();
|
|
|
|
path.push(env::current_dir().unwrap());
|
2018-08-01 14:19:19 -05:00
|
|
|
path.push(tmpdir.to_path_buf());
|
2018-07-24 11:27:06 -07:00
|
|
|
exec(
|
|
|
|
Command::new("node")
|
|
|
|
.env("NODE_PATH", env::join_paths(&path).unwrap())
|
|
|
|
.arg(&js_path)
|
|
|
|
.args(args)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(unix)]
|
|
|
|
fn exec(cmd: &mut Command) -> Result<(), Error> {
|
|
|
|
use std::os::unix::prelude::*;
|
|
|
|
Err(Error::from(cmd.exec()).context("failed to execute `node`").into())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(windows)]
|
|
|
|
fn exec(cmd: &mut Command) -> Result<(), Error> {
|
2018-07-27 09:01:13 -07:00
|
|
|
use std::process;
|
2018-07-24 11:27:06 -07:00
|
|
|
let status = cmd.status()?;
|
|
|
|
process::exit(status.code().unwrap_or(3));
|
|
|
|
}
|