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