• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2017 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 os
7import tempfile
8
9from autotest_lib.client.bin import utils
10from autotest_lib.client.common_lib import error
11from autotest_lib.client.common_lib import file_utils
12from autotest_lib.client.common_lib.cros import arc, arc_util
13from autotest_lib.client.common_lib.cros import chrome
14from autotest_lib.client.cros import cryptohome
15from autotest_lib.client.cros.input_playback import keyboard
16
17
18_CHROME_EXEC_TIME = 'chrome-exec'
19_LOGOUT_STARTED_TIME = 'logout-started'
20_LOGOUT_TIMEOUT = 60  # logout should finsih in 60 seconds.
21
22
23class platform_LogoutPerf(arc.ArcTest):
24    """Measured the time for signing off from a logged on user session.
25
26    The test mainly measures the time for signing off a session and raises
27    an exception if it could not be finished in time. First, it uses telemetry
28    to login a GAIA account and waits for container boots up if the
29    device supports ARC++, then validates the account. Next, it injects the
30    ctrl+shift+q twice to logout the session, then waits for new login screen
31    , i.e. the event of 'login-visible-prompt' to calculate the time elapsed
32    for logging out.
33    """
34    version = 1
35
36
37    def _get_latest_uptime(self, ts_name):
38        pathname = '/tmp/uptime-' + ts_name
39        if not os.path.exists(pathname):
40            logging.info('timestamp %s is missing', ts_name)
41            return 0
42        with open(pathname) as statfile:
43            values = map(lambda l: float(l.split()[0]),
44                         statfile.readlines())
45        logging.info('timestamp of %s -> %s ', ts_name, values[-1])
46        return values[-1]
47
48
49    def _validate(self):
50        # Validate if the environment is expected.
51        if not cryptohome.is_vault_mounted(
52                user=chrome.NormalizeEmail(self.username)):
53            raise error.TestFail('Expected to find a mounted vault for %s'
54                                 % self.username)
55        tab = self.cr.browser.tabs.New()
56        tab.Navigate('http://accounts.google.com')
57        tab.WaitForDocumentReadyStateToBeComplete()
58        res = tab.EvaluateJavaScript('''
59                var res = '',
60                    divs = document.getElementsByTagName('div');
61                for (var i = 0; i < divs.length; i++) {
62                    res = divs[i].textContent;
63                    if (res.search('%s') > 1) {
64                    break;
65                    }
66                }
67                res;
68        ''' % self.username)
69        if not res:
70            raise error.TestFail('No references to %s on accounts page.'
71                                 % self.username)
72        tab.Close()
73
74
75    def initialize(self):
76        self.keyboard = keyboard.Keyboard()
77        self.username, password = arc_util.get_test_account_info()
78        # Login a user session.
79        if utils.is_arc_available():
80            super(platform_LogoutPerf, self).initialize(
81                    gaia_login=True,
82                    disable_arc_opt_in=False)
83            self.cr = self._chrome
84        else:
85            with tempfile.NamedTemporaryFile() as cap:
86                file_utils.download_file(arc_util._ARCP_URL, cap.name)
87                password = cap.read().rstrip()
88            self.cr = chrome.Chrome(gaia_login=True,
89                                    username=self.username,
90                                    password=password)
91
92
93    def arc_setup(self):
94        # Do nothing here
95        logging.info('No ARC++ specific setup required')
96
97
98    def arc_teardown(self):
99        # Do nothing here
100        logging.info('No ARC++ specific teardown required')
101
102
103    def cleanup(self):
104        self.keyboard.close()
105        if utils.is_arc_available():
106            super(platform_LogoutPerf, self).cleanup()
107
108
109    def run_once(self):
110        """Main entry point of test."""
111        # Validate the current GAIA login session
112        self._validate()
113
114        # Get old logout start timestamp
115        logout_started = self._get_latest_uptime(_LOGOUT_STARTED_TIME)
116
117        # Logout hotkey: pressing ctrl+shift+q twice. Double ctrl+shift+q might
118        # be interrupted by window transition, sending extra keys to reduce test
119        # flakiness.
120        for _ in range(4):
121            self.keyboard.press_key('ctrl+shift+q')
122
123        # Poll for logout start timestamp update
124        utils.poll_for_condition(
125                lambda: self._get_latest_uptime(_LOGOUT_STARTED_TIME) !=
126                    logout_started,
127                exception=error.TestFail('Timeout: Could not sign off in time'),
128                timeout=_LOGOUT_TIMEOUT,
129                sleep_interval=2,
130                desc='Polling for user to be logged out.')
131
132        logout_started = self._get_latest_uptime(_LOGOUT_STARTED_TIME)
133        logging.info('logout started @%s', logout_started)
134        chrome_exec = self._get_latest_uptime(_CHROME_EXEC_TIME)
135        logging.info('chrome restarts @%s', chrome_exec)
136        elapsed_time = float(chrome_exec) - float(logout_started)
137        logging.info('The elapsed time for signout is %s', elapsed_time)
138        self.output_perf_value(description='Seconds elapsed for Signout',
139                               value=elapsed_time,
140                               higher_is_better=False,
141                               units='seconds')
142