blob: 6b03c79a284591b9d029aa3bb2a1e50c4917140b [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 Chabot72731f32009-03-31 11:14:05 -070073 def __init__(self):
74 # disable logging of timestamp
Niko Catania2e990b92009-04-02 16:52:26 -070075 self._root_path = android_build.GetTop()
Nicolas Catania97b24c42009-04-22 11:08:32 -070076 logger.SetTimestampLogging(False)
Brett Chabot3ae5f8a2009-06-28 12:00:47 -070077 self._adb = None
78 self._known_tests = None
79 self._options = None
80 self._test_args = None
Brett Chabot59b47782009-10-21 17:23:01 -070081 self._tests_to_run = None
Brett Chabot72731f32009-03-31 11:14:05 -070082
The Android Open Source Project6ffae012009-03-18 17:39:43 -070083 def _ProcessOptions(self):
84 """Processes command-line options."""
85 # TODO error messages on once-only or mutually-exclusive options.
86 user_test_default = os.path.join(os.environ.get("HOME"), ".android",
Brett Chabotf61f43e2009-04-02 11:52:48 -070087 self._TEST_FILE_NAME)
The Android Open Source Project6ffae012009-03-18 17:39:43 -070088
89 parser = optparse.OptionParser(usage=self._RUNTEST_USAGE)
90
91 parser.add_option("-l", "--list-tests", dest="only_list_tests",
92 default=False, action="store_true",
93 help="To view the list of tests")
94 parser.add_option("-b", "--skip-build", dest="skip_build", default=False,
95 action="store_true", help="Skip build - just launch")
Brett Chabot2477b382009-09-23 18:05:28 -070096 parser.add_option("-j", "--jobs", dest="make_jobs",
97 metavar="X", default=self._DEFAULT_JOBS,
98 help="Number of make jobs to use when building")
The Android Open Source Project6ffae012009-03-18 17:39:43 -070099 parser.add_option("-n", "--skip_execute", dest="preview", default=False,
100 action="store_true",
101 help="Do not execute, just preview commands")
102 parser.add_option("-r", "--raw-mode", dest="raw_mode", default=False,
103 action="store_true",
104 help="Raw mode (for output to other tools)")
105 parser.add_option("-a", "--suite-assign", dest="suite_assign_mode",
106 default=False, action="store_true",
107 help="Suite assignment (for details & usage see "
108 "InstrumentationTestRunner)")
109 parser.add_option("-v", "--verbose", dest="verbose", default=False,
110 action="store_true",
111 help="Increase verbosity of %s" % sys.argv[0])
112 parser.add_option("-w", "--wait-for-debugger", dest="wait_for_debugger",
113 default=False, action="store_true",
114 help="Wait for debugger before launching tests")
115 parser.add_option("-c", "--test-class", dest="test_class",
116 help="Restrict test to a specific class")
117 parser.add_option("-m", "--test-method", dest="test_method",
118 help="Restrict test to a specific method")
Brett Chabot8a101cb2009-05-05 12:56:39 -0700119 parser.add_option("-p", "--test-package", dest="test_package",
120 help="Restrict test to a specific java package")
121 parser.add_option("-z", "--size", dest="test_size",
122 help="Restrict test to a specific test size")
Brett Chabotc0611542010-02-20 20:09:58 -0800123 parser.add_option("--annotation", dest="test_annotation",
124 help="Include only those tests tagged with a specific"
125 " annotation")
126 parser.add_option("--not-annotation", dest="test_not_annotation",
Brett Chabot2e16fbc2010-02-23 12:28:27 -0800127 help="Exclude any tests tagged with a specific"
Brett Chabotc0611542010-02-20 20:09:58 -0800128 " annotation")
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700129 parser.add_option("-u", "--user-tests-file", dest="user_tests_file",
130 metavar="FILE", default=user_test_default,
131 help="Alternate source of user test definitions")
132 parser.add_option("-o", "--coverage", dest="coverage",
133 default=False, action="store_true",
134 help="Generate code coverage metrics for test(s)")
Brett Chabot59b47782009-10-21 17:23:01 -0700135 parser.add_option("-x", "--path", dest="test_path",
136 help="Run test(s) at given file system path")
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700137 parser.add_option("-t", "--all-tests", dest="all_tests",
138 default=False, action="store_true",
139 help="Run all defined tests")
140 parser.add_option("--continuous", dest="continuous_tests",
141 default=False, action="store_true",
142 help="Run all tests defined as part of the continuous "
143 "test set")
Wei-Ta Chen97752d42009-05-21 16:24:04 -0700144 parser.add_option("--timeout", dest="timeout",
145 default=300, help="Set a timeout limit (in sec) for "
146 "running native tests on a device (default: 300 secs)")
Brett Chabot4a5d9f12010-02-18 20:01:11 -0800147 parser.add_option("--suite", dest="suite",
Brett Chabot49b77112009-06-02 11:46:04 -0700148 help="Run all tests defined as part of the "
Brett Chabot4a5d9f12010-02-18 20:01:11 -0800149 "the given test suite")
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700150 group = optparse.OptionGroup(
151 parser, "Targets", "Use these options to direct tests to a specific "
152 "Android target")
153 group.add_option("-e", "--emulator", dest="emulator", default=False,
154 action="store_true", help="use emulator")
155 group.add_option("-d", "--device", dest="device", default=False,
156 action="store_true", help="use device")
157 group.add_option("-s", "--serial", dest="serial",
158 help="use specific serial")
159 parser.add_option_group(group)
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700160 self._options, self._test_args = parser.parse_args()
161
Brett Chabot49b77112009-06-02 11:46:04 -0700162 if (not self._options.only_list_tests
163 and not self._options.all_tests
164 and not self._options.continuous_tests
Brett Chabot4a5d9f12010-02-18 20:01:11 -0800165 and not self._options.suite
Brett Chabot59b47782009-10-21 17:23:01 -0700166 and not self._options.test_path
Brett Chabot49b77112009-06-02 11:46:04 -0700167 and len(self._test_args) < 1):
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700168 parser.print_help()
169 logger.SilentLog("at least one test name must be specified")
170 raise errors.AbortError
171
172 self._adb = adb_interface.AdbInterface()
173 if self._options.emulator:
174 self._adb.SetEmulatorTarget()
175 elif self._options.device:
176 self._adb.SetDeviceTarget()
177 elif self._options.serial is not None:
178 self._adb.SetTargetSerial(self._options.serial)
179
180 if self._options.verbose:
181 logger.SetVerbose(True)
182
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700183 self._known_tests = self._ReadTests()
184
Brett Chabot764d3fa2009-06-25 17:57:31 -0700185 self._options.host_lib_path = android_build.GetHostLibraryPath()
186 self._options.test_data_path = android_build.GetTestAppPath()
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700187
188 def _ReadTests(self):
189 """Parses the set of test definition data.
190
191 Returns:
192 A TestDefinitions object that contains the set of parsed tests.
193 Raises:
194 AbortError: If a fatal error occurred when parsing the tests.
195 """
196 core_test_path = os.path.join(self._root_path, self._CORE_TEST_PATH)
197 try:
198 known_tests = test_defs.TestDefinitions()
199 known_tests.Parse(core_test_path)
Brett Chabot2d85c0e2009-03-31 15:19:13 -0700200 # read all <android root>/vendor/*/tests/testinfo/test_defs.xml paths
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700201 vendor_tests_pattern = os.path.join(self._root_path,
202 self._VENDOR_TEST_PATH)
203 test_file_paths = glob.glob(vendor_tests_pattern)
204 for test_file_path in test_file_paths:
205 known_tests.Parse(test_file_path)
206 if os.path.isfile(self._options.user_tests_file):
207 known_tests.Parse(self._options.user_tests_file)
208 return known_tests
209 except errors.ParseError:
210 raise errors.AbortError
211
212 def _DumpTests(self):
213 """Prints out set of defined tests."""
Brett Chabotbe659c02009-09-21 17:48:26 -0700214 print "The following tests are currently defined:\n"
215 print "%-25s %-40s %s" % ("name", "build path", "description")
216 print "-" * 80
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700217 for test in self._known_tests:
Brett Chabotbe659c02009-09-21 17:48:26 -0700218 print "%-25s %-40s %s" % (test.GetName(), test.GetBuildPath(),
219 test.GetDescription())
220 print "\nSee %s for more information" % self._TEST_FILE_NAME
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700221
222 def _DoBuild(self):
223 logger.SilentLog("Building tests...")
Brett Chabot8dc9eb82010-04-15 15:43:04 -0700224
225 tests = self._GetTestsToRun()
226 self._DoFullBuild(tests)
227
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700228 target_set = Set()
Niko Cataniaa6dc2ab2009-04-03 14:12:46 -0700229 extra_args_set = Set()
Brett Chabot2477b382009-09-23 18:05:28 -0700230 for test_suite in tests:
Niko Cataniaa6dc2ab2009-04-03 14:12:46 -0700231 self._AddBuildTarget(test_suite, target_set, extra_args_set)
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700232
Guang Zhu8aff3602010-04-15 10:48:26 -0700233 rebuild_libcore = False
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700234 if target_set:
235 if self._options.coverage:
Brett Chabot764d3fa2009-06-25 17:57:31 -0700236 coverage.EnableCoverageBuild()
Guang Zhu8aff3602010-04-15 10:48:26 -0700237 # hack to remove core library intermediates
238 # hack is needed because:
239 # 1. EMMA_INSTRUMENT changes what source files to include in libcore
240 # but it does not trigger a rebuild
241 # 2. there's no target (like "clear-intermediates") to remove the files
242 # decently
243 rebuild_libcore = not coverage.TestDeviceCoverageSupport(self._adb)
244 if rebuild_libcore:
245 cmd = "rm -rf %s" % os.path.join(
246 self._root_path,
247 "out/target/common/obj/JAVA_LIBRARIES/core_intermediates/")
248 logger.Log(cmd)
249 run_command.RunCommand(cmd, return_output=False)
Brett Chabot2477b382009-09-23 18:05:28 -0700250
Brett Chabot8dc9eb82010-04-15 15:43:04 -0700251 target_build_string = ' '.join(list(target_set))
252 extra_args_string = ' '.join(list(extra_args_set))
Brett Chabot764d3fa2009-06-25 17:57:31 -0700253 # mmm cannot be used from python, so perform a similar operation using
Brett Chabot2b6643b2009-04-07 18:35:27 -0700254 # ONE_SHOT_MAKEFILE
Brett Chabot2477b382009-09-23 18:05:28 -0700255 cmd = 'ONE_SHOT_MAKEFILE="%s" make -j%s -C "%s" files %s' % (
256 target_build_string, self._options.make_jobs, self._root_path,
257 extra_args_string)
Brett Chabot764d3fa2009-06-25 17:57:31 -0700258 logger.Log(cmd)
Niko Cataniaa6dc2ab2009-04-03 14:12:46 -0700259
Brett Chabot72731f32009-03-31 11:14:05 -0700260 if self._options.preview:
261 # in preview mode, just display to the user what command would have been
262 # run
263 logger.Log("adb sync")
264 else:
Guang Zhu8aff3602010-04-15 10:48:26 -0700265 # set timeout for build to 10 minutes, since libcore may need to
266 # be rebuilt
267 run_command.RunCommand(cmd, return_output=False, timeout_time=600)
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700268 logger.Log("Syncing to device...")
Guang Zhu8aff3602010-04-15 10:48:26 -0700269 self._adb.Sync(runtime_restart=rebuild_libcore)
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700270
Brett Chabot8dc9eb82010-04-15 15:43:04 -0700271 def _DoFullBuild(self, tests):
272 """If necessary, run a full 'make' command for the tests that need it."""
273 extra_args_set = Set()
274
275 # hack to build cts dependencies
276 # TODO: remove this when cts dependencies are removed
277 if self._IsCtsTests(tests):
278 # need to use make since these fail building with ONE_SHOT_MAKEFILE
279 extra_args_set.add('CtsTestStubs')
280 extra_args_set.add('android.core.tests.runner')
281 for test in tests:
282 if test.IsFullMake():
283 if test.GetExtraBuildArgs():
284 # extra args contains the args to pass to 'make'
285 extra_args_set.add(test.GetExtraBuildArgs())
286 else:
287 logger.Log("Warning: test %s needs a full build but does not specify"
288 " extra_build_args" % test.GetName())
289
290 # check if there is actually any tests that required a full build
291 if extra_args_set:
292 cmd = ('make -j%s %s' % (self._options.make_jobs,
293 ' '.join(list(extra_args_set))))
294 logger.Log(cmd)
295 if not self._options.preview:
296 old_dir = os.getcwd()
297 os.chdir(self._root_path)
298 run_command.RunCommand(cmd, return_output=False)
299 os.chdir(old_dir)
300
Niko Cataniaa6dc2ab2009-04-03 14:12:46 -0700301 def _AddBuildTarget(self, test_suite, target_set, extra_args_set):
Brett Chabot8dc9eb82010-04-15 15:43:04 -0700302 if not test_suite.IsFullMake():
303 build_dir = test_suite.GetBuildPath()
304 if self._AddBuildTargetPath(build_dir, target_set):
305 extra_args_set.add(test_suite.GetExtraBuildArgs())
306 for path in test_suite.GetBuildDependencies(self._options):
307 self._AddBuildTargetPath(path, target_set)
Brett Chabot2b6643b2009-04-07 18:35:27 -0700308
309 def _AddBuildTargetPath(self, build_dir, target_set):
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700310 if build_dir is not None:
311 build_file_path = os.path.join(build_dir, "Android.mk")
312 if os.path.isfile(os.path.join(self._root_path, build_file_path)):
313 target_set.add(build_file_path)
Brett Chabot2b6643b2009-04-07 18:35:27 -0700314 return True
Brett Chabote00595b2009-10-21 20:01:31 -0700315 else:
316 logger.Log("%s has no Android.mk, skipping" % build_dir)
Brett Chabot2b6643b2009-04-07 18:35:27 -0700317 return False
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700318
319 def _GetTestsToRun(self):
320 """Get a list of TestSuite objects to run, based on command line args."""
Brett Chabot59b47782009-10-21 17:23:01 -0700321 if self._tests_to_run:
322 return self._tests_to_run
323
324 self._tests_to_run = []
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700325 if self._options.all_tests:
Brett Chabot59b47782009-10-21 17:23:01 -0700326 self._tests_to_run = self._known_tests.GetTests()
Brett Chabot49b77112009-06-02 11:46:04 -0700327 elif self._options.continuous_tests:
Brett Chabot59b47782009-10-21 17:23:01 -0700328 self._tests_to_run = self._known_tests.GetContinuousTests()
Brett Chabot4a5d9f12010-02-18 20:01:11 -0800329 elif self._options.suite:
330 self._tests_to_run = \
331 self._known_tests.GetTestsInSuite(self._options.suite)
Brett Chabot59b47782009-10-21 17:23:01 -0700332 elif self._options.test_path:
333 walker = test_walker.TestWalker()
334 self._tests_to_run = walker.FindTests(self._options.test_path)
335
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700336 for name in self._test_args:
337 test = self._known_tests.GetTest(name)
338 if test is None:
339 logger.Log("Error: Could not find test %s" % name)
340 self._DumpTests()
341 raise errors.AbortError
Brett Chabot59b47782009-10-21 17:23:01 -0700342 self._tests_to_run.append(test)
343 return self._tests_to_run
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700344
Brett Chabot2477b382009-09-23 18:05:28 -0700345 def _IsCtsTests(self, test_list):
346 """Check if any cts tests are included in given list of tests to run."""
347 for test in test_list:
Brett Chabot4a5d9f12010-02-18 20:01:11 -0800348 if test.GetSuite() == 'cts':
Brett Chabot2477b382009-09-23 18:05:28 -0700349 return True
350 return False
351
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700352 def RunTests(self):
353 """Main entry method - executes the tests according to command line args."""
354 try:
355 run_command.SetAbortOnError()
356 self._ProcessOptions()
357 if self._options.only_list_tests:
358 self._DumpTests()
359 return
360
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700361 if not self._options.skip_build:
362 self._DoBuild()
363
364 for test_suite in self._GetTestsToRun():
Brett Chabot920e9fe2010-01-21 17:30:47 -0800365 try:
366 test_suite.Run(self._options, self._adb)
367 except errors.WaitForResponseTimedOutError:
368 logger.Log("Timed out waiting for response")
Brett Chabot764d3fa2009-06-25 17:57:31 -0700369
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700370 except KeyboardInterrupt:
371 logger.Log("Exiting...")
Brett Chabot3ae5f8a2009-06-28 12:00:47 -0700372 except errors.AbortError, error:
373 logger.Log(error.msg)
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700374 logger.SilentLog("Exiting due to AbortError...")
375 except errors.WaitForResponseTimedOutError:
376 logger.Log("Timed out waiting for response")
377
378
379def RunTests():
380 runner = TestRunner()
381 runner.RunTests()
382
383if __name__ == "__main__":
384 RunTests()