Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(binaryinstall): Add initial tests #517

Merged
merged 9 commits into from
Mar 1, 2019
3 changes: 3 additions & 0 deletions .appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ build: false
test_script:
- cargo test --release --tests --locked
- cargo test --release --doc
- cd binary-install
- cargo test
- cd ..

before_deploy:
- ps: |
Expand Down
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ matrix:
install:
- *INSTALL_NODE_VIA_NVM
script:
- cargo test --locked
- cargo test --all --locked
- rustup component add rustfmt-preview
- cargo fmt --version
- cargo fmt --all -- --check
Expand Down
3 changes: 3 additions & 0 deletions binary-install/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,6 @@ is_executable = "0.1.2"
siphasher = "0.2.3"
tar = "0.4.16"
zip = "0.5.0"

[dev-dependencies]
tempfile = "3.0.5"
102 changes: 88 additions & 14 deletions binary-install/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@ use std::path::{Path, PathBuf};

/// Global cache for wasm-pack, currently containing binaries downloaded from
/// urls like wasm-bindgen and such.
#[derive(Debug)]
pub struct Cache {
destination: PathBuf,
}

/// Representation of a downloaded tarball/zip
#[derive(Debug)]
pub struct Download {
root: PathBuf,
}
Expand Down Expand Up @@ -81,22 +83,10 @@ impl Cache {
binaries: &[&str],
url: &str,
) -> Result<Option<Download>, Error> {
let mut hasher = SipHasher13::new();
url.hash(&mut hasher);
let result = hasher.finish();
let hex = hex::encode(&[
(result >> 0) as u8,
(result >> 8) as u8,
(result >> 16) as u8,
(result >> 24) as u8,
(result >> 32) as u8,
(result >> 40) as u8,
(result >> 48) as u8,
(result >> 56) as u8,
]);
let dirname = format!("{}-{}", name, hex);
let dirname = hashed_dirname(url, name);

let destination = self.destination.join(&dirname);

if destination.exists() {
return Ok(Some(Download { root: destination }));
}
Expand Down Expand Up @@ -270,3 +260,87 @@ fn curl(url: &str) -> Result<Vec<u8>, Error> {
)
}
}

fn hashed_dirname(url: &str, name: &str) -> String {
let mut hasher = SipHasher13::new();
url.hash(&mut hasher);
let result = hasher.finish();
let hex = hex::encode(&[
(result >> 0) as u8,
(result >> 8) as u8,
(result >> 16) as u8,
(result >> 24) as u8,
(result >> 32) as u8,
(result >> 40) as u8,
(result >> 48) as u8,
(result >> 56) as u8,
]);
format!("{}-{}", name, hex)
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn it_returns_same_hash_for_same_name_and_url() {
let name = "wasm-pack";
let url = "http://localhost:7878/wasm-pack-v0.6.0.tar.gz";

let first = hashed_dirname(url, name);
let second = hashed_dirname(url, name);

assert!(!first.is_empty());
assert!(!second.is_empty());
assert_eq!(first, second);
}

#[test]
fn it_returns_different_hashes_for_different_urls() {
let name = "wasm-pack";
let url = "http://localhost:7878/wasm-pack-v0.5.1.tar.gz";
let second_url = "http://localhost:7878/wasm-pack-v0.6.0.tar.gz";

let first = hashed_dirname(url, name);
let second = hashed_dirname(second_url, name);

assert_ne!(first, second);
}

#[test]
fn it_returns_cache_dir() {
let name = "wasm-pack";
let cache = Cache::new(name);

let expected = dirs::cache_dir()
.unwrap()
.join(PathBuf::from(".".to_owned() + name));

assert!(cache.is_ok());
assert_eq!(cache.unwrap().destination, expected);
}

#[test]
fn it_returns_destination_if_binary_already_exists() {
use std::fs;

let binary_name = "wasm-pack";
let binaries = vec![binary_name];

let dir = tempfile::TempDir::new().unwrap();
let cache = Cache::at(dir.path());
let url = &format!("{}/{}.tar.gz", "http://localhost:7878", binary_name);

let dirname = hashed_dirname(&url, &binary_name);
let full_path = dir.path().join(dirname);

// Create temporary directory and binary to simulate that
// a cached binary already exists.
fs::create_dir_all(full_path).unwrap();

let dl = cache.download(true, binary_name, &binaries, url);

assert!(dl.is_ok());
assert!(dl.unwrap().is_some())
}
}
141 changes: 141 additions & 0 deletions binary-install/tests/all/cache.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
use binary_install::Cache;
use std::path::Path;
use utils;

