use std::fs::File;
use std::io;
use std::process::Command;
use anyhow::{Context, Result};
use camino::Utf8Path;
use log::*;
use memmap::Mmap;
use rayon::prelude::*;
use piz::read::*;
use piz::result::ZipError;
#[test]
fn smoke() -> Result<()> {
let _ = env_logger::builder().is_test(true).try_init();
let inputs = [
"tests/inputs/hello.zip",
"tests/inputs/hello-prefixed.zip",
"tests/inputs/zip64.zip",
];
if inputs.iter().any(|i| !Utf8Path::new(i).exists()) {
Command::new("tests/create-inputs.sh")
.status()
.expect("Couldn't set up input files");
}
for input in &inputs {
read_zip(input)?;
}
Ok(())
}
fn read_zip(zip_path: &str) -> Result<()> {
info!("Memory mapping {:#?}", zip_path);
let zip_file = File::open(zip_path).context("Couldn't open zip file")?;
let mapping = unsafe { Mmap::map(&zip_file).context("Couldn't mmap zip file")? };
let archive = ZipArchive::with_prepended_data(&mapping)
.context("Couldn't load archive")?
.0;
let tree = as_tree(archive.entries())?;
match zip_path {
"tests/inputs/hello.zip" | "tests/inputs/hello-prefixed.zip" => {
tree.lookup("hello/hi.txt")?;
tree.lookup("hello/rip.txt")?;
tree.lookup("hello/sr71.txt")?;
let no_such_file = Utf8Path::new("no/such/file");
match tree.lookup(no_such_file) {
Err(ZipError::NoSuchFile(p)) => {
assert_eq!(no_such_file, p);
}
Err(other) => panic!("Got incorrect error from path with no file: {:?}", other),
Ok(_) => panic!("Got a file back from a path with no file"),
};
let no_such_file = Utf8Path::new("top-level-no-such-file");
match tree.lookup(no_such_file) {
Err(ZipError::NoSuchFile(p)) => {
assert_eq!(no_such_file, p);
}
Err(other) => panic!("Got incorrect error from path with no file: {:?}", other),
Ok(_) => panic!("Got a file back from a path with no file"),
};
let invalid_path = Utf8Path::new("../nope");
match tree.lookup(invalid_path) {
Err(ZipError::InvalidPath(_)) => { }
Err(other) => panic!("Got incorrect error from invalid path: {:?}", other),
Ok(_) => panic!("Got a file back from invalid path"),
};
}
"tests/inputs/zip64.zip" => {
tree.lookup("zip64/zero100")?;
tree.lookup("zip64/zero4400")?;
tree.lookup("zip64/zero5000")?;
}
wut => unreachable!("{}", wut),
};
tree.files()
.map(|e| archive.read(e))
.par_bridge()
.try_for_each::<_, Result<()>>(|reader| {
let mut sink = io::sink();
io::copy(&mut reader?, &mut sink)?;
Ok(())
})?;
Ok(())
}