use std::collections::HashSet;
use crate::{
Builder,
test_util::{build_and_open, test_entry_data::TestEntryData},
};
use assert2::assert;
use indexmap::IndexMap;
use std::io::Read;
use test_strategy::proptest;
#[tokio::test]
async fn empty_archive() {
let unpacked = build_and_open(Builder::<&[u8]>::new()).await;
assert!(unpacked.is_empty());
}
#[tokio::test]
async fn empty_entry_name() {
let mut builder: Builder<&[u8]> = Builder::new();
builder.add_entry(String::new(), b"".as_ref()).unwrap();
let mut unpacked = build_and_open(builder).await;
assert!(unpacked.len() == 1);
let mut zipfile = unpacked.by_index(0).unwrap();
let name = std::str::from_utf8(zipfile.name_raw()).unwrap().to_string();
assert!(name.is_empty());
let mut file_content = Vec::new();
zipfile.read_to_end(&mut file_content).unwrap();
assert!(file_content.is_empty());
}
#[tokio::test]
async fn archive_with_single_file() {
let mut builder: Builder<&[u8]> = Builder::new();
builder
.add_entry("Foo".to_owned(), b"bar!".as_slice())
.unwrap();
let mut unpacked = build_and_open(builder).await;
assert!(unpacked.len() == 1);
let mut zipfile = unpacked.by_index(0).unwrap();
let name = std::str::from_utf8(zipfile.name_raw()).unwrap().to_string();
assert!(name == "Foo");
let mut file_content = Vec::new();
zipfile.read_to_end(&mut file_content).unwrap();
assert!(file_content == b"bar!");
}
#[tokio::test]
async fn archive_with_single_empty_file() {
let mut builder: Builder<&[u8]> = Builder::new();
builder.add_entry("0".to_owned(), b"".as_slice()).unwrap();
let mut unpacked = build_and_open(builder).await;
assert!(unpacked.len() == 1);
let mut zipfile = unpacked.by_index(0).unwrap();
let name = std::str::from_utf8(zipfile.name_raw()).unwrap().to_string();
assert!(name == "0");
let mut file_content = Vec::new();
zipfile.read_to_end(&mut file_content).unwrap();
assert!(file_content == b"");
}
#[proptest(async = "tokio")]
async fn any_archive(content: TestEntryData) {
let builder = content.clone().into();
let mut unpacked = build_and_open(builder).await;
assert!(unpacked.len() == content.0.len());
let mut unpacked_content: IndexMap<String, Vec<u8>> = IndexMap::new();
for i in 0..unpacked.len() {
dbg!(&i);
let mut zipfile = unpacked.by_index(i).unwrap();
let name = std::str::from_utf8(zipfile.name_raw()).unwrap().to_string();
let mut file_content = Vec::new();
zipfile.read_to_end(&mut file_content).unwrap();
unpacked_content.insert(name, file_content);
}
assert!(unpacked_content == content.0);
}
#[proptest(async = "tokio")]
async fn entry_ordering(entry_names: HashSet<String>) {
let entry_names: Vec<_> = entry_names.into_iter().collect();
let mut builder = Builder::<&[u8]>::new();
for name in &entry_names {
builder.add_entry(name.clone(), b"".as_ref()).unwrap();
}
let mut unpacked = build_and_open(builder).await;
let unpacked_entries: Vec<_> = (0..unpacked.len())
.map(|i| {
let zipfile = unpacked.by_index(i).unwrap();
std::str::from_utf8(zipfile.name_raw()).unwrap().to_string()
})
.collect();
assert!(unpacked_entries == entry_names);
}
#[proptest(async = "tokio")]
async fn file_modification_time(
#[strategy(1980..=2107)] year: i32,
#[strategy(1u32..=12u32)] month: u32,
#[strategy(1u32..=31u32)] day: u32,
#[strategy(0u32..=23u32)] hour: u32,
#[strategy(0u32..=59u32)] minute: u32,
#[strategy(0u32..=59u32)] second: u32,
) {
let mut builder: Builder<&[u8]> = Builder::new();
builder
.add_entry("X".into(), b"".as_ref())
.unwrap()
.datetime_fields(year, month, day, hour, minute, second)
.unwrap();
let mut unpacked = build_and_open(builder).await;
assert!(unpacked.len() == 1);
let unpacked_timestamp = unpacked.by_index(0).unwrap().last_modified();
assert!(unpacked_timestamp.year() == u16::try_from(year).unwrap());
assert!(unpacked_timestamp.month() == u8::try_from(month).unwrap());
assert!(unpacked_timestamp.day() == u8::try_from(day).unwrap());
assert!(unpacked_timestamp.hour() == u8::try_from(hour).unwrap());
assert!(unpacked_timestamp.minute() == u8::try_from(minute).unwrap());
assert!(unpacked_timestamp.second() == u8::try_from(second & !1).unwrap());
}
#[tokio::test]
async fn regular_file_default_permissions() {
let mut builder: Builder<&[u8]> = Builder::new();
builder.add_entry("X".into(), b"".as_ref()).unwrap();
let mut unpacked = build_and_open(builder).await;
assert!(unpacked.len() == 1);
let permissions = unpacked.by_index(0).unwrap().unix_mode().unwrap();
assert!(permissions == 0o100_644);
}
#[tokio::test]
async fn directory_default_permissions() {
let mut builder: Builder<&[u8]> = Builder::new();
builder
.add_entry("X".into(), b"".as_ref())
.unwrap()
.directory();
let mut unpacked = build_and_open(builder).await;
assert!(unpacked.len() == 1);
let permissions = unpacked.by_index(0).unwrap().unix_mode().unwrap();
assert!(permissions == 0o40_755);
}
#[tokio::test]
async fn regular_file_override_permissions() {
let mut builder: Builder<&[u8]> = Builder::new();
builder
.add_entry("X".into(), b"".as_ref())
.unwrap()
.unix_permissions(0o123);
let mut unpacked = build_and_open(builder).await;
assert!(unpacked.len() == 1);
let permissions = unpacked.by_index(0).unwrap().unix_mode().unwrap();
assert!(permissions == 0o100_123);
}
#[tokio::test]
async fn directory_override_permissions() {
let mut builder: Builder<&[u8]> = Builder::new();
builder
.add_entry("X".into(), b"".as_ref())
.unwrap()
.directory()
.unix_permissions(0o123);
let mut unpacked = build_and_open(builder).await;
assert!(unpacked.len() == 1);
let permissions = unpacked.by_index(0).unwrap().unix_mode().unwrap();
assert!(permissions == 0o40_123);
}
#[tokio::test]
async fn readonly_file_permissions() {
let mut builder: Builder<&[u8]> = Builder::new();
builder
.add_entry("ro_file".into(), b"".as_ref())
.unwrap()
.readonly(true);
let mut unpacked = build_and_open(builder).await;
assert!(unpacked.len() == 1);
let permissions = unpacked.by_index(0).unwrap().unix_mode().unwrap();
assert!(permissions == 0o100_444);
}
#[tokio::test]
async fn readonly_directory_permissions() {
let mut builder: Builder<&[u8]> = Builder::new();
builder
.add_entry("ro_dir".into(), b"".as_ref())
.unwrap()
.directory()
.readonly(true);
let mut unpacked = build_and_open(builder).await;
assert!(unpacked.len() == 1);
let permissions = unpacked.by_index(0).unwrap().unix_mode().unwrap();
assert!(permissions == 0o40_555);
}
#[tokio::test]
async fn symlink_permissions() {
let mut builder: Builder<&[u8]> = Builder::new();
builder
.add_entry("X".into(), b"".as_ref())
.unwrap()
.symlink()
.unix_permissions(0o123);
let mut unpacked = build_and_open(builder).await;
assert!(unpacked.len() == 1);
let permissions = unpacked.by_index(0).unwrap().unix_mode().unwrap();
assert!(permissions == 0o120_777);
}