Add arm-nacl port.
[glibc.git] / sysdeps / nacl / nacl-test-wrapper.sh
blob0e058131433a1ce4b0a79bbb719c76a7ea79bf90
1 #!/bin/bash
2 # test-wrapper script for NaCl.
4 # Copyright (C) 2015 Free Software Foundation, Inc.
5 # This file is part of the GNU C Library.
7 # The GNU C Library is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU Lesser General Public
9 # License as published by the Free Software Foundation; either
10 # version 2.1 of the License, or (at your option) any later version.
12 # The GNU C Library is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 # Lesser General Public License for more details.
17 # You should have received a copy of the GNU Lesser General Public
18 # License along with the GNU C Library; if not, see
19 # <http://www.gnu.org/licenses/>.
21 progname="$(basename "$0")"
23 usage="usage: ${progname} --arch=ARCH [VAR=VAL...] COMMAND ..."
24 help="
27 use_bootstrap=true
28 arch=
29 env=()
30 envi=0
31 while [ $# -gt 0 ]; do
32 case "$1" in
34 --help)
35 echo "$usage"
36 echo "$help"
37 exit 0
40 --arch=*)
41 arch="${1#--arch=}"
42 shift
45 *=*)
46 env[envi++]='-E'
47 env[envi++]="$1"
48 shift
51 --)
52 shift
53 break
57 break
59 esac
60 done
62 if [ $# -lt 1 -o -z "$arch" ]; then
63 echo "$usage" >&2
64 echo "Type '${progname} --help' for more detailed help." >&2
65 exit 1
68 test_args=("$@")
70 if [ -z "$NACL_SDK_ROOT" ]; then
71 echo >&2 "$0: NACL_SDK_ROOT must be set in the environment"
72 exit 77
75 # We use a handful of things from the NaCl SDK, or at least
76 # from a directory matching the layout of the NaCl SDK.
77 sdk_tools="${NACL_SDK_ROOT}/tools"
79 NACL_BOOTSTRAP="${sdk_tools}/nacl_helper_bootstrap_${arch}"
80 NACL_SEL_LDR="${sdk_tools}/sel_ldr_${arch}"
81 NACL_IRT="${sdk_tools}/irt_core_${arch}.nexe"
82 NACL_LOADER="${sdk_tools}/loader_${arch}.nexe"
84 if [ ! -x "$NACL_BOOTSTRAP" -o ! -x "$NACL_SEL_LDR" ]; then
85 echo >&2 "$0: sel_ldr_${arch} and/or nacl_helper_bootstrap_${arch} missing"
86 echo >&2 "$0: from directory $sdk_tools"
87 exit 77
90 if [ ! -r "$NACL_IRT" -o ! -r "$NACL_LOADER" ]; then
91 echo >&2 "$0: irt_core_${arch}.nexe and/or loader_${arch}.nexe missing"
92 echo >&2 "$0: from directory $sdk_tools"
93 exit 77
96 # Figure out if we are building for the native machine or not.
97 # If not, we'll run sel_ldr under qemu.
98 decide_use_emulator()
100 local arg
101 for arg; do
102 if [[ "$(uname -m)" = "$1" ]]; then
103 return
105 done
106 use_emulator=true
109 use_emulator=false
110 case "$arch" in
111 arm)
112 decide_use_emulator 'arm*'
113 emulator=(qemu-arm -cpu cortex-a15 -L "${sdk_tools}/arm_trusted")
115 x86_32)
116 decide_use_emulator 'i?86' 'x86_64*'
117 emulator=(qemu-i386)
119 x86_64)
120 decide_use_emulator 'x86_64*'
121 emulator=(qemu-x86_64)
123 esac
125 if $use_emulator; then
126 ldr_args=('-Q')
127 emulator_factor=10
128 else
129 emulator=()
130 ldr_args=()
131 emulator_factor=1
134 if $use_bootstrap; then
135 ldr=(
136 "${NACL_BOOTSTRAP}"
137 "${NACL_SEL_LDR}"
138 '--r_debug=0xXXXXXXXXXXXXXXXX'
139 '--reserved_at_zero=0xXXXXXXXXXXXXXXXX'
141 else
142 ldr=("${NACL_SEL_LDR}")
145 static=true
146 case "$1" in
147 */ld-nacl*) static=false ;;
148 esac
150 if $static; then
151 loader=()
152 else
153 loader=(-f "${NACL_LOADER}")
156 run_test()
158 local test_fifo="$1"
159 local cmd=(
160 "${emulator[@]}" "${ldr[@]}" -q -S -a "${ldr_args[@]}" -B "${NACL_IRT}"
161 "${loader[@]}" "${env[@]}" -E TEST_DIRECT="$test_fifo" -- "${test_args[@]}"
163 if [ "${NACLVERBOSITY:+set}" = set ]; then
164 "${cmd[@]}"
165 else
166 NACLLOG=/dev/null "${cmd[@]}"
170 temp_files=()
171 test_fifo=
172 do_cleanup()
174 rm -rf "$test_fifo" "${temp_files[@]}"
176 trap do_cleanup EXIT HUP INT TERM
178 # Create a named pipe to receive the TEST_DIRECT information from the test
179 # program.
180 test_fifo=${TMPDIR:-/tmp}/libc-test-fifo.$$
181 rm -f "$test_fifo"
182 mkfifo "$test_fifo" || {
183 echo "Cannot create test FIFO '$test_fifo'"
184 exit 1
187 # Run the test in the background, so we can implement a timeout.
188 # The no-op redirection defeats the default behavior of "< /dev/null"
189 # for a background command.
190 run_test "$test_fifo" <&0 & test_pid=$!
192 # Set up a short timeout before we read from the FIFO, in case
193 # the program doesn't actually write to the FIFO at all (it is
194 # not a test-skeleton.c program, or it dies very early).
195 no_skeleton=false
196 script_pid=$$
197 trap 'no_skeleton=true' USR1
198 (sleep 2; kill -USR1 $script_pid) 2> /dev/null &
200 # The test should first write into the FIFO to describe its expectations.
201 # Our open-for-reading of the FIFO will block until the test starts up and
202 # opens it for writing. Then our reads will block until the test finishes
203 # writing out info and closes the FIFO. At that point we will have
204 # collected (and evaluated) what it emitted. It sets these variables:
205 # timeout=%u
206 # timeoutfactor=%u
207 # exit=%u
208 # signal=%s
209 unset exit signal
210 . "$test_fifo" 2> /dev/null
212 # If we got this far, either the 'no_skeleton=true' watchdog already
213 # fired, or else we don't want it to.
214 trap '' USR1
216 if $no_skeleton; then
217 # We hit the timeout, so we didn't get full information about test
218 # expectations. Reset any partial results we may have gotten.
219 unset exit signal
220 else
221 # Now we know the expected timeout, so we can start the timer running.
222 ((sleep_time = timeout * timeoutfactor * emulator_factor))
224 # Now start a background subshell to enforce the timeout.
225 (sleep "$sleep_time"; kill -ALRM $test_pid) 2> /dev/null &
228 # This corresponds to '#ifdef EXPECTED_STATUS' in test-skeleton.c.
229 expected_status()
231 test "${exit+yes}" = yes
233 # This corresponds to '#ifdef EXPECTED_SIGNAL' in test-skeleton.c.
234 expected_signal()
236 test "${signal+yes}" = yes
238 # This corresponds to 'if (WIFEXITED (status))' in test-skeleton.c.
239 wifexited()
241 test $test_rc -lt 128
244 # Now wait for the test process to finish.
245 wait $test_pid
246 test_rc=$?
248 # This exactly duplicates the logic in test-skeleton.c.
249 if wifexited; then
250 if ! expected_status; then
251 if ! expected_signal; then
252 # Simply exit with the return value of the test. */
253 exit $test_rc
254 else
255 echo "Expected signal '${signal}' from child, got none"
256 exit 1
258 else
259 if [ $test_rc -ne $exit ]; then
260 echo "Expected status $exit, got $test_rc"
261 exit 1
263 exit 0
265 else
266 # Process was killed by timer or other signal.
267 ((test_signal = test_rc > 192 ? 256 - test_rc : test_rc - 128 ))
268 test_signame=$(kill -l "$test_signal")
269 if ! expected_signal; then
270 echo "Didn't expect signal from child; got '${test_signame}'"
271 exit 1
272 else
273 if [ "$test_signame" != "$signal" ]; then
274 echo "\
275 Incorrect signal from child: got '${test_signame}', need '${signal}'"
276 exit 1
278 exit 0