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

Side by Side Diff: build/android/run_tests.py

Issue 11557016: Clean up Android gtest runners. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years 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
« no previous file with comments | « build/android/pylib/test_package_executable.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # 2 #
3 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 3 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be 4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file. 5 # found in the LICENSE file.
6 6
7 """Runs all the native unit tests. 7 """Runs all the native unit tests.
8 8
9 1. Copy over test binary to /data/local on device. 9 1. Copy over test binary to /data/local on device.
10 2. Resources: chrome/unit_tests requires resources (chrome.pak and en-US.pak) 10 2. Resources: chrome/unit_tests requires resources (chrome.pak and en-US.pak)
11 to be deployed to the device. We use the device's $EXTERNAL_STORAGE as the 11 to be deployed to the device. We use the device's $EXTERNAL_STORAGE as the
12 base dir (which maps to Context.getExternalFilesDir()). 12 base dir (which maps to Context.getExternalFilesDir()).
13 3. Environment: 13 3. Environment:
14 3.1. chrome/unit_tests requires (via chrome_paths.cc) a directory named: 14 3.1. chrome/unit_tests requires (via chrome_paths.cc) a directory named:
15 $EXTERNAL_STORAGE + /chrome/test/data 15 $EXTERNAL_STORAGE + /chrome/test/data
16 3.2. page_cycler_tests have following requirements, 16 3.2. page_cycler_tests have following requirements,
17 3.2.1 the following data on host: 17 3.2.1 the following data on host:
18 <chrome_src_dir>/tools/page_cycler 18 <chrome_src_dir>/tools/page_cycler
19 <chrome_src_dir>/data/page_cycler 19 <chrome_src_dir>/data/page_cycler
20 3.2.2. two data directories to store above test data on device named: 20 3.2.2. two data directories to store above test data on device named:
21 $EXTERNAL_STORAGE + /tools/ (for database perf test) 21 $EXTERNAL_STORAGE + /tools/ (for database perf test)
22 $EXTERNAL_STORAGE + /data/ (for other perf tests) 22 $EXTERNAL_STORAGE + /data/ (for other perf tests)
23 3.2.3. a http server to serve http perf tests. 23 3.2.3. a http server to serve http perf tests.
24 The http root is host's <chrome_src_dir>/data/page_cycler/, port 8000. 24 The http root is host's <chrome_src_dir>/data/page_cycler/, port 8000.
25 3.2.4 a tool named forwarder is also required to run on device to 25 3.2.4 a tool named forwarder is also required to run on device to
26 forward the http request/response between host and device. 26 forward the http request/response between host and device.
27 3.2.5 Chrome is installed on device. 27 3.2.5 Chrome is installed on device.
28 4. Run the binary in the device and stream the log to the host. 28 4. Run the binary in the device and stream the log to the host.
29 4.1. Optionally, filter specific tests. 29 4.1. Optionally, filter specific tests.
30 4.2. Optionally, rebaseline: run the available tests and update the 30 4.2. If we're running a single test suite and we have multiple devices
31 suppressions file for failures.
32 4.3. If we're running a single test suite and we have multiple devices
33 connected, we'll shard the tests. 31 connected, we'll shard the tests.
34 5. Clean up the device. 32 5. Clean up the device.
35 33
36 Suppressions: 34 Suppressions:
37 35
38 Individual tests in a test binary can be suppressed by listing it in 36 Individual tests in a test binary can be suppressed by listing it in
39 the gtest_filter directory in a file of the same name as the test binary, 37 the gtest_filter directory in a file of the same name as the test binary,
40 one test per line. Here is an example: 38 one test per line. Here is an example:
41 39
42 $ cat gtest_filter/base_unittests_disabled 40 $ cat gtest_filter/base_unittests_disabled
43 DataPackTest.Load 41 DataPackTest.Load
44 ReadOnlyFileUtilTest.ContentsEqual 42 ReadOnlyFileUtilTest.ContentsEqual
45 43
46 This file is generated by the tests running on devices. If running on emulator, 44 This file is generated by the tests running on devices. If running on emulator,
47 additonal filter file which lists the tests only failed in emulator will be 45 additonal filter file which lists the tests only failed in emulator will be
48 loaded. We don't care about the rare testcases which succeeded on emuatlor, but 46 loaded. We don't care about the rare testcases which succeeded on emuatlor, but
49 failed on device. 47 failed on device.
50 """ 48 """
51 49
52 import copy 50 import copy
53 import fnmatch 51 import fnmatch
54 import logging 52 import logging
55 import optparse 53 import optparse
56 import os 54 import os
57 import signal 55 import signal
58 import subprocess 56 import subprocess
59 import sys 57 import sys
60 import time 58 import time
61 59
60 import emulator
62 from pylib import android_commands 61 from pylib import android_commands
63 from pylib.base_test_sharder import BaseTestSharder
64 from pylib import buildbot_report 62 from pylib import buildbot_report
65 from pylib import cmd_helper 63 from pylib import cmd_helper
66 from pylib import constants
67 from pylib import debug_info 64 from pylib import debug_info
68 import emulator
69 from pylib import ports 65 from pylib import ports
70 from pylib import run_tests_helper 66 from pylib import run_tests_helper
71 from pylib import test_options_parser 67 from pylib import test_options_parser
68 from pylib.base_test_sharder import BaseTestSharder
72 from pylib.single_test_runner import SingleTestRunner 69 from pylib.single_test_runner import SingleTestRunner
73 from pylib.test_result import BaseTestResult, TestResults
74 70
75 71
76 _TEST_SUITES = ['base_unittests', 72 _TEST_SUITES = ['base_unittests',
77 'cc_unittests', 73 'cc_unittests',
78 'content_unittests', 74 'content_unittests',
79 'gpu_unittests', 75 'gpu_unittests',
80 'ipc_tests', 76 'ipc_tests',
81 'media_unittests', 77 'media_unittests',
82 'net_unittests', 78 'net_unittests',
83 'sql_unittests', 79 'sql_unittests',
84 'sync_unit_tests', 80 'sync_unit_tests',
85 'ui_unittests', 81 'ui_unittests',
86 'unit_tests', 82 'unit_tests',
87 'webkit_compositor_bindings_unittests', 83 'webkit_compositor_bindings_unittests',
88 ] 84 ]
89 85
90 86
91 def FullyQualifiedTestSuites(exe, option_test_suite, build_type): 87 def FullyQualifiedTestSuites(exe, option_test_suite, build_type):
92 """Return a fully qualified list 88 """Get a list of absolute paths to test suite targets.
93 89
94 Args: 90 Args:
95 exe: if True, use the executable-based test runner. 91 exe: if True, use the executable-based test runner.
96 option_test_suite: the test_suite specified as an option. 92 option_test_suite: the test_suite specified as an option.
97 build_type: 'Release' or 'Debug'. 93 build_type: 'Release' or 'Debug'.
98 """ 94 """
99 test_suite_dir = os.path.join(cmd_helper.OutDirectory.get(), build_type) 95 test_suite_dir = os.path.join(cmd_helper.OutDirectory.get(), build_type)
100 if option_test_suite: 96 if option_test_suite:
101 all_test_suites = [option_test_suite] 97 all_test_suites = [option_test_suite]
102 else: 98 else:
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 except: 178 except:
183 pass 179 pass
184 del os.environ['DISPLAY'] 180 del os.environ['DISPLAY']
185 self._pid = 0 181 self._pid = 0
186 182
187 183
188 class TestSharder(BaseTestSharder): 184 class TestSharder(BaseTestSharder):
189 """Responsible for sharding the tests on the connected devices.""" 185 """Responsible for sharding the tests on the connected devices."""
190 186
191 def __init__(self, attached_devices, test_suite, gtest_filter, 187 def __init__(self, attached_devices, test_suite, gtest_filter,
192 test_arguments, timeout, rebaseline, performance_test, 188 test_arguments, timeout, performance_test,
193 cleanup_test_files, tool, log_dump_name, fast_and_loose, 189 cleanup_test_files, tool, log_dump_name, fast_and_loose,
194 build_type, in_webkit_checkout): 190 build_type, in_webkit_checkout):
195 BaseTestSharder.__init__(self, attached_devices, build_type) 191 BaseTestSharder.__init__(self, attached_devices, build_type)
196 self.test_suite = test_suite 192 self.test_suite = test_suite
197 self.test_suite_basename = os.path.basename(test_suite) 193 self.test_suite_basename = os.path.basename(test_suite)
198 self.gtest_filter = gtest_filter or '' 194 self.gtest_filter = gtest_filter or ''
199 self.test_arguments = test_arguments 195 self.test_arguments = test_arguments
200 self.timeout = timeout 196 self.timeout = timeout
201 self.rebaseline = rebaseline
202 self.performance_test = performance_test 197 self.performance_test = performance_test
203 self.cleanup_test_files = cleanup_test_files 198 self.cleanup_test_files = cleanup_test_files
204 self.tool = tool 199 self.tool = tool
205 self.log_dump_name = log_dump_name 200 self.log_dump_name = log_dump_name
206 self.fast_and_loose = fast_and_loose 201 self.fast_and_loose = fast_and_loose
207 self.build_type = build_type
208 self.in_webkit_checkout = in_webkit_checkout 202 self.in_webkit_checkout = in_webkit_checkout
209 self.tests = [] 203 self.all_tests = []
210 if not self.gtest_filter: 204 if not self.gtest_filter:
211 # No filter has been specified, let's add all tests then. 205 # No filter has been specified, let's add all tests then.
212 self.tests, self.attached_devices = self._GetTests() 206 self.all_tests = self._GetAllEnabledTests()
207 self.tests = self.all_tests
213 208
214 def _GetTests(self): 209 def _GetAllEnabledTests(self):
215 """Returns a tuple of (all_tests, available_devices). 210 """Returns a list of all enabled tests.
216 211
217 Tries to obtain the list of available tests. 212 Obtains a list of enabled tests from the test package on the device,
213 then filters it again using the diabled list on the host.
bulach 2012/12/13 14:55:21 I dislike this combination :) the while + try is t
frankf 2012/12/13 19:54:04 Done. On 2012/12/13 14:55:21, bulach wrote:
214
218 Raises Exception if all devices failed. 215 Raises Exception if all devices failed.
219 """ 216 """
220 available_devices = list(self.attached_devices) 217 available_devices = list(self.attached_devices)
221 while available_devices: 218 while available_devices:
222 try: 219 try:
223 logging.info('Obtaining tests from %s', available_devices[-1]) 220 current_device = available_devices[-1]
224 all_tests = self._GetTestsFromDevice(available_devices[-1]) 221 logging.info('Obtaining tests from %s', current_device)
225 return all_tests, available_devices 222 test_runner = SingleTestRunner(
223 current_device,
224 self.test_suite,
225 self.gtest_filter,
226 self.test_arguments,
227 self.timeout,
228 self.performance_test,
229 self.cleanup_test_files,
230 self.tool,
231 0,
232 not not self.log_dump_name,
Yaron 2012/12/13 00:04:34 cute
233 self.fast_and_loose,
234 self.build_type,
235 self.in_webkit_checkout)
236 # The executable/apk needs to be copied before we can call GetAllTests.
237 test_runner.test_package.StripAndCopyExecutable()
238 all_tests = test_runner.test_package.GetAllTests()
239 disabled_list = test_runner.GetDisabledTests()
240 # Only includes tests that do not have any match in the disabled list.
241 all_tests = filter(lambda t:
242 not any([fnmatch.fnmatch(t, disabled_pattern)
243 for disabled_pattern in disabled_list]),
244 all_tests)
245 return all_tests
226 except Exception as e: 246 except Exception as e:
227 logging.info('Failed obtaining tests from %s %s', 247 logging.warning('Failed obtaining tests from %s %s',
228 available_devices[-1], e) 248 current_device, e)
229 available_devices.pop() 249 available_devices.pop()
250
230 raise Exception('No device available to get the list of tests.') 251 raise Exception('No device available to get the list of tests.')
231 252
232 def _GetTestsFromDevice(self, device):
233 test = SingleTestRunner(device, self.test_suite, self.gtest_filter,
234 self.test_arguments, self.timeout, self.rebaseline,
235 self.performance_test, self.cleanup_test_files,
236 self.tool, 0,
237 not not self.log_dump_name, self.fast_and_loose,
238 self.build_type, self.in_webkit_checkout)
239 # The executable/apk needs to be copied before we can call GetAllTests.
240 test.test_package.StripAndCopyExecutable()
241 all_tests = test.test_package.GetAllTests()
242 if not self.rebaseline:
243 disabled_list = test.GetDisabledTests()
244 # Only includes tests that do not have any match in the disabled list.
245 all_tests = filter(lambda t:
246 not any([fnmatch.fnmatch(t, disabled_pattern)
247 for disabled_pattern in disabled_list]),
248 all_tests)
249 return all_tests
250
251 def CreateShardedTestRunner(self, device, index): 253 def CreateShardedTestRunner(self, device, index):
252 """Creates a suite-specific test runner. 254 """Creates a suite-specific test runner.
253 255
254 Args: 256 Args:
255 device: Device serial where this shard will run. 257 device: Device serial where this shard will run.
256 index: Index of this device in the pool. 258 index: Index of this device in the pool.
257 259
258 Returns: 260 Returns:
259 A SingleTestRunner object. 261 A SingleTestRunner object.
260 """ 262 """
261 device_num = len(self.attached_devices) 263 device_num = len(self.attached_devices)
262 shard_size = (len(self.tests) + device_num - 1) / device_num 264 shard_size = (len(self.tests) + device_num - 1) / device_num
263 shard_test_list = self.tests[index * shard_size : (index + 1) * shard_size] 265 shard_test_list = self.tests[index * shard_size : (index + 1) * shard_size]
264 test_filter = ':'.join(shard_test_list) + self.gtest_filter 266 test_filter = ':'.join(shard_test_list) + self.gtest_filter
265 return SingleTestRunner(device, self.test_suite, 267 return SingleTestRunner(
266 test_filter, self.test_arguments, self.timeout, 268 device,
267 self.rebaseline, self.performance_test, 269 self.test_suite,
268 self.cleanup_test_files, self.tool, index, 270 test_filter,
269 not not self.log_dump_name, self.fast_and_loose, 271 self.test_arguments,
270 self.build_type, self.in_webkit_checkout) 272 self.timeout,
273 self.performance_test,
274 self.cleanup_test_files, self.tool, index,
275 not not self.log_dump_name,
276 self.fast_and_loose,
277 self.build_type,
278 self.in_webkit_checkout)
271 279
272 def OnTestsCompleted(self, test_runners, test_results): 280 def OnTestsCompleted(self, test_runners, test_results):
273 """Notifies that we completed the tests.""" 281 """Notifies that we completed the tests."""
274 test_results.LogFull('Unit test', os.path.basename(self.test_suite), 282 test_results.LogFull('Unit test', os.path.basename(self.test_suite),
275 self.build_type, self.tests) 283 self.build_type, self.all_tests)
276 test_results.PrintAnnotation() 284 test_results.PrintAnnotation()
277 if test_results.failed and self.rebaseline:
278 test_runners[0].UpdateFilter(test_results.failed)
279 if self.log_dump_name: 285 if self.log_dump_name:
280 # Zip all debug info outputs into a file named by log_dump_name. 286 # Zip all debug info outputs into a file named by log_dump_name.
281 debug_info.GTestDebugInfo.ZipAndCleanResults( 287 debug_info.GTestDebugInfo.ZipAndCleanResults(
282 os.path.join(cmd_helper.OutDirectory.get(), self.build_type, 288 os.path.join(
289 cmd_helper.OutDirectory.get(), self.build_type,
283 'debug_info_dumps'), 290 'debug_info_dumps'),
284 self.log_dump_name) 291 self.log_dump_name)
285 292
286 293
287 def _RunATestSuite(options): 294 def _RunATestSuite(options):
288 """Run a single test suite. 295 """Run a single test suite.
289 296
290 Helper for Dispatch() to allow stop/restart of the emulator across 297 Helper for Dispatch() to allow stop/restart of the emulator across
291 test bundles. If using the emulator, we start it on entry and stop 298 test bundles. If using the emulator, we start it on entry and stop
292 it on exit. 299 it on exit.
293 300
294 Args: 301 Args:
295 options: options for running the tests. 302 options: options for running the tests.
296 303
297 Returns: 304 Returns:
298 0 if successful, number of failing tests otherwise. 305 0 if successful, number of failing tests otherwise.
299 """ 306 """
300 step_name = os.path.basename(options.test_suite).replace('-debug.apk', '') 307 step_name = os.path.basename(options.test_suite).replace('-debug.apk', '')
301 buildbot_report.PrintNamedStep(step_name) 308 buildbot_report.PrintNamedStep(step_name)
302 attached_devices = [] 309 attached_devices = []
303 buildbot_emulators = [] 310 buildbot_emulators = []
304 311
305 if options.use_emulator: 312 if options.use_emulator:
306 for n in range(options.emulator_count): 313 for n in range(options.emulator_count):
307 t = TimeProfile('Emulator launch %d' % n) 314 t = TimeProfile('Emulator launch %d' % n)
308 avd_name = None 315 avd_name = None
309 if n > 0: 316 if n > 0:
310 # Creates a temporary AVD for the extra emulators. 317 # Creates a temporary AVD for the extra emulators.
311 avd_name = 'run_tests_avd_%d' % n 318 avd_name = 'run_tests_avd_%d' % n
312 buildbot_emulator = emulator.Emulator(avd_name, options.fast_and_loose) 319 buildbot_emulator = emulator.Emulator(avd_name, options.fast_and_loose)
313 buildbot_emulator.Launch(kill_all_emulators=n == 0) 320 buildbot_emulator.Launch(kill_all_emulators=n == 0)
314 t.Stop() 321 t.Stop()
315 buildbot_emulators.append(buildbot_emulator) 322 buildbot_emulators.append(buildbot_emulator)
316 attached_devices.append(buildbot_emulator.device) 323 attached_devices.append(buildbot_emulator.device)
317 # Wait for all emulators to boot completed. 324 # Wait for all emulators to boot completed.
318 map(lambda buildbot_emulator: buildbot_emulator.ConfirmLaunch(True), 325 map(lambda buildbot_emulator: buildbot_emulator.ConfirmLaunch(True),
319 buildbot_emulators) 326 buildbot_emulators)
320 elif options.test_device: 327 elif options.test_device:
321 attached_devices = [options.test_device] 328 attached_devices = [options.test_device]
322 else: 329 else:
323 attached_devices = android_commands.GetAttachedDevices() 330 attached_devices = android_commands.GetAttachedDevices()
324 331
325 if not attached_devices: 332 if not attached_devices:
326 logging.critical('A device must be attached and online.') 333 logging.critical('A device must be attached and online.')
327 buildbot_report.PrintError() 334 buildbot_report.PrintError()
328 return 1 335 return 1
329 336
330 # Reset the test port allocation. It's important to do it before starting 337 # Reset the test port allocation. It's important to do it before starting
331 # to dispatch any tests. 338 # to dispatch any tests.
332 if not ports.ResetTestServerPortAllocation(): 339 if not ports.ResetTestServerPortAllocation():
333 raise Exception('Failed to reset test server port.') 340 raise Exception('Failed to reset test server port.')
334 341
335 if options.performance_test or options.gtest_filter: 342 if options.performance_test or options.gtest_filter:
336 # These configuration can't be split in multiple devices. 343 logging.warning('Sharding is not possible with these configurations.')
337 attached_devices = [attached_devices[0]] 344 attached_devices = [attached_devices[0]]
338 sharder = TestSharder(attached_devices, options.test_suite, 345
339 options.gtest_filter, options.test_arguments, 346 sharder = TestSharder(
340 options.timeout, options.rebaseline, 347 attached_devices,
341 options.performance_test, 348 options.test_suite,
342 options.cleanup_test_files, options.tool, 349 options.gtest_filter,
343 options.log_dump, options.fast_and_loose, 350 options.test_arguments,
344 options.build_type, options.webkit) 351 options.timeout,
352 options.performance_test,
353 options.cleanup_test_files,
354 options.tool,
355 options.log_dump,
356 options.fast_and_loose,
357 options.build_type,
358 options.webkit)
345 test_results = sharder.RunShardedTests() 359 test_results = sharder.RunShardedTests()
346 360
347 for buildbot_emulator in buildbot_emulators: 361 for buildbot_emulator in buildbot_emulators:
348 buildbot_emulator.Shutdown() 362 buildbot_emulator.Shutdown()
349 363
350 return len(test_results.failed) 364 return len(test_results.failed)
351 365
352 366
353 def Dispatch(options): 367 def Dispatch(options):
354 """Dispatches the tests, sharding if possible. 368 """Dispatches the tests, sharding if possible.
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
395 option_parser = optparse.OptionParser() 409 option_parser = optparse.OptionParser()
396 test_options_parser.AddTestRunnerOptions(option_parser, default_timeout=0) 410 test_options_parser.AddTestRunnerOptions(option_parser, default_timeout=0)
397 option_parser.add_option('-s', '--suite', dest='test_suite', 411 option_parser.add_option('-s', '--suite', dest='test_suite',
398 help='Executable name of the test suite to run ' 412 help='Executable name of the test suite to run '
399 '(use -s help to list them)') 413 '(use -s help to list them)')
400 option_parser.add_option('--out-directory', dest='out_directory', 414 option_parser.add_option('--out-directory', dest='out_directory',
401 help='Path to the out/ directory, irrespective of ' 415 help='Path to the out/ directory, irrespective of '
402 'the build type. Only for non-Chromium uses.') 416 'the build type. Only for non-Chromium uses.')
403 option_parser.add_option('-d', '--device', dest='test_device', 417 option_parser.add_option('-d', '--device', dest='test_device',
404 help='Target device the test suite to run ') 418 help='Target device the test suite to run ')
405 option_parser.add_option('-r', dest='rebaseline',
406 help='Rebaseline and update *testsuite_disabled',
407 action='store_true')
408 option_parser.add_option('-f', '--gtest_filter', dest='gtest_filter', 419 option_parser.add_option('-f', '--gtest_filter', dest='gtest_filter',
409 help='gtest filter') 420 help='gtest filter')
410 option_parser.add_option('-a', '--test_arguments', dest='test_arguments', 421 option_parser.add_option('-a', '--test_arguments', dest='test_arguments',
411 help='Additional arguments to pass to the test') 422 help='Additional arguments to pass to the test')
412 option_parser.add_option('-p', dest='performance_test', 423 option_parser.add_option('-p', dest='performance_test',
frankf 2012/12/12 22:46:06 @bulach: What's the history behind this option. It
bulach 2012/12/13 14:55:21 I tried some archeology in the other trees, but no
413 help='Indicator of performance test', 424 help='Indicator of performance test',
414 action='store_true') 425 action='store_true')
415 option_parser.add_option('-L', dest='log_dump', 426 option_parser.add_option('-L', dest='log_dump',
416 help='file name of log dump, which will be put in ' 427 help='file name of log dump, which will be put in '
417 'subfolder debug_info_dumps under the same ' 428 'subfolder debug_info_dumps under the same '
418 'directory in where the test_suite exists.') 429 'directory in where the test_suite exists.')
419 option_parser.add_option('-e', '--emulator', dest='use_emulator', 430 option_parser.add_option('-e', '--emulator', dest='use_emulator',
420 action='store_true', 431 action='store_true',
421 help='Run tests in a new instance of emulator') 432 help='Run tests in a new instance of emulator')
422 option_parser.add_option('-n', '--emulator_count', 433 option_parser.add_option('-n', '--emulator_count',
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
464 # the batch (this happens because the exit status is a sum of all failures 475 # the batch (this happens because the exit status is a sum of all failures
465 # from all suites, but the buildbot associates the exit status only with the 476 # from all suites, but the buildbot associates the exit status only with the
466 # most recent step). 477 # most recent step).
467 if options.exit_code: 478 if options.exit_code:
468 return failed_tests_count 479 return failed_tests_count
469 return 0 480 return 0
470 481
471 482
472 if __name__ == '__main__': 483 if __name__ == '__main__':
473 sys.exit(main(sys.argv)) 484 sys.exit(main(sys.argv))
OLDNEW
« no previous file with comments | « build/android/pylib/test_package_executable.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698