• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Lint as: python2, python3
2# Copyright 2017 The Chromium OS 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 logging
7import os
8import tempfile
9
10from autotest_lib.client.bin import utils
11from autotest_lib.client.common_lib import error
12from autotest_lib.client.common_lib import file_utils
13from autotest_lib.client.common_lib.cros import arc, arc_util
14from autotest_lib.client.common_lib.cros import chrome
15from autotest_lib.client.cros import cryptohome
16from autotest_lib.client.cros.input_playback import keyboard
17
18
19_CHROME_EXEC_TIME = 'chrome-exec'
20_LOGOUT_STARTED_TIME = 'logout-started'
21_LOGOUT_TIMEOUT = 60  # logout should finsih in 60 seconds.
22
23
24class platform_LogoutPerf(arc.ArcTest):
25    """Measured the time for signing off from a logged on user session.
26
27    The test mainly measures the time for signing off a session and raises
28    an exception if it could not be finished in time. First, it uses telemetry
29    to login a GAIA account and waits for container boots up if the
30    device supports ARC++, then validates the account. Next, it injects the
31    ctrl+shift+q twice to logout the session, then waits for new login screen
32    , i.e. the event of 'login-visible-prompt' to calculate the time elapsed
33    for logging out.
34    """
35    version = 1
36
37
38    def _get_latest_uptime(self, ts_name):
39        pathname = '/tmp/uptime-' + ts_name
40        if not os.path.exists(pathname):
41            logging.info('timestamp %s is missing', ts_name)
42            return 0
43        with open(pathname) as statfile:
44            values = [float(l.split()[0]) for l in 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