blob: 5e4cbd6296d379ad9730151fc5e977da01176692 [file] [log] [blame]
#!/bin/bash
#
# Copyright (C) 2008 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Options and default values
# TODO: other options ideas:
# pass options to am (then remove some of the more specific options)
# TODO capture more non-error output when not -v
# TODO read configs from vendor/*, not just from vendor/google
optListTests=0
optSkipBuild=0
optPreview=0
optRawmode=0
optSuiteAssignmentMode=0
optAdbTarget=""
optVerbose=0
optWaitForDebugger=0
optTestClass=""
optTestMethod=""
optUserTests=${HOME}/.android/runtest.rc
#
# process command-line options. You must pass them into this function.
# TODO error messages on once-only or mutually-exclusive options
#
function processOptions() {
while getopts "l b n a r d e s: v w c:t:u:" opt ; do
case ${opt} in
l ) optListTests=1 ;;
b ) optSkipBuild=1 ;;
n ) optPreview=1 ;;
r ) optRawMode=1 ;;
a ) optSuiteAssignmentMode=1 ;;
d ) optAdbTarget="-d" ;;
e ) optAdbTarget="-e" ;;
s ) optAdbTarget="-s ${OPTARG}" ;;
v ) optVerbose=1 ;;
w ) optWaitForDebugger=1 ;;
c ) optTestClass=${OPTARG} ;;
t ) optTestMethod=${OPTARG} ;;
u ) optUserTests=${OPTARG} ;;
esac
done
}
#
# Show the command usage and options
#
function showUsage() {
echo "usage: The $progName script works in two ways. You can query it for a list" >&2
echo " of tests, or you can launch a test, test case, or test suite." >&2
echo "" >&2
echo " $progName -l # To view the list of tests" >&2
echo "" >&2
echo " $progName # To launch tests" >&2
echo " [-b] # Skip build - just launch" >&2
echo " [-n] # Do not execute, just preview commands" >&2
echo " [-r] # Raw mode (for output to other tools)" >&2
echo " [-a] # Suite assignment (for details & usage" >&2
echo " # see InstrumentationTestRunner)" >&2
echo " [-v] # Increase verbosity of ${progName}" >&2
echo " [-w] # Wait for debugger before launching tests" >&2
echo " [-c test-class] # Restrict test to a specific class" >&2
echo " [-t test-method] # Restrict test to a specific method" >&2
echo " [-e | -d | -s ser-num] # use emulator, device, or serial number" >&2
echo " [-u user-tests-file] # Alternate source of user definitions" >&2
echo " short-test-name # (req'd) test configuration to launch" >&2
}
# The list below are built-in test definitions. You can also define your own
# tests by creating a file named "~/.android/runtest.rc" and adding them to that
# file. (No array needed, just plain lines of text).
#
# Tests are defined by entries with the following format:
# <short-name> <build-path> <test-package> <test-class>
# <testrunner-package> <testrunner-component>
#
# These map to the following commands:
# (if test-class = "#")
# adb shell am instrument -w \
# <testrunner-package>/<testrunner-component>
# (else)
# adb shell am instrument -w \
# -e class <test-package>.<test-class> \
# <testrunner-package>/<testrunner-component>
#
# In order to define the most common cases simply, "#" can be used for some of
# the fields, with the following default values:
# <build-path> = "#": skip build/sync step
# <test-package> = "#": test class is fully qualified with package
# <test-class> = "#": omit "-e class" section
# <testrunner-package> = "#": use same value as test-package
# <testrunner-component> = "#": use "android.test.InstrumentationTestRunner"
#
# TODO: fields may be omitted completely if the trailing values are all "#"
# TODO: this should be a here doc instead of an array
knownTests=(
# NAME BUILD DIR <test-package> <test-class> <testrunner-package> <testrunner-component>
# system-wide tests
"framework frameworks/base/tests/FrameworkTest # com.android.frameworktest.AllTests com.android.frameworktest.tests #"
"account frameworks/base/tests/AndroidTests # com.android.unit_tests.accounts.AccountManagerServiceTest com.android.unit_tests #"
"android frameworks/base/tests/AndroidTests com.android.unit_tests AndroidTests # #"
"smoke frameworks/base/tests/SmokeTest com.android.smoketest # com.android.smoketest.tests #"
"core frameworks/base/tests/CoreTests # android.core.CoreTests android.core #"
"libcore frameworks/base/tests/CoreTests # android.core.JavaTests android.core #"
"apidemos development/samples/ApiDemos com.example.android.apis # com.example.android.apis.tests #"
"launchperf development/apps/launchperf com.android.launchperf # # .SimpleActivityLaunchPerformance"
# targeted framework tests
"heap frameworks/base/tests/AndroidTests com.android.unit_tests HeapTest # #"
"activity frameworks/base/tests/AndroidTests com.android.unit_tests activity.ActivityTests # #"
"deadlock tests/Deadlock com.android.deadlock # com.android.deadlock.tests #"
"syncadapter vendor/google/tests/AbstractGDataSyncAdapterTest # # com.google.android.providers.abstractgdatasyncadaptertests #"
"tablemerger frameworks/base/tests/FrameworkTest # android.content.AbstractTableMergerTest com.android.frameworktest.tests #"
# selected app tests
"browser packages/apps/Browser com.android.browser # # .BrowserTestRunner"
"browserfunc packages/apps/Browser com.android.browser # # .BrowserFunctionalTestRunner"
"calendar packages/apps/Calendar/tests com.android.calendar.tests # # #"
"calprov packages/providers/CalendarProvider com.android.providers.calendar # com.android.providers.calendar.tests #"
"camera tests/Camera com.android.cameratests # # CameraInstrumentationTestRunner"
"contactsprov packages/providers/GoogleContactsProvider/tests com.android.providers.contacts # com.android.providers.contactstests #"
"email packages/apps/Email com.android.email # com.android.email.tests #"
"emailsmall packages/apps/Email com.android.email SmallTests com.android.email.tests #"
"media tests/MediaFrameworkTest com.android.mediaframeworktest # # .MediaFrameworkTestRunner"
"mediaunit tests/MediaFrameworkTest com.android.mediaframeworktest # # .MediaFrameworkUnitTestRunner"
"mediaprov tests/MediaProvider com.android.mediaprovidertests # # .MediaProviderTestsInstrumentation"
"mms packages/apps/Mms # # com.android.mms.tests com.android.mms.ui.MMSInstrumentationTestRunner"
"mmslaunch packages/apps/Mms # # com.android.mms.tests com.android.mms.SmsLaunchPerformance"
"phone tests/Phone com.android.phonetests # # .PhoneInstrumentationTestRunner"
"phonestress tests/Phone com.android.phonetests # # .PhoneInstrumentationStressTestRunner"
"ringtone tests/RingtoneSettings com.android.ringtonesettingstests # # .RingtoneSettingsInstrumentationTestRunner"
)
#
# Searches for a runtest.rc file in a given directory and, if found, prepends it to
# the list of known tests.
#
function readConfigFile () {
rcFile=$1
if [[ -f ${rcFile} ]] ; then
declare -a lines
exec 3<${rcFile} || exit
while read curline <&3; do
if [[ -z ${curline} || ${curline:0:1} = "#" ]]; then
continue
fi
lines=("${lines[@]}" "${curline}")
done
exec 3<&-
# now prepend the user lines (so they can override defaults)
knownTests=("${lines[@]}" "${knownTests[@]}")
fi
}
#
# Searches for a specific test in the knownTests array. If found, writes out
# the remaining elements in the definition line (not including the test name).
#
function findTest() {
count=${#knownTests[@]}
index=0
while [[ ${index} -lt ${count} ]]
do
# If the first word in the entry matches the argument...
test=(${knownTests[$index]})
if [[ ${test[0]} = $1 ]] ; then
# Print all but the first word
echo ${test[@]:1}
return
fi
let "index = $index + 1"
done
}
#
# Generate a simple listing of available tests
#
function dumpTests() {
echo "The following tests are currently defined:"
count=${#knownTests[@]}
index=0
while [[ ${index} -lt ${count} ]]
do
test=(${knownTests[$index]})
echo " " ${test[0]}
let "index = $index + 1"
done
}
#
# Writes the full pathname of the "top" of the development tree, as set by envsetup & lunch.
# (based on gettop() from envsetup.sh)
#
function gettop {
TOPFILE=build/core/envsetup.mk
if [[ -n ${TOP} && -f ${TOP}/${TOPFILE} ]] ; then
echo ${TOP}
else
if [[ -f ${TOPFILE} ]] ; then
echo ${PWD}
else
# We redirect cd to /dev/null in case it's aliased to
# a command that prints something as a side-effect
# (like pushd)
HERE=${PWD}
T=
# while [ \( ! \( -f ${TOPFILE} \) \) -a \( $PWD != "/" \) ]; do
while [[ ! -f ${TOPFILE} && ${PWD} != "/" ]] ; do
cd .. > /dev/null
T=${PWD}
done
cd ${HERE} > /dev/null
if [[ -f ${T}/${TOPFILE} ]]; then
echo ${T}
fi
fi
fi
}
#
# Captures the "mmm" command from envsetup.sh
#
function call_mmm() {
TOP=$(gettop)
if [[ -n ${TOP} ]] ; then
. ${TOP}/build/envsetup.sh
mmm ${TOP}/$@
fi
}
# main script
progName=$(basename $0)
if [[ $# -eq 0 ]] ; then
showUsage
exit 1
fi
processOptions $@
shift $((OPTIND-1))
readConfigFile $optUserTests
# TODO: Read from *any* vendor/*/runtest.rc
readConfigFile $(gettop)/vendor/google/runtest.rc
# if requested, list all tests and halt
if [[ ${optListTests} -ne 0 ]] ; then
dumpTests
exit 0
fi
testInfo=($(findTest $1))
if [[ ${#testInfo[@]} -eq 5 ]] ; then
# break out test definition elements
buildPath=${testInfo[0]}
testPackage=${testInfo[1]}
testClass=${testInfo[2]}
runnerPackage=${testInfo[3]}
runnerComponent=${testInfo[4]}
# replace wildcards with default values
if [[ ${testPackage} == "#" ]] ; then
testPackage=
fi
if [[ ${runnerPackage} == "#" ]] ; then
runnerPackage=$testPackage
fi
if [[ ${runnerComponent} == "#" ]] ; then
runnerComponent="android.test.InstrumentationTestRunner"
fi
if [[ -n ${optTestClass} ]] ; then
testClass=$optTestClass
fi
# build & sync, if requested
if [[ ${optSkipBuild} -eq 0 ]] ; then
if [[ ${buildPath} != "#" ]] ; then
if [[ $optVerbose -ne 0 || ${optPreview} -ne 0 ]] ; then
echo mmm ${buildPath} "&&" adb ${optAdbTarget} remount "&&" adb ${optAdbTarget} sync
fi
if [[ ${optPreview} -eq 0 ]] ; then
call_mmm ${buildPath} && adb ${optAdbTarget} remount && adb ${optAdbTarget} sync
buildResult=$?
else
buildResult=0
fi
if [[ $buildResult -ne 0 ]] ; then
exit ${buildResult}
fi
# finally, sleep a bit. this is a hack. it gives the package manager time to
# install the package(s) that were just synced. this causes a reduction in the number
# of false failures, but it's not a perfect solution.
if [ ${optPreview} -eq 0 ] ; then
echo "sleeping..."
sleep 2
fi
fi
fi
# setup additional clauses for the command
classOptions=""
if [[ ${testClass} != "#" ]] ; then
if [[ -z ${testPackage} ]] ; then
classOptions="-e class ${testClass}"
else
classOptions="-e class ${testPackage}.${testClass}"
fi
if [[ -n ${optTestMethod} ]] ; then
classOptions=${classOptions}#${optTestMethod}
fi
fi
debugOptions=""
if [[ ${optWaitForDebugger} -ne 0 ]] ; then
debugOptions="-e debug true"
fi
fi
if [[ ${optSuiteAssignmentMode} -ne 0 ]] ; then
debugOptions="-e suiteAssignment true "${debugOptions}
fi
if [[ ${optRawMode} -ne 0 ]] ; then
debugOptions="-r "${debugOptions}
fi
# "prevent" a race condition where we try to run the tests before they're
# actually installed
if [ ${optPreview} -eq 0 ] ; then
echo "sleeping..."
sleep 2
fi
# now run the command
if [[ $optVerbose -ne 0 || ${optPreview} -ne 0 ]] ; then
echo adb ${optAdbTarget} shell am instrument -w \
${debugOptions} \
${classOptions} \
${runnerPackage}/${runnerComponent}
fi
if [[ ${optPreview} -eq 0 ]] ; then
adb ${optAdbTarget} shell am instrument -w \
${debugOptions} \
${classOptions} \
${runnerPackage}/${runnerComponent}
fi
exit 0
else
echo "$progName: unknown test \"$1\"" >&2
exit 1
fi