| # Copyright 2017 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. |
| |
| # Update event types. |
| EVENT_TYPE_DOWNLOAD_COMPLETE = '1' |
| EVENT_TYPE_INSTALL_COMPLETE = '2' |
| EVENT_TYPE_UPDATE_COMPLETE = '3' |
| EVENT_TYPE_DOWNLOAD_STARTED = '13' |
| EVENT_TYPE_DOWNLOAD_FINISHED = '14' |
| EVENT_TYPE_REBOOTED_AFTER_UPDATE = '54' |
| |
| # Update event results. |
| EVENT_RESULT_ERROR = '0' |
| EVENT_RESULT_SUCCESS = '1' |
| EVENT_RESULT_UPDATE_DEFERRED = '9' |
| |
| # Omaha event types/results, from update_engine/omaha_request_action.h |
| # These are stored in dict form in order to easily print out the keys. |
| EVENT_TYPE_DICT = { |
| EVENT_TYPE_DOWNLOAD_COMPLETE: 'download_complete', |
| EVENT_TYPE_INSTALL_COMPLETE: 'install_complete', |
| EVENT_TYPE_UPDATE_COMPLETE: 'update_complete', |
| EVENT_TYPE_DOWNLOAD_STARTED: 'download_started', |
| EVENT_TYPE_DOWNLOAD_FINISHED: 'download_finished', |
| EVENT_TYPE_REBOOTED_AFTER_UPDATE: 'rebooted_after_update' |
| } |
| |
| EVENT_RESULT_DICT = { |
| EVENT_RESULT_ERROR: 'error', |
| EVENT_RESULT_SUCCESS: 'success', |
| EVENT_RESULT_UPDATE_DEFERRED: 'update_deferred' |
| } |
| |
| |
| def get_event_type(event_type_code): |
| """Utility to look up the different event type codes.""" |
| return EVENT_TYPE_DICT[event_type_code] |
| |
| |
| def get_event_result(event_result_code): |
| """Utility to look up the different event result codes.""" |
| return EVENT_RESULT_DICT[event_result_code] |
| |
| |
| class UpdateEngineEvent(object): |
| """This class represents a single EXPECTED update engine event. |
| |
| This class's data will be compared against an ACTUAL event returned by |
| update_engine. |
| """ |
| |
| def __init__(self, event_type=None, event_result=None, version=None, |
| previous_version=None, on_error=None): |
| """Initializes an event. |
| |
| @param event_type: Expected event type. |
| @param event_result: Expected event result code. |
| @param version: Expected reported image version. |
| @param previous_version: Expected reported previous image version. |
| @param on_error: a function to call when the event's data is invalid. |
| """ |
| self._expected_attrs = { |
| 'event_type': event_type, |
| 'event_result': event_result, |
| 'version': version, |
| 'previous_version': previous_version, |
| } |
| self._on_error = on_error |
| |
| |
| def _verify_event_attribute(self, attr_name, expected_attr_val, |
| actual_attr_val): |
| """Compares a single attribute to ensure expected matches actual. |
| |
| @param attr_name: name of the attribute to verify. |
| @param expected_attr_val: expected attribute value. |
| @param actual_attr_val: actual attribute value. |
| |
| @return True if actual value is present and matches, False otherwise. |
| """ |
| # None values are assumed to be missing and non-matching. |
| if actual_attr_val is None: |
| return False |
| |
| # We allow expected version numbers (e.g. 2940.0.0) to be contained in |
| # actual values (2940.0.0-a1) for developer images. |
| if (actual_attr_val == expected_attr_val or |
| ('version' in attr_name and expected_attr_val in actual_attr_val)): |
| return True |
| |
| return False |
| |
| |
| def __str__(self): |
| """Returns a comma separated list of the event data.""" |
| return '{%s}' % ', '.join(['%s:%s' % (k, v) for k, v in |
| self._expected_attrs.iteritems()]) |
| |
| def equals(self, actual_event): |
| """Compares this expected event with an actual event from the update. |
| |
| @param actual_event: a dictionary containing event attributes. |
| |
| @return An error message, or None if all attributes as expected. |
| """ |
| mismatched_attrs = [ |
| attr_name for attr_name, expected_attr_val |
| in self._expected_attrs.iteritems() |
| if (expected_attr_val and |
| not self._verify_event_attribute(attr_name, expected_attr_val, |
| actual_event.get(attr_name)))] |
| |
| if not mismatched_attrs: |
| return None |
| |
| return self._on_error(self._expected_attrs, actual_event, |
| mismatched_attrs) |