1#!/bin/bash 2# 3# Runs robolectric tests. 4 5set -euo pipefail 6 7# Terminate with a fatal error. 8function fatal() { 9 echo "Fatal: $*" 10 exit 113 11} 12 13# Ensures that the given variable is set. 14function validate_var() { 15 local name="$1"; shift || fatal "Missing argument: name" 16 test $# = 0 || fatal "Too many arguments" 17 18 eval [[ -n \${${name}+dummy} ]] || { 19 echo "Variable not set: $name"; 20 return 1; 21 } 22} 23 24# Ensures that all the required variables are set. 25function validate_vars() { 26 test $# = 0 || fatal "Too many arguments" 27 28 validate_var 'PRIVATE_INTERMEDIATES' 29 validate_var 'PRIVATE_JARS' 30 validate_var 'PRIVATE_JAVA_ARGS' 31 validate_var 'PRIVATE_ROBOLECTRIC_PATH' 32 validate_var 'PRIVATE_ROBOLECTRIC_SCRIPT_PATH' 33 validate_var 'PRIVATE_RUN_INDIVIDUALLY' 34 validate_var 'PRIVATE_TARGET_MESSAGE' 35 validate_var 'PRIVATE_TESTS' 36 validate_var 'PRIVATE_TIMEOUT' 37 38 validate_var 'XML_OUTPUT_FILE' 39 validate_var 'TEST_WORKSPACE' 40} 41 42# Remove leading and trailing spaces around the given argument. 43function strip() { 44 local value="$1"; shift || fatal "Missing argument: value" 45 test $# = 0 || fatal "Too many arguments" 46 47 echo "$value" | sed -e 's/^ *//' -e 's/ *$//' 48} 49 50# Normalizes a list of paths and turns it into a colon-separated list. 51function normalize-path-list() { 52 echo "$@" | sed -e 's/^ *//' -e 's/ *$//' -e 's/ */ /g' -e 's/ /:/g' 53} 54 55function junit() { 56 # This adds the lib folder to the cp. 57 local classpath="$(strip "$(normalize-path-list "${PRIVATE_JARS}")")" 58 # Setting the DEBUG_ROBOLECTRIC environment variable will print additional logging from 59 # Robolectric and also make it wait for a debugger to be connected. 60 # For Android Studio / IntelliJ the debugger can be connected via the "remote" configuration: 61 # https://www.jetbrains.com/help/idea/2016.2/run-debug-configuration-remote.html 62 # From command line the debugger can be connected via 63 # jdb -attach localhost:5005 64 if [ -n ${DEBUG_ROBOLECTRIC:-""} ]; then 65 # The arguments to the JVM needed to debug the tests. 66 # - server: wait for connection rather than connecting to a debugger 67 # - transport: how to accept debugger connections (sockets) 68 # - address: the port on which to accept debugger connections 69 # - timeout: how long (in ms) to wait for a debugger to connect 70 # - suspend: do not start running any code until the debugger connects 71 local debug_java_args="-Drobolectric.logging.enabled=true \ 72 -Xdebug -agentlib:jdwp=server=y,transport=dt_socket,address=localhost:5005,suspend=y" 73 # Remove the timeout so Robolectric doesn't get killed while debugging 74 local debug_timeout="0" 75 fi 76 local command=( 77 "${PRIVATE_ROBOLECTRIC_SCRIPT_PATH}/java-timeout" 78 "${debug_timeout:-${PRIVATE_TIMEOUT}}" 79 ${debug_java_args:-${PRIVATE_JAVA_ARGS}} 80 -Drobolectric.dependency.dir="${PRIVATE_ROBOLECTRIC_PATH}" 81 -Drobolectric.offline=true 82 -Drobolectric.logging=stdout 83 -Drobolectric.usePreinstrumentedJars=false 84 -Drobolectric.conscryptMode=OFF 85 -Drobolectric.logging.enabled=true 86 -cp "$classpath" 87 com.android.junitxml.JUnitXmlRunner 88 ) 89 echo "${command[@]}" "$@" 90 "${command[@]}" "$@" 91} 92 93function runtests() { 94 local tests="$1"; shift || fatal "Missing argument: tests" 95 test $# = 0 || fatal "Too many arguments" 96 97 if [[ "$(strip "${PRIVATE_RUN_INDIVIDUALLY}")" = 'true' ]]; then 98 local result=0 99 for test in ${tests}; do 100 echo "-------------------------------------------------------------------" 101 echo "Running $test:" 102 junit "${test}" 103 done 104 return "$result" 105 else 106 echo "-------------------------------------------------------------------" 107 echo "Running $tests:" 108 junit $tests # Contains a space-separated list of tests. 109 fi 110} 111 112# Run the robolectric tests 113function run() { 114 test $# = 0 || fatal "Too many arguments" 115 116 [ "${PRIVATE_TARGET_MESSAGE}" == '' ] || echo "${PRIVATE_TARGET_MESSAGE}" 117 local tests="${PRIVATE_TESTS}" 118 if [ "$tests" = '' ]; then 119 # Somehow there are no tests to run. Assume this is failure. 120 echo "No tests to run." 121 exit 1 122 fi 123 local output="${PRIVATE_INTERMEDIATES}/output.out" 124 local failed="${PRIVATE_INTERMEDIATES}/failed.out" 125 local result=0 126 runtests "${tests}" >"$output" 2>&1 || result="$?" 127 echo "$output" 128 cat "$output" 129 if [ "$result" = 0 ]; then 130 return "$result" 131 fi 132 "${PRIVATE_ROBOLECTRIC_SCRIPT_PATH}/list_failed.sh" <"$output" >"$failed" 133 return "$result" 134} 135 136function main() { 137 test $# = 0 || fatal "Too many arguments" 138 139 validate_vars 140 run 141} 142 143main "$@" 144