create runtime abi crate and vfs implementation

This commit is contained in:
Mackenzie Clark 2019-03-12 10:39:48 -07:00
parent ef69f6151c
commit f014a05304
6 changed files with 434 additions and 1 deletions

123
Cargo.lock generated
View File

@ -64,6 +64,14 @@ dependencies = [
"libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "base64"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "bindgen"
version = "0.46.0"
@ -101,6 +109,15 @@ dependencies = [
"constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "blob"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "byteorder"
version = "1.3.1"
@ -148,6 +165,9 @@ dependencies = [
name = "cc"
version = "1.0.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "cexpr"
@ -437,6 +457,16 @@ name = "field-offset"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "filetime"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fuchsia-cprng"
version = "0.1.1"
@ -745,6 +775,18 @@ dependencies = [
"proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand"
version = "0.6.5"
@ -1112,6 +1154,17 @@ dependencies = [
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tar"
version = "0.4.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)",
"xattr 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "target-lexicon"
version = "0.2.0"
@ -1122,6 +1175,15 @@ dependencies = [
"serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tempdir"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tempfile"
version = "3.0.7"
@ -1288,6 +1350,7 @@ dependencies = [
"wasmer-emscripten 0.2.1",
"wasmer-llvm-backend 0.1.0",
"wasmer-runtime 0.2.1",
"wasmer-runtime-abi 0.2.1",
"wasmer-runtime-core 0.2.1",
]
@ -1328,6 +1391,7 @@ dependencies = [
"wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
"wasmer-clif-backend 0.2.0",
"wasmer-llvm-backend 0.1.0",
"wasmer-runtime-abi 0.2.1",
"wasmer-runtime-core 0.2.1",
]
@ -1366,6 +1430,19 @@ dependencies = [
"wasmer-runtime-core 0.2.1",
]
[[package]]
name = "wasmer-runtime-abi"
version = "0.2.1"
dependencies = [
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"tar 0.4.21 (registry+https://github.com/rust-lang/crates.io-index)",
"tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"wasmer-runtime-core 0.2.1",
"wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
"zstd 0.4.22+zstd.1.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "wasmer-runtime-c-api"
version = "0.2.1"
@ -1492,6 +1569,42 @@ dependencies = [
"winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "xattr"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "zstd"
version = "0.4.22+zstd.1.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"zstd-safe 1.4.7+zstd.1.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "zstd-safe"
version = "1.4.7+zstd.1.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
"zstd-sys 1.4.8+zstd.1.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "zstd-sys"
version = "1.4.8+zstd.1.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"blob 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)",
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
]
[metadata]
"checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5"
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
@ -1501,9 +1614,11 @@ dependencies = [
"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799"
"checksum backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "cd5a90e2b463010cd0e0ce9a11d4a9d5d58d9f41d4a6ba3dcaf9e68b466e88b4"
"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6"
"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
"checksum bindgen 0.46.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8f7f7f0701772b17de73e4f5cbcb1dd6926f4706cba4c1ab62c5367f8bdc94e1"
"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
"checksum blake2b_simd 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce2571a6cd634670daa2977cc894c1cc2ba57c563c498e5a82c35446f34d056e"
"checksum blob 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "19803aa44ff8b43123bbe369efaddcb638ea7dc332e543972dd95ac7cb148b92"
"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb"
"checksum capstone 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "00be9d203fa0e078b93b24603633fb081851dfe0c1086364431f52587a47157e"
"checksum capstone-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2dc8d32bc5c1e6d0fcde10af411c98b07d93498d51654f678757f08fa2acd6a6"
@ -1540,6 +1655,7 @@ dependencies = [
"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2"
"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1"
"checksum field-offset 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "64e9bc339e426139e02601fa69d101e96a92aee71b58bc01697ec2a63a5c9e68"
"checksum filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a2df5c1a8c4be27e7707789dc42ae65976e60b394afd293d1419ab915833e646"
"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
"checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2"
"checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592"
@ -1580,6 +1696,7 @@ dependencies = [
"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
"checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1"
"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
@ -1623,7 +1740,9 @@ dependencies = [
"checksum syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1825685f977249735d510a242a6727b46efe914bb67e38d30c071b1b72b1d5c2"
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015"
"checksum tar 0.4.21 (registry+https://github.com/rust-lang/crates.io-index)" = "904b43da53c99b929c4484fa281e5535f2eb86b3040de3e3e5b69708e2a8bd65"
"checksum target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4af5e2227f0b887d591d3724b796a96eff04226104d872f5b3883fcd427d64b9"
"checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8"
"checksum tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b86c784c88d98c801132806dadd3819ed29d8600836c4088e855cdf3e178ed8a"
"checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f"
"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
@ -1656,3 +1775,7 @@ dependencies = [
"checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
"checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba"
"checksum xattr 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c"
"checksum zstd 0.4.22+zstd.1.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6f042dd18d52854d302d3d92f66d0a63c2d520d7b7034a9d43cde7441d1b4ddd"
"checksum zstd-safe 1.4.7+zstd.1.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "63febf0b0dcd076db81e6b3110ed254cfb8ed54378a4c3cfbb68956e839d4f59"
"checksum zstd-sys 1.4.8+zstd.1.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "4cb187d624025a7d9878ecf13437491869423426183ded2fa40d4651b85f7ae7"

View File

@ -25,12 +25,13 @@ wasmer-clif-backend = { path = "lib/clif-backend" }
wasmer-runtime = { path = "lib/runtime" }
wasmer-runtime-core = { path = "lib/runtime-core" }
wasmer-emscripten = { path = "lib/emscripten" }
wasmer-runtime-abi = { path = "lib/runtime-abi", optional = true }
[target.'cfg(not(windows))'.dependencies]
wasmer-llvm-backend = { path = "lib/llvm-backend" }
[workspace]
members = ["lib/clif-backend", "lib/runtime", "lib/runtime-core", "lib/emscripten", "lib/spectests", "lib/win-exception-handler", "lib/runtime-c-api", "lib/llvm-backend"]
members = ["lib/clif-backend", "lib/runtime", "lib/runtime-core", "lib/emscripten", "lib/spectests", "lib/win-exception-handler", "lib/runtime-c-api", "lib/llvm-backend", "lib/runtime-abi"]
[build-dependencies]
wabt = "0.7.2"

View File

@ -0,0 +1,22 @@
[package]
name = "wasmer-runtime-abi"
version = "0.2.1"
description = "Wasmer runtime core library"
license = "MIT"
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
repository = "https://github.com/wasmerio/wasmer"
edition = "2018"
[dependencies]
wasmer-runtime-core = { path = "../runtime-core", features = ["vfs"] }
hashbrown = "0.1"
failure = "0.1"
tar = "0.4"
zstd = "0.4"
wasmparser = "0.23.0"
[dev-dependencies]
tempdir = "0.3"
[features]
debug = []

View File

@ -0,0 +1,4 @@
#[macro_use]
extern crate failure;
pub mod vfs;

View File

@ -0,0 +1 @@
pub mod vfs;

View File

@ -0,0 +1,282 @@
use hashbrown::HashMap;
use std::io::Read;
use std::io::Write;
use std::path::{Path, PathBuf};
use std::sync::atomic::{AtomicIsize, Ordering};
use std::sync::Arc;
/// Simply an alias. May become a more complicated type in the future.
pub type Fd = isize;
/// Index into the file data vec.
pub type DataIndex = usize;
/// A simple key representing a path or a file descriptor. This filesystem treats paths and file
/// descriptor as first class citizens. A key has access to an index in the filesystem data.
#[derive(Hash, Eq, PartialEq, Debug)]
pub enum DataKey {
Path(PathBuf),
Fd(Fd),
}
pub struct VfsBacking {
/// The file data
blocks: Vec<Vec<u8>>,
/// Map of file descriptors or paths to indexes in the file data
data: HashMap<DataKey, DataIndex>,
/// Counter for file descriptors
fd_count: Arc<AtomicIsize>,
}
impl VfsBacking {
/// like read(2), will read the data for the file descriptor
pub fn read_file<Writer: Write>(
&mut self,
fd: Fd,
mut buf: Writer,
) -> Result<usize, failure::Error> {
let key = DataKey::Fd(fd);
let data_index = *self
.data
.get(&key)
.ok_or(VfsBackingError::FileDescriptorNotExist)?;
let data = self
.blocks
.get(data_index)
.ok_or(VfsBackingError::DataDoesNotExist)?;
buf.write(&data[..])
.map_err(|_| VfsBackingError::CopyError.into())
.map(|s| s as _)
}
/// like open(2), creates a file descriptor for the path if it exists
pub fn open_file<P: AsRef<Path>>(&mut self, path: P) -> Result<Fd, failure::Error> {
let path = path.as_ref().to_path_buf();
let key = DataKey::Path(path);
let data_index = *self
.data
.get(&key)
.ok_or(VfsBackingError::PathDoesNotExist)?;
// create an insert a file descriptor key
let fd = self.fd_count.fetch_add(1, Ordering::SeqCst);
let fd_key = DataKey::Fd(fd);
let _ = self.data.insert(fd_key, data_index);
Ok(fd)
}
/// Like `VfsBacking::from_tar_bytes` except it also decompresses from the zstd format.
pub fn from_tar_zstd_bytes<Reader: Read>(tar_bytes: Reader) -> Result<Self, failure::Error> {
let result = zstd::decode_all(tar_bytes);
let decompressed_data = result.unwrap();
VfsBacking::from_tar_bytes(&decompressed_data[..])
}
/// Create a vfs from raw bytes in tar format
pub fn from_tar_bytes<Reader: Read>(tar_bytes: Reader) -> Result<Self, failure::Error> {
let mut ar = tar::Archive::new(tar_bytes);
let mut data = HashMap::new();
let mut blocks = vec![];
for entry in ar.entries()? {
let mut entry = entry?;
// make a key from a path and insert the index of the
let path = entry.path().unwrap().to_path_buf();
let key = DataKey::Path(path);
let index = blocks.len();
data.insert(key, index);
// read the entry into a buffer and then push it into the file store
let mut file_data: Vec<u8> = vec![];
entry.read_to_end(&mut file_data).unwrap();
blocks.push(file_data);
}
let vfs = VfsBacking {
blocks,
data,
fd_count: Arc::new(AtomicIsize::new(0)),
};
Ok(vfs)
}
}
#[derive(Debug, Fail)]
pub enum VfsBackingError {
#[fail(display = "Data does not exist.")]
DataDoesNotExist,
#[fail(display = "Path does not exist.")]
PathDoesNotExist,
#[fail(display = "File descriptor does not exist.")]
FileDescriptorNotExist,
#[fail(display = "Error while copying to buffer")]
CopyError,
}
#[derive(Debug, Fail)]
pub enum VfsError {
#[fail(display = "File does not exist.")]
FileDoesNotExist,
}
#[cfg(test)]
mod open_test {
use crate::vfs::vfs::VfsBacking;
use std::fs::File;
use std::io::Write;
#[test]
fn open_files() {
// SETUP: create temp dir and files
let tmp_dir = tempdir::TempDir::new("open_files").unwrap();
let file_path = tmp_dir.path().join("foo.txt");
let mut tmp_file = File::create(file_path.clone()).unwrap();
writeln!(tmp_file, "foo foo foo").unwrap();
let tar_data = vec![];
let mut ar = tar::Builder::new(tar_data);
ar.append_path_with_name(file_path, "foo.txt").unwrap();
let archive = ar.into_inner().unwrap();
// SETUP: create virtual filesystem with tar data
let vfs_result = VfsBacking::from_tar_bytes(&archive[..]);
// ASSERT:
assert!(
vfs_result.is_ok(),
"Failed to create file system from empty archive"
);
let mut vfs = vfs_result.unwrap();
// open the file, get a file descriptor
let open_result = vfs.open_file("foo.txt");
assert!(
open_result.is_ok(),
"Failed to open file in the virtual filesystem."
);
// open the same file twice, and expect different descriptors
let fd_1 = open_result.unwrap();
let open_result_2 = vfs.open_file("foo.txt");
assert!(
open_result_2.is_ok(),
"Failed to open the same file twice in the virtual filesystem."
);
let fd_2 = open_result_2.unwrap();
assert_ne!(fd_1, fd_2, "Open produced the same file descriptor twice.");
}
#[test]
fn open_non_existent_file() {
// SETUP: create temp dir and files
let tmp_dir = tempdir::TempDir::new("open_non_existent_file").unwrap();
let file_path = tmp_dir.path().join("foo.txt");
let mut tmp_file = File::create(file_path.clone()).unwrap();
writeln!(tmp_file, "foo foo foo").unwrap();
let tar_data = vec![];
let mut ar = tar::Builder::new(tar_data);
ar.append_path_with_name(file_path, "foo.txt").unwrap();
let archive = ar.into_inner().unwrap();
// SETUP: create virtual filesystem with tar data
let vfs_result = VfsBacking::from_tar_bytes(&archive[..]);
// ASSERT:
assert!(
vfs_result.is_ok(),
"Failed to create file system from empty archive"
);
let mut vfs = vfs_result.unwrap();
// read the file
let open_result = vfs.open_file("foo.txt");
assert!(open_result.is_ok(), "Failed to read file from vfs");
// open a non-existent file
let open_result_2 = vfs.open_file("bar.txt");
assert!(
open_result_2.is_err(),
"Somehow opened a non-existent file."
);
}
}
#[cfg(test)]
mod read_test {
use crate::vfs::vfs::VfsBacking;
use std::fs::File;
use std::io::Write;
use tempdir;
#[test]
fn empty_archive() {
// SETUP: create temp dir and files
let empty_archive = vec![];
// SETUP: create virtual filesystem with tar data
let vfs_result = VfsBacking::from_tar_bytes(&empty_archive[..]);
// ASSERT:
assert!(
vfs_result.is_ok(),
"Failed to create file system from empty archive"
);
}
#[test]
fn single_file_archive() {
// SETUP: create temp dir and files
let tmp_dir = tempdir::TempDir::new("single_file_archive").unwrap();
let foo_file_path = tmp_dir.path().join("foo.txt");
let mut foo_tmp_file = File::create(foo_file_path.clone()).unwrap();
writeln!(foo_tmp_file, "foo foo foo").unwrap();
let tar_data = vec![];
let mut ar = tar::Builder::new(tar_data);
ar.append_path_with_name(foo_file_path, "foo.txt").unwrap();
let archive = ar.into_inner().unwrap();
// SETUP: create virtual filesystem with tar data
let vfs_result = VfsBacking::from_tar_bytes(&archive[..]);
// ASSERT:
assert!(
vfs_result.is_ok(),
"Failed to create file system from empty archive"
);
let mut vfs = vfs_result.unwrap();
// read the file
let fd = vfs.open_file("foo.txt").unwrap();
let mut actual_data: Vec<u8> = Vec::new();
let read_result = vfs.read_file(fd, &mut actual_data);
assert!(read_result.is_ok(), "Failed to read file from vfs");
let expected_data = "foo foo foo\n".as_bytes();
assert_eq!(actual_data, expected_data, "Contents were not equal");
}
#[test]
fn two_files_in_archive() {
// SETUP: create temp dir and files
let tmp_dir = tempdir::TempDir::new("two_files_in_archive").unwrap();
let foo_file_path = tmp_dir.path().join("foo.txt");
let bar_file_path = tmp_dir.path().join("bar.txt");
let mut foo_tmp_file = File::create(foo_file_path.clone()).unwrap();
let mut bar_tmp_file = File::create(bar_file_path.clone()).unwrap();
writeln!(foo_tmp_file, "foo foo foo").unwrap();
writeln!(bar_tmp_file, "bar bar").unwrap();
let tar_data = vec![];
let mut ar = tar::Builder::new(tar_data);
ar.append_path_with_name(foo_file_path, "foo.txt").unwrap();
ar.append_path_with_name(bar_file_path, "bar.txt").unwrap();
let archive = ar.into_inner().unwrap();
// SETUP: create virtual filesystem with tar data
let vfs_result = VfsBacking::from_tar_bytes(&archive[..]);
// ASSERT:
assert!(
vfs_result.is_ok(),
"Failed to create file system from empty archive"
);
let mut vfs = vfs_result.unwrap();
// read the file
let foo_fd = vfs.open_file("foo.txt").unwrap();
let bar_fd = vfs.open_file("bar.txt").unwrap();
let mut foo_actual_data: Vec<u8> = Vec::new();
let foo_read_result = vfs.read_file(foo_fd, &mut foo_actual_data);
let mut bar_actual_data: Vec<u8> = Vec::new();
let bar_read_result = vfs.read_file(bar_fd, &mut bar_actual_data);
assert!(foo_read_result.is_ok(), "Failed to read foo.txt from vfs");
assert!(bar_read_result.is_ok(), "Failed to read bar.txt from vfs");
let foo_expected_data = Vec::from("foo foo foo\n");
let bar_expected_data = Vec::from("bar bar\n");
assert_eq!(
foo_actual_data, foo_expected_data,
"Contents of `foo.txt` is not correct"
);
assert_eq!(
bar_actual_data, bar_expected_data,
"Contents of `bar.txt` is not correct"
);
}
}