blob: 937630537fbea42f1baf780bb4f9fd2706462eb4 [file] [log] [blame]
Fathi Boudra422bf772019-12-02 11:10:16 +02001#!/bin/bash
2#
3# Copyright (c) 2019, Arm Limited. All rights reserved.
4#
5# SPDX-License-Identifier: BSD-3-Clause
6#
7
8set -e
9
10in_red() {
11 echo "$(tput setaf 1)${1:?}$(tput sgr0)"
12}
13export -f in_red
14
15in_green() {
16 echo "$(tput setaf 2)${1:?}$(tput sgr0)"
17}
18export -f in_green
19
20in_yellow() {
21 echo "$(tput setaf 3)${1:?}$(tput sgr0)"
22}
23export -f in_yellow
24
25print_success() {
26 in_green "$1: SUCCESS"
27}
28export -f print_success
29
30print_failure() {
31 in_red "$1: FAILURE"
32}
33export -f print_failure
34
35print_unstable() {
36 in_yellow "$1: UNSTABLE"
37}
38export -f print_unstable
39
40gen_makefile() {
41 local num="$(find -name "*.test" -type f | wc -l)"
42 local i=0
43
44 cat <<EOF >Makefile
45SHELL=/bin/bash
46
47all:
48
49EOF
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 "\$@"
71EOF
72}
73
74# This function is invoked from the Makefile. Descriptor 5 points to the active
75# terminal.
76run_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
88 workspace="$id" test_desc="$test_file" "$ci_root/script/parse_test.sh"
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
112 case "$action" in
113 "build")
114 echo "building: $config_string" >&5
115 if ! bash $minus_x "$ci_root/script/build_package.sh" \
116 >&6 2>&1; then
117 {
118 print_failure "$config_string (build)"
119 if [ "$console_file" ]; then
120 echo " see $console_file"
121 fi
122 } >&5
123 exit 1
124 fi
125 ;;
126
127 "run")
128 # Local runs only for FVP unless asked not to
129 if echo "$RUN_CONFIG" | grep -q "^fvp" && \
130 not_upon "$skip_runs"; then
131 echo "running: $config_string" >&5
132 if bash $minus_x "$ci_root/script/run_package.sh" \
133 >&6 2>&1; then
134 if grep -q -e "--BUILD UNSTABLE--" \
135 "$log_file"; then
136 print_unstable "$config_string" >&5
137 else
138 print_success "$config_string" >&5
139 fi
140 exit 0
141 else
142 {
143 print_failure "$config_string (run)"
144 if [ "$console_file" ]; then
145 echo " see $console_file"
146 fi
147 } >&5
148 exit 1
149 fi
150 else
151 if grep -q -e "--BUILD UNSTABLE--" \
152 "$log_file"; then
153 print_unstable "$config_string (not run)" >&5
154 else
155 print_success "$config_string (not run)" >&5
156 fi
157 exit 0
158 fi
159 ;;
160
161 *)
162 in_red "Invalid action: $action!" >&5
163 exit 1
164 ;;
165 esac
166}
167export -f run_one_test
168
169workspace="${workspace:?}"
170ci_root="$(readlink -f "$(dirname "$0")/..")"
171
172# If this script was invoked with bash -x, have subsequent build/run invocations
173# to use -x as well.
174if echo "$-" | grep -q "x"; then
175 export minus_x="-x"
176fi
177
178# For a local run, when some variables as specified as "?", launch zenity to
179# prompt for test config via. GUI. If it's "??", then choose a directory.
180if [ "$test_groups" = "?" -o "$test_groups" = "??" ]; then
181 zenity_opts=(
182 --file-selection
183 --filename="$ci_root/group/README"
184 --multiple
185 --title "Choose test config"
186 )
187
188 if [ "$test_groups" = "??" ]; then
189 zenity_opts+=("--directory")
190 fi
191
192 # In case of multiple selections, zenity returns absolute paths of files
193 # separated by '|'. We remove the pipe characters, and make the paths
194 # relative to the group directory.
195 selections="$(cd "$ci_root"; zenity ${zenity_opts[*]})"
196 test_groups="$(echo "$selections" | tr '|' ' ')"
197 test_groups="$(echo "$test_groups" | sed "s#$ci_root/group/##g")"
198fi
199
200test_groups="${test_groups:?}"
201local_count=0
202
203if [ -z "$tf_root" ]; then
204 in_red "NOTE: NOT using local work tree for TF"
205else
206 tf_root="$(readlink -f $tf_root)"
207 tf_refspec=
208 in_green "Using local work tree for TF"
209 let "++local_count"
210fi
211
212if [ -z "$tftf_root" ]; then
213 in_red "NOTE: NOT using local work tree for TFTF"
214 tforg_user="${tforg_user:?}"
215else
216 tftf_root="$(readlink -f $tftf_root)"
217 tf_refspec=
218 in_green "Using local work tree for TFTF"
219 let "++local_count"
220fi
221
222if [ -z "$scp_root" ]; then
223 in_red "NOTE: NOT using local work tree for SCP"
224else
225 scp_root="$(readlink -f $scp_root)"
226 scp_refspec=
227 in_green "Using local work tree for SCP"
228 let "++local_count"
229fi
230
231# User preferences
232user_test_run="$test_run"
233user_dont_clean="$dont_clean"
234user_keep_going="$keep_going"
235user_primary_live="$primary_live"
236
237export ci_root
238export dont_clean=0
239export local_ci=1
240export parallel
241export test_run=0
242export primary_live=0
243
244rm -rf "$workspace"
245mkdir -p "$workspace"
246
247source "$ci_root/utils.sh"
248
249# SCP is not cloned by default
250export clone_scp
251export scp_root
252if not_upon "$scp_root" && upon "$clone_scp"; then
253 clone_scp=1
254else
255 clone_scp=0
256fi
257
258# Use clone_repos.sh to clone and share repositores that aren't local.
259no_tf="$tf_root" no_tftf="$tftf_root" no_ci="$ci_root" \
260 bash $minus_x "$ci_root/script/clone_repos.sh"
261
262set -a
263source "$workspace/env"
264set +a
265
266if [ "$local_count" -gt 0 ]; then
267 # At least one repository is local
268 serialize_builds=1
269else
270 dont_clean=0
271fi
272
273export -f upon not_upon
274
275# Generate test descriptions
276"$ci_root/script/gen_test_desc.py"
277
278# Iterate through test files in workspace
279pushd "$workspace"
280
281if not_upon "$parallel" || echo "$parallel" | grep -vq "[0-9]"; then
282 parallel=1
283 test_run="$user_test_run"
284 dont_clean="$user_dont_clean"
285 primary_live="$user_primary_live"
286fi
287
288if [ "$parallel" -gt 1 ]; then
289 msg="Running at most $parallel jobs in parallel"
290 if upon "$serialize_builds"; then
291 msg+=" (builds serialized)"
292 fi
293 msg+="..."
294fi
295
296# Generate Makefile
297gen_makefile
298
299if upon "$msg"; then
300 echo "$msg"
301 echo
302fi
303
304keep_going="${user_keep_going:-1}"
305if not_upon "$keep_going"; then
306 keep_going=
307fi
308
309MAKEFLAGS= make -r -j "$parallel" ${keep_going+-k} 5>&1 &>"make.log"