1#!/usr/bin/env python 2# Copyright 2016 The Chromium Authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6# pylint: disable=protected-access 7""" 8Unit tests for the contents of find_usb_devices.py. 9 10Device tree for these tests is as follows: 11Bus 001: 121: Device 011 "foo" 132: Device 012 "bar" 143: Device 013 "baz" 15 16Bus 002: 171: Device 011 "quux" 182: Device 020 "My Test HUB" #hub 1 192:1: Device 021 "usb_device_p7_h1_t0" #physical port 7 on hub 1, on ttyUSB0 202:3: Device 022 "usb_device_p5_h1_t1" #physical port 5 on hub 1, on ttyUSB1 212:4: Device 023 "My Test Internal HUB" #internal section of hub 1 222:4:2: Device 024 "usb_device_p3_h1_t2" #physical port 3 on hub 1, on ttyUSB2 232:4:3: Device 026 "Not a Battery Monitor" #physical port 1 on hub 1, on ttyUSB3 242:4:4: Device 025 "usb_device_p1_h1_t3" #physical port 1 on hub 1, on ttyUSB3 253: Device 100 "My Test HUB" #hub 2 263:4: Device 101 "My Test Internal HUB" #internal section of hub 2 273:4:4: Device 102 "usb_device_p1_h2_t4" #physical port 1 on hub 2, on ttyusb4 28""" 29 30import logging 31import unittest 32 33from devil import devil_env 34from devil.utils import find_usb_devices 35from devil.utils import lsusb 36from devil.utils import usb_hubs 37 38with devil_env.SysPath(devil_env.PYMOCK_PATH): 39 import mock # pylint: disable=import-error 40 41# Output of lsusb.lsusb(). 42# We just test that the dictionary is working by creating an 43# "ID number" equal to (bus_num*1000)+device_num and seeing if 44# it is picked up correctly. Also we test the description 45 46DEVLIST = [(1, 11, 'foo'), (1, 12, 'bar'), (1, 13, 'baz'), (2, 11, 'quux'), 47 (2, 20, 'My Test HUB'), (2, 21, 'ID 0403:6001 usb_device_p7_h1_t0'), 48 (2, 22, 'ID 0403:6001 usb_device_p5_h1_t1'), 49 (2, 23, 'My Test Internal HUB'), 50 (2, 24, 'ID 0403:6001 usb_device_p3_h1_t2'), 51 (2, 25, 'ID 0403:6001 usb_device_p1_h1_t3'), 52 (2, 26, 'Not a Battery Monitor'), (2, 100, 'My Test HUB'), 53 (2, 101, 'My Test Internal HUB'), 54 (2, 102, 'ID 0403:6001 usb_device_p1_h1_t4')] 55 56LSUSB_OUTPUT = [{ 57 'bus': b, 58 'device': d, 59 'desc': t, 60 'id': (1000 * b) + d 61} for (b, d, t) in DEVLIST] 62 63# Note: "Lev", "Cnt", "Spd", and "MxCh" are not used by parser, 64# so we just leave them as zeros here. Also note that the port 65# numbers reported here start at 0, so they're 1 less than the 66# port numbers reported elsewhere. 67USB_DEVICES_OUTPUT = ''' 68T: Bus=01 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 11 Spd=000 MxCh=00 69S: SerialNumber=FooSerial 70T: Bus=01 Lev=00 Prnt=00 Port=01 Cnt=00 Dev#= 12 Spd=000 MxCh=00 71S: SerialNumber=BarSerial 72T: Bus=01 Lev=00 Prnt=00 Port=02 Cnt=00 Dev#= 13 Spd=000 MxCh=00 73S: SerialNumber=BazSerial 74 75T: Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 11 Spd=000 MxCh=00 76 77T: Bus=02 Lev=00 Prnt=00 Port=01 Cnt=00 Dev#= 20 Spd=000 MxCh=00 78T: Bus=02 Lev=00 Prnt=20 Port=00 Cnt=00 Dev#= 21 Spd=000 MxCh=00 79S: SerialNumber=UsbDevice0 80T: Bus=02 Lev=00 Prnt=20 Port=02 Cnt=00 Dev#= 22 Spd=000 MxCh=00 81S: SerialNumber=UsbDevice1 82T: Bus=02 Lev=00 Prnt=20 Port=03 Cnt=00 Dev#= 23 Spd=000 MxCh=00 83T: Bus=02 Lev=00 Prnt=23 Port=01 Cnt=00 Dev#= 24 Spd=000 MxCh=00 84S: SerialNumber=UsbDevice2 85T: Bus=02 Lev=00 Prnt=23 Port=03 Cnt=00 Dev#= 25 Spd=000 MxCh=00 86S: SerialNumber=UsbDevice3 87T: Bus=02 Lev=00 Prnt=23 Port=02 Cnt=00 Dev#= 26 Spd=000 MxCh=00 88 89T: Bus=02 Lev=00 Prnt=00 Port=02 Cnt=00 Dev#=100 Spd=000 MxCh=00 90T: Bus=02 Lev=00 Prnt=100 Port=03 Cnt=00 Dev#=101 Spd=000 MxCh=00 91T: Bus=02 Lev=00 Prnt=101 Port=03 Cnt=00 Dev#=102 Spd=000 MxCh=00 92''' 93 94RAW_LSUSB_OUTPUT = ''' 95Bus 001 Device 011: FAST foo 96Bus 001 Device 012: FAST bar 97Bus 001 Device 013: baz 98Bus 002 Device 011: quux 99Bus 002 Device 020: My Test HUB 100Bus 002 Device 021: ID 0403:6001 usb_device_p7_h1_t0 101Bus 002 Device 022: ID 0403:6001 usb_device_p5_h1_t1 102Bus 002 Device 023: My Test Internal HUB 103Bus 002 Device 024: ID 0403:6001 usb_device_p3_h1_t2 104Bus 002 Device 025: ID 0403:6001 usb_device_p1_h1_t3 105Bus 002 Device 026: Not a Battery Monitor 106Bus 002 Device 100: My Test HUB 107Bus 002 Device 101: My Test Internal HUB 108Bus 002 Device 102: ID 0403:6001 usb_device_p1_h1_t4 109''' 110 111LIST_TTY_OUTPUT = ''' 112ttyUSB0 113Something-else-0 114ttyUSB1 115ttyUSB2 116Something-else-1 117ttyUSB3 118ttyUSB4 119Something-else-2 120ttyUSB5 121''' 122 123# Note: The real output will have multiple lines with 124# ATTRS{busnum} and ATTRS{devnum}, but only the first 125# one counts. Thus the test output duplicates this. 126UDEVADM_USBTTY0_OUTPUT = ''' 127ATTRS{busnum}=="2" 128ATTRS{devnum}=="21" 129ATTRS{busnum}=="0" 130ATTRS{devnum}=="0" 131''' 132 133UDEVADM_USBTTY1_OUTPUT = ''' 134ATTRS{busnum}=="2" 135ATTRS{devnum}=="22" 136ATTRS{busnum}=="0" 137ATTRS{devnum}=="0" 138''' 139 140UDEVADM_USBTTY2_OUTPUT = ''' 141ATTRS{busnum}=="2" 142ATTRS{devnum}=="24" 143ATTRS{busnum}=="0" 144ATTRS{devnum}=="0" 145''' 146 147UDEVADM_USBTTY3_OUTPUT = ''' 148ATTRS{busnum}=="2" 149ATTRS{devnum}=="25" 150ATTRS{busnum}=="0" 151ATTRS{devnum}=="0" 152''' 153 154UDEVADM_USBTTY4_OUTPUT = ''' 155ATTRS{busnum}=="2" 156ATTRS{devnum}=="102" 157ATTRS{busnum}=="0" 158ATTRS{devnum}=="0" 159''' 160 161UDEVADM_USBTTY5_OUTPUT = ''' 162ATTRS{busnum}=="2" 163ATTRS{devnum}=="26" 164ATTRS{busnum}=="0" 165ATTRS{devnum}=="0" 166''' 167 168UDEVADM_OUTPUT_DICT = { 169 'ttyUSB0': UDEVADM_USBTTY0_OUTPUT, 170 'ttyUSB1': UDEVADM_USBTTY1_OUTPUT, 171 'ttyUSB2': UDEVADM_USBTTY2_OUTPUT, 172 'ttyUSB3': UDEVADM_USBTTY3_OUTPUT, 173 'ttyUSB4': UDEVADM_USBTTY4_OUTPUT, 174 'ttyUSB5': UDEVADM_USBTTY5_OUTPUT 175} 176 177 178# Identification criteria for Plugable 7-Port Hub 179def isTestHub(node): 180 """Check if a node is a Plugable 7-Port Hub 181 (Model USB2-HUB7BC) 182 The topology of this device is a 4-port hub, 183 with another 4-port hub connected on port 4. 184 """ 185 if not isinstance(node, find_usb_devices.USBDeviceNode): 186 return False 187 if 'Test HUB' not in node.desc: 188 return False 189 if not node.HasPort(4): 190 return False 191 return 'Test Internal HUB' in node.PortToDevice(4).desc 192 193 194TEST_HUB = usb_hubs.HubType(isTestHub, { 195 1: 7, 196 2: 6, 197 3: 5, 198 4: { 199 1: 4, 200 2: 3, 201 3: 2, 202 4: 1 203 } 204}) 205 206 207class USBScriptTest(unittest.TestCase): 208 def setUp(self): 209 find_usb_devices._GetTtyUSBInfo = mock.Mock( 210 side_effect=lambda x: UDEVADM_OUTPUT_DICT[x]) 211 find_usb_devices._GetParsedLSUSBOutput = mock.Mock( 212 return_value=LSUSB_OUTPUT) 213 find_usb_devices._GetUSBDevicesOutput = mock.Mock( 214 return_value=USB_DEVICES_OUTPUT) 215 find_usb_devices._GetCommList = mock.Mock(return_value=LIST_TTY_OUTPUT) 216 lsusb.raw_lsusb = mock.Mock(return_value=RAW_LSUSB_OUTPUT) 217 218 def testGetTTYDevices(self): 219 pp = find_usb_devices.GetAllPhysicalPortToTTYMaps([TEST_HUB]) 220 result = list(pp) 221 self.assertEquals(result[0], { 222 7: 'ttyUSB0', 223 5: 'ttyUSB1', 224 3: 'ttyUSB2', 225 2: 'ttyUSB5', 226 1: 'ttyUSB3' 227 }) 228 self.assertEquals(result[1], {1: 'ttyUSB4'}) 229 230 def testGetPortDeviceMapping(self): 231 pp = find_usb_devices.GetAllPhysicalPortToBusDeviceMaps([TEST_HUB]) 232 result = list(pp) 233 self.assertEquals(result[0], { 234 7: (2, 21), 235 5: (2, 22), 236 3: (2, 24), 237 2: (2, 26), 238 1: (2, 25) 239 }) 240 self.assertEquals(result[1], {1: (2, 102)}) 241 242 def testGetSerialMapping(self): 243 pp = find_usb_devices.GetAllPhysicalPortToSerialMaps([TEST_HUB]) 244 result = list(pp) 245 self.assertEquals(result[0], { 246 7: 'UsbDevice0', 247 5: 'UsbDevice1', 248 3: 'UsbDevice2', 249 1: 'UsbDevice3' 250 }) 251 self.assertEquals(result[1], {}) 252 253 def testFastDeviceDescriptions(self): 254 bd = find_usb_devices.GetBusNumberToDeviceTreeMap() 255 dev_foo = bd[1].FindDeviceNumber(11) 256 dev_bar = bd[1].FindDeviceNumber(12) 257 dev_usb_device_p7_h1_t0 = bd[2].FindDeviceNumber(21) 258 self.assertEquals(dev_foo.desc, 'FAST foo') 259 self.assertEquals(dev_bar.desc, 'FAST bar') 260 self.assertEquals(dev_usb_device_p7_h1_t0.desc, 261 'ID 0403:6001 usb_device_p7_h1_t0') 262 263 def testDeviceDescriptions(self): 264 bd = find_usb_devices.GetBusNumberToDeviceTreeMap(fast=False) 265 dev_foo = bd[1].FindDeviceNumber(11) 266 dev_bar = bd[1].FindDeviceNumber(12) 267 dev_usb_device_p7_h1_t0 = bd[2].FindDeviceNumber(21) 268 self.assertEquals(dev_foo.desc, 'foo') 269 self.assertEquals(dev_bar.desc, 'bar') 270 self.assertEquals(dev_usb_device_p7_h1_t0.desc, 271 'ID 0403:6001 usb_device_p7_h1_t0') 272 273 def testDeviceInformation(self): 274 bd = find_usb_devices.GetBusNumberToDeviceTreeMap(fast=False) 275 dev_foo = bd[1].FindDeviceNumber(11) 276 dev_bar = bd[1].FindDeviceNumber(12) 277 dev_usb_device_p7_h1_t0 = bd[2].FindDeviceNumber(21) 278 self.assertEquals(dev_foo.info['id'], 1011) 279 self.assertEquals(dev_bar.info['id'], 1012) 280 self.assertEquals(dev_usb_device_p7_h1_t0.info['id'], 2021) 281 282 def testSerialNumber(self): 283 bd = find_usb_devices.GetBusNumberToDeviceTreeMap(fast=False) 284 dev_foo = bd[1].FindDeviceNumber(11) 285 dev_bar = bd[1].FindDeviceNumber(12) 286 dev_usb_device_p7_h1_t0 = bd[2].FindDeviceNumber(21) 287 self.assertEquals(dev_foo.serial, 'FooSerial') 288 self.assertEquals(dev_bar.serial, 'BarSerial') 289 self.assertEquals(dev_usb_device_p7_h1_t0.serial, 'UsbDevice0') 290 291 292if __name__ == "__main__": 293 logging.getLogger().setLevel(logging.DEBUG) 294 unittest.main(verbosity=2) 295