#!/bin/bash set -e # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color # Test counter TESTS_PASSED=0 TESTS_FAILED=0 # Cleanup function cleanup() { echo -e "\n${YELLOW}Cleaning up test artifacts...${NC}" rm -rf test test-*.tgz test-*.zip collect /tmp/test_output.txt 2>/dev/null || true echo -e "${GREEN}Cleanup completed.${NC}" } # Set trap to cleanup on script exit (success, failure, or interruption) trap cleanup EXIT # Function to run a test run_test() { local test_name="$1" local command="$2" local expected_exit_code="${3:-0}" echo -n "Testing $test_name... " # Run command and capture exit code set +e eval "$command" > /tmp/test_output.txt 2>&1 local exit_code=$? set -e if [ $exit_code -eq $expected_exit_code ]; then echo -e "${GREEN}PASSED${NC}" ((TESTS_PASSED++)) return 0 else echo -e "${RED}FAILED${NC}" echo " Expected exit code: $expected_exit_code, got: $exit_code" echo " Output:" cat /tmp/test_output.txt | sed 's/^/ /' ((TESTS_FAILED++)) return 1 fi } # Function to verify archive contents verify_archive_contents() { local archive="$1" local expected_files="$2" echo -n " Verifying contents of $archive... " if [[ "$archive" == *.tgz || "$archive" == *.tar.gz ]]; then actual_files=$(tar -tzf "$archive" | sort | tr '\n' ' ' | sed 's/ $//') elif [[ "$archive" == *.zip ]]; then actual_files=$(unzip -l "$archive" | grep -v "Archive:" | grep -v "Length" | grep -v -- "--------" | grep -v "files" | awk '{print $4}' | grep -v '^$' | sort | tr '\n' ' ' | sed 's/ $//') else echo -e "${RED}Unknown archive format${NC}" return 1 fi expected_sorted=$(echo "$expected_files" | tr ' ' '\n' | sort | tr '\n' ' ' | sed 's/ $//') if [ "$actual_files" = "$expected_sorted" ]; then echo -e "${GREEN}OK${NC}" return 0 else echo -e "${RED}FAILED${NC}" echo " Expected: $expected_sorted" echo " Got: $actual_files" return 1 fi } echo -e "${YELLOW}=== Collect CLI Test Suite ===${NC}\n" # Clean up any previous test artifacts echo "Cleaning up previous test artifacts..." rm -rf test test-*.tgz test-*.zip collect # Build the tool echo "Building collect tool..." if ! go build -o collect; then echo -e "${RED}Failed to build collect tool${NC}" exit 1 fi echo -e "${GREEN}Build successful${NC}\n" # Create test directory structure echo "Setting up test environment..." mkdir -p test/subdir/aet-bin test/subdir/aet-config test/other test/deep/nested/aet-tools echo "test config" > test/.mise.toml echo "another config" > test/subdir/.mise.toml echo "binary" > test/subdir/aet-bin/tool echo "config" > test/subdir/aet-config/settings.conf echo "other file" > test/other/file.txt echo "deep tool" > test/deep/nested/aet-tools/deep.sh echo "not in aet dir" > test/deep/nested/regular.txt echo -e "${GREEN}Test environment ready${NC}\n" # Test 1: Name matching with tar.gz run_test "name matching (.mise.toml) with tar.gz" \ "./collect --name .mise.toml test/ test-name.tgz" verify_archive_contents "test-name.tgz" ".mise.toml subdir/.mise.toml" # Test 2: Pattern matching with zip run_test "pattern matching (aet-*) with zip" \ "./collect --match 'aet-*' test/ test-pattern.zip" verify_archive_contents "test-pattern.zip" "subdir/aet-bin/tool subdir/aet-config/settings.conf deep/nested/aet-tools/deep.sh" # Test 3: Pattern matching with tgz run_test "pattern matching (aet-*) with tgz" \ "./collect --match 'aet-*' test/ test-pattern.tgz" verify_archive_contents "test-pattern.tgz" "deep/nested/aet-tools/deep.sh subdir/aet-bin/tool subdir/aet-config/settings.conf" # Test 4: No files found (should exit with code 1) run_test "no files found error" \ "./collect --name nonexistent.file test/ test-empty.zip" 1 # Test 5: Invalid arguments - no flags run_test "invalid arguments - no flags" \ "./collect test/ output.zip" 3 # Test 6: Invalid arguments - no positional args run_test "invalid arguments - no positional args" \ "./collect --name .mise.toml" 3 # Test 7: Invalid arguments - missing output file run_test "invalid arguments - missing output file" \ "./collect --name .mise.toml test/" 3 # Test 8: Invalid archive format run_test "invalid archive format" \ "./collect --name .mise.toml test/ output.txt" 3 # Test 9: Non-existent source directory run_test "non-existent source directory" \ "./collect --name .mise.toml nonexistent/ output.zip" 2 # Test 10: Help flag run_test "help flag output" \ "./collect --help" 0 # Test 11: Name matching with subdirectory pattern echo "subdir config" > test/subdir/aet-bin/.mise.toml run_test "name matching finds files in pattern dirs too" \ "./collect --name .mise.toml test/ test-name-all.tgz" verify_archive_contents "test-name-all.tgz" ".mise.toml subdir/.mise.toml subdir/aet-bin/.mise.toml" # Test 12: Multiple name flags echo "readme" > test/README.md echo "makefile" > test/Makefile echo "another makefile" > test/subdir/Makefile run_test "multiple name flags" \ "./collect --name .mise.toml --name README.md --name Makefile test/ test-multi-name.tgz" verify_archive_contents "test-multi-name.tgz" ".mise.toml Makefile README.md subdir/.mise.toml subdir/Makefile subdir/aet-bin/.mise.toml" # Test 13: Multiple match flags mkdir -p test/prefix-one test/prefix-two test/other-prefix echo "file1" > test/prefix-one/data.txt echo "file2" > test/prefix-two/config.yml echo "file3" > test/other-prefix/info.log run_test "multiple match flags" \ "./collect --match 'prefix-*' --match 'aet-*' test/ test-multi-match.tgz" verify_archive_contents "test-multi-match.tgz" "deep/nested/aet-tools/deep.sh prefix-one/data.txt prefix-two/config.yml subdir/aet-bin/.mise.toml subdir/aet-bin/tool subdir/aet-config/settings.conf" # Test 14: Combined name and match flags run_test "combined name and match flags" \ "./collect --name .mise.toml --match 'aet-*' --name README.md test/ test-combined.tgz" verify_archive_contents "test-combined.tgz" ".mise.toml README.md deep/nested/aet-tools/deep.sh subdir/.mise.toml subdir/aet-bin/.mise.toml subdir/aet-bin/tool subdir/aet-config/settings.conf" # Test 15: Include directory filter - simple path mkdir -p test/src test/docs test/examples echo "source file" > test/src/main.go echo "doc file" > test/docs/README.md echo "example file" > test/examples/demo.txt run_test "include directory - simple path" \ "./collect --include-dir src --name 'main.go' test/ test-include-simple.tgz" verify_archive_contents "test-include-simple.tgz" "src/main.go" # Test 16: Include directory filter - glob pattern mkdir -p test/project-one/src test/project-two/src test/other/src echo "p1 source" > test/project-one/src/app.go echo "p2 source" > test/project-two/src/lib.go echo "other source" > test/other/src/util.go run_test "include directory - glob pattern" \ "./collect --include-dir 'project-*' --name 'app.go' --name 'lib.go' test/ test-include-glob.tgz" verify_archive_contents "test-include-glob.tgz" "project-one/src/app.go project-two/src/lib.go" # Test 17: Exclude directory filter - simple path run_test "exclude directory - simple path" \ "./collect --exclude-dir docs --name 'README.md' test/ test-exclude-simple.tgz" verify_archive_contents "test-exclude-simple.tgz" "README.md" # Test 18: Exclude directory filter - glob pattern mkdir -p test/temp-cache test/temp-logs test/important echo "cache file" > test/temp-cache/data.txt echo "log file" > test/temp-logs/app.log echo "important file" > test/important/config.txt run_test "exclude directory - glob pattern" \ "./collect --exclude-dir 'temp-*' --name 'data.txt' --name 'config.txt' --name 'demo.txt' test/ test-exclude-glob.tgz" verify_archive_contents "test-exclude-glob.tgz" "examples/demo.txt important/config.txt prefix-one/data.txt" # Test 19: Multiple include directories run_test "multiple include directories" \ "./collect --include-dir src --include-dir docs --name 'main.go' --name 'README.md' test/ test-multi-include.tgz" verify_archive_contents "test-multi-include.tgz" "docs/README.md src/main.go" # Test 20: Multiple exclude directories run_test "multiple exclude directories" \ "./collect --exclude-dir 'temp-*' --exclude-dir examples --name 'data.txt' --name 'config.txt' test/ test-multi-exclude.tgz" verify_archive_contents "test-multi-exclude.tgz" "important/config.txt prefix-one/data.txt" # Test 21: Combined include and exclude (include takes precedence in overlaps) run_test "combined include and exclude filters" \ "./collect --include-dir 'project-*' --exclude-dir 'project-two' --name 'app.go' --name 'lib.go' test/ test-include-exclude.tgz" verify_archive_contents "test-include-exclude.tgz" "project-one/src/app.go" # Summary echo -e "\n${YELLOW}=== Test Summary ===${NC}" echo -e "Tests passed: ${GREEN}$TESTS_PASSED${NC}" echo -e "Tests failed: ${RED}$TESTS_FAILED${NC}" if [ $TESTS_FAILED -eq 0 ]; then echo -e "\n${GREEN}All tests passed!${NC}" exit 0 else echo -e "\n${RED}Some tests failed!${NC}" exit 1 fi