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 5import logging 6 7from autotest_lib.client.bin import utils 8from autotest_lib.client.common_lib import error 9from autotest_lib.client.cros import touch_playback_test_base 10 11 12class 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.*%s' % hw_id ] 97 98 fail_terms = ['error[^s]', 'err[^a-z]'] 99 ignore_terms = ['touchview','autotest'] 100 101 # Remove lines that match ignore_terms. 102 for term in ignore_terms: 103 log_cmd += ' | grep -v -i %s' % term 104 105 # Check for key terms in touch logs. 106 for term in pass_terms + fail_terms: 107 search_cmd = '%s | grep -i %s' % (log_cmd, term) 108 log_entries = utils.run(search_cmd, ignore_status=True).stdout 109 if term in fail_terms and len(log_entries) > 0: 110 error_msg = log_entries.split('\n')[0] 111 error_msg = error_msg[error_msg.find(term)+len(term):].strip() 112 raise error.TestFail(error_msg) 113 if term in pass_terms and len(log_entries) == 0: 114 logging.info('Did not find "%s"!', term) 115 raise error.TestFail('Touch firmware did not attempt update.') 116 117 def run_once(self, input_type='touchpad'): 118 """Entry point of this test.""" 119 if not self.player.has(input_type): 120 raise error.TestError('No %s found on this device!' % input_type) 121 122 # Skip run on invalid touch inputs. 123 if self._platform in self._INVALID_BOARDS: 124 logging.info('This touchpad is not supported for this test.') 125 return 126 127 self._check_updates(input_type) 128