1# Copyright (c) 2012 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, os 6 7import constants, cros_logging, cros_ui, cryptohome 8from autotest_lib.client.bin import utils 9from autotest_lib.client.common_lib import error 10 11 12class CrashError(error.TestError): 13 """Error raised when a pertinent process crashes while waiting on 14 a condition. 15 """ 16 pass 17 18 19class UnexpectedCondition(error.TestError): 20 """Error raised when an expected precondition is not met.""" 21 pass 22 23 24def process_crashed(process, log_reader): 25 """Checks the log watched by |log_reader| to see if a crash was reported 26 for |process|. 27 28 @param process: process name to look for. 29 @param log_reader: LogReader object set up to watch appropriate log file. 30 31 @return: True if so, False if not. 32 """ 33 return log_reader.can_find('Received crash notification for %s' % process) 34 35 36def wait_for_condition(condition, timeout_msg, timeout, process, crash_msg): 37 """Wait for callable |condition| to return true, while checking for crashes. 38 39 Poll for |condition| to become true, for |timeout| seconds. If the timeout 40 is reached, check to see if |process| crashed while we were polling. 41 If so, raise CrashError(crash_msg). If not, raise TimeoutError(timeout_msg). 42 43 @param condition: a callable to poll on. 44 @param timeout_msg: message to put in TimeoutError before raising. 45 @param timeout: float number of seconds to poll on |condition|. 46 @param process: process name to watch for crashes while polling. 47 @param crash_msg: message to put in CrashError if polling failed and 48 |process| crashed. 49 50 @raise: TimeoutError if timeout is reached. 51 @raise: CrashError if process crashed and the condition never fired. 52 """ 53 # Mark /var/log/messages now; we'll run through all subsequent log 54 # messages if we couldn't start chrome to see if the browser crashed. 55 log_reader = cros_logging.LogReader() 56 log_reader.set_start_by_current() 57 try: 58 utils.poll_for_condition( 59 condition, 60 utils.TimeoutError(timeout_msg), 61 timeout=timeout) 62 except utils.TimeoutError, e: 63 # We could fail faster if necessary, but it'd be more complicated. 64 if process_crashed(process, log_reader): 65 logging.error(crash_msg) 66 raise CrashError(crash_msg) 67 else: 68 raise e 69 70 71def wait_for_browser(timeout=cros_ui.RESTART_UI_TIMEOUT): 72 """Wait until a Chrome process is running. 73 74 @param timeout: float number of seconds to wait. 75 76 @raise: TimeoutError: Chrome didn't start before timeout. 77 """ 78 wait_for_condition( 79 lambda: os.system('pgrep ^%s$ >/dev/null' % constants.BROWSER) == 0, 80 timeout_msg='Timed out waiting for Chrome to start', 81 timeout=timeout, 82 process=constants.BROWSER, 83 crash_msg='Chrome crashed while starting up.') 84 85 86def wait_for_browser_exit(crash_msg, timeout=cros_ui.RESTART_UI_TIMEOUT): 87 """Wait for the Chrome process to exit. 88 89 @param crash_msg: Error message to include if Chrome crashed. 90 @param timeout: float number of seconds to wait. 91 92 @return: True if Chrome exited; False otherwise. 93 94 @raise: CrashError: Chrome crashed while we were waiting. 95 """ 96 try: 97 wait_for_condition( 98 lambda: os.system('pgrep ^%s$ >/dev/null' % constants.BROWSER) != 0, 99 timeout_msg='Timed out waiting for Chrome to exit', 100 timeout=timeout, 101 process=constants.BROWSER, 102 crash_msg=crash_msg) 103 return True 104 except utils.TimeoutError, e: 105 return False 106 107 108def wait_for_cryptohome(user, timeout=cros_ui.RESTART_UI_TIMEOUT): 109 """Wait until cryptohome is mounted. 110 111 @param user: the user whose cryptohome the caller wants to wait for. 112 @param timeout: float number of seconds to wait. 113 114 @raise: TimeoutError: cryptohome wasn't mounted before timeout 115 """ 116 wait_for_condition( 117 condition=lambda: cryptohome.is_vault_mounted(user), 118 timeout_msg='Timed out waiting for cryptohome to be mounted', 119 timeout=timeout, 120 process='cryptohomed', 121 crash_msg='cryptohomed crashed during mount attempt') 122 123 124def wait_for_ownership(timeout=constants.DEFAULT_OWNERSHIP_TIMEOUT): 125 """Wait until device owner key file exists on disk. 126 127 @param timeout: float number of seconds to wait. 128 129 @raise: TimeoutError: file didn't appear before timeout. 130 """ 131 if os.access(constants.OWNER_KEY_FILE, os.F_OK): 132 raise error.TestError('Device is already owned!') 133 wait_for_condition( 134 condition=lambda: os.access(constants.OWNER_KEY_FILE, os.F_OK), 135 timeout_msg='Timed out waiting for ownership', 136 timeout=timeout, 137 process=constants.BROWSER, 138 crash_msg='Chrome crashed before ownership could be taken.') 139