blob: b6938cdbc417d4db7eeabb0536a8e9b1aaa7aede [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
17"""Command line utility for running a pre-defined test.
18
19Based on previous <androidroot>/development/tools/runtest shell script.
20"""
21
22# Python imports
23import glob
24import optparse
25import os
26from sets import Set
27import sys
28
29# local imports
30import adb_interface
31import android_build
32import coverage
33import errors
34import logger
35import run_command
Brett Chabot764d3fa2009-06-25 17:57:31 -070036from test_defs import test_defs
The Android Open Source Project6ffae012009-03-18 17:39:43 -070037
38
39class TestRunner(object):
40 """Command line utility class for running pre-defined Android test(s)."""
41
Brett Chabotf61f43e2009-04-02 11:52:48 -070042 _TEST_FILE_NAME = "test_defs.xml"
43
The Android Open Source Project6ffae012009-03-18 17:39:43 -070044 # file path to android core platform tests, relative to android build root
45 # TODO move these test data files to another directory
Nicolas Catania97b24c42009-04-22 11:08:32 -070046 _CORE_TEST_PATH = os.path.join("development", "testrunner",
Brett Chabotf61f43e2009-04-02 11:52:48 -070047 _TEST_FILE_NAME)
The Android Open Source Project6ffae012009-03-18 17:39:43 -070048
49 # vendor glob file path patterns to tests, relative to android
50 # build root
51 _VENDOR_TEST_PATH = os.path.join("vendor", "*", "tests", "testinfo",
Brett Chabotf61f43e2009-04-02 11:52:48 -070052 _TEST_FILE_NAME)
The Android Open Source Project6ffae012009-03-18 17:39:43 -070053
54 _RUNTEST_USAGE = (
55 "usage: runtest.py [options] short-test-name[s]\n\n"
56 "The runtest script works in two ways. You can query it "
57 "for a list of tests, or you can launch one or more tests.")
58
Brett Chabot2477b382009-09-23 18:05:28 -070059 # default value for make -jX
60 _DEFAULT_JOBS=4
61
Brett Chabot72731f32009-03-31 11:14:05 -070062 def __init__(self):
63 # disable logging of timestamp
Niko Catania2e990b92009-04-02 16:52:26 -070064 self._root_path = android_build.GetTop()
Nicolas Catania97b24c42009-04-22 11:08:32 -070065 logger.SetTimestampLogging(False)
Brett Chabot3ae5f8a2009-06-28 12:00:47 -070066 self._adb = None
67 self._known_tests = None
68 self._options = None
69 self._test_args = None
Brett Chabot72731f32009-03-31 11:14:05 -070070
The Android Open Source Project6ffae012009-03-18 17:39:43 -070071 def _ProcessOptions(self):
72 """Processes command-line options."""
73 # TODO error messages on once-only or mutually-exclusive options.
74 user_test_default = os.path.join(os.environ.get("HOME"), ".android",
Brett Chabotf61f43e2009-04-02 11:52:48 -070075 self._TEST_FILE_NAME)
The Android Open Source Project6ffae012009-03-18 17:39:43 -070076
77 parser = optparse.OptionParser(usage=self._RUNTEST_USAGE)
78
79 parser.add_option("-l", "--list-tests", dest="only_list_tests",
80 default=False, action="store_true",
81 help="To view the list of tests")
82 parser.add_option("-b", "--skip-build", dest="skip_build", default=False,
83 action="store_true", help="Skip build - just launch")
Brett Chabot2477b382009-09-23 18:05:28 -070084 parser.add_option("-j", "--jobs", dest="make_jobs",
85 metavar="X", default=self._DEFAULT_JOBS,
86 help="Number of make jobs to use when building")
The Android Open Source Project6ffae012009-03-18 17:39:43 -070087 parser.add_option("-n", "--skip_execute", dest="preview", default=False,
88 action="store_true",
89 help="Do not execute, just preview commands")
90 parser.add_option("-r", "--raw-mode", dest="raw_mode", default=False,
91 action="store_true",
92 help="Raw mode (for output to other tools)")
93 parser.add_option("-a", "--suite-assign", dest="suite_assign_mode",
94 default=False, action="store_true",
95 help="Suite assignment (for details & usage see "
96 "InstrumentationTestRunner)")
97 parser.add_option("-v", "--verbose", dest="verbose", default=False,
98 action="store_true",
99 help="Increase verbosity of %s" % sys.argv[0])
100 parser.add_option("-w", "--wait-for-debugger", dest="wait_for_debugger",
101 default=False, action="store_true",
102 help="Wait for debugger before launching tests")
103 parser.add_option("-c", "--test-class", dest="test_class",
104 help="Restrict test to a specific class")
105 parser.add_option("-m", "--test-method", dest="test_method",
106 help="Restrict test to a specific method")
Brett Chabot8a101cb2009-05-05 12:56:39 -0700107 parser.add_option("-p", "--test-package", dest="test_package",
108 help="Restrict test to a specific java package")
109 parser.add_option("-z", "--size", dest="test_size",
110 help="Restrict test to a specific test size")
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700111 parser.add_option("-u", "--user-tests-file", dest="user_tests_file",
112 metavar="FILE", default=user_test_default,
113 help="Alternate source of user test definitions")
114 parser.add_option("-o", "--coverage", dest="coverage",
115 default=False, action="store_true",
116 help="Generate code coverage metrics for test(s)")
117 parser.add_option("-t", "--all-tests", dest="all_tests",
118 default=False, action="store_true",
119 help="Run all defined tests")
120 parser.add_option("--continuous", dest="continuous_tests",
121 default=False, action="store_true",
122 help="Run all tests defined as part of the continuous "
123 "test set")
Wei-Ta Chen97752d42009-05-21 16:24:04 -0700124 parser.add_option("--timeout", dest="timeout",
125 default=300, help="Set a timeout limit (in sec) for "
126 "running native tests on a device (default: 300 secs)")
Brett Chabot49b77112009-06-02 11:46:04 -0700127 parser.add_option("--cts", dest="cts_tests",
128 default=False, action="store_true",
129 help="Run all tests defined as part of the "
130 "compatibility test suite")
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700131 group = optparse.OptionGroup(
132 parser, "Targets", "Use these options to direct tests to a specific "
133 "Android target")
134 group.add_option("-e", "--emulator", dest="emulator", default=False,
135 action="store_true", help="use emulator")
136 group.add_option("-d", "--device", dest="device", default=False,
137 action="store_true", help="use device")
138 group.add_option("-s", "--serial", dest="serial",
139 help="use specific serial")
140 parser.add_option_group(group)
141
142 self._options, self._test_args = parser.parse_args()
143
Brett Chabot49b77112009-06-02 11:46:04 -0700144 if (not self._options.only_list_tests
145 and not self._options.all_tests
146 and not self._options.continuous_tests
147 and not self._options.cts_tests
148 and len(self._test_args) < 1):
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700149 parser.print_help()
150 logger.SilentLog("at least one test name must be specified")
151 raise errors.AbortError
152
153 self._adb = adb_interface.AdbInterface()
154 if self._options.emulator:
155 self._adb.SetEmulatorTarget()
156 elif self._options.device:
157 self._adb.SetDeviceTarget()
158 elif self._options.serial is not None:
159 self._adb.SetTargetSerial(self._options.serial)
160
161 if self._options.verbose:
162 logger.SetVerbose(True)
163
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700164 self._known_tests = self._ReadTests()
165
Brett Chabot764d3fa2009-06-25 17:57:31 -0700166 self._options.host_lib_path = android_build.GetHostLibraryPath()
167 self._options.test_data_path = android_build.GetTestAppPath()
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700168
169 def _ReadTests(self):
170 """Parses the set of test definition data.
171
172 Returns:
173 A TestDefinitions object that contains the set of parsed tests.
174 Raises:
175 AbortError: If a fatal error occurred when parsing the tests.
176 """
177 core_test_path = os.path.join(self._root_path, self._CORE_TEST_PATH)
178 try:
179 known_tests = test_defs.TestDefinitions()
180 known_tests.Parse(core_test_path)
Brett Chabot2d85c0e2009-03-31 15:19:13 -0700181 # read all <android root>/vendor/*/tests/testinfo/test_defs.xml paths
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700182 vendor_tests_pattern = os.path.join(self._root_path,
183 self._VENDOR_TEST_PATH)
184 test_file_paths = glob.glob(vendor_tests_pattern)
185 for test_file_path in test_file_paths:
186 known_tests.Parse(test_file_path)
187 if os.path.isfile(self._options.user_tests_file):
188 known_tests.Parse(self._options.user_tests_file)
189 return known_tests
190 except errors.ParseError:
191 raise errors.AbortError
192
193 def _DumpTests(self):
194 """Prints out set of defined tests."""
Brett Chabotbe659c02009-09-21 17:48:26 -0700195 print "The following tests are currently defined:\n"
196 print "%-25s %-40s %s" % ("name", "build path", "description")
197 print "-" * 80
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700198 for test in self._known_tests:
Brett Chabotbe659c02009-09-21 17:48:26 -0700199 print "%-25s %-40s %s" % (test.GetName(), test.GetBuildPath(),
200 test.GetDescription())
201 print "\nSee %s for more information" % self._TEST_FILE_NAME
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700202
203 def _DoBuild(self):
204 logger.SilentLog("Building tests...")
205 target_set = Set()
Niko Cataniaa6dc2ab2009-04-03 14:12:46 -0700206 extra_args_set = Set()
Brett Chabot2477b382009-09-23 18:05:28 -0700207 tests = self._GetTestsToRun()
208 for test_suite in tests:
Niko Cataniaa6dc2ab2009-04-03 14:12:46 -0700209 self._AddBuildTarget(test_suite, target_set, extra_args_set)
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700210
211 if target_set:
212 if self._options.coverage:
Brett Chabot764d3fa2009-06-25 17:57:31 -0700213 coverage.EnableCoverageBuild()
Brett Chabot2477b382009-09-23 18:05:28 -0700214
215 # hack to build cts dependencies
216 # TODO: remove this when build dependency support added to runtest or
217 # cts dependencies are removed
218 if self._IsCtsTests(tests):
219 # need to use make since these fail building with ONE_SHOT_MAKEFILE
220 cmd=('make -j%s CtsTestStubs android.core.tests.runner' %
221 self._options.make_jobs)
222 logger.Log(cmd)
223 if not self._options.preview:
Brett Chabote00595b2009-10-21 20:01:31 -0700224 old_dir = os.getcwd()
225 os.chdir(self._root_path)
Brett Chabot2477b382009-09-23 18:05:28 -0700226 run_command.RunCommand(cmd, return_output=False)
Brett Chabote00595b2009-10-21 20:01:31 -0700227 os.chdir(old_dir)
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700228 target_build_string = " ".join(list(target_set))
Niko Cataniaa6dc2ab2009-04-03 14:12:46 -0700229 extra_args_string = " ".join(list(extra_args_set))
Brett Chabot764d3fa2009-06-25 17:57:31 -0700230 # mmm cannot be used from python, so perform a similar operation using
Brett Chabot2b6643b2009-04-07 18:35:27 -0700231 # ONE_SHOT_MAKEFILE
Brett Chabot2477b382009-09-23 18:05:28 -0700232 cmd = 'ONE_SHOT_MAKEFILE="%s" make -j%s -C "%s" files %s' % (
233 target_build_string, self._options.make_jobs, self._root_path,
234 extra_args_string)
Brett Chabot764d3fa2009-06-25 17:57:31 -0700235 logger.Log(cmd)
Niko Cataniaa6dc2ab2009-04-03 14:12:46 -0700236
Brett Chabot72731f32009-03-31 11:14:05 -0700237 if self._options.preview:
238 # in preview mode, just display to the user what command would have been
239 # run
240 logger.Log("adb sync")
241 else:
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700242 run_command.RunCommand(cmd, return_output=False)
243 logger.Log("Syncing to device...")
244 self._adb.Sync()
245
Niko Cataniaa6dc2ab2009-04-03 14:12:46 -0700246 def _AddBuildTarget(self, test_suite, target_set, extra_args_set):
247 build_dir = test_suite.GetBuildPath()
Brett Chabot2b6643b2009-04-07 18:35:27 -0700248 if self._AddBuildTargetPath(build_dir, target_set):
Brett Chabot764d3fa2009-06-25 17:57:31 -0700249 extra_args_set.add(test_suite.GetExtraBuildArgs())
250 for path in test_suite.GetBuildDependencies(self._options):
251 self._AddBuildTargetPath(path, target_set)
Brett Chabot2b6643b2009-04-07 18:35:27 -0700252
253 def _AddBuildTargetPath(self, build_dir, target_set):
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700254 if build_dir is not None:
255 build_file_path = os.path.join(build_dir, "Android.mk")
256 if os.path.isfile(os.path.join(self._root_path, build_file_path)):
257 target_set.add(build_file_path)
Brett Chabot2b6643b2009-04-07 18:35:27 -0700258 return True
Brett Chabote00595b2009-10-21 20:01:31 -0700259 else:
260 logger.Log("%s has no Android.mk, skipping" % build_dir)
Brett Chabot2b6643b2009-04-07 18:35:27 -0700261 return False
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700262
263 def _GetTestsToRun(self):
264 """Get a list of TestSuite objects to run, based on command line args."""
265 if self._options.all_tests:
266 return self._known_tests.GetTests()
Brett Chabot49b77112009-06-02 11:46:04 -0700267 elif self._options.continuous_tests:
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700268 return self._known_tests.GetContinuousTests()
Brett Chabot49b77112009-06-02 11:46:04 -0700269 elif self._options.cts_tests:
270 return self._known_tests.GetCtsTests()
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700271 tests = []
272 for name in self._test_args:
273 test = self._known_tests.GetTest(name)
274 if test is None:
275 logger.Log("Error: Could not find test %s" % name)
276 self._DumpTests()
277 raise errors.AbortError
278 tests.append(test)
279 return tests
280
Brett Chabot2477b382009-09-23 18:05:28 -0700281 def _IsCtsTests(self, test_list):
282 """Check if any cts tests are included in given list of tests to run."""
283 for test in test_list:
284 if test.IsCts():
285 return True
286 return False
287
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700288 def RunTests(self):
289 """Main entry method - executes the tests according to command line args."""
290 try:
291 run_command.SetAbortOnError()
292 self._ProcessOptions()
293 if self._options.only_list_tests:
294 self._DumpTests()
295 return
296
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700297 if not self._options.skip_build:
298 self._DoBuild()
299
300 for test_suite in self._GetTestsToRun():
Brett Chabot764d3fa2009-06-25 17:57:31 -0700301 test_suite.Run(self._options, self._adb)
302
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700303 except KeyboardInterrupt:
304 logger.Log("Exiting...")
Brett Chabot3ae5f8a2009-06-28 12:00:47 -0700305 except errors.AbortError, error:
306 logger.Log(error.msg)
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700307 logger.SilentLog("Exiting due to AbortError...")
308 except errors.WaitForResponseTimedOutError:
309 logger.Log("Timed out waiting for response")
310
311
312def RunTests():
313 runner = TestRunner()
314 runner.RunTests()
315
316if __name__ == "__main__":
317 RunTests()