diff options
author | Mark Salyzyn <salyzyn@google.com> | 2017-10-10 14:57:12 -0700 |
---|---|---|
committer | Mark Salyzyn <salyzyn@google.com> | 2017-10-11 13:48:33 -0700 |
commit | 9a3870490a005ac73dc1e2be202e0824cc239e43 (patch) | |
tree | 35b5d46079fa5c95388c923b540e6d1cebe30f35 /bootstat | |
parent | bb52cbf35d7b6889fc79e0efc84983d177d60ca0 (diff) | |
download | core-9a3870490a005ac73dc1e2be202e0824cc239e43.tar.gz core-9a3870490a005ac73dc1e2be202e0824cc239e43.tar.bz2 core-9a3870490a005ac73dc1e2be202e0824cc239e43.zip |
bootstat: test: inject ro.boot.bootreason values
Adding a set of automated engineering unit tests with a strict list of
prerequisites. Not meant for "user" builds. Must have a crafted
bootloader that does not set the boot reason. Only works on platforms
where the bootloader either by accident or specifically does not set
the ro.boot.bootreason via kernel command line configuration
androidboot.bootreason=. If the tests do not have the prerequisites,
the test will report success, but with protest.
These new tests should work on current Hikey and Hikey960 bootloaders
but could very well become obsolete if those platform bootloaders
start setting the boot reason.
We do not want a platform solution as it could allow a third party to
override the bootloader boot reason.
Test: system/core/bootstat/boot_reason_test.sh
Bug: 63736262
Change-Id: I1793184a8484b83e1d9077475bc65af9816dadf7
Diffstat (limited to 'bootstat')
-rw-r--r-- | bootstat/Android.bp | 5 | ||||
-rwxr-xr-x | bootstat/boot_reason_test.sh | 188 | ||||
-rw-r--r-- | bootstat/bootstat-debug.rc | 7 |
3 files changed, 172 insertions, 28 deletions
diff --git a/bootstat/Android.bp b/bootstat/Android.bp index 6734f4d91..2c870182c 100644 --- a/bootstat/Android.bp +++ b/bootstat/Android.bp @@ -65,6 +65,11 @@ cc_binary { static_libs: ["libbootstat"], shared_libs: ["liblogcat"], init_rc: ["bootstat.rc"], + product_variables: { + debuggable: { + init_rc: ["bootstat-debug.rc"], + }, + }, srcs: ["bootstat.cpp"], } diff --git a/bootstat/boot_reason_test.sh b/bootstat/boot_reason_test.sh index c42680cba..7a45e4dc3 100755 --- a/bootstat/boot_reason_test.sh +++ b/bootstat/boot_reason_test.sh @@ -74,6 +74,30 @@ checkDebugBuild() { fi >&2 } +[ "USAGE: setBootloaderBootReason [value] + +Returns: true if device supports and set boot reason injection" ] +setBootloaderBootReason() { + inAdb || ( echo "ERROR: device not in adb mode." >&2 ; false ) || return 1 + if [ -z "`adb shell ls /etc/init/bootstat-debug.rc 2>/dev/null`" ]; then + echo "ERROR: '${TEST}' test requires /etc/init/bootstat-debug.rc" >&2 + return 1 + fi + checkDebugBuild || return 1 + if adb shell su root "cat /proc/cmdline | tr '\\0 ' '\\n\\n'" | + grep '^androidboot[.]bootreason=[^ ]' >/dev/null; then + echo "ERROR: '${TEST}' test requires a device with a bootloader that" >&2 + echo " does not set androidboot.bootreason kernel parameter." >&2 + return 1 + fi + adb shell su root setprop persist.test.boot.reason "'${1}'" 2>/dev/null + test_reason="`adb shell getprop persist.test.boot.reason 2>/dev/null`" + if [ X"${test_reason}" != X"${1}" ]; then + echo "ERROR: can not set persist.test.boot.reason to '${1}'." >&2 + return 1 + fi +} + [ "USAGE: enterPstore Prints a warning string requiring functional pstore @@ -259,6 +283,8 @@ bootstat: Service started: /system/bin/bootstat -l bootstat: Battery level at shutdown 100% bootstat: Battery level at startup 100% init : Parsing file /system/etc/init/bootstat.rc... +init : processing action (persist.test.boot.reason=*) from (/system/etc/init/bootstat-debug.rc: +init : Command 'setprop ro.boot.bootreason \${persist.test.boot.reason}' action=persist.test.boot.reason=* (/system/etc/init/bootstat-debug.rc: init : processing action (post-fs-data) from (/system/etc/init/bootstat.rc init : processing action (boot) from (/system/etc/init/bootstat.rc init : processing action (ro.boot.bootreason=*) from (/system/etc/init/bootstat.rc @@ -361,37 +387,33 @@ wrap_test() { end_test ${2} } -[ "USAGE: validate_property <property> +[ "USAGE: validate_reason <value> Check property for CTS compliance with our expectations. Return a cleansed string representing what is acceptable. -NB: must roughly match heuristics in system/core/bootstat/bootstat.cpp" ] -validate_property() { - var=`adb shell getprop ${1} 2>&1` - var=`echo -n ${var} | +NB: must also roughly match heuristics in system/core/bootstat/bootstat.cpp" ] +validate_reason() { + var=`echo -n ${*} | tr '[A-Z]' '[a-z]' | tr ' \f\t\r\n' '_____'` case ${var} in - watchdog) ;; - watchdog,?*) ;; - kernel_panic) ;; - kernel_panic,?*) ;; - recovery) ;; - recovery,?*) ;; - bootloader) ;; - bootloader,?*) ;; - cold) ;; - cold,?*) ;; - hard) ;; - hard,?*) ;; - warm) ;; - warm,?*) ;; - shutdown) ;; - shutdown,?*) ;; - reboot) ;; - reboot,?*) ;; - # Aliases + watchdog | watchdog,?* ) ;; + kernel_panic | kernel_panic,?*) ;; + recovery | recovery,?*) ;; + bootloader | bootloader,?*) ;; + cold | cold,?*) ;; + hard | hard,?*) ;; + warm | warm,?*) ;; + shutdown | shutdown,?*) ;; + reboot,reboot | reboot,reboot,* ) var=${var#reboot,} ; var=${var%,} ;; + reboot,cold | reboot,cold,* ) var=${var#reboot,} ; var=${var%,} ;; + reboot,hard | reboot,hard,* ) var=${var#reboot,} ; var=${var%,} ;; + reboot,warm | reboot,warm,* ) var=${var#reboot,} ; var=${var%,} ;; + reboot,recovery | reboot,recovery,* ) var=${var#reboot,} ; var=${var%,} ;; + reboot,bootloader | reboot,bootloader,* ) var=${var#reboot,} ; var=${var%,} ;; + reboot | reboot,?*) ;; + # Aliases and Heuristics *wdog* | *watchdog* ) var="watchdog" ;; *powerkey* ) var="cold,powerkey" ;; *panic* | *kernel_panic*) var="kernel_panic" ;; @@ -399,12 +421,26 @@ validate_property() { *s3_wakeup*) var="warm,s3_wakeup" ;; *hw_reset*) var="hard,hw_reset" ;; *bootloader*) var="bootloader" ;; - ?*) var="reboot,${var}" ;; *) var="reboot" ;; esac echo ${var} } +[ "USAGE: validate_property <property> + +Check property for CTS compliance with our expectations. Return a cleansed +string representing what is acceptable. + +NB: must also roughly match heuristics in system/core/bootstat/bootstat.cpp" ] +validate_property() { + val="`adb shell getprop ${1} 2>&1`" + ret=`validate_reason "${val}"` + if [ "reboot" = "${ret}" ]; then + ret=`validate_reason "reboot,${val}"` + fi + echo ${ret} +} + # # Actual test frames # @@ -428,7 +464,7 @@ test_properties() { # ERROR: expected "reboot" got "" # for Android property persist.sys.boot.reason # following is mitigation for the persist.sys.boot.reason, skip it - if [ "reboot,factory_reset" = `validate_property ro.boot_bootreason` ]; then + if [ "reboot,factory_reset" = "`validate_property ro.boot_bootreason`" ]; then check_set="ro.boot.bootreason sys.boot.reason" bootloader="bootloader" fi @@ -843,6 +879,94 @@ test_Its_Just_So_Hard_reboot() { report_bootstat_logs reboot,its_just_so_hard } +[ "USAGE: run_bootloader [value [expected]] + +bootloader boot reason injection tests: +- setBootloaderBootReason value +- adb shell reboot +- (wait until screen is up, boot has completed) +- adb shell getprop sys.boot.reason +- NB: should report reboot,value" ] +run_bootloader() { + bootloader_expected="${1}" + if [ -z "${bootloader_expected}" ]; then + bootloader_expected="${TEST#bootloader_}" + fi + if ! setBootloaderBootReason ${bootloader_expected}; then + echo " Skipping FAILURE." 2>&1 + return + fi + duration_test + if [ X"warm" = X"${bootloader_expected}" ]; then + last_expected=cold + else + last_expected=warm + fi + adb reboot ${last_expected} + wait_for_screen + # Reset so that other tests do not get unexpected injection + setBootloaderBootReason + # Determine the expected values + sys_expected="${2}" + if [ -z "${sys_expected}" ]; then + sys_expected="`validate_reason ${bootloader_expected}`" + if [ "reboot" = "${sys_expected}" ]; then + sys_expected="${last_expected}" + fi + else + sys_expected=`validate_reason ${sys_expected}` + fi + case ${sys_expected} in + kernel_panic | kernel_panic,* | watchdog | watchdog,* ) + last_expected=${sys_expected} + ;; + esac + # Check values + EXPECT_PROPERTY ro.boot.bootreason "${bootloader_expected}" + EXPECT_PROPERTY sys.boot.reason "${sys_expected}" + EXPECT_PROPERTY persist.sys.boot.reason "${last_expected}" + report_bootstat_logs "${sys_expected}" +} + +[ "USAGE: test_bootloader_<type> + +bootloader boot reasons test injection" ] +test_bootloader_normal() { + run_bootloader +} + +test_bootloader_watchdog() { + run_bootloader +} + +test_bootloader_kernel_panic() { + run_bootloader +} + +test_bootloader_oem_powerkey() { + run_bootloader +} + +test_bootloader_wdog_reset() { + run_bootloader +} + +test_bootloader_cold() { + run_bootloader +} + +test_bootloader_warm() { + run_bootloader +} + +test_bootloader_hard() { + run_bootloader +} + +test_bootloader_recovery() { + run_bootloader +} + [ "USAGE: ${0##*/} [-s SERIAL] [tests] Mainline executive to run the above tests" ] @@ -893,8 +1017,13 @@ if [ -z "$*" ]; then grep -v '^optional_'` if [ -z "${2}" ]; then # Hard coded should shell fail to find them above (search/permission issues) - eval set ota cold factory_reset hard battery unknown kernel_panic warm \ - thermal_shutdown userrequested_shutdown shell_reboot adb_reboot + eval set properties ota cold factory_reset hard battery unknown \ + kernel_panic warm thermal_shutdown userrequested_shutdown \ + shell_reboot adb_reboot Its_Just_So_Hard_reboot \ + bootloader_normal bootloader_watchdog bootloader_kernel_panic \ + bootloader_oem_powerkey bootloader_wdog_reset \ + bootloader_wdog_reset bootloader_wdog_reset bootloader_hard \ + bootloader_recovery fi if [ X"nothing" = X"${1}" ]; then shift 1 @@ -902,6 +1031,9 @@ if [ -z "$*" ]; then fi echo "INFO: selected test(s): ${@}" >&2 echo +# Prepare device +setBootloaderBootReason 2>/dev/null +# Start pouring through the tests. failures= successes= for t in "${@}"; do diff --git a/bootstat/bootstat-debug.rc b/bootstat/bootstat-debug.rc new file mode 100644 index 000000000..6a0044067 --- /dev/null +++ b/bootstat/bootstat-debug.rc @@ -0,0 +1,7 @@ +# This file is the userdebug LOCAL_INIT_RC file for the bootstat command. + +# FOR TESTING +# For devices w/o bootloader boot reason reported, mirror test boot reason +# to bootloader boot reason to allow test to inject reasons +on property:persist.test.boot.reason=* + setprop ro.boot.bootreason ${persist.test.boot.reason} |