Files
android-encrypted-archiver/.planning/phases/03-round-trip-verification/03-01-PLAN.md
2026-02-25 00:23:05 +03:00

8.4 KiB
Raw Blame History

phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
phase plan type wave depends_on files_modified autonomous requirements must_haves
03-round-trip-verification 01 execute 1
src/lib.rs
src/main.rs
Cargo.toml
src/crypto.rs
src/compression.rs
src/format.rs
true
TST-03
truths artifacts key_links
Unit tests pass for crypto module: encrypt/decrypt round-trip, HMAC compute/verify, SHA-256 known value
Unit tests pass for compression module: compress/decompress round-trip, empty data, should_compress heuristic
Unit tests pass for format module: header write/read round-trip, TOC entry write/read round-trip (ASCII + Cyrillic names)
Project compiles as both library crate and binary crate (cargo build succeeds)
path provides contains
src/lib.rs Library crate re-exporting all modules for integration tests pub mod crypto
path provides contains
Cargo.toml Dev-dependencies for test infrastructure tempfile
from to via pattern
src/main.rs src/lib.rs use encrypted_archive:: imports use encrypted_archive::
from to via pattern
src/lib.rs src/crypto.rs pub mod crypto pub mod crypto
Create the library crate structure, add test dependencies, and implement unit tests for every pipeline module (crypto, compression, format serialization).

Purpose: TST-03 requires unit tests for each pipeline stage. The lib.rs creation also unblocks Plan 02 which needs to import library functions from integration tests in tests/.

Output: src/lib.rs with module re-exports, dev-dependencies in Cargo.toml, unit tests in #[cfg(test)] blocks inside crypto.rs, compression.rs, format.rs.

<execution_context> @/home/nick/.claude/get-shit-done/workflows/execute-plan.md @/home/nick/.claude/get-shit-done/templates/summary.md </execution_context>

@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/03-round-trip-verification/03-RESEARCH.md @docs/FORMAT.md @src/main.rs @src/crypto.rs @src/compression.rs @src/format.rs @src/key.rs @Cargo.toml Task 1: Create lib.rs, update main.rs imports, add dev-dependencies src/lib.rs, src/main.rs, Cargo.toml 1. Create `src/lib.rs` that re-exports all modules as public: ```rust pub mod archive; pub mod cli; pub mod compression; pub mod crypto; pub mod format; pub mod key; ```
  1. Update src/main.rs to use the library crate instead of local mod declarations:
  • Remove all mod declarations (archive, cli, compression, crypto, format, key)
  • Replace with use encrypted_archive::cli::{Cli, Commands}; and use encrypted_archive::archive;
  • Keep the use clap::Parser; import
  • The main() function body stays the same
  1. Add dev-dependencies to Cargo.toml:
[dev-dependencies]
tempfile = "3.26"
assert_cmd = "2.1"
hex-literal = "1.1"
predicates = "3.1"

IMPORTANT: Use Context7 to verify tempfile and assert_cmd API before writing code if needed. The research doc already verified versions (tempfile 3.26.0, assert_cmd 2.1.2, hex-literal 1.1.0, predicates 3.1.4).

  1. Verify: cargo build succeeds (both lib and bin targets compile). cd /home/nick/Projects/Rust/encrypted_archive && cargo build 2>&1 No lib.rs compilation errors, main.rs uses encrypted_archive:: imports Project compiles as both library and binary crate. All six modules re-exported via lib.rs. Dev-dependencies declared in Cargo.toml.
Task 2: Add unit tests to crypto.rs, compression.rs, and format.rs src/crypto.rs, src/compression.rs, src/format.rs Add `#[cfg(test)] mod tests { ... }` blocks at the bottom of each module file.