#[test]
fn it_returns_none_if_install_is_not_permitted() {
let binary_name = "wasm-pack";
let binaries = vec![binary_name];

let dir = tempfile::TempDir::new().unwrap();
let cache = Cache::at(dir.path());

let dl = cache.download(
false,
binary_name,
&binaries,
&format!("{}/{}.tar.gz", "", binary_name),
);

assert!(dl.is_ok());
assert!(dl.unwrap().is_none())
}

#[test]
fn it_downloads_tarball() {
let server_port = 7880;
let url = format!("http://{}:{}", utils::TEST_SERVER_HOST, server_port);
let binary_name = "wasm-pack";
let binaries = vec![binary_name];

// Create a temporary tarball.
let tarball = utils::create_tarball(binary_name).ok();

// Spin up a local TcpListener.
utils::start_server(server_port, tarball).recv().unwrap();

let dir = tempfile::TempDir::new().unwrap();
let cache = Cache::at(dir.path());

let dl = cache.download(
true,
binary_name,
&binaries,
&format!("{}/{}.tar.gz", &url, binary_name),
);

assert!(dl.is_ok());
assert!(dl.unwrap().is_some())
}

#[test]
fn it_returns_error_when_it_failed_to_download() {
let server_port = 7881;
let url = format!("http://{}:{}", utils::TEST_SERVER_HOST, server_port);
let binary_name = "wasm-pack";
let binaries = vec![binary_name];

let dir = tempfile::TempDir::new().unwrap();
let cache = Cache::at(dir.path());
let full_url = &format!("{}/{}.tar.gz", &url, binary_name);

let dl = cache.download(true, binary_name, &binaries, full_url);

assert!(dl.is_err());
assert_eq!(
&format!("failed to download from {}", full_url),
&format!("{}", dl.unwrap_err())
);
}

#[test]
fn it_returns_error_when_it_failed_to_extract_tarball() {
let server_port = 7882;
let url = format!("http://{}:{}", utils::TEST_SERVER_HOST, server_port);
let binary_name = "wasm-pack";
let binaries = vec![binary_name];

let dir = tempfile::TempDir::new().unwrap();
let cache = Cache::at(dir.path());
let full_url = &format!("{}/{}.tar.gz", &url, binary_name);

// Spin up a local TcpListener.
utils::start_server(server_port, None).recv().unwrap();

let dl = cache.download(true, binary_name, &binaries, full_url);

assert!(dl.is_err());
assert_eq!(
&format!("failed to extract tarball from {}", full_url),
&format!("{}", dl.unwrap_err())
);
}

#[test]
fn it_returns_error_when_it_failed_to_extract_zip() {
let server_port = 7883;
let url = format!("http://{}:{}", utils::TEST_SERVER_HOST, server_port);
let binary_name = "wasm-pack";
let binaries = vec![binary_name];

let dir = tempfile::TempDir::new().unwrap();
let cache = Cache::at(dir.path());
let full_url = &format!("{}/{}.zip", &url, binary_name);

// Spin up a local TcpListener.
utils::start_server(server_port, None).recv().unwrap();

let dl = cache.download(true, binary_name, &binaries, full_url);

assert!(dl.is_err());
assert_eq!(
&format!("failed to extract zip from {}", full_url),
&format!("{}", dl.unwrap_err())
);
}

#[test]
#[should_panic(expected = "don't know how to extract http://localhost:7884/wasm-pack.bin")]
fn it_panics_if_not_tarball_or_zip() {
let server_port = 7884;
let url = format!("http://{}:{}", utils::TEST_SERVER_HOST, server_port);
let binary_name = "wasm-pack";
let binaries = vec![binary_name];

let dir = tempfile::TempDir::new().unwrap();
let cache = Cache::at(dir.path());
let full_url = &format!("{}/{}.bin", &url, binary_name);

// Spin up a local TcpListener.
utils::start_server(server_port, None).recv().unwrap();

let _ = cache.download(true, binary_name, &binaries, full_url);
}

#[test]
fn it_joins_path_with_destination() {
let dir = tempfile::TempDir::new().unwrap();
let cache = Cache::at(dir.path());

assert_eq!(dir.path().join("hello"), cache.join(Path::new("hello")));
}
Loading