From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id 6509FBA800 for ; Thu, 14 Dec 2023 15:49:03 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 16F0B18A8D for ; Thu, 14 Dec 2023 15:49:03 +0100 (CET) Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com [94.136.29.106]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by firstgate.proxmox.com (Proxmox) with ESMTPS for ; Thu, 14 Dec 2023 15:49:02 +0100 (CET) Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1]) by proxmox-new.maurer-it.com (Proxmox) with ESMTP id C73964763C for ; Thu, 14 Dec 2023 15:49:01 +0100 (CET) From: Filip Schauer To: pbs-devel@lists.proxmox.com Date: Thu, 14 Dec 2023 15:48:22 +0100 Message-Id: <20231214144824.100616-4-f.schauer@proxmox.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20231214144824.100616-1-f.schauer@proxmox.com> References: <20231214144824.100616-1-f.schauer@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL -0.154 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record T_SCC_BODY_TEXT_LINE -0.01 - Subject: [pbs-devel] [PATCH v3 proxmox 3/3] compression: Add unit tests for the ZipEncoder X-BeenThere: pbs-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox Backup Server development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 14 Dec 2023 14:49:03 -0000 Signed-off-by: Filip Schauer --- proxmox-compression/Cargo.toml | 2 +- proxmox-compression/tests/zip.rs | 134 +++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 proxmox-compression/tests/zip.rs diff --git a/proxmox-compression/Cargo.toml b/proxmox-compression/Cargo.toml index 49735cb..8c9c47e 100644 --- a/proxmox-compression/Cargo.toml +++ b/proxmox-compression/Cargo.toml @@ -27,5 +27,5 @@ proxmox-io = { workspace = true, features = [ "tokio" ] } proxmox-lang.workspace = true [dev-dependencies] -tokio = { workspace = true, features = [ "macros" ] } +tokio = { workspace = true, features = [ "macros", "rt" ] } diff --git a/proxmox-compression/tests/zip.rs b/proxmox-compression/tests/zip.rs new file mode 100644 index 0000000..f684ccc --- /dev/null +++ b/proxmox-compression/tests/zip.rs @@ -0,0 +1,134 @@ +use proxmox_compression::zip::{FileType, ZipEncoder, ZipEntry}; + +use anyhow::{ensure, Error}; +use flate2::{Decompress, FlushDecompress}; +use std::ffi::OsString; +use tokio::test; + +fn check_zip_with_one_file( + bytes: Vec, + expected_file_name: &str, + expected_content: &[u8], + expected_file_attributes: u16, + is_file: bool, +) -> Result<(), Error> { + ensure!( + &bytes[..4] == b"PK\x03\x04", + "ZIP magic number does not match" + ); + + let general_purpose_flags = &bytes[6..8]; + let size_compressed = &bytes[18..22]; + let size_uncompressed = &bytes[22..26]; + let file_name_len = (bytes[26] as usize) | ((bytes[27] as usize) << 8); + let extra_len = (bytes[28] as usize) | ((bytes[29] as usize) << 8); + let file_name = &bytes[30..30 + file_name_len]; + let mut offset = 30 + file_name_len; + + assert_eq!(expected_file_name.as_bytes(), file_name); + + offset += extra_len; + + if is_file { + let mut decompress = Decompress::new(false); + let mut decompressed_data = vec![0u8; expected_content.len()]; + decompress.decompress( + &bytes[offset..], + &mut decompressed_data, + FlushDecompress::Finish, + )?; + + assert_eq!(decompressed_data, expected_content); + + offset += decompress.total_in() as usize; + } + + // Optional data descriptor + if &bytes[offset..offset + 4] == b"PK\x07\x08" { + offset += 4; + + if (general_purpose_flags[0] & 0x08) == 0x08 { + offset += 12; + + if size_compressed == b"\xff\xff\xff\xff" && size_uncompressed == b"\xff\xff\xff\xff" { + offset += 8; + } + } + } + + ensure!( + &bytes[offset..offset + 4] == b"PK\x01\x02", + "Missing central directory file header" + ); + + let external_file_attributes = &bytes[offset + 38..offset + 42]; + let file_attributes = u16::from_le_bytes(external_file_attributes[2..4].try_into()?); + + assert_eq!(expected_file_attributes, file_attributes); + + Ok(()) +} + +#[test] +async fn test_zip_text_file() -> Result<(), Error> { + let mut target = Vec::new(); + + let source_contents = "bar"; + let source = source_contents.as_bytes(); + + let mut zip_encoder = ZipEncoder::new(&mut target); + zip_encoder + .add_entry( + ZipEntry::new("foo.txt", 0, 0o755, FileType::Regular), + Some(source), + ) + .await?; + + zip_encoder.finish().await?; + + check_zip_with_one_file(target, "foo.txt", b"bar", 0o100755, true)?; + + Ok(()) +} + +#[test] +async fn test_zip_symlink() -> Result<(), Error> { + let mut target = Vec::new(); + + let link_path = OsString::from("/dev/null"); + + let mut zip_encoder = ZipEncoder::new(&mut target); + let content: Option = None; + zip_encoder + .add_entry( + ZipEntry::new("link", 0, 0o755, FileType::Symlink(link_path)), + content, + ) + .await?; + + zip_encoder.finish().await?; + + check_zip_with_one_file(target, "link", b"/dev/null", 0o120755, true)?; + + Ok(()) +} + +#[test] +async fn test_zip_directory() -> Result<(), Error> { + let mut target = Vec::new(); + + let mut zip_encoder = ZipEncoder::new(&mut target); + let content: Option = None; + zip_encoder + .add_entry( + ZipEntry::new("directory", 0, 0o755, FileType::Directory), + content, + ) + .await?; + + zip_encoder.finish().await?; + + check_zip_with_one_file(target, "directory/", b"", 0o40755, false)?; + + Ok(()) +} -- 2.39.2