| OLD | NEW |
| 1 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 1 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 import logging, os, utils, signal, time | 5 import logging, os, utils, signal, subprocess, time |
| 6 from autotest_lib.client.bin import chromeos_constants, site_cryptohome | 6 from autotest_lib.client.bin import chromeos_constants, site_cryptohome |
| 7 from autotest_lib.client.bin import site_utils, test | 7 from autotest_lib.client.bin import site_utils, test |
| 8 from autotest_lib.client.common_lib import error, site_ui | 8 from autotest_lib.client.common_lib import error, site_ui |
| 9 | 9 |
| 10 | 10 |
| 11 class TimeoutError(error.TestError): | 11 class TimeoutError(error.TestError): |
| 12 """Error returned if we time out while waiting on a condition.""" | 12 """Error raised when we time out while waiting on a condition.""" |
| 13 pass | 13 pass |
| 14 | 14 |
| 15 | 15 |
| 16 def setup_autox(test): | 16 class UnexpectedCondition(error.TestError): |
| 17 test.job.setup_dep(['autox']) | 17 """Error raised when an expected precondition is not met.""" |
| 18 # create a empty srcdir to prevent the error that checks .version file | 18 pass |
| 19 if not os.path.exists(test.srcdir): | 19 |
| 20 os.mkdir(test.srcdir) | 20 |
| 21 def __get_session_manager_pid(): |
| 22 """Determine the pid of the session manager. |
| 23 |
| 24 Returns: |
| 25 An integer indicating the current session manager pid, or None if |
| 26 it is not running. |
| 27 """ |
| 28 |
| 29 p = subprocess.Popen(["pgrep", "^%s$" % chromeos_constants.SESSION_MANAGER], |
| 30 stdout=subprocess.PIPE) |
| 31 ary = p.communicate()[0].split() |
| 32 return int(ary[0]) if ary else None |
| 33 |
| 34 |
| 35 def __session_manager_restarted(oldpid): |
| 36 """Detect if the session manager has restarted. |
| 37 |
| 38 Args: |
| 39 oldpid: Integer indicating the last known pid of the session_manager. |
| 40 |
| 41 Returns: |
| 42 True if the session manager is running under a pid other than |
| 43 'oldpid', X is running, and there is a window displayed. |
| 44 """ |
| 45 import autox |
| 46 |
| 47 newpid = __get_session_manager_pid() |
| 48 if newpid and newpid != oldpid: |
| 49 try: |
| 50 ax = site_ui.get_autox() |
| 51 except autox.Xlib.error.DisplayConnectionError: |
| 52 return False |
| 53 |
| 54 # When the session manager starts up there is a moment where we can |
| 55 # make a connection with autox, but there is no window displayed. If |
| 56 # we start sending keystrokes at this point they get lost. If we wait |
| 57 # for this window to show up, things go much smoother. |
| 58 wid = ax.get_top_window_id_at_point(0, 0) |
| 59 if not wid: |
| 60 return False |
| 61 |
| 62 # The login manager displays its widgetry in a second window centered |
| 63 # on the screen. Waiting for this window to show up is also helpful. |
| 64 # TODO: perhaps the login manager should emit some more trustworthy |
| 65 # signal when it's ready to accept credentials. |
| 66 x, y = ax.get_screen_size() |
| 67 wid2 = ax.get_top_window_id_at_point(x / 2, y / 2) |
| 68 if wid == wid2: |
| 69 return False |
| 70 |
| 71 return True |
| 72 |
| 73 return False |
| 21 | 74 |
| 22 | 75 |
| 23 def logged_in(): | 76 def logged_in(): |
| 24 # this file is created when the session_manager emits start-user-session | 77 # this file is created when the session_manager emits start-user-session |
| 25 # and removed when the session_manager emits stop-user-session | 78 # and removed when the session_manager emits stop-user-session |
| 26 return os.path.exists(chromeos_constants.LOGGED_IN_MAGIC_FILE) | 79 return os.path.exists(chromeos_constants.LOGGED_IN_MAGIC_FILE) |
| 27 | 80 |
| 28 | 81 |
| 29 # TODO: Update this to use the Python-based autox instead. | 82 def attempt_login(username, password, timeout=20): |
| 30 def attempt_login(test, script_file, timeout=10): | |
| 31 """Attempt to log in. | 83 """Attempt to log in. |
| 32 | 84 |
| 33 Args: | 85 Args: |
| 34 script: str filename of autox JSON script | 86 script: str filename of autox JSON script |
| 35 timeout: float number of seconds to wait | 87 timeout: float number of seconds to wait |
| 36 | 88 |
| 37 Raises: | 89 Raises: |
| 38 error.TestFail: autox program exited with failure | |
| 39 TimeoutError: login didn't complete before timeout | 90 TimeoutError: login didn't complete before timeout |
| 91 UnexpectedCondition: login manager is not running, or user is already |
| 92 logged in. |
| 40 """ | 93 """ |
| 41 dep = 'autox' | 94 logging.info("Attempting to login using autox.py and (%s, %s)" % |
| 42 dep_dir = os.path.join(test.autodir, 'deps', dep) | 95 (username, password)) |
| 43 test.job.install_pkg(dep, 'dep', dep_dir) | |
| 44 | 96 |
| 45 autox_binary = '%s/%s' % (dep_dir, 'autox') | 97 if not __get_session_manager_pid(): |
| 46 autox_script = os.path.join(test.job.configdir, script_file) | 98 raise UnexpectedCondition("Session manager is not running") |
| 47 | 99 |
| 48 # TODO: Use something more robust that checks whether the login window is | 100 if logged_in(): |
| 49 # mapped. | 101 raise UnexpectedCondition("Already logged in") |
| 50 wait_for_browser() | 102 |
| 51 try: | 103 ax = site_ui.get_autox() |
| 52 utils.system(site_ui.xcommand('%s %s' % (autox_binary, autox_script))) | 104 # navigate to login screen |
| 53 except error.CmdError, e: | 105 ax.send_hotkey("Ctrl+Alt+L") |
| 54 logging.debug(e) | 106 # focus username |
| 55 raise error.TestFail('AutoX program failed to login for test user') | 107 ax.send_hotkey("Alt+U") |
| 108 ax.send_text(username) |
| 109 # TODO(rginda): remove Tab after http://codereview.chromium.org/1390003 |
| 110 ax.send_hotkey("Tab") |
| 111 # focus password |
| 112 ax.send_hotkey("Alt+P") |
| 113 ax.send_text(password) |
| 114 ax.send_hotkey("Return") |
| 56 | 115 |
| 57 site_utils.poll_for_condition( | 116 site_utils.poll_for_condition( |
| 58 lambda: logged_in(), | 117 logged_in, TimeoutError('Timed out waiting for login'), |
| 59 TimeoutError('Timed out while waiting to be logged in'), | |
| 60 timeout=timeout) | 118 timeout=timeout) |
| 61 | 119 |
| 62 | 120 |
| 63 def attempt_logout(timeout=10): | 121 def attempt_logout(timeout=20): |
| 64 """Attempt to log out by killing Chrome. | 122 """Attempt to log out by killing Chrome. |
| 65 | 123 |
| 66 Args: | 124 Args: |
| 67 timeout: float number of seconds to wait | 125 timeout: float number of seconds to wait |
| 68 | 126 |
| 69 Raises: | 127 Raises: |
| 70 TimeoutError: logout didn't complete before timeout | 128 TimeoutError: logout didn't complete before timeout |
| 129 UnexpectedCondition: user is not logged in |
| 71 """ | 130 """ |
| 72 # Gracefully exiting chrome causes the user's session to end. | 131 if not logged_in(): |
| 73 wait_for_initial_chrome_window() | 132 raise UnexpectedCondition('Already logged out') |
| 74 utils.system('pkill -TERM -o ^%s$' % chromeos_constants.BROWSER) | 133 |
| 134 oldpid = __get_session_manager_pid() |
| 135 |
| 136 # Gracefully exiting the session manager causes the user's session to end. |
| 137 utils.system('pkill -TERM -o ^%s$' % chromeos_constants.SESSION_MANAGER) |
| 138 |
| 75 site_utils.poll_for_condition( | 139 site_utils.poll_for_condition( |
| 76 lambda: not logged_in(), | 140 lambda: __session_manager_restarted(oldpid), |
| 77 TimeoutError('Timed out while waiting for logout'), | 141 TimeoutError('Timed out waiting for logout'), |
| 78 timeout=timeout) | 142 timeout) |
| 79 | 143 |
| 80 | 144 |
| 81 def wait_for_browser(timeout=10): | 145 def wait_for_browser(timeout=10): |
| 82 """Wait until a Chrome process is running. | 146 """Wait until a Chrome process is running. |
| 83 | 147 |
| 84 Args: | 148 Args: |
| 85 timeout: float number of seconds to wait | 149 timeout: float number of seconds to wait |
| 86 | 150 |
| 87 Raises: | 151 Raises: |
| 88 TimeoutError: Chrome didn't start before timeout | 152 TimeoutError: Chrome didn't start before timeout |
| (...skipping 22 matching lines...) Expand all Loading... |
| 111 def wait_for_screensaver(timeout=10): | 175 def wait_for_screensaver(timeout=10): |
| 112 """Wait until xscreensaver is responding. | 176 """Wait until xscreensaver is responding. |
| 113 | 177 |
| 114 Args: | 178 Args: |
| 115 timeout: float number of seconds to wait | 179 timeout: float number of seconds to wait |
| 116 | 180 |
| 117 Raises: | 181 Raises: |
| 118 TimeoutError: xscreensaver didn't respond before timeout | 182 TimeoutError: xscreensaver didn't respond before timeout |
| 119 """ | 183 """ |
| 120 site_utils.poll_for_condition( | 184 site_utils.poll_for_condition( |
| 121 lambda: os.system( | 185 lambda: site_ui.xsystem('xscreensaver-command -version', |
| 122 site_ui.xcommand('xscreensaver-command -version')) == 0, | 186 ignore_status=True) == 0, |
| 123 TimeoutError('Timed out waiting for xscreensaver to respond'), | 187 TimeoutError('Timed out waiting for xscreensaver to respond'), |
| 124 timeout=timeout) | 188 timeout=timeout) |
| 125 | 189 |
| 126 | 190 |
| 127 def wait_for_window_manager(timeout=20): | 191 def wait_for_window_manager(timeout=20): |
| 128 """Wait until the window manager is running. | 192 """Wait until the window manager is running. |
| 129 | 193 |
| 130 Args: | 194 Args: |
| 131 timeout: float number of seconds to wait | 195 timeout: float number of seconds to wait |
| 132 | 196 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 159 nuke_process_by_name('session_manager') | 223 nuke_process_by_name('session_manager') |
| 160 wait_for_browser() | 224 wait_for_browser() |
| 161 | 225 |
| 162 | 226 |
| 163 def nuke_process_by_name(name, with_prejudice=False): | 227 def nuke_process_by_name(name, with_prejudice=False): |
| 164 pid = int(utils.system_output('pgrep -o ^%s$' % name)) | 228 pid = int(utils.system_output('pgrep -o ^%s$' % name)) |
| 165 if with_prejudice: | 229 if with_prejudice: |
| 166 utils.nuke_pid(pid, [signal.SIGKILL]) | 230 utils.nuke_pid(pid, [signal.SIGKILL]) |
| 167 else: | 231 else: |
| 168 utils.nuke_pid(pid) | 232 utils.nuke_pid(pid) |
| OLD | NEW |