blob: 34f979fc0f5bbb3cd588fb976028533d8216e4a7 [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
Niko Catania2e990b92009-04-02 16:52:26 -070026import re
The Android Open Source Project6ffae012009-03-18 17:39:43 -070027from sets import Set
28import sys
29
30# local imports
31import adb_interface
32import android_build
33import coverage
34import errors
35import logger
36import run_command
Brett Chabot764d3fa2009-06-25 17:57:31 -070037from test_defs import test_defs
The Android Open Source Project6ffae012009-03-18 17:39:43 -070038
39
40class TestRunner(object):
41 """Command line utility class for running pre-defined Android test(s)."""
42
Brett Chabotf61f43e2009-04-02 11:52:48 -070043 _TEST_FILE_NAME = "test_defs.xml"
44
The Android Open Source Project6ffae012009-03-18 17:39:43 -070045 # file path to android core platform tests, relative to android build root
46 # TODO move these test data files to another directory
Nicolas Catania97b24c42009-04-22 11:08:32 -070047 _CORE_TEST_PATH = os.path.join("development", "testrunner",
Brett Chabotf61f43e2009-04-02 11:52:48 -070048 _TEST_FILE_NAME)
The Android Open Source Project6ffae012009-03-18 17:39:43 -070049
50 # vendor glob file path patterns to tests, relative to android
51 # build root
52 _VENDOR_TEST_PATH = os.path.join("vendor", "*", "tests", "testinfo",
Brett Chabotf61f43e2009-04-02 11:52:48 -070053 _TEST_FILE_NAME)
The Android Open Source Project6ffae012009-03-18 17:39:43 -070054
55 _RUNTEST_USAGE = (
56 "usage: runtest.py [options] short-test-name[s]\n\n"
57 "The runtest script works in two ways. You can query it "
58 "for a list of tests, or you can launch one or more tests.")
59
Brett Chabot72731f32009-03-31 11:14:05 -070060 def __init__(self):
61 # disable logging of timestamp
Niko Catania2e990b92009-04-02 16:52:26 -070062 self._root_path = android_build.GetTop()
Nicolas Catania97b24c42009-04-22 11:08:32 -070063 logger.SetTimestampLogging(False)
Brett Chabot72731f32009-03-31 11:14:05 -070064
The Android Open Source Project6ffae012009-03-18 17:39:43 -070065 def _ProcessOptions(self):
66 """Processes command-line options."""
67 # TODO error messages on once-only or mutually-exclusive options.
68 user_test_default = os.path.join(os.environ.get("HOME"), ".android",
Brett Chabotf61f43e2009-04-02 11:52:48 -070069 self._TEST_FILE_NAME)
The Android Open Source Project6ffae012009-03-18 17:39:43 -070070
71 parser = optparse.OptionParser(usage=self._RUNTEST_USAGE)
72
73 parser.add_option("-l", "--list-tests", dest="only_list_tests",
74 default=False, action="store_true",
75 help="To view the list of tests")
76 parser.add_option("-b", "--skip-build", dest="skip_build", default=False,
77 action="store_true", help="Skip build - just launch")
78 parser.add_option("-n", "--skip_execute", dest="preview", default=False,
79 action="store_true",
80 help="Do not execute, just preview commands")
81 parser.add_option("-r", "--raw-mode", dest="raw_mode", default=False,
82 action="store_true",
83 help="Raw mode (for output to other tools)")
84 parser.add_option("-a", "--suite-assign", dest="suite_assign_mode",
85 default=False, action="store_true",
86 help="Suite assignment (for details & usage see "
87 "InstrumentationTestRunner)")
88 parser.add_option("-v", "--verbose", dest="verbose", default=False,
89 action="store_true",
90 help="Increase verbosity of %s" % sys.argv[0])
91 parser.add_option("-w", "--wait-for-debugger", dest="wait_for_debugger",
92 default=False, action="store_true",
93 help="Wait for debugger before launching tests")
94 parser.add_option("-c", "--test-class", dest="test_class",
95 help="Restrict test to a specific class")
96 parser.add_option("-m", "--test-method", dest="test_method",
97 help="Restrict test to a specific method")
Brett Chabot8a101cb2009-05-05 12:56:39 -070098 parser.add_option("-p", "--test-package", dest="test_package",
99 help="Restrict test to a specific java package")
100 parser.add_option("-z", "--size", dest="test_size",
101 help="Restrict test to a specific test size")
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700102 parser.add_option("-u", "--user-tests-file", dest="user_tests_file",
103 metavar="FILE", default=user_test_default,
104 help="Alternate source of user test definitions")
105 parser.add_option("-o", "--coverage", dest="coverage",
106 default=False, action="store_true",
107 help="Generate code coverage metrics for test(s)")
108 parser.add_option("-t", "--all-tests", dest="all_tests",
109 default=False, action="store_true",
110 help="Run all defined tests")
111 parser.add_option("--continuous", dest="continuous_tests",
112 default=False, action="store_true",
113 help="Run all tests defined as part of the continuous "
114 "test set")
Wei-Ta Chen97752d42009-05-21 16:24:04 -0700115 parser.add_option("--timeout", dest="timeout",
116 default=300, help="Set a timeout limit (in sec) for "
117 "running native tests on a device (default: 300 secs)")
Brett Chabot49b77112009-06-02 11:46:04 -0700118 parser.add_option("--cts", dest="cts_tests",
119 default=False, action="store_true",
120 help="Run all tests defined as part of the "
121 "compatibility test suite")
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700122 group = optparse.OptionGroup(
123 parser, "Targets", "Use these options to direct tests to a specific "
124 "Android target")
125 group.add_option("-e", "--emulator", dest="emulator", default=False,
126 action="store_true", help="use emulator")
127 group.add_option("-d", "--device", dest="device", default=False,
128 action="store_true", help="use device")
129 group.add_option("-s", "--serial", dest="serial",
130 help="use specific serial")
131 parser.add_option_group(group)
132
133 self._options, self._test_args = parser.parse_args()
134
Brett Chabot49b77112009-06-02 11:46:04 -0700135 if (not self._options.only_list_tests
136 and not self._options.all_tests
137 and not self._options.continuous_tests
138 and not self._options.cts_tests
139 and len(self._test_args) < 1):
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700140 parser.print_help()
141 logger.SilentLog("at least one test name must be specified")
142 raise errors.AbortError
143
144 self._adb = adb_interface.AdbInterface()
145 if self._options.emulator:
146 self._adb.SetEmulatorTarget()
147 elif self._options.device:
148 self._adb.SetDeviceTarget()
149 elif self._options.serial is not None:
150 self._adb.SetTargetSerial(self._options.serial)
151
152 if self._options.verbose:
153 logger.SetVerbose(True)
154
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700155 self._known_tests = self._ReadTests()
156
Brett Chabot764d3fa2009-06-25 17:57:31 -0700157 self._options.host_lib_path = android_build.GetHostLibraryPath()
158 self._options.test_data_path = android_build.GetTestAppPath()
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700159
160 def _ReadTests(self):
161 """Parses the set of test definition data.
162
163 Returns:
164 A TestDefinitions object that contains the set of parsed tests.
165 Raises:
166 AbortError: If a fatal error occurred when parsing the tests.
167 """
168 core_test_path = os.path.join(self._root_path, self._CORE_TEST_PATH)
169 try:
170 known_tests = test_defs.TestDefinitions()
171 known_tests.Parse(core_test_path)
Brett Chabot2d85c0e2009-03-31 15:19:13 -0700172 # read all <android root>/vendor/*/tests/testinfo/test_defs.xml paths
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700173 vendor_tests_pattern = os.path.join(self._root_path,
174 self._VENDOR_TEST_PATH)
175 test_file_paths = glob.glob(vendor_tests_pattern)
176 for test_file_path in test_file_paths:
177 known_tests.Parse(test_file_path)
178 if os.path.isfile(self._options.user_tests_file):
179 known_tests.Parse(self._options.user_tests_file)
180 return known_tests
181 except errors.ParseError:
182 raise errors.AbortError
183
184 def _DumpTests(self):
185 """Prints out set of defined tests."""
186 print "The following tests are currently defined:"
187 for test in self._known_tests:
Niko Catania2e990b92009-04-02 16:52:26 -0700188 print "%-15s %s" % (test.GetName(), test.GetDescription())
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700189
190 def _DoBuild(self):
191 logger.SilentLog("Building tests...")
192 target_set = Set()
Niko Cataniaa6dc2ab2009-04-03 14:12:46 -0700193 extra_args_set = Set()
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700194 for test_suite in self._GetTestsToRun():
Niko Cataniaa6dc2ab2009-04-03 14:12:46 -0700195 self._AddBuildTarget(test_suite, target_set, extra_args_set)
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700196
197 if target_set:
198 if self._options.coverage:
Brett Chabot764d3fa2009-06-25 17:57:31 -0700199 coverage.EnableCoverageBuild()
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700200 target_build_string = " ".join(list(target_set))
Niko Cataniaa6dc2ab2009-04-03 14:12:46 -0700201 extra_args_string = " ".join(list(extra_args_set))
Brett Chabot764d3fa2009-06-25 17:57:31 -0700202 # mmm cannot be used from python, so perform a similar operation using
Brett Chabot2b6643b2009-04-07 18:35:27 -0700203 # ONE_SHOT_MAKEFILE
Niko Cataniaa6dc2ab2009-04-03 14:12:46 -0700204 cmd = 'ONE_SHOT_MAKEFILE="%s" make -C "%s" files %s' % (
205 target_build_string, self._root_path, extra_args_string)
Brett Chabot764d3fa2009-06-25 17:57:31 -0700206 logger.Log(cmd)
Niko Cataniaa6dc2ab2009-04-03 14:12:46 -0700207
Brett Chabot72731f32009-03-31 11:14:05 -0700208 if self._options.preview:
209 # in preview mode, just display to the user what command would have been
210 # run
211 logger.Log("adb sync")
212 else:
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700213 run_command.RunCommand(cmd, return_output=False)
214 logger.Log("Syncing to device...")
215 self._adb.Sync()
216
Niko Cataniaa6dc2ab2009-04-03 14:12:46 -0700217 def _AddBuildTarget(self, test_suite, target_set, extra_args_set):
218 build_dir = test_suite.GetBuildPath()
Brett Chabot2b6643b2009-04-07 18:35:27 -0700219 if self._AddBuildTargetPath(build_dir, target_set):
Brett Chabot764d3fa2009-06-25 17:57:31 -0700220 extra_args_set.add(test_suite.GetExtraBuildArgs())
221 for path in test_suite.GetBuildDependencies(self._options):
222 self._AddBuildTargetPath(path, target_set)
Brett Chabot2b6643b2009-04-07 18:35:27 -0700223
224 def _AddBuildTargetPath(self, build_dir, target_set):
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700225 if build_dir is not None:
226 build_file_path = os.path.join(build_dir, "Android.mk")
227 if os.path.isfile(os.path.join(self._root_path, build_file_path)):
228 target_set.add(build_file_path)
Brett Chabot2b6643b2009-04-07 18:35:27 -0700229 return True
230 return False
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700231
232 def _GetTestsToRun(self):
233 """Get a list of TestSuite objects to run, based on command line args."""
234 if self._options.all_tests:
235 return self._known_tests.GetTests()
Brett Chabot49b77112009-06-02 11:46:04 -0700236 elif self._options.continuous_tests:
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700237 return self._known_tests.GetContinuousTests()
Brett Chabot49b77112009-06-02 11:46:04 -0700238 elif self._options.cts_tests:
239 return self._known_tests.GetCtsTests()
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700240 tests = []
241 for name in self._test_args:
242 test = self._known_tests.GetTest(name)
243 if test is None:
244 logger.Log("Error: Could not find test %s" % name)
245 self._DumpTests()
246 raise errors.AbortError
247 tests.append(test)
248 return tests
249
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700250 def RunTests(self):
251 """Main entry method - executes the tests according to command line args."""
252 try:
253 run_command.SetAbortOnError()
254 self._ProcessOptions()
255 if self._options.only_list_tests:
256 self._DumpTests()
257 return
258
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700259 if not self._options.skip_build:
260 self._DoBuild()
261
262 for test_suite in self._GetTestsToRun():
Brett Chabot764d3fa2009-06-25 17:57:31 -0700263 test_suite.Run(self._options, self._adb)
264
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700265 except KeyboardInterrupt:
266 logger.Log("Exiting...")
Brett Chabot8a101cb2009-05-05 12:56:39 -0700267 except errors.AbortError, e:
268 logger.Log(e.msg)
The Android Open Source Project6ffae012009-03-18 17:39:43 -0700269 logger.SilentLog("Exiting due to AbortError...")
270 except errors.WaitForResponseTimedOutError:
271 logger.Log("Timed out waiting for response")
272
273
274def RunTests():
275 runner = TestRunner()
276 runner.RunTests()
277
278if __name__ == "__main__":
279 RunTests()