From e48edb2aaee343af749c38ad4fedd19f99e8fa8c Mon Sep 17 00:00:00 2001 From: grumbach Date: Thu, 17 Jul 2025 14:06:35 +0900 Subject: [PATCH 1/3] chore: clippy fixes --- examples/basic_encryptor.rs | 24 ++++------- examples/parallel_streaming_decryptor.rs | 31 +++++++------- src/data_map.rs | 8 ++-- src/lib.rs | 22 +++++----- src/python.rs | 36 ++++++++-------- tests/integration_tests.rs | 53 ++++++++++-------------- tests/lib.rs | 18 ++++---- 7 files changed, 89 insertions(+), 103 deletions(-) diff --git a/examples/basic_encryptor.rs b/examples/basic_encryptor.rs index e1b65bec7..693e03922 100644 --- a/examples/basic_encryptor.rs +++ b/examples/basic_encryptor.rs @@ -79,7 +79,7 @@ struct Args { } fn to_hex(ch: u8) -> String { - fmt::format(format_args!("{:02x}", ch)) + fmt::format(format_args!("{ch:02x}")) } fn file_name(name: XorName) -> String { @@ -115,7 +115,7 @@ impl DiskBasedStorage { let mut file = File::create(&path)?; file.write_all(&data[..]) .map(|_| { - println!("Chunk written to {:?}", path); + println!("Chunk written to {path:?}"); }) .map_err(From::from) } @@ -128,7 +128,7 @@ async fn main() { .and_then(|d| d.deserialize()) .unwrap_or_else(|e| e.exit()); if args.flag_help { - println!("{:?}", args) + println!("{args:?}") } let mut chunk_store_dir = env::temp_dir(); @@ -145,7 +145,7 @@ async fn main() { let mut data = Vec::new(); match file.read_to_end(&mut data) { Ok(_) => (), - Err(error) => return println!("{}", error), + Err(error) => return println!("{error}"), } let (data_map, encrypted_chunks) = encrypt(Bytes::from(data)).unwrap(); @@ -163,20 +163,14 @@ async fn main() { Ok(mut file) => { let encoded = serialize(&data_map).unwrap(); match file.write_all(&encoded[..]) { - Ok(_) => println!("Data map written to {:?}", data_map_file), + Ok(_) => println!("Data map written to {data_map_file:?}"), Err(error) => { - println!( - "Failed to write data map to {:?} - {:?}", - data_map_file, error - ); + println!("Failed to write data map to {data_map_file:?} - {error:?}"); } } } Err(error) => { - println!( - "Failed to create data map at {:?} - {:?}", - data_map_file, error - ); + println!("Failed to create data map at {data_map_file:?} - {error:?}"); } } } else { @@ -214,7 +208,7 @@ async fn main() { let content = decrypt(&DataMap::new(keys), encrypted_chunks.as_ref()).unwrap(); match file.write_all(&content[..]) { - Err(error) => println!("File write failed - {:?}", error), + Err(error) => println!("File write failed - {error:?}"), Ok(_) => { println!("File decrypted to {:?}", args.arg_destination.unwrap()) } @@ -228,7 +222,7 @@ async fn main() { } } } else { - println!("Failed to open data map at {:?}", data_map_file); + println!("Failed to open data map at {data_map_file:?}"); } } } diff --git a/examples/parallel_streaming_decryptor.rs b/examples/parallel_streaming_decryptor.rs index 87d728674..a9a07ae02 100644 --- a/examples/parallel_streaming_decryptor.rs +++ b/examples/parallel_streaming_decryptor.rs @@ -26,8 +26,8 @@ fn validate_paths(args: &Args) -> Result<()> { // Check data map file exists and is readable if !Path::new(&args.data_map).exists() { return Err(Error::Generic(format!( - "Data map file does not exist: {}", - args.data_map + "Data map file does not exist: {file}", + file = args.data_map ))); } @@ -35,14 +35,14 @@ fn validate_paths(args: &Args) -> Result<()> { let chunks_dir = Path::new(&args.chunks_dir); if !chunks_dir.exists() { return Err(Error::Generic(format!( - "Chunks directory does not exist: {}", - args.chunks_dir + "Chunks directory does not exist: {dir}", + dir = args.chunks_dir ))); } if !chunks_dir.is_dir() { return Err(Error::Generic(format!( - "Chunks path is not a directory: {}", - args.chunks_dir + "Chunks path is not a directory: {dir}", + dir = args.chunks_dir ))); } @@ -51,8 +51,8 @@ fn validate_paths(args: &Args) -> Result<()> { if let Some(parent) = output_path.parent() { if !parent.exists() { return Err(Error::Generic(format!( - "Output directory does not exist: {}", - parent.display() + "Output directory does not exist: {dir}", + dir = parent.display() ))); } // Try to verify write permissions @@ -62,8 +62,8 @@ fn validate_paths(args: &Args) -> Result<()> { .unwrap_or(true) { return Err(Error::Generic(format!( - "Output directory is not writable: {}", - parent.display() + "Output directory is not writable: {dir}", + dir = parent.display() ))); } } @@ -89,7 +89,7 @@ fn main() -> Result<()> { let mut chunk_data = Vec::new(); File::open(&chunk_path) .and_then(|mut file| file.read_to_end(&mut chunk_data)) - .map_err(|e| Error::Generic(format!("Failed to read chunk: {}", e)))?; + .map_err(|e| Error::Generic(format!("Failed to read chunk: {e}")))?; Ok(Bytes::from(chunk_data)) }) .collect() @@ -98,7 +98,10 @@ fn main() -> Result<()> { // Use the streaming decryption function streaming_decrypt_from_storage(&data_map, Path::new(&args.output), get_chunk_parallel)?; - println!("Successfully decrypted file to: {}", args.output); + println!( + "Successfully decrypted file to: {output}", + output = args.output + ); Ok(()) } @@ -106,9 +109,9 @@ fn main() -> Result<()> { // Helper function to load data map from a file fn load_data_map(path: &str) -> Result { let mut file = - File::open(path).map_err(|e| Error::Generic(format!("Failed to open data map: {}", e)))?; + File::open(path).map_err(|e| Error::Generic(format!("Failed to open data map: {e}")))?; let mut data = Vec::new(); file.read_to_end(&mut data) - .map_err(|e| Error::Generic(format!("Failed to read data map: {}", e)))?; + .map_err(|e| Error::Generic(format!("Failed to read data map: {e}")))?; deserialize(&data) } diff --git a/src/data_map.rs b/src/data_map.rs index bcb5f3a66..8f4625cde 100644 --- a/src/data_map.rs +++ b/src/data_map.rs @@ -82,14 +82,14 @@ impl Debug for DataMap { fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result { writeln!(formatter, "DataMap:")?; if let Some(child) = self.child { - writeln!(formatter, " child: {}", child)?; + writeln!(formatter, " child: {child}")?; } let len = self.chunk_identifiers.len(); for (index, chunk) in self.chunk_identifiers.iter().enumerate() { if index + 1 == len { - write!(formatter, " {:?}", chunk)? + write!(formatter, " {chunk:?}")? } else { - writeln!(formatter, " {:?}", chunk)? + writeln!(formatter, " {chunk:?}")? } } Ok(()) @@ -124,7 +124,7 @@ fn debug_bytes>(input: V) -> String { if input_ref.len() <= 6 { let mut ret = String::new(); for byte in input_ref.iter() { - write!(ret, "{:02x}", byte).unwrap_or(()); + write!(ret, "{byte:02x}").unwrap_or(()); } return ret; } diff --git a/src/lib.rs b/src/lib.rs index ba9b8e068..7314bcf2f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -173,8 +173,7 @@ pub fn encrypt(bytes: Bytes) -> Result<(DataMap, Vec)> { let file_size = bytes.len(); if file_size < MIN_ENCRYPTABLE_BYTES { return Err(Error::Generic(format!( - "Too small for self-encryption! Required size at least {}", - MIN_ENCRYPTABLE_BYTES + "Too small for self-encryption! Required size at least {MIN_ENCRYPTABLE_BYTES}", ))); } @@ -495,7 +494,7 @@ pub fn decrypt(data_map: &DataMap, chunks: &[EncryptedChunk]) -> Result { chunk_map .get(&hash) .map(|chunk| chunk.content.clone()) - .ok_or_else(|| Error::Generic(format!("Chunk not found for hash: {:?}", hash))) + .ok_or_else(|| Error::Generic(format!("Chunk not found for hash: {hash:?}"))) }; // Get the root map if we're dealing with a child map @@ -588,8 +587,7 @@ where if file_size < MIN_ENCRYPTABLE_BYTES { return Err(Error::Generic(format!( - "Too small for self-encryption! Required size at least {}", - MIN_ENCRYPTABLE_BYTES + "Too small for self-encryption! Required size at least {MIN_ENCRYPTABLE_BYTES}", ))); } @@ -720,7 +718,10 @@ where .iter() .map(|info| { let content = chunk_cache.get(&info.dst_hash).ok_or_else(|| { - Error::Generic(format!("Chunk not found for hash: {:?}", info.dst_hash)) + Error::Generic(format!( + "Chunk not found for hash: {hash:?}", + hash = info.dst_hash + )) })?; Ok(EncryptedChunk { content: content.clone(), @@ -751,7 +752,7 @@ where /// /// * `Result>` - The serialized bytes or an error pub fn serialize(data: &T) -> Result> { - bincode::serialize(data).map_err(|e| Error::Generic(format!("Serialization error: {}", e))) + bincode::serialize(data).map_err(|e| Error::Generic(format!("Serialization error: {e}"))) } /// Deserializes bytes into a data structure using bincode. @@ -764,7 +765,7 @@ pub fn serialize(data: &T) -> Result> { /// /// * `Result` - The deserialized data structure or an error pub fn deserialize(bytes: &[u8]) -> Result { - bincode::deserialize(bytes).map_err(|e| Error::Generic(format!("Deserialization error: {}", e))) + bincode::deserialize(bytes).map_err(|e| Error::Generic(format!("Deserialization error: {e}"))) } /// Verifies and deserializes a chunk by checking its content hash matches the provided name. @@ -790,8 +791,7 @@ pub fn verify_chunk(name: XorName, bytes: &[u8]) -> Result { // Verify the hash matches if calculated_hash != name { return Err(Error::Generic(format!( - "Chunk content hash mismatch. Expected: {:?}, Got: {:?}", - name, calculated_hash + "Chunk content hash mismatch. Expected: {name:?}, Got: {calculated_hash:?}" ))); } @@ -900,7 +900,7 @@ mod tests { println!("\nFinal Data Map Info:"); println!("Number of chunks: {}", shrunk_map.len()); - println!("Original file size: {}", file_size); + println!("Original file size: {file_size}"); println!("Is child: {}", shrunk_map.is_child()); for (i, info) in shrunk_map.infos().iter().enumerate() { diff --git a/src/python.rs b/src/python.rs index 2b0ef2ae4..859df4b2d 100644 --- a/src/python.rs +++ b/src/python.rs @@ -136,7 +136,7 @@ impl PyDataMap { #[staticmethod] pub fn from_json(json_str: &str) -> PyResult { let inner = serde_json::from_str(json_str) - .map_err(|e| pyo3::exceptions::PyValueError::new_err(format!("Invalid JSON: {}", e)))?; + .map_err(|e| pyo3::exceptions::PyValueError::new_err(format!("Invalid JSON: {e}")))?; Ok(Self { inner }) } @@ -146,7 +146,7 @@ impl PyDataMap { /// str: A JSON string representation of the DataMap. pub fn to_json(&self) -> PyResult { serde_json::to_string(&self.inner).map_err(|e| { - pyo3::exceptions::PyValueError::new_err(format!("Failed to serialize: {}", e)) + pyo3::exceptions::PyValueError::new_err(format!("Failed to serialize: {e}")) }) } @@ -274,9 +274,8 @@ impl PyEncryptedChunk { #[pyfunction] pub fn encrypt(data: &[u8]) -> PyResult<(PyDataMap, Vec)> { let bytes = Bytes::copy_from_slice(data); - let (data_map, chunks) = crate::encrypt(bytes).map_err(|e| { - pyo3::exceptions::PyValueError::new_err(format!("Encryption failed: {}", e)) - })?; + let (data_map, chunks) = crate::encrypt(bytes) + .map_err(|e| pyo3::exceptions::PyValueError::new_err(format!("Encryption failed: {e}")))?; let py_chunks = chunks .into_iter() .map(|chunk| PyEncryptedChunk { inner: chunk }) @@ -307,9 +306,8 @@ pub fn decrypt( .into_iter() .map(|chunk| chunk.inner) .collect::>(); - let bytes = crate::decrypt(&data_map.inner, &inner_chunks).map_err(|e| { - pyo3::exceptions::PyValueError::new_err(format!("Decryption failed: {}", e)) - })?; + let bytes = crate::decrypt(&data_map.inner, &inner_chunks) + .map_err(|e| pyo3::exceptions::PyValueError::new_err(format!("Decryption failed: {e}")))?; Ok(bytes.to_vec().into()) } @@ -335,7 +333,7 @@ pub fn encrypt_from_file(input_file: &str, output_dir: &str) -> PyResult<(PyData let input_path = Path::new(input_file); let output_path = Path::new(output_dir); let (data_map, chunk_names) = rust_encrypt_from_file(input_path, output_path).map_err(|e| { - pyo3::exceptions::PyOSError::new_err(format!("Failed to encrypt file: {}", e)) + pyo3::exceptions::PyOSError::new_err(format!("Failed to encrypt file: {e}")) })?; let chunk_names = chunk_names.iter().map(|name| hex::encode(name.0)).collect(); Ok((PyDataMap { inner: data_map }, chunk_names)) @@ -365,15 +363,15 @@ pub fn decrypt_from_storage( let name_str = hex::encode(name.0); let chunk = get_chunk .call1((name_str,)) - .map_err(|e| crate::Error::Python(format!("Failed to call get_chunk: {}", e)))?; + .map_err(|e| crate::Error::Python(format!("Failed to call get_chunk: {e}")))?; let bytes = chunk .downcast::() - .map_err(|e| crate::Error::Python(format!("get_chunk must return bytes: {}", e)))?; + .map_err(|e| crate::Error::Python(format!("get_chunk must return bytes: {e}")))?; Ok(Bytes::copy_from_slice(bytes.as_bytes())) }; rust_decrypt_from_storage(&data_map.inner, output_path, get_chunk_wrapper) - .map_err(|e| pyo3::exceptions::PyOSError::new_err(format!("Decryption failed: {}", e))) + .map_err(|e| pyo3::exceptions::PyOSError::new_err(format!("Decryption failed: {e}"))) } /// Decrypt data using streaming for better performance with large files. @@ -400,24 +398,24 @@ pub fn streaming_decrypt_from_storage( let name_strs: Vec = names.iter().map(|x| hex::encode(x.0)).collect(); let chunks = get_chunks .call1((name_strs,)) - .map_err(|e| crate::Error::Python(format!("Failed to call get_chunks: {}", e)))?; + .map_err(|e| crate::Error::Python(format!("Failed to call get_chunks: {e}")))?; let chunks = chunks .try_iter() - .map_err(|e| crate::Error::Python(format!("get_chunks must return a list: {}", e)))?; + .map_err(|e| crate::Error::Python(format!("get_chunks must return a list: {e}")))?; let mut result = Vec::new(); for chunk in chunks { let chunk = chunk - .map_err(|e| crate::Error::Python(format!("Failed to iterate chunks: {}", e)))?; - let bytes = chunk.downcast::().map_err(|e| { - crate::Error::Python(format!("get_chunks must return bytes: {}", e)) - })?; + .map_err(|e| crate::Error::Python(format!("Failed to iterate chunks: {e}")))?; + let bytes = chunk + .downcast::() + .map_err(|e| crate::Error::Python(format!("get_chunks must return bytes: {e}")))?; result.push(Bytes::copy_from_slice(bytes.as_bytes())); } Ok(result) }; rust_streaming_decrypt_from_storage(&data_map.inner, output_path, get_chunks_wrapper).map_err( - |e| pyo3::exceptions::PyOSError::new_err(format!("Streaming decryption failed: {}", e)), + |e| pyo3::exceptions::PyOSError::new_err(format!("Streaming decryption failed: {e}")), ) } diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index 609ce55ce..ed1a6977d 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -71,10 +71,10 @@ impl StorageBackend { Box::new(move |hash| { let path = base_path.join(hex::encode(hash)); let mut file = File::open(&path) - .map_err(|e| Error::Generic(format!("Failed to open chunk file: {}", e)))?; + .map_err(|e| Error::Generic(format!("Failed to open chunk file: {e}")))?; let mut data = Vec::new(); file.read_to_end(&mut data) - .map_err(|e| Error::Generic(format!("Failed to read chunk data: {}", e)))?; + .map_err(|e| Error::Generic(format!("Failed to read chunk data: {e}")))?; Ok(Bytes::from(data)) }) } @@ -98,7 +98,7 @@ impl StorageBackend { } fn debug_storage_state(&self, prefix: &str) -> Result<()> { - println!("\n=== {} ===", prefix); + println!("\n=== {prefix} ==="); if let Ok(guard) = self.memory.lock() { println!("Memory storage contains {} chunks", guard.len()); for (hash, data) in guard.iter() { @@ -138,7 +138,7 @@ fn test_cross_backend_encryption_decryption() -> Result<()> { let temp_dir = TempDir::new()?; for (name, use_memory_store, _use_memory_retrieve) in &[("memory-to-memory", true, true)] { - println!("\nRunning test case: {}", name); + println!("\nRunning test case: {name}"); let input_path = temp_dir.path().join("input.dat"); let mut input_file = File::create(&input_path)?; @@ -242,12 +242,8 @@ fn test_concurrent_backend_access() -> Result<()> { let count = processed.fetch_add(1, Ordering::SeqCst); // Setup paths with unique identifiers - let input_path = temp_dir - .path() - .join(format!("input_{}_{}.dat", count, size)); - let output_path = temp_dir - .path() - .join(format!("output_{}_{}.dat", count, size)); + let input_path = temp_dir.path().join(format!("input_{count}_{size}.dat")); + let output_path = temp_dir.path().join(format!("output_{count}_{size}.dat")); // Write test data File::create(&input_path)?.write_all(&data)?; @@ -320,7 +316,7 @@ fn test_cross_platform_compatibility() -> Result<()> { for size in &[3073, 1024 * 1024] { // Start with smaller subset for testing - println!("Testing size: {}", size); + println!("Testing size: {size}"); // Create deterministic data let mut content = vec![0u8; *size]; @@ -329,7 +325,7 @@ fn test_cross_platform_compatibility() -> Result<()> { } let original_data = Bytes::from(content); - let input_path = temp_dir.path().join(format!("input_{}.dat", size)); + let input_path = temp_dir.path().join(format!("input_{size}.dat")); let mut input_file = File::create(&input_path)?; input_file.write_all(&original_data)?; @@ -372,7 +368,7 @@ fn test_platform_specific_sizes() -> Result<()> { ]; for (name, size) in test_cases { - println!("Testing size: {} ({} bytes)", name, size); + println!("Testing size: {name} ({size} bytes)"); let original_data = random_bytes(size); @@ -404,9 +400,7 @@ fn test_platform_specific_sizes() -> Result<()> { assert_eq!( original_data.as_ref(), decrypted_bytes.as_ref(), - "Data mismatch for {} (size: {})", - name, - size + "Data mismatch for {name} (size: {size})" ); } @@ -431,7 +425,7 @@ fn test_encrypt_from_file_stores_all_chunks() -> Result<()> { // Now encrypt from file let (data_map, chunk_names) = encrypt_from_file(&input_path, storage.disk_dir.path())?; - println!("Expected chunks: {}", expected_chunk_count); + println!("Expected chunks: {expected_chunk_count}"); println!("Got chunk names: {}", chunk_names.len()); // Verify we got all chunks @@ -472,7 +466,7 @@ fn test_comprehensive_encryption_decryption() -> Result<()> { ]; for (size_name, size) in test_cases { - println!("\n=== Testing {} file ===", size_name); + println!("\n=== Testing {size_name} file ==="); let original_data = random_bytes(size); // 1. In-memory encryption (encrypt) @@ -483,7 +477,7 @@ fn test_comprehensive_encryption_decryption() -> Result<()> { // 2. File-based encryption (encrypt_from_file) println!("\n2. Testing file-based encryption (encrypt_from_file):"); - let input_path = temp_dir.path().join(format!("input_{}.dat", size_name)); + let input_path = temp_dir.path().join(format!("input_{size_name}.dat")); File::create(&input_path)?.write_all(&original_data)?; let (data_map2, chunk_names) = encrypt_from_file(&input_path, storage.disk_dir.path())?; println!("- Generated {} chunks", chunk_names.len()); @@ -510,7 +504,7 @@ fn test_comprehensive_encryption_decryption() -> Result<()> { let chunk_path = storage.disk_dir.path().join(hex::encode(hash)); File::create(&chunk_path)?.write_all(&chunk.content)?; } - let output_path1 = temp_dir.path().join(format!("output1_{}.dat", size_name)); + let output_path1 = temp_dir.path().join(format!("output1_{size_name}.dat")); let mut retrieve_fn = storage.retrieve_from_disk(); decrypt_from_storage(&data_map1, &output_path1, &mut retrieve_fn)?; @@ -527,7 +521,7 @@ fn test_comprehensive_encryption_decryption() -> Result<()> { println!("\nA.3 Testing streaming_decrypt_from_storage() with encrypt() result:"); let output_path1_stream = temp_dir .path() - .join(format!("output1_stream_{}.dat", size_name)); + .join(format!("output1_stream_{size_name}.dat")); // Create parallel chunk retrieval function let chunk_dir = storage.disk_dir.path().to_owned(); @@ -539,7 +533,7 @@ fn test_comprehensive_encryption_decryption() -> Result<()> { let mut chunk_data = Vec::new(); File::open(&chunk_path) .and_then(|mut file| file.read_to_end(&mut chunk_data)) - .map_err(|e| Error::Generic(format!("Failed to read chunk: {}", e)))?; + .map_err(|e| Error::Generic(format!("Failed to read chunk: {e}")))?; Ok(Bytes::from(chunk_data)) }) .collect() @@ -577,7 +571,7 @@ fn test_comprehensive_encryption_decryption() -> Result<()> { // E. Test decrypt_from_storage() with file-based encryption result println!("\nB.2 Testing decrypt_from_storage() with encrypt_from_file() result:"); - let output_path2 = temp_dir.path().join(format!("output2_{}.dat", size_name)); + let output_path2 = temp_dir.path().join(format!("output2_{size_name}.dat")); let mut retrieve_fn = storage.retrieve_from_disk(); decrypt_from_storage(&data_map2, &output_path2, &mut retrieve_fn)?; @@ -594,7 +588,7 @@ fn test_comprehensive_encryption_decryption() -> Result<()> { println!("\nB.3 Testing streaming_decrypt_from_storage() with encrypt_from_file() result:"); let output_path2_stream = temp_dir .path() - .join(format!("output2_stream_{}.dat", size_name)); + .join(format!("output2_stream_{size_name}.dat")); streaming_decrypt_from_storage(&data_map2, &output_path2_stream, get_chunk_parallel)?; let mut decrypted = Vec::new(); @@ -645,14 +639,13 @@ fn test_comprehensive_encryption_decryption() -> Result<()> { File::open(path2)?.read_to_end(&mut content2)?; assert_eq!( content1, content2, - "Output files don't match: {:?} vs {:?}", - path1, path2 + "Output files don't match: {path1:?} vs {path2:?}" ); } } println!("✓ All output files match"); - println!("\n{} test completed successfully", size_name); + println!("\n{size_name} test completed successfully"); } Ok(()) @@ -682,7 +675,7 @@ fn test_streaming_decrypt_with_parallel_retrieval() -> Result<()> { let mut chunk_data = Vec::new(); File::open(&chunk_path) .and_then(|mut file| file.read_to_end(&mut chunk_data)) - .map_err(|e| Error::Generic(format!("Failed to read chunk: {}", e)))?; + .map_err(|e| Error::Generic(format!("Failed to read chunk: {e}")))?; Ok(Bytes::from(chunk_data)) }) .collect() @@ -757,8 +750,8 @@ fn test_chunk_verification() -> Result<()> { File::open(&chunk_path)?.read_to_end(&mut chunk_content)?; match verify_chunk(info.dst_hash, &chunk_content) { - Ok(_) => println!("✓ Chunk {} verified successfully", i), - Err(e) => println!("✗ Chunk {} verification failed: {}", i, e), + Ok(_) => println!("✓ Chunk {i} verified successfully"), + Err(e) => println!("✗ Chunk {i} verification failed: {e}"), } } diff --git a/tests/lib.rs b/tests/lib.rs index 7d065798c..08d52e50c 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -80,9 +80,9 @@ async fn cross_platform_check() -> Result<()> { ); for (i, info) in data_map.infos().iter().enumerate() { - println!("ChunkInfo {}: src_hash = {:02x?}", i, info.src_hash.0); - println!("ChunkInfo {}: dst_hash = {:02x?}", i, info.dst_hash.0); - println!("ChunkInfo {}: size = {}", i, info.src_size); + println!("ChunkInfo {i}: src_hash = {:02x?}", info.src_hash.0); + println!("ChunkInfo {i}: dst_hash = {:02x?}", info.dst_hash.0); + println!("ChunkInfo {i}: size = {}", info.src_size); } // Store these values as the new reference once we're happy with the implementation @@ -92,15 +92,13 @@ async fn cross_platform_check() -> Result<()> { for (i, (expected, got)) in ref_data_map.iter().zip(data_map.infos()).enumerate() { assert_eq!( expected.src_hash, got.src_hash, - "Chunk {} src_hash mismatch", - i + "Chunk {i} src_hash mismatch" ); assert_eq!( expected.dst_hash, got.dst_hash, - "Chunk {} dst_hash mismatch", - i + "Chunk {i} dst_hash mismatch" ); - assert_eq!(expected.src_size, got.src_size, "Chunk {} size mismatch", i); + assert_eq!(expected.src_size, got.src_size, "Chunk {i} size mismatch"); } Ok(()) @@ -163,12 +161,12 @@ fn test_data_map_debug() { // Test Debug output without child let data_map = DataMap::new(chunk_infos.clone()); - let debug_str = format!("{:?}", data_map); + let debug_str = format!("{data_map:?}"); assert!(!debug_str.contains("child:")); // Test Debug output with child let data_map = DataMap::with_child(chunk_infos, 42); - let debug_str = format!("{:?}", data_map); + let debug_str = format!("{data_map:?}"); assert!(debug_str.contains("child: 42")); } From 19b1803a422c093f7c3d34562d11f42307020af9 Mon Sep 17 00:00:00 2001 From: grumbach Date: Thu, 17 Jul 2025 14:26:52 +0900 Subject: [PATCH 2/3] feat: test that proves stream output is different from mem encryption --- src/chunk.rs | 2 +- tests/stream_vs_mem.rs | 146 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 tests/stream_vs_mem.rs diff --git a/src/chunk.rs b/src/chunk.rs index eea336cf7..59b13960c 100644 --- a/src/chunk.rs +++ b/src/chunk.rs @@ -9,7 +9,7 @@ use bytes::Bytes; /// The actual encrypted content of the chunk -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq, Eq)] pub struct EncryptedChunk { /// The encrypted content of the chunk pub content: Bytes, diff --git a/tests/stream_vs_mem.rs b/tests/stream_vs_mem.rs new file mode 100644 index 000000000..220a59551 --- /dev/null +++ b/tests/stream_vs_mem.rs @@ -0,0 +1,146 @@ +use self_encryption::{encrypt, test_helpers::random_bytes, StreamSelfEncryptor}; +use std::fs; +use tempfile::tempdir; + +/// Test that confirms chunks obtained through StreamSelfEncryptor are the same as those obtained through the encrypt function. +#[test] +fn test_stream_vs_memory_encryption_consistency() { + // Create test data of sufficient size to generate multiple chunks + let file_size = 5 * 1024 * 1024; // 5MB to ensure multiple chunks + let test_data = random_bytes(file_size); + + // Create temporary directory for test files + let temp_dir = tempdir().expect("Failed to create temp directory"); + let input_file_path = temp_dir.path().join("input.dat"); + let chunk_dir = temp_dir.path().join("chunks"); + + // Write test data to file + fs::write(&input_file_path, &test_data).expect("Failed to write test data"); + + // Method 1: Use the encrypt function (memory-based) + let (memory_data_map, memory_chunks) = + encrypt(test_data.clone()).expect("Memory encryption failed"); + + // Method 2: Use StreamSelfEncryptor (stream-based) + let mut stream_encryptor = + StreamSelfEncryptor::encrypt_from_file(input_file_path.clone(), Some(chunk_dir.clone())) + .expect("Failed to create stream encryptor"); + + let mut stream_chunks = Vec::new(); + let stream_data_map = loop { + let (chunk_opt, map_opt) = stream_encryptor + .next_encryption() + .expect("Stream encryption failed"); + + if let Some(chunk) = chunk_opt { + stream_chunks.push(chunk); + } + + if let Some(map) = map_opt { + break map; + } + }; + + // Verify both methods produced the same amount of chunks + assert_eq!( + memory_chunks.len(), + stream_chunks.len(), + "Memory and stream encryption should produce the same number of chunks" + ); + + // Verify both methods produced the same chunks + assert_eq!( + memory_chunks, stream_chunks, + "Memory and stream encryption should produce the same chunks" + ); + + // Verify data maps are identical + assert_eq!( + memory_data_map, stream_data_map, + "Data maps should be identical" + ); +} + +/// Test with different file sizes to ensure consistency across various scenarios +#[test] +fn test_stream_vs_memory_encryption_different_sizes() { + let test_sizes = vec![ + 3 * 1024 * 1024, // 3MB - minimum size for multiple chunks + 10 * 1024 * 1024, // 10MB - medium size + 50 * 1024 * 1024, // 50MB - large size + ]; + + for file_size in test_sizes { + let test_data = random_bytes(file_size); + + // Create temporary directory for test files + let temp_dir = tempdir().expect("Failed to create temp directory"); + let input_file_path = temp_dir.path().join("input.dat"); + let chunk_dir = temp_dir.path().join("chunks"); + + // Write test data to file + fs::write(&input_file_path, &test_data).expect("Failed to write test data"); + + // Memory-based encryption + let (memory_data_map, memory_chunks) = + encrypt(test_data.clone()).expect("Memory encryption failed"); + + // Stream-based encryption + let mut stream_encryptor = StreamSelfEncryptor::encrypt_from_file( + input_file_path.clone(), + Some(chunk_dir.clone()), + ) + .expect("Failed to create stream encryptor"); + + let mut stream_chunks = Vec::new(); + let stream_data_map = loop { + let (chunk_opt, map_opt) = stream_encryptor + .next_encryption() + .expect("Stream encryption failed"); + + if let Some(chunk) = chunk_opt { + stream_chunks.push(chunk); + } + + if let Some(map) = map_opt { + break map; + } + }; + + // Verify chunk counts match + assert_eq!( + memory_chunks.len(), + stream_chunks.len(), + "Chunk counts should match for file size {file_size}" + ); + + // Verify chunk values match + assert_eq!( + memory_chunks, stream_chunks, + "Chunk should match for file size {file_size}" + ); + + // Verify data map sizes match + assert_eq!( + memory_data_map, stream_data_map, + "Data map should be identical for file size {file_size}" + ); + + // Verify decrypted data matches + let memory_decrypted = self_encryption::decrypt(&memory_data_map, &memory_chunks) + .expect("Failed to decrypt memory-encrypted data"); + + let stream_decrypted = self_encryption::decrypt(&stream_data_map, &stream_chunks) + .expect("Failed to decrypt stream-encrypted data"); + + assert_eq!( + memory_decrypted, stream_decrypted, + "Decrypted data should be identical for file size {file_size}" + ); + + assert_eq!( + test_data, memory_decrypted, + "Decrypted data should match original for file size {file_size}" + ); + } +} From f6f2b5201a1985973c46a694a666922dc376302f Mon Sep 17 00:00:00 2001 From: grumbach Date: Thu, 17 Jul 2025 15:12:36 +0900 Subject: [PATCH 3/3] feat: add test that proves the functor approach doesnt match either --- tests/functor_vs_mem.rs | 178 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 tests/functor_vs_mem.rs diff --git a/tests/functor_vs_mem.rs b/tests/functor_vs_mem.rs new file mode 100644 index 000000000..754c17bc3 --- /dev/null +++ b/tests/functor_vs_mem.rs @@ -0,0 +1,178 @@ +use self_encryption::{encrypt, streaming_encrypt_from_file, test_helpers::random_bytes}; +use std::fs; +use tempfile::tempdir; + +/// Test that confirms chunks obtained through streaming_encrypt_from_file are the same as those obtained through the encrypt function. +#[test] +fn test_streaming_encrypt_vs_memory_encryption_consistency() { + // Create test data of sufficient size to generate multiple chunks + let file_size = 5 * 1024 * 1024; // 5MB to ensure multiple chunks + let test_data = random_bytes(file_size); + + // Create temporary directory for test files + let temp_dir = tempdir().expect("Failed to create temp directory"); + let input_file_path = temp_dir.path().join("input.dat"); + + // Write test data to file + fs::write(&input_file_path, &test_data).expect("Failed to write test data"); + + // Method 1: Use the encrypt function (memory-based) + let (memory_data_map, memory_chunks) = + encrypt(test_data.clone()).expect("Memory encryption failed"); + + // Method 2: Use streaming_encrypt_from_file (streaming-based) + let mut streaming_chunks = Vec::new(); + let streaming_data_map = streaming_encrypt_from_file(&input_file_path, |_, content| { + // Store chunk in memory for comparison + streaming_chunks.push(self_encryption::EncryptedChunk { content }); + Ok(()) + }) + .expect("Streaming encryption failed"); + + // Verify both methods produced the same amount of chunks + assert_eq!( + memory_chunks.len(), + streaming_chunks.len(), + "Memory and streaming encryption should produce the same number of chunks" + ); + + // Verify both methods produced the same chunks + assert_eq!( + memory_chunks, streaming_chunks, + "Memory and streaming encryption should produce the same chunks" + ); + + // Verify data maps are identical + assert_eq!( + memory_data_map, streaming_data_map, + "Data maps should be identical" + ); +} + +/// Test with different file sizes to ensure consistency across various scenarios +#[test] +fn test_streaming_encrypt_vs_memory_encryption_different_sizes() { + let test_sizes = vec![ + 3 * 1024 * 1024, // 3MB - minimum size for multiple chunks + 10 * 1024 * 1024, // 10MB - medium size + 50 * 1024 * 1024, // 50MB - large size + ]; + + for file_size in test_sizes { + let test_data = random_bytes(file_size); + + // Create temporary directory for test files + let temp_dir = tempdir().expect("Failed to create temp directory"); + let input_file_path = temp_dir.path().join("input.dat"); + + // Write test data to file + fs::write(&input_file_path, &test_data).expect("Failed to write test data"); + + // Memory-based encryption + let (memory_data_map, memory_chunks) = + encrypt(test_data.clone()).expect("Memory encryption failed"); + + // Streaming-based encryption + let mut streaming_chunks = Vec::new(); + let streaming_data_map = streaming_encrypt_from_file(&input_file_path, |_hash, content| { + // Store chunk in memory for comparison + streaming_chunks.push(self_encryption::EncryptedChunk { content }); + Ok(()) + }) + .expect("Streaming encryption failed"); + + // Verify chunk counts match + assert_eq!( + memory_chunks.len(), + streaming_chunks.len(), + "Chunk counts should match for file size {file_size}" + ); + + // Verify chunk values match + assert_eq!( + memory_chunks, streaming_chunks, + "Chunks should match for file size {file_size}" + ); + + assert_eq!( + memory_data_map, streaming_data_map, + "Data map should have identical hashes for file size {file_size}" + ); + + // Verify decrypted data matches + let memory_decrypted = self_encryption::decrypt(&memory_data_map, &memory_chunks) + .expect("Failed to decrypt memory-encrypted data"); + + let streaming_decrypted = self_encryption::decrypt(&streaming_data_map, &streaming_chunks) + .expect("Failed to decrypt streaming-encrypted data"); + + assert_eq!( + memory_decrypted, streaming_decrypted, + "Decrypted data should be identical for file size {file_size}" + ); + + assert_eq!( + test_data, memory_decrypted, + "Decrypted data should match original for file size {file_size}" + ); + } +} + +/// Test that verifies the streaming encryption works with actual file storage +#[test] +fn test_streaming_encrypt_with_file_storage() { + let file_size = 5 * 1024 * 1024; // 5MB + let test_data = random_bytes(file_size); + + // Create temporary directory for test files + let temp_dir = tempdir().expect("Failed to create temp directory"); + let input_file_path = temp_dir.path().join("input.dat"); + let chunk_dir = temp_dir.path().join("chunks"); + + // Create chunk directory + fs::create_dir_all(&chunk_dir).expect("Failed to create chunk directory"); + + // Write test data to file + fs::write(&input_file_path, &test_data).expect("Failed to write test data"); + + // Memory-based encryption + let (memory_data_map, memory_chunks) = + encrypt(test_data.clone()).expect("Memory encryption failed"); + + // Streaming-based encryption with file storage + let mut streaming_chunks = Vec::new(); + let streaming_data_map = streaming_encrypt_from_file(&input_file_path, |hash, content| { + // Store chunk to file + let chunk_path = chunk_dir.join(hex::encode(hash)); + fs::write(&chunk_path, &content).expect("Failed to write chunk to file"); + + // Also store in memory for comparison + streaming_chunks.push(self_encryption::EncryptedChunk { content }); + Ok(()) + }) + .expect("Streaming encryption failed"); + + // Verify chunks match + assert_eq!( + memory_chunks, streaming_chunks, + "Memory and streaming encryption should produce the same chunks" + ); + + // Verify data maps are identical + assert_eq!( + memory_data_map, streaming_data_map, + "Data maps should have identical hashes" + ); + + // Verify that chunks were actually written to disk + for chunk in &streaming_chunks { + let chunk_hash = self_encryption::XorName::from_content(&chunk.content); + let chunk_path = chunk_dir.join(hex::encode(chunk_hash)); + assert!( + chunk_path.exists(), + "Chunk file should exist on disk: {:?}", + chunk_path + ); + } +} +