summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorfrankf@google.com <frankf@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2012-08-29 23:46:21 +0000
committerfrankf@google.com <frankf@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2012-08-29 23:46:21 +0000
commit118cfe57fe9e79b863f53be8500229adaf329334 (patch)
tree4a7f3faf3a61def030e9aca1bdb39adff0138d13
parent2972876692c7a645670a844aeff7427643e95ef5 (diff)
downloadchromium_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.py4
-rw-r--r--build/android/pylib/test_result.py10
-rwxr-xr-xbuild/android/run_monkey_test.py127
-rwxr-xr-xbuild/android/run_tests.py11
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: