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