blob: f7d72af2b30188eab528056ac83ea1264be6e174 [file] [log] [blame]
The Android Open Source Project6ffae012009-03-18 17:39:43 -07001#!/usr/bin/python2.4
2#
3# Copyright 2008, The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
Brett Chabot59b47782009-10-21 17:23:01 -070017"""Command line utility for running Android tests
The Android Open Source Project6ffae012009-03-18 17:39:43 -070018
Brett Chabot59b47782009-10-21 17:23:01 -070019runtest helps automate the instructions for building and running tests
20- It builds the corresponding test package for the code you want to test
21- It pushes the test package to your device or emulator
22- It launches InstrumentationTestRunner (or similar) to run the tests you
23specify.
24
25runtest supports running tests whose attributes have been pre-defined in
26_TEST_FILE_NAME files, (runtest <testname>), or by specifying the file
27system path to the test to run (runtest --path <path>).
28
29Do runtest --help to see full list of options.
The Android Open Source Project6ffae012009-03-18 17:39:43 -070030"""
31
32# Python imports
33import glob
34import optparse
35import os
36from sets import Set
37import sys
38
39# local imports
40import adb_interface
41import android_build
42import coverage
43import errors
44import logger
45import run_command
Brett Chabot764d3fa2009-06-25 17:57:31 -070046from test_defs import test_defs
Brett Chabot59b47782009-10-21 17:23:01 -070047from test_defs import test_walker
The Android Open Source Project6ffae012009-03-18 17:39:43 -070048
49
50class TestRunner(object):
51 """Command line utility class for running pre-defined Android test(s)."""
52
Brett Chabotf61f43e2009-04-02 11:52:48 -070053 _TEST_FILE_NAME = "test_defs.xml"
54
The Android Open Source Project6ffae012009-03-18 17:39:43 -070055 # file path to android core platform tests, relative to android build root
56 # TODO move these test data files to another directory
Nicolas Catania97b24c42009-04-22 11:08:32 -070057 _CORE_TEST_PATH = os.path.join("development", "testrunner",
Brett Chabotf61f43e2009-04-02 11:52:48 -070058 _TEST_FILE_NAME)
The Android Open Source Project6ffae012009-03-18 17:39:43 -070059
60 # vendor glob file path patterns to tests, relative to android
61 # build root
62 _VENDOR_TEST_PATH = os.path.join("vendor", "*", "tests", "testinfo",
Brett Chabotf61f43e2009-04-02 11:52:48 -070063 _TEST_FILE_NAME)
The Android Open Source Project6ffae012009-03-18 17:39:43 -070064
65 _RUNTEST_USAGE = (
66 "usage: runtest.py [options] short-test-name[s]\n\n"
67 "The runtest script works in two ways. You can query it "
68 "for a list of tests, or you can launch one or more tests.")
69
Brett Chabot2477b382009-09-23 18:05:28 -070070 # default value for make -jX
Brett Chabot59b47782009-10-21 17:23:01 -070071 _DEFAULT_JOBS = 4
Brett Chabot2477b382009-09-23 18:05:28 -070072
Brett Chabotccae47d2010-06-14 15:19:25 -070073 _DALVIK_VERIFIER_OFF_PROP = "dalvik.vm.dexopt-flags = v=n"
74
Brett Chabot72731f32009-03-31 11:14:05 -070075 def __init__(self):
76 # disable logging of timestamp
Niko Catania2e990b92009-04-02 16:52:26 -070077 self._root_path = android_build.GetTop()
Nicolas Catania97b24c42009-04-22 11:08:32 -070078 logger.SetTimestampLogging(False)
Brett Chabot3ae5f8a2009-06-28 12:00:47 -070079 self._adb = None
80 self._known_tests = None
81 self._options = None
82 self._test_args = None
Brett Chabot59b47782009-10-21 17:23:01 -070083 self._tests_to_run = None
Brett Chabot72731f32009-03-31 11:14:05 -070084
The Android Open Source Project6ffae012009-03-18 17:39:43 -070085 def _ProcessOptions(self):
86 """Processes command-line options."""
87 # TODO error messages on once-only or mutually-exclusive options.
88 user_test_default = os.path.join(os.environ.get("HOME"), ".android",
Brett Chabotf61f43e2009-04-02 11:52:48 -070089 self._TEST_FILE_NAME)
The Android Open Source Project6ffae012009-03-18 17:39:43 -070090
91 parser = optparse.OptionParser(usage=self._RUNTEST_USAGE)
92
93 parser.add_option("-l", "--list-tests", dest="only_list_tests",
94 default=False, action="store_true",
95 help="To view the list of tests")
96 parser.add_option("-b", "--skip-build", dest="skip_build", default=False,
97 action="store_true", help="Skip build - just launch")
Brett Chabot2477b382009-09-23 18:05:28 -070098 parser.add_option("-j", "--jobs", dest="make_jobs",
99 metavar="X", default=self._DEFAULT_JOBS,
100 help="Number of make jobs to use when building")
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700101 parser.add_option("-n", "--skip_execute", dest="preview", default=False,
102 action="store_true",
103 help="Do not execute, just preview commands")
104 parser.add_option("-r", "--raw-mode", dest="raw_mode", default=False,
105 action="store_true",
106 help="Raw mode (for output to other tools)")
107 parser.add_option("-a", "--suite-assign", dest="suite_assign_mode",
108 default=False, action="store_true",
109 help="Suite assignment (for details & usage see "
110 "InstrumentationTestRunner)")
111 parser.add_option("-v", "--verbose", dest="verbose", default=False,
112 action="store_true",
113 help="Increase verbosity of %s" % sys.argv[0])
114 parser.add_option("-w", "--wait-for-debugger", dest="wait_for_debugger",
115 default=False, action="store_true",
116 help="Wait for debugger before launching tests")
117 parser.add_option("-c", "--test-class", dest="test_class",
118 help="Restrict test to a specific class")
119 parser.add_option("-m", "--test-method", dest="test_method",
120 help="Restrict test to a specific method")
Brett Chabot8a101cb2009-05-05 12:56:39 -0700121 parser.add_option("-p", "--test-package", dest="test_package",
122 help="Restrict test to a specific java package")
123 parser.add_option("-z", "--size", dest="test_size",
124 help="Restrict test to a specific test size")
Brett Chabotc0611542010-02-20 20:09:58 -0800125 parser.add_option("--annotation", dest="test_annotation",
126 help="Include only those tests tagged with a specific"
127 " annotation")
128 parser.add_option("--not-annotation", dest="test_not_annotation",
Brett Chabot2e16fbc2010-02-23 12:28:27 -0800129 help="Exclude any tests tagged with a specific"
Brett Chabotc0611542010-02-20 20:09:58 -0800130 " annotation")
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700131 parser.add_option("-u", "--user-tests-file", dest="user_tests_file",
132 metavar="FILE", default=user_test_default,
133 help="Alternate source of user test definitions")
134 parser.add_option("-o", "--coverage", dest="coverage",
135 default=False, action="store_true",
136 help="Generate code coverage metrics for test(s)")
Brett Chabot59b47782009-10-21 17:23:01 -0700137 parser.add_option("-x", "--path", dest="test_path",
138 help="Run test(s) at given file system path")
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700139 parser.add_option("-t", "--all-tests", dest="all_tests",
140 default=False, action="store_true",
141 help="Run all defined tests")
142 parser.add_option("--continuous", dest="continuous_tests",
143 default=False, action="store_true",
144 help="Run all tests defined as part of the continuous "
145 "test set")
Wei-Ta Chen97752d42009-05-21 16:24:04 -0700146 parser.add_option("--timeout", dest="timeout",
147 default=300, help="Set a timeout limit (in sec) for "
148 "running native tests on a device (default: 300 secs)")
Brett Chabot4a5d9f12010-02-18 20:01:11 -0800149 parser.add_option("--suite", dest="suite",
Brett Chabot49b77112009-06-02 11:46:04 -0700150 help="Run all tests defined as part of the "
Brett Chabot4a5d9f12010-02-18 20:01:11 -0800151 "the given test suite")
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700152 group = optparse.OptionGroup(
153 parser, "Targets", "Use these options to direct tests to a specific "
154 "Android target")
155 group.add_option("-e", "--emulator", dest="emulator", default=False,
156 action="store_true", help="use emulator")
157 group.add_option("-d", "--device", dest="device", default=False,
158 action="store_true", help="use device")
159 group.add_option("-s", "--serial", dest="serial",
160 help="use specific serial")
161 parser.add_option_group(group)
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700162 self._options, self._test_args = parser.parse_args()
163
Brett Chabot49b77112009-06-02 11:46:04 -0700164 if (not self._options.only_list_tests
165 and not self._options.all_tests
166 and not self._options.continuous_tests
Brett Chabot4a5d9f12010-02-18 20:01:11 -0800167 and not self._options.suite
Brett Chabot59b47782009-10-21 17:23:01 -0700168 and not self._options.test_path
Brett Chabot49b77112009-06-02 11:46:04 -0700169 and len(self._test_args) < 1):
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700170 parser.print_help()
171 logger.SilentLog("at least one test name must be specified")
172 raise errors.AbortError
173
174 self._adb = adb_interface.AdbInterface()
175 if self._options.emulator:
176 self._adb.SetEmulatorTarget()
177 elif self._options.device:
178 self._adb.SetDeviceTarget()
179 elif self._options.serial is not None:
180 self._adb.SetTargetSerial(self._options.serial)
181
182 if self._options.verbose:
183 logger.SetVerbose(True)
184
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700185 self._known_tests = self._ReadTests()
186
Brett Chabot764d3fa2009-06-25 17:57:31 -0700187 self._options.host_lib_path = android_build.GetHostLibraryPath()
188 self._options.test_data_path = android_build.GetTestAppPath()
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700189
190 def _ReadTests(self):
191 """Parses the set of test definition data.
192
193 Returns:
194 A TestDefinitions object that contains the set of parsed tests.
195 Raises:
196 AbortError: If a fatal error occurred when parsing the tests.
197 """
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700198 try:
199 known_tests = test_defs.TestDefinitions()
Brett Chabot3c9cefc2011-06-06 20:53:56 -0700200 # only read tests when not in path mode
201 if not self._options.test_path:
202 core_test_path = os.path.join(self._root_path, self._CORE_TEST_PATH)
203 if os.path.isfile(core_test_path):
204 known_tests.Parse(core_test_path)
205 # read all <android root>/vendor/*/tests/testinfo/test_defs.xml paths
206 vendor_tests_pattern = os.path.join(self._root_path,
207 self._VENDOR_TEST_PATH)
208 test_file_paths = glob.glob(vendor_tests_pattern)
209 for test_file_path in test_file_paths:
210 known_tests.Parse(test_file_path)
211 if os.path.isfile(self._options.user_tests_file):
212 known_tests.Parse(self._options.user_tests_file)
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700213 return known_tests
214 except errors.ParseError:
215 raise errors.AbortError
216
217 def _DumpTests(self):
218 """Prints out set of defined tests."""
Brett Chabotbe659c02009-09-21 17:48:26 -0700219 print "The following tests are currently defined:\n"
220 print "%-25s %-40s %s" % ("name", "build path", "description")
221 print "-" * 80
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700222 for test in self._known_tests:
Brett Chabotbe659c02009-09-21 17:48:26 -0700223 print "%-25s %-40s %s" % (test.GetName(), test.GetBuildPath(),
224 test.GetDescription())
225 print "\nSee %s for more information" % self._TEST_FILE_NAME
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700226
227 def _DoBuild(self):
228 logger.SilentLog("Building tests...")
Brett Chabot8dc9eb82010-04-15 15:43:04 -0700229
230 tests = self._GetTestsToRun()
Brett Chabotb1eb5d22010-06-15 11:18:42 -0700231 # turn off dalvik verifier if necessary
232 self._TurnOffVerifier(tests)
Brett Chabot8dc9eb82010-04-15 15:43:04 -0700233 self._DoFullBuild(tests)
234
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700235 target_set = Set()
Niko Cataniaa6dc2ab2009-04-03 14:12:46 -0700236 extra_args_set = Set()
Brett Chabot2477b382009-09-23 18:05:28 -0700237 for test_suite in tests:
Niko Cataniaa6dc2ab2009-04-03 14:12:46 -0700238 self._AddBuildTarget(test_suite, target_set, extra_args_set)
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700239
Brett Chabotccae47d2010-06-14 15:19:25 -0700240 if not self._options.preview:
241 self._adb.EnableAdbRoot()
242 else:
243 logger.Log("adb root")
Guang Zhu8aff3602010-04-15 10:48:26 -0700244 rebuild_libcore = False
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700245 if target_set:
246 if self._options.coverage:
Brett Chabot764d3fa2009-06-25 17:57:31 -0700247 coverage.EnableCoverageBuild()
Guang Zhu8aff3602010-04-15 10:48:26 -0700248 # hack to remove core library intermediates
249 # hack is needed because:
250 # 1. EMMA_INSTRUMENT changes what source files to include in libcore
251 # but it does not trigger a rebuild
252 # 2. there's no target (like "clear-intermediates") to remove the files
253 # decently
254 rebuild_libcore = not coverage.TestDeviceCoverageSupport(self._adb)
255 if rebuild_libcore:
256 cmd = "rm -rf %s" % os.path.join(
257 self._root_path,
258 "out/target/common/obj/JAVA_LIBRARIES/core_intermediates/")
259 logger.Log(cmd)
260 run_command.RunCommand(cmd, return_output=False)
Brett Chabot2477b382009-09-23 18:05:28 -0700261
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700262 target_build_string = " ".join(list(target_set))
Niko Cataniaa6dc2ab2009-04-03 14:12:46 -0700263 extra_args_string = " ".join(list(extra_args_set))
Brett Chabotb1eb5d22010-06-15 11:18:42 -0700264
Brett Chabot764d3fa2009-06-25 17:57:31 -0700265 # mmm cannot be used from python, so perform a similar operation using
Brett Chabot2b6643b2009-04-07 18:35:27 -0700266 # ONE_SHOT_MAKEFILE
Brett Chabot546a3282011-06-07 19:19:30 -0700267 cmd = 'ONE_SHOT_MAKEFILE="%s" make -j%s -C "%s" all_modules %s' % (
Brett Chabot2477b382009-09-23 18:05:28 -0700268 target_build_string, self._options.make_jobs, self._root_path,
269 extra_args_string)
Brett Chabot764d3fa2009-06-25 17:57:31 -0700270 logger.Log(cmd)
Niko Cataniaa6dc2ab2009-04-03 14:12:46 -0700271
Brett Chabot72731f32009-03-31 11:14:05 -0700272 if self._options.preview:
273 # in preview mode, just display to the user what command would have been
274 # run
275 logger.Log("adb sync")
276 else:
Guang Zhu8aff3602010-04-15 10:48:26 -0700277 # set timeout for build to 10 minutes, since libcore may need to
278 # be rebuilt
279 run_command.RunCommand(cmd, return_output=False, timeout_time=600)
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700280 logger.Log("Syncing to device...")
Guang Zhu8aff3602010-04-15 10:48:26 -0700281 self._adb.Sync(runtime_restart=rebuild_libcore)
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700282
Brett Chabot8dc9eb82010-04-15 15:43:04 -0700283 def _DoFullBuild(self, tests):
284 """If necessary, run a full 'make' command for the tests that need it."""
285 extra_args_set = Set()
286
287 # hack to build cts dependencies
288 # TODO: remove this when cts dependencies are removed
289 if self._IsCtsTests(tests):
290 # need to use make since these fail building with ONE_SHOT_MAKEFILE
291 extra_args_set.add('CtsTestStubs')
292 extra_args_set.add('android.core.tests.runner')
293 for test in tests:
294 if test.IsFullMake():
295 if test.GetExtraBuildArgs():
296 # extra args contains the args to pass to 'make'
297 extra_args_set.add(test.GetExtraBuildArgs())
298 else:
299 logger.Log("Warning: test %s needs a full build but does not specify"
300 " extra_build_args" % test.GetName())
301
302 # check if there is actually any tests that required a full build
303 if extra_args_set:
304 cmd = ('make -j%s %s' % (self._options.make_jobs,
305 ' '.join(list(extra_args_set))))
306 logger.Log(cmd)
307 if not self._options.preview:
308 old_dir = os.getcwd()
309 os.chdir(self._root_path)
310 run_command.RunCommand(cmd, return_output=False)
311 os.chdir(old_dir)
312
Niko Cataniaa6dc2ab2009-04-03 14:12:46 -0700313 def _AddBuildTarget(self, test_suite, target_set, extra_args_set):
Brett Chabot8dc9eb82010-04-15 15:43:04 -0700314 if not test_suite.IsFullMake():
315 build_dir = test_suite.GetBuildPath()
316 if self._AddBuildTargetPath(build_dir, target_set):
317 extra_args_set.add(test_suite.GetExtraBuildArgs())
318 for path in test_suite.GetBuildDependencies(self._options):
319 self._AddBuildTargetPath(path, target_set)
Brett Chabot2b6643b2009-04-07 18:35:27 -0700320
321 def _AddBuildTargetPath(self, build_dir, target_set):
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700322 if build_dir is not None:
323 build_file_path = os.path.join(build_dir, "Android.mk")
324 if os.path.isfile(os.path.join(self._root_path, build_file_path)):
325 target_set.add(build_file_path)
Brett Chabot2b6643b2009-04-07 18:35:27 -0700326 return True
Brett Chabote00595b2009-10-21 20:01:31 -0700327 else:
328 logger.Log("%s has no Android.mk, skipping" % build_dir)
Brett Chabot2b6643b2009-04-07 18:35:27 -0700329 return False
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700330
331 def _GetTestsToRun(self):
332 """Get a list of TestSuite objects to run, based on command line args."""
Brett Chabot59b47782009-10-21 17:23:01 -0700333 if self._tests_to_run:
334 return self._tests_to_run
335
336 self._tests_to_run = []
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700337 if self._options.all_tests:
Brett Chabot59b47782009-10-21 17:23:01 -0700338 self._tests_to_run = self._known_tests.GetTests()
Brett Chabot49b77112009-06-02 11:46:04 -0700339 elif self._options.continuous_tests:
Brett Chabot59b47782009-10-21 17:23:01 -0700340 self._tests_to_run = self._known_tests.GetContinuousTests()
Brett Chabot4a5d9f12010-02-18 20:01:11 -0800341 elif self._options.suite:
342 self._tests_to_run = \
343 self._known_tests.GetTestsInSuite(self._options.suite)
Brett Chabot59b47782009-10-21 17:23:01 -0700344 elif self._options.test_path:
345 walker = test_walker.TestWalker()
346 self._tests_to_run = walker.FindTests(self._options.test_path)
347
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700348 for name in self._test_args:
349 test = self._known_tests.GetTest(name)
350 if test is None:
351 logger.Log("Error: Could not find test %s" % name)
352 self._DumpTests()
353 raise errors.AbortError
Brett Chabot59b47782009-10-21 17:23:01 -0700354 self._tests_to_run.append(test)
355 return self._tests_to_run
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700356
Brett Chabot2477b382009-09-23 18:05:28 -0700357 def _IsCtsTests(self, test_list):
358 """Check if any cts tests are included in given list of tests to run."""
359 for test in test_list:
Brett Chabot4a5d9f12010-02-18 20:01:11 -0800360 if test.GetSuite() == 'cts':
Brett Chabot2477b382009-09-23 18:05:28 -0700361 return True
362 return False
363
Brett Chabotccae47d2010-06-14 15:19:25 -0700364 def _TurnOffVerifier(self, test_list):
365 """Turn off the dalvik verifier if needed by given tests.
366
367 If one or more tests needs dalvik verifier off, and it is not already off,
368 turns off verifier and reboots device to allow change to take effect.
369 """
370 # hack to check if these are framework/base tests. If so, turn off verifier
371 # to allow framework tests to access package-private framework api
372 framework_test = False
373 for test in test_list:
374 if os.path.commonprefix([test.GetBuildPath(), "frameworks/base"]):
375 framework_test = True
376 if framework_test:
377 # check if verifier is off already - to avoid the reboot if not
378 # necessary
379 output = self._adb.SendShellCommand("cat /data/local.prop")
380 if not self._DALVIK_VERIFIER_OFF_PROP in output:
381 if self._options.preview:
382 logger.Log("adb shell \"echo %s >> /data/local.prop\""
383 % self._DALVIK_VERIFIER_OFF_PROP)
384 logger.Log("adb reboot")
385 logger.Log("adb wait-for-device")
386 else:
387 logger.Log("Turning off dalvik verifier and rebooting")
388 self._adb.SendShellCommand("\"echo %s >> /data/local.prop\""
389 % self._DALVIK_VERIFIER_OFF_PROP)
390 self._adb.SendCommand("reboot")
391 self._adb.SendCommand("wait-for-device", timeout_time=60,
392 retry_count=3)
Brett Chabotb1eb5d22010-06-15 11:18:42 -0700393 self._adb.EnableAdbRoot()
Brett Chabotccae47d2010-06-14 15:19:25 -0700394
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700395 def RunTests(self):
396 """Main entry method - executes the tests according to command line args."""
397 try:
398 run_command.SetAbortOnError()
399 self._ProcessOptions()
400 if self._options.only_list_tests:
401 self._DumpTests()
402 return
403
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700404 if not self._options.skip_build:
405 self._DoBuild()
406
407 for test_suite in self._GetTestsToRun():
Brett Chabot920e9fe2010-01-21 17:30:47 -0800408 try:
409 test_suite.Run(self._options, self._adb)
410 except errors.WaitForResponseTimedOutError:
411 logger.Log("Timed out waiting for response")
Brett Chabot764d3fa2009-06-25 17:57:31 -0700412
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700413 except KeyboardInterrupt:
414 logger.Log("Exiting...")
Brett Chabot3ae5f8a2009-06-28 12:00:47 -0700415 except errors.AbortError, error:
416 logger.Log(error.msg)
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700417 logger.SilentLog("Exiting due to AbortError...")
418 except errors.WaitForResponseTimedOutError:
419 logger.Log("Timed out waiting for response")
420
421
422def RunTests():
423 runner = TestRunner()
424 runner.RunTests()
425
426if __name__ == "__main__":
427 RunTests()