xref: /aosp_15_r20/external/autotest/client/site_tests/autoupdate_Backoff/autoupdate_Backoff.py (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
1# Lint as: python2, python3
2# Copyright 2018 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
7import os
8
9from autotest_lib.client.bin import utils
10from autotest_lib.client.common_lib import error
11from autotest_lib.client.cros.update_engine import nebraska_wrapper
12from autotest_lib.client.cros.update_engine import update_engine_test
13
14class autoupdate_Backoff(update_engine_test.UpdateEngineTest):
15    """
16    Tests update_engine's backoff mechanism.
17
18    When an update fails, update_engine will not allow another update to the
19    same URL for a certain backoff period. The backoff period is stored in
20    /var/lib/update_engine/prefs/backoff-expiry-time. It is stored as an
21    integer representing the number of microseconds since 1/1/1601.
22
23    By default, backoff is disabled on test images but by creating a
24    'no-ignore-backoff' pref we can test it.
25
26    """
27    version = 1
28
29    _BACKOFF_DISABLED = 'Resetting backoff expiry time as payload backoff is ' \
30                        'disabled'
31    _BACKOFF_ENABLED = 'Incrementing the backoff expiry time'
32    _BACKOFF_ERROR = 'Updating payload state for error code: 40 (' \
33                     'ErrorCode::kOmahaUpdateDeferredForBackoff)'
34    _BACKOFF_EXPIRY_TIME_PREF = 'backoff-expiry-time'
35    _NO_IGNORE_BACKOFF_PREF = 'no-ignore-backoff'
36
37
38    def cleanup(self):
39        """Cleans up the state and extra files this test created."""
40        self._remove_update_engine_pref(self._NO_IGNORE_BACKOFF_PREF)
41        self._remove_update_engine_pref(self._BACKOFF_EXPIRY_TIME_PREF)
42        super(autoupdate_Backoff, self).cleanup()
43
44
45    def run_once(self, payload_url, backoff):
46        """
47        Tests update_engine can do backoff.
48
49        @param payload_url: The payload url.
50        @param backoff: True if backoff is enabled.
51
52        """
53        utils.run(['touch',
54                   os.path.join(self._UPDATE_ENGINE_PREFS_DIR,
55                                self._NO_IGNORE_BACKOFF_PREF)],
56                  ignore_status=True)
57
58        with nebraska_wrapper.NebraskaWrapper(
59            log_dir=self.resultsdir, payload_url=payload_url) as nebraska:
60            # Only set one URL in the Nebraska response so we can test the
61            # backoff functionality quicker.
62            response_props = {'disable_payload_backoff': not backoff,
63                              'failures_per_url': 1,
64                              'critical_update': True}
65
66            # Start the update.
67            self._check_for_update(nebraska.get_update_url(**response_props),
68                                   interactive=False)
69            self._wait_for_progress(0.2)
70
71            # Disable internet so the update fails.
72            self._disable_internet()
73            self._wait_for_update_to_fail()
74            self._enable_internet()
75
76            if backoff:
77                self._check_update_engine_log_for_entry(self._BACKOFF_ENABLED,
78                                                        raise_error=True)
79                utils.run(['cat',
80                           os.path.join(self._UPDATE_ENGINE_PREFS_DIR,
81                                        self._BACKOFF_EXPIRY_TIME_PREF)])
82                try:
83                    self._check_for_update(
84                        nebraska.get_update_url(**response_props),
85                        interactive=False, wait_for_completion=True)
86                except error.CmdError as e:
87                    logging.info('Update failed as expected.')
88                    logging.error(e)
89                    self._check_update_engine_log_for_entry(self._BACKOFF_ERROR,
90                                                            raise_error=True)
91                    return
92
93                raise error.TestFail('Second update attempt succeeded. It was '
94                                     'supposed to have failed due to backoff.')
95            else:
96                self._check_update_engine_log_for_entry(self._BACKOFF_DISABLED,
97                                                        raise_error=True)
98                self._check_for_update(
99                    nebraska.get_update_url(**response_props),
100                    interactive=False)
101                self._wait_for_update_to_complete()
102