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