diff options
author | frankf@google.com <frankf@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-29 23:46:21 +0000 |
---|---|---|
committer | frankf@google.com <frankf@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-29 23:46:21 +0000 |
commit | 118cfe57fe9e79b863f53be8500229adaf329334 (patch) | |
tree | 4a7f3faf3a61def030e9aca1bdb39adff0138d13 | |
parent | 2972876692c7a645670a844aeff7427643e95ef5 (diff) | |
download | chromium_src-118cfe57fe9e79b863f53be8500229adaf329334.zip chromium_src-118cfe57fe9e79b863f53be8500229adaf329334.tar.gz chromium_src-118cfe57fe9e79b863f53be8500229adaf329334.tar.bz2 |
Add a test runner/sharder for Monkey stress tests.
BUG=145039
Review URL: https://chromiumcodereview.appspot.com/10894021
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@154006 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | build/android/pylib/android_commands.py | 4 | ||||
-rw-r--r-- | build/android/pylib/test_result.py | 10 | ||||
-rwxr-xr-x | build/android/run_monkey_test.py | 127 | ||||
-rwxr-xr-x | build/android/run_tests.py | 11 |
4 files changed, 141 insertions, 11 deletions
diff --git a/build/android/pylib/android_commands.py b/build/android/pylib/android_commands.py index e665a65..127c2fa 100644 --- a/build/android/pylib/android_commands.py +++ b/build/android/pylib/android_commands.py @@ -1021,7 +1021,9 @@ class AndroidCommands(object): '--throttle %d' % throttle, '-s %d' % seed, '-v ' * verbosity, + '--monitor-native-crashes', + '--kill-process-after-error', extra_args, - '%s' % event_count] + '%d' % event_count] return self.RunShellCommand(' '.join(cmd), timeout_time=event_count*throttle*1.5) diff --git a/build/android/pylib/test_result.py b/build/android/pylib/test_result.py index 6c2fad0..043cb48 100644 --- a/build/android/pylib/test_result.py +++ b/build/android/pylib/test_result.py @@ -9,6 +9,7 @@ import os import time import traceback +import buildbot_report import constants @@ -193,3 +194,12 @@ class TestResults(object): [t.name for t in self.unknown]) logging.critical(summary_string) return summary_string + + def PrintAnnotation(self): + """Print buildbot annotations for test results.""" + if self.timed_out: + buildbot_report.PrintWarning() + elif self.failed or self.crashed or self.overall_fail: + buildbot_report.PrintError() + else: + print 'Step success!' # No annotation needed diff --git a/build/android/run_monkey_test.py b/build/android/run_monkey_test.py new file mode 100755 index 0000000..3a89796 --- /dev/null +++ b/build/android/run_monkey_test.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python +# Copyright (c) 2012 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Runs the Monkey tests on one or more devices.""" +import logging +import optparse +import time + +from pylib import android_commands +from pylib import python_test_base +from pylib import python_test_caller +from pylib import python_test_sharder +from pylib import test_options_parser +from pylib import test_result + + +class MonkeyTest(python_test_base.PythonTestBase): + def __init__(self, test_name, options): + self.options = options + super(MonkeyTest, self).__init__(test_name) + + def testMonkey(self): + start_ms = int(time.time()) * 1000 + + # Launch and wait for Chrome to launch. + self.adb.StartActivity(self.options['package_name'], + self.options.pop('activity_name'), + wait_for_completion=True, + action='android.intent.action.MAIN') + + # Chrome crashes are not always caught by Monkey test runner. + # Verify Chrome has the same PID before and after the test. + before_pids = self.adb.ExtractPid(self.options['package_name']) + + # Run the test. + output = '' + duration_ms = 0 + if before_pids: + output = '\n'.join(self.adb.RunMonkey(**self.options)) + duration_ms = int(time.time()) * 1000 - start_ms + after_pids = self.adb.ExtractPid(self.options['package_name']) + + crashed = (not before_pids or not after_pids + or after_pids[0] != before_pids[0]) + result = test_result.SingleTestResult(self.qualified_name, start_ms, + duration_ms, test_result.PYTHON, + log=output) + results = test_result.TestResults() + + if 'Monkey finished' in output and not crashed: + results.ok = [result] + else: + results.crashed = [result] + + return results + + +def DispatchPythonTests(options): + """Dispatches the Monkey tests, sharding it if there multiple devices.""" + logger = logging.getLogger() + logger.setLevel(logging.DEBUG) + + build_type = options.pop('build_type') + available_tests = [MonkeyTest('testMonkey', options)] + attached_devices = android_commands.GetAttachedDevices() + if not attached_devices: + raise Exception('You have no devices attached or visible!') + + # Actually run the tests. + # TODO(frankf): Test sharder should really be handling the case + # where only 1 device is attached. + if len(attached_devices) > 1: + logging.debug('Sharding Python tests.') + available_tests *= len(attached_devices) + sharder = python_test_sharder.PythonTestSharder( + attached_devices, 1, available_tests) + result = sharder.RunShardedTests() + else: + logging.debug('Running Python tests serially.') + result = python_test_caller.CallPythonTest(available_tests[0], + attached_devices[0], 0) + result.LogFull('Monkey', 'Monkey', build_type) + result.PrintAnnotation() + + +def main(): + desc = 'Run the Monkey tests on 1 or more devices.' + parser = optparse.OptionParser(description=desc) + test_options_parser.AddBuildTypeOption(parser) + parser.add_option('--package-name', + help='Allowed package.') + parser.add_option('--activity-name', + default='com.google.android.apps.chrome.Main', + help='Name of the activity to start [default: %default].') + parser.add_option('--category', + help='A list of allowed categories [default: ""].') + parser.add_option('--throttle', default=100, type='int', + help='Delay between events (ms) [default: %default]. ') + parser.add_option('--seed', type='int', + help='Seed value for pseduo-random generator. Same seed' + ' value generates the same sequence of events. Seed is' + ' randomized by default.') + parser.add_option('--event-count', default=10000, type='int', + help='Number of events to generate [default: %default].') + parser.add_option('--verbosity', default=1, type='int', + help='Verbosity level [0-3] [default: %default].') + parser.add_option('--extra-args', default='', + help='String of other args to pass to the command verbatim' + ' [default: "%default"].') + (options, args) = parser.parse_args() + + if args: + parser.error('Unknown arguments: %s' % args) + + if not options.package_name: + parser.error('Missing package name') + + if options.category: + options.category = options.category.split(',') + + DispatchPythonTests(vars(options)) + + +if __name__ == '__main__': + main() diff --git a/build/android/run_tests.py b/build/android/run_tests.py index ccd2230..afb5f0e 100755 --- a/build/android/run_tests.py +++ b/build/android/run_tests.py @@ -184,15 +184,6 @@ class Xvfb(object): self._pid = 0 -def PrintAnnotationForTestResults(test_results): - if test_results.timed_out: - buildbot_report.PrintWarning() - elif test_results.failed or test_results.crashed or test_results.overall_fail: - buildbot_report.PrintError() - else: - print 'Step success!' # No annotation needed - - class TestSharder(BaseTestSharder): """Responsible for sharding the tests on the connected devices.""" @@ -258,7 +249,7 @@ class TestSharder(BaseTestSharder): """Notifies that we completed the tests.""" test_results.LogFull('Unit test', os.path.basename(self.test_suite), self.build_type) - PrintAnnotationForTestResults(test_results) + test_results.PrintAnnotation() if test_results.failed and self.rebaseline: test_runners[0].UpdateFilter(test_results.failed) if self.log_dump_name: |