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