Skip to content

Commit dfaed38

Browse files
committed
Start implementing a test suite for the CLI
We have very few tests today so this starts to add the basics of a test suite which compiles Cargo projects on-the-fly which will hopefully help us bolster the amount of assertions we can make about the output.
1 parent f3b190a commit dfaed38

File tree

4 files changed

+298
-1
lines changed

4 files changed

+298
-1
lines changed

crates/cli/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,9 @@ walrus = "0.5"
2828
wasm-bindgen-cli-support = { path = "../cli-support", version = "=0.2.40" }
2929
wasm-bindgen-shared = { path = "../shared", version = "=0.2.40" }
3030

31+
[dev-dependencies]
32+
assert_cmd = "0.11"
33+
predicates = "1.0.0"
34+
3135
[features]
3236
vendored-openssl = ['openssl/vendored']

crates/cli/src/bin/wasm-bindgen.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ fn main() {
7979
};
8080
eprintln!("error: {}", err);
8181
for cause in err.iter_causes() {
82-
eprintln!("\tcaused by: {}", cause);
82+
eprintln!(" caused by: {}", cause);
8383
}
8484
process::exit(1);
8585
}

crates/cli/tests/wasm-bindgen/main.rs

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
//! A small test suite for the `wasm-bindgen` CLI command itself
2+
//!
3+
//! This test suite is intended to exercise functionality of the CLI in terms of
4+
//! errors and such. It is not intended for comprehensive behavior testing, as
5+
//! that should all be placed in the top-level `tests` directory for the
6+
//! `wasm-bindgen` crate itself.
7+
//!
8+
//! Assertions about errors in `wasm-bindgen` or assertions about the output of
9+
//! `wasm-bindgen` should all be placed in this test suite, however. Currently
10+
//! it is largely based off actually running `cargo build` at test time which is
11+
//! quite expensive, so it's recommended that this test suite doesn't become too
12+
//! large!
13+
14+
use assert_cmd::prelude::*;
15+
use predicates::str;
16+
use std::env;
17+
use std::fs;
18+
use std::path::PathBuf;
19+
use std::process::Command;
20+
21+
fn target_dir() -> PathBuf {
22+
let mut dir = PathBuf::from(env::current_exe().unwrap());
23+
dir.pop(); // current exe
24+
if dir.ends_with("deps") {
25+
dir.pop();
26+
}
27+
dir.pop(); // debug and/or release
28+
return dir;
29+
}
30+
31+
fn repo_root() -> PathBuf {
32+
let mut repo_root = env::current_dir().unwrap();
33+
repo_root.pop(); // remove 'cli'
34+
repo_root.pop(); // remove 'crates'
35+
repo_root
36+
}
37+
38+
struct Project {
39+
root: PathBuf,
40+
name: &'static str,
41+
}
42+
43+
impl Project {
44+
fn new(name: &'static str) -> Project {
45+
let root = target_dir().join("cli-tests").join(name);
46+
drop(fs::remove_dir_all(&root));
47+
fs::create_dir_all(&root).unwrap();
48+
Project { root, name }
49+
}
50+
51+
fn file(&mut self, name: &str, contents: &str) -> &mut Project {
52+
let dst = self.root.join(name);
53+
fs::create_dir_all(dst.parent().unwrap()).unwrap();
54+
fs::write(&dst, contents).unwrap();
55+
self
56+
}
57+
58+
fn wasm_bindgen(&mut self, args: &str) -> (Command, PathBuf) {
59+
let wasm = self.build();
60+
let output = self.root.join("pkg");
61+
fs::create_dir_all(&output).unwrap();
62+
let mut cmd = Command::cargo_bin("wasm-bindgen").unwrap();
63+
cmd.arg("--out-dir").arg(&output);
64+
cmd.arg(&wasm);
65+
for arg in args.split_whitespace() {
66+
cmd.arg(arg);
67+
}
68+
(cmd, output)
69+
}
70+
71+
fn build(&mut self) -> PathBuf {
72+
if !self.root.join("Cargo.toml").is_file() {
73+
self.file(
74+
"Cargo.toml",
75+
&format!(
76+
"
77+
[package]
78+
name = \"{}\"
79+
authors = []
80+
version = \"1.0.0\"
81+
edition = '2018'
82+
83+
[dependencies]
84+
wasm-bindgen = {{ path = '{}' }}
85+
86+
[lib]
87+
crate-type = ['cdylib']
88+
89+
[workspace]
90+
",
91+
self.name,
92+
repo_root().display(),
93+
),
94+
);
95+
}
96+
97+
let target_dir = target_dir();
98+
Command::new("cargo")
99+
.current_dir(&self.root)
100+
.arg("build")
101+
.arg("--target")
102+
.arg("wasm32-unknown-unknown")
103+
.env("CARGO_TARGET_DIR", &target_dir)
104+
.assert()
105+
.success();
106+
107+
target_dir
108+
.join("wasm32-unknown-unknown")
109+
.join("debug")
110+
.join(self.name)
111+
.with_extension("wasm")
112+
}
113+
}
114+
115+
#[test]
116+
fn version_useful() {
117+
Command::cargo_bin("wasm-bindgen")
118+
.unwrap()
119+
.arg("-V")
120+
.assert()
121+
.stdout(str::ends_with("\n"))
122+
.stdout(str::starts_with("wasm-bindgen "))
123+
.success();
124+
}
125+
126+
#[test]
127+
fn works_on_empty_project() {
128+
let (mut cmd, _out_dir) = Project::new("works_on_empty_project")
129+
.file(
130+
"src/lib.rs",
131+
r#"
132+
"#,
133+
)
134+
.wasm_bindgen("");
135+
cmd.assert().success();
136+
}
137+
138+
mod npm;

