Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 # Copyright (c) 2012 Google Inc.
2 # All rights reserved.
3 #
4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions are
6 # met:
7 #
8 # * Redistributions of source code must retain the above copyright
9 # notice, this list of conditions and the following disclaimer.
10 # * Redistributions in binary form must reproduce the above
11 # copyright notice, this list of conditions and the following disclaimer
12 # in the documentation and/or other materials provided with the
13 # distribution.
14 # * Neither the name of Google Inc. nor the names of its
15 # contributors may be used to endorse or promote products derived from
16 # this software without specific prior written permission.
17 #
18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 # Collection of common shell functions for 'run-checks.sh' et 'test-shell.sh'
32 # All internal variables and functions use an underscore as a prefix
33 # (e.g. _VERBOSE, _ALL_CLEANUPS, etc..).
35 # Sanitize the environment
36 export LANG=C
37 export LC_ALL=C
39 if [ "$BASH_VERSION" ]; then
40 set -o posix
41 fi
43 # Utility functions
45 _ALL_CLEANUPS=
47 # Register a function to be called when the script exits, even in case of
48 # Ctrl-C, logout, etc.
49 # $1: function name.
50 atexit () {
51 if [ -z "$_ALL_CLEANUPS" ]; then
52 _ALL_CLEANUPS=$1
53 # Ensure a clean exit when the script is:
54 # - Exiting normally (EXIT)
55 # - Interrupted by Ctrl-C (INT)
56 # - Interrupted by log out (HUP)
57 # - Being asked to quit nicely (TERM)
58 # - Being asked to quit and dump core (QUIT)
59 trap "_exit_cleanups \$?" EXIT INT HUP QUIT TERM
60 else
61 _ALL_CLEANUPS="$_ALL_CLEANUPS $1"
62 fi
63 }
65 # Called on exit if at least one function was registered with atexit
66 # $1: final exit status code
67 _exit_cleanups () {
68 local CLEANUP CLEANUPS
69 # Ignore calls to atexit during cleanups
70 CLEANUPS=$_ALL_CLEANUPS
71 _ALL_CLEANUPS=
72 for CLEANUP in $CLEANUPS; do
73 ($CLEANUP)
74 done
75 exit "$@"
76 }
81 # Dump a panic message then exit.
82 # $1+: message
83 panic () {
84 echo "ERROR: $@" >&2
85 exit 1
86 }
88 # If the previous command failed, dump a panic message then exit.
89 # $1+: message.
90 fail_panic () {
91 if [ $? != 0 ]; then
92 panic "$@"
93 fi;
94 }
96 _VERBOSE=0
98 # Increase verbosity for dump/log/run/run2 functions
99 increase_verbosity () {
100 _VERBOSE=$(( $_VERBOSE + 1 ))
101 }
103 # Decrease verbosity
104 decrease_verbosity () {
105 _VERBOSE=$(( $_VERBOSE - 1 ))
106 }
108 # Returns success iff verbosity level is higher than a specific value
109 # $1: verbosity level
110 verbosity_is_higher_than () {
111 [ "$_VERBOSE" -gt "$1" ]
112 }
114 # Returns success iff verbosity level is lower than a specific value
115 # $1: verbosity level
116 verbosity_is_lower_than () {
117 [ "$_VERBOSE" -le "$1" ]
118 }
120 # Dump message to stdout, unless verbosity is < 0, i.e. --quiet was called
121 # $1+: message
122 dump () {
123 if [ "$_VERBOSE" -ge 0 ]; then
124 printf "%s\n" "$*"
125 fi
126 }
128 # If --verbose was used, dump a message to stdout.
129 # $1+: message
130 log () {
131 if [ "$_VERBOSE" -ge 1 ]; then
132 printf "%s\n" "$*"
133 fi
134 }
136 _RUN_LOG=
138 # Set a run log file that can be used to collect the output of commands that
139 # are not displayed.
140 set_run_log () {
141 _RUN_LOG=$1
142 }
144 # Run a command. Output depends on $_VERBOSE:
145 # $_VERBOSE <= 0: Run command, store output into the run log
146 # $_VERBOSE >= 1: Dump command, run it, output goest to stdout
147 # Note: Ideally, the command's output would go to the run log for $_VERBOSE >= 1
148 # but the 'tee' tool doesn't preserve the status code of its input pipe
149 # in case of error.
150 run () {
151 local LOGILE
152 if [ "$_RUN_LOG" ]; then
153 LOGFILE=$_RUN_LOG
154 else
155 LOGFILE=/dev/null
156 fi
158 if [ "$_VERBOSE" -ge 1 ]; then
159 echo "COMMAND: $@"
160 "$@"
161 else
162 "$@" >>$LOGFILE 2>&1
163 fi
164 }
166 # Same as run(), but only dump command output for $_VERBOSE >= 2
167 run2 () {
168 local LOGILE
169 if [ "$_RUN_LOG" ]; then
170 LOGFILE=$_RUN_LOG
171 else
172 LOGFILE=/dev/null
173 fi
175 if [ "$_VERBOSE" -ge 1 ]; then
176 echo "COMMAND: $@"
177 fi
178 if [ "$_VERBOSE" -ge 2 ]; then
179 "$@"
180 else
181 "$@" >>$LOGFILE 2>&1
182 fi
183 }
185 # Extract number of cores to speed up the builds
186 # Out: number of CPU cores
187 get_core_count () {
188 case $(uname -s) in
189 Linux)
190 grep -c -e '^processor' /proc/cpuinfo
191 ;;
192 Darwin)
193 sysctl -n hw.ncpu
194 ;;
195 CYGWIN*|*_NT-*)
196 echo $NUMBER_OF_PROCESSORS
197 ;;
198 *)
199 echo 1
200 ;;
201 esac
202 }
205 # Check for the Android ADB program.
206 #
207 # On success, return nothing, but updates internal variables so later calls to
208 # adb_shell, adb_push, etc.. will work. You can get the path to the ADB program
209 # with adb_get_program if needed.
210 #
211 # On failure, returns 1, and updates the internal adb error message, which can
212 # be retrieved with adb_get_error.
213 #
214 # $1: optional ADB program path.
215 # Return: success or failure.
216 _ADB=
217 _ADB_STATUS=
218 _ADB_ERROR=
220 adb_check () {
221 # First, try to find the executable in the path, or the SDK install dir.
222 _ADB=$1
223 if [ -z "$_ADB" ]; then
224 _ADB=$(which adb 2>/dev/null)
225 if [ -z "$_ADB" -a "$ANDROID_SDK_ROOT" ]; then
226 _ADB=$ANDROID_SDK_ROOT/platform-tools/adb
227 if [ ! -f "$_ADB" ]; then
228 _ADB=
229 fi
230 fi
231 if [ -z "$_ADB" ]; then
232 _ADB_STATUS=1
233 _ADB_ERROR="The Android 'adb' tool is not in your path."
234 return 1
235 fi
236 fi
238 log "Found ADB program: $_ADB"
240 # Check that it works correctly
241 local ADB_VERSION
242 ADB_VERSION=$("$_ADB" version 2>/dev/null)
243 case $ADB_VERSION in
244 "Android Debug Bridge "*) # Pass
245 log "Found ADB version: $ADB_VERSION"
246 ;;
247 *) # Fail
248 _ADB_ERROR="Your ADB binary reports a bad version ($ADB_VERSION): $_ADB"
249 _ADB_STATUS=1
250 return 1
251 esac
253 _ADB_STATUS=0
254 return 0
255 }
258 # Return the path to the Android ADB program, if correctly detected.
259 # On failure, return the empty string.
260 # Out: ADB program path (or empty on failure)
261 # Return: success or failure.
262 adb_get_program () {
263 # Return cached value as soon as possible.
264 if [ -z "$_ADB_STATUS" ]; then
265 adb_check $1
266 fi
267 echo "$_ADB"
268 return $_ADB_STATUS
269 }
271 # Return the error corresponding to the last ADB function failure.
272 adb_get_error () {
273 echo "$_ADB_ERROR"
274 }
276 # Check that there is one device connected through ADB.
277 # In case of failure, use adb_get_error to know why this failed.
278 # $1: Optional adb program path
279 # Return: success or failure.
280 _ADB_DEVICE=
281 _ADB_DEVICE_STATUS=
282 adb_check_device () {
283 if [ "$_ADB_DEVICE_STATUS" ]; then
284 return $_ADB_DEVICE_STATUS
285 fi
287 # Check for ADB.
288 if ! adb_check $1; then
289 _ADB_DEVICE_STATUS=$_ADB_STATUS
290 return 1
291 fi
293 local ADB_DEVICES NUM_DEVICES FINGERPRINT
295 # Count the number of connected devices.
296 ADB_DEVICES=$("$_ADB" devices 2>/dev/null | awk '$2 == "device" { print $1; }')
297 NUM_DEVICES=$(echo "$ADB_DEVICES" | wc -l)
298 case $NUM_DEVICES in
299 0)
300 _ADB_ERROR="No Android device connected. Please connect one to your machine."
301 _ADB_DEVICE_STATUS=1
302 return 1
303 ;;
304 1) # Pass
305 # Ensure the same device will be called in later adb_shell calls.
306 export ANDROID_SERIAL=$ADB_DEVICES
307 ;;
308 *) # 2 or more devices.
309 if [ "$ANDROID_SERIAL" ]; then
310 ADB_DEVICES=$ANDROID_SERIAL
311 NUM_DEVICES=1
312 else
313 _ADB_ERROR="More than one Android device connected. \
314 Please define ANDROID_SERIAL in your environment"
315 _ADB_DEVICE_STATUS=1
316 return 1
317 fi
318 ;;
319 esac
321 _ADB_DEVICE_STATUS=0
322 _ADB_DEVICE=$ADB_DEVICES
324 FINGERPRINT=$(adb_shell getprop ro.build.fingerprint)
325 log "Using ADB device: $ANDROID_SERIAL ($FINGERPRINT)"
326 return 0
327 }
329 # The 'adb shell' command is pretty hopeless, try to make sense of it by:
330 # 1/ Removing trailing \r from line endings.
331 # 2/ Ensuring the function returns the command's status code.
332 #
333 # $1+: Command
334 # Out: command output (stdout + stderr combined)
335 # Return: command exit status
336 adb_shell () {
337 local RET ADB_LOG
338 # Check for ADB device.
339 adb_check_device || return 1
340 ADB_LOG=$(mktemp "${TMPDIR:-/tmp}/adb-XXXXXXXX")
341 "$_ADB" shell "$@" ";" echo \$? > "$ADB_LOG" 2>&1
342 sed -i -e 's![[:cntrl:]]!!g' "$ADB_LOG" # Remove \r.
343 RET=$(sed -e '$!d' "$ADB_LOG") # Last line contains status code.
344 sed -e '$d' "$ADB_LOG" # Print everything except last line.
345 rm -f "$ADB_LOG"
346 return $RET
347 }
349 # Push a file to a device.
350 # $1: source file path
351 # $2: device target file path
352 # Return: success or failure.
353 adb_push () {
354 adb_check_device || return 1
355 run "$_ADB" push "$1" "$2"
356 }
358 # Pull a file from a device
359 # $1: device file path
360 # $2: target host file path
361 # Return: success or failure.
362 adb_pull () {
363 adb_check_device || return 1
364 run "$_ADB" pull "$1" "$2"
365 }
367 # Same as adb_push, but will panic if the operations didn't succeed.
368 adb_install () {
369 adb_push "$@"
370 fail_panic "Failed to install $1 to the Android device at $2"
371 }