294 lines
11 KiB
Bash
Executable file
294 lines
11 KiB
Bash
Executable file
#!/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
|
|
}
|
|
|
|
# Function to verify command output contains expected text
|
|
verify_output_contains() {
|
|
local expected_text="$1"
|
|
|
|
echo -n " Verifying output contains '$expected_text'... "
|
|
|
|
if grep -q "$expected_text" /tmp/test_output.txt; then
|
|
echo -e "${GREEN}OK${NC}"
|
|
return 0
|
|
else
|
|
echo -e "${RED}FAILED${NC}"
|
|
echo " Expected to find: $expected_text"
|
|
echo " In output:"
|
|
cat /tmp/test_output.txt | sed 's/^/ /'
|
|
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"
|
|
|
|
# Test 22: Verbose output shows files being found
|
|
run_test "verbose output shows files being found" \
|
|
"./collect --verbose --name 'README.md' --name 'main.go' test/ test-verbose.tgz"
|
|
verify_archive_contents "test-verbose.tgz" "README.md docs/README.md src/main.go"
|
|
verify_output_contains "found: README.md"
|
|
verify_output_contains "found: docs/README.md"
|
|
verify_output_contains "found: src/main.go"
|
|
|
|
# Test 23: Dry-run shows files that would be collected without creating archive
|
|
run_test "dry-run shows files without creating archive" \
|
|
"./collect --dry-run --name 'README.md' --name 'main.go' test/ test-dry-run.tgz"
|
|
verify_output_contains "DRY RUN: Found 3 files that would be collected:"
|
|
verify_output_contains " README.md"
|
|
verify_output_contains " docs/README.md"
|
|
verify_output_contains " src/main.go"
|
|
verify_output_contains "DRY RUN: Would create archive: test-dry-run.tgz"
|
|
verify_output_contains "DRY RUN: No archive created"
|
|
|
|
# Verify that dry-run didn't actually create the archive
|
|
echo -n " Verifying no archive was created... "
|
|
if [ ! -f "test-dry-run.tgz" ]; then
|
|
echo -e "${GREEN}OK${NC}"
|
|
else
|
|
echo -e "${RED}FAILED${NC}"
|
|
echo " Archive was created when it shouldn't have been"
|
|
((TESTS_FAILED++))
|
|
fi
|
|
|
|
# Test 24: Dry-run with verbose shows both found messages and dry-run output
|
|
run_test "dry-run with verbose shows comprehensive output" \
|
|
"./collect --dry-run --verbose --name 'main.go' test/ test-dry-run-verbose.tgz"
|
|
verify_output_contains "found: src/main.go"
|
|
verify_output_contains "DRY RUN: Found 1 files that would be collected:"
|
|
verify_output_contains " src/main.go"
|
|
|
|
# Test 25: Dry-run with no matching files
|
|
run_test "dry-run with no matching files" \
|
|
"./collect --dry-run --name 'nonexistent.file' test/ test-dry-run-empty.tgz" 1
|
|
|
|
# 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
|