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