Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 #!/usr/bin/env python | |
| 2 # Copyright (c) 2012 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 | |
| 6 import collections | |
| 7 import glob | |
| 8 import json | |
| 9 import optparse | |
| 10 import os | |
| 11 import pipes | |
| 12 import shutil | |
| 13 import subprocess | |
| 14 import sys | |
| 15 | |
| 16 sys.path.append(os.path.join(os.path.dirname(__file__), '..')) | |
| 17 from pylib import buildbot_report | |
| 18 from pylib import constants | |
| 19 | |
| 20 TESTING = 'BUILDBOT_TESTING' in os.environ | |
|
xusydoc (do not use)
2013/01/04 17:09:21
2 spaces between top-level defines
| |
| 21 CHROME_SRC = constants.CHROME_DIR | |
| 22 | |
| 23 | |
| 24 # Describes an instrumation test suite: | |
| 25 # test: Name of test we're running. | |
| 26 # apk: apk to be installed. | |
| 27 # apk_package: package for the apk to be installed. | |
| 28 # test_apk: apk to run tests on. | |
| 29 # test_data: data folder in format destination:source. | |
| 30 I_TEST = collections.namedtuple('InstrumentationTest', [ | |
| 31 'name', 'apk', 'apk_package', 'test_apk', 'test_data']) | |
| 32 | |
| 33 INSTRUMENTATION_TESTS = dict((suite.name, suite) for suite in [ | |
|
xusydoc (do not use)
2013/01/04 17:09:21
same
| |
| 34 I_TEST('ContentShell', | |
| 35 'ContentShell.apk', | |
| 36 'org.chromium.content_shell', | |
| 37 'ContentShellTest', | |
|
frankf
2012/12/27 19:57:47
There's a lot of redundancy here. Why can't you de
Isaac (away)
2012/12/27 22:23:03
I am porting bash code to python. If we want to s
| |
| 38 'content:content/test/data/android/device_files'), | |
| 39 I_TEST('ChromiumTestShell', | |
| 40 'ChromiumTestShell.apk', | |
| 41 'org.chromium.chrome.testshell', | |
| 42 'ChromiumTestShellTest', | |
| 43 'chrome:chrome/test/data/android/device_files'), | |
| 44 I_TEST('AndroidWebView', | |
| 45 'AndroidWebView.apk', | |
| 46 'org.chromium.android_webview', | |
| 47 'AndroidWebViewTest', | |
| 48 'webview:android_webview/test/data/device_files'), | |
| 49 ]) | |
| 50 | |
| 51 VALID_TESTS = set(['ui', 'unit', 'webkit', 'webkit_layout']) | |
|
xusydoc (do not use)
2013/01/04 17:09:21
same
| |
| 52 | |
| 53 | |
| 54 def RunCmd(command, flunk_on_failure=True): | |
| 55 """Run a command relative to the chrome source root.""" | |
| 56 | |
| 57 # Add adb binary to path. In the future, might use build_internal copy. | |
| 58 env = dict(os.environ) | |
| 59 env['PATH'] = os.pathsep.join([ | |
| 60 env['PATH'], os.path.join(constants.ANDROID_SDK_ROOT, 'platform-tools')]) | |
| 61 | |
| 62 command_str = ' '.join(map(pipes.quote, command)) | |
| 63 print '>', command_str | |
| 64 if not TESTING: | |
| 65 code = subprocess.Popen(command, cwd=CHROME_SRC, env=env).wait() | |
| 66 else: | |
| 67 code = 0 | |
| 68 print '<', command_str | |
| 69 if code != 0: | |
| 70 print 'ERROR: non-zero status %d from %s' % (code, command) | |
| 71 if flunk_on_failure: | |
| 72 buildbot_report.PrintError() | |
| 73 else: | |
| 74 buildbot_report.PrintWarning() | |
| 75 return code | |
| 76 | |
| 77 | |
| 78 def RunTestSuites(options, suite): | |
| 79 """Manages an invocation of run_tests.py. | |
| 80 | |
| 81 Args: | |
| 82 options: options object. | |
| 83 suite: The suite to pass to run_tests or None to run default suites. | |
| 84 """ | |
| 85 args = ['--verbose'] | |
| 86 if suite: | |
| 87 args.extend(['-s', suite]) | |
| 88 if options.target == 'Release': | |
| 89 args.append('--release') | |
| 90 if options.asan: | |
| 91 args.append('--tool=asan') | |
| 92 RunCmd(['build/android/run_tests.py'] + args) | |
|
frankf
2012/12/27 19:57:47
If we're adding the complexity of another wrapper,
Isaac (away)
2012/12/27 22:23:03
This is a pure port - bash -> python. We are not
frankf
2012/12/27 22:33:26
OK, let's keep this CL simple, but it seems we're
| |
| 93 | |
| 94 | |
| 95 def InstallApk(apk, apk_package, target): | |
| 96 args = ['--apk', apk, '--apk_package', apk_package] | |
| 97 if target == 'Release': | |
| 98 args.append('--release') | |
| 99 | |
| 100 RunCmd(['build/android/adb_install_apk.py'] + args) | |
| 101 | |
| 102 | |
| 103 def RunInstrumentationSuite(options, test): | |
| 104 """Manages an invocation of run_instrumentaiton_tests.py. | |
| 105 | |
| 106 Args: | |
| 107 options: options object | |
| 108 test: An I_TEST namedtuple | |
| 109 """ | |
| 110 buildbot_report.PrintNamedStep('Instrumentation tests for %s' % test.name) | |
|
frankf
2012/12/27 19:57:47
Will crbug.com/161993 be addressed in a follow up
Isaac (away)
2012/12/27 22:23:03
That is a separate bug, not directly related to th
frankf
2012/12/27 22:33:26
Let's avoid spaces. I've proposed a convention in
Isaac (away)
2012/12/27 22:55:20
OK, I took a look. I think the word instrumentati
frankf
2012/12/27 23:06:10
It's needed to remove ambiguity in other contexts.
Isaac (away)
2012/12/28 05:31:53
The instrumentation tests use ChromiumTestShell, w
| |
| 111 | |
| 112 InstallApk(test.apk, test.apk_package, options.target) | |
| 113 args = ['--test-apk', test.test_apk, '--test_data', test.test_data, '-vvv', | |
| 114 '-I'] | |
| 115 if options.target == 'Release': | |
| 116 args.append('--release') | |
| 117 if options.asan: | |
| 118 args.append('--tool=asan') | |
| 119 | |
| 120 RunCmd(['build/android/run_instrumentation_tests.py'] + args) | |
|
frankf
2012/12/27 19:57:47
Again, run_instrumentation_tests.py won't produce
Isaac (away)
2012/12/27 22:23:03
See above. Pure port / wrapper changes. It is co
| |
| 121 | |
| 122 | |
| 123 def RunWebkitLint(target): | |
| 124 """Lint WebKit's TestExpectation files.""" | |
| 125 buildbot_report.PrintNamedStep('webkit_lint') | |
| 126 RunCmd(['webkit/tools/layout_tests/run_webkit_tests.py', | |
| 127 '--lint-test-files', | |
| 128 '--chromium', | |
| 129 '--target', target]) | |
| 130 | |
| 131 | |
| 132 def RunWebkitLayoutTests(options): | |
| 133 """Run layout tests on an actual device.""" | |
| 134 buildbot_report.PrintNamedStep('webkit_tests') | |
| 135 RunCmd(['webkit/tools/layout_tests/run_webkit_tests.py', | |
| 136 '--no-show-results', | |
| 137 '--no-new-test-results', | |
| 138 '--full-results-html', | |
| 139 '--clobber-old-results', | |
| 140 '--exit-after-n-failures', '5000', | |
| 141 '--exit-after-n-crashes-or-timeouts', '100', | |
| 142 '--debug-rwt-logging', | |
| 143 '--results-directory', '..layout-test-results', | |
| 144 '--target', options.target, | |
| 145 '--builder-name', options.build_properties.get('buildername', ''), | |
| 146 '--build-number', options.build_properties.get('buildnumber', ''), | |
| 147 '--master-name', options.build_properties.get('mastername', ''), | |
| 148 '--build-name', options.build_properties.get('buildername', ''), | |
| 149 '--platform=chromium-android', | |
| 150 '--test-results-server', | |
| 151 options.factory_properties.get('test_results_server', '')]) | |
| 152 | |
| 153 | |
| 154 def MainTestWrapper(options): | |
| 155 if options.install: | |
| 156 test_obj = INSTRUMENTATION_TESTS[options.install] | |
| 157 InstallApk(test_obj.apk, test_obj.apk_package, options.target) | |
| 158 | |
| 159 if not options.test_filter: | |
| 160 return | |
| 161 | |
| 162 # Device check and alert emails | |
| 163 RunCmd(['build/android/device_status_check.py'], flunk_on_failure=False) | |
| 164 | |
| 165 # Spawn logcat monitor | |
| 166 logcat_dir = os.path.join(CHROME_SRC, 'out/logcat') | |
| 167 shutil.rmtree(logcat_dir, ignore_errors=True) | |
| 168 if not TESTING: | |
| 169 subprocess.Popen( | |
| 170 ['build/android/adb_logcat_monitor.py', logcat_dir], cwd=CHROME_SRC) | |
| 171 | |
| 172 if 'unit' in options.test_filter: | |
| 173 RunTestSuites(options, None) | |
| 174 if 'ui' in options.test_filter: | |
| 175 for test in INSTRUMENTATION_TESTS.itervalues(): | |
| 176 RunInstrumentationSuite(options, test) | |
| 177 if 'webkit' in options.test_filter: | |
| 178 RunTestSuites(options, 'webkit_unit_tests') | |
| 179 RunTestSuites(options, 'TestWebKitAPI') | |
| 180 RunWebkitLint(options.target) | |
| 181 if 'webkit_layout' in options.test_filter: | |
| 182 RunWebkitLayoutTests(options) | |
| 183 | |
| 184 if options.experimental: | |
| 185 pass | |
| 186 | |
| 187 # Print logcat, kill logcat monitor | |
| 188 buildbot_report.PrintNamedStep('Logcat dump') | |
| 189 RunCmd(['build/android/adb_logcat_printer.py', logcat_dir]) | |
| 190 | |
| 191 buildbot_report.PrintNamedStep('Test report') | |
| 192 for report in glob.glob( | |
| 193 os.path.join(CHROME_SRC, 'out', options.target, 'test_logs', '*.log')): | |
| 194 subprocess.Popen(['cat', report]).wait() | |
| 195 os.remove(report) | |
| 196 | |
| 197 | |
| 198 def main(argv): | |
| 199 parser = optparse.OptionParser() | |
| 200 | |
| 201 def convert_json(option, _, value, parser): | |
| 202 setattr(parser.values, option.dest, json.loads(value)) | |
| 203 | |
| 204 parser.add_option('--build-properties', action='callback', | |
| 205 callback=convert_json, type='string', default={}, | |
| 206 help='build properties in JSON format') | |
| 207 parser.add_option('--factory-properties', action='callback', | |
| 208 callback=convert_json, type='string', default={}, | |
| 209 help='factory properties in JSON format') | |
| 210 parser.add_option('--slave-properties', action='callback', | |
| 211 callback=convert_json, type='string', default={}, | |
| 212 help='Properties set by slave script in JSON format') | |
| 213 parser.add_option('--experimental', action='store_true', | |
| 214 help='Run experiemental tests') | |
| 215 parser.add_option('-f', '--test-filter', metavar='<filter>', default=[], | |
| 216 action='append', | |
| 217 help=('Run a test suite. Test suites: "%s"' % | |
| 218 '", "'.join(VALID_TESTS))) | |
| 219 parser.add_option('--asan', action='store_true', help='Run tests with asan.') | |
| 220 parser.add_option('--install', metavar='<apk name>', | |
| 221 help='Install an apk by name') | |
| 222 options, args = parser.parse_args(argv[1:]) | |
| 223 | |
| 224 def ParserError(msg): | |
| 225 """We avoid parser.error because it calls sys.exit.""" | |
| 226 parser.print_help() | |
| 227 print >>sys.stderr, '\nERROR:', msg | |
| 228 return 1 | |
| 229 | |
| 230 if args: | |
| 231 return ParserError('Unused args %s' % args) | |
| 232 | |
| 233 unknown_tests = set(options.test_filter) - VALID_TESTS | |
| 234 if unknown_tests: | |
| 235 return ParserError('Unknown tests %s' % list(unknown_tests)) | |
| 236 | |
| 237 setattr(options, 'target', options.factory_properties.get('target', 'Debug')) | |
| 238 | |
| 239 MainTestWrapper(options) | |
| 240 | |
| 241 if __name__ == '__main__': | |
|
xusydoc (do not use)
2013/01/04 17:09:21
same
| |
| 242 sys.exit(main(sys.argv)) | |
| OLD | NEW |