8.4 KiB
phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
| phase | plan | type | wave | depends_on | files_modified | autonomous | requirements | must_haves | ||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 05-shell-decoder | 02 | execute | 2 |
|
|
true |
|
|
Purpose: Prove the shell decoder correctly implements the archive format by testing against Rust-created archives (same pattern as kotlin/test_decoder.sh).
Output: shell/test_decoder.sh -- a test script that creates archives with the Rust CLI, decodes with decode.sh, and verifies byte-identical output via SHA-256 comparison.
<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/05-shell-decoder/05-01-SUMMARY.md @kotlin/test_decoder.sh @shell/decode.sh Task 1: Create shell/test_decoder.sh cross-validation test script shell/test_decoder.sh Create `shell/test_decoder.sh` modeled after `kotlin/test_decoder.sh` but adapted for the shell decoder. This script uses bash (it runs on the development machine, not the target device) but invokes `decode.sh` with `sh` to ensure POSIX compatibility.Script structure (follow kotlin/test_decoder.sh pattern):
-
Header:
#!/usr/bin/env bashset -euo pipefail- Comment: Cross-validation test script for Shell decoder
-
Variables and helpers (copy pattern from kotlin/test_decoder.sh):
- SCRIPT_DIR, PROJECT_DIR, TMPDIR, PASS_COUNT, FAIL_COUNT, TOTAL_COUNT
- Colors (GREEN, RED, YELLOW, BOLD, NC) with terminal detection
cleanup()function with trappass(),fail(),sha256_of(),verify_file()helper functions (identical to kotlin version)
-
Prerequisites check:
- Check for
cargo(to build Rust archiver) - Check for
openssl(needed by decode.sh) - Check for
sh(always available, but verify) - Print versions: cargo, openssl, sh
- Check for
-
Build Rust archiver:
(cd "$PROJECT_DIR" && cargo build --release -q) ARCHIVER="$PROJECT_DIR/target/release/encrypted_archive" -
Decoder path:
DECODER="$SCRIPT_DIR/decode.sh"Verify it exists and is executable.
-
Test cases (6 tests matching kotlin/test_decoder.sh):
Test 1: Single text file
- Create
hello.txtwith content "Hello, World!" (no newline:echo -n) - Pack with Rust archiver
- Decode with:
sh "$DECODER" "$TMPDIR/test1.archive" "$TMPDIR/output1/" - verify_file hello.txt
Test 2: Multiple files (text + binary)
- Create text.txt with 3 lines
- Create binary.bin with 10 KB random data (
dd if=/dev/urandom bs=1024 count=10) - Pack both files
- Decode with sh
- verify_file text.txt, binary.bin
Test 3: No-compress mode
- Create fake.dat with 2.5 KB random data
- Pack with
--no-compress "fake.dat" - Decode with sh
- verify_file fake.dat
Test 4: Empty file
- Create empty.txt with
touch - Pack with Rust archiver
- Decode with sh
- Verify output file exists and is 0 bytes (same logic as kotlin test)
Test 5: Large file (100 KB)
- Create large.bin with 100 KB random data
- Pack with Rust archiver
- Decode with sh
- verify_file large.bin
Test 6: Cyrillic UTF-8 filename (SHL-03 validation)
- Create a file with a Cyrillic name:
echo -n "Тестовое содержимое" > "$TMPDIR/файл.txt" - Pack with Rust archiver
- Decode with sh
- verify_file that the Cyrillic-named file exists and matches SHA-256
- This test specifically validates SHL-03
- Create
-
Summary:
- Print results: "N passed, M failed out of T tests"
- Exit 1 if any failures, exit 0 if all pass
Key difference from kotlin test: Instead of java -jar "$JAR", use sh "$DECODER" to invoke the shell decoder. This ensures the decoder is tested under POSIX sh, not bash.
Make the script executable: chmod +x shell/test_decoder.sh
cd /home/nick/Projects/Rust/encrypted_archive && test -f shell/test_decoder.sh && test -x shell/test_decoder.sh && bash -n shell/test_decoder.sh && echo "SYNTAX OK" && grep -q 'decode.sh' shell/test_decoder.sh && grep -q 'verify_file' shell/test_decoder.sh && echo "STRUCTURE OK"
Run bash shell/test_decoder.sh and verify all 6 tests pass
shell/test_decoder.sh exists, is executable, passes bash -n, and contains all 6 test cases including Cyrillic filename test
cd /home/nick/Projects/Rust/encrypted_archive
bash shell/test_decoder.sh
Expected: All 6 tests pass (PASS for each test case).
If tests fail:
- Read the error output carefully
- Common issues to look for:
- Hex case mismatch: HMAC or SHA-256 comparison fails because of uppercase vs lowercase hex. Fix: normalize with
tr 'A-F' 'a-f' - dd offset errors: Wrong offset calculation in TOC parsing. Fix: verify field order matches FORMAT.md Section 5 exactly
- openssl pipe issues: Decryption produces garbage. Fix: extract ciphertext to temp file first, then decrypt from file (not pipe)
- Empty file handling: gunzip fails on empty input. Fix: check original_size=0 before decompression
- Cyrillic filename: garbled characters. Fix: ensure LC_ALL=C and no text processing on filename bytes
- HMAC scope error: Wrong bytes fed to HMAC. Fix: HMAC = IV (from archive file, 16 bytes) || ciphertext (encrypted_size bytes)
- Hex case mismatch: HMAC or SHA-256 comparison fails because of uppercase vs lowercase hex. Fix: normalize with
Fix decode.sh until all tests pass. Do NOT modify the test script to make tests pass -- fix the decoder.
After all tests pass, run one more verification:
# Verify Rust round-trip still works
cd /home/nick/Projects/Rust/encrypted_archive && cargo test --release 2>&1 | tail -5
<success_criteria>
- shell/test_decoder.sh exists and is executable
- All 6 test cases pass: single file, multiple files, no-compress, empty file, large file, Cyrillic filename
- Shell decoder produces byte-identical output verified by SHA-256 comparison
- Existing Rust test suite still passes </success_criteria>