Leonardo Sandoval | 9dfdd1b | 2020-08-06 17:08:11 -0500 | [diff] [blame] | 1 | #!/usr/bin/env bash |
Fathi Boudra | 422bf77 | 2019-12-02 11:10:16 +0200 | [diff] [blame] | 2 | # |
Zelalem | 219df41 | 2020-05-17 19:21:20 -0500 | [diff] [blame] | 3 | # Copyright (c) 2019-2020, Arm Limited. All rights reserved. |
Fathi Boudra | 422bf77 | 2019-12-02 11:10:16 +0200 | [diff] [blame] | 4 | # |
| 5 | # SPDX-License-Identifier: BSD-3-Clause |
| 6 | # |
| 7 | |
| 8 | set -e |
| 9 | |
| 10 | in_red() { |
| 11 | echo "$(tput setaf 1)${1:?}$(tput sgr0)" |
| 12 | } |
| 13 | export -f in_red |
| 14 | |
| 15 | in_green() { |
| 16 | echo "$(tput setaf 2)${1:?}$(tput sgr0)" |
| 17 | } |
| 18 | export -f in_green |
| 19 | |
| 20 | in_yellow() { |
| 21 | echo "$(tput setaf 3)${1:?}$(tput sgr0)" |
| 22 | } |
| 23 | export -f in_yellow |
| 24 | |
| 25 | print_success() { |
| 26 | in_green "$1: SUCCESS" |
| 27 | } |
| 28 | export -f print_success |
| 29 | |
| 30 | print_failure() { |
| 31 | in_red "$1: FAILURE" |
| 32 | } |
| 33 | export -f print_failure |
| 34 | |
| 35 | print_unstable() { |
| 36 | in_yellow "$1: UNSTABLE" |
| 37 | } |
| 38 | export -f print_unstable |
| 39 | |
| 40 | gen_makefile() { |
| 41 | local num="$(find -name "*.test" -type f | wc -l)" |
| 42 | local i=0 |
| 43 | |
| 44 | cat <<EOF >Makefile |
| 45 | SHELL=/bin/bash |
| 46 | |
| 47 | all: |
| 48 | |
| 49 | EOF |
| 50 | |
| 51 | # If we're using local checkouts for either TF or TFTF, we must |
| 52 | # serialise builds |
| 53 | while [ "$i" -lt "$num" ]; do |
| 54 | { |
| 55 | printf "all: %03d_run %03d_build\n" "$i" "$i" |
| 56 | if upon "$serialize_builds" && [ "$i" -gt 0 ]; then |
| 57 | printf "%03d_build: %03d_build\n" "$i" "$((i - 1))" |
| 58 | fi |
| 59 | echo |
| 60 | } >>Makefile |
| 61 | let "++i" |
| 62 | done |
| 63 | |
| 64 | cat <<EOF >>Makefile |
| 65 | |
| 66 | %_run: %_build |
| 67 | @run_one_test "\$@" |
| 68 | |
| 69 | %_build: |
| 70 | @run_one_test "\$@" |
| 71 | EOF |
| 72 | } |
| 73 | |
| 74 | # This function is invoked from the Makefile. Descriptor 5 points to the active |
| 75 | # terminal. |
| 76 | run_one_test() { |
| 77 | id="${1%%_*}" |
| 78 | action="${1##*_}" |
| 79 | test_file="$(find -name "$id*.test" -printf "%f\n")" |
| 80 | |
| 81 | mkdir -p "$id" |
| 82 | |
| 83 | # Copy the test_file into the workspace directory with the name |
| 84 | # TEST_DESC, just like Jenkins would. |
| 85 | export TEST_DESC="$(basename "$test_file")" |
| 86 | cp "$test_file" "$id/TEST_DESC" |
| 87 | |
Zelalem | 219df41 | 2020-05-17 19:21:20 -0500 | [diff] [blame] | 88 | workspace="$id" test_desc="$test_file" cc_enable="$cc_enable" "$ci_root/script/parse_test.sh" |
Fathi Boudra | 422bf77 | 2019-12-02 11:10:16 +0200 | [diff] [blame] | 89 | |
| 90 | set -a |
| 91 | source "$id/env" |
| 92 | set +a |
| 93 | |
| 94 | # Makefiles don't like commas and colons in file names. We therefore |
| 95 | # replace them with _ |
| 96 | config_subst="$(echo "$TEST_CONFIG" | tr ',:' '_')" |
| 97 | config_string="$id: $TEST_GROUP/$TEST_CONFIG" |
| 98 | workspace="$workspace/$TEST_GROUP/$config_subst" |
| 99 | mkdir -p "$workspace" |
| 100 | |
| 101 | log_file="$workspace/artefacts/build.log" |
| 102 | if [ "$parallel" -gt 1 ]; then |
| 103 | console_file="$workspace/console.log" |
| 104 | exec 6>>"$console_file" |
| 105 | else |
| 106 | exec 6>&5 |
| 107 | fi |
| 108 | |
| 109 | # Unset make flags for build script |
| 110 | MAKEFLAGS= |
| 111 | |
Zelalem | 219df41 | 2020-05-17 19:21:20 -0500 | [diff] [blame] | 112 | if [ $import_cc -eq 1 ]; then |
| 113 | # Path to plugin if there is no local reference |
| 114 | cc_path_spec=$workspace/cc_plugin |
| 115 | fi |
| 116 | |
Fathi Boudra | 422bf77 | 2019-12-02 11:10:16 +0200 | [diff] [blame] | 117 | case "$action" in |
| 118 | "build") |
| 119 | echo "building: $config_string" >&5 |
Zelalem | 219df41 | 2020-05-17 19:21:20 -0500 | [diff] [blame] | 120 | if ! ccpathspec="$cc_path_spec" bash $minus_x "$ci_root/script/build_package.sh" \ |
Fathi Boudra | 422bf77 | 2019-12-02 11:10:16 +0200 | [diff] [blame] | 121 | >&6 2>&1; then |
| 122 | { |
| 123 | print_failure "$config_string (build)" |
| 124 | if [ "$console_file" ]; then |
| 125 | echo " see $console_file" |
| 126 | fi |
| 127 | } >&5 |
| 128 | exit 1 |
| 129 | fi |
| 130 | ;; |
| 131 | |
| 132 | "run") |
Javier Almansa Sobrino | 412d361 | 2020-05-22 17:53:12 +0100 | [diff] [blame] | 133 | # Local runs for FVP or arm_fpga unless asked not to |
Fathi Boudra | 422bf77 | 2019-12-02 11:10:16 +0200 | [diff] [blame] | 134 | if echo "$RUN_CONFIG" | grep -q "^fvp" && \ |
| 135 | not_upon "$skip_runs"; then |
| 136 | echo "running: $config_string" >&5 |
Zelalem | 219df41 | 2020-05-17 19:21:20 -0500 | [diff] [blame] | 137 | if [ -n "$cc_enable" ]; then |
| 138 | # Enable of code coverage during run |
| 139 | if cc_enable="$cc_enable" trace_file_prefix=tr \ |
| 140 | coverage_trace_plugin=$cc_path_spec/scripts/tools/code_coverage/fastmodel_baremetal/bmcov/model-plugin/CoverageTrace.so \ |
| 141 | bash $minus_x "$ci_root/script/run_package.sh" \ |
Fathi Boudra | 422bf77 | 2019-12-02 11:10:16 +0200 | [diff] [blame] | 142 | >&6 2>&1; then |
Zelalem | 219df41 | 2020-05-17 19:21:20 -0500 | [diff] [blame] | 143 | if grep -q -e "--BUILD UNSTABLE--" \ |
Fathi Boudra | 422bf77 | 2019-12-02 11:10:16 +0200 | [diff] [blame] | 144 | "$log_file"; then |
Zelalem | 219df41 | 2020-05-17 19:21:20 -0500 | [diff] [blame] | 145 | print_unstable "$config_string" >&5 |
| 146 | else |
| 147 | print_success "$config_string" >&5 |
| 148 | if [ -d "$workspace/artefacts/release" ] && \ |
| 149 | [ -f "$workspace/artefacts/release/tr-FVP_Base_RevC_2xAEMv8A.cluster0.cpu0.log" ]; then |
| 150 | cp $workspace/artefacts/release/*.log $workspace/artefacts/debug |
| 151 | fi |
| 152 | # Setting environmental variables for run of code coverage |
| 153 | OBJDUMP=$TOOLCHAIN/bin/aarch64-none-elf-objdump \ |
| 154 | READELF=$TOOLCHAIN/bin/aarch64-none-elf-readelf \ |
| 155 | ELF_FOLDER=$workspace/artefacts/debug \ |
| 156 | TRACE_FOLDER=$workspace/artefacts/debug \ |
| 157 | workspace=$workspace \ |
| 158 | TRACE_PREFIX=tr python \ |
| 159 | $cc_path_spec/scripts/tools/code_coverage/fastmodel_baremetal/bmcov/report/gen-coverage-report.py --config \ |
| 160 | $cc_path_spec/scripts/tools/code_coverage/fastmodel_baremetal/bmcov/report/config_atf.py |
| 161 | fi |
| 162 | exit 0 |
Fathi Boudra | 422bf77 | 2019-12-02 11:10:16 +0200 | [diff] [blame] | 163 | else |
Zelalem | 219df41 | 2020-05-17 19:21:20 -0500 | [diff] [blame] | 164 | { |
| 165 | print_failure "$config_string (run)" |
| 166 | if [ "$console_file" ]; then |
| 167 | echo " see $console_file" |
| 168 | fi |
| 169 | } >&5 |
| 170 | exit 1 |
Fathi Boudra | 422bf77 | 2019-12-02 11:10:16 +0200 | [diff] [blame] | 171 | fi |
Fathi Boudra | 422bf77 | 2019-12-02 11:10:16 +0200 | [diff] [blame] | 172 | else |
Zelalem | 219df41 | 2020-05-17 19:21:20 -0500 | [diff] [blame] | 173 | if bash $minus_x "$ci_root/script/run_package.sh" \ |
| 174 | >&6 2>&1; then |
| 175 | if grep -q -e "--BUILD UNSTABLE--" \ |
| 176 | "$log_file"; then |
| 177 | print_unstable "$config_string" >&5 |
| 178 | else |
| 179 | print_success "$config_string" >&5 |
| 180 | fi |
| 181 | exit 0 |
| 182 | else |
| 183 | { |
| 184 | print_failure "$config_string (run)" |
| 185 | if [ "$console_file" ]; then |
| 186 | echo " see $console_file" |
| 187 | fi |
| 188 | } >&5 |
| 189 | exit 1 |
Fathi Boudra | 422bf77 | 2019-12-02 11:10:16 +0200 | [diff] [blame] | 190 | fi |
Fathi Boudra | 422bf77 | 2019-12-02 11:10:16 +0200 | [diff] [blame] | 191 | fi |
| 192 | else |
Javier Almansa Sobrino | 412d361 | 2020-05-22 17:53:12 +0100 | [diff] [blame] | 193 | # Local runs for arm_fpga platform |
| 194 | if echo "$RUN_CONFIG" | grep -q "^arm_fpga" && \ |
| 195 | not_upon "$skip_runs"; then |
| 196 | echo "running: $config_string" >&5 |
| 197 | if bash $minus_x "$ci_root/script/test_fpga_payload.sh" \ |
| 198 | >&6 2>&1; then |
| 199 | if grep -q -e "--BUILD UNSTABLE--" \ |
| 200 | "$log_file"; then |
| 201 | print_unstable "$config_string" >&5 |
| 202 | else |
| 203 | print_success "$config_string" >&5 |
| 204 | fi |
| 205 | exit 0 |
| 206 | else |
| 207 | { |
| 208 | print_failure "$config_string (run)" |
| 209 | if [ "$console_file" ]; then |
| 210 | echo " see $console_file" |
| 211 | fi |
| 212 | } >&5 |
| 213 | exit 1 |
| 214 | fi |
Fathi Boudra | 422bf77 | 2019-12-02 11:10:16 +0200 | [diff] [blame] | 215 | else |
Javier Almansa Sobrino | 412d361 | 2020-05-22 17:53:12 +0100 | [diff] [blame] | 216 | if grep -q -e "--BUILD UNSTABLE--" \ |
| 217 | "$log_file"; then |
| 218 | print_unstable "$config_string (not run)" >&5 |
| 219 | else |
| 220 | print_success "$config_string (not run)" >&5 |
| 221 | fi |
| 222 | exit 0 |
Fathi Boudra | 422bf77 | 2019-12-02 11:10:16 +0200 | [diff] [blame] | 223 | fi |
Fathi Boudra | 422bf77 | 2019-12-02 11:10:16 +0200 | [diff] [blame] | 224 | fi |
| 225 | ;; |
| 226 | |
| 227 | *) |
| 228 | in_red "Invalid action: $action!" >&5 |
| 229 | exit 1 |
| 230 | ;; |
| 231 | esac |
| 232 | } |
| 233 | export -f run_one_test |
| 234 | |
| 235 | workspace="${workspace:?}" |
| 236 | ci_root="$(readlink -f "$(dirname "$0")/..")" |
| 237 | |
| 238 | # If this script was invoked with bash -x, have subsequent build/run invocations |
| 239 | # to use -x as well. |
| 240 | if echo "$-" | grep -q "x"; then |
| 241 | export minus_x="-x" |
| 242 | fi |
| 243 | |
Leonardo Sandoval | 8f9cea6 | 2020-07-10 11:08:55 -0500 | [diff] [blame] | 244 | # if test_groups variable is not present, check if it can be formed at least from 'test_group' and 'tf_config' |
| 245 | # environment variables |
| 246 | if [ -z "${test_groups}" ]; then |
| 247 | if [ -n "${test_group}" -a -n "${tf_config}" ]; then |
| 248 | |
| 249 | # default the rest to nil if not present |
| 250 | tftf_config="${tftf_config:-nil}" |
| 251 | scp_config="${scp_config:-nil}" |
| 252 | scp_tools="${scp_tools:-nil}" |
| 253 | run_config="${run_config:-nil}" |
| 254 | |
| 255 | # constuct the 'long form' so it takes into account all possible configurations |
| 256 | tg=$(printf "%s/%s,%s,%s,%s:%s" "${test_group}" "${tf_config}" "${tftf_config}" "${scp_config}" "${scp_tools}" "${run_config}") |
| 257 | |
| 258 | # trim any ',nil:' from it |
| 259 | tg="${tg/,nil:/:}" tg="${tg/,nil:/:}"; tg="${tg/,nil:/:}" |
| 260 | |
| 261 | # finally exported |
| 262 | export test_groups="${tg}" |
| 263 | fi |
| 264 | fi |
| 265 | |
Fathi Boudra | 422bf77 | 2019-12-02 11:10:16 +0200 | [diff] [blame] | 266 | # For a local run, when some variables as specified as "?", launch zenity to |
| 267 | # prompt for test config via. GUI. If it's "??", then choose a directory. |
| 268 | if [ "$test_groups" = "?" -o "$test_groups" = "??" ]; then |
| 269 | zenity_opts=( |
| 270 | --file-selection |
| 271 | --filename="$ci_root/group/README" |
| 272 | --multiple |
| 273 | --title "Choose test config" |
| 274 | ) |
| 275 | |
| 276 | if [ "$test_groups" = "??" ]; then |
| 277 | zenity_opts+=("--directory") |
| 278 | fi |
| 279 | |
| 280 | # In case of multiple selections, zenity returns absolute paths of files |
| 281 | # separated by '|'. We remove the pipe characters, and make the paths |
| 282 | # relative to the group directory. |
| 283 | selections="$(cd "$ci_root"; zenity ${zenity_opts[*]})" |
| 284 | test_groups="$(echo "$selections" | tr '|' ' ')" |
| 285 | test_groups="$(echo "$test_groups" | sed "s#$ci_root/group/##g")" |
| 286 | fi |
| 287 | |
| 288 | test_groups="${test_groups:?}" |
| 289 | local_count=0 |
| 290 | |
| 291 | if [ -z "$tf_root" ]; then |
| 292 | in_red "NOTE: NOT using local work tree for TF" |
| 293 | else |
| 294 | tf_root="$(readlink -f $tf_root)" |
| 295 | tf_refspec= |
| 296 | in_green "Using local work tree for TF" |
| 297 | let "++local_count" |
| 298 | fi |
| 299 | |
| 300 | if [ -z "$tftf_root" ]; then |
| 301 | in_red "NOTE: NOT using local work tree for TFTF" |
| 302 | tforg_user="${tforg_user:?}" |
| 303 | else |
| 304 | tftf_root="$(readlink -f $tftf_root)" |
Zelalem | 219df41 | 2020-05-17 19:21:20 -0500 | [diff] [blame] | 305 | tftf_refspec= |
Fathi Boudra | 422bf77 | 2019-12-02 11:10:16 +0200 | [diff] [blame] | 306 | in_green "Using local work tree for TFTF" |
| 307 | let "++local_count" |
| 308 | fi |
| 309 | |
| 310 | if [ -z "$scp_root" ]; then |
| 311 | in_red "NOTE: NOT using local work tree for SCP" |
| 312 | else |
| 313 | scp_root="$(readlink -f $scp_root)" |
| 314 | scp_refspec= |
| 315 | in_green "Using local work tree for SCP" |
| 316 | let "++local_count" |
| 317 | fi |
| 318 | |
Zelalem | 219df41 | 2020-05-17 19:21:20 -0500 | [diff] [blame] | 319 | if [ -n "$cc_enable" ]; then |
| 320 | in_green "Code Coverage enabled" |
| 321 | if [ -z "$TOOLCHAIN" ]; then |
| 322 | in_red "TOOLCHAIN not set for code coverage: ex: export TOOLCHAIN=<path to toolchain>/gcc-arm-<gcc version>-x86_64-aarch64-none-elf" |
| 323 | exit 1 |
| 324 | fi |
| 325 | if [ -n "$cc_path" ]; then |
| 326 | in_green "Code coverage plugin path specified" |
| 327 | cc_path_spec=$cc_path |
| 328 | import_cc=0 |
| 329 | else |
| 330 | in_red "Code coverage plugin path not specified" |
| 331 | cc_path_spec="$workspace/cc_plugin" |
| 332 | import_cc=1 |
| 333 | fi |
Jimmy Brisson | 4347d8a | 2020-07-24 10:26:16 -0500 | [diff] [blame] | 334 | else |
| 335 | in_green "Code coverage disabled" |
| 336 | import_cc=1 |
Zelalem | 219df41 | 2020-05-17 19:21:20 -0500 | [diff] [blame] | 337 | fi |
| 338 | |
Fathi Boudra | 422bf77 | 2019-12-02 11:10:16 +0200 | [diff] [blame] | 339 | # User preferences |
Javier Almansa Sobrino | e836318 | 2020-11-10 16:40:53 +0000 | [diff] [blame^] | 340 | [ "$connect_debugger" ] && [ "$connect_debugger" -eq 1 ] && user_connect_debugger=1 |
| 341 | user_test_run="${user_connect_debugger:-$test_run}" |
Fathi Boudra | 422bf77 | 2019-12-02 11:10:16 +0200 | [diff] [blame] | 342 | user_dont_clean="$dont_clean" |
| 343 | user_keep_going="$keep_going" |
| 344 | user_primary_live="$primary_live" |
Javier Almansa Sobrino | e836318 | 2020-11-10 16:40:53 +0000 | [diff] [blame^] | 345 | user_connect_debugger="${user_connect_debugger:-0}" |
Fathi Boudra | 422bf77 | 2019-12-02 11:10:16 +0200 | [diff] [blame] | 346 | |
| 347 | export ci_root |
| 348 | export dont_clean=0 |
| 349 | export local_ci=1 |
| 350 | export parallel |
| 351 | export test_run=0 |
| 352 | export primary_live=0 |
Zelalem | 219df41 | 2020-05-17 19:21:20 -0500 | [diff] [blame] | 353 | export cc_path_spec |
| 354 | export import_cc |
Javier Almansa Sobrino | e836318 | 2020-11-10 16:40:53 +0000 | [diff] [blame^] | 355 | export connect_debugger="$user_connect_debugger" |
Fathi Boudra | 422bf77 | 2019-12-02 11:10:16 +0200 | [diff] [blame] | 356 | |
| 357 | rm -rf "$workspace" |
| 358 | mkdir -p "$workspace" |
| 359 | |
| 360 | source "$ci_root/utils.sh" |
| 361 | |
| 362 | # SCP is not cloned by default |
| 363 | export clone_scp |
| 364 | export scp_root |
| 365 | if not_upon "$scp_root" && upon "$clone_scp"; then |
| 366 | clone_scp=1 |
| 367 | else |
| 368 | clone_scp=0 |
| 369 | fi |
| 370 | |
Zelalem | 219df41 | 2020-05-17 19:21:20 -0500 | [diff] [blame] | 371 | # Enable of code coverage and whether there is a local plugin |
| 372 | if upon "$cc_enable" && not_upon "$cc_path"; then |
| 373 | no_cc_t=1 |
| 374 | else |
| 375 | no_cc_t=0 |
| 376 | fi |
| 377 | |
| 378 | # Use clone_repos.sh to clone and share repositories that aren't local. |
| 379 | no_tf="$tf_root" no_tftf="$tftf_root" no_ci="$ci_root" no_cc="$import_cc" \ |
Fathi Boudra | 422bf77 | 2019-12-02 11:10:16 +0200 | [diff] [blame] | 380 | bash $minus_x "$ci_root/script/clone_repos.sh" |
| 381 | |
| 382 | set -a |
| 383 | source "$workspace/env" |
| 384 | set +a |
| 385 | |
| 386 | if [ "$local_count" -gt 0 ]; then |
| 387 | # At least one repository is local |
| 388 | serialize_builds=1 |
| 389 | else |
| 390 | dont_clean=0 |
| 391 | fi |
| 392 | |
| 393 | export -f upon not_upon |
| 394 | |
| 395 | # Generate test descriptions |
| 396 | "$ci_root/script/gen_test_desc.py" |
| 397 | |
| 398 | # Iterate through test files in workspace |
| 399 | pushd "$workspace" |
| 400 | |
| 401 | if not_upon "$parallel" || echo "$parallel" | grep -vq "[0-9]"; then |
| 402 | parallel=1 |
| 403 | test_run="$user_test_run" |
| 404 | dont_clean="$user_dont_clean" |
| 405 | primary_live="$user_primary_live" |
| 406 | fi |
| 407 | |
| 408 | if [ "$parallel" -gt 1 ]; then |
| 409 | msg="Running at most $parallel jobs in parallel" |
| 410 | if upon "$serialize_builds"; then |
| 411 | msg+=" (builds serialized)" |
| 412 | fi |
| 413 | msg+="..." |
| 414 | fi |
| 415 | |
| 416 | # Generate Makefile |
| 417 | gen_makefile |
| 418 | |
| 419 | if upon "$msg"; then |
| 420 | echo "$msg" |
| 421 | echo |
| 422 | fi |
| 423 | |
| 424 | keep_going="${user_keep_going:-1}" |
| 425 | if not_upon "$keep_going"; then |
| 426 | keep_going= |
| 427 | fi |
| 428 | |
| 429 | MAKEFLAGS= make -r -j "$parallel" ${keep_going+-k} 5>&1 &>"make.log" |