Skip to content

Commit 0c98778

Browse files
committed
test(binaryinstall): Add initial tests
1 parent c8410f2 commit 0c98778

File tree

5 files changed

+273
-14
lines changed

5 files changed

+273
-14
lines changed

binary-install/Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,6 @@ is_executable = "0.1.2"
1818
siphasher = "0.2.3"
1919
tar = "0.4.16"
2020
zip = "0.5.0"
21+
22+
[dev-dependencies]
23+
tempfile = "3.0.5"

binary-install/src/lib.rs

+83-14
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,13 @@ use std::path::{Path, PathBuf};
2323

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

3031
/// Representation of a downloaded tarball/zip
32+
#[derive(Debug)]
3133
pub struct Download {
3234
root: PathBuf,
3335
}
@@ -81,22 +83,10 @@ impl Cache {
8183
binaries: &[&str],
8284
url: &str,
8385
) -> Result<Option<Download>, Error> {
84-
let mut hasher = SipHasher13::new();
85-
url.hash(&mut hasher);
86-
let result = hasher.finish();
87-
let hex = hex::encode(&[
88-
(result >> 0) as u8,
89-
(result >> 8) as u8,
90-
(result >> 16) as u8,
91-
(result >> 24) as u8,
92-
(result >> 32) as u8,
93-
(result >> 40) as u8,
94-
(result >> 48) as u8,
95-
(result >> 56) as u8,
96-
]);
97-
let dirname = format!("{}-{}", name, hex);
86+
let dirname = hashed_dirname(url, name);
9887

9988
let destination = self.destination.join(&dirname);
89+
10090
if destination.exists() {
10191
return Ok(Some(Download { root: destination }));
10292
}
@@ -270,3 +260,82 @@ fn curl(url: &str) -> Result<Vec<u8>, Error> {
270260
)
271261
}
272262
}
263+
264+
fn hashed_dirname(url: &str, name: &str) -> String {
265+
let mut hasher = SipHasher13::new();
266+
url.hash(&mut hasher);
267+
let result = hasher.finish();
268+
let hex = hex::encode(&[
269+
(result >> 0) as u8,
270+
(result >> 8) as u8,
271+
(result >> 16) as u8,
272+
(result >> 24) as u8,
273+
(result >> 32) as u8,
274+
(result >> 40) as u8,
275+
(result >> 48) as u8,
276+
(result >> 56) as u8,
277+
]);
278+
format!("{}-{}", name, hex)
279+
}
280+
281+
#[test]
282+
fn it_returns_same_hash_for_same_name_and_url() {
283+
let name = "wasm-pack";
284+
let url = "http://localhost:7878/wasm-pack-v0.6.0.tar.gz";
285+
286+
let first = hashed_dirname(url, name);
287+
let second = hashed_dirname(url, name);
288+
289+
assert!(!first.is_empty());
290+
assert!(!second.is_empty());
291+
assert_eq!(first, second);
292+
}
293+
294+
#[test]
295+
fn it_returns_different_hashes_for_different_urls() {
296+
let name = "wasm-pack";
297+
let url = "http://localhost:7878/wasm-pack-v0.5.1.tar.gz";
298+
let second_url = "http://localhost:7878/wasm-pack-v0.6.0.tar.gz";
299+
300+
let first = hashed_dirname(url, name);
301+
let second = hashed_dirname(second_url, name);
302+
303+
assert_ne!(first, second);
304+
}
305+
306+
#[test]
307+
fn it_returns_cache_dir() {
308+
let name = "wasm-pack";
309+
let cache = Cache::new(name);
310+
311+
let expected = dirs::cache_dir()
312+
.unwrap()
313+
.join(PathBuf::from(".".to_owned() + name));
314+
315+
assert!(cache.is_ok());
316+
assert_eq!(cache.unwrap().destination, expected);
317+
}
318+
319+
#[test]
320+
fn it_returns_destination_if_binary_already_exists() {
321+
use std::fs;
322+
323+
let binary_name = "wasm-pack";
324+
let binaries = vec![binary_name];
325+
326+
let dir = tempfile::TempDir::new().unwrap();
327+
let cache = Cache::at(dir.path());
328+
let url = &format!("{}/{}.tar.gz", "http://localhost:7878", binary_name);
329+
330+
let dirname = hashed_dirname(&url, &binary_name);
331+
let full_path = dir.path().join(dirname);
332+
333+
// Create temporary directory and binary to simulate that
334+
// a cached binary already exists.
335+
fs::create_dir_all(full_path).unwrap();
336+
337+
let dl = cache.download(true, binary_name, &binaries, url);
338+
339+
assert!(dl.is_ok());
340+
assert!(dl.unwrap().is_some())
341+
}

binary-install/tests/all/cache.rs

