1 # Copyright 2013 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
5 """Runs a monkey test on a single device."""
10 from devil
.android
import device_errors
11 from devil
.android
.sdk
import intent
12 from pylib
import constants
13 from pylib
.base
import base_test_result
14 from pylib
.base
import base_test_runner
16 _CHROME_PACKAGE
= constants
.PACKAGE_INFO
['chrome'].package
18 class TestRunner(base_test_runner
.BaseTestRunner
):
19 """A TestRunner instance runs a monkey test on a single device."""
21 def __init__(self
, test_options
, device
, _
):
22 super(TestRunner
, self
).__init
__(device
, None)
23 self
._options
= test_options
24 self
._package
= constants
.PACKAGE_INFO
[self
._options
.package
].package
25 self
._activity
= constants
.PACKAGE_INFO
[self
._options
.package
].activity
27 def _LaunchMonkeyTest(self
):
28 """Runs monkey test for a given package.
31 Output from the monkey command on the device.
34 timeout_ms
= self
._options
.event_count
* self
._options
.throttle
* 1.5
37 '-p %s' % self
._package
,
38 ' '.join(['-c %s' % c
for c
in self
._options
.category
]),
39 '--throttle %d' % self
._options
.throttle
,
40 '-s %d' % (self
._options
.seed
or random
.randint(1, 100)),
41 '-v ' * self
._options
.verbose_count
,
42 '--monitor-native-crashes',
43 '--kill-process-after-error',
44 self
._options
.extra_args
,
45 '%d' % self
._options
.event_count
]
46 return self
.device
.RunShellCommand(' '.join(cmd
), timeout
=timeout_ms
)
48 def RunTest(self
, test_name
):
49 """Run a Monkey test on the device.
52 test_name: String to use for logging the test result.
55 A tuple of (TestRunResults, retry).
57 self
.device
.StartActivity(
58 intent
.Intent(package
=self
._package
, activity
=self
._activity
,
59 action
='android.intent.action.MAIN'),
60 blocking
=True, force_stop
=True)
62 # Chrome crashes are not always caught by Monkey test runner.
63 # Verify Chrome has the same PID before and after the test.
64 before_pids
= self
.device
.GetPids(self
._package
)
69 if len(before_pids
.get(self
._package
, [])) > 1:
71 'At most one instance of process %s expected but found pids: '
72 '%s' % (self
._package
, before_pids
))
73 output
= '\n'.join(self
._LaunchMonkeyTest
())
74 after_pids
= self
.device
.GetPids(self
._package
)
77 if not self
._package
in before_pids
:
78 logging
.error('Failed to start the process.')
79 elif not self
._package
in after_pids
:
80 logging
.error('Process %s has died.', before_pids
[self
._package
])
81 elif before_pids
[self
._package
] != after_pids
[self
._package
]:
82 logging
.error('Detected process restart %s -> %s',
83 before_pids
[self
._package
], after_pids
[self
._package
])
87 results
= base_test_result
.TestRunResults()
88 success_pattern
= 'Events injected: %d' % self
._options
.event_count
89 if success_pattern
in output
and not crashed
:
90 result
= base_test_result
.BaseTestResult(
91 test_name
, base_test_result
.ResultType
.PASS
, log
=output
)
93 result
= base_test_result
.BaseTestResult(
94 test_name
, base_test_result
.ResultType
.FAIL
, log
=output
)
95 if 'chrome' in self
._options
.package
:
96 logging
.warning('Starting MinidumpUploadService...')
97 # TODO(jbudorick): Update this after upstreaming.
98 minidump_intent
= intent
.Intent(
99 action
='%s.crash.ACTION_FIND_ALL' % _CHROME_PACKAGE
,
100 package
=self
._package
,
101 activity
='%s.crash.MinidumpUploadService' % _CHROME_PACKAGE
)
103 self
.device
.RunShellCommand(
104 ['am', 'startservice'] + minidump_intent
.am_args
,
105 as_root
=True, check_return
=True)
106 except device_errors
.CommandFailedError
:
107 logging
.exception('Failed to start MinidumpUploadService')
109 results
.AddResult(result
)
110 return results
, False