blob: 4a659257fb1df221a6d9d3e94832a64948e4bcba [file] [log] [blame]
[email protected]e185b7e82013-01-09 03:49:571#!/usr/bin/env python
2# Copyright (c) 2013 The Chromium Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6import collections
7import glob
[email protected]78af8712013-01-14 10:37:128import multiprocessing
[email protected]e185b7e82013-01-09 03:49:579import os
[email protected]e185b7e82013-01-09 03:49:5710import shutil
[email protected]e185b7e82013-01-09 03:49:5711import sys
12
[email protected]c5282752013-06-07 23:14:3913import bb_utils
14
[email protected]e185b7e82013-01-09 03:49:5715sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
[email protected]78af8712013-01-14 10:37:1216from pylib import android_commands
[email protected]e185b7e82013-01-09 03:49:5717from pylib import buildbot_report
18from pylib import constants
[email protected]a8fea93f2013-01-10 04:00:0719from pylib.gtest import gtest_config
[email protected]e185b7e82013-01-09 03:49:5720
[email protected]78af8712013-01-14 10:37:1221sys.path.append(os.path.join(
[email protected]b3c0d4a2013-06-05 23:28:0922 constants.DIR_SOURCE_ROOT, 'third_party', 'android_testrunner'))
[email protected]78af8712013-01-14 10:37:1223import errors
24
[email protected]e185b7e82013-01-09 03:49:5725
[email protected]b3c0d4a2013-06-05 23:28:0926CHROME_SRC = constants.DIR_SOURCE_ROOT
[email protected]e185b7e82013-01-09 03:49:5727
28# Describes an instrumation test suite:
29# test: Name of test we're running.
30# apk: apk to be installed.
31# apk_package: package for the apk to be installed.
32# test_apk: apk to run tests on.
33# test_data: data folder in format destination:source.
34I_TEST = collections.namedtuple('InstrumentationTest', [
[email protected]8d8ca042013-02-14 19:29:1735 'name', 'apk', 'apk_package', 'test_apk', 'test_data', 'host_driven_root'])
[email protected]e185b7e82013-01-09 03:49:5736
37INSTRUMENTATION_TESTS = dict((suite.name, suite) for suite in [
38 I_TEST('ContentShell',
39 'ContentShell.apk',
[email protected]4d4eb5b2013-01-29 21:55:5540 'org.chromium.content_shell_apk',
[email protected]e185b7e82013-01-09 03:49:5741 'ContentShellTest',
[email protected]8d8ca042013-02-14 19:29:1742 'content:content/test/data/android/device_files',
43 None),
[email protected]e185b7e82013-01-09 03:49:5744 I_TEST('ChromiumTestShell',
45 'ChromiumTestShell.apk',
46 'org.chromium.chrome.testshell',
47 'ChromiumTestShellTest',
[email protected]8d8ca042013-02-14 19:29:1748 'chrome:chrome/test/data/android/device_files',
49 constants.CHROMIUM_TEST_SHELL_HOST_DRIVEN_DIR),
[email protected]e185b7e82013-01-09 03:49:5750 I_TEST('AndroidWebView',
51 'AndroidWebView.apk',
[email protected]8c56afd2013-03-25 15:37:4552 'org.chromium.android_webview.shell',
[email protected]e185b7e82013-01-09 03:49:5753 'AndroidWebViewTest',
[email protected]8d8ca042013-02-14 19:29:1754 'webview:android_webview/test/data/device_files',
55 None),
[email protected]e185b7e82013-01-09 03:49:5756 ])
57
[email protected]d8897f6c2013-03-05 00:27:1658VALID_TESTS = set(['chromedriver', 'ui', 'unit', 'webkit', 'webkit_layout'])
[email protected]e185b7e82013-01-09 03:49:5759
[email protected]c5282752013-06-07 23:14:3960RunCmd = bb_utils.RunCmd
[email protected]e185b7e82013-01-09 03:49:5761
62
[email protected]78af8712013-01-14 10:37:1263# multiprocessing map_async requires a top-level function for pickle library.
64def RebootDeviceSafe(device):
65 """Reboot a device, wait for it to start, and squelch timeout exceptions."""
66 try:
67 android_commands.AndroidCommands(device).Reboot(True)
68 except errors.DeviceUnresponsiveError as e:
69 return e
70
71
72def RebootDevices():
73 """Reboot all attached and online devices."""
74 buildbot_report.PrintNamedStep('Reboot devices')
[email protected]c94ae6b2013-01-14 21:38:3475 # Early return here to avoid presubmit dependence on adb,
76 # which might not exist in this checkout.
[email protected]c5282752013-06-07 23:14:3977 if bb_utils.TESTING:
[email protected]c94ae6b2013-01-14 21:38:3478 return
[email protected]78af8712013-01-14 10:37:1279 devices = android_commands.GetAttachedDevices()
80 print 'Rebooting: %s' % devices
[email protected]c94ae6b2013-01-14 21:38:3481 if devices:
[email protected]78af8712013-01-14 10:37:1282 pool = multiprocessing.Pool(len(devices))
83 results = pool.map_async(RebootDeviceSafe, devices).get(99999)
84
85 for device, result in zip(devices, results):
86 if result:
87 print '%s failed to startup.' % device
88
89 if any(results):
90 buildbot_report.PrintWarning()
91 else:
92 print 'Reboots complete.'
93
94
[email protected]a8fea93f2013-01-10 04:00:0795def RunTestSuites(options, suites):
[email protected]e185b7e82013-01-09 03:49:5796 """Manages an invocation of run_tests.py.
97
98 Args:
99 options: options object.
[email protected]a8fea93f2013-01-10 04:00:07100 suites: List of suites to run.
[email protected]e185b7e82013-01-09 03:49:57101 """
102 args = ['--verbose']
[email protected]e185b7e82013-01-09 03:49:57103 if options.target == 'Release':
104 args.append('--release')
105 if options.asan:
106 args.append('--tool=asan')
[email protected]a8fea93f2013-01-10 04:00:07107 for suite in suites:
[email protected]9324bff2013-03-13 04:09:27108 buildbot_report.PrintNamedStep(suite.name)
109 cmd = ['build/android/run_tests.py', '-s', suite.name] + args
110 if suite.is_suite_exe:
111 cmd.append('--exe')
112 RunCmd(cmd)
[email protected]e185b7e82013-01-09 03:49:57113
[email protected]2b5decc2013-03-02 18:09:15114def RunBrowserTestSuite(options):
115 """Manages an invocation of run_browser_tests.py.
116
117 Args:
118 options: options object.
119 """
[email protected]a61af452013-05-07 18:39:18120 args = ['--verbose']
[email protected]2b5decc2013-03-02 18:09:15121 if options.target == 'Release':
122 args.append('--release')
123 if options.asan:
124 args.append('--tool=asan')
125 buildbot_report.PrintNamedStep(constants.BROWSERTEST_SUITE_NAME)
126 RunCmd(['build/android/run_browser_tests.py'] + args)
[email protected]e185b7e82013-01-09 03:49:57127
[email protected]d8897f6c2013-03-05 00:27:16128def RunChromeDriverTests():
129 """Run all the steps for running chromedriver tests."""
130 buildbot_report.PrintNamedStep('chromedriver_annotation')
131 RunCmd(['chrome/test/chromedriver/run_buildbot_steps.py',
132 '--android-package=%s' % constants.CHROMIUM_TEST_SHELL_PACKAGE])
133
[email protected]a2a725242013-01-09 21:52:57134def InstallApk(options, test, print_step=False):
135 """Install an apk to all phones.
136
137 Args:
138 options: options object
139 test: An I_TEST namedtuple
140 print_step: Print a buildbot step
141 """
142 if print_step:
143 buildbot_report.PrintNamedStep('install_%s' % test.name.lower())
144 args = ['--apk', test.apk, '--apk_package', test.apk_package]
145 if options.target == 'Release':
[email protected]e185b7e82013-01-09 03:49:57146 args.append('--release')
147
[email protected]800673bf2013-05-14 17:15:30148 RunCmd(['build/android/adb_install_apk.py'] + args, halt_on_failure=True)
[email protected]e185b7e82013-01-09 03:49:57149
150
151def RunInstrumentationSuite(options, test):
152 """Manages an invocation of run_instrumentaiton_tests.py.
153
154 Args:
155 options: options object
156 test: An I_TEST namedtuple
157 """
158 buildbot_report.PrintNamedStep('%s_instrumentation_tests' % test.name.lower())
159
[email protected]a2a725242013-01-09 21:52:57160 InstallApk(options, test)
[email protected]d1a0657c2013-04-10 22:38:59161 args = ['--test-apk', test.test_apk, '--test_data', test.test_data,
162 '--verbose', '-I']
[email protected]e185b7e82013-01-09 03:49:57163 if options.target == 'Release':
164 args.append('--release')
165 if options.asan:
166 args.append('--tool=asan')
[email protected]da06cc52013-01-16 18:58:41167 if options.upload_to_flakiness_server:
[email protected]b796a772013-01-19 03:55:22168 args.append('--flakiness-dashboard-server=%s' %
169 constants.UPSTREAM_FLAKINESS_SERVER)
[email protected]8d8ca042013-02-14 19:29:17170 if test.host_driven_root:
171 args.append('--python_test_root=%s' % test.host_driven_root)
[email protected]e185b7e82013-01-09 03:49:57172
173 RunCmd(['build/android/run_instrumentation_tests.py'] + args)
174
175
176def RunWebkitLint(target):
177 """Lint WebKit's TestExpectation files."""
178 buildbot_report.PrintNamedStep('webkit_lint')
179 RunCmd(['webkit/tools/layout_tests/run_webkit_tests.py',
180 '--lint-test-files',
181 '--chromium',
182 '--target', target])
183
184
185def RunWebkitLayoutTests(options):
186 """Run layout tests on an actual device."""
187 buildbot_report.PrintNamedStep('webkit_tests')
[email protected]22ee7002013-01-23 20:58:04188 cmd_args = [
189 '--no-show-results',
190 '--no-new-test-results',
191 '--full-results-html',
192 '--clobber-old-results',
193 '--exit-after-n-failures', '5000',
194 '--exit-after-n-crashes-or-timeouts', '100',
195 '--debug-rwt-logging',
196 '--results-directory', '..layout-test-results',
197 '--target', options.target,
198 '--builder-name', options.build_properties.get('buildername', ''),
[email protected]0b793d62013-05-20 22:00:39199 '--build-number', str(options.build_properties.get('buildnumber', '')),
[email protected]22ee7002013-01-23 20:58:04200 '--master-name', options.build_properties.get('mastername', ''),
201 '--build-name', options.build_properties.get('buildername', ''),
202 '--platform=chromium-android']
203
204 for flag in 'test_results_server', 'driver_name', 'additional_drt_flag':
205 if flag in options.factory_properties:
206 cmd_args.extend(['--%s' % flag.replace('_', '-'),
207 options.factory_properties.get(flag)])
208
[email protected]2c39b292013-03-20 09:34:10209 for f in options.factory_properties.get('additional_expectations', []):
210 cmd_args.extend(
211 ['--additional-expectations=%s' % os.path.join(CHROME_SRC, *f)])
212
213 # TODO(dpranke): Remove this block after
214 # https://codereview.chromium.org/12927002/ lands.
[email protected]22ee7002013-01-23 20:58:04215 for f in options.factory_properties.get('additional_expectations_files', []):
[email protected]62c5b982013-01-26 08:23:16216 cmd_args.extend(
217 ['--additional-expectations=%s' % os.path.join(CHROME_SRC, *f)])
[email protected]22ee7002013-01-23 20:58:04218
[email protected]8feb3672013-03-24 00:28:35219 RunCmd(['webkit/tools/layout_tests/run_webkit_tests.py'] + cmd_args,
220 flunk_on_failure=False)
[email protected]e185b7e82013-01-09 03:49:57221
222
223def MainTestWrapper(options):
[email protected]78af8712013-01-14 10:37:12224 # Restart adb to work around bugs, sleep to wait for usb discovery.
225 RunCmd(['adb', 'kill-server'])
226 RunCmd(['adb', 'start-server'])
227 RunCmd(['sleep', '1'])
228
229 # Spawn logcat monitor
230 logcat_dir = os.path.join(CHROME_SRC, 'out/logcat')
231 shutil.rmtree(logcat_dir, ignore_errors=True)
[email protected]c5282752013-06-07 23:14:39232 bb_utils.SpawnCmd(['build/android/adb_logcat_monitor.py', logcat_dir])
[email protected]78af8712013-01-14 10:37:12233
234 # Wait for logcat_monitor to pull existing logcat
235 RunCmd(['sleep', '5'])
236
237 if options.reboot:
238 RebootDevices()
239
[email protected]693c54d2013-01-09 19:41:25240 # Device check and alert emails
[email protected]a8fea93f2013-01-10 04:00:07241 buildbot_report.PrintNamedStep('device_status_check')
[email protected]800673bf2013-05-14 17:15:30242 RunCmd(['build/android/device_status_check.py'], halt_on_failure=True)
[email protected]693c54d2013-01-09 19:41:25243
[email protected]12f36c82013-03-29 06:21:13244 # Provision devices
[email protected]c89aae02013-04-06 00:25:19245 buildbot_report.PrintNamedStep('provision_devices')
246 target = options.factory_properties.get('target', 'Debug')
247 RunCmd(['build/android/provision_devices.py', '-t', target])
[email protected]12f36c82013-03-29 06:21:13248
[email protected]e185b7e82013-01-09 03:49:57249 if options.install:
250 test_obj = INSTRUMENTATION_TESTS[options.install]
[email protected]a2a725242013-01-09 21:52:57251 InstallApk(options, test_obj, print_step=True)
[email protected]e185b7e82013-01-09 03:49:57252
[email protected]d8897f6c2013-03-05 00:27:16253 if 'chromedriver' in options.test_filter:
254 RunChromeDriverTests()
[email protected]e185b7e82013-01-09 03:49:57255 if 'unit' in options.test_filter:
[email protected]a8fea93f2013-01-10 04:00:07256 RunTestSuites(options, gtest_config.STABLE_TEST_SUITES)
[email protected]e185b7e82013-01-09 03:49:57257 if 'ui' in options.test_filter:
258 for test in INSTRUMENTATION_TESTS.itervalues():
259 RunInstrumentationSuite(options, test)
260 if 'webkit' in options.test_filter:
[email protected]9324bff2013-03-13 04:09:27261 RunTestSuites(options, [
262 gtest_config.Apk('webkit_unit_tests'),
[email protected]9324bff2013-03-13 04:09:27263 ])
[email protected]e185b7e82013-01-09 03:49:57264 RunWebkitLint(options.target)
265 if 'webkit_layout' in options.test_filter:
266 RunWebkitLayoutTests(options)
267
268 if options.experimental:
[email protected]a8fea93f2013-01-10 04:00:07269 RunTestSuites(options, gtest_config.EXPERIMENTAL_TEST_SUITES)
[email protected]a61af452013-05-07 18:39:18270 RunBrowserTestSuite(options)
[email protected]e185b7e82013-01-09 03:49:57271
272 # Print logcat, kill logcat monitor
[email protected]a8fea93f2013-01-10 04:00:07273 buildbot_report.PrintNamedStep('logcat_dump')
[email protected]e185b7e82013-01-09 03:49:57274 RunCmd(['build/android/adb_logcat_printer.py', logcat_dir])
275
[email protected]a8fea93f2013-01-10 04:00:07276 buildbot_report.PrintNamedStep('test_report')
[email protected]e185b7e82013-01-09 03:49:57277 for report in glob.glob(
278 os.path.join(CHROME_SRC, 'out', options.target, 'test_logs', '*.log')):
[email protected]78af8712013-01-14 10:37:12279 RunCmd(['cat', report])
[email protected]e185b7e82013-01-09 03:49:57280 os.remove(report)
281
282
283def main(argv):
[email protected]c5282752013-06-07 23:14:39284 parser = bb_utils.GetParser()
[email protected]e185b7e82013-01-09 03:49:57285 parser.add_option('--experimental', action='store_true',
286 help='Run experiemental tests')
287 parser.add_option('-f', '--test-filter', metavar='<filter>', default=[],
288 action='append',
289 help=('Run a test suite. Test suites: "%s"' %
290 '", "'.join(VALID_TESTS)))
291 parser.add_option('--asan', action='store_true', help='Run tests with asan.')
292 parser.add_option('--install', metavar='<apk name>',
293 help='Install an apk by name')
[email protected]78af8712013-01-14 10:37:12294 parser.add_option('--reboot', action='store_true',
295 help='Reboot devices before running tests')
[email protected]da06cc52013-01-16 18:58:41296 parser.add_option('--upload-to-flakiness-server', action='store_true',
297 help='Upload the results to the flakiness dashboard.')
[email protected]12f36c82013-03-29 06:21:13298 parser.add_option(
299 '--auto-reconnect', action='store_true',
300 help='Push script to device which restarts adbd on disconnections.')
[email protected]e185b7e82013-01-09 03:49:57301 options, args = parser.parse_args(argv[1:])
302
[email protected]e185b7e82013-01-09 03:49:57303 if args:
[email protected]c5282752013-06-07 23:14:39304 return sys.exit('Unused args %s' % args)
[email protected]e185b7e82013-01-09 03:49:57305
306 unknown_tests = set(options.test_filter) - VALID_TESTS
307 if unknown_tests:
[email protected]c5282752013-06-07 23:14:39308 return sys.exit('Unknown tests %s' % list(unknown_tests))
[email protected]e185b7e82013-01-09 03:49:57309
310 setattr(options, 'target', options.factory_properties.get('target', 'Debug'))
311
[email protected]78af8712013-01-14 10:37:12312 # Add adb binary and chromium-source platform-tools to tip of PATH variable.
313 android_paths = [os.path.join(constants.ANDROID_SDK_ROOT, 'platform-tools')]
314
315 # Bots checkout chrome in /b/build/slave/<name>/build/src
316 build_internal_android = os.path.abspath(os.path.join(
317 CHROME_SRC, '..', '..', '..', '..', '..', 'build_internal', 'scripts',
318 'slave', 'android'))
319 if os.path.exists(build_internal_android):
320 android_paths.insert(0, build_internal_android)
321 os.environ['PATH'] = os.pathsep.join(android_paths + [os.environ['PATH']])
322
[email protected]e185b7e82013-01-09 03:49:57323 MainTestWrapper(options)
324
325
326if __name__ == '__main__':
327 sys.exit(main(sys.argv))