1# Copyright 2018 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 datetime 6import logging 7 8from autotest_lib.client.bin import utils 9from autotest_lib.client.common_lib import error 10from autotest_lib.client.common_lib.cros import chrome 11from autotest_lib.client.cros.update_engine import nebraska_wrapper 12from autotest_lib.client.cros.update_engine import update_engine_test 13 14class autoupdate_EOL(update_engine_test.UpdateEngineTest): 15 """Tests end of life (EOL) behaviour.""" 16 version = 1 17 18 _EXPECTED_FINAL_TITLE = 'Final software update' 19 _DAYS_BEFORE_EOL_START_WARNING = 180 20 # Value within {} expected to be number of days since epoch. 21 _EXPECTED_EOL_DATE_TEMPLATE = 'EOL_DATE={}' 22 # Value within {} expected to be the month and year. 23 _EXPECTED_WARNING_TITLE = 'Updates end {}' 24 _UNIX_EPOCH = datetime.datetime(1970, 1, 1) 25 26 27 def _get_expected_eol_date(self, eol_date): 28 """Figure out the expected eol date.""" 29 return self._UNIX_EPOCH + datetime.timedelta(eol_date) 30 31 32 def _check_eol_info(self): 33 """Checks update_engines eol status.""" 34 result = utils.run( 35 [self._UPDATE_ENGINE_CLIENT_CMD, '--eol_status']).stdout.strip() 36 if self._EXPECTED_EOL_DATE not in result: 37 raise error.TestFail('Expected date %s. Actual: %s' % 38 (self._EXPECTED_EOL_DATE, result)) 39 40 41 def _check_eol_notification(self, eol_date): 42 """Checks that we are showing an EOL notification to the user.""" 43 expected_eol_date = self._get_expected_eol_date(eol_date) 44 expected_warning_begins_date = (expected_eol_date 45 - datetime.timedelta( 46 self._DAYS_BEFORE_EOL_START_WARNING)) 47 48 expected_final_title = self._EXPECTED_FINAL_TITLE 49 expected_warning_title = (self._EXPECTED_WARNING_TITLE. 50 format(expected_eol_date.strftime("%B %Y"))) 51 52 def find_notification(expected_title): 53 """Helper to find notification.""" 54 notifications = self._cr.get_visible_notifications() 55 return any([n['title'] == expected_title 56 for n in (notifications or [])]) 57 58 def check_eol_notifications(): 59 """Checks if correct notification is shown.""" 60 final_notification = find_notification(expected_final_title) 61 warning_notification = find_notification(expected_warning_title) 62 63 now = datetime.datetime.utcnow() 64 if expected_eol_date <= now: 65 return final_notification and not warning_notification 66 elif expected_warning_begins_date <= now: 67 return not final_notification and warning_notification 68 return not final_notification and not warning_notification 69 70 utils.poll_for_condition(condition=lambda: check_eol_notifications(), 71 desc='End of Life Notification UI passed', 72 timeout=5, sleep_interval=1) 73 74 75 def _check_eol_settings(self, eol_date): 76 """Check that the messages about EOL in Settings are correct.""" 77 tab = self._cr.browser.tabs[0] 78 tab.Navigate('chrome://os-settings/help/details') 79 tab.WaitForDocumentReadyStateToBeComplete() 80 eol_js = ''' 81 settings.AboutPageBrowserProxyImpl.getInstance().getEndOfLifeInfo() 82 ''' 83 eol_promise = tab.EvaluateJavaScript(eol_js, promise=True) 84 expected_eol_date = self._get_expected_eol_date(eol_date) 85 eol_msg = ('This device will get automatic software and security ' 86 'updates until') 87 if expected_eol_date <= datetime.datetime.utcnow(): 88 eol_msg = ('This device stopped getting automatic software and ' 89 'security updates in') 90 if eol_msg not in eol_promise['aboutPageEndOfLifeMessage']: 91 raise error.TestFail('"%s" not found in Settings.' % eol_msg) 92 93 94 def run_once(self, eol_date): 95 """ 96 Checks that DUT behaves correctly in EOL scenarios. 97 98 @param eol_date: the days from epoch value passed along to 99 NanoOmahaDevServer placed within the _eol_date tag 100 in the Omaha response. 101 102 """ 103 self._EXPECTED_EOL_DATE = \ 104 self._EXPECTED_EOL_DATE_TEMPLATE.format(eol_date) 105 106 # Start a Nebraska server to return a response with eol entry. 107 with nebraska_wrapper.NebraskaWrapper( 108 log_dir=self.resultsdir) as nebraska: 109 # Try to update. It should fail with noupdate. 110 try: 111 self._check_for_update( 112 nebraska.get_update_url(eol_date=eol_date, no_update=True), 113 wait_for_completion=True) 114 except error.CmdError: 115 logging.info('Update failed as expected.') 116 117 self._check_eol_info() 118 with chrome.Chrome(autotest_ext=True, logged_in=True) as cr: 119 self._cr = cr 120 self._check_eol_notification(eol_date) 121 self._check_eol_settings(eol_date) 122