| # Lint as: python2, python3 |
| # Copyright 2020 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| import logging |
| |
| from autotest_lib.client.bin import utils |
| from autotest_lib.client.common_lib import error |
| from autotest_lib.client.common_lib.cros import chrome |
| from autotest_lib.client.cros.update_engine import nebraska_wrapper |
| from autotest_lib.client.cros.update_engine import update_engine_test |
| from telemetry.core import exceptions |
| |
| class autoupdate_UpdateFromUI(update_engine_test.UpdateEngineTest): |
| """Starts an update from the ChromeOS Settings app. """ |
| version = 1 |
| |
| _NOTIFICATION_INTERVAL = 1 |
| _NOTIFICATION_TIMEOUT = 10 |
| _NOTIFICATION_TITLE = "Update available" |
| |
| |
| def initialize(self): |
| """Test setup.""" |
| super(autoupdate_UpdateFromUI, self).initialize() |
| self._clear_custom_lsb_release() |
| self._cr = None |
| |
| |
| def cleanup(self): |
| """Test cleanup. Clears the custom lsb-release used by the test. """ |
| self._clear_custom_lsb_release() |
| super(autoupdate_UpdateFromUI, self).cleanup() |
| |
| def _wait_for_update_notification(self): |
| """Waits for the post-update notification to appear. """ |
| |
| def find_notification(): |
| """Polls for visibility of the post-update notification. """ |
| notifications = self._cr.get_visible_notifications() |
| if notifications is None: |
| return False |
| return any(n for n in notifications |
| if self._NOTIFICATION_TITLE in n['title']) |
| |
| utils.poll_for_condition( |
| condition=find_notification, |
| exception=error.TestFail('Post-update notification not found'), |
| timeout=self._NOTIFICATION_TIMEOUT, |
| sleep_interval=self._NOTIFICATION_INTERVAL) |
| |
| |
| def run_once(self, payload_url): |
| """ |
| Tests that a ChromeOS software update can be completed from the UI, |
| and that the post-update notification appears when the update is |
| complete. |
| |
| @param payload_url: The payload url to use. |
| |
| """ |
| with nebraska_wrapper.NebraskaWrapper( |
| log_dir=self.resultsdir, payload_url=payload_url) as nebraska: |
| # To check the post-update notification, we need to remain logged |
| # in after the update completes. However, the DUT will auto-reboot |
| # if we log out after completing an update. This will cause the |
| # server test to fail when returning from the client test. To avoid |
| # this, we stay logged in at the end of the client test by not |
| # using a context manager for the Chrome session. |
| try: |
| self._cr = chrome.Chrome(autotest_ext=True) |
| |
| # Need to create a custom lsb-release file to point the UI |
| # update button to Nebraska instead of the default update |
| # server. |
| self._create_custom_lsb_release( |
| nebraska.get_update_url(critical_update=True)) |
| |
| # Go to the OS settings page and check for an update. |
| tab = self._cr.browser.tabs[0] |
| tab.Navigate('chrome://os-settings/help') |
| tab.WaitForDocumentReadyStateToBeComplete() |
| self._take_screenshot('before_check_for_updates.png') |
| request_update_js = ''' |
| async function checkForUpdate() { |
| return await import('chrome://os-settings/chromeos/os_settings.js').then(m => |
| m.AboutPageBrowserProxyImpl.getInstance().requestUpdate()); |
| } |
| checkForUpdate(); |
| ''' |
| try: |
| tab.EvaluateJavaScript(request_update_js) |
| except exceptions.EvaluateException: |
| raise error.TestFail( |
| 'Failed to find and click Check For Updates button.') |
| self._take_screenshot('after_check_for_updates.png') |
| self._wait_for_update_to_complete() |
| |
| except Exception as e: |
| # The update didn't complete, so we can close the Chrome |
| # session without worrying about auto-reboot. |
| logging.exception("Failed to perform the update: %s", e) |
| if self._cr: |
| self._cr.close() |
| raise error.TestFail("Failed to perform the update: %s" % e) |
| |
| self._wait_for_update_notification() |