blob: af65135df5ba197ee9fe2a2e34eb4d01974684de [file] [log] [blame]
Mark Salyzynb304f6d2017-08-04 13:35:51 -07001#! /bin/bash
2#
3# Bootstat boot reason tests
4#
5# throughout testing:
6# - manual tests can only run on eng/userdebug builds
7# - watch adb logcat -b all -d -s bootstat
8# - watch adb logcat -b all -d | audit2allow
9# - wait until screen is up, boot has completed, can mean wait for
10# sys.boot_completed=1 and sys.logbootcomplete=1 to be true
11#
12# All test frames, and nothing else, must be function names prefixed and
13# specifiged with the pattern 'test_<test>() {' as this is also how the
14# script discovers the full list of tests by inspecting its own code.
15#
16
17# Helper variables
18
19SPACE=" "
20ESCAPE=""
21TAB=" "
22GREEN="${ESCAPE}[38;5;40m"
23RED="${ESCAPE}[38;5;196m"
24NORMAL="${ESCAPE}[0m"
Mark Salyzyn2450cb12017-10-10 10:44:57 -070025# Best guess to an average device's reboot time, refined as tests return
26DURATION_DEFAULT=45
Mark Salyzynb304f6d2017-08-04 13:35:51 -070027
28# Helper functions
29
30[ "USAGE: inFastboot
31
32Returns: true if device is in fastboot mode" ]
33inFastboot() {
34 fastboot devices | grep "^${ANDROID_SERIAL}[${SPACE}${TAB}]" > /dev/null
35}
36
Mark Salyzyn62909822017-10-09 09:27:16 -070037[ "USAGE: inAdb
38
39Returns: true if device is in adb mode" ]
40inAdb() {
41 adb devices | grep -v 'List of devices attached' | grep "^${ANDROID_SERIAL}[${SPACE}${TAB}]" > /dev/null
42}
43
44[ "USAGE: hasPstore
45
46Returns: true if device (likely) has pstore data" ]
47hasPstore() {
48 if inAdb && [ 0 -eq `adb shell su root ls /sys/fs/pstore | wc -l` ]; then
49 false
50 fi
51}
52
53[ "USAGE: isDebuggable
54
55Returns: true if device is (likely) a debug build" ]
56isDebuggable() {
57 if inAdb && [ 1 -ne `adb shell getprop ro.debuggable` ]; then
58 false
59 fi
60}
61
Mark Salyzyn2450cb12017-10-10 10:44:57 -070062[ "USAGE: checkDebugBuild [--noerror]
Mark Salyzyn62909822017-10-09 09:27:16 -070063
64Returns: true if device is a userdebug or eng release" ]
65checkDebugBuild() {
66 if isDebuggable; then
67 echo "INFO: '${TEST}' test requires userdebug build"
Mark Salyzyn2450cb12017-10-10 10:44:57 -070068 elif [ -n "${1}" ]; then
69 echo "WARNING: '${TEST}' test requires userdebug build"
70 false
Mark Salyzyn62909822017-10-09 09:27:16 -070071 else
72 echo "ERROR: '${TEST}' test requires userdebug build, skipping FAILURE"
Mark Salyzyn244947e2017-10-13 09:21:50 -070073 duration_prefix="~"
74 duration_estimate=1
Mark Salyzyn62909822017-10-09 09:27:16 -070075 false
76 fi >&2
77}
78
Mark Salyzyn9a387042017-10-10 14:57:12 -070079[ "USAGE: setBootloaderBootReason [value]
80
81Returns: true if device supports and set boot reason injection" ]
82setBootloaderBootReason() {
83 inAdb || ( echo "ERROR: device not in adb mode." >&2 ; false ) || return 1
84 if [ -z "`adb shell ls /etc/init/bootstat-debug.rc 2>/dev/null`" ]; then
85 echo "ERROR: '${TEST}' test requires /etc/init/bootstat-debug.rc" >&2
86 return 1
87 fi
88 checkDebugBuild || return 1
89 if adb shell su root "cat /proc/cmdline | tr '\\0 ' '\\n\\n'" |
90 grep '^androidboot[.]bootreason=[^ ]' >/dev/null; then
91 echo "ERROR: '${TEST}' test requires a device with a bootloader that" >&2
92 echo " does not set androidboot.bootreason kernel parameter." >&2
93 return 1
94 fi
95 adb shell su root setprop persist.test.boot.reason "'${1}'" 2>/dev/null
96 test_reason="`adb shell getprop persist.test.boot.reason 2>/dev/null`"
97 if [ X"${test_reason}" != X"${1}" ]; then
98 echo "ERROR: can not set persist.test.boot.reason to '${1}'." >&2
99 return 1
100 fi
101}
102
Mark Salyzyn62909822017-10-09 09:27:16 -0700103[ "USAGE: enterPstore
104
105Prints a warning string requiring functional pstore
106
107Returns: pstore_ok variable set to true or false" ]
108enterPstore() {
109 if hasPstore; then
110 echo "INFO: '${TEST}' test requires functional and reliable pstore"
111 pstore_ok=true
112 else
113 echo "WARNING: '${TEST}' test requires functional pstore"
114 pstore_ok=false
115 fi >&2
116 ${pstore_ok}
117}
118
119[ "USAGE: exitPstore
120
121Prints an error string requiring functional pstore
122
123Returns: clears error if pstore dysfunctional" ]
124exitPstore() {
125 save_ret=${?}
126 if [ ${save_ret} != 0 ]; then
127 if hasPstore; then
128 return ${save_ret}
129 fi
130 if [ true = ${pstore_ok} ]; then
131 echo "WARNING: '${TEST}' test requires functional pstore"
132 return ${save_ret}
133 fi
134 echo "ERROR: '${TEST}' test requires functional pstore, skipping FAILURE"
Mark Salyzyn244947e2017-10-13 09:21:50 -0700135 duration_prefix="~"
136 duration_estimate=1
Mark Salyzyn62909822017-10-09 09:27:16 -0700137 fi >&2
138}
139
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700140[ "USAGE: format_duration <seconds>
141
142human readable output whole seconds, whole minutes or mm:ss" ]
143format_duration() {
144 if [ -z "${1}" ]; then
145 echo unknown
146 return
147 fi
148 seconds=`expr ${1} % 60`
149 minutes=`expr ${1} / 60`
150 if [ 0 -eq ${minutes} ]; then
151 if [ 1 -eq ${1} ]; then
152 echo 1 second
153 return
154 fi
155 echo ${1} seconds
156 return
157 elif [ 60 -eq ${1} ]; then
158 echo 1 minute
159 return
160 elif [ 0 -eq ${seconds} ]; then
161 echo ${minutes} minutes
162 return
163 fi
164 echo ${minutes}:`expr ${seconds} / 10``expr ${seconds} % 10`
165}
166
167wait_for_screen_timeout=900
168[ "USAGE: wait_for_screen [-n] [TIMEOUT]
169
170-n - echo newline at exit
171TIMEOUT - default `format_duration ${wait_for_screen_timeout}`" ]
172wait_for_screen() {
173 exit_function=true
174 if [ X"-n" = X"${1}" ]; then
175 exit_function=echo
176 shift
177 fi
178 timeout=${wait_for_screen_timeout}
179 if [ ${#} -gt 0 ]; then
180 timeout=${1}
181 shift
182 fi
183 counter=0
184 while true; do
Mark Salyzyn62909822017-10-09 09:27:16 -0700185 if inFastboot; then
186 fastboot reboot
187 elif inAdb; then
188 if [ 0 != ${counter} ]; then
189 adb wait-for-device </dev/null >/dev/null 2>/dev/null
190 fi
191 if [ -n "`adb shell getprop sys.boot.reason </dev/null 2>/dev/null`" ]
192 then
193 vals=`adb shell getprop </dev/null 2>/dev/null |
194 sed -n 's/[[]sys[.]\(boot_completed\|logbootcomplete\)[]]: [[]\([01]\)[]]$/\1=\2/p'`
195 if [ "${vals}" = "`echo boot_completed=1 ; echo logbootcomplete=1`" ]
196 then
Mark Salyzyn73691aa2017-10-24 15:20:44 -0700197 sleep 1
Mark Salyzyn62909822017-10-09 09:27:16 -0700198 break
199 fi
200 if [ "${vals}" = "`echo logbootcomplete=1 ; echo boot_completed=1`" ]
201 then
Mark Salyzyn73691aa2017-10-24 15:20:44 -0700202 sleep 1
Mark Salyzyn62909822017-10-09 09:27:16 -0700203 break
204 fi
205 fi
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700206 fi
207 counter=`expr ${counter} + 1`
208 if [ ${counter} -gt ${timeout} ]; then
209 ${exit_function}
210 echo "ERROR: wait_for_screen() timed out (`format_duration ${timeout}`)" >&2
211 return 1
212 fi
Mark Salyzyn62909822017-10-09 09:27:16 -0700213 sleep 1
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700214 done
215 ${exit_function}
216}
217
218[ "USAGE: EXPECT_EQ <lval> <rval> [message]
219
220Returns true if (regex) lval matches rval" ]
221EXPECT_EQ() {
222 lval="${1}"
223 rval="${2}"
224 shift 2
225 if ! ( echo X"${rval}" | grep '^X'"${lval}"'$' >/dev/null 2>/dev/null ); then
226 echo "ERROR: expected \"${lval}\" got \"${rval}\"" >&2
227 if [ -n "${*}" ] ; then
228 echo " ${*}" >&2
229 fi
230 return 1
231 fi
232 if [ -n "${*}" ] ; then
233 if [ X"${lval}" != X"${rval}" ]; then
234 echo "INFO: ok \"${lval}\"(=\"${rval}\") ${*}" >&2
235 else
236 echo "INFO: ok \"${lval}\" ${*}" >&2
237 fi
238 fi
239 return 0
240}
241
Mark Salyzyn2450cb12017-10-10 10:44:57 -0700242[ "USAGE: EXPECT_PROPERTY <prop> <value> [--allow_failure]
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700243
244Returns true if current return (regex) value is true and the result matches" ]
245EXPECT_PROPERTY() {
246 save_ret=${?}
247 property="${1}"
248 value="${2}"
249 shift 2
250 val=`adb shell getprop ${property} 2>&1`
251 EXPECT_EQ "${value}" "${val}" for Android property ${property} ||
Mark Salyzyn2450cb12017-10-10 10:44:57 -0700252 [ -n "${1}" ] ||
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700253 save_ret=${?}
254 return ${save_ret}
255}
256
257[ "USAGE: report_bootstat_logs <expected> ...
258
259if not prefixed with a minus (-), <expected> will become a series of expected
260matches:
261
262 bootstat: Canonical boot reason: <expected_property_value>
263
264If prefixed with a minus, <expected> will look for an exact match after
265removing the minux prefix. All expected content is _dropped_ from the output
266and in essence forms a known blacklist, unexpected content will show.
267
268Report any logs, minus a known blacklist, preserve the current exit status" ]
269report_bootstat_logs() {
270 save_ret=${?}
271 match=
Mark Salyzyn62909822017-10-09 09:27:16 -0700272 for i in "${@}"; do
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700273 if [ X"${i}" != X"${i#-}" ] ; then
274 match="${match}
275${i#-}"
276 else
277 match="${match}
278bootstat: Canonical boot reason: ${i}"
279 fi
280 done
281 adb logcat -b all -d |
Mark Salyzyn08b02562017-09-18 10:07:07 -0700282 grep bootstat[^e] |
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700283 grep -v -F "bootstat: Service started: /system/bin/bootstat --record_boot_complete${match}
284bootstat: Failed to read /data/misc/bootstat/post_decrypt_time_elapsed: No such file or directory
285bootstat: Failed to parse boot time record: /data/misc/bootstat/post_decrypt_time_elapsed
286bootstat: Service started: /system/bin/bootstat --record_boot_reason
287bootstat: Service started: /system/bin/bootstat --record_time_since_factory_reset
288bootstat: Service started: /system/bin/bootstat -l
289bootstat: Battery level at shutdown 100%
290bootstat: Battery level at startup 100%
291init : Parsing file /system/etc/init/bootstat.rc...
Mark Salyzynbcf66ed2017-10-24 15:20:44 -0700292init : Parsing file /system/etc/init/bootstat-debug.rc...
Mark Salyzyn9a387042017-10-10 14:57:12 -0700293init : processing action (persist.test.boot.reason=*) from (/system/etc/init/bootstat-debug.rc:
294init : Command 'setprop ro.boot.bootreason \${persist.test.boot.reason}' action=persist.test.boot.reason=* (/system/etc/init/bootstat-debug.rc:
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700295init : processing action (post-fs-data) from (/system/etc/init/bootstat.rc
296init : processing action (boot) from (/system/etc/init/bootstat.rc
297init : processing action (ro.boot.bootreason=*) from (/system/etc/init/bootstat.rc
298init : processing action (sys.boot_completed=1 && sys.logbootcomplete=1) from (/system/etc/init/bootstat.rc
Mark Salyzyn557a9d42017-09-15 13:02:19 -0700299 (/system/bin/bootstat --record_boot_complete --record_boot_reason --record_time_since_factory_reset -l)'
300 (/system/bin/bootstat -r post_decrypt_time_elapsed)'
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700301init : Command 'exec - system log -- /system/bin/bootstat --record_boot_complete' action=sys.boot_completed=1 && sys.logbootcomplete=1 (/system/etc/init/bootstat.rc:
302init : Command 'exec - system log -- /system/bin/bootstat --record_boot_reason' action=sys.boot_completed=1 && sys.logbootcomplete=1 (/system/etc/init/bootstat.rc:
303init : Command 'exec - system log -- /system/bin/bootstat --record_time_since_factory_reset' action=sys.boot_completed=1 && sys.logbootcomplete=1 (/system/etc/init/bootstat.rc:
304 (/system/bin/bootstat --record_boot_complete)'...
305 (/system/bin/bootstat --record_boot_complete)' (pid${SPACE}
306 (/system/bin/bootstat --record_boot_reason)'...
307 (/system/bin/bootstat --record_boot_reason)' (pid${SPACE}
308 (/system/bin/bootstat --record_time_since_factory_reset)'...
309 (/system/bin/bootstat --record_time_since_factory_reset)' (pid${SPACE}
310 (/system/bin/bootstat -l)'...
311 (/system/bin/bootstat -l)' (pid " |
312 grep -v 'bootstat: Unknown boot reason: $' # Hikey Special
313 return ${save_ret}
314}
315
316[ "USAGE: start_test [message]
317
318Record start of test, preserve exit status" ]
319start_test() {
320 save_ret=${?}
Mark Salyzyn2450cb12017-10-10 10:44:57 -0700321 duration_prefix="~"
322 duration_estimate=1
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700323 START=`date +%s`
324 echo "${GREEN}[ RUN ]${NORMAL} ${TEST} ${*}"
325 return ${save_ret}
326}
327
Mark Salyzyn2450cb12017-10-10 10:44:57 -0700328duration_sum_diff=0
329duration_num=0
330[ "USAGE: duration_test [[prefix]seconds]
331
332Report the adjusted and expected test duration" ]
333duration_test() {
334 duration_prefix=${1%%[0123456789]*}
335 if [ -z "${duration_prefix}" ]; then
336 duration_prefix="~"
337 fi
338 duration_estimate="${1#${duration_prefix}}"
339 if [ -z "${duration_estimate}" ]; then
340 duration_estimate="${DURATION_DEFAULT}"
341 fi
342 duration_new_estimate="${duration_estimate}"
343 if [ 0 -ne ${duration_num} ]; then
344 duration_new_estimate=`expr ${duration_new_estimate} + \
345 \( ${duration_num} / 2 + ${duration_sum_diff} \) / ${duration_num}`
346 # guard against catastrophe
347 if [ -z "${duration_new_estimate}" ]; then
348 duration_new_estimate=${duration_estimate}
349 fi
350 fi
351 # negative values are so undignified
352 if [ 0 -ge ${duration_new_estimate} ]; then
353 duration_new_estimate=1
354 fi
355 echo "INFO: expected duration of '${TEST}' test" \
356 "${duration_prefix}`format_duration ${duration_new_estimate}`" >&2
357}
358
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700359[ "USAGE: end_test [message]
360
361Document duration and success of test, preserve exit status" ]
362end_test() {
363 save_ret=${?}
364 END=`date +%s`
365 duration=`expr ${END} - ${START} 2>/dev/null`
Mark Salyzyn2450cb12017-10-10 10:44:57 -0700366 [ 0 -ge ${duration} ] ||
Mark Salyzyn62909822017-10-09 09:27:16 -0700367 echo "INFO: '${TEST}' test duration `format_duration ${duration}`" >&2
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700368 if [ ${save_ret} = 0 ]; then
Mark Salyzyn2450cb12017-10-10 10:44:57 -0700369 if [ 0 -lt ${duration} -a 0 -lt ${duration_estimate} -a \( \
370 X"~" = X"${duration_prefix}" -o \
371 ${duration_estimate} -gt ${duration} \) ]; then
372 duration_sum_diff=`expr ${duration_sum_diff} + \
373 ${duration} - ${duration_estimate}`
374 duration_num=`expr ${duration_num} + 1`
375 fi
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700376 echo "${GREEN}[ OK ]${NORMAL} ${TEST} ${*}"
377 else
378 echo "${RED}[ FAILED ]${NORMAL} ${TEST} ${*}"
379 fi
380 return ${save_ret}
381}
382
383[ "USAGE: wrap_test <test> [message]
384
385All tests below are wrapped with this helper" ]
386wrap_test() {
387 if [ -z "${1}" -o X"nothing" = X"${1}" ]; then
388 return
389 fi
390 TEST=${1}
391 shift
392 start_test ${1}
393 eval test_${TEST}
394 end_test ${2}
395}
396
Mark Salyzyn9a387042017-10-10 14:57:12 -0700397[ "USAGE: validate_reason <value>
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700398
399Check property for CTS compliance with our expectations. Return a cleansed
400string representing what is acceptable.
401
Mark Salyzyn9a387042017-10-10 14:57:12 -0700402NB: must also roughly match heuristics in system/core/bootstat/bootstat.cpp" ]
403validate_reason() {
404 var=`echo -n ${*} |
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700405 tr '[A-Z]' '[a-z]' |
406 tr ' \f\t\r\n' '_____'`
407 case ${var} in
Mark Salyzyn9a387042017-10-10 14:57:12 -0700408 watchdog | watchdog,?* ) ;;
409 kernel_panic | kernel_panic,?*) ;;
410 recovery | recovery,?*) ;;
411 bootloader | bootloader,?*) ;;
412 cold | cold,?*) ;;
413 hard | hard,?*) ;;
414 warm | warm,?*) ;;
415 shutdown | shutdown,?*) ;;
416 reboot,reboot | reboot,reboot,* ) var=${var#reboot,} ; var=${var%,} ;;
417 reboot,cold | reboot,cold,* ) var=${var#reboot,} ; var=${var%,} ;;
418 reboot,hard | reboot,hard,* ) var=${var#reboot,} ; var=${var%,} ;;
419 reboot,warm | reboot,warm,* ) var=${var#reboot,} ; var=${var%,} ;;
420 reboot,recovery | reboot,recovery,* ) var=${var#reboot,} ; var=${var%,} ;;
421 reboot,bootloader | reboot,bootloader,* ) var=${var#reboot,} ; var=${var%,} ;;
422 reboot | reboot,?*) ;;
423 # Aliases and Heuristics
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700424 *wdog* | *watchdog* ) var="watchdog" ;;
425 *powerkey* ) var="cold,powerkey" ;;
426 *panic* | *kernel_panic*) var="kernel_panic" ;;
427 *thermal*) var="shutdown,thermal" ;;
428 *s3_wakeup*) var="warm,s3_wakeup" ;;
429 *hw_reset*) var="hard,hw_reset" ;;
430 *bootloader*) var="bootloader" ;;
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700431 *) var="reboot" ;;
432 esac
433 echo ${var}
434}
435
Mark Salyzyn9a387042017-10-10 14:57:12 -0700436[ "USAGE: validate_property <property>
437
438Check property for CTS compliance with our expectations. Return a cleansed
439string representing what is acceptable.
440
441NB: must also roughly match heuristics in system/core/bootstat/bootstat.cpp" ]
442validate_property() {
443 val="`adb shell getprop ${1} 2>&1`"
444 ret=`validate_reason "${val}"`
445 if [ "reboot" = "${ret}" ]; then
446 ret=`validate_reason "reboot,${val}"`
447 fi
448 echo ${ret}
449}
450
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700451#
452# Actual test frames
453#
454
455[ "USAGE: test_properties
456
457properties test
458- (wait until screen is up, boot has completed)
459- adb shell getprop ro.boot.bootreason (bootloader reason)
460- adb shell getprop persist.sys.boot.reason (last reason)
461- adb shell getprop sys.boot.reason (system reason)
462- NB: all should have a value that is compliant with our known set." ]
463test_properties() {
Mark Salyzyn2450cb12017-10-10 10:44:57 -0700464 duration_test 1
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700465 wait_for_screen
466 retval=0
467 check_set="ro.boot.bootreason persist.sys.boot.reason sys.boot.reason"
468 bootloader=""
469 # NB: this test could fail if performed _after_ optional_factory_reset test
470 # and will report
471 # ERROR: expected "reboot" got ""
472 # for Android property persist.sys.boot.reason
473 # following is mitigation for the persist.sys.boot.reason, skip it
Mark Salyzyn9a387042017-10-10 14:57:12 -0700474 if [ "reboot,factory_reset" = "`validate_property ro.boot_bootreason`" ]; then
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700475 check_set="ro.boot.bootreason sys.boot.reason"
476 bootloader="bootloader"
477 fi
478 for prop in ${check_set}; do
479 reason=`validate_property ${prop}`
480 EXPECT_PROPERTY ${prop} ${reason} || retval=${?}
481 done
482 # sys.boot.reason is last for a reason
483 report_bootstat_logs ${reason} ${bootloader}
484 return ${retval}
485}
486
487[ "USAGE: test_ota
488
489ota test
490- rm out/.kati_stamp-* out/build_date.txt out/build_number.txt
491- rm out/target/product/*/*/*.prop
492- rm -r out/target/product/*/obj/ETC/system_build_prop_intermediates
493- m
494- NB: ro.build.date.utc should update
495- fastboot flashall
496- (wait until screen is up, boot has completed)
497- adb shell getprop sys.boot.reason
498- NB: should report ota
499
500Decision to change the build itself rather than trick bootstat by
501rummaging through its data files was made." ]
502test_ota() {
Mark Salyzyn2450cb12017-10-10 10:44:57 -0700503 duration_test ">300"
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700504 echo " extended by build and flashing times" >&2
505 if [ -z "${TARGET_PRODUCT}" -o \
506 -z "${ANDROID_PRODUCT_OUT}" -o \
507 -z "${ANDROID_BUILD_TOP}" -o \
508 -z "${TARGET_BUILD_VARIANT}" ]; then
509 echo "ERROR: Missing envsetup.sh and lunch" >&2
510 return 1
511 fi
512 rm ${ANDROID_PRODUCT_OUT%/out/*}/out/.kati_stamp-* ||
513 true
514 rm ${ANDROID_PRODUCT_OUT%/out/*}/out/build_date.txt ||
515 true
516 rm ${ANDROID_PRODUCT_OUT%/out/*}/out/build_number.txt ||
517 true
518 rm ${ANDROID_PRODUCT_OUT}/*/*.prop ||
519 true
520 rm -r ${ANDROID_PRODUCT_OUT}/obj/ETC/system_build_prop_intermediates ||
521 true
522 pushd ${ANDROID_BUILD_TOP} >&2
523 make -j50 >&2
524 if [ ${?} != 0 ]; then
525 popd >&2
526 return 1
527 fi
528 if ! inFastboot; then
529 adb reboot-bootloader >&2
530 fi
531 fastboot flashall >&2
532 popd >&2
533 wait_for_screen
534 EXPECT_PROPERTY sys.boot.reason "\(reboot,ota\|bootloader\)"
Mark Salyzyn62909822017-10-09 09:27:16 -0700535 EXPECT_PROPERTY persist.sys.boot.reason bootloader
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700536 report_bootstat_logs reboot,ota bootloader
537}
538
539[ "USAGE: test_optional_ota
540
541fast and fake (touch build_date on device to make it different)" ]
542test_optional_ota() {
Mark Salyzyn62909822017-10-09 09:27:16 -0700543 checkDebugBuild || return
Mark Salyzyn2450cb12017-10-10 10:44:57 -0700544 duration_test
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700545 adb shell su root touch /data/misc/bootstat/build_date >&2
546 adb reboot ota
547 wait_for_screen
548 EXPECT_PROPERTY sys.boot.reason reboot,ota
549 EXPECT_PROPERTY persist.sys.boot.reason reboot,ota
550 report_bootstat_logs reboot,ota
551}
552
Mark Salyzyn62909822017-10-09 09:27:16 -0700553[ "USAGE: [TEST=<test>] blind_reboot_test
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700554
555Simple tests helper
556- adb reboot <test>
557- (wait until screen is up, boot has completed)
558- adb shell getprop sys.boot.reason
Mark Salyzyn62909822017-10-09 09:27:16 -0700559- NB: should report <test>, or reboot,<test> depending on canonical rules
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700560
561We interleave the simple reboot tests between the hard/complex ones
562as a means of checking sanity and any persistent side effect of the
563other tests." ]
564blind_reboot_test() {
Mark Salyzyn2450cb12017-10-10 10:44:57 -0700565 duration_test
Mark Salyzyn62909822017-10-09 09:27:16 -0700566 case ${TEST} in
567 bootloader | recovery | cold | hard | warm ) reason=${TEST} ;;
568 *) reason=reboot,${TEST} ;;
569 esac
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700570 adb reboot ${TEST}
571 wait_for_screen
Mark Salyzyn2a8e5cc2017-10-24 13:37:39 -0700572 bootloader_reason=`validate_property ro.boot.bootreason`
573 EXPECT_PROPERTY ro.boot.bootreason ${bootloader_reason}
Mark Salyzyn62909822017-10-09 09:27:16 -0700574 EXPECT_PROPERTY sys.boot.reason ${reason}
575 EXPECT_PROPERTY persist.sys.boot.reason ${reason}
576 report_bootstat_logs ${reason}
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700577}
578
579[ "USAGE: test_cold
580
581cold test
582- adb reboot cold
583- (wait until screen is up, boot has completed)
584- adb shell getprop sys.boot.reason
585- NB: should report cold" ]
586test_cold() {
587 blind_reboot_test
588}
589
590[ "USAGE: test_factory_reset
591
592factory_reset test
593- adb shell su root rm /data/misc/bootstat/build_date
594- adb reboot
595- (wait until screen is up, boot has completed)
596- adb shell getprop sys.boot.reason
597- NB: should report factory_reset
598
599Decision to rummage through bootstat data files was made as
600a _real_ factory_reset is too destructive to the device." ]
601test_factory_reset() {
Mark Salyzyn62909822017-10-09 09:27:16 -0700602 checkDebugBuild || return
Mark Salyzyn2450cb12017-10-10 10:44:57 -0700603 duration_test
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700604 adb shell su root rm /data/misc/bootstat/build_date >&2
605 adb reboot >&2
606 wait_for_screen
607 EXPECT_PROPERTY sys.boot.reason reboot,factory_reset
Mark Salyzyn277eca12017-09-11 15:22:57 -0700608 EXPECT_PROPERTY persist.sys.boot.reason "reboot,.*"
609 report_bootstat_logs reboot,factory_reset reboot, reboot,adb \
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700610 "-bootstat: Failed to read /data/misc/bootstat/build_date: No such file or directory" \
611 "-bootstat: Failed to parse boot time record: /data/misc/bootstat/build_date"
612}
613
614[ "USAGE: test_optional_factory_reset
615
616factory_reset test
617- adb reboot-bootloader
618- fastboot format userdata
619- fastboot reboot
620- (wait until screen is up, boot has completed)
621- adb shell getprop sys.boot.reason
622- NB: should report factory_reset
623
624For realz, and disruptive" ]
625test_optional_factory_reset() {
Mark Salyzyn2450cb12017-10-10 10:44:57 -0700626 duration_test 60
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700627 if ! inFastboot; then
628 adb reboot-bootloader
629 fi
630 fastboot format userdata >&2
631 fastboot reboot >&2
632 wait_for_screen
633 EXPECT_PROPERTY sys.boot.reason reboot,factory_reset
634 EXPECT_PROPERTY persist.sys.boot.reason ""
635 report_bootstat_logs reboot,factory_reset bootloader \
636 "-bootstat: Failed to read /data/misc/bootstat/last_boot_time_utc: No such file or directory" \
637 "-bootstat: Failed to parse boot time record: /data/misc/bootstat/last_boot_time_utc" \
638 "-bootstat: Failed to read /data/misc/bootstat/build_date: No such file or directory" \
639 "-bootstat: Failed to parse boot time record: /data/misc/bootstat/build_date" \
640 "-bootstat: Failed to read /data/misc/bootstat/factory_reset: No such file or directory" \
641 "-bootstat: Failed to parse boot time record: /data/misc/bootstat/factory_reset"
642}
643
644[ "USAGE: test_hard
645
646hard test:
647- adb reboot hard
648- (wait until screen is up, boot has completed)
649- adb shell getprop sys.boot.reason
650- NB: should report hard" ]
651test_hard() {
652 blind_reboot_test
653}
654
655[ "USAGE: test_battery
656
657battery test (trick):
Mark Salyzyna16e4372017-09-20 08:36:12 -0700658- echo healthd: battery l=2<space> | adb shell su root tee /dev/kmsg
659- adb reboot cold
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700660- (wait until screen is up, boot has completed)
661- adb shell getprop sys.boot.reason
662- NB: should report reboot,battery, unless healthd managed to log
663 before reboot in above trick.
664
665- Bonus points (manual extras)
666- Make sure the following is added to the /init.rc file in post-fs
667 section before logd is started:
668 + setprop logd.kernel false
669 + rm /sys/fs/pstore/console-ramoops
670 + rm /sys/fs/pstore/console-ramoops-0
Mark Salyzyna16e4372017-09-20 08:36:12 -0700671 + write /dev/kmsg \"healthd: battery l=2${SPACE}
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700672 +\"
673- adb reboot fs
674- (wait until screen is up, boot has completed)
675- adb shell getprop sys.boot.reason
676- NB: should report reboot,battery
677- (replace set logd.kernel true to the above, and retry test)" ]
678test_battery() {
Mark Salyzyn62909822017-10-09 09:27:16 -0700679 checkDebugBuild || return
Mark Salyzyn2450cb12017-10-10 10:44:57 -0700680 duration_test 120
Mark Salyzyn62909822017-10-09 09:27:16 -0700681 enterPstore
Mark Salyzyn8a30fca2017-09-18 10:48:39 -0700682 # Send it _many_ times to combat devices with flakey pstore
683 for i in a b c d e f g h i j k l m n o p q r s t u v w x y z; do
Mark Salyzyna16e4372017-09-20 08:36:12 -0700684 echo 'healthd: battery l=2 ' | adb shell su root tee /dev/kmsg >/dev/null
Mark Salyzyn8a30fca2017-09-18 10:48:39 -0700685 done
686 adb reboot cold >&2
687 adb wait-for-device
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700688 wait_for_screen
689 adb shell su root \
690 cat /proc/fs/pstore/console-ramoops \
691 /proc/fs/pstore/console-ramoops-0 2>/dev/null |
692 grep 'healthd: battery l=' |
693 tail -1 |
Mark Salyzyna16e4372017-09-20 08:36:12 -0700694 grep 'healthd: battery l=2 ' >/dev/null || (
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700695 if ! EXPECT_PROPERTY sys.boot.reason reboot,battery >/dev/null 2>/dev/null; then
696 # retry
Mark Salyzyn8a30fca2017-09-18 10:48:39 -0700697 for i in a b c d e f g h i j k l m n o p q r s t u v w x y z; do
Mark Salyzyna16e4372017-09-20 08:36:12 -0700698 echo 'healthd: battery l=2 ' | adb shell su root tee /dev/kmsg >/dev/null
Mark Salyzyn8a30fca2017-09-18 10:48:39 -0700699 done
700 adb reboot cold >&2
701 adb wait-for-device
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700702 wait_for_screen
703 fi
704 )
705
706 EXPECT_PROPERTY sys.boot.reason shutdown,battery
Mark Salyzyn62909822017-10-09 09:27:16 -0700707 EXPECT_PROPERTY persist.sys.boot.reason cold
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700708 report_bootstat_logs shutdown,battery "-bootstat: Battery level at shutdown 2%"
Mark Salyzyn62909822017-10-09 09:27:16 -0700709 exitPstore
710}
711
712[ "USAGE: test_optional_battery
713
714battery shutdown test:
715- adb shell setprop sys.powerctl shutdown,battery
716- (power up the device)
717- (wait until screen is up, boot has completed)
718- adb shell getprop sys.boot.reason
719- NB: should report shutdown,battery" ]
720test_optional_battery() {
Mark Salyzyn2450cb12017-10-10 10:44:57 -0700721 duration_test ">60"
Mark Salyzyn62909822017-10-09 09:27:16 -0700722 echo " power on request" >&2
723 adb shell setprop sys.powerctl shutdown,battery
724 sleep 5
725 echo -n "WARNING: Please power device back up, waiting ... " >&2
726 wait_for_screen -n >&2
727 EXPECT_PROPERTY sys.boot.reason shutdown,battery
728 EXPECT_PROPERTY persist.sys.boot.reason shutdown,battery
729 report_bootstat_logs shutdown,battery
730}
731
732[ "USAGE: test_optional_battery_thermal
733
734battery thermal shutdown test:
735- adb shell setprop sys.powerctl shutdown,thermal,battery
736- (power up the device)
737- (wait until screen is up, boot has completed)
738- adb shell getprop sys.boot.reason
739- NB: should report shutdown,thermal,battery" ]
740test_optional_battery_thermal() {
Mark Salyzyn2450cb12017-10-10 10:44:57 -0700741 duration_test ">60"
Mark Salyzyn62909822017-10-09 09:27:16 -0700742 echo " power on request" >&2
743 adb shell setprop sys.powerctl shutdown,thermal,battery
744 sleep 5
745 echo -n "WARNING: Please power device back up, waiting ... " >&2
746 wait_for_screen -n >&2
747 EXPECT_PROPERTY sys.boot.reason shutdown,thermal,battery
748 EXPECT_PROPERTY persist.sys.boot.reason shutdown,thermal,battery
749 report_bootstat_logs shutdown,thermal,battery
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700750}
751
752[ "USAGE: test_unknown
753
754unknown test
755- adb reboot unknown
756- (wait until screen is up, boot has completed)
757- adb shell getprop sys.boot.reason
758- NB: should report reboot,unknown
759- NB: expect log \"... I bootstat: Unknown boot reason: reboot,unknown\"" ]
760test_unknown() {
Mark Salyzyn62909822017-10-09 09:27:16 -0700761 blind_reboot_test
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700762}
763
764[ "USAGE: test_kernel_panic
765
766kernel_panic test:
767- echo c | adb shell su root tee /proc/sysrq-trigger
768- (wait until screen is up, boot has completed)
769- adb shell getprop sys.boot.reason
770- NB: should report kernel_panic,sysrq" ]
771test_kernel_panic() {
Mark Salyzyn62909822017-10-09 09:27:16 -0700772 checkDebugBuild || return
Mark Salyzyn2450cb12017-10-10 10:44:57 -0700773 duration_test ">90"
Mark Salyzyn62909822017-10-09 09:27:16 -0700774 panic_msg="kernel_panic,sysrq"
775 enterPstore || panic_msg="\(kernel_panic,sysrq\|kernel_panic\)"
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700776 echo c | adb shell su root tee /proc/sysrq-trigger >/dev/null
777 wait_for_screen
Mark Salyzyn62909822017-10-09 09:27:16 -0700778 EXPECT_PROPERTY sys.boot.reason ${panic_msg}
779 EXPECT_PROPERTY persist.sys.boot.reason ${panic_msg}
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700780 report_bootstat_logs kernel_panic,sysrq
Mark Salyzyn62909822017-10-09 09:27:16 -0700781 exitPstore
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700782}
783
784[ "USAGE: test_warm
785
786warm test
787- adb reboot warm
788- (wait until screen is up, boot has completed)
789- adb shell getprop sys.boot.reason
790- NB: should report warm" ]
791test_warm() {
792 blind_reboot_test
793}
794
795[ "USAGE: test_thermal_shutdown
796
797thermal shutdown test:
798- adb shell setprop sys.powerctl shutdown,thermal
799- (power up the device)
800- (wait until screen is up, boot has completed)
801- adb shell getprop sys.boot.reason
802- NB: should report shutdown,thermal" ]
803test_thermal_shutdown() {
Mark Salyzyn244947e2017-10-13 09:21:50 -0700804 duration_test ">60"
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700805 echo " power on request" >&2
806 adb shell setprop sys.powerctl shutdown,thermal
807 sleep 5
808 echo -n "WARNING: Please power device back up, waiting ... " >&2
809 wait_for_screen -n >&2
810 EXPECT_PROPERTY sys.boot.reason shutdown,thermal
811 EXPECT_PROPERTY persist.sys.boot.reason shutdown,thermal
812 report_bootstat_logs shutdown,thermal
813}
814
815[ "USAGE: test_userrequested_shutdown
816
817userrequested shutdown test:
818- adb shell setprop sys.powerctl shutdown,userrequested
819- (power up the device)
820- (wait until screen is up, boot has completed)
821- adb shell getprop sys.boot.reason
822- NB: should report shutdown,userrequested" ]
823test_userrequested_shutdown() {
Mark Salyzyn2450cb12017-10-10 10:44:57 -0700824 duration_test ">60"
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700825 echo " power on request" >&2
826 adb shell setprop sys.powerctl shutdown,userrequested
827 sleep 5
828 echo -n "WARNING: Please power device back up, waiting ... " >&2
829 wait_for_screen -n >&2
830 EXPECT_PROPERTY sys.boot.reason shutdown,userrequested
831 EXPECT_PROPERTY persist.sys.boot.reason shutdown,userrequested
832 report_bootstat_logs shutdown,userrequested
833}
834
Mark Salyzyn277eca12017-09-11 15:22:57 -0700835[ "USAGE: test_shell_reboot
836
837shell reboot test:
838- adb shell reboot
839- (wait until screen is up, boot has completed)
840- adb shell getprop sys.boot.reason
841- NB: should report reboot,shell" ]
842test_shell_reboot() {
Mark Salyzyn2450cb12017-10-10 10:44:57 -0700843 duration_test
Mark Salyzyn277eca12017-09-11 15:22:57 -0700844 adb shell reboot
845 wait_for_screen
846 EXPECT_PROPERTY sys.boot.reason reboot,shell
847 EXPECT_PROPERTY persist.sys.boot.reason reboot,shell
848 report_bootstat_logs reboot,shell
849}
850
851[ "USAGE: test_adb_reboot
852
853adb reboot test:
854- adb reboot
855- (wait until screen is up, boot has completed)
856- adb shell getprop sys.boot.reason
857- NB: should report reboot,adb" ]
858test_adb_reboot() {
Mark Salyzyn2450cb12017-10-10 10:44:57 -0700859 duration_test
Mark Salyzyn277eca12017-09-11 15:22:57 -0700860 adb reboot
861 wait_for_screen
862 EXPECT_PROPERTY sys.boot.reason reboot,adb
863 EXPECT_PROPERTY persist.sys.boot.reason reboot,adb
864 report_bootstat_logs reboot,adb
865}
866
Mark Salyzyna16e4372017-09-20 08:36:12 -0700867[ "USAGE: test_Its_Just_So_Hard_reboot
868
869Its Just So Hard reboot test:
870- adb shell reboot 'Its Just So Hard'
871- (wait until screen is up, boot has completed)
872- adb shell getprop sys.boot.reason
873- NB: should report reboot,its_just_so_hard
874- NB: expect log \"... I bootstat: Unknown boot reason: reboot,its_just_so_hard\"" ]
875test_Its_Just_So_Hard_reboot() {
Mark Salyzyn2450cb12017-10-10 10:44:57 -0700876 duration_test
Mark Salyzyna16e4372017-09-20 08:36:12 -0700877 adb shell 'reboot "Its Just So Hard"'
878 wait_for_screen
879 EXPECT_PROPERTY sys.boot.reason reboot,its_just_so_hard
880 EXPECT_PROPERTY persist.sys.boot.reason "reboot,Its Just So Hard"
881 adb shell su root setprop persist.sys.boot.reason reboot,its_just_so_hard
Mark Salyzyn2450cb12017-10-10 10:44:57 -0700882 if checkDebugBuild; then
883 flag=""
884 else
885 flag="--allow_failure"
886 fi
887 EXPECT_PROPERTY persist.sys.boot.reason reboot,its_just_so_hard ${flag}
Mark Salyzyna16e4372017-09-20 08:36:12 -0700888 report_bootstat_logs reboot,its_just_so_hard
889}
890
Mark Salyzyn9a387042017-10-10 14:57:12 -0700891[ "USAGE: run_bootloader [value [expected]]
892
893bootloader boot reason injection tests:
894- setBootloaderBootReason value
895- adb shell reboot
896- (wait until screen is up, boot has completed)
897- adb shell getprop sys.boot.reason
898- NB: should report reboot,value" ]
899run_bootloader() {
900 bootloader_expected="${1}"
901 if [ -z "${bootloader_expected}" ]; then
902 bootloader_expected="${TEST#bootloader_}"
903 fi
904 if ! setBootloaderBootReason ${bootloader_expected}; then
905 echo " Skipping FAILURE." 2>&1
906 return
907 fi
908 duration_test
909 if [ X"warm" = X"${bootloader_expected}" ]; then
910 last_expected=cold
911 else
912 last_expected=warm
913 fi
914 adb reboot ${last_expected}
915 wait_for_screen
916 # Reset so that other tests do not get unexpected injection
917 setBootloaderBootReason
918 # Determine the expected values
919 sys_expected="${2}"
920 if [ -z "${sys_expected}" ]; then
921 sys_expected="`validate_reason ${bootloader_expected}`"
922 if [ "reboot" = "${sys_expected}" ]; then
923 sys_expected="${last_expected}"
924 fi
925 else
926 sys_expected=`validate_reason ${sys_expected}`
927 fi
928 case ${sys_expected} in
929 kernel_panic | kernel_panic,* | watchdog | watchdog,* )
930 last_expected=${sys_expected}
931 ;;
932 esac
933 # Check values
934 EXPECT_PROPERTY ro.boot.bootreason "${bootloader_expected}"
935 EXPECT_PROPERTY sys.boot.reason "${sys_expected}"
936 EXPECT_PROPERTY persist.sys.boot.reason "${last_expected}"
937 report_bootstat_logs "${sys_expected}"
938}
939
940[ "USAGE: test_bootloader_<type>
941
942bootloader boot reasons test injection" ]
943test_bootloader_normal() {
944 run_bootloader
945}
946
947test_bootloader_watchdog() {
948 run_bootloader
949}
950
951test_bootloader_kernel_panic() {
952 run_bootloader
953}
954
955test_bootloader_oem_powerkey() {
956 run_bootloader
957}
958
959test_bootloader_wdog_reset() {
960 run_bootloader
961}
962
963test_bootloader_cold() {
964 run_bootloader
965}
966
967test_bootloader_warm() {
968 run_bootloader
969}
970
971test_bootloader_hard() {
972 run_bootloader
973}
974
975test_bootloader_recovery() {
976 run_bootloader
977}
978
Mark Salyzynb304f6d2017-08-04 13:35:51 -0700979[ "USAGE: ${0##*/} [-s SERIAL] [tests]
980
981Mainline executive to run the above tests" ]
982
983# Rudimentary argument parsing
984
985if [ ${#} -ge 2 -a X"-s" = X"${1}" ]; then
986 export ANDROID_SERIAL="${2}"
987 shift 2
988fi
989
990if [ X"--help" = X"${1}" -o X"-h" = X"${1}" -o X"-?" = X"${1}" ]; then
991 echo "USAGE: ${0##*/} [-s SERIAL] [tests]"
992 echo tests - `sed -n 's/^test_\([^ ()]*\)() {/\1/p' $0 </dev/null`
993 exit 0
994fi
995
996# Check if all conditions for the script are sane
997
998if [ -z "${ANDROID_SERIAL}" ]; then
999 ndev=`(
1000 adb devices | grep -v 'List of devices attached'
1001 fastboot devices
1002 ) |
1003 grep -v "^[${SPACE}${TAB}]*\$" |
1004 wc -l`
1005 if [ ${ndev} -gt 1 ]; then
1006 echo "ERROR: no target device specified, ${ndev} connected" >&2
1007 echo "${RED}[ FAILED ]${NORMAL}"
1008 exit 1
1009 fi
1010 echo "WARNING: no target device specified" >&2
1011fi
1012
1013ret=0
1014
1015# Test Series
1016if [ X"all" = X"${*}" ]; then
1017 # automagically pick up all test_<function>s.
1018 eval set nothing `sed -n 's/^test_\([^ ()]*\)() {/\1/p' $0 </dev/null`
1019 if [ X"nothing" = X"${1}" ]; then
1020 shift 1
1021 fi
1022fi
1023if [ -z "$*" ]; then
1024 # automagically pick up all test_<function>, except test_optional_<function>.
1025 eval set nothing `sed -n 's/^test_\([^ ()]*\)() {/\1/p' $0 </dev/null |
1026 grep -v '^optional_'`
1027 if [ -z "${2}" ]; then
1028 # Hard coded should shell fail to find them above (search/permission issues)
Mark Salyzyn9a387042017-10-10 14:57:12 -07001029 eval set properties ota cold factory_reset hard battery unknown \
1030 kernel_panic warm thermal_shutdown userrequested_shutdown \
1031 shell_reboot adb_reboot Its_Just_So_Hard_reboot \
1032 bootloader_normal bootloader_watchdog bootloader_kernel_panic \
1033 bootloader_oem_powerkey bootloader_wdog_reset \
1034 bootloader_wdog_reset bootloader_wdog_reset bootloader_hard \
1035 bootloader_recovery
Mark Salyzynb304f6d2017-08-04 13:35:51 -07001036 fi
1037 if [ X"nothing" = X"${1}" ]; then
1038 shift 1
1039 fi
1040fi
1041echo "INFO: selected test(s): ${@}" >&2
1042echo
Mark Salyzyn9a387042017-10-10 14:57:12 -07001043# Prepare device
1044setBootloaderBootReason 2>/dev/null
1045# Start pouring through the tests.
Mark Salyzynb304f6d2017-08-04 13:35:51 -07001046failures=
1047successes=
1048for t in "${@}"; do
1049 wrap_test ${t}
1050 retval=${?}
1051 if [ 0 = ${retval} ]; then
1052 if [ -z "${successes}" ]; then
1053 successes=${t}
1054 else
1055 successes="${successes} ${t}"
1056 fi
1057 else
1058 ret=${retval}
1059 if [ -z "${failures}" ]; then
1060 failures=${t}
1061 else
1062 failures="${failures} ${t}"
1063 fi
1064 fi
1065 echo
1066done
1067
1068if [ -n "${successes}" ]; then
1069 echo "${GREEN}[ PASSED ]${NORMAL} ${successes}"
1070fi
1071if [ -n "${failures}" ]; then
1072 echo "${RED}[ FAILED ]${NORMAL} ${failures}"
1073fi
1074exit ${ret}