blob: d9ac8b3be2cbd936336f2de7e1924cdcdc5cbba2 [file] [log] [blame]
Chris Sosab76e0ee2013-05-22 16:55:41 -07001# 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.client.common_lib.cros import autoupdater, dev_server
10from autotest_lib.server import autotest, test
11from autotest_lib.server.cros.dynamic_suite import tools
12
13
14class platform_RebootAfterUpdate(test.test):
15 """Test that updates the machine, reboots, and logs in / logs out.
16
17 This test keeps a reboot timeout in order to keep the system boot times
18 regressing in performance. For example, if Chrome takes a long time to
19 shutdown / hangs, other tests have much longer timeouts (to prevent them
20 from being flaky) while this test targets these hangs. Note, this test only
21 has smaller timeouts for boot, not for login/logout. Also, these timeouts
22 are still fairly conservative and are only meant to catch large regressions
23 or hangs, not small regressions.
24
25 """
26 version = 1
27
28 _REBOOT_ERROR_MESSAGE = (
29 'System failed to restart within the timeout after '
30 '%(reason)s. This failure indicates that the system after '
31 'receiving a reboot request and restarting did not '
32 'reconnect via ssh within the timeout. Actual time %(actual)d '
33 'seconds vs expected time: %(expected)d seconds')
34
35 # Timeouts specific to this test. These should be as low as possible.
36
37 # Total amount of time to wait for a reboot to return.
38 _REBOOT_TIMEOUT = 60
39
40
41 @classmethod
42 def reboot_with_timeout(cls, host, reason):
43 """Reboots the device and checks to see if it completed within desired.
44
45 @param host: Autotest host object to reboot.
46 @param reason: string representing why we are rebooting e.g. autoupdate.
47
48 Raises:
49 error.TestFail: If it takes too long to reboot.
50 """
51 start_time = time.time()
52 host.reboot()
53 reboot_duration = time.time() - start_time
54 if reboot_duration > cls._REBOOT_TIMEOUT:
55 raise error.TestFail(
56 cls._REBOOT_ERROR_MESSAGE % dict(
57 reason=reason, actual=reboot_duration,
58 expected=cls._REBOOT_TIMEOUT))
59
60
61 def run_once(self, host, job_repo_url=None):
62 """Runs the test.
63
64 @param host: a host object representing the DUT
65 @param job_repo_url: URL to get the image.
66
67 @raise error.TestError if anything went wrong with setting up the test;
68 error.TestFail if any part of the test has failed.
69
70 """
71 # Get the job_repo_url -- if not present, attempt to use the one
72 # specified in the host attributes for the host.
73 if not job_repo_url:
74 try:
75 job_repo_url = host.lookup_job_repo_url()
76 except KeyError:
77 logging.fatal('Could not lookup job_repo_url from afe.')
78
79 if not job_repo_url:
80 raise error.TestError(
81 'Test could not be run. Missing the url with which to '
82 're-image the device!')
83
84 # Get the devserver url and build (image) from the repo url e.g.
85 # 'http://mydevserver:8080', 'x86-alex-release/R27-123.0.0'
86 ds, build = tools.get_devserver_build_from_package_url(job_repo_url)
87 devserver = dev_server.ImageServer(ds)
88
89 # We only need to update stateful to do this test.
90 updater = autoupdater.ChromiumOSUpdater(
91 devserver.get_update_url(build), host=host)
92 updater.update_stateful(clobber=True)
93
94 logging.info('Rebooting after performing update.')
95 self.reboot_with_timeout(host, 'update')
96
97 # TODO(sosa): Ideally we would be able to just use
98 # autotest.run_static_method to login/logout, however, this
99 # functionality is currently nested deep into the test logic. Once
100 # telemetry has replaced pyauto login and has been librarized, we
101 # should switch to using that code and not have to rely on running a
102 # client test to do what we want.
103 logging.info('Running sanity desktop login to see that we can '
104 'login and logout after performing an update.')
105 client_at = autotest.Autotest(host)
106 self.job.set_state('client_success', False)
107 client_at.run_test('login_LoginSuccess')
108 if not self.job.get_state('client_success'):
109 raise error.TestFail(
110 'Failed to login successfully after an update.')
111
112 logging.info('Rebooting the DUT after first login/logout.')
113 self.reboot_with_timeout(host, 'first login')