xref: /aosp_15_r20/external/autotest/client/cros/login.py (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
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