blob: be279184b76d689cd6d77786577ce29a3b4a9833 [file] [log] [blame]
Javier Almansa Sobrino412d3612020-05-22 17:53:12 +01001#!/bin/bash
2#
3# Copyright (c) 2020, Arm Limited. All rights reserved.
4#
5# SPDX-License-Identifier: BSD-3-Clause
6#
7
8set -e
9
10# Enable job control to have background processes run in their own process
11# group. That way, we can kill a background process group in one go.
12set -m
13
14ci_root="$(readlink -f "$(dirname "$0")/..")"
15source "$ci_root/utils.sh"
16
17artefacts="${artefacts-$workspace/artefacts}"
18
19run_root="$workspace/run"
20pid_dir="$workspace/pids"
21
22mkdir -p "$pid_dir"
23mkdir -p "$run_root"
24
25archive="$artefacts"
26
27gen_fpga_params() {
28 local fpga_param_file="fpga_env.sh"
29
30 echo "Generating parameters for FPGA $fpga..."
31 echo
32
33 echo "baudrate=$uart_baudrate" > $fpga_param_file
34 echo "fpga=$fpga" >> $fpga_param_file
35 echo "fpga_bitfile=$fpga_bitfile" >> $fpga_param_file
36 echo "fpga_payload=$fpga_payload" >> $fpga_param_file
37 echo "project_name=$project_name" >> $fpga_param_file
38 echo "port=$uart_port" >> $fpga_param_file
39 echo "uart=$uart_descriptor" >> $fpga_param_file
40
41 archive_file "$fpga_param_file"
42}
43
44kill_and_reap() {
45 local gid
46 # Kill an active process. Ignore errors
47 [ "$1" ] || return 0
48 kill -0 "$1" &>/dev/null || return 0
49
50 # Kill the children
51 kill -- "-$1" &>/dev/null || true
52 # Kill the group
53 { gid="$(awk '{print $5}' < /proc/$1/stat)";} 2>/dev/null || return
54 kill -SIGKILL -- "-$gid" &>/dev/null || true
55
56 wait "$gid" &>/dev/null || true
57}
58
59# Perform clean up and ignore errors
60cleanup() {
61 local pid
62
63 # Test success. Kill all background processes so far and wait for them
64 pushd "$pid_dir"
65 set +e
66 while read pid; do
67 pid="$(cat $pid)"
68 kill_and_reap "$pid"
69 done < <(find -name '*.pid')
70 popd
71}
72
73# Launch a program. Have its PID saved in a file with given name with .pid
74# suffix. When the program exits, create a file with .success suffix, or one
75# with .fail if it fails. This function blocks, so the caller must '&' this if
76# they want to continue. Call must wait for $pid_dir/$name.pid to be created
77# should it want to read it.
78launch() {
79 local pid
80
81 "$@" &
82 pid="$!"
83 echo "$pid" > "$pid_dir/${name:?}.pid"
84 if wait "$pid"; then
85 touch "$pid_dir/$name.success"
86 else
87 touch "$pid_dir/$name.fail"
88 fi
89}
90
91# Cleanup actions
92trap cleanup SIGINT SIGHUP SIGTERM EXIT
93
94# Source variables required for run
95source "$artefacts/env"
96
97echo
98echo "RUNNING: $TEST_CONFIG"
99echo
100
101# Accept BIN_MODE from environment, or default to release. If bin_mode is set
102# and non-empty (intended to be set from command line), that takes precedence.
103pkg_bin_mode="${BIN_MODE:-release}"
104bin_mode="${bin_mode:-$pkg_bin_mode}"
105
106artefacts_wd="$artefacts/$bin_mode"
107
108# Change directory so that all binaries can be accessed relative to where they
109# lie
110run_cwd="$artefacts/$bin_mode"
111cd "$run_cwd"
112
113# Source environment for run
114if [ -f "run/env" ]; then
115 source "run/env"
116fi
117
118# Whether to display primary UART progress live on the console
119primary_live="${primary_live-$PRIMARY_LIVE}"
120
121# Assume 0 is the primary UART to track
122primary_uart="${primary_uart:-0}"
123
124# Assume 1 UARTs by default
125num_uarts="${num_uarts:-1}"
126
127# Generate the environment configuration file for the FPGA host.
128for u in $(seq 0 $(( $num_uarts - 1 )) | tac); do
129 descriptor="run/uart$u/descriptor"
130 if [ -f "$descriptor" ]; then
131 uart_descriptor="$(cat "$descriptor")"
132 else
133 echo "Error: No descriptor specified for UART$u"
134 exit 1
135 fi
136
137 baudrate="run/uart$u/baudrate"
138 if [ -f "$baudrate" ]; then
139 uart_baudrate="$(cat "$baudrate")"
140 else
141 echo "Error: No baudrate specified for UART$u"
142 exit 1
143 fi
144
145 port="run/uart$u/port"
146 if [ -f "$port" ]; then
147 uart_port="$(cat "$port")"
148 else
149 echo "Error: No port specified for UART$u"
150 exit 1
151 fi
152
153 fpga="$fpga_cluster" gen_fpga_params
154done
155
156if [ -z "$fpga_user" ]; then
157 echo "FPGA user not configured!"
158 exit 1
159fi
160if [ -z "$fpga_host" ]; then
161 echo "FPGA host not configured!"
162 exit 1
163fi
164remote_user="$fpga_user"
165remote_host="$fpga_host"
166
167echo
168echo "Copying artefacts to $remote_host as user $remote_user"
169echo
170
171# Copy the image to the remote host.
172scp "$artefacts_wd/$fpga_payload" "$remote_user@$remote_host:./$fpga_payload" > \
173 /dev/null
174
175# Copy the env and run scripts to the remote host.
176scp "$artefacts_wd/fpga_env.sh" "$remote_user@$remote_host:." > /dev/null
177scp "$ci_root/script/$fpga_run_script" "$remote_user@$remote_host:." > /dev/null
178
179echo "FPGA configuration options:"
180echo
181cat "$artefacts_wd/fpga_env.sh"
182
183# For an automated run, export a known variable so that we can identify stale
184# processes spawned by Trusted Firmware CI by inspecting its environment.
185export TRUSTED_FIRMWARE_CI="1"
186
187echo
188echo "Executing on $remote_host as user $remote_user"
189echo
190
191# Run the FPGA from the remote host.
192name="fpga_run" launch ssh "$remote_user@$remote_host" "bash ./$fpga_run_script" > \
193 /dev/null 2>&1 &
194
195# Wait enough time for the UART to show up on the FPGA host so the connection
196# can be stablished.
197sleep 35
198
199# If it's a test run, skip all the hoops and start a telnet connection to the FPGA.
200if upon "$test_run"; then
201 telnet "$remote_host" "$(cat "run/uart$primary_uart/port")"
202 exit 0
203fi
204
205# Launch expect scripts for all UARTs
206for u in $(seq 0 $(( $num_uarts - 1 )) | tac); do
207 script="run/uart$u/expect"
208 if [ -f "$script" ]; then
209 script="$(cat "$script")"
210 else
211 script=
212 fi
213
214 # Primary UART must have a script
215 if [ -z "$script" ]; then
216 if [ "$u" = "$primary_uart" ]; then
217 die "No primary UART script!"
218 else
219 echo "Ignoring UART$u (no expect script provided)."
220 continue
221 fi
222 fi
223
224 uart_descriptor="$(cat "run/uart$u/descriptor")"
225
226 timeout="run/uart$u/timeout"
227 uart_port="$(cat "run/uart$u/port")"
228
229 if [ -f "$timeout" ]; then
230 timeout="$(cat "$timeout")"
231 else
232 timeout=
233 fi
234 timeout="${timeout-600}"
235
236 full_log="$run_root/uart${u}_full.txt"
237
238 if [ "$u" = "$primary_uart" ]; then
239 star="*"
240 uart_name="primary_uart"
241 else
242 star=" "
243 uart_name="uart$u"
244 fi
245
246 # Launch expect after exporting required variables
247 (
248 if [ -f "run/uart$u/env" ]; then
249 set -a
250 source "run/uart$u/env"
251 set +a
252 fi
253
254 if [ "$u" = "$primary_uart" ] && upon "$primary_live"; then
255 uart_port="$uart_port" remote_host="$remote_host" timeout="$timeout" \
256 name="$uart_name" launch expect -f "$ci_root/expect/$script" | \
257 tee "$full_log"
258 echo
259 else
260 uart_port="$uart_port" remote_host="$remote_host" timeout="$timeout" \
261 name="$uart_name" launch expect -f "$ci_root/expect/$script" \
262 &>"$full_log"
263 fi
264
265 ) &
266
267 echo "Tracking UART$u$star ($uart_descriptor) with $script and timeout $timeout."
268done
269echo
270
271result=0
272
273set +e
274
275# Wait for all the children. Note that the wait below is *not* a timed wait.
276wait -n
277
278pushd "$pid_dir"
279# Wait for fpga_run to finish on the remote server.
280while :; do
281 if [ "$(wc -l < <(ls -l fpga_run.* 2> /dev/null))" -eq 2 ]; then
282 break
283 else
284 sleep 1
285 fi
286done
287
288# Check if there is any failure.
289while :; do
290 # Exit failure if we've any failures
291 if [ "$(wc -l < <(find -name '*.fail'))" -ne 0 ]; then
292 result=1
293 break
294 fi
295
296 # We're done if the primary UART exits success
297 if [ -f "$pid_dir/primary_uart.success" ]; then
298 break
299 fi
300done
301
302cleanup
303
304if [ "$result" -eq 0 ]; then
305 echo "Test success!"
306else
307 echo "Test failed!"
308fi
309
310if upon "$jenkins_run"; then
311 echo
312 echo "Artefacts location: $BUILD_URL."
313 echo
314fi
315
316if upon "$jenkins_run" && upon "$artefacts_receiver" && [ -d "$workspace/run" ]; then
317 source "$CI_ROOT/script/send_artefacts.sh" "run"
318fi
319
320exit "$result"
321# vim: set tw=80 sw=8 noet: