1 contributor
#!/bin/bash
# Media Importer Test Runner
# Comprehensive testing framework based on Development.md specifications
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
TEST_DIR="$SCRIPT_DIR/test"
SOURCE_DIR="$TEST_DIR/source"
DEST_DIR="$TEST_DIR/destination"
SAMPLES_DIR="$SCRIPT_DIR/sample" # Fixed: was 'samples' but should be 'sample'
MEDIA_IMPORTER="$SCRIPT_DIR/media-importer.sh"
TEST_REPORTS_DIR="$SCRIPT_DIR/test_reports"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Function to print colored output
print_color() {
local color="$1"
local message="$2"
echo -e "${color}${message}${NC}"
}
# Function to create test directories
create_test_dirs() {
print_color "$BLUE" "Creating test directories..."
mkdir -p "$SOURCE_DIR"
mkdir -p "$DEST_DIR"
mkdir -p "$TEST_REPORTS_DIR"
}
# Function to clean test directory
clean_test_dir() {
print_color "$BLUE" "Cleaning test directory..."
rm -rf "$TEST_DIR"/*
}
# Function to copy sample files
copy_sample_files() {
local source_pattern="$1"
local target_dir="$2"
if [[ -d "$SAMPLES_DIR/$source_pattern" ]]; then
# Copy all files recursively from source to target directory
find "$SAMPLES_DIR/$source_pattern" -type f \( -iname "*.jpg" -o -iname "*.jpeg" -o -iname "*.png" -o -iname "*.tiff" -o -iname "*.tif" -o -iname "*.cr2" -o -iname "*.nef" -o -iname "*.arw" -o -iname "*.dng" -o -iname "*.raw" -o -iname "*.mp4" -o -iname "*.mov" -o -iname "*.avi" -o -iname "*.mts" -o -iname "*.m2ts" -o -iname "*.mkv" -o -iname "*.wmv" -o -iname "*.3gp" -o -iname "*.m4v" \) -exec cp {} "$target_dir/" \; 2>/dev/null || true
print_color "$GREEN" "Copied $source_pattern files to $target_dir"
else
print_color "$YELLOW" "Warning: $SAMPLES_DIR/$source_pattern not found. Path: $SAMPLES_DIR/$source_pattern"
fi
}
# Function to capture directory state
capture_state() {
local dir_path="$1"
local output_file="$2"
local label="$3"
print_color "$BLUE" "Capturing $label directory state..."
if [[ -d "$dir_path" ]]; then
find "$dir_path" -type f | sort > "$output_file"
else
echo "# Directory does not exist or is empty" > "$output_file"
fi
}
# Function to run test command and capture output
run_test_command() {
local command="$1"
local log_file="$2"
print_color "$YELLOW" "Executing: $command"
echo "$command" > "$log_file"
echo "" >> "$log_file"
echo "=== SCRIPT OUTPUT ===" >> "$log_file"
# Run command and capture both stdout and stderr
if eval "$command" >> "$log_file" 2>&1; then
echo "" >> "$log_file"
echo "=== COMMAND COMPLETED SUCCESSFULLY ===" >> "$log_file"
return 0
else
echo "" >> "$log_file"
echo "=== COMMAND FAILED ===" >> "$log_file"
return 1
fi
}
# Function to generate test report
generate_test_report() {
local test_name="$1"
local scenario="$2"
local objective="$3"
local files_used="$4"
local command="$5"
local result_status="$6"
# Determine success/failure prefix
local status_prefix
if [[ $result_status -eq 0 ]]; then
status_prefix="s"
else
status_prefix="f"
fi
# Format date as YYYYMMDD
local date_stamp=$(date '+%Y%m%d')
# Create filename with new format: [s|f]_date_restul_numelei
local report_file="$TEST_REPORTS_DIR/${status_prefix}_${date_stamp}_${test_name}.md"
print_color "$BLUE" "Generating test report: $report_file"
cat > "$report_file" << EOF
# Test Report: $test_name
## Test Information
- **Date**: $(date)
- **Scenario**: $scenario
- **Objective**: $objective
- **Files Used**: $files_used
## Pre-Test State
### Source Directory Structure
\`\`\`
$(cat "$TEST_DIR/source_before.txt" 2>/dev/null || echo "# No pre-test source state captured")
\`\`\`
### Destination Directory Structure
\`\`\`
$(cat "$TEST_DIR/dest_before.txt" 2>/dev/null || echo "# No pre-test destination state captured")
\`\`\`
## Test Execution
### Command Used
\`\`\`bash
$command
\`\`\`
### Script Output
\`\`\`
$(cat "$TEST_DIR/import_log.txt" 2>/dev/null || echo "# No script output captured")
\`\`\`
## Post-Test State
### Source Directory Structure
\`\`\`
$(cat "$TEST_DIR/source_after.txt" 2>/dev/null || echo "# No post-test source state captured")
\`\`\`
### Destination Directory Structure
\`\`\`
$(cat "$TEST_DIR/dest_after.txt" 2>/dev/null || echo "# No post-test destination state captured")
\`\`\`
## Analysis and Verification
### Expected Results
- Files should be processed according to the test scenario
- No data loss should occur
- Proper error handling for edge cases
### Actual Results
- Test execution completed with status: $result_status
### Issues Found
- [ ] No issues detected
- [ ] Issues found (see notes below)
### Protections Verified
- [ ] Destination exclusion working
- [ ] Move confirmation functional
- [ ] No data loss detected
- [ ] UTC conversion correct (for QuickTime files)
- [ ] Unimportable files handling (if applicable)
## Conclusion
### Test Result
- [ ] PASSED
- [ ] FAILED
- [ ] PARTIAL (with notes)
### Notes
Test completed as per Development.md specifications.
### Files Generated
- \`test/source_before.txt\` - Pre-test source structure
- \`test/dest_before.txt\` - Pre-test destination structure
- \`test/source_after.txt\` - Post-test source structure
- \`test/dest_after.txt\` - Post-test destination structure
- \`test/import_log.txt\` - Full script execution log
- \`test/test_report.md\` - This report
EOF
print_color "$GREEN" "Test report generated: $report_file"
# Clean up old reports, keeping only the last 10
cleanup_old_reports
}
# Function to clean up old test reports, keeping only the last 10
cleanup_old_reports() {
if [[ -d "$TEST_REPORTS_DIR" ]]; then
# Count total reports
local total_reports=$(find "$TEST_REPORTS_DIR" -name "*.md" | wc -l)
if [[ $total_reports -gt 10 ]]; then
print_color "$BLUE" "Cleaning up old test reports (keeping last 10)..."
# Find and remove oldest reports, keeping the 10 most recent
find "$TEST_REPORTS_DIR" -name "*.md" -type f -printf '%T@ %p\n' | \
sort -n | \
head -n -$((10)) | \
cut -d' ' -f2- | \
xargs -r rm
local remaining=$(find "$TEST_REPORTS_DIR" -name "*.md" | wc -l)
print_color "$GREEN" "Kept $remaining most recent test reports"
fi
fi
}
# Test Case 0: Basic Functionality Test
run_basic_functionality_test() {
print_color "$GREEN" "=== Running Test 0: Basic Functionality Test ==="
clean_test_dir
create_test_dirs
# Setup test files
copy_sample_files "media/sortable" "$SOURCE_DIR"
# Capture pre-test state
capture_state "$SOURCE_DIR" "$TEST_DIR/source_before.txt" "source"
capture_state "$DEST_DIR" "$TEST_DIR/dest_before.txt" "destination"
# Run test
local command="\"$MEDIA_IMPORTER\" -s \"$SOURCE_DIR\" -d \"$DEST_DIR\" -v"
local result=0
run_test_command "$command" "$TEST_DIR/import_log.txt" || result=$?
# Capture post-test state
capture_state "$SOURCE_DIR" "$TEST_DIR/source_after.txt" "source"
capture_state "$DEST_DIR" "$TEST_DIR/dest_after.txt" "destination"
# Generate report
generate_test_report \
"Basic_Functionality" \
"Processing files with valid EXIF data" \
"Verify correct sorting and organization of media files" \
"Sample media files with EXIF data from samples/media/sortable/" \
"$command" \
"$result"
}
# Test Case 1: Unimportable Files Test
run_unimportable_files_test() {
print_color "$GREEN" "=== Running Test 1: Unimportable Files Test ==="
clean_test_dir
create_test_dirs
# Setup test files - mix of sortable and unimportable
copy_sample_files "media/sortable" "$SOURCE_DIR"
copy_sample_files "media/unimportable" "$SOURCE_DIR"
# Capture pre-test state
capture_state "$SOURCE_DIR" "$TEST_DIR/source_before.txt" "source"
capture_state "$DEST_DIR" "$TEST_DIR/dest_before.txt" "destination"
# Run test (without --collect-unimportable flag)
local command="\"$MEDIA_IMPORTER\" -s \"$SOURCE_DIR\" -d \"$DEST_DIR\" -v"
local result=0
run_test_command "$command" "$TEST_DIR/import_log.txt" || result=$?
# Capture post-test state
capture_state "$SOURCE_DIR" "$TEST_DIR/source_after.txt" "source"
capture_state "$DEST_DIR" "$TEST_DIR/dest_after.txt" "destination"
# Generate report
generate_test_report \
"Unimportable_Files_Handling" \
"Testing files without EXIF data in root and subfolders" \
"Verify proper handling of unimportable files without collection flag" \
"Mixed sortable and unimportable files from samples/media/" \
"$command" \
"$result"
}
# Test Case 2: Mixed Content Test
run_mixed_content_test() {
print_color "$GREEN" "=== Running Test 2: Mixed Content Test ==="
clean_test_dir
create_test_dirs
# Setup separate folders for sortable vs unimportable
mkdir -p "$SOURCE_DIR/sortable" "$SOURCE_DIR/unimportable"
copy_sample_files "media/sortable" "$SOURCE_DIR/sortable"
copy_sample_files "media/unimportable" "$SOURCE_DIR/unimportable"
# Capture pre-test state
capture_state "$SOURCE_DIR" "$TEST_DIR/source_before.txt" "source"
capture_state "$DEST_DIR" "$TEST_DIR/dest_before.txt" "destination"
# Run test
local command="\"$MEDIA_IMPORTER\" -s \"$SOURCE_DIR\" -d \"$DEST_DIR\" -v"
local result=0
run_test_command "$command" "$TEST_DIR/import_log.txt" || result=$?
# Capture post-test state
capture_state "$SOURCE_DIR" "$TEST_DIR/source_after.txt" "source"
capture_state "$DEST_DIR" "$TEST_DIR/dest_after.txt" "destination"
# Generate report
generate_test_report \
"Mixed_Content" \
"Processing sortable and unimportable files in separate folders" \
"Verify cleanup behavior for folders with different file types" \
"Separate folders: sortable/ and unimportable/ with respective file types" \
"$command" \
"$result"
}
# Test Case 3: Safety Protections Test
run_safety_protections_test() {
print_color "$GREEN" "=== Running Test 3: Safety Protections Test ==="
clean_test_dir
create_test_dirs
# Setup test files
copy_sample_files "media/sortable" "$SOURCE_DIR"
# Create a file in destination to test exclusion
echo "test file" > "$DEST_DIR/test.txt"
# Capture pre-test state
capture_state "$SOURCE_DIR" "$TEST_DIR/source_before.txt" "source"
capture_state "$DEST_DIR" "$TEST_DIR/dest_before.txt" "destination"
# Run test
local command="\"$MEDIA_IMPORTER\" -s \"$SOURCE_DIR\" -d \"$DEST_DIR\" -v"
local result=0
run_test_command "$command" "$TEST_DIR/import_log.txt" || result=$?
# Capture post-test state
capture_state "$SOURCE_DIR" "$TEST_DIR/source_after.txt" "source"
capture_state "$DEST_DIR" "$TEST_DIR/dest_after.txt" "destination"
# Generate report
generate_test_report \
"Safety_Protections" \
"Testing destination exclusion and move confirmation" \
"Verify data integrity protections prevent data loss" \
"Sample files with pre-existing destination content" \
"$command" \
"$result"
}
# Test Case 4: UTC Conversion Test
run_utc_conversion_test() {
print_color "$GREEN" "=== Running Test 4: UTC Conversion Test ==="
clean_test_dir
create_test_dirs
# Setup test files (assuming QuickTime files are available)
copy_sample_files "media/sortable" "$SOURCE_DIR"
# Capture pre-test state
capture_state "$SOURCE_DIR" "$TEST_DIR/source_before.txt" "source"
capture_state "$DEST_DIR" "$TEST_DIR/dest_before.txt" "destination"
# Run test
local command="\"$MEDIA_IMPORTER\" -s \"$SOURCE_DIR\" -d \"$DEST_DIR\" -v"
local result=0
run_test_command "$command" "$TEST_DIR/import_log.txt" || result=$?
# Capture post-test state
capture_state "$SOURCE_DIR" "$TEST_DIR/source_after.txt" "source"
capture_state "$DEST_DIR" "$TEST_DIR/dest_after.txt" "destination"
# Generate report
generate_test_report \
"UTC_Conversion" \
"Testing UTC timestamp conversion for QuickTime files" \
"Verify correct UTC to local time conversion" \
"QuickTime/Apple media files with UTC timestamps" \
"$command" \
"$result"
}
# Test Case 5: Subdirectory Processing Test
run_subdirectory_processing_test() {
print_color "$GREEN" "=== Running Test 5: Subdirectory Processing Test ==="
clean_test_dir
create_test_dirs
# Create nested directory structure
mkdir -p "$SOURCE_DIR/level1/level2"
copy_sample_files "media/sortable" "$SOURCE_DIR/level1/level2"
# Capture pre-test state
capture_state "$SOURCE_DIR" "$TEST_DIR/source_before.txt" "source"
capture_state "$DEST_DIR" "$TEST_DIR/dest_before.txt" "destination"
# Run test
local command="\"$MEDIA_IMPORTER\" -s \"$SOURCE_DIR\" -d \"$DEST_DIR\" -v"
local result=0
run_test_command "$command" "$TEST_DIR/import_log.txt" || result=$?
# Capture post-test state
capture_state "$SOURCE_DIR" "$TEST_DIR/source_after.txt" "source"
capture_state "$DEST_DIR" "$TEST_DIR/dest_after.txt" "destination"
# Generate report
generate_test_report \
"Subdirectory_Processing" \
"Testing processing of files in nested subdirectories" \
"Verify recursive file discovery and processing" \
"Files in nested directory structure (level1/level2/)" \
"$command" \
"$result"
}
# Test Case 6: Keep Empty Directories Test
run_keep_empty_dirs_test() {
print_color "$GREEN" "=== Running Test 6: Keep Empty Directories Test ==="
clean_test_dir
create_test_dirs
# Create directory structure with some empty dirs
mkdir -p "$SOURCE_DIR/sortable" "$SOURCE_DIR/empty1" "$SOURCE_DIR/empty2"
copy_sample_files "media/sortable" "$SOURCE_DIR/sortable"
# Capture pre-test state
capture_state "$SOURCE_DIR" "$TEST_DIR/source_before.txt" "source"
capture_state "$DEST_DIR" "$TEST_DIR/dest_before.txt" "destination"
# Run test with --keep-empty-dirs
local command="\"$MEDIA_IMPORTER\" -s \"$SOURCE_DIR\" -d \"$DEST_DIR\" --keep-empty-dirs -v"
local result=0
run_test_command "$command" "$TEST_DIR/import_log.txt" || result=$?
# Capture post-test state
capture_state "$SOURCE_DIR" "$TEST_DIR/source_after.txt" "source"
capture_state "$DEST_DIR" "$TEST_DIR/dest_after.txt" "destination"
# Generate report
generate_test_report \
"Keep_Empty_Directories" \
"Testing --keep-empty-dirs functionality" \
"Verify empty directory preservation when flag is used" \
"Directory structure with sortable files and empty directories" \
"$command" \
"$result"
}
# Test Case 7: Source Only Test
run_source_only_test() {
print_color "$GREEN" "=== Running Test 7: Source Only Test ==="
clean_test_dir
create_test_dirs
# Setup test files
copy_sample_files "media/sortable" "$SOURCE_DIR"
# Capture pre-test state
capture_state "$SOURCE_DIR" "$TEST_DIR/source_before.txt" "source"
capture_state "$SOURCE_DIR/sorted" "$TEST_DIR/dest_before.txt" "auto-destination"
# Run test with only source parameter
local command="\"$MEDIA_IMPORTER\" -s \"$SOURCE_DIR\" -v"
local result=0
run_test_command "$command" "$TEST_DIR/import_log.txt" || result=$?
# Capture post-test state
capture_state "$SOURCE_DIR" "$TEST_DIR/source_after.txt" "source"
capture_state "$SOURCE_DIR/sorted" "$TEST_DIR/dest_after.txt" "auto-destination"
# Generate report
generate_test_report \
"Source_Only_Test" \
"Testing processing with only source parameter" \
"Verify automatic creation of sorted subdirectory" \
"Sample media files, no explicit destination specified" \
"$command" \
"$result"
}
# Function to show menu
show_menu() {
echo ""
print_color "$GREEN" "Media Importer Test Runner"
echo "=========================="
echo ""
echo "Available Tests:"
echo "0. Basic Functionality Test"
echo "1. Unimportable Files Test"
echo "2. Mixed Content Test"
echo "3. Safety Protections Test"
echo "4. UTC Conversion Test"
echo "5. Subdirectory Processing Test"
echo "6. Keep Empty Directories Test"
echo "7. Source Only Test"
echo "8. Run All Tests"
echo "q. Quit"
echo ""
echo -n "Select test to run (0-8, q to quit): "
}
# Function to run all tests
run_all_tests() {
print_color "$GREEN" "Running all tests sequentially..."
run_basic_functionality_test
echo ""
run_unimportable_files_test
echo ""
run_mixed_content_test
echo ""
run_safety_protections_test
echo ""
run_utc_conversion_test
echo ""
run_subdirectory_processing_test
echo ""
run_keep_empty_dirs_test
echo ""
run_source_only_test
print_color "$GREEN" "All tests completed!"
}
# Main menu loop
main() {
while true; do
show_menu
read -r choice
case $choice in
0)
run_basic_functionality_test
;;
1)
run_unimportable_files_test
;;
2)
run_mixed_content_test
;;
3)
run_safety_protections_test
;;
4)
run_utc_conversion_test
;;
5)
run_subdirectory_processing_test
;;
6)
run_keep_empty_dirs_test
;;
7)
run_source_only_test
;;
8)
run_all_tests
;;
q|Q)
print_color "$GREEN" "Exiting test runner."
exit 0
;;
*)
print_color "$RED" "Invalid choice. Please select 0-8 or q to quit."
;;
esac
echo ""
echo -n "Press Enter to continue..."
read -r
done
}
# Check if script exists
if [[ ! -f "$MEDIA_IMPORTER" ]]; then
print_color "$RED" "Error: $MEDIA_IMPORTER not found!"
exit 1
fi
# Check if samples directory exists
if [[ ! -d "$SAMPLES_DIR" ]]; then
print_color "$YELLOW" "Warning: $SAMPLES_DIR not found. Some tests may not work properly."
fi
# Run main menu if no arguments provided
if [[ $# -eq 0 ]]; then
main
else
# Handle command line arguments
case "$1" in
"basic"|"0")
run_basic_functionality_test
;;
"unimportable"|"1")
run_unimportable_files_test
;;
"mixed"|"2")
run_mixed_content_test
;;
"safety"|"3")
run_safety_protections_test
;;
"utc"|"4")
run_utc_conversion_test
;;
"subdir"|"5")
run_subdirectory_processing_test
;;
"keep-empty"|"6")
run_keep_empty_dirs_test
;;
"source-only"|"7")
run_source_only_test
;;
"all"|"8")
run_all_tests
;;
"clean")
clean_test_dir
;;
"setup")
create_test_dirs
;;
*)
print_color "$RED" "Unknown test: $1"
echo "Usage: $0 [basic|unimportable|mixed|safety|utc|subdir|keep-empty|source-only|all|clean|setup] or [0-8]"
exit 1
;;
esac
fi