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

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

Issue 11312239: Modify the Android test running scripts so they can be used from WebKit (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 1 month 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 # 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)
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
55 import optparse 55 import optparse
56 import os 56 import os
57 import signal 57 import signal
58 import subprocess 58 import subprocess
59 import sys 59 import sys
60 import time 60 import time
61 61
62 from pylib import android_commands 62 from pylib import android_commands
63 from pylib.base_test_sharder import BaseTestSharder 63 from pylib.base_test_sharder import BaseTestSharder
64 from pylib import buildbot_report 64 from pylib import buildbot_report
65 from pylib import cmd_helper
65 from pylib import constants 66 from pylib import constants
66 from pylib import debug_info 67 from pylib import debug_info
67 import emulator 68 import emulator
68 from pylib import ports 69 from pylib import ports
69 from pylib import run_tests_helper 70 from pylib import run_tests_helper
70 from pylib import test_options_parser 71 from pylib import test_options_parser
71 from pylib.single_test_runner import SingleTestRunner 72 from pylib.single_test_runner import SingleTestRunner
72 from pylib.test_result import BaseTestResult, TestResults 73 from pylib.test_result import BaseTestResult, TestResults
73 74
74 75
75 _TEST_SUITES = ['base_unittests', 76 _TEST_SUITES = ['base_unittests',
76 'cc_unittests', 77 'cc_unittests',
77 'content_unittests', 78 'content_unittests',
78 'gpu_unittests', 79 'gpu_unittests',
79 'ipc_tests', 80 'ipc_tests',
80 'media_unittests', 81 'media_unittests',
81 'net_unittests', 82 'net_unittests',
82 'sql_unittests', 83 'sql_unittests',
83 'sync_unit_tests', 84 'sync_unit_tests',
84 'ui_unittests', 85 'ui_unittests',
85 'unit_tests', 86 'unit_tests',
86 'webkit_compositor_bindings_unittests', 87 'webkit_compositor_bindings_unittests',
87 ] 88 ]
88 89
89 90
90 def TestSuiteDir(build_type):
91 """Return the base directory of test suites."""
92 return os.path.abspath(os.path.join(constants.CHROME_DIR, 'out', build_type))
93
94 def FullyQualifiedTestSuites(exe, option_test_suite, build_type): 91 def FullyQualifiedTestSuites(exe, option_test_suite, build_type):
95 """Return a fully qualified list 92 """Return a fully qualified list
96 93
97 Args: 94 Args:
98 exe: if True, use the executable-based test runner. 95 exe: if True, use the executable-based test runner.
99 option_test_suite: the test_suite specified as an option. 96 option_test_suite: the test_suite specified as an option.
100 build_type: 'Release' or 'Debug'. 97 build_type: 'Release' or 'Debug'.
101 """ 98 """
102 test_suite_dir = TestSuiteDir(build_type) 99 test_suite_dir = os.path.join(cmd_helper.OutDirectory(), build_type)
103 if option_test_suite: 100 if option_test_suite:
104 all_test_suites = [option_test_suite] 101 all_test_suites = [option_test_suite]
105 else: 102 else:
106 all_test_suites = _TEST_SUITES 103 all_test_suites = _TEST_SUITES
107 104
108 if exe: 105 if exe:
109 qualified_test_suites = [os.path.join(test_suite_dir, t) 106 qualified_test_suites = [os.path.join(test_suite_dir, t)
110 for t in all_test_suites] 107 for t in all_test_suites]
111 else: 108 else:
112 # out/(Debug|Release)/$SUITE_apk/$SUITE-debug.apk 109 # out/(Debug|Release)/$SUITE_apk/$SUITE-debug.apk
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
188 del os.environ['DISPLAY'] 185 del os.environ['DISPLAY']
189 self._pid = 0 186 self._pid = 0
190 187
191 188
192 class TestSharder(BaseTestSharder): 189 class TestSharder(BaseTestSharder):
193 """Responsible for sharding the tests on the connected devices.""" 190 """Responsible for sharding the tests on the connected devices."""
194 191
195 def __init__(self, attached_devices, test_suite, gtest_filter, 192 def __init__(self, attached_devices, test_suite, gtest_filter,
196 test_arguments, timeout, rebaseline, performance_test, 193 test_arguments, timeout, rebaseline, performance_test,
197 cleanup_test_files, tool, log_dump_name, fast_and_loose, 194 cleanup_test_files, tool, log_dump_name, fast_and_loose,
198 build_type): 195 build_type, in_webkit_checkout):
199 BaseTestSharder.__init__(self, attached_devices, build_type) 196 BaseTestSharder.__init__(self, attached_devices, build_type)
200 self.test_suite = test_suite 197 self.test_suite = test_suite
201 self.test_suite_basename = os.path.basename(test_suite) 198 self.test_suite_basename = os.path.basename(test_suite)
202 self.gtest_filter = gtest_filter or '' 199 self.gtest_filter = gtest_filter or ''
203 self.test_arguments = test_arguments 200 self.test_arguments = test_arguments
204 self.timeout = timeout 201 self.timeout = timeout
205 self.rebaseline = rebaseline 202 self.rebaseline = rebaseline
206 self.performance_test = performance_test 203 self.performance_test = performance_test
207 self.cleanup_test_files = cleanup_test_files 204 self.cleanup_test_files = cleanup_test_files
208 self.tool = tool 205 self.tool = tool
209 self.log_dump_name = log_dump_name 206 self.log_dump_name = log_dump_name
210 self.fast_and_loose = fast_and_loose 207 self.fast_and_loose = fast_and_loose
211 self.build_type = build_type 208 self.build_type = build_type
209 self.in_webkit_checkout = in_webkit_checkout
212 self.tests = [] 210 self.tests = []
213 if not self.gtest_filter: 211 if not self.gtest_filter:
214 # No filter has been specified, let's add all tests then. 212 # No filter has been specified, let's add all tests then.
215 self.tests, self.attached_devices = self._GetTests() 213 self.tests, self.attached_devices = self._GetTests()
216 214
217 def _GetTests(self): 215 def _GetTests(self):
218 """Returns a tuple of (all_tests, available_devices). 216 """Returns a tuple of (all_tests, available_devices).
219 217
220 Tries to obtain the list of available tests. 218 Tries to obtain the list of available tests.
221 Raises Exception if all devices failed. 219 Raises Exception if all devices failed.
222 """ 220 """
223 available_devices = list(self.attached_devices) 221 available_devices = list(self.attached_devices)
224 while available_devices: 222 while available_devices:
225 try: 223 try:
226 logging.info('Obtaining tests from %s', available_devices[-1]) 224 logging.info('Obtaining tests from %s', available_devices[-1])
227 all_tests = self._GetTestsFromDevice(available_devices[-1]) 225 all_tests = self._GetTestsFromDevice(available_devices[-1])
228 return all_tests, available_devices 226 return all_tests, available_devices
229 except Exception as e: 227 except Exception as e:
230 logging.info('Failed obtaining tests from %s %s', 228 logging.info('Failed obtaining tests from %s %s',
231 available_devices[-1], e) 229 available_devices[-1], e)
232 available_devices.pop() 230 available_devices.pop()
233 raise Exception('No device available to get the list of tests.') 231 raise Exception('No device available to get the list of tests.')
234 232
235 def _GetTestsFromDevice(self, device): 233 def _GetTestsFromDevice(self, device):
236 test = SingleTestRunner(device, self.test_suite, self.gtest_filter, 234 test = SingleTestRunner(device, self.test_suite, self.gtest_filter,
237 self.test_arguments, self.timeout, self.rebaseline, 235 self.test_arguments, self.timeout, self.rebaseline,
238 self.performance_test, self.cleanup_test_files, 236 self.performance_test, self.cleanup_test_files,
239 self.tool, 0, 237 self.tool, 0,
240 not not self.log_dump_name, self.fast_and_loose, 238 not not self.log_dump_name, self.fast_and_loose,
241 self.build_type) 239 self.build_type, self.in_webkit_checkout)
242 # The executable/apk needs to be copied before we can call GetAllTests. 240 # The executable/apk needs to be copied before we can call GetAllTests.
243 test.test_package.StripAndCopyExecutable() 241 test.test_package.StripAndCopyExecutable()
244 all_tests = test.test_package.GetAllTests() 242 all_tests = test.test_package.GetAllTests()
245 if not self.rebaseline: 243 if not self.rebaseline:
246 disabled_list = test.GetDisabledTests() 244 disabled_list = test.GetDisabledTests()
247 # Only includes tests that do not have any match in the disabled list. 245 # Only includes tests that do not have any match in the disabled list.
248 all_tests = filter(lambda t: 246 all_tests = filter(lambda t:
249 not any([fnmatch.fnmatch(t, disabled_pattern) 247 not any([fnmatch.fnmatch(t, disabled_pattern)
250 for disabled_pattern in disabled_list]), 248 for disabled_pattern in disabled_list]),
251 all_tests) 249 all_tests)
(...skipping 11 matching lines...) Expand all
263 """ 261 """
264 device_num = len(self.attached_devices) 262 device_num = len(self.attached_devices)
265 shard_size = (len(self.tests) + device_num - 1) / device_num 263 shard_size = (len(self.tests) + device_num - 1) / device_num
266 shard_test_list = self.tests[index * shard_size : (index + 1) * shard_size] 264 shard_test_list = self.tests[index * shard_size : (index + 1) * shard_size]
267 test_filter = ':'.join(shard_test_list) + self.gtest_filter 265 test_filter = ':'.join(shard_test_list) + self.gtest_filter
268 return SingleTestRunner(device, self.test_suite, 266 return SingleTestRunner(device, self.test_suite,
269 test_filter, self.test_arguments, self.timeout, 267 test_filter, self.test_arguments, self.timeout,
270 self.rebaseline, self.performance_test, 268 self.rebaseline, self.performance_test,
271 self.cleanup_test_files, self.tool, index, 269 self.cleanup_test_files, self.tool, index,
272 not not self.log_dump_name, self.fast_and_loose, 270 not not self.log_dump_name, self.fast_and_loose,
273 self.build_type) 271 self.build_type, self.in_webkit_checkout)
274 272
275 def OnTestsCompleted(self, test_runners, test_results): 273 def OnTestsCompleted(self, test_runners, test_results):
276 """Notifies that we completed the tests.""" 274 """Notifies that we completed the tests."""
277 test_results.LogFull('Unit test', os.path.basename(self.test_suite), 275 test_results.LogFull('Unit test', os.path.basename(self.test_suite),
278 self.build_type, self.tests) 276 self.build_type, self.tests)
279 test_results.PrintAnnotation() 277 test_results.PrintAnnotation()
280 if test_results.failed and self.rebaseline: 278 if test_results.failed and self.rebaseline:
281 test_runners[0].UpdateFilter(test_results.failed) 279 test_runners[0].UpdateFilter(test_results.failed)
282 if self.log_dump_name: 280 if self.log_dump_name:
283 # Zip all debug info outputs into a file named by log_dump_name. 281 # Zip all debug info outputs into a file named by log_dump_name.
284 debug_info.GTestDebugInfo.ZipAndCleanResults( 282 debug_info.GTestDebugInfo.ZipAndCleanResults(
285 os.path.join(TestSuiteDir(self.build_type), 'debug_info_dumps'), 283 os.path.join(cmd_helper.OutDirectory(), self.build_type,
284 'debug_info_dumps'),
286 self.log_dump_name) 285 self.log_dump_name)
287 286
288 287
289 def _RunATestSuite(options): 288 def _RunATestSuite(options):
290 """Run a single test suite. 289 """Run a single test suite.
291 290
292 Helper for Dispatch() to allow stop/restart of the emulator across 291 Helper for Dispatch() to allow stop/restart of the emulator across
293 test bundles. If using the emulator, we start it on entry and stop 292 test bundles. If using the emulator, we start it on entry and stop
294 it on exit. 293 it on exit.
295 294
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
336 335
337 if options.performance_test or options.gtest_filter: 336 if options.performance_test or options.gtest_filter:
338 # These configuration can't be split in multiple devices. 337 # These configuration can't be split in multiple devices.
339 attached_devices = [attached_devices[0]] 338 attached_devices = [attached_devices[0]]
340 sharder = TestSharder(attached_devices, options.test_suite, 339 sharder = TestSharder(attached_devices, options.test_suite,
341 options.gtest_filter, options.test_arguments, 340 options.gtest_filter, options.test_arguments,
342 options.timeout, options.rebaseline, 341 options.timeout, options.rebaseline,
343 options.performance_test, 342 options.performance_test,
344 options.cleanup_test_files, options.tool, 343 options.cleanup_test_files, options.tool,
345 options.log_dump, options.fast_and_loose, 344 options.log_dump, options.fast_and_loose,
346 options.build_type) 345 options.build_type, options.webkit)
347 test_results = sharder.RunShardedTests() 346 test_results = sharder.RunShardedTests()
348 347
349 for buildbot_emulator in buildbot_emulators: 348 for buildbot_emulator in buildbot_emulators:
350 buildbot_emulator.Shutdown() 349 buildbot_emulator.Shutdown()
351 350
352 return len(test_results.failed) 351 return len(test_results.failed)
353 352
354 353
355 def Dispatch(options): 354 def Dispatch(options):
356 """Dispatches the tests, sharding if possible. 355 """Dispatches the tests, sharding if possible.
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
392 for test_suite in _TEST_SUITES: 391 for test_suite in _TEST_SUITES:
393 print test_suite 392 print test_suite
394 393
395 394
396 def main(argv): 395 def main(argv):
397 option_parser = optparse.OptionParser() 396 option_parser = optparse.OptionParser()
398 test_options_parser.AddTestRunnerOptions(option_parser, default_timeout=0) 397 test_options_parser.AddTestRunnerOptions(option_parser, default_timeout=0)
399 option_parser.add_option('-s', '--suite', dest='test_suite', 398 option_parser.add_option('-s', '--suite', dest='test_suite',
400 help='Executable name of the test suite to run ' 399 help='Executable name of the test suite to run '
401 '(use -s help to list them)') 400 '(use -s help to list them)')
401 option_parser.add_option('--out-directory', dest='out_directory',
402 help='Path to the out/ directory, ambiguous of the '
bulach 2012/11/15 01:06:39 s/ambiguous/irrespective/
Peter Beverloo 2012/11/15 12:11:29 Done.
403 'build type. Only necessary for non-Chromium uses.')
402 option_parser.add_option('-d', '--device', dest='test_device', 404 option_parser.add_option('-d', '--device', dest='test_device',
403 help='Target device the test suite to run ') 405 help='Target device the test suite to run ')
404 option_parser.add_option('-r', dest='rebaseline', 406 option_parser.add_option('-r', dest='rebaseline',
405 help='Rebaseline and update *testsuite_disabled', 407 help='Rebaseline and update *testsuite_disabled',
406 action='store_true') 408 action='store_true')
407 option_parser.add_option('-f', '--gtest_filter', dest='gtest_filter', 409 option_parser.add_option('-f', '--gtest_filter', dest='gtest_filter',
408 help='gtest filter') 410 help='gtest filter')
409 option_parser.add_option('-a', '--test_arguments', dest='test_arguments', 411 option_parser.add_option('-a', '--test_arguments', dest='test_arguments',
410 help='Additional arguments to pass to the test') 412 help='Additional arguments to pass to the test')
411 option_parser.add_option('-p', dest='performance_test', 413 option_parser.add_option('-p', dest='performance_test',
412 help='Indicator of performance test', 414 help='Indicator of performance test',
413 action='store_true') 415 action='store_true')
414 option_parser.add_option('-L', dest='log_dump', 416 option_parser.add_option('-L', dest='log_dump',
415 help='file name of log dump, which will be put in ' 417 help='file name of log dump, which will be put in '
416 'subfolder debug_info_dumps under the same ' 418 'subfolder debug_info_dumps under the same '
417 'directory in where the test_suite exists.') 419 'directory in where the test_suite exists.')
418 option_parser.add_option('-e', '--emulator', dest='use_emulator', 420 option_parser.add_option('-e', '--emulator', dest='use_emulator',
419 action='store_true', 421 action='store_true',
420 help='Run tests in a new instance of emulator') 422 help='Run tests in a new instance of emulator')
421 option_parser.add_option('-n', '--emulator_count', 423 option_parser.add_option('-n', '--emulator_count',
422 type='int', default=1, 424 type='int', default=1,
423 help='Number of emulators to launch for running the ' 425 help='Number of emulators to launch for running the '
424 'tests.') 426 'tests.')
425 option_parser.add_option('-x', '--xvfb', dest='use_xvfb', 427 option_parser.add_option('-x', '--xvfb', dest='use_xvfb',
426 action='store_true', 428 action='store_true',
427 help='Use Xvfb around tests (ignored if not Linux)') 429 help='Use Xvfb around tests (ignored if not Linux)')
430 option_parser.add_option('--webkit', action='store_true',
431 help='Run the tests from a WebKit checkout.')
428 option_parser.add_option('--fast', '--fast_and_loose', dest='fast_and_loose', 432 option_parser.add_option('--fast', '--fast_and_loose', dest='fast_and_loose',
429 action='store_true', 433 action='store_true',
430 help='Go faster (but be less stable), ' 434 help='Go faster (but be less stable), '
431 'for quick testing. Example: when tracking down ' 435 'for quick testing. Example: when tracking down '
432 'tests that hang to add to the disabled list, ' 436 'tests that hang to add to the disabled list, '
433 'there is no need to redeploy the test binary ' 437 'there is no need to redeploy the test binary '
434 'or data to the device again. ' 438 'or data to the device again. '
435 'Don\'t use on bots by default!') 439 'Don\'t use on bots by default!')
436 option_parser.add_option('--repeat', dest='repeat', type='int', 440 option_parser.add_option('--repeat', dest='repeat', type='int',
437 default=2, 441 default=2,
438 help='Repeat count on test timeout') 442 help='Repeat count on test timeout')
439 option_parser.add_option('--exit_code', action='store_true', 443 option_parser.add_option('--exit_code', action='store_true',
440 help='If set, the exit code will be total number ' 444 help='If set, the exit code will be total number '
441 'of failures.') 445 'of failures.')
442 option_parser.add_option('--exe', action='store_true', 446 option_parser.add_option('--exe', action='store_true',
443 help='If set, use the exe test runner instead of ' 447 help='If set, use the exe test runner instead of '
444 'the APK.') 448 'the APK.')
445 449
446 options, args = option_parser.parse_args(argv) 450 options, args = option_parser.parse_args(argv)
447 if len(args) > 1: 451 if len(args) > 1:
448 print 'Unknown argument:', args[1:] 452 print 'Unknown argument:', args[1:]
449 option_parser.print_usage() 453 option_parser.print_usage()
450 sys.exit(1) 454 sys.exit(1)
451 run_tests_helper.SetLogLevel(options.verbose_count) 455 run_tests_helper.SetLogLevel(options.verbose_count)
456 if options.out_directory:
bulach 2012/11/15 01:06:39 see above: I was thinking that the caller coud set
Peter Beverloo 2012/11/15 12:11:29 As replied earlier on: amended.
457 os.environ['ANDROID_TEST_OUT_DIRECTORY'] = options.out_directory
452 emulator.DeleteAllTempAVDs() 458 emulator.DeleteAllTempAVDs()
453 failed_tests_count = Dispatch(options) 459 failed_tests_count = Dispatch(options)
454 460
455 # Failures of individual test suites are communicated by printing a 461 # Failures of individual test suites are communicated by printing a
456 # STEP_FAILURE message. 462 # STEP_FAILURE message.
457 # Returning a success exit status also prevents the buildbot from incorrectly 463 # Returning a success exit status also prevents the buildbot from incorrectly
458 # marking the last suite as failed if there were failures in other suites in 464 # marking the last suite as failed if there were failures in other suites in
459 # the batch (this happens because the exit status is a sum of all failures 465 # the batch (this happens because the exit status is a sum of all failures
460 # from all suites, but the buildbot associates the exit status only with the 466 # from all suites, but the buildbot associates the exit status only with the
461 # most recent step). 467 # most recent step).
462 if options.exit_code: 468 if options.exit_code:
463 return failed_tests_count 469 return failed_tests_count
464 return 0 470 return 0
465 471
466 472
467 if __name__ == '__main__': 473 if __name__ == '__main__':
468 sys.exit(main(sys.argv)) 474 sys.exit(main(sys.argv))
OLDNEW
« build/android/pylib/single_test_runner.py ('K') | « build/android/pylib/single_test_runner.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698