|
1 | 1 | #!/bin/bash |
2 | | -export DESKTOP_FORCE_MOBILE="Y" |
3 | 2 |
|
| 3 | +# Exit on any error |
| 4 | +set -euo pipefail |
| 5 | + |
| 6 | +# Configurations |
| 7 | +export DESKTOP_FORCE_MOBILE="Y" |
| 8 | +MAX_INACTIVITY=${MAX_INACTIVITY:-180} |
| 9 | +MAX_PARALLEL_TESTS=${MAX_PARALLEL_TESTS:-2} |
| 10 | +TEST_TIMEOUT=${TEST_TIMEOUT:-600} |
| 11 | +RETRY_COUNT=${RETRY_COUNT:-1} |
| 12 | + |
| 13 | +# Data directories to clean |
| 14 | +DATA_DIRS=( |
| 15 | + "$HOME/.local/share/com.example.cake_wallet" |
| 16 | + "$HOME/Documents/cake_wallet" |
| 17 | +) |
| 18 | + |
| 19 | +# Global state |
4 | 20 | declare -a targets |
5 | 21 | declare -a passed_tests |
6 | 22 | declare -a failed_tests |
| 23 | +declare -a test_durations |
| 24 | +declare -a test_start_times |
7 | 25 |
|
8 | | -# Max inactivity duration in seconds before marking the test as failed |
9 | | -MAX_INACTIVITY=180 # Adjust as needed (e.g., 300 seconds = 5 minutes) |
| 26 | +# Signal handling |
| 27 | +cleanup() { |
| 28 | + echo "🛑 Received interrupt signal, cleaning up..." |
| 29 | + exit 1 |
| 30 | +} |
10 | 31 |
|
11 | | -# Function to monitor test output and kill the process if inactive |
12 | | -monitor_test() { |
13 | | - local test_pid=$1 |
14 | | - local log_file=$2 |
15 | | - local start_time=$(date +%s) |
| 32 | +trap cleanup SIGINT SIGTERM |
16 | 33 |
|
17 | | - while true; do |
18 | | - sleep 10 |
| 34 | +# Utility functions |
| 35 | +log() { |
| 36 | + echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" |
| 37 | +} |
19 | 38 |
|
20 | | - # Check if the process is still running |
21 | | - if ! kill -0 $test_pid 2>/dev/null; then |
22 | | - break |
23 | | - fi |
| 39 | +error() { |
| 40 | + echo "[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: $1" >&2 |
| 41 | +} |
24 | 42 |
|
25 | | - # Check for log activity: use OS-specific flag for stat command |
26 | | - if [[ "$(uname)" == "Darwin" ]]; then |
27 | | - last_modified=$(stat -f %m "$log_file") |
28 | | - else |
29 | | - last_modified=$(stat -c %Y "$log_file") |
30 | | - fi |
| 43 | +# Format seconds into hours, minutes, seconds |
| 44 | +format_duration() { |
| 45 | + local seconds=$1 |
| 46 | + local hours=$((seconds / 3600)) |
| 47 | + local minutes=$(((seconds % 3600) / 60)) |
| 48 | + local secs=$((seconds % 60)) |
| 49 | + |
| 50 | + if (( hours > 0 )); then |
| 51 | + echo "${hours}h ${minutes}m ${secs}s" |
| 52 | + elif (( minutes > 0 )); then |
| 53 | + echo "${minutes}m ${secs}s" |
| 54 | + else |
| 55 | + echo "${secs}s" |
| 56 | + fi |
| 57 | +} |
| 58 | + |
| 59 | +clean_data_directories() { |
| 60 | + if [[ "${REMOVE_DATA_DIRECTORY:-}" == "Y" ]]; then |
| 61 | + log "Cleaning data directories..." |
| 62 | + for dir in "${DATA_DIRS[@]}"; do |
| 63 | + if [[ -d "$dir" ]]; then |
| 64 | + rm -rf "$dir" || error "Failed to remove $dir" |
| 65 | + fi |
| 66 | + done |
| 67 | + fi |
| 68 | +} |
31 | 69 |
|
32 | | - local current_time=$(date +%s) |
33 | | - if (( current_time - last_modified > MAX_INACTIVITY )); then |
34 | | - echo "❌ Test hung due to inactivity, terminating..." |
35 | | - kill -9 $test_pid |
36 | | - return 1 |
| 70 | +# No longer needed for sequential execution |
| 71 | + |
| 72 | +# Run a single test with retry logic |
| 73 | +run_test() { |
| 74 | + local test_file="$1" |
| 75 | + local test_name=$(basename "$test_file" .dart) |
| 76 | + local retry_count=0 |
| 77 | + |
| 78 | + while (( retry_count <= RETRY_COUNT )); do |
| 79 | + log "Running test: $test_name (attempt $((retry_count + 1)))" |
| 80 | + |
| 81 | + # Clean data directories before each attempt |
| 82 | + clean_data_directories |
| 83 | + |
| 84 | + # Record start time |
| 85 | + local start_time=$(date +%s) |
| 86 | + test_start_times+=("$start_time") |
| 87 | + |
| 88 | + # Run the test in foreground |
| 89 | + if flutter drive \ |
| 90 | + --driver=test_driver/integration_test.dart \ |
| 91 | + --target="$test_file" \ |
| 92 | + --dart-define=CI_BUILD=true; then |
| 93 | + # Calculate duration |
| 94 | + local end_time=$(date +%s) |
| 95 | + local duration=$((end_time - start_time)) |
| 96 | + test_durations+=("$duration") |
| 97 | + |
| 98 | + log "✅ Test passed: $test_name ($(format_duration $duration))" |
| 99 | + passed_tests+=("$test_name") |
| 100 | + return 0 |
| 101 | + else |
| 102 | + # Calculate duration even for failed tests |
| 103 | + local end_time=$(date +%s) |
| 104 | + local duration=$((end_time - start_time)) |
| 105 | + test_durations+=("$duration") |
| 106 | + |
| 107 | + log "❌ Test failed: $test_name ($(format_duration $duration))" |
| 108 | + |
| 109 | + if (( retry_count < RETRY_COUNT )); then |
| 110 | + log "Retrying test: $test_name" |
| 111 | + retry_count=$((retry_count + 1)) |
| 112 | + sleep 5 # Brief pause before retry |
| 113 | + else |
| 114 | + failed_tests+=("$test_name") |
| 115 | + return 1 |
| 116 | + fi |
37 | 117 | fi |
38 | 118 | done |
39 | | - |
40 | | - return 0 |
41 | 119 | } |
42 | 120 |
|
43 | | - |
44 | | -# Collect all Dart test files in the integration_test directory |
45 | | -while IFS= read -r -d $'\0' file; do |
46 | | - targets+=("$file") |
47 | | -done < <(find integration_test/test_suites -name "*.dart" -type f -print0) |
48 | | - |
49 | | -# Run each test and collect results |
50 | | -for target in "${targets[@]}" |
51 | | -do |
52 | | - if [[ "x$REMOVE_DATA_DIRECTORY" == "xY" ]]; then |
53 | | - rm -rf ~/.local/share/com.example.cake_wallet ~/Documents/cake_wallet |
| 121 | +# Main execution |
| 122 | +main() { |
| 123 | + log "Starting integration test runner" |
| 124 | + log "Configuration: RETRY_COUNT=${RETRY_COUNT}" |
| 125 | + |
| 126 | + # Collect all Dart test files from test_suites directory |
| 127 | + while IFS= read -r -d $'\0' file; do |
| 128 | + targets+=("$file") |
| 129 | + done < <(find integration_test/test_suites -name "*.dart" -type f -print0) |
| 130 | + |
| 131 | + if [[ $? -ne 0 ]]; then |
| 132 | + error "Failed to find test files" |
| 133 | + exit 1 |
54 | 134 | fi |
55 | | - echo "Running test: $target" |
56 | | - |
57 | | - # Temporary log file to track activity |
58 | | - log_file=$(mktemp) |
59 | | - |
60 | | - # Run the test in the background and log output |
61 | | - flutter drive \ |
62 | | - --driver=test_driver/integration_test.dart \ |
63 | | - --target="$target" \ |
64 | | - --dart-define=CI_BUILD=true \ |
65 | | - >"$log_file" 2>&1 & |
66 | | - test_pid=$! |
67 | | - |
68 | | - # Monitor the test for inactivity |
69 | | - if monitor_test $test_pid "$log_file"; then |
70 | | - echo "✅ Test passed: $target" |
71 | | - passed_tests+=("$target") |
72 | | - else |
73 | | - echo "❌ Test failed or hung: $target" |
74 | | - failed_tests+=("$target") |
| 135 | + |
| 136 | + if (( ${#targets[@]} == 0 )); then |
| 137 | + error "No test files found in integration_test/test_suites directory" |
| 138 | + exit 1 |
75 | 139 | fi |
76 | 140 |
|
77 | | - # Clean up log file |
78 | | - rm -f "$log_file" |
79 | | -done |
| 141 | + log "Found ${#targets[@]} test files" |
80 | 142 |
|
81 | | -# Provide a summary of test results |
82 | | -echo -e "\n===== Test Summary =====" |
83 | | -if [ ${#passed_tests[@]} -gt 0 ]; then |
84 | | - echo "✅ Passed Tests:" |
85 | | - for test in "${passed_tests[@]}"; do |
86 | | - echo " - $test" |
| 143 | + # Record overall start time |
| 144 | + local overall_start_time=$(date +%s) |
| 145 | + |
| 146 | + # Run tests sequentially |
| 147 | + for target in "${targets[@]}"; do |
| 148 | + run_test "$target" |
87 | 149 | done |
88 | | -fi |
89 | 150 |
|
90 | | -if [ ${#failed_tests[@]} -gt 0 ]; then |
91 | | - echo -e "\n❌ Failed Tests:" |
92 | | - for test in "${failed_tests[@]}"; do |
93 | | - echo " - $test" |
94 | | - done |
95 | | - # Exit with a non-zero status to indicate failure |
96 | | - exit 1 |
97 | | -else |
98 | | - echo -e "\n🎉 All tests passed successfully!" |
99 | | -fi |
| 151 | + # Calculate total duration |
| 152 | + local overall_end_time=$(date +%s) |
| 153 | + local total_duration=$((overall_end_time - overall_start_time)) |
| 154 | + |
| 155 | + # Generate summary |
| 156 | + echo -e "\n===== Test Summary =====" |
| 157 | + echo "Total tests: ${#targets[@]}" |
| 158 | + echo "Passed: ${#passed_tests[@]}" |
| 159 | + echo "Failed: ${#failed_tests[@]}" |
| 160 | + echo "Total duration: $(format_duration $total_duration)" |
| 161 | + |
| 162 | + if (( ${#passed_tests[@]} > 0 )); then |
| 163 | + echo -e "\n✅ Passed Tests:" |
| 164 | + for i in $(seq 0 $((${#passed_tests[@]} - 1))); do |
| 165 | + local test_name="${passed_tests[$i]}" |
| 166 | + local duration="${test_durations[$i]}" |
| 167 | + echo " - $test_name ($(format_duration $duration))" |
| 168 | + done |
| 169 | + fi |
| 170 | + |
| 171 | + if (( ${#failed_tests[@]} > 0 )); then |
| 172 | + echo -e "\n❌ Failed Tests:" |
| 173 | + for i in $(seq 0 $((${#failed_tests[@]} - 1))); do |
| 174 | + local test_name="${failed_tests[$i]}" |
| 175 | + local duration="${test_durations[$i]}" |
| 176 | + echo " - $test_name ($(format_duration $duration))" |
| 177 | + done |
| 178 | + exit 1 |
| 179 | + else |
| 180 | + echo -e "\n🎉 All tests passed successfully!" |
| 181 | + fi |
| 182 | +} |
| 183 | + |
| 184 | +# Run main function |
| 185 | +main "$@" |
0 commit comments