| # Copyright (c) 2015 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| import logging |
| import unittest |
| from array import array |
| |
| import common |
| from autotest_lib.client.cros.cellular.mbim_compliance.usb_descriptors \ |
| import * |
| |
| |
| class TestDescriptor(Descriptor): |
| """ Descriptor for unit testing. """ |
| DESCRIPTOR_TYPE = 0xAA |
| DESCRIPTOR_SUBTYPE = 0xBB |
| _FIELDS = (('B', 'bLength'), |
| ('B', 'bDescriptorType'), |
| ('B', 'bDescriptorSubtype')) |
| |
| |
| class DescriptorTestCase(unittest.TestCase): |
| """ Test cases for verifying Descriptor classes and DescriptorParser. """ |
| |
| |
| def test_fields_not_defined(self): |
| """ |
| Verifies that an excepion is raised when constructing a Descriptor |
| subclass that does not define a _FIELDS attribute. |
| """ |
| with self.assertRaisesRegexp( |
| mbim_errors.MBIMComplianceFrameworkError, |
| 'DescriptorFieldsNotDefined must define a _FIELDS attribute$'): |
| class DescriptorFieldsNotDefined(Descriptor): |
| """ Descriptor without _FIELDS attribute. """ |
| pass |
| |
| |
| def test_descriptor_type_not_defined(self): |
| """ |
| Verifies that it is OK to construct a Descriptor subclass that does not |
| define a DESCRIPTOR_TYPE attribute. |
| """ |
| class DescriptorTypeNotDefined(Descriptor): |
| """ Descriptor without DESCRIPTOR_TYPE attribute. """ |
| _FIELDS = (('B', 'bLength'), ('B', 'bDescriptorType')) |
| |
| descriptor_data = array('B', [0x02, 0xAA]) |
| descriptor = DescriptorTypeNotDefined(descriptor_data) |
| self.assertEqual(2, descriptor.bLength) |
| self.assertEqual(0xAA, descriptor.bDescriptorType) |
| self.assertEqual(descriptor_data, descriptor.data) |
| |
| |
| def test_descriptor_type_mismatch(self): |
| """ |
| Verifies that an exception is raised when constructing a Descriptor |
| subclass from raw descriptor data with a descriptor type that differs |
| from the value specified by the DESCRIPTOR_TYPE attribute of the |
| subclass. |
| """ |
| with self.assertRaisesRegexp( |
| mbim_errors.MBIMComplianceFrameworkError, |
| '^Expected descriptor type 0xAA, got 0xBB$'): |
| descriptor = TestDescriptor(array('B', [0x03, 0xBB, 0xBB])) |
| |
| |
| def test_descriptor_subtype_mismatch(self): |
| """ |
| Verifies that an exception is raised when constructing a Descriptor |
| subclass from raw descriptor data with a descriptor subtype that differs |
| from the value specified by the DESCRIPTOR_SUBTYPE attribute of the |
| subclass. |
| """ |
| with self.assertRaisesRegexp( |
| mbim_errors.MBIMComplianceFrameworkError, |
| '^Expected descriptor subtype 0xBB, got 0xCC$'): |
| descriptor = TestDescriptor(array('B', [0x03, 0xAA, 0xCC])) |
| |
| |
| def test_descriptor_length_mismatch(self): |
| """ |
| Verifies that an exception is raised when constructing a Descriptor |
| subclass from raw descriptor data with a descriptor length that differs |
| from the length of the descriptor data. |
| """ |
| with self.assertRaisesRegexp( |
| mbim_errors.MBIMComplianceFrameworkError, |
| '^Expected descriptor length 3, got 1$'): |
| descriptor = TestDescriptor(array('B', [0x01, 0xAA, 0xBB])) |
| |
| with self.assertRaisesRegexp( |
| mbim_errors.MBIMComplianceFrameworkError, |
| '^Expected descriptor length 3, got 4$'): |
| descriptor = TestDescriptor(array('B', [0x04, 0xAA, 0xBB])) |
| |
| |
| def test_descriptor_data_less_than_total_size_of_fields(self): |
| """ |
| Verifies that an exception is raised when constructing a Descriptor |
| subclass from raw descriptor data of length less than the total size of |
| fields specified by the _FIELDS attribute. |
| """ |
| with self.assertRaisesRegexp( |
| mbim_errors.MBIMComplianceFrameworkError, |
| '^Expected 3 or more bytes of descriptor data, got 1$'): |
| descriptor = TestDescriptor(array('B', [0x03])) |
| |
| |
| def test_descriptor_data_more_than_total_size_of_fields(self): |
| """ |
| Verifies that it is OK to construct a Descriptor subclass from raw |
| descriptor data of length more than the total size of fields specified |
| by the _FIELDS attribute. |
| """ |
| descriptor_data = array('B', [0x03, 0xAA, 0xBB]) |
| descriptor = TestDescriptor(descriptor_data) |
| self.assertEqual(3, descriptor.bLength) |
| self.assertEqual(0xAA, descriptor.bDescriptorType) |
| self.assertEqual(descriptor_data, descriptor.data) |
| |
| |
| def test_parsing_unknown_descriptor_type(self): |
| """ |
| Verifies that DescriptorParser returns an instance of UnknownDescriptor |
| when the descriptor type is not specified by any Descriptor subclass. |
| """ |
| descriptor_data = array('B', [0x02, 0xFF]) |
| descriptors = list(DescriptorParser(descriptor_data)) |
| self.assertEqual(1, len(descriptors)) |
| descriptor = descriptors[0] |
| self.assertIsInstance(descriptor, UnknownDescriptor) |
| self.assertEqual(2, descriptor.bLength) |
| self.assertEqual(0xFF, descriptor.bDescriptorType) |
| self.assertEqual(descriptor_data, descriptor.data) |
| |
| |
| def test_parsing_unsupported_descriptor_subtype(self): |
| """ |
| Verifies that DescriptorParser returns an instance of |
| FunctionalDescriptor when the descriptor type is 0x24 but the descriptor |
| subtype is not supported. |
| """ |
| descriptor_data = array('B', [0x03, 0x24, 0xFF]) |
| descriptors = list(DescriptorParser(descriptor_data)) |
| self.assertEqual(1, len(descriptors)) |
| descriptor = descriptors[0] |
| self.assertIsInstance(descriptor, FunctionalDescriptor) |
| self.assertEqual(3, descriptor.bLength) |
| self.assertEqual(0x24, descriptor.bDescriptorType) |
| self.assertEqual(0xFF, descriptor.bDescriptorSubtype) |
| self.assertEqual(descriptor_data, descriptor.data) |
| |
| |
| def test_parsing_descriptors(self): |
| """ |
| Verifies that DescriptorParser returns an instance of an appropriate |
| Descriptor subclass for each descriptor found in the given raw |
| descriptor data. |
| """ |
| descriptor_data = array('B', [0x09, 0x02, 0x5f, 0x00, 0x02, 0x01, 0x04, |
| 0xa0, 0xfa, 0x08, 0x0b, 0x00, 0x02, 0x02, |
| 0x0e, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, |
| 0x01, 0x02, 0x0e, 0x00, 0x05, 0x05, 0x24, |
| 0x00, 0x20, 0x01, 0x0c, 0x24, 0x1b, 0x00, |
| 0x01, 0x00, 0x06, 0x20, 0x80, 0x96, 0x05, |
| 0x00, 0x08, 0x24, 0x1c, 0x00, 0x01, 0x0f, |
| 0x96, 0x05, 0x05, 0x24, 0x06, 0x00, 0x01, |
| 0x07, 0x05, 0x81, 0x03, 0x40, 0x00, 0x05, |
| 0x09, 0x04, 0x01, 0x00, 0x00, 0x0a, 0x00, |
| 0x02, 0x06, 0x09, 0x04, 0x01, 0x01, 0x02, |
| 0x0a, 0x00, 0x02, 0x07, 0x07, 0x05, 0x82, |
| 0x02, 0x00, 0x02, 0x00, 0x07, 0x05, 0x01, |
| 0x02, 0x00, 0x02, 0x00]) |
| parser = DescriptorParser(descriptor_data) |
| |
| descriptor = parser.next() |
| self.assertIsInstance(descriptor, ConfigurationDescriptor) |
| self.assertIsInstance(descriptor, Descriptor) |
| self.assertEquals(9, descriptor.bLength) |
| self.assertEquals(0x02, descriptor.bDescriptorType) |
| self.assertEquals(95, descriptor.wTotalLength) |
| self.assertEquals(2, descriptor.bNumInterfaces) |
| self.assertEquals(1, descriptor.bConfigurationValue) |
| self.assertEquals(4, descriptor.iConfiguration) |
| self.assertEquals(0xA0, descriptor.bmAttributes) |
| self.assertEquals(250, descriptor.bMaxPower) |
| self.assertEqual(array('B', [0x09, 0x02, 0x5f, 0x00, 0x02, 0x01, 0x04, |
| 0xa0, 0xfa]), |
| descriptor.data) |
| |
| descriptor = parser.next() |
| self.assertIsInstance(descriptor, InterfaceAssociationDescriptor) |
| self.assertIsInstance(descriptor, Descriptor) |
| self.assertEquals(8, descriptor.bLength) |
| self.assertEquals(0x0B, descriptor.bDescriptorType) |
| self.assertEquals(0, descriptor.bFirstInterface) |
| self.assertEquals(2, descriptor.bInterfaceCount) |
| self.assertEquals(0x02, descriptor.bFunctionClass) |
| self.assertEquals(0x0E, descriptor.bFunctionSubClass) |
| self.assertEquals(0x00, descriptor.bFunctionProtocol) |
| self.assertEquals(0, descriptor.iFunction) |
| self.assertEqual(array('B', [0x08, 0x0b, 0x00, 0x02, 0x02, 0x0e, 0x00, |
| 0x00]), |
| descriptor.data) |
| |
| descriptor = parser.next() |
| self.assertIsInstance(descriptor, InterfaceDescriptor) |
| self.assertIsInstance(descriptor, Descriptor) |
| self.assertEquals(9, descriptor.bLength) |
| self.assertEquals(0x04, descriptor.bDescriptorType) |
| self.assertEquals(0, descriptor.bInterfaceNumber) |
| self.assertEquals(0, descriptor.bAlternateSetting) |
| self.assertEquals(1, descriptor.bNumEndpoints) |
| self.assertEquals(0x02, descriptor.bInterfaceClass) |
| self.assertEquals(0x0E, descriptor.bInterfaceSubClass) |
| self.assertEquals(0x00, descriptor.bInterfaceProtocol) |
| self.assertEquals(5, descriptor.iInterface) |
| self.assertEqual(array('B', [0x09, 0x04, 0x00, 0x00, 0x01, 0x02, 0x0e, |
| 0x00, 0x05]), |
| descriptor.data) |
| |
| descriptor = parser.next() |
| self.assertIsInstance(descriptor, HeaderFunctionalDescriptor) |
| self.assertIsInstance(descriptor, FunctionalDescriptor) |
| self.assertIsInstance(descriptor, Descriptor) |
| self.assertEquals(5, descriptor.bLength) |
| self.assertEquals(0x24, descriptor.bDescriptorType) |
| self.assertEquals(0x00, descriptor.bDescriptorSubtype) |
| self.assertEquals(0x120, descriptor.bcdCDC) |
| self.assertEqual(array('B', [0x05, 0x24, 0x00, 0x20, 0x01]), |
| descriptor.data) |
| |
| descriptor = parser.next() |
| self.assertIsInstance(descriptor, MBIMFunctionalDescriptor) |
| self.assertIsInstance(descriptor, FunctionalDescriptor) |
| self.assertIsInstance(descriptor, Descriptor) |
| self.assertEquals(12, descriptor.bLength) |
| self.assertEquals(0x24, descriptor.bDescriptorType) |
| self.assertEquals(0x1B, descriptor.bDescriptorSubtype) |
| self.assertEquals(0x100, descriptor.bcdMBIMVersion) |
| self.assertEquals(1536, descriptor.wMaxControlMessage) |
| self.assertEquals(32, descriptor.bNumberFilters) |
| self.assertEquals(128, descriptor.bMaxFilterSize) |
| self.assertEquals(1430, descriptor.wMaxSegmentSize) |
| self.assertEquals(0x00, descriptor.bmNetworkCapabilities) |
| self.assertEqual(array('B', [0x0c, 0x24, 0x1b, 0x00, 0x01, 0x00, 0x06, |
| 0x20, 0x80, 0x96, 0x05, 0x00]), |
| descriptor.data) |
| |
| descriptor = parser.next() |
| self.assertIsInstance(descriptor, MBIMExtendedFunctionalDescriptor) |
| self.assertIsInstance(descriptor, FunctionalDescriptor) |
| self.assertIsInstance(descriptor, Descriptor) |
| self.assertEquals(8, descriptor.bLength) |
| self.assertEquals(0x24, descriptor.bDescriptorType) |
| self.assertEquals(0x1C, descriptor.bDescriptorSubtype) |
| self.assertEquals(0x100, descriptor.bcdMBIMExtendedVersion) |
| self.assertEquals(15, descriptor.bMaxOutstandingCommandMessages) |
| self.assertEquals(1430, descriptor.wMTU) |
| self.assertEqual(array('B', [0x08, 0x24, 0x1c, 0x00, 0x01, 0x0f, 0x96, |
| 0x05]), |
| descriptor.data) |
| |
| descriptor = parser.next() |
| self.assertIsInstance(descriptor, UnionFunctionalDescriptor) |
| self.assertIsInstance(descriptor, FunctionalDescriptor) |
| self.assertIsInstance(descriptor, Descriptor) |
| self.assertEquals(5, descriptor.bLength) |
| self.assertEquals(0x24, descriptor.bDescriptorType) |
| self.assertEquals(0x06, descriptor.bDescriptorSubtype) |
| self.assertEquals(0, descriptor.bControlInterface) |
| self.assertEquals(1, descriptor.bSubordinateInterface0) |
| self.assertEqual(array('B', [0x05, 0x24, 0x06, 0x00, 0x01]), |
| descriptor.data) |
| |
| descriptor = parser.next() |
| self.assertIsInstance(descriptor, EndpointDescriptor) |
| self.assertIsInstance(descriptor, Descriptor) |
| self.assertEquals(7, descriptor.bLength) |
| self.assertEquals(0x05, descriptor.bDescriptorType) |
| self.assertEquals(0x81, descriptor.bEndpointAddress) |
| self.assertEquals(0x03, descriptor.bmAttributes) |
| self.assertEquals(64, descriptor.wMaxPacketSize) |
| self.assertEquals(5, descriptor.bInterval) |
| self.assertEqual(array('B', [0x07, 0x05, 0x81, 0x03, 0x40, 0x00, 0x05]), |
| descriptor.data) |
| |
| descriptor = parser.next() |
| self.assertIsInstance(descriptor, InterfaceDescriptor) |
| self.assertIsInstance(descriptor, Descriptor) |
| self.assertEquals(9, descriptor.bLength) |
| self.assertEquals(0x04, descriptor.bDescriptorType) |
| self.assertEquals(1, descriptor.bInterfaceNumber) |
| self.assertEquals(0, descriptor.bAlternateSetting) |
| self.assertEquals(0, descriptor.bNumEndpoints) |
| self.assertEquals(0x0A, descriptor.bInterfaceClass) |
| self.assertEquals(0x00, descriptor.bInterfaceSubClass) |
| self.assertEquals(0x02, descriptor.bInterfaceProtocol) |
| self.assertEquals(6, descriptor.iInterface) |
| self.assertEqual(array('B', [0x09, 0x04, 0x01, 0x00, 0x00, 0x0a, 0x00, |
| 0x02, 0x06]), |
| descriptor.data) |
| |
| descriptor = parser.next() |
| self.assertIsInstance(descriptor, InterfaceDescriptor) |
| self.assertIsInstance(descriptor, Descriptor) |
| self.assertEquals(9, descriptor.bLength) |
| self.assertEquals(0x04, descriptor.bDescriptorType) |
| self.assertEquals(1, descriptor.bInterfaceNumber) |
| self.assertEquals(1, descriptor.bAlternateSetting) |
| self.assertEquals(2, descriptor.bNumEndpoints) |
| self.assertEquals(0x0A, descriptor.bInterfaceClass) |
| self.assertEquals(0x00, descriptor.bInterfaceSubClass) |
| self.assertEquals(0x02, descriptor.bInterfaceProtocol) |
| self.assertEquals(7, descriptor.iInterface) |
| self.assertEqual(array('B', [0x09, 0x04, 0x01, 0x01, 0x02, 0x0a, 0x00, |
| 0x02, 0x07]), |
| descriptor.data) |
| |
| descriptor = parser.next() |
| self.assertIsInstance(descriptor, EndpointDescriptor) |
| self.assertIsInstance(descriptor, Descriptor) |
| self.assertEquals(7, descriptor.bLength) |
| self.assertEquals(0x05, descriptor.bDescriptorType) |
| self.assertEquals(0x82, descriptor.bEndpointAddress) |
| self.assertEquals(0x02, descriptor.bmAttributes) |
| self.assertEquals(512, descriptor.wMaxPacketSize) |
| self.assertEquals(0, descriptor.bInterval) |
| self.assertEqual(array('B', [0x07, 0x05, 0x82, 0x02, 0x00, 0x02, 0x00]), |
| descriptor.data) |
| |
| descriptor = parser.next() |
| self.assertIsInstance(descriptor, EndpointDescriptor) |
| self.assertIsInstance(descriptor, Descriptor) |
| self.assertEquals(7, descriptor.bLength) |
| self.assertEquals(0x05, descriptor.bDescriptorType) |
| self.assertEquals(0x01, descriptor.bEndpointAddress) |
| self.assertEquals(0x02, descriptor.bmAttributes) |
| self.assertEquals(512, descriptor.wMaxPacketSize) |
| self.assertEquals(0, descriptor.bInterval) |
| self.assertEqual(array('B', [0x07, 0x05, 0x01, 0x02, 0x00, 0x02, 0x00]), |
| descriptor.data) |
| |
| with self.assertRaises(StopIteration): |
| descriptor = parser.next() |
| |
| |
| if __name__ == '__main__': |
| logging.basicConfig(level=logging.DEBUG) |
| unittest.main() |