1# Copyright 2020 The Chromium OS Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5import logging 6 7from autotest_lib.client.bin import utils 8from autotest_lib.client.common_lib import error 9from autotest_lib.client.common_lib.cros import chrome 10from autotest_lib.client.cros.update_engine import nebraska_wrapper 11from autotest_lib.client.cros.update_engine import update_engine_test 12from telemetry.core import exceptions 13 14class autoupdate_UpdateFromUI(update_engine_test.UpdateEngineTest): 15 """Starts an update from the Chrome OS Settings app. """ 16 version = 1 17 18 _NOTIFICATION_INTERVAL = 1 19 _NOTIFICATION_TIMEOUT = 10 20 _NOTIFICATION_TITLE = "Update available" 21 22 23 def initialize(self): 24 """Test setup.""" 25 super(autoupdate_UpdateFromUI, self).initialize() 26 self._clear_custom_lsb_release() 27 self._cr = None 28 29 30 def cleanup(self): 31 """Test cleanup. Clears the custom lsb-release used by the test. """ 32 self._clear_custom_lsb_release() 33 super(autoupdate_UpdateFromUI, self).cleanup() 34 35 def _wait_for_update_notification(self): 36 """Waits for the post-update notification to appear. """ 37 38 def find_notification(): 39 """Polls for visibility of the post-update notification. """ 40 notifications = self._cr.get_visible_notifications() 41 if notifications is None: 42 return False 43 return any(n for n in notifications 44 if self._NOTIFICATION_TITLE in n['title']) 45 46 utils.poll_for_condition( 47 condition=find_notification, 48 exception=error.TestFail('Post-update notification not found'), 49 timeout=self._NOTIFICATION_TIMEOUT, 50 sleep_interval=self._NOTIFICATION_INTERVAL) 51 52 53 def run_once(self, payload_url): 54 """ 55 Tests that a Chrome OS software update can be completed from the UI, 56 and that the post-update notification appears when the update is 57 complete. 58 59 @param payload_url: The payload url to use. 60 61 """ 62 with nebraska_wrapper.NebraskaWrapper( 63 log_dir=self.resultsdir, payload_url=payload_url) as nebraska: 64 # To check the post-update notification, we need to remain logged 65 # in after the update completes. However, the DUT will auto-reboot 66 # if we log out after completing an update. This will cause the 67 # server test to fail when returning from the client test. To avoid 68 # this, we stay logged in at the end of the client test by not 69 # using a context manager for the Chrome session. 70 try: 71 self._cr = chrome.Chrome(autotest_ext=True) 72 73 # Need to create a custom lsb-release file to point the UI 74 # update button to Nebraska instead of the default update 75 # server. 76 self._create_custom_lsb_release( 77 nebraska.get_update_url(critical_update=True)) 78 79 # Go to the OS settings page and check for an update. 80 tab = self._cr.browser.tabs[0] 81 tab.Navigate('chrome://os-settings/help') 82 tab.WaitForDocumentReadyStateToBeComplete() 83 self._take_screenshot('before_check_for_updates.png') 84 try: 85 tab.EvaluateJavaScript('settings.AboutPageBrowserProxyImpl' 86 '.getInstance().requestUpdate()') 87 except exceptions.EvaluateException: 88 raise error.TestFail( 89 'Failed to find and click Check For Updates button.') 90 self._take_screenshot('after_check_for_updates.png') 91 self._wait_for_update_to_complete() 92 93 except Exception as e: 94 # The update didn't complete, so we can close the Chrome 95 # session without worrying about auto-reboot. 96 logging.exception("Failed to perform the update: %s", e) 97 if self._cr: 98 self._cr.close() 99 raise error.TestFail("Failed to perform the update: %s" % e) 100 101 self._wait_for_update_notification() 102