crates/cli/tests/wasm-bindgen/npm.rs

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
use crate::*;
2+
3+
#[test]
4+
fn no_modules_rejects_npm() {
5+
let (mut cmd, _out_dir) = Project::new("no_modules_rejects_npm")
6+
.file(
7+
"src/lib.rs",
8+
r#"
9+
use wasm_bindgen::prelude::*;
10+
11+
#[wasm_bindgen(module = "foo")]
12+
extern {
13+
fn foo();
14+
}
15+
16+
#[wasm_bindgen(start)]
17+
pub fn main() {
18+
foo();
19+
}
20+
"#,
21+
)
22+
.file("package.json", "")
23+
.wasm_bindgen("--no-modules");
24+
cmd.assert()
25+
.stderr("\
26+
error: failed to generate bindings for JS import `foo`
27+
caused by: import from `foo` module not allowed with `--no-modules`; use `--nodejs`, `--browser`, or no flag instead
28+
")
29+
.failure();
30+
}
31+
32+
#[test]
33+
fn more_package_json_fields_rejected() {
34+
let (mut cmd, _out_dir) = Project::new("more_package_json_fields_rejected")
35+
.file(
36+
"src/lib.rs",
37+
r#"
38+
use wasm_bindgen::prelude::*;
39+
40+
#[wasm_bindgen(module = "foo")]
41+
extern {
42+
fn foo();
43+
}
44+
45+
#[wasm_bindgen(start)]
46+
pub fn main() {
47+
foo();
48+
}
49+
"#,
50+
)
51+
.file(
52+
"package.json",
53+
r#"
54+
{
55+
"name": "foo",
56+
"dependencies": {}
57+
}
58+
"#,
59+
)
60+
.wasm_bindgen("");
61+
cmd.assert()
62+
.stderr(str::is_match("\
63+
error: NPM manifest found at `.*` can currently only have one key, .*
64+
").unwrap())
65+
.failure();
66+
}
67+
68+
#[test]
69+
fn npm_conflict_rejected() {
70+
let (mut cmd, _out_dir) = Project::new("npm_conflict_rejected")
71+
.file(
72+
"Cargo.toml",
73+
&format!(r#"
74+
[package]
75+
name = "npm_conflict_rejected"
76+
authors = []
77+
version = "1.0.0"
78+
edition = '2018'
79+
80+
[dependencies]
81+
wasm-bindgen = {{ path = '{}' }}
82+
bar = {{ path = 'bar' }}
83+
84+
[lib]
85+
crate-type = ['cdylib']
86+
87+
[workspace]
88+
"#,
89+
repo_root().display()
90+
)
91+
)
92+
.file(
93+
"src/lib.rs",
94+
r#"
95+
use wasm_bindgen::prelude::*;
96+
97+
#[wasm_bindgen(module = "bar")]
98+
extern {
99+
fn foo();
100+
}
101+
102+
#[wasm_bindgen(start)]
103+
pub fn main() {
104+
foo();
105+
bar::foo();
106+
}
107+
"#,
108+
)
109+
.file(
110+
"package.json",
111+
r#"
112+
{
113+
"dependencies": {"bar": "0.0.0"}
114+
}
115+
"#,
116+
)
117+
.file(
118+
"bar/Cargo.toml",
119+
&format!(r#"
120+
[package]
121+
name = "bar"
122+
authors = []
123+
version = "1.0.0"
124+
edition = '2018'
125+
126+
[dependencies]
127+
wasm-bindgen = {{ path = '{}' }}
128+
"#,
129+
repo_root().display()
130+
)
131+
)
132+
.file(
133+
"bar/src/lib.rs",
134+
r#"
135+
use wasm_bindgen::prelude::*;
136+
137+
#[wasm_bindgen(module = "bar")]
138+
extern {
139+
pub fn foo();
140+
}
141+
"#,
142+
)
143+
.file(
144+
"bar/package.json",
145+
r#"
146+
{
147+
"dependencies": {"bar": "1.0.0"}
148+
}
149+
"#,
150+
)
151+
.wasm_bindgen("");
152+
cmd.assert()
153+
.stderr(str::is_match("dependency on NPM package `bar` specified in two").unwrap())
154+
.failure();
155+
}

0 commit comments

Comments
 (0)