Skip to content

Commit

Permalink
Add --list, --ignored and --exact to wasm-bindgen-test-runner (
Browse files Browse the repository at this point in the history
  • Loading branch information
daxpedda authored Dec 17, 2024
1 parent dfb9d92 commit 54034a5
Show file tree
Hide file tree
Showing 10 changed files with 158 additions and 46 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
* Support importing memory and using `wasm_bindgen::module()` in Node.js.
[#4349](https://github.com/rustwasm/wasm-bindgen/pull/4349)

* Add `--list`, `--ignored`, `--exact` and `--nocapture` to `wasm-bindgen-test-runner`, analogous to `cargo test`.
[#4356](https://github.com/rustwasm/wasm-bindgen/pull/4356)

### Changed

* Optional parameters are now typed as `T | undefined | null` to reflect the actual JS behavior.
Expand All @@ -34,6 +37,9 @@
* Remove `WASM_BINDGEN_THREADS_MAX_MEMORY` and `WASM_BINDGEN_THREADS_STACK_SIZE`. The maximum memory size can be set via `-Clink-arg=--max-memory=<size>`. The stack size of a thread can be set when initializing the thread via the `default` function.
[#4363](https://github.com/rustwasm/wasm-bindgen/pull/4363)

* `console.*()` calls in tests are now always intercepted by default. To show them use `--nocapture`. When shown they are always printed in-place instead of after test results, analogous to `cargo test`.
[#4356](https://github.com/rustwasm/wasm-bindgen/pull/4356)

### Fixed

- Fixed using [JavaScript keyword](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#keywords) as identifiers not being handled correctly.
Expand Down
2 changes: 2 additions & 0 deletions crates/cli/src/bin/wasm-bindgen-test-runner/deno.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub fn execute(module: &str, tmpdir: &Path, cli: Cli, tests: &[String]) -> Resul
let mut js_to_execute = format!(
r#"import * as wasm from "./{module}.js";
const nocapture = {nocapture};
{console_override}
window.__wbg_test_invoke = f => f();
Expand All @@ -21,6 +22,7 @@ pub fn execute(module: &str, tmpdir: &Path, cli: Cli, tests: &[String]) -> Resul
const tests = [];
"#,
nocapture = cli.nocapture.clone(),
console_override = SHARED_SETUP,
args = cli.into_args(),
);
Expand Down
13 changes: 7 additions & 6 deletions crates/cli/src/bin/wasm-bindgen-test-runner/headless.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,14 +210,15 @@ pub fn run(
println!("output div contained:\n{}", tab(&output));
}
}
if !logs.is_empty() {
println!("console.log div contained:\n{}", tab(&logs));
}
if !errors.is_empty() {
println!("console.log div contained:\n{}", tab(&errors));
}

if !output.contains("test result: ok") {
if !logs.is_empty() {
println!("console.log div contained:\n{}", tab(&logs));
}
if !errors.is_empty() {
println!("console.log div contained:\n{}", tab(&errors));
}

bail!("some tests failed")
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,14 @@
}
};

// {NOCAPTURE}
const wrap = method => {
const og = orig(`console_${method}`);
const on_method = `on_console_${method}`;
console[method] = function (...args) {
if (nocapture) {
orig("output").apply(this, args);
}
if (window[on_method]) {
window[on_method](args);
}
Expand Down
77 changes: 68 additions & 9 deletions crates/cli/src/bin/wasm-bindgen-test-runner/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use anyhow::{bail, Context};
use clap::Parser;
use clap::ValueEnum;
use std::env;
use std::fs;
use std::path::Path;
Expand All @@ -34,14 +35,32 @@ struct Cli {
help = "The file to test. `cargo test` passes this argument for you."
)]
file: PathBuf,
#[arg(long = "include-ignored", help = "Run ignored tests")]
#[arg(long, conflicts_with = "ignored", help = "Run ignored tests")]
include_ignored: bool,
#[arg(long, conflicts_with = "include_ignored", help = "Run ignored tests")]
ignored: bool,
#[arg(long, help = "Exactly match filters rather than by substring")]
exact: bool,
#[arg(
long = "skip",
long,
value_name = "FILTER",
help = "Skip tests whose names contain FILTER (this flag can be used multiple times)"
)]
skip: Vec<String>,
#[arg(long, help = "List all tests and benchmarks")]
list: bool,
#[arg(
long,
help = "don't capture `console.*()` of each task, allow printing directly"
)]
nocapture: bool,
#[arg(
long,
value_enum,
value_name = "terse",
help = "Configure formatting of output"
)]
format: Option<FormatSetting>,
#[arg(
index = 2,
value_name = "FILTER",
Expand All @@ -54,6 +73,8 @@ struct Cli {
impl Cli {
fn into_args(self) -> String {
let include_ignored = self.include_ignored;
let ignored = self.ignored;
let exact = self.exact;
let skip = self.skip;
let filter = if let Some(filter) = self.filter {
&format!("\"{filter}\"")
Expand All @@ -65,6 +86,8 @@ impl Cli {
r#"
// Forward runtime arguments.
cx.include_ignored({include_ignored:?});
cx.ignored({ignored:?});
cx.exact({exact:?});
cx.skip({skip:?});
cx.filter({filter});
"#
Expand All @@ -85,10 +108,6 @@ fn main() -> anyhow::Result<()> {
.map(Path::new)
.context("file to test is not a valid file, can't extract file name")?;

let tmpdir = tempfile::tempdir()?;

let module = "wasm-bindgen-test";

// Collect all tests that the test harness is supposed to run. We assume
// that any exported function with the prefix `__wbg_test` is a test we need
// to execute.
Expand All @@ -98,12 +117,45 @@ fn main() -> anyhow::Result<()> {
let mut tests = Vec::new();

for export in wasm.exports.iter() {
if !export.name.starts_with("__wbgt_") {
continue;
if export.name.starts_with("__wbgt_") {
tests.push(export.name.to_string());
}
tests.push(export.name.to_string());
}

if cli.list {
'outer: for test in tests {
if !cli.ignored || test.starts_with("__wbgt_$") {
if let Some(filter) = &cli.filter {
let matches = if cli.exact {
test == *filter
} else {
test.contains(filter)
};

if !matches {
continue;
}
}

for skip in &cli.skip {
if test.contains(skip) {
continue 'outer;
}
}

println!("{}: test", test.split_once("::").unwrap().1);
}
}

// Returning cleanly has the strange effect of outputting
// an additional empty line with spaces in it.
std::process::exit(0);
}

let tmpdir = tempfile::tempdir()?;

let module = "wasm-bindgen-test";

// Right now there's a bug where if no tests are present then the
// `wasm-bindgen-test` runtime support isn't linked in, so just bail out
// early saying everything is ok.
Expand Down Expand Up @@ -348,3 +400,10 @@ fn coverage_args(file_name: &Path) -> PathBuf {
None => PathBuf::from(generated(file_name, &prefix)),
}
}

/// Possible values for the `--format` option.
#[derive(Debug, Clone, Copy, ValueEnum)]
enum FormatSetting {
/// Display one character per test
Terse,
}
8 changes: 7 additions & 1 deletion crates/cli/src/bin/wasm-bindgen-test-runner/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,17 @@ const wrap = method => {
const og = console[method];
const on_method = `on_console_${method}`;
console[method] = function (...args) {
og.apply(this, args);
if (nocapture) {
og.apply(this, args);
}
if (handlers[on_method]) {
handlers[on_method](args);
}
};
};
// save original `console.log`
global.__wbgtest_og_console_log = console.log;
// override `console.log` and `console.error` etc... 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
Expand Down Expand Up @@ -53,6 +57,7 @@ pub fn execute(
{fs};
{wasm};
const nocapture = {nocapture};
{console_override}
global.__wbg_test_invoke = f => f();
Expand Down Expand Up @@ -88,6 +93,7 @@ pub fn execute(
r"import fs from 'node:fs/promises'".to_string()
},
coverage = coverage.display(),
nocapture = cli.nocapture.clone(),
console_override = SHARED_SETUP,
args = cli.into_args(),
);
Expand Down
6 changes: 6 additions & 0 deletions crates/cli/src/bin/wasm-bindgen-test-runner/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ pub(crate) fn spawn(
)
};

let nocapture = cli.nocapture;
let args = cli.into_args();

if test_mode.is_worker() {
Expand Down Expand Up @@ -102,9 +103,13 @@ pub(crate) fn spawn(

worker_script.push_str(&format!(
r#"
const nocapture = {nocapture};
const wrap = method => {{
const on_method = `on_console_${{method}}`;
self.console[method] = function (...args) {{
if (nocapture) {{
self.__wbg_test_output_writeln(args);
}}
if (self[on_method]) {{
self[on_method](args);
}}
Expand Down Expand Up @@ -297,6 +302,7 @@ pub(crate) fn spawn(
} else {
include_str!("index.html")
};
let s = s.replace("// {NOCAPTURE}", &format!("const nocapture = {nocapture};"));
let s = if !test_mode.is_worker() && test_mode.no_modules() {
s.replace(
"<!-- {IMPORT_SCRIPTS} -->",
Expand Down
14 changes: 4 additions & 10 deletions crates/test-macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,8 @@
extern crate proc_macro;

use proc_macro2::*;
use quote::format_ident;
use quote::quote;
use quote::quote_spanned;
use std::sync::atomic::*;

static CNT: AtomicUsize = AtomicUsize::new(0);

#[proc_macro_attribute]
pub fn wasm_bindgen_test(
Expand Down Expand Up @@ -94,18 +90,16 @@ pub fn wasm_bindgen_test(
quote! { cx.execute_sync(test_name, #ident, #should_panic_par, #ignore_par); }
};

// We generate a `#[no_mangle]` with a known prefix so the test harness can
// later slurp up all of these functions and pass them as arguments to the
// main test harness. This is the entry point for all tests.
let name = format_ident!("__wbgt_{}_{}", ident, CNT.fetch_add(1, Ordering::SeqCst));
let ignore_name = if ignore.is_some() { "$" } else { "" };

let wasm_bindgen_path = attributes.wasm_bindgen_path;
tokens.extend(
quote! {
const _: () = {
#wasm_bindgen_path::__rt::wasm_bindgen::__wbindgen_coverage! {
#[no_mangle]
#[export_name = ::core::concat!("__wbgt_", #ignore_name, ::core::module_path!(), "::", ::core::stringify!(#ident))]
#[cfg(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))]
pub extern "C" fn #name(cx: &#wasm_bindgen_path::__rt::Context) {
extern "C" fn __wbgt_test(cx: &#wasm_bindgen_path::__rt::Context) {
let test_name = ::core::concat!(::core::module_path!(), "::", ::core::stringify!(#ident));
#test_body
}
Expand Down
Loading

0 comments on commit 54034a5

Please sign in to comment.