• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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