OLD | NEW |
---|---|
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 import collections | 6 import collections |
7 import glob | 7 import glob |
8 import multiprocessing | 8 import multiprocessing |
9 import os | 9 import os |
10 import shutil | 10 import shutil |
11 import sys | 11 import sys |
12 import time | |
12 | 13 |
13 import bb_utils | 14 import bb_utils |
14 import bb_annotations | 15 import bb_annotations |
15 | 16 |
16 sys.path.append(os.path.join(os.path.dirname(__file__), '..')) | 17 sys.path.append(os.path.join(os.path.dirname(__file__), '..')) |
17 import provision_devices | 18 import provision_devices |
18 from pylib import android_commands | 19 from pylib import android_commands |
19 from pylib import constants | 20 from pylib import constants |
20 from pylib.gtest import gtest_config | 21 from pylib.gtest import gtest_config |
21 | 22 |
22 sys.path.append(os.path.join( | 23 sys.path.append(os.path.join( |
23 constants.DIR_SOURCE_ROOT, 'third_party', 'android_testrunner')) | 24 constants.DIR_SOURCE_ROOT, 'third_party', 'android_testrunner')) |
24 import errors | 25 import errors |
25 | 26 |
26 | 27 |
27 CHROME_SRC = constants.DIR_SOURCE_ROOT | 28 CHROME_SRC = constants.DIR_SOURCE_ROOT |
28 LOGCAT_DIR = os.path.join(CHROME_SRC, 'out', 'logcat') | 29 LOGCAT_DIR = os.path.join(CHROME_SRC, 'out', 'logcat') |
30 REVISION_FILENAME = 'FULL_BUILD_REVISION' | |
29 | 31 |
30 # Describes an instrumation test suite: | 32 # Describes an instrumation test suite: |
31 # test: Name of test we're running. | 33 # test: Name of test we're running. |
32 # apk: apk to be installed. | 34 # apk: apk to be installed. |
33 # apk_package: package for the apk to be installed. | 35 # apk_package: package for the apk to be installed. |
34 # test_apk: apk to run tests on. | 36 # test_apk: apk to run tests on. |
35 # test_data: data folder in format destination:source. | 37 # test_data: data folder in format destination:source. |
36 # host_driven_root: The host-driven test root directory. | 38 # host_driven_root: The host-driven test root directory. |
37 # annotation: Annotation of the tests to include. | 39 # annotation: Annotation of the tests to include. |
38 # exclude_annotation: The annotation of the tests to exclude. | 40 # exclude_annotation: The annotation of the tests to exclude. |
39 I_TEST = collections.namedtuple('InstrumentationTest', [ | 41 I_TEST = collections.namedtuple('InstrumentationTest', [ |
40 'name', 'apk', 'apk_package', 'test_apk', 'test_data', 'host_driven_root', | 42 'name', 'apk', 'apk_package', 'test_apk', 'test_data', 'coverage', |
41 'annotation', 'exclude_annotation', 'extra_flags']) | 43 'host_driven_root', 'annotation', 'exclude_annotation', 'extra_flags']) |
42 | 44 |
43 def I(name, apk, apk_package, test_apk, test_data, host_driven_root=None, | 45 def I(name, apk, apk_package, test_apk, test_data, coverage=True, |
44 annotation=None, exclude_annotation=None, extra_flags=None): | 46 host_driven_root=None, annotation=None, exclude_annotation=None, |
45 return I_TEST(name, apk, apk_package, test_apk, test_data, host_driven_root, | 47 extra_flags=None): |
46 annotation, exclude_annotation, extra_flags) | 48 return I_TEST(name, apk, apk_package, test_apk, test_data, coverage, |
49 host_driven_root, annotation, exclude_annotation, extra_flags) | |
47 | 50 |
48 INSTRUMENTATION_TESTS = dict((suite.name, suite) for suite in [ | 51 INSTRUMENTATION_TESTS = dict((suite.name, suite) for suite in [ |
49 I('ContentShell', | 52 I('ContentShell', |
50 'ContentShell.apk', | 53 'ContentShell.apk', |
51 'org.chromium.content_shell_apk', | 54 'org.chromium.content_shell_apk', |
52 'ContentShellTest', | 55 'ContentShellTest', |
53 'content:content/test/data/android/device_files'), | 56 'content:content/test/data/android/device_files'), |
54 I('ChromiumTestShell', | 57 I('ChromiumTestShell', |
55 'ChromiumTestShell.apk', | 58 'ChromiumTestShell.apk', |
56 'org.chromium.chrome.testshell', | 59 'org.chromium.chrome.testshell', |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
158 InstallApk(options, test) | 161 InstallApk(options, test) |
159 args = ['--test-apk', test.test_apk, '--test_data', test.test_data, | 162 args = ['--test-apk', test.test_apk, '--test_data', test.test_data, |
160 '--verbose'] | 163 '--verbose'] |
161 if options.target == 'Release': | 164 if options.target == 'Release': |
162 args.append('--release') | 165 args.append('--release') |
163 if options.asan: | 166 if options.asan: |
164 args.append('--tool=asan') | 167 args.append('--tool=asan') |
165 if options.flakiness_server: | 168 if options.flakiness_server: |
166 args.append('--flakiness-dashboard-server=%s' % | 169 args.append('--flakiness-dashboard-server=%s' % |
167 options.flakiness_server) | 170 options.flakiness_server) |
171 if options.coverage_bucket and test.coverage: | |
172 args.append('--coverage-dir=%s' % options.coverage_dir) | |
168 if test.host_driven_root: | 173 if test.host_driven_root: |
169 args.append('--host-driven-root=%s' % test.host_driven_root) | 174 args.append('--host-driven-root=%s' % test.host_driven_root) |
170 if test.annotation: | 175 if test.annotation: |
171 args.extend(['-A', test.annotation]) | 176 args.extend(['-A', test.annotation]) |
172 if test.exclude_annotation: | 177 if test.exclude_annotation: |
173 args.extend(['-E', test.exclude_annotation]) | 178 args.extend(['-E', test.exclude_annotation]) |
174 if test.extra_flags: | 179 if test.extra_flags: |
175 args.extend(test.extra_flags) | 180 args.extend(test.extra_flags) |
176 if python_only: | 181 if python_only: |
177 args.append('-p') | 182 args.append('-p') |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
263 ('provision_devices', ProvisionDevices), | 268 ('provision_devices', ProvisionDevices), |
264 ('device_status_check', DeviceStatusCheck) | 269 ('device_status_check', DeviceStatusCheck) |
265 ] | 270 ] |
266 | 271 |
267 | 272 |
268 def RunUnitTests(options): | 273 def RunUnitTests(options): |
269 RunTestSuites(options, gtest_config.STABLE_TEST_SUITES) | 274 RunTestSuites(options, gtest_config.STABLE_TEST_SUITES) |
270 | 275 |
271 | 276 |
272 def RunInstrumentationTests(options): | 277 def RunInstrumentationTests(options): |
278 if options.coverage_bucket: | |
279 shutil.rmtree(options.coverage_dir, ignore_errors=True) | |
Isaac (away)
2013/08/20 23:28:10
not needed for triggered bots. Also, I'd prefer w
gkanwar1
2013/08/20 23:40:29
Good to know, removed. Not sure what you mean by s
Isaac (away)
2013/08/22 18:10:37
I mean, if you're going to delete a folder, print
gkanwar1
2013/08/22 18:12:11
Ah, got it. Good to know for the future. For this
| |
280 os.mkdir(options.coverage_dir) | |
281 | |
273 for test in INSTRUMENTATION_TESTS.itervalues(): | 282 for test in INSTRUMENTATION_TESTS.itervalues(): |
274 RunInstrumentationSuite(options, test) | 283 RunInstrumentationSuite(options, test) |
275 | 284 |
285 if options.coverage_bucket: | |
Isaac (away)
2013/08/20 23:28:10
Does this need to be called from RunInstrumentatio
gkanwar1
2013/08/20 23:40:29
Nope. It was there because it was acting sort of a
| |
286 GenerateJavaCoverageReport(options) | |
287 | |
276 | 288 |
277 def RunWebkitTests(options): | 289 def RunWebkitTests(options): |
278 RunTestSuites(options, ['webkit_unit_tests']) | 290 RunTestSuites(options, ['webkit_unit_tests']) |
279 RunWebkitLint(options.target) | 291 RunWebkitLint(options.target) |
280 | 292 |
281 | 293 |
282 def RunWebRTCTests(options): | 294 def RunWebRTCTests(options): |
283 RunTestSuites(options, gtest_config.WEBRTC_TEST_SUITES) | 295 RunTestSuites(options, gtest_config.WEBRTC_TEST_SUITES) |
284 | 296 |
285 | 297 |
286 def GetTestStepCmds(): | 298 def GetTestStepCmds(): |
287 return [ | 299 return [ |
288 ('chromedriver', RunChromeDriverTests), | 300 ('chromedriver', RunChromeDriverTests), |
289 ('unit', RunUnitTests), | 301 ('unit', RunUnitTests), |
290 ('ui', RunInstrumentationTests), | 302 ('ui', RunInstrumentationTests), |
291 ('webkit', RunWebkitTests), | 303 ('webkit', RunWebkitTests), |
292 ('webkit_layout', RunWebkitLayoutTests), | 304 ('webkit_layout', RunWebkitLayoutTests), |
293 ('webrtc', RunWebRTCTests), | 305 ('webrtc', RunWebRTCTests), |
294 ] | 306 ] |
295 | 307 |
296 | 308 |
309 def UploadCoverageData(options, path, coverage_type): | |
310 revision_file = os.path.join(CHROME_SRC, 'out', options.target, | |
311 REVISION_FILENAME) | |
Isaac (away)
2013/08/20 23:28:10
Would be better to use revision from build_propert
gkanwar1
2013/08/20 23:40:29
Ah, didn't realize that was in build_properties. D
| |
312 # If the revision file doesn't exist, we're just testing the bot | |
313 if os.path.exists(revision_file): | |
314 with open(revision_file) as f: | |
315 revision = f.read() | |
316 else: | |
317 revision = 'testing' | |
318 bot_id = options.build_properties.get('buildername', 'unknown') | |
319 | |
320 timehash = hash(time.time()) | |
321 | |
322 boto_config = os.path.join(bb_utils.BB_BUILD_DIR, 'site_config', '.boto') | |
323 os.environ['AWS_CREDENTIAL_FILE'] = boto_config | |
Isaac (away)
2013/08/20 23:28:10
These are set automatically on bots; this isn't ne
gkanwar1
2013/08/20 23:40:29
Good to know, removed.
| |
324 os.environ['BOTO_CONFIG'] = boto_config | |
325 RunCmd([os.path.join(bb_utils.BB_BUILD_DIR, 'third_party', | |
Isaac (away)
2013/08/20 23:28:10
let's make the gsutil path a constant in bb_utils.
gkanwar1
2013/08/20 23:40:30
Done.
| |
326 'gsutil', 'gsutil'), 'cp', '-R', | |
327 path, 'gs://%s/%s/%s/%s/%s' % | |
328 (options.coverage_bucket, coverage_type, | |
329 bot_id, revision, timehash)]) | |
330 bb_annotations.PrintLink( | |
331 'Coverage report', | |
332 'https://storage.googleapis.com/%s/%s/%s/%s/%s/index.html' | |
333 % (options.coverage_bucket, coverage_type, bot_id, revision, timehash)) | |
334 | |
335 | |
336 def GenerateJavaCoverageReport(options): | |
337 bb_annotations.PrintNamedStep('java_coverage_report') | |
338 | |
339 coverage_html = os.path.join(options.coverage_dir, 'coverage_html') | |
340 RunCmd(['build/android/generate_emma_html.py', | |
341 '--coverage-dir', options.coverage_dir, | |
342 '--metadata-dir', os.path.join(CHROME_SRC, 'out', options.target), | |
343 '--output', os.path.join(coverage_html, 'coverage.html')]) | |
344 UploadCoverageData(options, coverage_html, 'java') | |
345 | |
346 | |
297 def LogcatDump(options): | 347 def LogcatDump(options): |
298 # Print logcat, kill logcat monitor | 348 # Print logcat, kill logcat monitor |
299 bb_annotations.PrintNamedStep('logcat_dump') | 349 bb_annotations.PrintNamedStep('logcat_dump') |
300 logcat_file = os.path.join(CHROME_SRC, 'out', options.target, 'full_log') | 350 logcat_file = os.path.join(CHROME_SRC, 'out', options.target, 'full_log') |
301 with open(logcat_file, 'w') as f: | 351 with open(logcat_file, 'w') as f: |
302 RunCmd([ | 352 RunCmd([ |
303 os.path.join(CHROME_SRC, 'build', 'android', 'adb_logcat_printer.py'), | 353 os.path.join(CHROME_SRC, 'build', 'android', 'adb_logcat_printer.py'), |
304 LOGCAT_DIR], stdout=f) | 354 LOGCAT_DIR], stdout=f) |
305 RunCmd(['cat', logcat_file]) | 355 RunCmd(['cat', logcat_file]) |
306 | 356 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
347 help='Run experiemental tests') | 397 help='Run experiemental tests') |
348 parser.add_option('-f', '--test-filter', metavar='<filter>', default=[], | 398 parser.add_option('-f', '--test-filter', metavar='<filter>', default=[], |
349 action='append', | 399 action='append', |
350 help=('Run a test suite. Test suites: "%s"' % | 400 help=('Run a test suite. Test suites: "%s"' % |
351 '", "'.join(VALID_TESTS))) | 401 '", "'.join(VALID_TESTS))) |
352 parser.add_option('--asan', action='store_true', help='Run tests with asan.') | 402 parser.add_option('--asan', action='store_true', help='Run tests with asan.') |
353 parser.add_option('--install', metavar='<apk name>', | 403 parser.add_option('--install', metavar='<apk name>', |
354 help='Install an apk by name') | 404 help='Install an apk by name') |
355 parser.add_option('--reboot', action='store_true', | 405 parser.add_option('--reboot', action='store_true', |
356 help='Reboot devices before running tests') | 406 help='Reboot devices before running tests') |
407 parser.add_option('--coverage-bucket', | |
408 help=('Bucket name to store coverage results. Coverage is ' | |
409 'only run if this is set.')) | |
357 parser.add_option( | 410 parser.add_option( |
358 '--flakiness-server', | 411 '--flakiness-server', |
359 help='The flakiness dashboard server to which the results should be ' | 412 help='The flakiness dashboard server to which the results should be ' |
360 'uploaded.') | 413 'uploaded.') |
361 parser.add_option( | 414 parser.add_option( |
362 '--auto-reconnect', action='store_true', | 415 '--auto-reconnect', action='store_true', |
363 help='Push script to device which restarts adbd on disconnections.') | 416 help='Push script to device which restarts adbd on disconnections.') |
364 parser.add_option( | 417 parser.add_option( |
365 '--logcat-dump-output', | 418 '--logcat-dump-output', |
366 help='The logcat dump output will be "tee"-ed into this file') | 419 help='The logcat dump output will be "tee"-ed into this file') |
367 | 420 |
368 return parser | 421 return parser |
369 | 422 |
370 | 423 |
371 def main(argv): | 424 def main(argv): |
372 parser = GetDeviceStepsOptParser() | 425 parser = GetDeviceStepsOptParser() |
373 options, args = parser.parse_args(argv[1:]) | 426 options, args = parser.parse_args(argv[1:]) |
374 | 427 |
375 if args: | 428 if args: |
376 return sys.exit('Unused args %s' % args) | 429 return sys.exit('Unused args %s' % args) |
377 | 430 |
378 unknown_tests = set(options.test_filter) - VALID_TESTS | 431 unknown_tests = set(options.test_filter) - VALID_TESTS |
379 if unknown_tests: | 432 if unknown_tests: |
380 return sys.exit('Unknown tests %s' % list(unknown_tests)) | 433 return sys.exit('Unknown tests %s' % list(unknown_tests)) |
381 | 434 |
382 setattr(options, 'target', options.factory_properties.get('target', 'Debug')) | 435 setattr(options, 'target', options.factory_properties.get('target', 'Debug')) |
436 if options.coverage_bucket: | |
437 setattr(options, 'coverage_dir', | |
438 os.path.join(CHROME_SRC, 'out', options.target, 'coverage')) | |
383 | 439 |
384 MainTestWrapper(options) | 440 MainTestWrapper(options) |
385 | 441 |
386 | 442 |
387 if __name__ == '__main__': | 443 if __name__ == '__main__': |
388 sys.exit(main(sys.argv)) | 444 sys.exit(main(sys.argv)) |
OLD | NEW |