Home | History | Annotate | Download | only in touch_UpdateErrors
      1 # Copyright (c) 2014 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 
      5 import logging
      6 
      7 from autotest_lib.client.bin import utils
      8 from autotest_lib.client.common_lib import error
      9 from autotest_lib.client.cros import touch_playback_test_base
     10 
     11 
     12 class touch_UpdateErrors(touch_playback_test_base.touch_playback_test_base):
     13     """Check that touch update is tried and that there are no update errors."""
     14     version = 1
     15 
     16     # Older devices with Synaptics touchpads do not report firmware updates.
     17     _INVALID_BOARDS = ['x86-alex', 'x86-alex_he', 'x86-zgb', 'x86-zgb_he',
     18                        'x86-mario', 'stout']
     19 
     20     # Devices which have errors in older builds but not newer ones.
     21     _IGNORE_OLDER_LOGS = ['expresso', 'enguarde', 'cyan', 'wizpig']
     22 
     23     # Devices which have errors in the first build after update.
     24     _IGNORE_AFTER_UPDATE_LOGS = ['link']
     25 
     26     def _find_logs_start_line(self):
     27         """Find where in /var/log/messages this build's logs start.
     28 
     29         Prevent bugs such as crosbug.com/p/31012, where unfixable errors from
     30         FSI builds remain in the logs.
     31 
     32         For devices where this applies, split the logs by Linux version.  Since
     33         this line can repeat, find the last chunk of logs where the version is
     34         all the same - all for the build under test.
     35 
     36         @returns: string of the line number to start looking at logs
     37 
     38         """
     39         if not (self._platform in self._IGNORE_OLDER_LOGS or
     40                 self._platform in self._IGNORE_AFTER_UPDATE_LOGS):
     41             return '0'
     42 
     43         log_cmd = 'grep -ni "Linux version " /var/log/messages'
     44 
     45         version_entries = utils.run(log_cmd).stdout.strip().split('\n')
     46 
     47         # Separate the line number and the version date (i.e. remove timestamp).
     48         lines, dates = [], []
     49         for entry in version_entries:
     50             lines.append(entry[:entry.find(':')])
     51             dates.append(entry[entry.find('Linux version '):])
     52         latest = dates[-1]
     53         start_line = lines[-1]
     54         start_line_index = -1
     55 
     56         # Find where logs from this build start by checking backwards for the
     57         # first change in build.  Some of these dates may be duplicated.
     58         for i in xrange(len(lines)-1, -1, -1):
     59             if dates[i] != latest:
     60                 break
     61             start_line = lines[i]
     62             start_line_index = i
     63 
     64         if start_line_index == 0:
     65             return '0'
     66 
     67         logging.info('This build has an older build; skipping some logs, '
     68                      'as was hardcoded for this platform.')
     69 
     70         # Ignore the first build after update if required.
     71         if self._platform in self._IGNORE_AFTER_UPDATE_LOGS:
     72             start_line_index += 1
     73             if start_line_index >= len(lines):
     74                 raise error.TestError(
     75                         'Insufficent logs: aborting test to avoid a known '
     76                         'issue!  Please reboot and try again.')
     77             start_line = lines[start_line_index]
     78 
     79         return start_line
     80 
     81     def _check_updates(self, input_type):
     82         """Fail the test if device has problems with touch firmware update.
     83 
     84         @param input_type: string of input type, e.g. 'touchpad'
     85 
     86         @raises: TestFail if no update attempt occurs or if there is an error.
     87 
     88         """
     89         hw_id = self.player.devices[input_type].hw_id
     90         if not hw_id:
     91             raise error.TestError('%s has no valid hw_id!' % input_type)
     92 
     93         start_line = self._find_logs_start_line()
     94         log_cmd = 'tail -n +%s /var/log/messages | grep -i touch' % start_line
     95 
     96         pass_terms = ['touch-firmware-update']
     97         if hw_id == 'wacom': # Wacom styluses don't have Product ids.
     98             pass_terms.append(hw_id)
     99         else:
    100             pass_terms.append('"Product[^a-z0-9]ID[^a-z0-9]*%s"' % hw_id)
    101         fail_terms = ['error[^s]', 'err[^a-z]']
    102         ignore_terms = ['touchview','autotest']
    103 
    104         # Remove lines that match ignore_terms.
    105         for term in ignore_terms:
    106             log_cmd += ' | grep -v -i %s' % term
    107 
    108         # Check for key terms in touch logs.
    109         for term in pass_terms + fail_terms:
    110             search_cmd = '%s | grep -i %s' % (log_cmd, term)
    111             log_entries = utils.run(search_cmd, ignore_status=True).stdout
    112             if term in fail_terms and len(log_entries) > 0:
    113                 error_msg = log_entries.split('\n')[0]
    114                 error_msg = error_msg[error_msg.find(term)+len(term):].strip()
    115                 raise error.TestFail(error_msg)
    116             if term in pass_terms and len(log_entries) == 0:
    117                 logging.info('Did not find "%s"!', term)
    118                 raise error.TestFail('Touch firmware did not attempt update.')
    119 
    120     def run_once(self, input_type='touchpad'):
    121         """Entry point of this test."""
    122         if not self.player.has(input_type):
    123             raise error.TestError('No %s found on this device!' % input_type)
    124 
    125         # Skip run on invalid touch inputs.
    126         if self._platform in self._INVALID_BOARDS:
    127             logging.info('This touchpad is not supported for this test.')
    128             return
    129 
    130         self._check_updates(input_type)
    131