1# Copyright (C) 2024 The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15import subprocess 16import unittest 17from unittest import mock 18 19from atest import atest_utils 20from atest import usb_speed_detect as usb 21 22 23class UsbIgnoredSpeedPatterns(unittest.TestCase): 24 25 def _usb_speed_assert_no_warning(self, negotiated_speed, max_speed): 26 """Parametrized test to verify whether a usb speed warning is printed.""" 27 warning = usb.verify_and_print_usb_speed_warning( 28 device_ids=usb.DeviceIds('', '', '', '', ''), 29 negotiated_speed=negotiated_speed, 30 max_speed=max_speed, 31 ) 32 33 self.assertFalse(warning) 34 35 def test_verify_print_speed_unknown_speed_doesnt_print(self): 36 self._usb_speed_assert_no_warning(0, 0) 37 38 def test_verify_print_speed_low_speed_doesnt_print(self): 39 self._usb_speed_assert_no_warning(480, 480) 40 41 def test_verify_print_speed_expected_speed_doesnt_print(self): 42 self._usb_speed_assert_no_warning(5000, 5000) 43 44 def test_verify_print_speed_high_speed_doesnt_print(self): 45 self._usb_speed_assert_no_warning(5000, 10000) 46 47 48class UsbSpeedDetectTest(unittest.TestCase): 49 50 def test_verify_print_speed_slow_speed_prints_warning(self): 51 warning = usb.verify_and_print_usb_speed_warning( 52 device_ids=usb.DeviceIds('', '', '', '', ''), 53 negotiated_speed=480, 54 max_speed=10000, 55 ) 56 57 self.assertTrue(warning) 58 59 60class UdcDriverPatterns(unittest.TestCase): 61 62 def _udc_driver_response( 63 self, attr_name: usb.UsbAttributeName, expected_response: int 64 ): 65 """Parametrized test for handling the responses from the usb driver.""" 66 67 speed = usb.get_udc_driver_usb_device_attribute_speed_value('', attr_name) 68 69 self.assertEqual(speed, expected_response) 70 71 @mock.patch('subprocess.check_output', return_value='not found') 72 def test_udc_driver_unexpected_subprocess_response_returns_0( 73 self, mock_output 74 ): 75 self._udc_driver_response(usb.UsbAttributeName.MAXIMUM_SPEED, 0) 76 77 @mock.patch('subprocess.check_output', return_value='UNKNOWN') 78 def test_udc_driver_unknown_speed_returns_0(self, mock_output): 79 self._udc_driver_response(usb.UsbAttributeName.MAXIMUM_SPEED, 0) 80 81 @mock.patch('subprocess.check_output', return_value='wireless') 82 def test_udc_driver_irrelevant_speed_returns_0(self, mock_output): 83 self._udc_driver_response(usb.UsbAttributeName.NEGOTIATED_SPEED, 0) 84 85 @mock.patch('subprocess.check_output', return_value='high-speed') 86 def test_udc_driver_high_speed_returns_numeric_speed(self, mock_output): 87 self._udc_driver_response(usb.UsbAttributeName.MAXIMUM_SPEED, 480) 88 89 @mock.patch('subprocess.check_output', return_value='high-speed\n') 90 def test_udc_driver_high_speed_output_has_newline_returns_numeric_speed( 91 self, mock_output 92 ): 93 self._udc_driver_response(usb.UsbAttributeName.MAXIMUM_SPEED, 480) 94 95 @mock.patch('subprocess.check_output', return_value='super-speed') 96 def test_udc_driver_super_speed_returns_numeric_speed(self, mock_output): 97 self._udc_driver_response(usb.UsbAttributeName.MAXIMUM_SPEED, 5000) 98 99 @mock.patch('subprocess.check_output', return_value='super-speed-plus') 100 def test_udc_driver_super_speed_plus_returns_numeric_speed(self, mock_output): 101 self._udc_driver_response(usb.UsbAttributeName.MAXIMUM_SPEED, 10000) 102 103 104class DeviceIdentifierPatterns(unittest.TestCase): 105 106 @mock.patch.object(atest_utils, 'has_command', return_value=True) 107 @mock.patch.object(subprocess, 'check_output') 108 def test_get_adb_device_identifiers_port_fwd_device_returns_address( 109 self, mock_output, mock_utils 110 ): 111 def check_output_side_effect_port_fwd_device(*args, **kwargs): 112 for arg in args: 113 if 'ro.serialno' in arg: 114 return 'SERIAL' 115 if all(cmd_arg in ['adb', 'devices'] for cmd_arg in arg): 116 return 'List of devices\nlocalhost:27030 device' 117 if any( 118 cmd_arg 119 in { 120 'ro.product.manufacturer', 121 'ro.product.model', 122 'ro.product.name', 123 } 124 for cmd_arg in arg 125 ): 126 return '' 127 128 mock_output.side_effect = check_output_side_effect_port_fwd_device 129 130 device_ids = usb.get_adb_device_identifiers() 131 132 self.assertEqual(device_ids.address, 'localhost:27030') 133 134 @mock.patch.object(atest_utils, 'has_command', return_value=True) 135 @mock.patch.object(subprocess, 'check_output') 136 def test_get_adb_device_identifiers_tcp_device_returns_address( 137 self, mock_output, mock_utils 138 ): 139 def check_output_side_effect_tcp_device(*args, **kwargs): 140 for arg in args: 141 if 'ro.serialno' in arg: 142 return 'SERIAL' 143 if all(cmd_arg in ['adb', 'devices'] for cmd_arg in arg): 144 return ( 145 '* daemon not running; starting now at tcp:1111\n * daemon ' 146 'started successfully\n List of devices\n33a832a820 device' 147 ) 148 if any( 149 # If check_output is called with any of ('model', 'name', 150 # 'manufacturer', return an empty placeholder value. 151 cmd_arg 152 in { 153 'ro.product.manufacturer', 154 'ro.product.model', 155 'ro.product.name', 156 } 157 for cmd_arg in arg 158 ): 159 return '' 160 161 mock_output.side_effect = check_output_side_effect_tcp_device 162 163 device_ids = usb.get_adb_device_identifiers() 164 165 self.assertEqual(device_ids.address, '33a832a820') 166 167 @mock.patch.object(atest_utils, 'has_command', return_value=True) 168 @mock.patch.object(subprocess, 'check_output') 169 def test_get_adb_device_identifiers_multiple_devices_returns_none( 170 self, mock_output, mock_utils 171 ): 172 def check_output_side_effect_multiple_devices(*args, **kwargs): 173 for arg in args: 174 # When multiple devices are connected, ADB will display an error "adb: 175 # more than one device/emulator" and no serial will be returned. 176 if 'ro.serialno' in arg: 177 return None 178 179 mock_output.side_effect = check_output_side_effect_multiple_devices 180 181 device_ids = usb.get_adb_device_identifiers() 182 183 self.assertIsNone(device_ids) 184