src/crypto.rs -- add these unit tests:

  • test_encrypt_decrypt_roundtrip: Encrypt "Hello, World!" with KEY and a zero IV, decrypt, assert equality.
  • test_encrypt_decrypt_empty: Encrypt empty slice, decrypt, assert empty result. Verifies PKCS7 full-block padding on 0-byte input.
  • test_encrypted_size_formula: Assert encrypt_data(b"Hello", &KEY, &iv).len() == 16 (5 bytes -> ((5/16)+1)*16 = 16). Also test 16 bytes -> 32 (full padding block), and 0 bytes -> 16.
  • test_hmac_compute_verify: Compute HMAC for a fixed IV + ciphertext, then verify_hmac returns true. Also test with wrong expected value returns false.
  • test_sha256_known_value: SHA-256("Hello") must equal 185f8db32271fe25f561a6fc938b2e264306ec304eda518007d1764826381969 (from FORMAT.md Section 12.3). Use hex_literal::hex!() macro for the expected value.
  • test_sha256_empty: SHA-256("") must equal e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.

Import use super::*; and use crate::key::KEY; and use hex_literal::hex; inside the test module.

src/compression.rs -- add these unit tests:

  • test_compress_decompress_roundtrip: Compress "Hello, World! This is test data for compression." -> decompress -> assert equals original.
  • test_compress_decompress_empty: Compress empty slice -> decompress -> assert empty.
  • test_compress_decompress_large: Compress 10000 bytes of pattern data -> decompress -> assert equals original.
  • test_should_compress_text: Assert should_compress("readme.txt", &[]) is true. Also test "data.json".
  • test_should_not_compress_known_extensions: Assert should_compress("app.apk", &[]) is false. Also test "photo.jpg", "archive.zip".
  • test_should_not_compress_excluded: Assert should_compress("special.dat", &["special.dat".into()]) is false.

Import use super::*; inside the test module.

src/format.rs -- add these unit tests:

  • test_header_write_read_roundtrip: Create a Header with typical values (version=1, flags=0x01, file_count=3, toc_offset=HEADER_SIZE, toc_size=330, toc_iv=zeroed, reserved=zeroed). Write to Vec, assert len == HEADER_SIZE. Read back from Cursor, assert all fields match.
  • test_toc_entry_roundtrip_ascii: Create a TocEntry for "hello.txt" with known field values. Write to Vec, assert len == 101 + 9. Read back, assert all fields match including iv/hmac/sha256 byte arrays.
  • test_toc_entry_roundtrip_cyrillic: Create a TocEntry for "тестовый_файл.txt". Write, read back, assert name and all fields match. Verify buf length == 101 + "тестовый_файл.txt".len() (which is 29 bytes for UTF-8 Cyrillic).
  • test_toc_entry_roundtrip_empty_name: Create a TocEntry with name="" (edge case). Write, read back, assert name is empty string.
  • test_header_rejects_bad_magic: Create a buffer with wrong magic bytes, attempt read_header, assert error.
  • test_header_rejects_bad_version: Create a valid-magic buffer but version=2, attempt read_header, assert error.
  • test_entry_size_calculation: Assert entry_size(&entry_for_hello_txt) == 110 and entry_size(&entry_for_data_bin) == 109. Test compute_toc_size on both entries equals 219 (matching FORMAT.md worked example).

Import use super::*; and use std::io::Cursor; inside the test module.

All assertions should use assert_eq! for value comparison (gives diff on failure) or assert! for boolean checks. cd /home/nick/Projects/Rust/encrypted_archive && cargo test 2>&1 All unit tests pass, no compilation errors Unit tests exist and pass for all three pipeline modules: crypto (6 tests), compression (6 tests), format (7 tests). Total: 19 unit tests covering encrypt/decrypt, HMAC, SHA-256, compress/decompress, should_compress, header/TOC serialization round-trips, and error cases.

- `cargo build` succeeds (lib + bin) - `cargo test` passes all unit tests - `src/lib.rs` exists and re-exports all modules - `src/main.rs` uses `use encrypted_archive::` imports (no local `mod` declarations) - Each of crypto.rs, compression.rs, format.rs has a `#[cfg(test)]` module with tests

<success_criteria>

  1. cargo test runs 19+ unit tests, all pass
  2. Project structure supports both cargo run (binary) and use encrypted_archive::module (library imports)
  3. TST-03 is satisfied: unit tests cover compression, encryption, HMAC, SHA-256, format serialization/deserialization </success_criteria>
After completion, create `.planning/phases/03-round-trip-verification/03-01-SUMMARY.md`