xref: /aosp_15_r20/tools/asuite/atest/usb_speed_detect_unittest.py (revision c2e18aaa1096c836b086f94603d04f4eb9cf37f5)
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