1#!/usr/bin/env python
2# Copyright 2017 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
6import os
7import sys
8import unittest
9
10if __name__ == '__main__':
11  sys.path.append(
12      os.path.abspath(os.path.join(
13          os.path.dirname(__file__),
14          '..',
15          '..',
16      )))
17
18from devil.android import crash_handler
19from devil.android import device_errors
20from devil.android import device_utils
21from devil.android import device_temp_file
22from devil.android import device_test_case
23from devil.utils import cmd_helper
24from devil.utils import reraiser_thread
25from devil.utils import timeout_retry
26
27
28class DeviceCrashTest(device_test_case.DeviceTestCase):
29  def setUp(self):
30    super(DeviceCrashTest, self).setUp()
31    self.device = device_utils.DeviceUtils(self.serial)
32
33  def testCrashDuringCommand(self):
34    self.device.EnableRoot()
35    with device_temp_file.DeviceTempFile(self.device.adb) as trigger_file:
36
37      trigger_text = 'hello world'
38
39      def victim():
40        trigger_cmd = 'echo -n %s > %s; sleep 20' % (cmd_helper.SingleQuote(
41            trigger_text), cmd_helper.SingleQuote(trigger_file.name))
42        crash_handler.RetryOnSystemCrash(
43            lambda d: d.RunShellCommand(
44                trigger_cmd,
45                shell=True,
46                check_return=True,
47                retries=1,
48                as_root=True,
49                timeout=180),
50            device=self.device)
51        self.assertEquals(
52            trigger_text,
53            self.device.ReadFile(trigger_file.name, retries=0).strip())
54        return True
55
56      def crasher():
57        def ready_to_crash():
58          try:
59            return trigger_text == self.device.ReadFile(
60                trigger_file.name, retries=0).strip()
61          except device_errors.CommandFailedError:
62            return False
63
64        timeout_retry.WaitFor(ready_to_crash, wait_period=2, max_tries=10)
65        if not ready_to_crash():
66          return False
67        self.device.adb.Shell(
68            'echo c > /proc/sysrq-trigger',
69            expect_status=None,
70            timeout=60,
71            retries=0)
72        return True
73
74    self.assertEquals([True, True], reraiser_thread.RunAsync([crasher, victim]))
75
76
77if __name__ == '__main__':
78  device_test_case.PrepareDevices()
79  unittest.main()
80