fork of https://github.com/rustwasm/wasm-pack for the needs of NextGraph.org
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
648 lines
20 KiB
648 lines
20 KiB
use binary_install::Cache;
|
|
use std::env;
|
|
use std::fs;
|
|
use std::mem::ManuallyDrop;
|
|
use std::path::{Path, PathBuf};
|
|
use std::process::{Command, Stdio};
|
|
use std::sync::{MutexGuard, Once, ONCE_INIT};
|
|
use std::thread;
|
|
use tempfile::TempDir;
|
|
use wasm_pack;
|
|
|
|
/// A test fixture in a temporary directory.
|
|
pub struct Fixture {
|
|
// NB: we wrap the fixture's tempdir in a `ManuallyDrop` so that if a test
|
|
// fails, its directory isn't deleted, and we have a chance to manually
|
|
// inspect its state and figure out what is going on.
|
|
pub dir: ManuallyDrop<TempDir>,
|
|
pub path: PathBuf,
|
|
}
|
|
|
|
impl Fixture {
|
|
/// Create a new test fixture in a temporary directory.
|
|
pub fn new() -> Fixture {
|
|
// Make sure that all fixtures end up sharing a target dir, and we don't
|
|
// recompile wasm-bindgen and friends many times over.
|
|
static SET_TARGET_DIR: Once = ONCE_INIT;
|
|
let target_dir = Path::new(env!("CARGO_MANIFEST_DIR")).join("target");
|
|
SET_TARGET_DIR.call_once(|| {
|
|
env::set_var("CARGO_TARGET_DIR", &target_dir);
|
|
});
|
|
|
|
let root = target_dir.join("t");
|
|
fs::create_dir_all(&root).unwrap();
|
|
let dir = TempDir::new_in(&root).unwrap();
|
|
let path = dir.path().join("wasm-pack");
|
|
eprintln!("Created fixture at {}", path.display());
|
|
Fixture {
|
|
dir: ManuallyDrop::new(dir),
|
|
path,
|
|
}
|
|
}
|
|
|
|
/// Create a file within this fixture.
|
|
///
|
|
/// `path` should be a relative path to the file (relative within this
|
|
/// fixture's path).
|
|
///
|
|
/// The `contents` are written to the file.
|
|
pub fn file<P: AsRef<Path>, C: AsRef<[u8]>>(&self, path: P, contents: C) -> &Self {
|
|
assert!(path.as_ref().is_relative());
|
|
let path = self.path.join(path);
|
|
if let Some(parent) = path.parent() {
|
|
fs::create_dir_all(parent).unwrap();
|
|
}
|
|
fs::write(path, contents).unwrap();
|
|
self
|
|
}
|
|
|
|
/// Add a generic `README.md` file to the fixture.
|
|
pub fn readme(&self) -> &Self {
|
|
self.file(
|
|
"README.md",
|
|
r#"
|
|
# Fixture!
|
|
> an example rust -> wasm project
|
|
"#,
|
|
)
|
|
}
|
|
|
|
/// Add `WTFPL LICENSE` file to the fixture.
|
|
pub fn wtfpl_license(&self) -> &Self {
|
|
self.file(
|
|
"LICENSE-WTFPL",
|
|
r#"
|
|
DO WHATEVER YOU WANT TO PUBLIC LICENSE
|
|
Version 2, December 2004
|
|
|
|
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
|
|
|
Everyone is permitted to copy and distribute verbatim or modified
|
|
copies of this license document, and changing it is allowed as long
|
|
as the name is changed.
|
|
|
|
DO WHATEVER YOU WANT TO PUBLIC LICENSE
|
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
|
|
|
0. You just DO WHATEVER YOU WANT TO.
|
|
"#,
|
|
)
|
|
}
|
|
|
|
/// Add `MIT LICENSE` file to the fixture.
|
|
pub fn mit_license(&self) -> &Self {
|
|
self.file(
|
|
"LICENSE-MIT",
|
|
r#"
|
|
Copyright <YEAR> <COPYRIGHT HOLDER>
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
"#,
|
|
)
|
|
}
|
|
|
|
/// Add a `Cargo.toml` with a correctly configured `wasm-bindgen`
|
|
/// dependency, `wasm-bindgen-test` dev-dependency, and `crate-type =
|
|
/// ["cdylib"]`.
|
|
///
|
|
/// `name` is the crate's name.
|
|
pub fn cargo_toml(&self, name: &str) -> &Self {
|
|
self.file(
|
|
"Cargo.toml",
|
|
&format!(
|
|
r#"
|
|
[package]
|
|
authors = ["The wasm-pack developers"]
|
|
description = "so awesome rust+wasm package"
|
|
license = "WTFPL"
|
|
name = "{}"
|
|
repository = "https://github.com/rustwasm/wasm-pack.git"
|
|
version = "0.1.0"
|
|
|
|
[lib]
|
|
crate-type = ["cdylib"]
|
|
|
|
[dependencies]
|
|
wasm-bindgen = "=0.2.21"
|
|
|
|
[dev-dependencies]
|
|
wasm-bindgen-test = "=0.2.21"
|
|
"#,
|
|
name
|
|
),
|
|
)
|
|
}
|
|
|
|
/// Add a `src/lib.rs` file that contains a "hello world" program.
|
|
pub fn hello_world_src_lib(&self) -> &Self {
|
|
self.file(
|
|
"src/lib.rs",
|
|
r#"
|
|
extern crate wasm_bindgen;
|
|
use wasm_bindgen::prelude::*;
|
|
|
|
// Import the `window.alert` function from the Web.
|
|
#[wasm_bindgen]
|
|
extern {
|
|
fn alert(s: &str);
|
|
}
|
|
|
|
// Export a `greet` function from Rust to JavaScript, that alerts a
|
|
// hello message.
|
|
#[wasm_bindgen]
|
|
pub fn greet(name: &str) {
|
|
alert(&format!("Hello, {}!", name));
|
|
}
|
|
"#,
|
|
)
|
|
}
|
|
|
|
/// Install a local wasm-bindgen for this fixture.
|
|
///
|
|
/// Takes care not to re-install for every fixture, but only the one time
|
|
/// for the whole test suite.
|
|
pub fn install_local_wasm_bindgen(&self) -> PathBuf {
|
|
static INSTALL_WASM_BINDGEN: Once = ONCE_INIT;
|
|
let cache = self.cache();
|
|
let version = "0.2.21";
|
|
|
|
let download = || {
|
|
if let Ok(download) =
|
|
wasm_pack::bindgen::download_prebuilt_wasm_bindgen(&cache, version, true)
|
|
{
|
|
return Ok(download);
|
|
}
|
|
|
|
wasm_pack::bindgen::cargo_install_wasm_bindgen(&cache, version, true)
|
|
};
|
|
|
|
// Only one thread can perform the actual download, and then afterwards
|
|
// everything will hit the cache so we can run the same path.
|
|
INSTALL_WASM_BINDGEN.call_once(|| {
|
|
download().unwrap();
|
|
});
|
|
download().unwrap().binary("wasm-bindgen").unwrap()
|
|
}
|
|
|
|
/// Download `geckodriver` and return its path.
|
|
///
|
|
/// Takes care to ensure that only one `geckodriver` is downloaded for the whole
|
|
/// test suite.
|
|
pub fn install_local_geckodriver(&self) -> PathBuf {
|
|
static FETCH_GECKODRIVER: Once = ONCE_INIT;
|
|
let cache = self.cache();
|
|
|
|
// like above for synchronization
|
|
FETCH_GECKODRIVER.call_once(|| {
|
|
wasm_pack::test::webdriver::install_geckodriver(&cache, true).unwrap();
|
|
});
|
|
wasm_pack::test::webdriver::install_geckodriver(&cache, true).unwrap()
|
|
}
|
|
|
|
/// Download `chromedriver` and return its path.
|
|
///
|
|
/// Takes care to ensure that only one `chromedriver` is downloaded for the whole
|
|
/// test suite.
|
|
pub fn install_local_chromedriver(&self) -> PathBuf {
|
|
static FETCH_CHROMEDRIVER: Once = ONCE_INIT;
|
|
let cache = self.cache();
|
|
|
|
// like above for synchronization
|
|
FETCH_CHROMEDRIVER.call_once(|| {
|
|
wasm_pack::test::webdriver::install_chromedriver(&cache, true).unwrap();
|
|
});
|
|
wasm_pack::test::webdriver::install_chromedriver(&cache, true).unwrap()
|
|
}
|
|
|
|
pub fn cache(&self) -> Cache {
|
|
let target_dir = Path::new(env!("CARGO_MANIFEST_DIR")).join("target");
|
|
Cache::at(&target_dir.join("test_cache"))
|
|
}
|
|
|
|
/// The `step_install_wasm_bindgen` and `step_run_wasm_bindgen` steps only
|
|
/// occur after the `step_build_wasm` step. In order to read the lockfile
|
|
/// in the test fixture's temporary directory, we should first build the
|
|
/// crate, targeting `wasm32-unknown-unknown`.
|
|
pub fn cargo_check(&self) -> &Self {
|
|
Command::new("cargo")
|
|
.current_dir(&self.path)
|
|
.arg("check")
|
|
.arg("--target")
|
|
.arg("wasm32-unknown-unknown")
|
|
.stdout(Stdio::null())
|
|
.stderr(Stdio::null())
|
|
.status()
|
|
.unwrap();
|
|
self
|
|
}
|
|
|
|
pub fn run(&self, cmd: wasm_pack::command::Command) -> Result<(), failure::Error> {
|
|
match cmd {
|
|
wasm_pack::command::Command::Test(cmd) => {
|
|
let _lock = self.lock();
|
|
let mut test = wasm_pack::command::test::Test::try_from_opts(cmd)?;
|
|
test.set_cache(self.cache());
|
|
test.run()
|
|
}
|
|
wasm_pack::command::Command::Build(cmd) => {
|
|
let mut build = wasm_pack::command::build::Build::try_from_opts(cmd)?;
|
|
build.set_cache(self.cache());
|
|
build.run()
|
|
}
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
|
|
pub fn lock(&self) -> MutexGuard<'static, ()> {
|
|
use std::sync::Mutex;
|
|
lazy_static! {
|
|
static ref ONE_TEST_AT_A_TIME: Mutex<()> = Mutex::new(());
|
|
}
|
|
ONE_TEST_AT_A_TIME.lock().unwrap_or_else(|e| e.into_inner())
|
|
}
|
|
}
|
|
|
|
impl Drop for Fixture {
|
|
fn drop(&mut self) {
|
|
if !thread::panicking() {
|
|
unsafe { ManuallyDrop::drop(&mut self.dir) }
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn bad_cargo_toml() -> Fixture {
|
|
let fixture = Fixture::new();
|
|
fixture.readme().hello_world_src_lib().file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bad-cargo-toml"
|
|
version = "0.1.0"
|
|
authors = ["The wasm-pack developers"]
|
|
|
|
[lib]
|
|
crate-type = ["foo"]
|
|
|
|
[dependencies]
|
|
# Note: no wasm-bindgen dependency!
|
|
"#,
|
|
);
|
|
fixture
|
|
}
|
|
|
|
pub fn js_hello_world() -> Fixture {
|
|
let fixture = Fixture::new();
|
|
fixture
|
|
.readme()
|
|
.cargo_toml("js-hello-world")
|
|
.hello_world_src_lib();
|
|
fixture
|
|
}
|
|
|
|
pub fn no_cdylib() -> Fixture {
|
|
let fixture = Fixture::new();
|
|
fixture.readme().hello_world_src_lib().file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
authors = ["The wasm-pack developers"]
|
|
description = "so awesome rust+wasm package"
|
|
license = "WTFPL"
|
|
name = "foo"
|
|
repository = "https://github.com/rustwasm/wasm-pack.git"
|
|
version = "0.1.0"
|
|
|
|
# [lib]
|
|
# crate-type = ["cdylib"]
|
|
|
|
[dependencies]
|
|
wasm-bindgen = "=0.2.21"
|
|
|
|
[dev-dependencies]
|
|
wasm-bindgen-test = "=0.2.21"
|
|
"#,
|
|
);
|
|
fixture
|
|
}
|
|
|
|
pub fn not_a_crate() -> Fixture {
|
|
let fixture = Fixture::new();
|
|
fixture.file("README.md", "This is not a Rust crate!");
|
|
fixture
|
|
}
|
|
|
|
pub fn serde_feature() -> Fixture {
|
|
let fixture = Fixture::new();
|
|
fixture.readme().hello_world_src_lib().file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "serde-serialize"
|
|
version = "0.1.0"
|
|
authors = ["The wasm-pack developers"]
|
|
|
|
[lib]
|
|
crate-type = ["cdylib"]
|
|
|
|
[dependencies.wasm-bindgen]
|
|
version = "^0.2"
|
|
features = ["serde-serialize"]
|
|
"#,
|
|
);
|
|
fixture
|
|
}
|
|
|
|
pub fn wbg_test_diff_versions() -> Fixture {
|
|
let fixture = Fixture::new();
|
|
fixture
|
|
.readme()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "wbg-test-diff-versions"
|
|
version = "0.1.0"
|
|
authors = ["The wasm-pack developers"]
|
|
|
|
[lib]
|
|
crate-type = ["cdylib", "rlib"]
|
|
|
|
[dependencies]
|
|
# We depend on wasm-bindgen 0.2.21
|
|
wasm-bindgen = "=0.2.21"
|
|
|
|
[dev-dependencies]
|
|
# And we depend on wasm-bindgen-test 0.2.19. This should still
|
|
# work, and we should end up with `wasm-bindgen` at 0.2.21 and
|
|
# wasm-bindgen-test at 0.2.19, and everything should still work.
|
|
wasm-bindgen-test = "0.2.19"
|
|
"#,
|
|
)
|
|
.file(
|
|
"src/lib.rs",
|
|
r#"
|
|
extern crate wasm_bindgen;
|
|
use wasm_bindgen::prelude::*;
|
|
|
|
#[wasm_bindgen]
|
|
pub fn one() -> u32 { 1 }
|
|
"#,
|
|
)
|
|
.file(
|
|
"tests/node.rs",
|
|
r#"
|
|
extern crate wbg_test_diff_versions;
|
|
extern crate wasm_bindgen_test;
|
|
use wasm_bindgen_test::*;
|
|
|
|
#[wasm_bindgen_test]
|
|
fn pass() {
|
|
assert_eq!(wbg_test_diff_versions::one(), 1);
|
|
}
|
|
"#,
|
|
);
|
|
fixture
|
|
}
|
|
|
|
pub fn wbg_test_browser() -> Fixture {
|
|
let fixture = Fixture::new();
|
|
fixture
|
|
.readme()
|
|
.cargo_toml("wbg-test-browser")
|
|
.hello_world_src_lib()
|
|
.file(
|
|
"tests/browser.rs",
|
|
r#"
|
|
extern crate wasm_bindgen_test;
|
|
use wasm_bindgen_test::*;
|
|
|
|
wasm_bindgen_test_configure!(run_in_browser);
|
|
|
|
#[wasm_bindgen_test]
|
|
fn pass() {
|
|
assert_eq!(1, 1);
|
|
}
|
|
"#,
|
|
);
|
|
fixture
|
|
}
|
|
|
|
pub fn wbg_test_fail() -> Fixture {
|
|
let fixture = Fixture::new();
|
|
fixture
|
|
.readme()
|
|
.cargo_toml("wbg-test-fail")
|
|
.hello_world_src_lib()
|
|
.file(
|
|
"tests/node.rs",
|
|
r#"
|
|
extern crate wasm_bindgen_test;
|
|
use wasm_bindgen_test::*;
|
|
|
|
#[wasm_bindgen_test]
|
|
fn pass() {
|
|
assert_eq!(1, 2);
|
|
}
|
|
"#,
|
|
);
|
|
fixture
|
|
}
|
|
|
|
pub fn wbg_test_node() -> Fixture {
|
|
let fixture = Fixture::new();
|
|
fixture
|
|
.readme()
|
|
.cargo_toml("wbg-test-node")
|
|
.hello_world_src_lib()
|
|
.file(
|
|
"tests/node.rs",
|
|
r#"
|
|
extern crate wasm_bindgen_test;
|
|
use wasm_bindgen_test::*;
|
|
|
|
#[wasm_bindgen_test]
|
|
fn pass() {
|
|
assert_eq!(1, 1);
|
|
}
|
|
"#,
|
|
);
|
|
fixture
|
|
}
|
|
|
|
pub fn transitive_dependencies() -> Fixture {
|
|
fn project_main_fixture(fixture: &mut Fixture) {
|
|
fixture.file(PathBuf::from("main/README"), "# Main Fixture\n");
|
|
fixture.file(
|
|
PathBuf::from("main/Cargo.toml"),
|
|
r#"
|
|
[package]
|
|
authors = ["The wasm-pack developers"]
|
|
description = "so awesome rust+wasm package"
|
|
license = "WTFPL"
|
|
name = "main_project"
|
|
repository = "https://github.com/rustwasm/wasm-pack.git"
|
|
version = "0.1.0"
|
|
|
|
[lib]
|
|
crate-type = ["cdylib"]
|
|
|
|
[dependencies]
|
|
wasm-bindgen = "=0.2.21"
|
|
project_a = { path = "../project_a" }
|
|
project_b = { path = "../project_b" }
|
|
|
|
[dev-dependencies]
|
|
wasm-bindgen-test = "=0.2.21"
|
|
"#,
|
|
);
|
|
fixture.file(
|
|
PathBuf::from("main/src/lib.rs"),
|
|
r#"
|
|
extern crate wasm_bindgen;
|
|
use wasm_bindgen::prelude::*;
|
|
|
|
// Import the `window.alert` function from the Web.
|
|
#[wasm_bindgen]
|
|
extern {
|
|
fn alert(s: &str);
|
|
}
|
|
|
|
// Export a `greet` function from Rust to JavaScript, that alerts a
|
|
// hello message.
|
|
#[wasm_bindgen]
|
|
pub fn greet(name: &str) {
|
|
alert(&format!("Hello, {}!", name));
|
|
}
|
|
"#,
|
|
);
|
|
}
|
|
|
|
fn project_a_fixture(fixture: &mut Fixture) {
|
|
fixture.file(
|
|
PathBuf::from("project_a/README"),
|
|
"# Project Alpha Fixture\n",
|
|
);
|
|
fixture.file(
|
|
PathBuf::from("project_a/Cargo.toml"),
|
|
r#"
|
|
[package]
|
|
authors = ["The wasm-pack developers"]
|
|
description = "so awesome rust+wasm package"
|
|
license = "WTFPL"
|
|
name = "project_a"
|
|
repository = "https://github.com/rustwasm/wasm-pack.git"
|
|
version = "0.1.0"
|
|
|
|
[lib]
|
|
crate-type = ["cdylib"]
|
|
|
|
[dependencies]
|
|
wasm-bindgen = "=0.2.21"
|
|
project_b = { path = "../project_b" }
|
|
|
|
[dev-dependencies]
|
|
wasm-bindgen-test = "=0.2.21"
|
|
"#,
|
|
);
|
|
fixture.file(
|
|
PathBuf::from("project_a/src/lib.rs"),
|
|
r#"
|
|
extern crate wasm_bindgen;
|
|
// extern crate project_b;
|
|
use wasm_bindgen::prelude::*;
|
|
|
|
// Import the `window.alert` function from the Web.
|
|
#[wasm_bindgen]
|
|
extern {
|
|
fn alert(s: &str);
|
|
}
|
|
|
|
// Export a `greet` function from Rust to JavaScript, that alerts a
|
|
// hello message.
|
|
#[wasm_bindgen]
|
|
pub fn greet(name: &str) {
|
|
alert(&format!("Hello, {}!", name));
|
|
}
|
|
"#,
|
|
);
|
|
}
|
|
|
|
fn project_b_fixture(fixture: &mut Fixture) {
|
|
fixture.file(
|
|
PathBuf::from("project_b/README"),
|
|
"# Project Beta Fixture\n",
|
|
);
|
|
fixture.file(
|
|
PathBuf::from("project_b/Cargo.toml"),
|
|
r#"
|
|
[package]
|
|
authors = ["The wasm-pack developers"]
|
|
description = "so awesome rust+wasm package"
|
|
license = "WTFPL"
|
|
name = "project_b"
|
|
repository = "https://github.com/rustwasm/wasm-pack.git"
|
|
version = "0.1.0"
|
|
|
|
[lib]
|
|
crate-type = ["cdylib"]
|
|
|
|
[dependencies]
|
|
wasm-bindgen = "=0.2.21"
|
|
|
|
[dev-dependencies]
|
|
wasm-bindgen-test = "=0.2.21"
|
|
"#,
|
|
);
|
|
fixture.file(
|
|
PathBuf::from("project_b/src/lib.rs"),
|
|
r#"
|
|
extern crate wasm_bindgen;
|
|
use wasm_bindgen::prelude::*;
|
|
|
|
// Import the `window.alert` function from the Web.
|
|
#[wasm_bindgen]
|
|
extern {
|
|
fn alert(s: &str);
|
|
}
|
|
|
|
// Export a `greet` function from Rust to JavaScript, that alerts a
|
|
// hello message.
|
|
#[wasm_bindgen]
|
|
pub fn greet(name: &str) {
|
|
alert(&format!("Hello, {}!", name));
|
|
}
|
|
"#,
|
|
);
|
|
}
|
|
|
|
let mut fixture = Fixture::new();
|
|
project_b_fixture(&mut fixture);
|
|
project_a_fixture(&mut fixture);
|
|
project_main_fixture(&mut fixture);
|
|
fixture
|
|
}
|
|
|
|
pub fn single_license() -> Fixture {
|
|
let fixture = Fixture::new();
|
|
fixture
|
|
.readme()
|
|
.cargo_toml("single_license")
|
|
.wtfpl_license()
|
|
.hello_world_src_lib();
|
|
fixture
|
|
}
|
|
|
|
pub fn dual_license() -> Fixture {
|
|
let fixture = Fixture::new();
|
|
fixture
|
|
.readme()
|
|
.cargo_toml("dual_license")
|
|
.wtfpl_license()
|
|
.mit_license()
|
|
.hello_world_src_lib();
|
|
fixture
|
|
}
|
|
|