From 9aeb6761111d1d0def296615c2b1e69aee1afc10 Mon Sep 17 00:00:00 2001 From: Leopere Date: Thu, 20 Mar 2025 18:27:48 -0400 Subject: [PATCH] Refactor test scripts into a single unified test file --- .gitignore | 6 +- Dockerfile | 8 +- README.md | 25 +++- docker-compose.yml | 82 ++++-------- test/complex-extracted-md5.txt | 6 + test/complex-original-md5.txt | 6 + test/test.sh | 222 +++++++++++++++++++++++++++++++++ 7 files changed, 292 insertions(+), 63 deletions(-) create mode 100644 test/complex-extracted-md5.txt create mode 100644 test/complex-original-md5.txt create mode 100755 test/test.sh diff --git a/.gitignore b/.gitignore index fde74a2..01a319f 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,8 @@ /test/complex/ /test/complex-extracted/ /test/local/ -/test/local-extracted/ \ No newline at end of file +/test/local-extracted/ +/test/standard-test/ +/test/standard-extracted/ +/test/reference-extracted/ +/test/*-checksums.txt \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 586d2c2..9bf28d9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -37,4 +37,10 @@ COPY --from=builder /app/tarballer-freebsd /bin/ COPY --from=builder /app/tarballer-darwin /bin/ # Make binaries executable -RUN chmod +x /bin/tarballer /bin/tarballer-freebsd /bin/tarballer-darwin \ No newline at end of file +RUN chmod +x /bin/tarballer /bin/tarballer-freebsd /bin/tarballer-darwin + +# Copy test script +COPY test/test.sh /bin/test.sh + +# Make test script executable +RUN chmod +x /bin/test.sh \ No newline at end of file diff --git a/README.md b/README.md index 3a39704..09fb2d8 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,8 @@ A simple utility to create tarballs with a specific directory structure. - Preserves file permissions and directory structure - Handles symbolic links correctly - Cross-platform compatibility (FreeBSD, macOS, Linux) +- Produces tarballs compatible with standard tar tools +- Verified data integrity with MD5 hash comparison ## Building @@ -25,17 +27,24 @@ This will create these binaries in the `./bin` directory: ## Testing -You can run the included test to verify functionality: +You can run the included tests to verify functionality: ```bash +# Run the basic functionality test docker compose up --build test + +# Run comparison test with standard tar tools +docker compose up --build tar-test ``` -This will: -1. Create a test directory structure with nested directories and symlinks -2. Create a tarball from it -3. Extract the tarball +The tests will: +1. Create test directory structures with nested directories and symlinks +2. Create tarballs from them +3. Extract the tarballs using standard tools 4. Verify the contents and file structure, including symlinks +5. Check that symlinks remain functional after extraction +6. Compare output with standard tar tools to ensure compatibility +7. Verify data integrity with MD5 hashing (original vs. extracted files) ## Usage @@ -61,4 +70,8 @@ The usage is the same for all binaries: ./bin/tarballer-freebsd -source ./myproject -output release.tar.gz -prefix app ``` -When extracted, all files will be under the `app/` directory in the tarball. \ No newline at end of file +When extracted, all files will be under the `app/` directory in the tarball and can be extracted with standard tools like: + +```bash +tar -xzf release.tar.gz -C /path/to/extract +``` \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 2bee676..21fd305 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,3 @@ -version: '3' - services: build: build: @@ -20,56 +18,30 @@ services: working_dir: /workdir depends_on: - build - command: | - sh -c "# Clean up existing test directories - rm -rf /test/complex /test/complex-extracted && - - # Create complex directory structure - mkdir -p /test/complex/dir1/subdir1/subsubdir1 && - mkdir -p /test/complex/dir1/subdir2 && - mkdir -p /test/complex/dir2/subdir1 && - - # Create files at different levels - echo 'root level file' > /test/complex/rootfile.txt && - echo 'level 1 file in dir1' > /test/complex/dir1/file1.txt && - echo 'level 1 file in dir2' > /test/complex/dir2/file2.txt && - echo 'level 2 file in subdir1' > /test/complex/dir1/subdir1/file3.txt && - echo 'level 2 file in subdir2' > /test/complex/dir1/subdir2/file4.txt && - echo 'level 3 file in subsubdir1' > /test/complex/dir1/subdir1/subsubdir1/file5.txt && - - # Create a symbolic link with a relative path instead of absolute - cd /test/complex/dir2 && ln -s ../rootfile.txt symlink.txt && cd /workdir && - - # Print the original structure for reference - echo '=== ORIGINAL DIRECTORY STRUCTURE ===' && - find /test/complex -type f -o -type l | sort && - - # Create the tarball - /bin/tarballer -source /test/complex -output /workdir/complex.tar.gz -prefix complex-app && - - # Extract the tarball - mkdir -p /test/complex-extracted && - tar -xzf /workdir/complex.tar.gz -C /test/complex-extracted && - - # Verify the extracted structure - echo '=== EXTRACTED DIRECTORY STRUCTURE ===' && - find /test/complex-extracted -type f -o -type l | sort && - - # Verify file content matches - echo '=== VERIFYING FILE CONTENTS ===' && - cat /test/complex/rootfile.txt && - echo ' <-- Original: rootfile.txt' && - cat /test/complex-extracted/complex-app/rootfile.txt && - echo ' <-- Extracted: rootfile.txt' && - - cat /test/complex/dir1/subdir1/subsubdir1/file5.txt && - echo ' <-- Original: deep nested file5.txt' && - cat /test/complex-extracted/complex-app/dir1/subdir1/subsubdir1/file5.txt && - echo ' <-- Extracted: deep nested file5.txt' && - - # Test symlink - echo '=== TESTING SYMLINK ===' && - ls -la /test/complex/dir2/symlink.txt && - ls -la /test/complex-extracted/complex-app/dir2/symlink.txt && - - echo 'All tests completed successfully!'" \ No newline at end of file + command: /bin/test.sh all + + basic-test: + build: + context: . + target: tester + volumes: + - ./bin:/output + - ./test:/test + - .:/workdir + working_dir: /workdir + depends_on: + - build + command: /bin/test.sh basic + + tar-test: + build: + context: . + target: tester + volumes: + - ./bin:/output + - ./test:/test + - .:/workdir + working_dir: /workdir + depends_on: + - build + command: /bin/test.sh tar \ No newline at end of file diff --git a/test/complex-extracted-md5.txt b/test/complex-extracted-md5.txt new file mode 100644 index 0000000..d17ba7b --- /dev/null +++ b/test/complex-extracted-md5.txt @@ -0,0 +1,6 @@ +fe910f3824aa56f69e6c5cfcaa617841 /test/complex-extracted/complex-app/dir1/file1.txt +65836cb8234924d22c1e383e4ddce797 /test/complex-extracted/complex-app/dir1/subdir1/file3.txt +03fc5818d2424dc1820fec5b6d3ba1ff /test/complex-extracted/complex-app/dir1/subdir1/subsubdir1/file5.txt +d4b7a1f50b3302d9523c0dba53f490fc /test/complex-extracted/complex-app/dir1/subdir2/file4.txt +604e0b2e70ef84a95fdc3dd6ca2d2d09 /test/complex-extracted/complex-app/dir2/file2.txt +788c8c79dbab5ef7507344254f0be0cb /test/complex-extracted/complex-app/rootfile.txt diff --git a/test/complex-original-md5.txt b/test/complex-original-md5.txt new file mode 100644 index 0000000..08d76be --- /dev/null +++ b/test/complex-original-md5.txt @@ -0,0 +1,6 @@ +fe910f3824aa56f69e6c5cfcaa617841 /test/complex/dir1/file1.txt +65836cb8234924d22c1e383e4ddce797 /test/complex/dir1/subdir1/file3.txt +03fc5818d2424dc1820fec5b6d3ba1ff /test/complex/dir1/subdir1/subsubdir1/file5.txt +d4b7a1f50b3302d9523c0dba53f490fc /test/complex/dir1/subdir2/file4.txt +604e0b2e70ef84a95fdc3dd6ca2d2d09 /test/complex/dir2/file2.txt +788c8c79dbab5ef7507344254f0be0cb /test/complex/rootfile.txt diff --git a/test/test.sh b/test/test.sh new file mode 100755 index 0000000..bf08d83 --- /dev/null +++ b/test/test.sh @@ -0,0 +1,222 @@ +#!/bin/sh + +# Determine which test to run +TEST_TYPE=${1:-"all"} + +run_basic_test() { + echo "=== RUNNING BASIC TEST ===" + + # Clean up existing test directories + rm -rf /test/complex /test/complex-extracted + + # Create complex directory structure + mkdir -p /test/complex/dir1/subdir1/subsubdir1 + mkdir -p /test/complex/dir1/subdir2 + mkdir -p /test/complex/dir2/subdir1 + + # Create files at different levels + echo 'root level file' > /test/complex/rootfile.txt + echo 'level 1 file in dir1' > /test/complex/dir1/file1.txt + echo 'level 1 file in dir2' > /test/complex/dir2/file2.txt + echo 'level 2 file in subdir1' > /test/complex/dir1/subdir1/file3.txt + echo 'level 2 file in subdir2' > /test/complex/dir1/subdir2/file4.txt + echo 'level 3 file in subsubdir1' > /test/complex/dir1/subdir1/subsubdir1/file5.txt + + # Create a symbolic link with a relative path instead of absolute + cd /test/complex/dir2 && ln -s ../rootfile.txt symlink.txt && cd /workdir + + # Calculate MD5 hashes of original files for verification + find /test/complex -type f | sort | xargs md5sum > /test/complex-original-md5.txt + + # Print the original structure for reference + echo '=== ORIGINAL DIRECTORY STRUCTURE ===' + find /test/complex -type f -o -type l | sort + + # Create the tarball + /bin/tarballer -source /test/complex -output /workdir/complex.tar.gz -prefix complex-app + + # Extract the tarball + mkdir -p /test/complex-extracted + tar -xzf /workdir/complex.tar.gz -C /test/complex-extracted + + # Verify the extracted structure + echo '=== EXTRACTED DIRECTORY STRUCTURE ===' + find /test/complex-extracted -type f -o -type l | sort + + # Calculate MD5 hashes of extracted files + find /test/complex-extracted -type f | sort | xargs md5sum > /test/complex-extracted-md5.txt + + # Compare file content + echo '=== VERIFYING FILE CONTENTS ===' + cat /test/complex/rootfile.txt + echo ' <-- Original: rootfile.txt' + cat /test/complex-extracted/complex-app/rootfile.txt + echo ' <-- Extracted: rootfile.txt' + + cat /test/complex/dir1/subdir1/subsubdir1/file5.txt + echo ' <-- Original: deep nested file5.txt' + cat /test/complex-extracted/complex-app/dir1/subdir1/subsubdir1/file5.txt + echo ' <-- Extracted: deep nested file5.txt' + + # Test symlink + echo '=== TESTING SYMLINK ===' + ls -la /test/complex/dir2/symlink.txt + ls -la /test/complex-extracted/complex-app/dir2/symlink.txt + + # Verify MD5 hashes + echo '=== MD5 HASH VERIFICATION ===' + echo 'Original file hashes:' + cat /test/complex-original-md5.txt + echo 'Extracted file hashes:' + cat /test/complex-extracted-md5.txt + + # Verify hash comparison + echo '=== COMPARING FILE HASHES ===' + ORIG_HASHES=$(cat /test/complex-original-md5.txt | awk '{print $1}' | sort) + EXTR_HASHES=$(cat /test/complex-extracted-md5.txt | grep -v 'complex-app$' | awk '{print $1}' | sort) + + if [ "$ORIG_HASHES" = "$EXTR_HASHES" ]; then + echo 'SUCCESS: All file hashes match between original and extracted files!' + else + echo 'ERROR: Hash mismatch detected!' + return 1 + fi + + echo 'Basic test completed successfully!' + return 0 +} + +run_tar_comparison_test() { + echo "=== RUNNING TAR COMPARISON TEST ===" + + # Clean up test directories + rm -rf /test/standard-test /test/standard-extracted /test/reference-extracted + + # Create a diverse test directory structure + mkdir -p /test/standard-test/config/settings + mkdir -p /test/standard-test/data/user/documents + mkdir -p /test/standard-test/data/user/pictures + mkdir -p /test/standard-test/logs + + # Create various file types + echo '{"app": "tarballer", "version": "1.0"}' > /test/standard-test/config/settings/app.json + echo 'debug=true' > /test/standard-test/config/settings/debug.conf + dd if=/dev/urandom bs=1K count=10 of=/test/standard-test/data/user/documents/binary.dat 2>/dev/null + echo 'Test log entry 1' > /test/standard-test/logs/app.log + echo 'Test log entry 2' >> /test/standard-test/logs/app.log + + # Create symlinks + ln -s ../config/settings/app.json /test/standard-test/data/config-link.json + ln -s ../../logs/app.log /test/standard-test/data/user/log-link.txt + + # Store MD5 hashes of original files for comparison + find /test/standard-test -type f | sort | xargs md5sum > /test/original-checksums.txt + + # Create tarball using our utility + /bin/tarballer -source /test/standard-test -output /workdir/standard.tar.gz -prefix app + + # Create a reference tarball using standard tar for comparison + tar -czf /workdir/reference.tar.gz -C /test/standard-test --transform 's,^./,app/,' . + + echo '=== TARBALLER OUTPUT ===' + mkdir -p /test/standard-extracted + tar -xzf /workdir/standard.tar.gz -C /test/standard-extracted + find /test/standard-extracted -type f -o -type l | sort + + # Extract reference tarball + echo '=== REFERENCE TAR OUTPUT ===' + mkdir -p /test/reference-extracted + tar -xzf /workdir/reference.tar.gz -C /test/reference-extracted + find /test/reference-extracted -type f -o -type l | sort + + # Verify checksums match for all extracted files + echo '=== CHECKSUMS OF EXTRACTED FILES ===' + find /test/standard-extracted -type f | sort | xargs md5sum > /test/standard-checksums.txt + find /test/reference-extracted -type f | sort | xargs md5sum > /test/reference-checksums.txt + + echo 'ORIGINAL FILE CHECKSUMS:' + cat /test/original-checksums.txt + + echo 'TARBALLER EXTRACTED CHECKSUMS:' + cat /test/standard-checksums.txt + + echo 'REFERENCE TAR EXTRACTED CHECKSUMS:' + cat /test/reference-checksums.txt + + # Compare MD5 checksums systematically + echo '=== SYSTEMATIC MD5 COMPARISON ===' + + # Extract just the hash part from each file + ORIG_HASHES=$(cat /test/original-checksums.txt | awk '{print $1}' | sort) + TARB_HASHES=$(cat /test/standard-checksums.txt | awk '{print $1}' | sort) + REF_HASHES=$(cat /test/reference-checksums.txt | awk '{print $1}' | sort) + + # Compare original to tarballer extraction + if [ "$ORIG_HASHES" = "$TARB_HASHES" ]; then + echo 'SUCCESS: Tarballer extraction hashes match original files!' + else + echo 'ERROR: Hash mismatch detected between original and tarballer extraction!' + return 1 + fi + + # Compare original to reference tar extraction + if [ "$ORIG_HASHES" = "$REF_HASHES" ]; then + echo 'SUCCESS: Reference tar extraction hashes match original files!' + else + echo 'ERROR: Hash mismatch detected between original and reference tar extraction!' + return 1 + fi + + echo '=== VERIFYING SYMLINKS ===' + echo 'ORIGINAL SYMLINKS:' + find /test/standard-test -type l -exec ls -la {} \; + echo 'EXTRACTED SYMLINKS:' + find /test/standard-extracted -type l -exec ls -la {} \; + + # Compare file counts to ensure all files were extracted + echo '=== FILE COUNT COMPARISON ===' + echo -n 'Original files: ' && find /test/standard-test -type f | wc -l + echo -n 'Extracted files: ' && find /test/standard-extracted -type f | wc -l + + # Test symlink functionality + echo '=== TESTING SYMLINK CONTENT ===' + echo 'Original linked content:' + cat /test/standard-test/data/config-link.json + echo 'Extracted linked content:' + cat /test/standard-extracted/app/data/config-link.json + + echo 'Tar comparison test completed successfully!' + return 0 +} + +# Main script execution +case "$TEST_TYPE" in + "basic") + run_basic_test + exit $? + ;; + "tar") + run_tar_comparison_test + exit $? + ;; + "all") + echo "=== RUNNING ALL TESTS ===" + run_basic_test + BASIC_RESULT=$? + run_tar_comparison_test + TAR_RESULT=$? + + if [ $BASIC_RESULT -eq 0 ] && [ $TAR_RESULT -eq 0 ]; then + echo "✅ ALL TESTS PASSED SUCCESSFULLY!" + exit 0 + else + echo "❌ SOME TESTS FAILED!" + exit 1 + fi + ;; + *) + echo "Unknown test type: $TEST_TYPE" + echo "Usage: $0 [basic|tar|all]" + exit 1 + ;; +esac \ No newline at end of file