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 -cp "$classpath" 84 com.android.junitxml.JUnitXmlRunner 85 ) 86 echo "${command[@]}" "$@" 87 "${command[@]}" "$@" 88} 89 90function runtests() { 91 local tests="$1"; shift || fatal "Missing argument: tests" 92 test $# = 0 || fatal "Too many arguments" 93 94 if [[ "$(strip "${PRIVATE_RUN_INDIVIDUALLY}")" = 'true' ]]; then 95 local result=0 96 for test in ${tests}; do 97 echo "-------------------------------------------------------------------" 98 echo "Running $test:" 99 junit "${test}" 100 done 101 return "$result" 102 else 103 echo "-------------------------------------------------------------------" 104 echo "Running $tests:" 105 junit $tests # Contains a space-separated list of tests. 106 fi 107} 108 109# Run the robolectric tests 110function run() { 111 test $# = 0 || fatal "Too many arguments" 112 113 [ "${PRIVATE_TARGET_MESSAGE}" == '' ] || echo "${PRIVATE_TARGET_MESSAGE}" 114 local tests="${PRIVATE_TESTS}" 115 if [ "$tests" = '' ]; then 116 # Somehow there are no tests to run. Assume this is failure. 117 echo "No tests to run." 118 exit 1 119 fi 120 local output="${PRIVATE_INTERMEDIATES}/output.out" 121 local failed="${PRIVATE_INTERMEDIATES}/failed.out" 122 local result=0 123 runtests "${tests}" >"$output" 2>&1 || result="$?" 124 echo "$output" 125 cat "$output" 126 if [ "$result" = 0 ]; then 127 return "$result" 128 fi 129 "${PRIVATE_ROBOLECTRIC_SCRIPT_PATH}/list_failed.sh" <"$output" >"$failed" 130 return "$result" 131} 132 133function main() { 134 test $# = 0 || fatal "Too many arguments" 135 136 validate_vars 137 run 138} 139 140main "$@" 141