Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(202)

Side by Side Diff: build/android/buildbot/bb_device_steps.py

Issue 15261003: Add a new script bb_host_steps.py which handles all host side steps. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: First Full CL Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 json
9 import multiprocessing 8 import multiprocessing
10 import optparse
11 import os 9 import os
12 import pipes
13 import shutil 10 import shutil
14 import subprocess
15 import sys 11 import sys
16 12
13 import bb_utils
14
17 sys.path.append(os.path.join(os.path.dirname(__file__), '..')) 15 sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
18 from pylib import android_commands 16 from pylib import android_commands
19 from pylib import buildbot_report 17 from pylib import buildbot_report
20 from pylib import constants 18 from pylib import constants
21 from pylib.gtest import gtest_config 19 from pylib.gtest import gtest_config
22 20
23 sys.path.append(os.path.join( 21 sys.path.append(os.path.join(
24 constants.CHROME_DIR, 'third_party', 'android_testrunner')) 22 constants.CHROME_DIR, 'third_party', 'android_testrunner'))
25 import errors 23 import errors
26 24
27 25
28 TESTING = 'BUILDBOT_TESTING' in os.environ
29
30 CHROME_SRC = constants.CHROME_DIR 26 CHROME_SRC = constants.CHROME_DIR
31 27
32 # Describes an instrumation test suite: 28 # Describes an instrumation test suite:
33 # test: Name of test we're running. 29 # test: Name of test we're running.
34 # apk: apk to be installed. 30 # apk: apk to be installed.
35 # apk_package: package for the apk to be installed. 31 # apk_package: package for the apk to be installed.
36 # test_apk: apk to run tests on. 32 # test_apk: apk to run tests on.
37 # test_data: data folder in format destination:source. 33 # test_data: data folder in format destination:source.
38 I_TEST = collections.namedtuple('InstrumentationTest', [ 34 I_TEST = collections.namedtuple('InstrumentationTest', [
39 'name', 'apk', 'apk_package', 'test_apk', 'test_data', 'host_driven_root']) 35 'name', 'apk', 'apk_package', 'test_apk', 'test_data', 'host_driven_root'])
(...skipping 14 matching lines...) Expand all
54 I_TEST('AndroidWebView', 50 I_TEST('AndroidWebView',
55 'AndroidWebView.apk', 51 'AndroidWebView.apk',
56 'org.chromium.android_webview.shell', 52 'org.chromium.android_webview.shell',
57 'AndroidWebViewTest', 53 'AndroidWebViewTest',
58 'webview:android_webview/test/data/device_files', 54 'webview:android_webview/test/data/device_files',
59 None), 55 None),
60 ]) 56 ])
61 57
62 VALID_TESTS = set(['chromedriver', 'ui', 'unit', 'webkit', 'webkit_layout']) 58 VALID_TESTS = set(['chromedriver', 'ui', 'unit', 'webkit', 'webkit_layout'])
63 59
64 60 R = bb_utils.RunCmd
Isaac (away) 2013/06/04 04:34:12 This is fine, but how about we name this RunCmd?
Siva Chandra 2013/06/04 19:42:40 Done.
65 def SpawnCmd(command):
66 """Spawn a process without waiting for termination."""
67 print '>', ' '.join(map(pipes.quote, command))
68 sys.stdout.flush()
69 if TESTING:
70 class MockPopen(object):
71 @staticmethod
72 def wait():
73 return 0
74 return MockPopen()
75
76 return subprocess.Popen(command, cwd=CHROME_SRC)
77
78 def RunCmd(command, flunk_on_failure=True, halt_on_failure=False):
79 """Run a command relative to the chrome source root."""
80 code = SpawnCmd(command).wait()
81 print '<', ' '.join(map(pipes.quote, command))
82 if code != 0:
83 print 'ERROR: process exited with code %d' % code
84 if flunk_on_failure:
85 buildbot_report.PrintError()
86 else:
87 buildbot_report.PrintWarning()
88 # Allow steps to have both halting (i.e. 1) and non-halting exit codes.
89 if code != 0 and code != 88 and halt_on_failure:
90 raise OSError()
91 return code
92 61
93 62
94 # multiprocessing map_async requires a top-level function for pickle library. 63 # multiprocessing map_async requires a top-level function for pickle library.
95 def RebootDeviceSafe(device): 64 def RebootDeviceSafe(device):
96 """Reboot a device, wait for it to start, and squelch timeout exceptions.""" 65 """Reboot a device, wait for it to start, and squelch timeout exceptions."""
97 try: 66 try:
98 android_commands.AndroidCommands(device).Reboot(True) 67 android_commands.AndroidCommands(device).Reboot(True)
99 except errors.DeviceUnresponsiveError as e: 68 except errors.DeviceUnresponsiveError as e:
100 return e 69 return e
101 70
102 71
103 def RebootDevices(): 72 def RebootDevices():
104 """Reboot all attached and online devices.""" 73 """Reboot all attached and online devices."""
105 buildbot_report.PrintNamedStep('Reboot devices') 74 buildbot_report.PrintNamedStep('Reboot devices')
106 # Early return here to avoid presubmit dependence on adb, 75 # Early return here to avoid presubmit dependence on adb,
107 # which might not exist in this checkout. 76 # which might not exist in this checkout.
108 if TESTING: 77 if bb_utils.TESTING:
109 return 78 return
110 devices = android_commands.GetAttachedDevices() 79 devices = android_commands.GetAttachedDevices()
111 print 'Rebooting: %s' % devices 80 print 'Rebooting: %s' % devices
112 if devices: 81 if devices:
113 pool = multiprocessing.Pool(len(devices)) 82 pool = multiprocessing.Pool(len(devices))
114 results = pool.map_async(RebootDeviceSafe, devices).get(99999) 83 results = pool.map_async(RebootDeviceSafe, devices).get(99999)
115 84
116 for device, result in zip(devices, results): 85 for device, result in zip(devices, results):
117 if result: 86 if result:
118 print '%s failed to startup.' % device 87 print '%s failed to startup.' % device
(...skipping 14 matching lines...) Expand all
133 args = ['--verbose'] 102 args = ['--verbose']
134 if options.target == 'Release': 103 if options.target == 'Release':
135 args.append('--release') 104 args.append('--release')
136 if options.asan: 105 if options.asan:
137 args.append('--tool=asan') 106 args.append('--tool=asan')
138 for suite in suites: 107 for suite in suites:
139 buildbot_report.PrintNamedStep(suite.name) 108 buildbot_report.PrintNamedStep(suite.name)
140 cmd = ['build/android/run_tests.py', '-s', suite.name] + args 109 cmd = ['build/android/run_tests.py', '-s', suite.name] + args
141 if suite.is_suite_exe: 110 if suite.is_suite_exe:
142 cmd.append('--exe') 111 cmd.append('--exe')
143 RunCmd(cmd) 112 R(cmd)
144 113
145 def RunBrowserTestSuite(options): 114 def RunBrowserTestSuite(options):
146 """Manages an invocation of run_browser_tests.py. 115 """Manages an invocation of run_browser_tests.py.
147 116
148 Args: 117 Args:
149 options: options object. 118 options: options object.
150 """ 119 """
151 args = ['--verbose'] 120 args = ['--verbose']
152 if options.target == 'Release': 121 if options.target == 'Release':
153 args.append('--release') 122 args.append('--release')
154 if options.asan: 123 if options.asan:
155 args.append('--tool=asan') 124 args.append('--tool=asan')
156 buildbot_report.PrintNamedStep(constants.BROWSERTEST_SUITE_NAME) 125 buildbot_report.PrintNamedStep(constants.BROWSERTEST_SUITE_NAME)
157 RunCmd(['build/android/run_browser_tests.py'] + args) 126 R(['build/android/run_browser_tests.py'] + args)
158 127
159 def RunChromeDriverTests(): 128 def RunChromeDriverTests():
160 """Run all the steps for running chromedriver tests.""" 129 """Run all the steps for running chromedriver tests."""
161 buildbot_report.PrintNamedStep('chromedriver_annotation') 130 buildbot_report.PrintNamedStep('chromedriver_annotation')
162 RunCmd(['chrome/test/chromedriver/run_buildbot_steps.py', 131 R(['chrome/test/chromedriver/run_buildbot_steps.py',
163 '--android-package=%s' % constants.CHROMIUM_TEST_SHELL_PACKAGE]) 132 '--android-package=%s' % constants.CHROMIUM_TEST_SHELL_PACKAGE])
164 133
165 134
166 def CheckInstall(): 135 def CheckInstall():
167 """Build bot step to see if adb install works on attached devices. """ 136 """Build bot step to see if adb install works on attached devices. """
168 buildbot_report.PrintNamedStep('Check device install') 137 buildbot_report.PrintNamedStep('Check device install')
169 # This step checks if apks can be installed on the devices. 138 # This step checks if apks can be installed on the devices.
170 args = ['--apk', 'build/android/CheckInstallApk-debug.apk'] 139 args = ['--apk', 'build/android/CheckInstallApk-debug.apk']
171 RunCmd(['build/android/adb_install_apk.py'] + args, halt_on_failure=True) 140 R(['build/android/adb_install_apk.py'] + args, halt_on_failure=True)
172 141
173 142
174 def InstallApk(options, test, print_step=False): 143 def InstallApk(options, test, print_step=False):
175 """Install an apk to all phones. 144 """Install an apk to all phones.
176 145
177 Args: 146 Args:
178 options: options object 147 options: options object
179 test: An I_TEST namedtuple 148 test: An I_TEST namedtuple
180 print_step: Print a buildbot step 149 print_step: Print a buildbot step
181 """ 150 """
182 if print_step: 151 if print_step:
183 buildbot_report.PrintNamedStep('install_%s' % test.name.lower()) 152 buildbot_report.PrintNamedStep('install_%s' % test.name.lower())
184 args = ['--apk', test.apk, '--apk_package', test.apk_package] 153 args = ['--apk', test.apk, '--apk_package', test.apk_package]
185 if options.target == 'Release': 154 if options.target == 'Release':
186 args.append('--release') 155 args.append('--release')
187 156
188 RunCmd(['build/android/adb_install_apk.py'] + args, halt_on_failure=True) 157 R(['build/android/adb_install_apk.py'] + args, halt_on_failure=True)
189 158
190 159
191 def RunInstrumentationSuite(options, test): 160 def RunInstrumentationSuite(options, test):
192 """Manages an invocation of run_instrumentaiton_tests.py. 161 """Manages an invocation of run_instrumentaiton_tests.py.
193 162
194 Args: 163 Args:
195 options: options object 164 options: options object
196 test: An I_TEST namedtuple 165 test: An I_TEST namedtuple
197 """ 166 """
198 buildbot_report.PrintNamedStep('%s_instrumentation_tests' % test.name.lower()) 167 buildbot_report.PrintNamedStep('%s_instrumentation_tests' % test.name.lower())
199 168
200 InstallApk(options, test) 169 InstallApk(options, test)
201 args = ['--test-apk', test.test_apk, '--test_data', test.test_data, 170 args = ['--test-apk', test.test_apk, '--test_data', test.test_data,
202 '--verbose', '-I'] 171 '--verbose', '-I']
203 if options.target == 'Release': 172 if options.target == 'Release':
204 args.append('--release') 173 args.append('--release')
205 if options.asan: 174 if options.asan:
206 args.append('--tool=asan') 175 args.append('--tool=asan')
207 if options.upload_to_flakiness_server: 176 if options.upload_to_flakiness_server:
208 args.append('--flakiness-dashboard-server=%s' % 177 args.append('--flakiness-dashboard-server=%s' %
209 constants.UPSTREAM_FLAKINESS_SERVER) 178 constants.UPSTREAM_FLAKINESS_SERVER)
210 if test.host_driven_root: 179 if test.host_driven_root:
211 args.append('--python_test_root=%s' % test.host_driven_root) 180 args.append('--python_test_root=%s' % test.host_driven_root)
212 181
213 RunCmd(['build/android/run_instrumentation_tests.py'] + args) 182 R(['build/android/run_instrumentation_tests.py'] + args)
214 183
215 184
216 def RunWebkitLint(target): 185 def RunWebkitLint(target):
217 """Lint WebKit's TestExpectation files.""" 186 """Lint WebKit's TestExpectation files."""
218 buildbot_report.PrintNamedStep('webkit_lint') 187 buildbot_report.PrintNamedStep('webkit_lint')
219 RunCmd(['webkit/tools/layout_tests/run_webkit_tests.py', 188 R(['webkit/tools/layout_tests/run_webkit_tests.py',
220 '--lint-test-files', 189 '--lint-test-files',
221 '--chromium', 190 '--chromium',
222 '--target', target]) 191 '--target', target])
223 192
224 193
225 def RunWebkitLayoutTests(options): 194 def RunWebkitLayoutTests(options):
226 """Run layout tests on an actual device.""" 195 """Run layout tests on an actual device."""
227 buildbot_report.PrintNamedStep('webkit_tests') 196 buildbot_report.PrintNamedStep('webkit_tests')
228 cmd_args = [ 197 cmd_args = [
229 '--no-show-results', 198 '--no-show-results',
(...skipping 19 matching lines...) Expand all
249 for f in options.factory_properties.get('additional_expectations', []): 218 for f in options.factory_properties.get('additional_expectations', []):
250 cmd_args.extend( 219 cmd_args.extend(
251 ['--additional-expectations=%s' % os.path.join(CHROME_SRC, *f)]) 220 ['--additional-expectations=%s' % os.path.join(CHROME_SRC, *f)])
252 221
253 # TODO(dpranke): Remove this block after 222 # TODO(dpranke): Remove this block after
254 # https://codereview.chromium.org/12927002/ lands. 223 # https://codereview.chromium.org/12927002/ lands.
255 for f in options.factory_properties.get('additional_expectations_files', []): 224 for f in options.factory_properties.get('additional_expectations_files', []):
256 cmd_args.extend( 225 cmd_args.extend(
257 ['--additional-expectations=%s' % os.path.join(CHROME_SRC, *f)]) 226 ['--additional-expectations=%s' % os.path.join(CHROME_SRC, *f)])
258 227
259 RunCmd(['webkit/tools/layout_tests/run_webkit_tests.py'] + cmd_args, 228 R(['webkit/tools/layout_tests/run_webkit_tests.py'] + cmd_args,
260 flunk_on_failure=False) 229 flunk_on_failure=False)
261 230
262 231
263 def MainTestWrapper(options): 232 def MainTestWrapper(options):
264 # Restart adb to work around bugs, sleep to wait for usb discovery. 233 # Restart adb to work around bugs, sleep to wait for usb discovery.
265 RunCmd(['adb', 'kill-server']) 234 R(['adb', 'kill-server'])
266 RunCmd(['adb', 'start-server']) 235 R(['adb', 'start-server'])
267 RunCmd(['sleep', '1']) 236 R(['sleep', '1'])
268 237
269 # Spawn logcat monitor 238 # Spawn logcat monitor
270 logcat_dir = os.path.join(CHROME_SRC, 'out/logcat') 239 logcat_dir = os.path.join(CHROME_SRC, 'out/logcat')
271 shutil.rmtree(logcat_dir, ignore_errors=True) 240 shutil.rmtree(logcat_dir, ignore_errors=True)
272 SpawnCmd(['build/android/adb_logcat_monitor.py', logcat_dir]) 241 bb_utils.SpawnCmd(['build/android/adb_logcat_monitor.py', logcat_dir])
273 242
274 # Wait for logcat_monitor to pull existing logcat 243 # Wait for logcat_monitor to pull existing logcat
275 RunCmd(['sleep', '5']) 244 R(['sleep', '5'])
276 245
277 if options.reboot: 246 if options.reboot:
278 RebootDevices() 247 RebootDevices()
279 248
280 # Device check and alert emails 249 # Device check and alert emails
281 buildbot_report.PrintNamedStep('device_status_check') 250 buildbot_report.PrintNamedStep('device_status_check')
282 RunCmd(['build/android/device_status_check.py'], halt_on_failure=True) 251 R(['build/android/device_status_check.py'], halt_on_failure=True)
283 252
284 # Provision devices 253 # Provision devices
285 buildbot_report.PrintNamedStep('provision_devices') 254 buildbot_report.PrintNamedStep('provision_devices')
286 target = options.factory_properties.get('target', 'Debug') 255 target = options.factory_properties.get('target', 'Debug')
287 RunCmd(['build/android/provision_devices.py', '-t', target]) 256 R(['build/android/provision_devices.py', '-t', target])
288 257
289 # Check to see if devices can install apks. 258 # Check to see if devices can install apks.
290 CheckInstall() 259 CheckInstall()
291 260
292 if options.install: 261 if options.install:
293 test_obj = INSTRUMENTATION_TESTS[options.install] 262 test_obj = INSTRUMENTATION_TESTS[options.install]
294 InstallApk(options, test_obj, print_step=True) 263 InstallApk(options, test_obj, print_step=True)
295 264
296 if 'chromedriver' in options.test_filter: 265 if 'chromedriver' in options.test_filter:
297 RunChromeDriverTests() 266 RunChromeDriverTests()
298 if 'unit' in options.test_filter: 267 if 'unit' in options.test_filter:
299 RunTestSuites(options, gtest_config.STABLE_TEST_SUITES) 268 RunTestSuites(options, gtest_config.STABLE_TEST_SUITES)
300 if 'ui' in options.test_filter: 269 if 'ui' in options.test_filter:
301 for test in INSTRUMENTATION_TESTS.itervalues(): 270 for test in INSTRUMENTATION_TESTS.itervalues():
302 RunInstrumentationSuite(options, test) 271 RunInstrumentationSuite(options, test)
303 if 'webkit' in options.test_filter: 272 if 'webkit' in options.test_filter:
304 RunTestSuites(options, [ 273 RunTestSuites(options, [
305 gtest_config.Apk('webkit_unit_tests'), 274 gtest_config.Apk('webkit_unit_tests'),
306 ]) 275 ])
307 RunWebkitLint(options.target) 276 RunWebkitLint(options.target)
308 if 'webkit_layout' in options.test_filter: 277 if 'webkit_layout' in options.test_filter:
309 RunWebkitLayoutTests(options) 278 RunWebkitLayoutTests(options)
310 279
311 if options.experimental: 280 if options.experimental:
312 RunTestSuites(options, gtest_config.EXPERIMENTAL_TEST_SUITES) 281 RunTestSuites(options, gtest_config.EXPERIMENTAL_TEST_SUITES)
313 RunBrowserTestSuite(options) 282 RunBrowserTestSuite(options)
314 283
315 # Print logcat, kill logcat monitor 284 # Print logcat, kill logcat monitor
316 buildbot_report.PrintNamedStep('logcat_dump') 285 buildbot_report.PrintNamedStep('logcat_dump')
317 RunCmd(['build/android/adb_logcat_printer.py', logcat_dir]) 286 R(['build/android/adb_logcat_printer.py', logcat_dir])
318 287
319 buildbot_report.PrintNamedStep('test_report') 288 buildbot_report.PrintNamedStep('test_report')
320 for report in glob.glob( 289 for report in glob.glob(
321 os.path.join(CHROME_SRC, 'out', options.target, 'test_logs', '*.log')): 290 os.path.join(CHROME_SRC, 'out', options.target, 'test_logs', '*.log')):
322 RunCmd(['cat', report]) 291 R(['cat', report])
323 os.remove(report) 292 os.remove(report)
324 293
325 294
326 def main(argv): 295 def main(argv):
327 parser = optparse.OptionParser() 296 buildbot_report.PrintNamedStep('Run tests')
328 297
329 def convert_json(option, _, value, parser): 298 parser = bb_utils.GetParser()
330 setattr(parser.values, option.dest, json.loads(value))
331
332 parser.add_option('--build-properties', action='callback',
333 callback=convert_json, type='string', default={},
334 help='build properties in JSON format')
335 parser.add_option('--factory-properties', action='callback',
336 callback=convert_json, type='string', default={},
337 help='factory properties in JSON format')
338 parser.add_option('--slave-properties', action='callback',
339 callback=convert_json, type='string', default={},
340 help='Properties set by slave script in JSON format')
341 parser.add_option('--experimental', action='store_true', 299 parser.add_option('--experimental', action='store_true',
342 help='Run experiemental tests') 300 help='Run experiemental tests')
343 parser.add_option('-f', '--test-filter', metavar='<filter>', default=[], 301 parser.add_option('-f', '--test-filter', metavar='<filter>', default=[],
344 action='append', 302 action='append',
345 help=('Run a test suite. Test suites: "%s"' % 303 help=('Run a test suite. Test suites: "%s"' %
346 '", "'.join(VALID_TESTS))) 304 '", "'.join(VALID_TESTS)))
347 parser.add_option('--asan', action='store_true', help='Run tests with asan.') 305 parser.add_option('--asan', action='store_true', help='Run tests with asan.')
348 parser.add_option('--install', metavar='<apk name>', 306 parser.add_option('--install', metavar='<apk name>',
349 help='Install an apk by name') 307 help='Install an apk by name')
350 parser.add_option('--reboot', action='store_true', 308 parser.add_option('--reboot', action='store_true',
351 help='Reboot devices before running tests') 309 help='Reboot devices before running tests')
352 parser.add_option('--upload-to-flakiness-server', action='store_true', 310 parser.add_option('--upload-to-flakiness-server', action='store_true',
353 help='Upload the results to the flakiness dashboard.') 311 help='Upload the results to the flakiness dashboard.')
354 parser.add_option( 312 parser.add_option(
355 '--auto-reconnect', action='store_true', 313 '--auto-reconnect', action='store_true',
356 help='Push script to device which restarts adbd on disconnections.') 314 help='Push script to device which restarts adbd on disconnections.')
357 options, args = parser.parse_args(argv[1:]) 315 options, args = parser.parse_args(argv[1:])
358 316
359 def ParserError(msg):
360 """We avoid parser.error because it calls sys.exit."""
361 parser.print_help()
362 print >> sys.stderr, '\nERROR:', msg
363 return 1
364
365 if args: 317 if args:
366 return ParserError('Unused args %s' % args) 318 return parser.Error('Unused args %s' % args)
367 319
368 unknown_tests = set(options.test_filter) - VALID_TESTS 320 unknown_tests = set(options.test_filter) - VALID_TESTS
369 if unknown_tests: 321 if unknown_tests:
370 return ParserError('Unknown tests %s' % list(unknown_tests)) 322 return parser.Error('Unknown tests %s' % list(unknown_tests))
371 323
372 setattr(options, 'target', options.factory_properties.get('target', 'Debug')) 324 setattr(options, 'target', options.factory_properties.get('target', 'Debug'))
373 325
374 # Add adb binary and chromium-source platform-tools to tip of PATH variable. 326 # Add adb binary and chromium-source platform-tools to tip of PATH variable.
375 android_paths = [os.path.join(constants.ANDROID_SDK_ROOT, 'platform-tools')] 327 android_paths = [os.path.join(constants.ANDROID_SDK_ROOT, 'platform-tools')]
376 328
377 # Bots checkout chrome in /b/build/slave/<name>/build/src 329 # Bots checkout chrome in /b/build/slave/<name>/build/src
378 build_internal_android = os.path.abspath(os.path.join( 330 build_internal_android = os.path.abspath(os.path.join(
379 CHROME_SRC, '..', '..', '..', '..', '..', 'build_internal', 'scripts', 331 CHROME_SRC, '..', '..', '..', '..', '..', 'build_internal', 'scripts',
380 'slave', 'android')) 332 'slave', 'android'))
381 if os.path.exists(build_internal_android): 333 if os.path.exists(build_internal_android):
382 android_paths.insert(0, build_internal_android) 334 android_paths.insert(0, build_internal_android)
383 os.environ['PATH'] = os.pathsep.join(android_paths + [os.environ['PATH']]) 335 os.environ['PATH'] = os.pathsep.join(android_paths + [os.environ['PATH']])
384 336
385 MainTestWrapper(options) 337 MainTestWrapper(options)
386 338
387 339
388 if __name__ == '__main__': 340 if __name__ == '__main__':
389 sys.exit(main(sys.argv)) 341 sys.exit(main(sys.argv))
OLDNEW
« no previous file with comments | « no previous file | build/android/buildbot/bb_host_steps.py » ('j') | build/android/buildbot/bb_host_steps.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698