+114
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
use binary_install::Cache;
2+
use utils;
3+
4+
#[test]
5+
fn it_returns_none_if_install_is_not_permitted() {
6+
let binary_name = "wasm-pack";
7+
let binaries = vec![binary_name];
8+
9+
let dir = tempfile::TempDir::new().unwrap();
10+
let cache = Cache::at(dir.path());
11+
12+
let dl = cache.download(
13+
false,
14+
binary_name,
15+
&binaries,
16+
&format!("{}/{}.tar.gz", "", binary_name),
17+
);
18+
19+
assert!(dl.is_ok());
20+
assert!(dl.unwrap().is_none())
21+
}
22+
23+
#[test]
24+
fn it_downloads_tarball() {
25+
let server_port = 7880;
26+
let url = format!("http://{}:{}", utils::TEST_SERVER_HOST, server_port);
27+
let binary_name = "wasm-pack";
28+
let binaries = vec![binary_name];
29+
30+
// Create a temporary tarball.
31+
let tarball = utils::create_tarball(binary_name).ok();
32+
33+
// Spin up a local TcpListener.
34+
utils::start_server(server_port, tarball);
35+
36+
let dir = tempfile::TempDir::new().unwrap();
37+
let cache = Cache::at(dir.path());
38+
39+
let dl = cache.download(
40+
true,
41+
binary_name,
42+
&binaries,
43+
&format!("{}/{}.tar.gz", &url, binary_name),
44+
);
45+
46+
assert!(dl.is_ok());
47+
assert!(dl.unwrap().is_some())
48+
}
49+
50+
#[test]
51+
fn it_returns_error_that_it_failed_to_download() {
52+
let server_port = 7881;
53+
let url = format!("http://{}:{}", utils::TEST_SERVER_HOST, server_port);
54+
let binary_name = "wasm-pack";
55+
let binaries = vec![binary_name];
56+
57+
let dir = tempfile::TempDir::new().unwrap();
58+
let cache = Cache::at(dir.path());
59+
let full_url = &format!("{}/{}.tar.gz", &url, binary_name);
60+
61+
let dl = cache.download(true, binary_name, &binaries, full_url);
62+
63+
assert!(dl.is_err());
64+
assert_eq!(
65+
&format!("failed to download from {}", full_url),
66+
&format!("{}", dl.unwrap_err())
67+
);
68+
}
69+
70+
#[test]
71+
fn it_returns_error_when_it_failed_to_extract_tarball() {
72+
let server_port = 7882;
73+
let url = format!("http://{}:{}", utils::TEST_SERVER_HOST, server_port);
74+
let binary_name = "wasm-pack";
75+
let binaries = vec![binary_name];
76+
77+
let dir = tempfile::TempDir::new().unwrap();
78+
let cache = Cache::at(dir.path());
79+
let full_url = &format!("{}/{}.tar.gz", &url, binary_name);
80+
81+
// Spin up a local TcpListener.
82+
utils::start_server(server_port, None);
83+
84+
let dl = cache.download(true, binary_name, &binaries, full_url);
85+
86+
assert!(dl.is_err());
87+
assert_eq!(
88+
&format!("failed to extract tarball from {}", full_url),
89+
&format!("{}", dl.unwrap_err())
90+
);
91+
}
92+
93+
#[test]
94+
fn it_returns_error_when_it_failed_to_extract_zip() {
95+
let server_port = 7883;
96+
let url = format!("http://{}:{}", utils::TEST_SERVER_HOST, server_port);
97+
let binary_name = "wasm-pack";
98+
let binaries = vec![binary_name];
99+
100+
let dir = tempfile::TempDir::new().unwrap();
101+
let cache = Cache::at(dir.path());
102+
let full_url = &format!("{}/{}.zip", &url, binary_name);
103+
104+
// Spin up a local TcpListener.
105+
utils::start_server(server_port, None);
106+
107+
let dl = cache.download(true, binary_name, &binaries, full_url);
108+
109+
assert!(dl.is_err());
110+
assert_eq!(
111+
&format!("failed to extract zip from {}", full_url),
112+
&format!("{}", dl.unwrap_err())
113+
);
114+
}

binary-install/tests/all/main.rs

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
extern crate binary_install;
2+
extern crate flate2;
3+
extern crate tar;
4+
5+
pub mod cache;
6+
pub mod utils;

binary-install/tests/all/utils/mod.rs

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
use flate2::write::GzEncoder;
2+
use flate2::Compression;
3+
use std::fs::{File, OpenOptions};
4+
use std::io::{self, Read, Write};
5+
use std::net::TcpListener;
6+
use std::thread;
7+
8+
pub const TEST_SERVER_HOST: &'static str = "localhost";
9+
10+
pub fn start_server(port: u32, tarball: Option<Vec<u8>>) -> thread::JoinHandle<TcpListener> {
11+
thread::spawn(move || {
12+
let listener = TcpListener::bind(format!("{}:{}", TEST_SERVER_HOST, port)).unwrap();
13+
14+
for stream in listener.incoming() {
15+
let mut stream = stream.unwrap();
16+
17+
let mut buffer = [0; 512];
18+
19+
stream.read(&mut buffer).unwrap();
20+
21+
let response = "HTTP/1.1 200 OK\r\n\r\n";
22+
23+
stream.write(response.as_bytes()).unwrap();
24+
25+
match tarball.to_owned() {
26+
Some(tar) => {
27+
stream.write(tar.as_ref()).unwrap();
28+
}
29+
None => {}
30+
}
31+
32+
stream.flush().unwrap();
33+
}
34+
listener
35+
})
36+
}
37+
38+
pub fn create_tarball(binary_name: &str) -> Result<Vec<u8>, io::Error> {
39+
let temp_dir = tempfile::TempDir::new().unwrap();
40+
let full_path = temp_dir.path().join(binary_name.to_owned() + ".tar.gz");
41+
42+
let tar = OpenOptions::new()
43+
.create(true)
44+
.read(true)
45+
.write(true)
46+
.open(&full_path)?;
47+
48+
let mut file = OpenOptions::new()
49+
.create(true)
50+
.read(true)
51+
.write(true)
52+
.open(temp_dir.path().join(binary_name))?;
53+
54+
let mut encoder = GzEncoder::new(tar, Compression::default());
55+
{
56+
let mut archive = tar::Builder::new(&mut encoder);
57+
archive.append_file(binary_name, &mut file)?;
58+
}
59+
60+
let mut contents = vec![];
61+
62+
encoder.finish()?;
63+
64+
File::open(temp_dir.path().join(&full_path))?.read_to_end(&mut contents)?;
65+
66+
Ok(contents)
67+
}

0 commit comments

Comments
 (0)