• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (c) 2013 The Chromium OS 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.
4
5import logging
6import time
7
8from autotest_lib.client.common_lib import error
9from autotest_lib.server import autotest, test
10from autotest_lib.server.cros import autoupdate_utils
11
12
13class platform_RebootAfterUpdate(test.test):
14    """Test that updates the machine, reboots, and logs in / logs out.
15
16    This test keeps a reboot timeout in order to keep the system boot times
17    regressing in performance. For example, if Chrome takes a long time to
18    shutdown / hangs, other tests have much longer timeouts (to prevent them
19    from being flaky) while this test targets these hangs. Note, this test only
20    has smaller timeouts for boot, not for login/logout. Also, these timeouts
21    are still fairly conservative and are only meant to catch large regressions
22    or hangs, not small regressions.
23
24    """
25    version = 1
26
27    _REBOOT_ERROR_MESSAGE = (
28            'System failed to restart within the timeout after '
29            '%(reason)s. This failure indicates that the system after '
30            'receiving a reboot request and restarting did not '
31            'reconnect via ssh within the timeout. Actual time %(actual)d '
32            'seconds vs expected time: %(expected)d seconds')
33
34    # Timeouts specific to this test. These should be as low as possible.
35
36    # Total amount of time to wait for a reboot to return.
37    _REBOOT_TIMEOUT = 120
38
39
40    @classmethod
41    def reboot_with_timeout(cls, host, reason):
42        """Reboots the device and checks to see if it completed within desired.
43
44        @param host: Autotest host object to reboot.
45        @param reason: string representing why we are rebooting e.g. autoupdate.
46
47        Raises:
48            error.TestFail: If it takes too long to reboot.
49        """
50        start_time = time.time()
51        host.reboot()
52        reboot_duration = time.time() - start_time
53        if reboot_duration > cls._REBOOT_TIMEOUT:
54            raise error.TestFail(
55                cls._REBOOT_ERROR_MESSAGE % dict(
56                        reason=reason, actual=reboot_duration,
57                        expected=cls._REBOOT_TIMEOUT))
58
59
60    def run_once(self, host, job_repo_url=None):
61        """Runs the test.
62
63        @param host: a host object representing the DUT
64        @param job_repo_url: URL to get the image.
65
66        @raise error.TestError if anything went wrong with setting up the test;
67               error.TestFail if any part of the test has failed.
68
69        """
70        updater = autoupdate_utils.get_updater_from_repo_url(host, job_repo_url)
71        updater.update_stateful(clobber=True)
72
73        logging.info('Rebooting after performing update.')
74        self.reboot_with_timeout(host, 'update')
75
76        # TODO(sosa): Ideally we would be able to just use
77        # autotest.run_static_method to login/logout, however, this
78        # functionality is currently nested deep into the test logic. Once
79        # telemetry has replaced pyauto login and has been librarized, we
80        # should switch to using that code and not have to rely on running a
81        # client test to do what we want.
82        logging.info('Running sanity desktop login to see that we can '
83                     'login and logout after performing an update.')
84        client_at = autotest.Autotest(host)
85        self.job.set_state('client_success', False)
86        client_at.run_test('login_LoginSuccess')
87        if not self.job.get_state('client_success'):
88            raise error.TestFail(
89                    'Failed to login successfully after an update.')
90
91        logging.info('Rebooting the DUT after first login/logout.')
92        self.reboot_with_timeout(host, 'first login')
93