blob: 433b2bdd5f81c748e3497f34f25e25487ffdb2b1 [file] [log] [blame]
David Ghandehari9e5b5872016-07-28 09:50:04 -07001#!/usr/bin/env python
2# Copyright (c) 2012 The Chromium Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Runs the Monkey tests on one or more devices."""
7import logging
8import optparse
9import random
10import sys
11import time
12
13from pylib import android_commands
14from pylib import python_test_base
15from pylib import python_test_sharder
16from pylib import test_options_parser
17from pylib import test_result
18
19
20class MonkeyTest(python_test_base.PythonTestBase):
21 def testMonkey(self):
22 start_ms = int(time.time()) * 1000
23
24 # Launch and wait for Chrome to launch.
25 self.adb.StartActivity(self.options.package_name,
26 self.options.activity_name,
27 wait_for_completion=True,
28 action='android.intent.action.MAIN',
29 force_stop=True)
30
31 # Chrome crashes are not always caught by Monkey test runner.
32 # Verify Chrome has the same PID before and after the test.
33 before_pids = self.adb.ExtractPid(self.options.package_name)
34
35 # Run the test.
36 output = ''
37 duration_ms = 0
38 if before_pids:
39 output = '\n'.join(self._LaunchMonkeyTest())
40 duration_ms = int(time.time()) * 1000 - start_ms
41 after_pids = self.adb.ExtractPid(self.options.package_name)
42
43 crashed = (not before_pids or not after_pids
44 or after_pids[0] != before_pids[0])
45 result = test_result.SingleTestResult(self.qualified_name, start_ms,
46 duration_ms, log=output)
47 results = test_result.TestResults()
48
49 if 'Monkey finished' in output and not crashed:
50 results.ok = [result]
51 else:
52 results.crashed = [result]
53
54 return results
55
56 def _LaunchMonkeyTest(self):
57 """Runs monkey test for a given package.
58
59 Looks at the following parameters in the options object provided
60 in class initializer:
61 package_name: Allowed package.
62 category: A list of allowed categories.
63 throttle: Delay between events (ms).
64 seed: Seed value for pseduo-random generator. Same seed value
65 generates the same sequence of events. Seed is randomized by
66 default.
67 event_count: Number of events to generate.
68 verbosity: Verbosity level [0-3].
69 extra_args: A string of other args to pass to the command verbatim.
70 """
71
72 category = self.options.category or []
73 seed = self.options.seed or random.randint(1, 100)
74 throttle = self.options.throttle or 100
75 event_count = self.options.event_count or 10000
76 verbosity = self.options.verbosity or 1
77 extra_args = self.options.extra_args or ''
78
79 timeout_ms = event_count * throttle * 1.5
80
81 cmd = ['monkey',
82 '-p %s' % self.options.package_name,
83 ' '.join(['-c %s' % c for c in category]),
84 '--throttle %d' % throttle,
85 '-s %d' % seed,
86 '-v ' * verbosity,
87 '--monitor-native-crashes',
88 '--kill-process-after-error',
89 extra_args,
90 '%d' % event_count]
91 return self.adb.RunShellCommand(' '.join(cmd), timeout_time=timeout_ms)
92
93
94def DispatchPythonTests(options):
95 """Dispatches the Monkey tests, sharding it if there multiple devices."""
96 logger = logging.getLogger()
97 logger.setLevel(logging.DEBUG)
98
99 available_tests = [MonkeyTest('testMonkey')]
100 attached_devices = android_commands.GetAttachedDevices()
101 if not attached_devices:
102 raise Exception('You have no devices attached or visible!')
103
104 # Actually run the tests.
105 logging.debug('Running monkey tests.')
106 available_tests *= len(attached_devices)
107 options.ensure_value('shard_retries', 1)
108 sharder = python_test_sharder.PythonTestSharder(
109 attached_devices, available_tests, options)
110 result = sharder.RunShardedTests()
111 result.LogFull('Monkey', 'Monkey', options.build_type, available_tests)
112 result.PrintAnnotation()
113
114
115def main():
116 desc = 'Run the Monkey tests on 1 or more devices.'
117 parser = optparse.OptionParser(description=desc)
118 test_options_parser.AddBuildTypeOption(parser)
119 parser.add_option('--package-name', help='Allowed package.')
120 parser.add_option('--activity-name',
121 default='com.google.android.apps.chrome.Main',
122 help='Name of the activity to start [default: %default].')
123 parser.add_option('--category',
124 help='A list of allowed categories [default: ""].')
125 parser.add_option('--throttle', default=100, type='int',
126 help='Delay between events (ms) [default: %default]. ')
127 parser.add_option('--seed', type='int',
128 help=('Seed value for pseduo-random generator. Same seed '
129 'value generates the same sequence of events. Seed '
130 'is randomized by default.'))
131 parser.add_option('--event-count', default=10000, type='int',
132 help='Number of events to generate [default: %default].')
133 parser.add_option('--verbosity', default=1, type='int',
134 help='Verbosity level [0-3] [default: %default].')
135 parser.add_option('--extra-args', default='',
136 help=('String of other args to pass to the command verbatim'
137 ' [default: "%default"].'))
138 (options, args) = parser.parse_args()
139
140 if args:
141 parser.print_help(sys.stderr)
142 parser.error('Unknown arguments: %s' % args)
143
144 if not options.package_name:
145 parser.print_help(sys.stderr)
146 parser.error('Missing package name')
147
148 if options.category:
149 options.category = options.category.split(',')
150
151 DispatchPythonTests(options)
152
153
154if __name__ == '__main__':
155 main()