12a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux#!/bin/bash 22a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux# 32a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux# Runs robolectric tests. 42a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux 52a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieuxset -euo pipefail 62a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux 72a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux# Terminate with a fatal error. 82a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieuxfunction fatal() { 92a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux echo "Fatal: $*" 102a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux exit 113 112a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux} 122a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux 132a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux# Ensures that the given variable is set. 142a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieuxfunction validate_var() { 152a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux local name="$1"; shift || fatal "Missing argument: name" 162a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux test $# = 0 || fatal "Too many arguments" 172a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux 182a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux eval [[ -n \${${name}+dummy} ]] || { 192a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux echo "Variable not set: $name"; 202a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux return 1; 212a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux } 222a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux} 232a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux 242a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux# Ensures that all the required variables are set. 252a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieuxfunction validate_vars() { 262a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux test $# = 0 || fatal "Too many arguments" 272a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux 282a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux validate_var 'PRIVATE_INTERMEDIATES' 292a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux validate_var 'PRIVATE_JARS' 302a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux validate_var 'PRIVATE_JAVA_ARGS' 312a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux validate_var 'PRIVATE_ROBOLECTRIC_PATH' 322a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux validate_var 'PRIVATE_ROBOLECTRIC_SCRIPT_PATH' 332a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux validate_var 'PRIVATE_RUN_INDIVIDUALLY' 342a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux validate_var 'PRIVATE_TARGET_MESSAGE' 352a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux validate_var 'PRIVATE_TESTS' 362a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux validate_var 'PRIVATE_TIMEOUT' 372a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux 382a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux validate_var 'XML_OUTPUT_FILE' 392a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux validate_var 'TEST_WORKSPACE' 402a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux} 412a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux 422a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux# Remove leading and trailing spaces around the given argument. 432a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieuxfunction strip() { 442a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux local value="$1"; shift || fatal "Missing argument: value" 452a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux test $# = 0 || fatal "Too many arguments" 462a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux 472a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux echo "$value" | sed -e 's/^ *//' -e 's/ *$//' 482a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux} 492a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux 502a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux# Normalizes a list of paths and turns it into a colon-separated list. 512a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieuxfunction normalize-path-list() { 522a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux echo "$@" | sed -e 's/^ *//' -e 's/ *$//' -e 's/ */ /g' -e 's/ /:/g' 532a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux} 542a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux 552a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieuxfunction junit() { 562a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux # This adds the lib folder to the cp. 572a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux local classpath="$(strip "$(normalize-path-list "${PRIVATE_JARS}")")" 5890f0b8e738c88e2da4ced82afd20cdc0ec6fce3fMaurice Lam # Setting the DEBUG_ROBOLECTRIC environment variable will print additional logging from 5990f0b8e738c88e2da4ced82afd20cdc0ec6fce3fMaurice Lam # Robolectric and also make it wait for a debugger to be connected. 6090f0b8e738c88e2da4ced82afd20cdc0ec6fce3fMaurice Lam # For Android Studio / IntelliJ the debugger can be connected via the "remote" configuration: 6190f0b8e738c88e2da4ced82afd20cdc0ec6fce3fMaurice Lam # https://www.jetbrains.com/help/idea/2016.2/run-debug-configuration-remote.html 6290f0b8e738c88e2da4ced82afd20cdc0ec6fce3fMaurice Lam # From command line the debugger can be connected via 6390f0b8e738c88e2da4ced82afd20cdc0ec6fce3fMaurice Lam # jdb -attach localhost:5005 6490f0b8e738c88e2da4ced82afd20cdc0ec6fce3fMaurice Lam if [ -n ${DEBUG_ROBOLECTRIC:-""} ]; then 6590f0b8e738c88e2da4ced82afd20cdc0ec6fce3fMaurice Lam # The arguments to the JVM needed to debug the tests. 6690f0b8e738c88e2da4ced82afd20cdc0ec6fce3fMaurice Lam # - server: wait for connection rather than connecting to a debugger 6790f0b8e738c88e2da4ced82afd20cdc0ec6fce3fMaurice Lam # - transport: how to accept debugger connections (sockets) 6890f0b8e738c88e2da4ced82afd20cdc0ec6fce3fMaurice Lam # - address: the port on which to accept debugger connections 6990f0b8e738c88e2da4ced82afd20cdc0ec6fce3fMaurice Lam # - timeout: how long (in ms) to wait for a debugger to connect 7090f0b8e738c88e2da4ced82afd20cdc0ec6fce3fMaurice Lam # - suspend: do not start running any code until the debugger connects 7190f0b8e738c88e2da4ced82afd20cdc0ec6fce3fMaurice Lam local debug_java_args="-Drobolectric.logging.enabled=true \ 7290f0b8e738c88e2da4ced82afd20cdc0ec6fce3fMaurice Lam -Xdebug -agentlib:jdwp=server=y,transport=dt_socket,address=localhost:5005,suspend=y" 7390f0b8e738c88e2da4ced82afd20cdc0ec6fce3fMaurice Lam # Remove the timeout so Robolectric doesn't get killed while debugging 7490f0b8e738c88e2da4ced82afd20cdc0ec6fce3fMaurice Lam local debug_timeout="0" 7590f0b8e738c88e2da4ced82afd20cdc0ec6fce3fMaurice Lam fi 762a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux local command=( 772a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux "${PRIVATE_ROBOLECTRIC_SCRIPT_PATH}/java-timeout" 7890f0b8e738c88e2da4ced82afd20cdc0ec6fce3fMaurice Lam "${debug_timeout:-${PRIVATE_TIMEOUT}}" 7990f0b8e738c88e2da4ced82afd20cdc0ec6fce3fMaurice Lam ${debug_java_args:-${PRIVATE_JAVA_ARGS}} 802a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux -Drobolectric.dependency.dir="${PRIVATE_ROBOLECTRIC_PATH}" 812a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux -Drobolectric.offline=true 822a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux -Drobolectric.logging=stdout 832a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux -cp "$classpath" 842a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux com.android.junitxml.JUnitXmlRunner 852a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux ) 862a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux echo "${command[@]}" "$@" 872a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux "${command[@]}" "$@" 882a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux} 892a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux 902a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieuxfunction runtests() { 912a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux local tests="$1"; shift || fatal "Missing argument: tests" 922a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux test $# = 0 || fatal "Too many arguments" 932a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux 942a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux if [[ "$(strip "${PRIVATE_RUN_INDIVIDUALLY}")" = 'true' ]]; then 952a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux local result=0 962a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux for test in ${tests}; do 972a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux echo "-------------------------------------------------------------------" 982a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux echo "Running $test:" 992a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux junit "${test}" 1002a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux done 1012a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux return "$result" 1022a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux else 1032a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux echo "-------------------------------------------------------------------" 1042a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux echo "Running $tests:" 1052a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux junit $tests # Contains a space-separated list of tests. 1062a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux fi 1072a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux} 1082a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux 1092a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux# Run the robolectric tests 1102a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieuxfunction run() { 1112a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux test $# = 0 || fatal "Too many arguments" 1122a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux 1132a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux [ "${PRIVATE_TARGET_MESSAGE}" == '' ] || echo "${PRIVATE_TARGET_MESSAGE}" 1142a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux local tests="${PRIVATE_TESTS}" 1152a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux if [ "$tests" = '' ]; then 1162a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux # Somehow there are no tests to run. Assume this is failure. 1172a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux echo "No tests to run." 1182a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux exit 1 1192a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux fi 1202a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux local output="${PRIVATE_INTERMEDIATES}/output.out" 1212a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux local failed="${PRIVATE_INTERMEDIATES}/failed.out" 1222a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux local result=0 1232a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux runtests "${tests}" >"$output" 2>&1 || result="$?" 1242a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux echo "$output" 1252a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux cat "$output" 1262a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux if [ "$result" = 0 ]; then 1272a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux return "$result" 1282a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux fi 1292a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux "${PRIVATE_ROBOLECTRIC_SCRIPT_PATH}/list_failed.sh" <"$output" >"$failed" 1302a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux return "$result" 1312a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux} 1322a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux 1332a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieuxfunction main() { 1342a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux test $# = 0 || fatal "Too many arguments" 1352a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux 1362a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux validate_vars 1372a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux run 1382a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux} 1392a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieux 1402a2559e5581c585721d342ffe6dceff6c5d7019eJames Lemieuxmain "$@" 141