From 62ff949194ea1b2e78ff1f8a59934d72511ccdff Mon Sep 17 00:00:00 2001 From: NikitolProject Date: Wed, 25 Feb 2026 01:09:35 +0300 Subject: [PATCH] feat(04-01): add cross-validation test script for Kotlin decoder - Checks prerequisites (kotlinc, java, cargo) with install instructions - Test 1: single text file round-trip (Rust pack -> Kotlin decode) - Test 2: multiple files with mixed content (text + 10KB binary) - Test 3: no-compress mode for pre-compressed files - Test 4: empty file edge case - Test 5: large file (100 KB random data) - SHA-256 comparison of original vs extracted for each test - Colored output, temp directory cleanup via trap, non-zero exit on failure Co-Authored-By: Claude Opus 4.6 --- kotlin/test_decoder.sh | 263 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 263 insertions(+) create mode 100755 kotlin/test_decoder.sh diff --git a/kotlin/test_decoder.sh b/kotlin/test_decoder.sh new file mode 100755 index 0000000..e071ecb --- /dev/null +++ b/kotlin/test_decoder.sh @@ -0,0 +1,263 @@ +#!/usr/bin/env bash +set -euo pipefail + +# --------------------------------------------------------------------------- +# Cross-validation test script for Kotlin ArchiveDecoder +# +# Creates archives with the Rust CLI, decodes with the Kotlin decoder, +# and verifies byte-identical output via SHA-256 comparison. +# --------------------------------------------------------------------------- + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" +TMPDIR="" +PASS_COUNT=0 +FAIL_COUNT=0 +TOTAL_COUNT=0 + +# Colors (if terminal supports them) +if [ -t 1 ]; then + GREEN='\033[0;32m' + RED='\033[0;31m' + YELLOW='\033[0;33m' + BOLD='\033[1m' + NC='\033[0m' +else + GREEN='' + RED='' + YELLOW='' + BOLD='' + NC='' +fi + +# --------------------------------------------------------------------------- +# Helpers +# --------------------------------------------------------------------------- + +cleanup() { + if [ -n "$TMPDIR" ] && [ -d "$TMPDIR" ]; then + rm -rf "$TMPDIR" + fi +} +trap cleanup EXIT + +pass() { + local name="$1" + PASS_COUNT=$((PASS_COUNT + 1)) + TOTAL_COUNT=$((TOTAL_COUNT + 1)) + echo -e " ${GREEN}PASS${NC}: $name" +} + +fail() { + local name="$1" + local detail="${2:-}" + FAIL_COUNT=$((FAIL_COUNT + 1)) + TOTAL_COUNT=$((TOTAL_COUNT + 1)) + echo -e " ${RED}FAIL${NC}: $name" + if [ -n "$detail" ]; then + echo " $detail" + fi +} + +sha256_of() { + sha256sum "$1" | awk '{print $1}' +} + +verify_file() { + local original="$1" + local extracted="$2" + local label="$3" + + if [ ! -f "$extracted" ]; then + fail "$label" "Extracted file not found: $extracted" + return + fi + + local orig_hash + local ext_hash + orig_hash=$(sha256_of "$original") + ext_hash=$(sha256_of "$extracted") + + if [ "$orig_hash" = "$ext_hash" ]; then + pass "$label (SHA-256: ${orig_hash:0:16}...)" + else + fail "$label" "SHA-256 mismatch: original=$orig_hash extracted=$ext_hash" + fi +} + +# --------------------------------------------------------------------------- +# Prerequisites check +# --------------------------------------------------------------------------- + +echo -e "${BOLD}Checking prerequisites...${NC}" + +if ! command -v kotlinc &>/dev/null; then + echo -e "${RED}ERROR${NC}: kotlinc not found." + echo " Install Kotlin compiler:" + echo " - SDKMAN: sdk install kotlin" + echo " - Homebrew: brew install kotlin" + echo " - Snap: sudo snap install kotlin --classic" + echo " - Manual: https://kotlinlang.org/docs/command-line.html" + exit 1 +fi + +if ! command -v java &>/dev/null; then + echo -e "${RED}ERROR${NC}: java not found." + echo " Install Java runtime:" + echo " - Ubuntu: sudo apt install default-jdk" + echo " - SDKMAN: sdk install java" + exit 1 +fi + +if ! command -v cargo &>/dev/null; then + echo -e "${RED}ERROR${NC}: cargo not found." + echo " Install Rust: https://rustup.rs/" + exit 1 +fi + +echo " kotlinc: $(kotlinc -version 2>&1 | head -1)" +echo " java: $(java -version 2>&1 | head -1)" +echo " cargo: $(cargo --version)" +echo "" + +# --------------------------------------------------------------------------- +# Build Rust archiver +# --------------------------------------------------------------------------- + +echo -e "${BOLD}Building Rust archiver...${NC}" +(cd "$PROJECT_DIR" && cargo build --release -q) +ARCHIVER="$PROJECT_DIR/target/release/encrypted_archive" +echo " Built: $ARCHIVER" +echo "" + +# --------------------------------------------------------------------------- +# Compile Kotlin decoder +# --------------------------------------------------------------------------- + +echo -e "${BOLD}Compiling Kotlin decoder...${NC}" +JAR="$SCRIPT_DIR/ArchiveDecoder.jar" +kotlinc "$SCRIPT_DIR/ArchiveDecoder.kt" -include-runtime -d "$JAR" 2>&1 | tail -5 || true +if [ ! -f "$JAR" ]; then + echo -e "${RED}ERROR${NC}: Compilation failed. ArchiveDecoder.jar not found." + exit 1 +fi +echo " Compiled: $JAR" +echo "" + +# --------------------------------------------------------------------------- +# Create temp directory +# --------------------------------------------------------------------------- + +TMPDIR=$(mktemp -d) +echo -e "${BOLD}Temp directory: $TMPDIR${NC}" +echo "" + +# --------------------------------------------------------------------------- +# Test case 1: Single text file +# --------------------------------------------------------------------------- + +echo -e "${BOLD}Test 1: Single text file${NC}" + +ORIG1="$TMPDIR/hello.txt" +echo -n "Hello, World!" > "$ORIG1" + +"$ARCHIVER" pack "$ORIG1" -o "$TMPDIR/test1.archive" +java -jar "$JAR" "$TMPDIR/test1.archive" "$TMPDIR/output1/" + +verify_file "$ORIG1" "$TMPDIR/output1/hello.txt" "hello.txt" +echo "" + +# --------------------------------------------------------------------------- +# Test case 2: Multiple files with mixed content (text + binary + Cyrillic) +# --------------------------------------------------------------------------- + +echo -e "${BOLD}Test 2: Multiple files with mixed content${NC}" + +ORIG2_TEXT="$TMPDIR/text.txt" +cat > "$ORIG2_TEXT" << 'TEXTEOF' +This is a test file with multiple lines. +It contains ASCII and Cyrillic characters. +Line 3: testing 1 2 3. +TEXTEOF + +ORIG2_BIN="$TMPDIR/binary.bin" +dd if=/dev/urandom bs=1024 count=10 of="$ORIG2_BIN" 2>/dev/null + +"$ARCHIVER" pack "$ORIG2_TEXT" "$ORIG2_BIN" -o "$TMPDIR/test2.archive" +java -jar "$JAR" "$TMPDIR/test2.archive" "$TMPDIR/output2/" + +verify_file "$ORIG2_TEXT" "$TMPDIR/output2/text.txt" "text.txt (multiline UTF-8)" +verify_file "$ORIG2_BIN" "$TMPDIR/output2/binary.bin" "binary.bin (10 KB random)" +echo "" + +# --------------------------------------------------------------------------- +# Test case 3: Already-compressed file (APK-like, no compression) +# --------------------------------------------------------------------------- + +echo -e "${BOLD}Test 3: Already-compressed file (no-compress mode)${NC}" + +ORIG3="$TMPDIR/fake.dat" +dd if=/dev/urandom bs=512 count=5 of="$ORIG3" 2>/dev/null + +# Use --no-compress with the filename pattern to skip compression +"$ARCHIVER" pack "$ORIG3" -o "$TMPDIR/test3.archive" --no-compress "fake.dat" +java -jar "$JAR" "$TMPDIR/test3.archive" "$TMPDIR/output3/" + +verify_file "$ORIG3" "$TMPDIR/output3/fake.dat" "fake.dat (no-compress)" +echo "" + +# --------------------------------------------------------------------------- +# Test case 4: Empty file +# --------------------------------------------------------------------------- + +echo -e "${BOLD}Test 4: Empty file${NC}" + +ORIG4="$TMPDIR/empty.txt" +touch "$ORIG4" + +"$ARCHIVER" pack "$ORIG4" -o "$TMPDIR/test4.archive" +java -jar "$JAR" "$TMPDIR/test4.archive" "$TMPDIR/output4/" + +# Verify output file exists and is empty +if [ -f "$TMPDIR/output4/empty.txt" ]; then + EMPTY_SIZE=$(wc -c < "$TMPDIR/output4/empty.txt") + if [ "$EMPTY_SIZE" -eq 0 ]; then + pass "empty.txt (0 bytes)" + else + fail "empty.txt" "Expected 0 bytes, got $EMPTY_SIZE bytes" + fi +else + fail "empty.txt" "File not found in output" +fi +echo "" + +# --------------------------------------------------------------------------- +# Test case 5: Large file (100 KB) +# --------------------------------------------------------------------------- + +echo -e "${BOLD}Test 5: Large file (100 KB)${NC}" + +ORIG5="$TMPDIR/large.bin" +dd if=/dev/urandom bs=1024 count=100 of="$ORIG5" 2>/dev/null + +"$ARCHIVER" pack "$ORIG5" -o "$TMPDIR/test5.archive" +java -jar "$JAR" "$TMPDIR/test5.archive" "$TMPDIR/output5/" + +verify_file "$ORIG5" "$TMPDIR/output5/large.bin" "large.bin (100 KB random)" +echo "" + +# --------------------------------------------------------------------------- +# Summary +# --------------------------------------------------------------------------- + +echo -e "${BOLD}========================================${NC}" +echo -e "${BOLD}Results: $PASS_COUNT passed, $FAIL_COUNT failed out of $TOTAL_COUNT tests${NC}" +echo -e "${BOLD}========================================${NC}" + +if [ "$FAIL_COUNT" -gt 0 ]; then + echo -e "${RED}SOME TESTS FAILED${NC}" + exit 1 +else + echo -e "${GREEN}ALL TESTS PASSED${NC}" + exit 0 +fi