Juan Pablo Conde | 6eb0d1e | 2023-12-08 13:52:21 -0600 | [diff] [blame] | 1 | #!/usr/bin/env bash |
| 2 | # |
| 3 | # Copyright (c) 2024 Arm Limited. All rights reserved. |
| 4 | # |
| 5 | # SPDX-License-Identifier: BSD-3-Clause |
| 6 | # |
| 7 | |
| 8 | # Runs the built unit tests |
| 9 | |
| 10 | set -e |
| 11 | |
| 12 | ci_root="$(readlink -f "$(dirname "$0")/..")" |
| 13 | source "$ci_root/script/run_common.sh" |
| 14 | source "$ci_root/utils.sh" |
| 15 | |
Juan Pablo Conde | 3b0380c | 2024-01-13 13:40:59 -0600 | [diff] [blame] | 16 | export -f launch |
| 17 | |
Juan Pablo Conde | 6eb0d1e | 2023-12-08 13:52:21 -0600 | [diff] [blame] | 18 | artefacts="${artefacts-$workspace/artefacts}" |
| 19 | |
| 20 | run_root="$workspace/unit_tests/run" |
Juan Pablo Conde | 3b0380c | 2024-01-13 13:40:59 -0600 | [diff] [blame] | 21 | pid_dir="$workspace/unit_tests/pids" |
Juan Pablo Conde | 6eb0d1e | 2023-12-08 13:52:21 -0600 | [diff] [blame] | 22 | |
| 23 | mkdir -p "$run_root" |
Juan Pablo Conde | 3b0380c | 2024-01-13 13:40:59 -0600 | [diff] [blame] | 24 | mkdir -p "$pid_dir" |
Juan Pablo Conde | 6eb0d1e | 2023-12-08 13:52:21 -0600 | [diff] [blame] | 25 | |
| 26 | export run_root |
Juan Pablo Conde | 3b0380c | 2024-01-13 13:40:59 -0600 | [diff] [blame] | 27 | export pid_dir |
Juan Pablo Conde | 6eb0d1e | 2023-12-08 13:52:21 -0600 | [diff] [blame] | 28 | |
Edward Potapov | db31e70 | 2025-06-30 16:28:40 -0500 | [diff] [blame^] | 29 | export tfut_root="${tfut_root:-$workspace/tf-a-unit-tests}" |
Juan Pablo Conde | 6eb0d1e | 2023-12-08 13:52:21 -0600 | [diff] [blame] | 30 | |
Juan Pablo Conde | 3b0380c | 2024-01-13 13:40:59 -0600 | [diff] [blame] | 31 | kill_and_reap() { |
| 32 | local gid |
| 33 | # Kill an active process. Ignore errors |
| 34 | [ "$1" ] || return 0 |
| 35 | kill -0 "$1" &>/dev/null || return 0 |
| 36 | |
| 37 | # Kill the children |
| 38 | kill -- "-$1" &>/dev/null || true |
| 39 | # Kill the group |
| 40 | { gid="$(awk '{print $5}' < /proc/$1/stat)";} 2>/dev/null || return |
| 41 | kill -SIGTERM -- "-$gid" &>/dev/null || true |
| 42 | wait "$gid" &>/dev/null || true |
| 43 | } |
| 44 | |
| 45 | # Perform clean up and ignore errors |
| 46 | cleanup() { |
| 47 | local pid |
| 48 | local sig |
| 49 | |
| 50 | pushd "$pid_dir" |
| 51 | set +e |
| 52 | |
| 53 | sig=${1:-SIGINT} |
| 54 | echo "signal received: $sig" |
| 55 | |
| 56 | if [ "$sig" != "EXIT" ]; then |
| 57 | # Kill all background processes so far and wait for them |
| 58 | while read pid; do |
| 59 | pid="$(cat $pid)" |
| 60 | echo $pid |
| 61 | |
| 62 | kill_and_reap "$pid" |
| 63 | |
| 64 | done < <(find -name '*.pid') |
| 65 | fi |
| 66 | |
| 67 | popd |
| 68 | } |
| 69 | |
Edward Potapov | db31e70 | 2025-06-30 16:28:40 -0500 | [diff] [blame^] | 70 | # Check coverage and make reports |
| 71 | run_coverage() { |
| 72 | if [ -f "tfut_coverage.txt" ]; then |
| 73 | COVERAGE="ON" |
| 74 | else |
| 75 | COVERAGE="OFF" |
| 76 | fi |
| 77 | |
| 78 | # Switch to the tfut root directory to check for coverage |
| 79 | pushd "$tfut_root/build" |
| 80 | if [ "$COVERAGE" = "ON" ]; then |
| 81 | echo "Generating coverage report..." |
| 82 | make coverage_report |
| 83 | cp -r ./tf-a-unit-tests-coverage "$workspace/unit_tests/" |
| 84 | cp -r ./trusted-firmware-a-coverage "$workspace/unit_tests/" |
| 85 | mkdir "$workspace/trace_report/" |
| 86 | cp -r ./trusted-firmware-a-coverage/* "$workspace/trace_report/" |
| 87 | cp ./coverage.info "$workspace/trace_report/" |
| 88 | cat > "$workspace/config_file.json" <<EOF |
| 89 | { |
| 90 | "configuration": { |
| 91 | "sources": [ |
| 92 | { |
| 93 | "type": "git", |
| 94 | "URL": "https://review.trustedfirmware.org/TF-A/trusted-firmware-a", |
| 95 | "LOCATION": "trusted-firmware-a" |
| 96 | } |
| 97 | ] |
| 98 | } |
| 99 | } |
| 100 | EOF |
| 101 | else |
| 102 | echo "Code coverage is disabled." |
| 103 | fi |
| 104 | popd |
| 105 | } |
| 106 | |
Juan Pablo Conde | 3b0380c | 2024-01-13 13:40:59 -0600 | [diff] [blame] | 107 | # Cleanup actions |
| 108 | trap_with_sig cleanup SIGINT SIGHUP SIGTERM EXIT |
Juan Pablo Conde | 6eb0d1e | 2023-12-08 13:52:21 -0600 | [diff] [blame] | 109 | |
| 110 | run_test() { |
| 111 | test="${1:?}" |
| 112 | echo "Running test $test..." |
| 113 | "./$@" |
| 114 | } |
| 115 | |
| 116 | export -f run_test |
| 117 | |
| 118 | # Accept BIN_MODE from environment, or default to release. If bin_mode is set |
| 119 | # and non-empty (intended to be set from command line), that takes precedence. |
| 120 | pkg_bin_mode="${BIN_MODE:-release}" |
| 121 | bin_mode="${bin_mode:-$pkg_bin_mode}" |
| 122 | |
| 123 | # Change directory so that all binaries can be accessed realtive to where they |
| 124 | # lie |
| 125 | run_cwd="$artefacts/$bin_mode" |
| 126 | cd "$run_cwd" |
| 127 | |
| 128 | run_sh="$run_root/run.sh" |
| 129 | |
| 130 | #Generate run.sh file |
| 131 | echo "echo \"Running unit tests\"" > "$run_sh" |
| 132 | echo "pwd" >> "$run_sh" |
| 133 | cat "tfut_artefacts.txt" | while read test; do |
| 134 | if upon "$test_run"; then |
| 135 | echo "run_test $test \$@" >> "$run_sh" |
Juan Pablo Conde | 3b0380c | 2024-01-13 13:40:59 -0600 | [diff] [blame] | 136 | else |
| 137 | echo "name=\"$test\" launch run_test $test \$@ " \ |
| 138 | "&> \"$run_root/${test}_output.txt\" &" >> "$run_sh" |
Juan Pablo Conde | 6eb0d1e | 2023-12-08 13:52:21 -0600 | [diff] [blame] | 139 | fi |
| 140 | done |
| 141 | chmod +x "$run_sh" |
| 142 | |
| 143 | # Run the unit tests directly |
| 144 | if upon "$test_run"; then |
| 145 | echo |
| 146 | "$run_sh" "$@" -v -c |
Edward Potapov | db31e70 | 2025-06-30 16:28:40 -0500 | [diff] [blame^] | 147 | run_coverage |
Juan Pablo Conde | 6eb0d1e | 2023-12-08 13:52:21 -0600 | [diff] [blame] | 148 | exit 0 |
| 149 | fi |
Juan Pablo Conde | 3b0380c | 2024-01-13 13:40:59 -0600 | [diff] [blame] | 150 | |
| 151 | # For an automated run, export a known variable so that we can identify stale |
| 152 | # processes spawned by Trusted Firmware CI by inspecting its environment. |
| 153 | export TRUSTED_FIRMWARE_CI="1" |
| 154 | |
| 155 | # Otherwise, run tests in background and monitor them. |
| 156 | if upon "$jenkins_run"; then |
| 157 | "$run_sh" "$@" -ojunit -v |
| 158 | else |
| 159 | "$run_sh" "$@" -c -v |
| 160 | fi |
Edward Potapov | db31e70 | 2025-06-30 16:28:40 -0500 | [diff] [blame^] | 161 | run_coverage |
Juan Pablo Conde | 3b0380c | 2024-01-13 13:40:59 -0600 | [diff] [blame] | 162 | batch_pid=$! |
| 163 | |
| 164 | # Wait for all children. Note that the wait below is *not* a timed wait. |
| 165 | result=0 |
| 166 | |
| 167 | set +e |
| 168 | pushd "$pid_dir" |
| 169 | |
| 170 | timeout=3600 |
| 171 | |
| 172 | echo |
| 173 | |
| 174 | while :; do |
| 175 | readarray -d '' all < <(find "${pid_dir}" -name '*.pid' -print0) |
| 176 | readarray -d '' succeeded < <(find "${pid_dir}" -name '*.success' -print0) |
| 177 | readarray -d '' failed < <(find "${pid_dir}" -name '*.fail' -print0) |
| 178 | |
| 179 | all=("${all[@]##${pid_dir}/}") |
| 180 | all=("${all[@]%%.pid}") |
| 181 | |
| 182 | succeeded=("${succeeded[@]##${pid_dir}/}") |
| 183 | succeeded=("${succeeded[@]%%.success}") |
| 184 | |
| 185 | failed=("${failed[@]##${pid_dir}/}") |
| 186 | failed=("${failed[@]%%.fail}") |
| 187 | |
| 188 | completed=("${succeeded[@]}" "${failed[@]}") |
| 189 | |
| 190 | readarray -t remaining < <( \ |
| 191 | comm -23 \ |
| 192 | <(printf '%s\n' "${all[@]}" | sort) \ |
| 193 | <(printf '%s\n' "${completed[@]}" | sort) \ |
| 194 | ) |
| 195 | |
| 196 | if [ ${#remaining[@]} = 0 ]; then |
| 197 | break |
| 198 | fi |
| 199 | |
| 200 | if [ ${timeout} = 0 ]; then |
| 201 | echo "- Timeout exceeded! Killing all processes..." |
| 202 | |
| 203 | cleanup |
| 204 | fi |
| 205 | |
| 206 | timeout=$((${timeout} - 5)) && sleep 5 |
| 207 | done |
| 208 | |
| 209 | echo |
| 210 | |
| 211 | if [ ${#failed[@]} != 0 ]; then |
| 212 | echo "${#failed[@]} tests failed:" |
| 213 | echo |
| 214 | |
| 215 | for test in "${failed[@]}"; do |
| 216 | echo " - Test ${test}: ${test}_output.txt" |
| 217 | done |
| 218 | |
| 219 | echo |
| 220 | |
| 221 | result=1 |
| 222 | fi |
| 223 | |
| 224 | popd |
| 225 | |
| 226 | if [ "$result" -eq 0 ]; then |
| 227 | echo "Unit testing success!" |
| 228 | else |
| 229 | echo "Unit testing failed!" |
| 230 | fi |
| 231 | |
| 232 | if upon "$jenkins_run"; then |
| 233 | echo |
| 234 | echo "Artefacts location: $BUILD_URL." |
| 235 | echo |
| 236 | fi |
| 237 | |
| 238 | exit "$result" |