blob: 593d11d229c78f182e0d1bae0a053984d95eeb8a [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 Chabot72731f32009-03-31 11:14:05 -070059 def __init__(self):
60 # disable logging of timestamp
Niko Catania2e990b92009-04-02 16:52:26 -070061 self._root_path = android_build.GetTop()
Nicolas Catania97b24c42009-04-22 11:08:32 -070062 logger.SetTimestampLogging(False)
Brett Chabot3ae5f8a2009-06-28 12:00:47 -070063 self._adb = None
64 self._known_tests = None
65 self._options = None
66 self._test_args = None
Brett Chabot72731f32009-03-31 11:14:05 -070067
The Android Open Source Project6ffae012009-03-18 17:39:43 -070068 def _ProcessOptions(self):
69 """Processes command-line options."""
70 # TODO error messages on once-only or mutually-exclusive options.
71 user_test_default = os.path.join(os.environ.get("HOME"), ".android",
Brett Chabotf61f43e2009-04-02 11:52:48 -070072 self._TEST_FILE_NAME)
The Android Open Source Project6ffae012009-03-18 17:39:43 -070073
74 parser = optparse.OptionParser(usage=self._RUNTEST_USAGE)
75
76 parser.add_option("-l", "--list-tests", dest="only_list_tests",
77 default=False, action="store_true",
78 help="To view the list of tests")
79 parser.add_option("-b", "--skip-build", dest="skip_build", default=False,
80 action="store_true", help="Skip build - just launch")
81 parser.add_option("-n", "--skip_execute", dest="preview", default=False,
82 action="store_true",
83 help="Do not execute, just preview commands")
84 parser.add_option("-r", "--raw-mode", dest="raw_mode", default=False,
85 action="store_true",
86 help="Raw mode (for output to other tools)")
87 parser.add_option("-a", "--suite-assign", dest="suite_assign_mode",
88 default=False, action="store_true",
89 help="Suite assignment (for details & usage see "
90 "InstrumentationTestRunner)")
91 parser.add_option("-v", "--verbose", dest="verbose", default=False,
92 action="store_true",
93 help="Increase verbosity of %s" % sys.argv[0])
94 parser.add_option("-w", "--wait-for-debugger", dest="wait_for_debugger",
95 default=False, action="store_true",
96 help="Wait for debugger before launching tests")
97 parser.add_option("-c", "--test-class", dest="test_class",
98 help="Restrict test to a specific class")
99 parser.add_option("-m", "--test-method", dest="test_method",
100 help="Restrict test to a specific method")
Brett Chabot8a101cb2009-05-05 12:56:39 -0700101 parser.add_option("-p", "--test-package", dest="test_package",
102 help="Restrict test to a specific java package")
103 parser.add_option("-z", "--size", dest="test_size",
104 help="Restrict test to a specific test size")
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700105 parser.add_option("-u", "--user-tests-file", dest="user_tests_file",
106 metavar="FILE", default=user_test_default,
107 help="Alternate source of user test definitions")
108 parser.add_option("-o", "--coverage", dest="coverage",
109 default=False, action="store_true",
110 help="Generate code coverage metrics for test(s)")
111 parser.add_option("-t", "--all-tests", dest="all_tests",
112 default=False, action="store_true",
113 help="Run all defined tests")
114 parser.add_option("--continuous", dest="continuous_tests",
115 default=False, action="store_true",
116 help="Run all tests defined as part of the continuous "
117 "test set")
Wei-Ta Chen97752d42009-05-21 16:24:04 -0700118 parser.add_option("--timeout", dest="timeout",
119 default=300, help="Set a timeout limit (in sec) for "
120 "running native tests on a device (default: 300 secs)")
Brett Chabot49b77112009-06-02 11:46:04 -0700121 parser.add_option("--cts", dest="cts_tests",
122 default=False, action="store_true",
123 help="Run all tests defined as part of the "
124 "compatibility test suite")
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700125 group = optparse.OptionGroup(
126 parser, "Targets", "Use these options to direct tests to a specific "
127 "Android target")
128 group.add_option("-e", "--emulator", dest="emulator", default=False,
129 action="store_true", help="use emulator")
130 group.add_option("-d", "--device", dest="device", default=False,
131 action="store_true", help="use device")
132 group.add_option("-s", "--serial", dest="serial",
133 help="use specific serial")
134 parser.add_option_group(group)
135
136 self._options, self._test_args = parser.parse_args()
137
Brett Chabot49b77112009-06-02 11:46:04 -0700138 if (not self._options.only_list_tests
139 and not self._options.all_tests
140 and not self._options.continuous_tests
141 and not self._options.cts_tests
142 and len(self._test_args) < 1):
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700143 parser.print_help()
144 logger.SilentLog("at least one test name must be specified")
145 raise errors.AbortError
146
147 self._adb = adb_interface.AdbInterface()
148 if self._options.emulator:
149 self._adb.SetEmulatorTarget()
150 elif self._options.device:
151 self._adb.SetDeviceTarget()
152 elif self._options.serial is not None:
153 self._adb.SetTargetSerial(self._options.serial)
154
155 if self._options.verbose:
156 logger.SetVerbose(True)
157
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700158 self._known_tests = self._ReadTests()
159
Brett Chabot764d3fa2009-06-25 17:57:31 -0700160 self._options.host_lib_path = android_build.GetHostLibraryPath()
161 self._options.test_data_path = android_build.GetTestAppPath()
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700162
163 def _ReadTests(self):
164 """Parses the set of test definition data.
165
166 Returns:
167 A TestDefinitions object that contains the set of parsed tests.
168 Raises:
169 AbortError: If a fatal error occurred when parsing the tests.
170 """
171 core_test_path = os.path.join(self._root_path, self._CORE_TEST_PATH)
172 try:
173 known_tests = test_defs.TestDefinitions()
174 known_tests.Parse(core_test_path)
Brett Chabot2d85c0e2009-03-31 15:19:13 -0700175 # read all <android root>/vendor/*/tests/testinfo/test_defs.xml paths
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700176 vendor_tests_pattern = os.path.join(self._root_path,
177 self._VENDOR_TEST_PATH)
178 test_file_paths = glob.glob(vendor_tests_pattern)
179 for test_file_path in test_file_paths:
180 known_tests.Parse(test_file_path)
181 if os.path.isfile(self._options.user_tests_file):
182 known_tests.Parse(self._options.user_tests_file)
183 return known_tests
184 except errors.ParseError:
185 raise errors.AbortError
186
187 def _DumpTests(self):
188 """Prints out set of defined tests."""
189 print "The following tests are currently defined:"
190 for test in self._known_tests:
Niko Catania2e990b92009-04-02 16:52:26 -0700191 print "%-15s %s" % (test.GetName(), test.GetDescription())
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700192
193 def _DoBuild(self):
194 logger.SilentLog("Building tests...")
195 target_set = Set()
Niko Cataniaa6dc2ab2009-04-03 14:12:46 -0700196 extra_args_set = Set()
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700197 for test_suite in self._GetTestsToRun():
Niko Cataniaa6dc2ab2009-04-03 14:12:46 -0700198 self._AddBuildTarget(test_suite, target_set, extra_args_set)
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700199
200 if target_set:
201 if self._options.coverage:
Brett Chabot764d3fa2009-06-25 17:57:31 -0700202 coverage.EnableCoverageBuild()
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700203 target_build_string = " ".join(list(target_set))
Niko Cataniaa6dc2ab2009-04-03 14:12:46 -0700204 extra_args_string = " ".join(list(extra_args_set))
Brett Chabot764d3fa2009-06-25 17:57:31 -0700205 # mmm cannot be used from python, so perform a similar operation using
Brett Chabot2b6643b2009-04-07 18:35:27 -0700206 # ONE_SHOT_MAKEFILE
Niko Cataniaa6dc2ab2009-04-03 14:12:46 -0700207 cmd = 'ONE_SHOT_MAKEFILE="%s" make -C "%s" files %s' % (
208 target_build_string, self._root_path, extra_args_string)
Brett Chabot764d3fa2009-06-25 17:57:31 -0700209 logger.Log(cmd)
Niko Cataniaa6dc2ab2009-04-03 14:12:46 -0700210
Brett Chabot72731f32009-03-31 11:14:05 -0700211 if self._options.preview:
212 # in preview mode, just display to the user what command would have been
213 # run
214 logger.Log("adb sync")
215 else:
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700216 run_command.RunCommand(cmd, return_output=False)
217 logger.Log("Syncing to device...")
218 self._adb.Sync()
219
Niko Cataniaa6dc2ab2009-04-03 14:12:46 -0700220 def _AddBuildTarget(self, test_suite, target_set, extra_args_set):
221 build_dir = test_suite.GetBuildPath()
Brett Chabot2b6643b2009-04-07 18:35:27 -0700222 if self._AddBuildTargetPath(build_dir, target_set):
Brett Chabot764d3fa2009-06-25 17:57:31 -0700223 extra_args_set.add(test_suite.GetExtraBuildArgs())
224 for path in test_suite.GetBuildDependencies(self._options):
225 self._AddBuildTargetPath(path, target_set)
Brett Chabot2b6643b2009-04-07 18:35:27 -0700226
227 def _AddBuildTargetPath(self, build_dir, target_set):
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700228 if build_dir is not None:
229 build_file_path = os.path.join(build_dir, "Android.mk")
230 if os.path.isfile(os.path.join(self._root_path, build_file_path)):
231 target_set.add(build_file_path)
Brett Chabot2b6643b2009-04-07 18:35:27 -0700232 return True
233 return False
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700234
235 def _GetTestsToRun(self):
236 """Get a list of TestSuite objects to run, based on command line args."""
237 if self._options.all_tests:
238 return self._known_tests.GetTests()
Brett Chabot49b77112009-06-02 11:46:04 -0700239 elif self._options.continuous_tests:
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700240 return self._known_tests.GetContinuousTests()
Brett Chabot49b77112009-06-02 11:46:04 -0700241 elif self._options.cts_tests:
242 return self._known_tests.GetCtsTests()
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700243 tests = []
244 for name in self._test_args:
245 test = self._known_tests.GetTest(name)
246 if test is None:
247 logger.Log("Error: Could not find test %s" % name)
248 self._DumpTests()
249 raise errors.AbortError
250 tests.append(test)
251 return tests
252
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700253 def RunTests(self):
254 """Main entry method - executes the tests according to command line args."""
255 try:
256 run_command.SetAbortOnError()
257 self._ProcessOptions()
258 if self._options.only_list_tests:
259 self._DumpTests()
260 return
261
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700262 if not self._options.skip_build:
263 self._DoBuild()
264
265 for test_suite in self._GetTestsToRun():
Brett Chabot764d3fa2009-06-25 17:57:31 -0700266 test_suite.Run(self._options, self._adb)
267
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700268 except KeyboardInterrupt:
269 logger.Log("Exiting...")
Brett Chabot3ae5f8a2009-06-28 12:00:47 -0700270 except errors.AbortError, error:
271 logger.Log(error.msg)
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700272 logger.SilentLog("Exiting due to AbortError...")
273 except errors.WaitForResponseTimedOutError:
274 logger.Log("Timed out waiting for response")
275
276
277def RunTests():
278 runner = TestRunner()
279 runner.RunTests()
280
281if __name__ == "__main__":
282 RunTests()