1# Copyright 2017 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"""Check USB device by running linux command on CfM""" 6 7from __future__ import print_function 8 9import logging 10import re 11import time 12import common 13from autotest_lib.client.common_lib.cros.manual import get_usb_devices 14from autotest_lib.client.common_lib.cros import power_cycle_usb_util 15 16CORE_DIR_LINES = 3 17ATRUS = '18d1:8001' 18 19def check_chrome_logfile(dut): 20 """ 21 Get the latest chrome log file. 22 @param dut: The handle of the device under test. 23 @returns: the latest chrome log file 24 """ 25 output = None 26 logging.info('---Get the latest chrome log file') 27 cmd = 'ls -latr /var/log/chrome/chrome' 28 try: 29 output = dut.run(cmd, ignore_status=True).stdout 30 except Exception as e: 31 logging.exception('Fail to run command %s.', cmd) 32 return None 33 logging.info('---cmd: %s', cmd) 34 logging.info('---output: %s', output.lower().strip()) 35 return output 36 37def check_last_reboot(dut): 38 """ 39 Get the last line of eventlog.txt 40 @param dut: The handle of the device under test. 41 @returns: the last line in eventlog.txt 42 """ 43 output = None 44 cmd = 'tail -1 /var/log/eventlog.txt' 45 logging.info('---Get the latest reboot log') 46 try: 47 output = dut.run(cmd, ignore_status=True).stdout 48 except Exception as e: 49 logging.exception('Fail to run command %s.', cmd) 50 return None 51 logging.info('---cmd: %s', cmd) 52 logging.info('---output: %s', output.lower().strip()) 53 return output 54 55def check_is_platform(dut, name): 56 """ 57 Check whether CfM is expected platform. 58 @param dut: The handle of the device under test. 59 @param name: The name of platform 60 @returns: True, if CfM's platform is same as expected. 61 False, if not. 62 """ 63 cmd = "mosys platform name" 64 output = dut.run(cmd, ignore_status=True).stdout.strip() 65 logging.info('---cmd: %s', cmd) 66 logging.info('---output: %s', output.lower()) 67 return output.lower() == name 68 69 70def get_mgmt_ipv4(dut): 71 """ 72 Get mgmt ipv4 address 73 @param dut: The handle of the device under test. Should be initialized in 74 autotest. 75 @return: ipv4 address for mgmt interface. 76 """ 77 cmd = 'ifconfig -a | grep eth0 -A 2 | grep netmask' 78 try: 79 output = dut.run(cmd, ignore_status=True).stdout 80 except Exception as e: 81 logging.exception('Fail to run command %s.', cmd) 82 return None 83 ipv4 = re.findall(r"inet\s*([0-9.]+)\s*netmask.*", output)[0] 84 return ipv4 85 86 87def retrieve_usb_devices(dut): 88 """ 89 Populate output of usb-devices on CfM. 90 @param dut: handle of CfM under test 91 @returns dict of all usb devices detected on CfM. 92 """ 93 usb_devices = (dut.run('usb-devices', ignore_status=True). 94 stdout.strip().split('\n\n')) 95 usb_data = get_usb_devices.extract_usb_data( 96 '\nUSB-Device\n'+'\nUSB-Device\n'.join(usb_devices)) 97 return usb_data 98 99 100def extract_peripherals_for_cfm(usb_data): 101 """ 102 Check CfM has camera, speaker and Mimo connected. 103 @param usb_data: dict extracted from output of "usb-devices" 104 """ 105 peripheral_map = {} 106 get_devices_funcs = (get_usb_devices.get_speakers, 107 get_usb_devices.get_cameras, get_usb_devices.get_display_mimo, 108 get_usb_devices.get_controller_mimo) 109 for get_devices in get_devices_funcs: 110 device_list = get_devices(usb_data) 111 for pid_vid, device_count in device_list.iteritems(): 112 if device_count > 0: 113 peripheral_map[pid_vid] = device_count 114 115 for pid_vid, device_count in peripheral_map.iteritems(): 116 logging.info('---device: %s (%s), count: %d', 117 pid_vid, get_usb_devices.get_device_prod(pid_vid), 118 device_count) 119 120 return peripheral_map 121 122 123def check_peripherals_for_cfm(peripheral_map): 124 """ 125 Check CfM has one and only one camera, 126 one and only one speaker, 127 or one and only one mimo. 128 @param peripheral_map: dict for connected camera, speaker, or mimo. 129 @returns: True if check passes, 130 False if check fails. 131 """ 132 peripherals = peripheral_map.keys() 133 134 type_camera = set(peripherals).intersection(get_usb_devices.CAMERA_LIST) 135 type_speaker = set(peripherals).intersection(get_usb_devices.SPEAKER_LIST) 136 type_controller = set(peripherals).intersection(\ 137 get_usb_devices.TOUCH_CONTROLLER_LIST) 138 type_panel = set(peripherals).intersection(\ 139 get_usb_devices.TOUCH_DISPLAY_LIST) 140 141 # check CfM have one, and only one type camera, huddly and mimo 142 if len(type_camera) == 0: 143 logging.info('No camera is found on CfM.') 144 return False 145 146 if not len(type_camera) == 1: 147 logging.info('More than one type of cameras are found on CfM.') 148 return False 149 150 if len(type_speaker) == 0: 151 logging.info('No speaker is found on CfM.') 152 return False 153 154 if not len(type_speaker) == 1: 155 logging.info('More than one type of speakers are found on CfM.') 156 return False 157 158 if len(type_controller) == 0: 159 logging.info('No controller is found on CfM.') 160 return False 161 162 163 if not len(type_controller) == 1: 164 logging.info('More than one type of controller are found on CfM.') 165 return False 166 167 if len(type_panel) == 0: 168 logging.info('No Display is found on CfM.') 169 return False 170 171 if not len(type_panel) == 1: 172 logging.info('More than one type of displays are found on CfM.') 173 return False 174 175 # check CfM have only one camera, huddly and mimo 176 for pid_vid, device_count in peripheral_map.iteritems(): 177 if device_count > 1: 178 logging.info('Number of device %s connected to CfM : %d', 179 get_usb_devices.get_device_prod(pid_vid), 180 device_count) 181 return False 182 183 return True 184 185 186def check_usb_enumeration(dut, puts): 187 """ 188 Check USB enumeration for devices 189 @param dut: the handle of CfM under test 190 @param puts: the list of peripherals under test 191 @returns True, none if test passes 192 False, errMsg if test test fails 193 """ 194 usb_data = retrieve_usb_devices(dut) 195 if not usb_data: 196 logging.warning('No usb devices found on DUT') 197 return False, 'No usb device found on DUT.' 198 else: 199 usb_device_list = extract_peripherals_for_cfm(usb_data) 200 logging.info('---usb device = %s', usb_device_list) 201 if not set(puts).issubset(set(usb_device_list.keys())): 202 logging.info('Detect device fails for usb enumeration') 203 logging.info('Expect enumerated devices: %s', puts) 204 logging.info('Actual enumerated devices: %s', 205 usb_device_list.keys()) 206 return False, 'Some usb devices are not found.' 207 return True, None 208 209 210def check_usb_interface_initializion(dut, puts): 211 """ 212 Check CfM shows valid interface for all peripherals connected. 213 @param dut: the handle of CfM under test 214 @param puts: the list of peripherals under test 215 @returns True, none if test passes 216 False, errMsg if test test fails 217 """ 218 usb_data = retrieve_usb_devices(dut) 219 for put in puts: 220 number, health = get_usb_devices.is_usb_device_ok(usb_data, put) 221 logging.info('---device interface = %d, %s for %s', 222 number, health, get_usb_devices.get_device_prod(put)) 223 if '0' in health: 224 logging.warning('Device %s has invalid interface', put) 225 return False, 'Device {} has invalid interface.'.format(put) 226 return True, None 227 228 229def clear_core_file(dut): 230 """clear core files""" 231 cmd = "rm -rf /var/spool/crash/*.*" 232 try: 233 dut.run_output(cmd) 234 except Exception as e: 235 logging.exception('Fail to clean core files under ' 236 '/var/spool/crash') 237 logging.exception('Fail to execute %s :', cmd) 238 239 240def check_process_crash(dut, cdlines): 241 """Check whether there is core file.""" 242 cmd = 'ls -latr /var/spool/crash' 243 try: 244 core_files_output = dut.run_output(cmd).splitlines() 245 except Exception as e: 246 logging.exception('Can not find file under /var/spool/crash.') 247 logging.exception('Fail to execute %s:', cmd) 248 return True, CORE_DIR_LINES 249 logging.info('---%s\n---%s', cmd, core_files_output) 250 if len(core_files_output) - cdlines <= 0: 251 logging.info('---length of files: %d', len(core_files_output)) 252 return True, len(core_files_output) 253 else: 254 return False, len(core_files_output) 255 256 257def gpio_usb_test(dut, gpio_list, device_list, pause, board): 258 """ 259 Run GPIO test to powercycle usb port. 260 @parama dut: handler of CfM, 261 @param gpio_list: the list of gpio ports, 262 @param device_list: the list of usb devices, 263 @param pause: time needs to wait before restoring power to usb port, 264 in seconds 265 @param board: board name for CfM 266 @returns True 267 """ 268 for device in device_list: 269 vid, pid = device.split(':') 270 logging.info('---going to powercyle device %s:%s', vid, pid) 271 try: 272 power_cycle_usb_util.power_cycle_usb_vidpid(dut, board, 273 vid, pid, pause) 274 except Exception as e: 275 errmsg = 'Fail to power cycle device.' 276 logging.exception('%s.', errmsg) 277 return False, errmsg 278 279 return True, None 280 281 282def reboot_test(dut, pause): 283 """ 284 Reboot CfM. 285 @parama dut: handler of CfM, 286 @param pause: time needs to wait after issuing reboot command, in seconds, 287 288 """ 289 try: 290 dut.reboot() 291 except Exception as e: 292 logging.exception('Fail to reboot CfM.') 293 return False 294 logging.info('---reboot done') 295 time.sleep(pause) 296 return True 297 298 299 300def find_last_log(dut, speaker): 301 """ 302 Get the lastlast_lines line for log files. 303 @param dut: handler of CfM 304 @param speaker: vidpid if speaker. 305 @returns: the list of string of the last line of logs. 306 """ 307 last_lines = { 308 'messages':[], 309 'chrome':[], 310 'ui': [], 311 'atrus': [] 312 } 313 logging.debug('Get the last line of log file, speaker %s', speaker) 314 try: 315 cmd = "tail -1 /var/log/messages | awk -v N=1 '{print $N}'" 316 last_lines['messages'] = dut.run_output(cmd).strip().split()[0] 317 cmd = "tail -1 /var/log/chrome/chrome | awk -v N=1 '{print $N}'" 318 last_lines['chrome'] = dut.run_output(cmd).strip().split()[0] 319 cmd = "tail -1 /var/log/ui/ui.LATEST | awk -v N=1 '{print $N}'" 320 last_lines['ui']= dut.run_output(cmd) 321 if speaker == ATRUS and check_is_platform(dut, 'guado'): 322 logging.info('---atrus speaker %s connected to CfM', speaker) 323 cmd = 'tail -1 /var/log/atrus.log | awk -v N=1 "{print $N}"' 324 last_lines['atrus'] = dut.run_output(cmd).strip().split()[0] 325 except Exception as e: 326 logging.exception('Fail to get the last line from log files.') 327 for item, timestamp in last_lines.iteritems(): 328 logging.debug('---%s: %s', item, timestamp) 329 return last_lines 330 331 332def collect_log_since_last_check(dut, lastlines, logfile): 333 """Collect log file since last check.""" 334 output = None 335 if logfile == "messages": 336 cmd ='awk \'/{}/,0\' /var/log/messages'.format(lastlines[logfile]) 337 if logfile == "chrome": 338 cmd ='awk \'/{}/,0\' /var/log/chrome/chrome'.format(lastlines[logfile]) 339 if logfile == "ui": 340 cmd ='awk \'/{}/,0\' /var/log/ui/ui.LATEST'.format(lastlines[logfile]) 341 if logfile == 'atrus': 342 cmd ='awk \'/{}/,0\' /var/log/atrus.log'.format(lastlines[logfile]) 343 logging.info('---cmd = %s', cmd) 344 try: 345 output = dut.run_output(cmd).split('\n') 346 except Exception as e: 347 logging.exception('Fail to get output from log files.') 348 logging.info('---length of log: %d', len(output)) 349 if not output: 350 logging.info('--fail to find match log, check the latest log.') 351 352 if not output: 353 if logfile == "messages": 354 cmd ='cat /var/log/messages' 355 if logfile == "chrome": 356 cmd ='cat /var/log/chrome/chrome' 357 if logfile == "ui": 358 cmd ='cat /var/log/ui/ui.LATEST' 359 if logfile == 'atrus': 360 cmd ='cat /var/log/atrus.log' 361 output = dut.run_output(cmd).split('\n') 362 logging.info('---length of log: %d', len(output)) 363 return output 364 365def check_log(dut, timestamp, error_list, checkitem, logfile): 366 """ 367 Check logfile does not contain any element in error_list[checkitem]. 368 """ 369 error_log_list = [] 370 logging.info('---now check log %s in file %s', checkitem, logfile) 371 output = collect_log_since_last_check(dut, timestamp, logfile) 372 for _error in error_list[checkitem]: 373 error_log_list.extend([s for s in output if _error in str(s)]) 374 if not error_log_list: 375 return True, None 376 else: 377 tempmsg = '\n'.join(error_log_list) 378 errmsg = 'Error_Found:in_log_file:{}:{}.'.format(logfile, tempmsg) 379 logging.info('---%s', errmsg) 380 return False, errmsg 381