Merge lp:~adeuring/launchpad/hwdb-class-udev-device-7 into lp:launchpad

Proposed by Abel Deuring
Status: Merged
Merged at revision: not available
Proposed branch: lp:~adeuring/launchpad/hwdb-class-udev-device-7
Merge into: lp:launchpad
Diff against target: 1070 lines
2 files modified
lib/canonical/launchpad/scripts/hwdbsubmissions.py (+83/-26)
lib/canonical/launchpad/scripts/tests/test_hwdb_submission_processing.py (+702/-70)
To merge this branch: bzr merge lp:~adeuring/launchpad/hwdb-class-udev-device-7
Reviewer Review Type Date Requested Status
Michael Nelson (community) code Approve
Review via email: mp+13413@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Abel Deuring (adeuring) wrote :

This branch has several small improvements for the HWDB submission
processing script for submissions with udev data:

- it fixes a bug in the udev test data for USB storage devices: The udev
  property DEVTYPE was missing.

  This uncovered a (now fixed) bug in BaseDevice.translateScsiBus()
  Up to now, the detection of a USB storage device pretending to be a
  SCSI device was based on the value "usb" of the property raw_bus of an
  ancestor node of the fake SCSI device, but the real value of
  ancestor.raw_bus for udev submissions is "usb_interface". Since this
  value is not used in submissions with HAL data, there are no bad
  side-effects.

- it defines a new property BaseDevice.is_root_device, implemented in
  the derived classes HALDevice and UdevDevice. There are a few places
  in the code, were the root device needs to be treated specially. Up to
  now, the decision "is this device the root device" was based on a
  comparison of the HAL-specific property "udi".

- it modifies the property BaseDevice.real_bus to properly deal with
  udev submissions. If we have a SCSI device, is now detected by
  comparing the value self.raw_bus with 'scsi' and 'scsi_device'. Again,
  HAL does not use the new value 'scsi_device', so there are no bad side
  effects.

- it adds tests for UdevDevice.real_bus and UdevDevice.translatePciBus()

test: ./bin/test --test=test_hwdb_submission_processing

= Launchpad lint =

Checking for conflicts. and issues in doctests and templates.
Running jslint, xmllint, pyflakes, and pylint.
Using normal rules.

Linting changed files:
  lib/canonical/launchpad/scripts/hwdbsubmissions.py
  lib/canonical/launchpad/scripts/tests/test_hwdb_submission_processing.py

== Pyflakes notices ==

lib/canonical/launchpad/scripts/hwdbsubmissions.py
    22: redefinition of unused 'etree' from line 20

== Pylint notices ==

lib/canonical/launchpad/scripts/hwdbsubmissions.py
    20: [F0401] Unable to import 'xml.etree.cElementTree' (No module
named etree)

The complaint is not related to my changes.

Revision history for this message
Michael Nelson (michael.nelson) wrote :
Download full text (11.4 KiB)

Great! The addition of the is_root_device property makes the code much
more readable.

As usual, just one or two comments below, in particular, one change for which I couldn't see the cause...

Thanks!

> === modified file 'lib/canonical/launchpad/scripts/hwdbsubmissions.py'
> --- lib/canonical/launchpad/scripts/hwdbsubmissions.py 2009-10-15 13:22:14 +0000
> +++ lib/canonical/launchpad/scripts/hwdbsubmissions.py 2009-10-15 13:59:33 +0000
> @@ -1644,7 +1644,7 @@
> return None
> pci_subclass = scsi_controller.pci_subclass
> return self.pci_storage_subclass_hwbus.get(pci_subclass)
> - elif scsi_controller_bus == 'usb':
> + elif scsi_controller_bus in ('usb', 'usb_interface'):
> # USB storage devices have the following HAL device hierarchy:
> # - HAL node for the USB device. info.bus == 'usb_device',
> # device class == 0, device subclass == 0
> @@ -1703,6 +1703,12 @@
> return HWBus.PCI
>
> @property
> + def is_root_device(self):
> + """Return True is this is the root node of all devicese, else False.
> + """
> + raise NotImplementedError
> +
> + @property
> def raw_bus(self):
> """Return the device bus as specified by HAL or udev."""
> raise NotImplementedError
> @@ -1719,11 +1725,11 @@
> if result is not None:
> return result
>
> - if device_bus == 'scsi':
> + if device_bus in ('scsi', 'scsi_device'):
> return self.translateScsiBus()
> elif device_bus == 'pci':
> return self.translatePciBus()
> - elif self.udi == ROOT_UDI:
> + elif self.is_root_device:
> # The computer itself. In Hardy, HAL provides no info.bus
> # for the machine itself; older versions set info.bus to
> # 'unknown', hence it is better to use the machine's
> @@ -1731,7 +1737,7 @@
> return HWBus.SYSTEM
> else:
> self.parser._logWarning(
> - 'Unknown bus %r for device %s' % (device_bus, self.udi))
> + 'Unknown bus %r for device %s' % (device_bus, self.device_id))
> return None
>
> @property
> @@ -2275,6 +2281,11 @@
> return result
> return self.getProperty('info.subsystem')
>
> + @property
> + def is_root_device(self):
> + """See `BaseDevice`."""
> + return self.udi == ROOT_UDI
> +
> def getVendorOrProduct(self, type_):
> """Return the vendor or product of this device.
>
> @@ -2547,7 +2558,7 @@
> # DEVTYPE. DEVTYPE is preferable.
> # The root device has the subsystem/bus value "acpi", which
> # is a bit nonsensical.
> - if self.device_id == UDEV_ROOT_PATH:
> + if self.is_root_device:
> return None
> properties = self.udev['E']
> devtype = properties.get('DEVTYPE')
> @@ -2555,6 +2566,11 @@
> return devtype
> return properties.get('SUBSYSTEM')
>
> + @property
> + def is_root_device(self):
> + """See `BaseDevice`."""
> + return self.udev[...

review: Approve (code)
Revision history for this message
Abel Deuring (adeuring) wrote :
Download full text (9.2 KiB)

Hi Michael,

thanks for your review!

> Great! The addition of the is_root_device property makes the code much
> more readable.
>
> As usual, just one or two comments below, in particular, one change for which
> I couldn't see the cause...
>
> Thanks!
>
> > === modified file 'lib/canonical/launchpad/scripts/hwdbsubmissions.py'
> > --- lib/canonical/launchpad/scripts/hwdbsubmissions.py 2009-10-15
> 13:22:14 +0000
> > +++ lib/canonical/launchpad/scripts/hwdbsubmissions.py 2009-10-15
> 13:59:33 +0000
> > @@ -1644,7 +1644,7 @@
> > return None
> > pci_subclass = scsi_controller.pci_subclass
> > return self.pci_storage_subclass_hwbus.get(pci_subclass)
> > - elif scsi_controller_bus == 'usb':
> > + elif scsi_controller_bus in ('usb', 'usb_interface'):
> > # USB storage devices have the following HAL device hierarchy:
> > # - HAL node for the USB device. info.bus == 'usb_device',
> > # device class == 0, device subclass == 0
> > @@ -1703,6 +1703,12 @@
> > return HWBus.PCI
> >
> > @property
> > + def is_root_device(self):
> > + """Return True is this is the root node of all devicese, else
> False.
> > + """
> > + raise NotImplementedError
> > +
> > + @property
> > def raw_bus(self):
> > """Return the device bus as specified by HAL or udev."""
> > raise NotImplementedError
> > @@ -1719,11 +1725,11 @@
> > if result is not None:
> > return result
> >
> > - if device_bus == 'scsi':
> > + if device_bus in ('scsi', 'scsi_device'):
> > return self.translateScsiBus()
> > elif device_bus == 'pci':
> > return self.translatePciBus()
> > - elif self.udi == ROOT_UDI:
> > + elif self.is_root_device:
> > # The computer itself. In Hardy, HAL provides no info.bus
> > # for the machine itself; older versions set info.bus to
> > # 'unknown', hence it is better to use the machine's
> > @@ -1731,7 +1737,7 @@
> > return HWBus.SYSTEM
> > else:
> > self.parser._logWarning(
> > - 'Unknown bus %r for device %s' % (device_bus, self.udi))
> > + 'Unknown bus %r for device %s' % (device_bus,
> self.device_id))
> > return None
> >
> > @property
> > @@ -2275,6 +2281,11 @@
> > return result
> > return self.getProperty('info.subsystem')
> >
> > + @property
> > + def is_root_device(self):
> > + """See `BaseDevice`."""
> > + return self.udi == ROOT_UDI
> > +
> > def getVendorOrProduct(self, type_):
> > """Return the vendor or product of this device.
> >
> > @@ -2547,7 +2558,7 @@
> > # DEVTYPE. DEVTYPE is preferable.
> > # The root device has the subsystem/bus value "acpi", which
> > # is a bit nonsensical.
> > - if self.device_id == UDEV_ROOT_PATH:
> > + if self.is_root_device:
> > return None
> > properties = self.udev['E']
> > devtype = properties.get('DEVTYPE')
> > @@ -2555,6...

Read more...

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/canonical/launchpad/scripts/hwdbsubmissions.py'
--- lib/canonical/launchpad/scripts/hwdbsubmissions.py 2009-10-13 21:03:31 +0000
+++ lib/canonical/launchpad/scripts/hwdbsubmissions.py 2009-10-15 17:00:35 +0000
@@ -87,12 +87,14 @@
87 'pci': '0x%04x',87 'pci': '0x%04x',
88 'usb_device': '0x%04x',88 'usb_device': '0x%04x',
89 'scsi': '%-8s',89 'scsi': '%-8s',
90 'scsi_device': '%-8s',
90 }91 }
9192
92DB_FORMAT_FOR_PRODUCT_ID = {93DB_FORMAT_FOR_PRODUCT_ID = {
93 'pci': '0x%04x',94 'pci': '0x%04x',
94 'usb_device': '0x%04x',95 'usb_device': '0x%04x',
95 'scsi': '%-16s',96 'scsi': '%-16s',
97 'scsi_device': '%-16s',
96 }98 }
9799
98UDEV_USB_DEVICE_PROPERTIES = set(('DEVTYPE', 'PRODUCT', 'TYPE'))100UDEV_USB_DEVICE_PROPERTIES = set(('DEVTYPE', 'PRODUCT', 'TYPE'))
@@ -1609,6 +1611,11 @@
1609 """The name of the driver contolling this device. May be None."""1611 """The name of the driver contolling this device. May be None."""
1610 raise NotImplementedError1612 raise NotImplementedError
16111613
1614 @property
1615 def scsi_controller(self):
1616 """Return the SCSI host controller for this device."""
1617 raise NotImplementedError
1618
1612 def translateScsiBus(self):1619 def translateScsiBus(self):
1613 """Return the real bus of a device where raw_bus=='scsi'.1620 """Return the real bus of a device where raw_bus=='scsi'.
16141621
@@ -1617,37 +1624,27 @@
1617 for more details. This method determines the real bus1624 for more details. This method determines the real bus
1618 of a device accessed via the kernel's SCSI subsystem.1625 of a device accessed via the kernel's SCSI subsystem.
1619 """1626 """
1620 # While SCSI devices from valid submissions should have a1627 scsi_controller = self.scsi_controller
1621 # parent and a grandparent, we can't be sure for bogus or1628 if scsi_controller is None:
1622 # broken submissions.
1623 parent = self.parent
1624 if parent is None:
1625 self.parser._logWarning(
1626 'Found SCSI device without a parent: %s.' % self.device_id)
1627 return None
1628 grandparent = parent.parent
1629 if grandparent is None:
1630 self.parser._logWarning(
1631 'Found SCSI device without a grandparent: %s.'
1632 % self.device_id)
1633 return None1629 return None
16341630
1635 grandparent_bus = grandparent.raw_bus1631 scsi_controller_bus = scsi_controller.raw_bus
1636 if grandparent_bus == 'pci':1632 if scsi_controller_bus == 'pci':
1637 if (grandparent.pci_class != PCI_CLASS_STORAGE):1633 if (scsi_controller.pci_class != PCI_CLASS_STORAGE):
1638 # This is not a storage class PCI device? This1634 # This is not a storage class PCI device? This
1639 # indicates a bug somewhere in HAL or in the hwdb1635 # indicates a bug somewhere in HAL or in the hwdb
1640 # client, or a fake submission.1636 # client, or a fake submission.
1641 device_class = grandparent.pci_class1637 device_class = scsi_controller.pci_class
1642 self.parser._logWarning(1638 self.parser._logWarning(
1643 'A (possibly fake) SCSI device %s is connected to '1639 'A (possibly fake) SCSI device %s is connected to '
1644 'PCI device %s that has the PCI device class %s; '1640 'PCI device %s that has the PCI device class %s; '
1645 'expected class 1 (storage).'1641 'expected class 1 (storage).'
1646 % (self.device_id, grandparent.device_id, device_class))1642 % (self.device_id, scsi_controller.device_id,
1643 device_class))
1647 return None1644 return None
1648 pci_subclass = grandparent.pci_subclass1645 pci_subclass = scsi_controller.pci_subclass
1649 return self.pci_storage_subclass_hwbus.get(pci_subclass)1646 return self.pci_storage_subclass_hwbus.get(pci_subclass)
1650 elif grandparent_bus == 'usb':1647 elif scsi_controller_bus in ('usb', 'usb_interface'):
1651 # USB storage devices have the following HAL device hierarchy:1648 # USB storage devices have the following HAL device hierarchy:
1652 # - HAL node for the USB device. info.bus == 'usb_device',1649 # - HAL node for the USB device. info.bus == 'usb_device',
1653 # device class == 0, device subclass == 01650 # device class == 0, device subclass == 0
@@ -1706,6 +1703,12 @@
1706 return HWBus.PCI1703 return HWBus.PCI
17071704
1708 @property1705 @property
1706 def is_root_device(self):
1707 """Return True is this is the root node of all devicese, else False.
1708 """
1709 raise NotImplementedError
1710
1711 @property
1709 def raw_bus(self):1712 def raw_bus(self):
1710 """Return the device bus as specified by HAL or udev."""1713 """Return the device bus as specified by HAL or udev."""
1711 raise NotImplementedError1714 raise NotImplementedError
@@ -1722,11 +1725,11 @@
1722 if result is not None:1725 if result is not None:
1723 return result1726 return result
17241727
1725 if device_bus == 'scsi':1728 if device_bus in ('scsi', 'scsi_device'):
1726 return self.translateScsiBus()1729 return self.translateScsiBus()
1727 elif device_bus == 'pci':1730 elif device_bus == 'pci':
1728 return self.translatePciBus()1731 return self.translatePciBus()
1729 elif self.udi == ROOT_UDI:1732 elif self.is_root_device:
1730 # The computer itself. In Hardy, HAL provides no info.bus1733 # The computer itself. In Hardy, HAL provides no info.bus
1731 # for the machine itself; older versions set info.bus to1734 # for the machine itself; older versions set info.bus to
1732 # 'unknown', hence it is better to use the machine's1735 # 'unknown', hence it is better to use the machine's
@@ -1734,7 +1737,7 @@
1734 return HWBus.SYSTEM1737 return HWBus.SYSTEM
1735 else:1738 else:
1736 self.parser._logWarning(1739 self.parser._logWarning(
1737 'Unknown bus %r for device %s' % (device_bus, self.udi))1740 'Unknown bus %r for device %s' % (device_bus, self.device_id))
1738 return None1741 return None
17391742
1740 @property1743 @property
@@ -2278,6 +2281,11 @@
2278 return result2281 return result
2279 return self.getProperty('info.subsystem')2282 return self.getProperty('info.subsystem')
22802283
2284 @property
2285 def is_root_device(self):
2286 """See `BaseDevice`."""
2287 return self.udi == ROOT_UDI
2288
2281 def getVendorOrProduct(self, type_):2289 def getVendorOrProduct(self, type_):
2282 """Return the vendor or product of this device.2290 """Return the vendor or product of this device.
22832291
@@ -2357,6 +2365,27 @@
2357 """See `BaseDevice`."""2365 """See `BaseDevice`."""
2358 return self.getVendorOrProductID('product')2366 return self.getVendorOrProductID('product')
23592367
2368 @property
2369 def scsi_controller(self):
2370 """See `BaseDevice`."""
2371 # While SCSI devices from valid submissions should have a
2372 # parent and a grandparent, we can't be sure for bogus or
2373 # broken submissions.
2374 if self.raw_bus != 'scsi':
2375 return None
2376 parent = self.parent
2377 if parent is None:
2378 self.parser._logWarning(
2379 'Found SCSI device without a parent: %s.' % self.device_id)
2380 return None
2381 grandparent = parent.parent
2382 if grandparent is None:
2383 self.parser._logWarning(
2384 'Found SCSI device without a grandparent: %s.'
2385 % self.device_id)
2386 return None
2387 return grandparent
2388
23602389
2361class UdevDevice(BaseDevice):2390class UdevDevice(BaseDevice):
2362 """The representation of a udev device node."""2391 """The representation of a udev device node."""
@@ -2529,7 +2558,7 @@
2529 # DEVTYPE. DEVTYPE is preferable.2558 # DEVTYPE. DEVTYPE is preferable.
2530 # The root device has the subsystem/bus value "acpi", which2559 # The root device has the subsystem/bus value "acpi", which
2531 # is a bit nonsensical.2560 # is a bit nonsensical.
2532 if self.device_id == UDEV_ROOT_PATH:2561 if self.is_root_device:
2533 return None2562 return None
2534 properties = self.udev['E']2563 properties = self.udev['E']
2535 devtype = properties.get('DEVTYPE')2564 devtype = properties.get('DEVTYPE')
@@ -2537,6 +2566,11 @@
2537 return devtype2566 return devtype
2538 return properties.get('SUBSYSTEM')2567 return properties.get('SUBSYSTEM')
25392568
2569 @property
2570 def is_root_device(self):
2571 """See `BaseDevice`."""
2572 return self.udev['P'] == UDEV_ROOT_PATH
2573
2540 def getVendorOrProduct(self, type_):2574 def getVendorOrProduct(self, type_):
2541 """Return the vendor or product of this device.2575 """Return the vendor or product of this device.
25422576
@@ -2547,7 +2581,7 @@
2547 'Unexpected value of type_: %r' % type_)2581 'Unexpected value of type_: %r' % type_)
25482582
2549 bus = self.raw_bus2583 bus = self.raw_bus
2550 if self.device_id == UDEV_ROOT_PATH:2584 if self.is_root_device:
2551 # udev does not known about any product information for2585 # udev does not known about any product information for
2552 # the root device. We use DMI data instead.2586 # the root device. We use DMI data instead.
2553 return self.root_device_ids[type_]2587 return self.root_device_ids[type_]
@@ -2587,7 +2621,7 @@
2587 'Unexpected value of type_: %r' % type_)2621 'Unexpected value of type_: %r' % type_)
25882622
2589 bus = self.raw_bus2623 bus = self.raw_bus
2590 if self.device_id == UDEV_ROOT_PATH:2624 if self.is_root_device:
2591 # udev does not known about any product information for2625 # udev does not known about any product information for
2592 # the root device. We use DMI data instead.2626 # the root device. We use DMI data instead.
2593 if type_ == 'vendor':2627 if type_ == 'vendor':
@@ -2617,6 +2651,29 @@
2617 """See `BaseDevice`."""2651 """See `BaseDevice`."""
2618 return self.getVendorOrProductID('product')2652 return self.getVendorOrProductID('product')
26192653
2654 @property
2655 def driver_name(self):
2656 """See `BaseDevice`."""
2657 return self.udev['E'].get('DRIVER')
2658
2659 @property
2660 def scsi_controller(self):
2661 """See `BaseDevice`."""
2662 if self.raw_bus != 'scsi_device':
2663 return None
2664
2665 # While SCSI devices from valid submissions should have four
2666 # ancestors, we can't be sure for bogus or broken submissions.
2667 try:
2668 controller = self.parent.parent.parent.parent
2669 except AttributeError:
2670 controller = None
2671 if controller is None:
2672 self.parser._logWarning(
2673 'Found a SCSI device without a sufficient number of '
2674 'ancestors: %s' % self.device_id)
2675 return None
2676 return controller
26202677
2621class ProcessingLoop(object):2678class ProcessingLoop(object):
2622 """An `ITunableLoop` for processing HWDB submissions."""2679 """An `ITunableLoop` for processing HWDB submissions."""
26232680
=== modified file 'lib/canonical/launchpad/scripts/tests/test_hwdb_submission_processing.py'
--- lib/canonical/launchpad/scripts/tests/test_hwdb_submission_processing.py 2009-10-13 21:02:35 +0000
+++ lib/canonical/launchpad/scripts/tests/test_hwdb_submission_processing.py 2009-10-15 17:00:35 +0000
@@ -539,6 +539,214 @@
539 'HAL property info.bus.')539 'HAL property info.bus.')
540540
541541
542 def test_HALDevice_scsi_controller_usb_storage_device(self):
543 """test of HALDevice.scsi_controller.
544
545 The physical device is a USB storage device.
546 """
547 devices = [
548 # The main node of the USB storage device.
549 {
550 'id': 1,
551 'udi': self.UDI_USB_STORAGE,
552 'properties': {
553 'info.bus': ('usb_device', 'str'),
554 },
555 },
556 # The storage interface of the USB device.
557 {
558 'id': 2,
559 'udi': self.UDI_USB_STORAGE_IF0,
560 'properties': {
561 'info.bus': ('usb', 'str'),
562 'info.parent': (self.UDI_USB_STORAGE, 'str'),
563 },
564 },
565 # The fake SCSI host of the storage device. Note that HAL does
566 # _not_ provide the info.bus property.
567 {
568 'id': 3,
569 'udi': self.UDI_USB_STORAGE_SCSI_HOST,
570 'properties': {
571 'info.parent': (self.UDI_USB_STORAGE_IF0, 'str'),
572 },
573 },
574 # The fake SCSI disk.
575 {
576 'id': 3,
577 'udi': self.UDI_USB_STORAGE_SCSI_DEVICE,
578 'properties': {
579 'info.bus': ('scsi', 'str'),
580 'info.parent': (self.UDI_USB_STORAGE_SCSI_HOST, 'str'),
581 },
582 },
583 ]
584 parsed_data = {
585 'hardware': {
586 'hal': {
587 'devices': devices,
588 },
589 },
590 }
591
592 parser = SubmissionParser()
593 parser.buildDeviceList(parsed_data)
594
595 usb_fake_scsi_disk = parser.hal_devices[
596 self.UDI_USB_STORAGE_SCSI_DEVICE]
597 usb_main_device = parser.hal_devices[self.UDI_USB_STORAGE_IF0]
598 self.assertEqual(usb_main_device, usb_fake_scsi_disk.scsi_controller)
599
600 def test_HALDevice_scsi_controller_pci_controller(self):
601 """test of HALDevice.scsi_controller.
602
603 Variant for a SCSI device connected to a PCI controller.
604 """
605 devices = [
606 # The PCI host controller.
607 {
608 'id': 1,
609 'udi': self.UDI_SATA_CONTROLLER,
610 'properties': {
611 'info.bus': ('pci', 'str'),
612 'pci.device_class': (PCI_CLASS_STORAGE, 'int'),
613 'pci.device_subclass': (PCI_SUBCLASS_STORAGE_SATA,
614 'int'),
615 },
616 },
617 # The (fake or real) SCSI host of the storage device.
618 {
619 'id': 2,
620 'udi': self.UDI_SATA_CONTROLLER_SCSI,
621 'properties': {
622 'info.parent': (self.UDI_SATA_CONTROLLER, 'str'),
623 },
624 },
625 # The (possibly fake) SCSI disk.
626 {
627 'id': 3,
628 'udi': self.UDI_SATA_DISK,
629 'properties': {
630 'info.bus': ('scsi', 'str'),
631 'info.parent': (self.UDI_SATA_CONTROLLER_SCSI, 'str'),
632 },
633 },
634 ]
635 parsed_data = {
636 'hardware': {
637 'hal': {
638 'devices': devices,
639 },
640 },
641 }
642
643 parser = SubmissionParser()
644 parser.buildDeviceList(parsed_data)
645
646 scsi_device = parser.hal_devices[self.UDI_SATA_DISK]
647 controller = parser.hal_devices[self.UDI_SATA_CONTROLLER]
648 self.assertEqual(controller, scsi_device.scsi_controller)
649
650 def test_HALDevice_scsi_controller_non_scsi_device(self):
651 """test of HALDevice.scsi_controller.
652
653 Variant for non-SCSI devices.
654 """
655 devices = [
656 {
657 'id': 1,
658 'udi': self.UDI_COMPUTER,
659 'properties': {},
660 },
661 ]
662 parsed_data = {
663 'hardware': {
664 'hal': {
665 'devices': devices,
666 },
667 },
668 }
669
670 parser = SubmissionParser()
671 parser.buildDeviceList(parsed_data)
672
673 device = parser.hal_devices[self.UDI_COMPUTER]
674 self.assertEqual(None, device.scsi_controller)
675
676 def test_HALDevice_scsi_controller_no_grandparent(self):
677 """test of HALDevice.scsi_controller.
678
679 Variant for a SCSI device without a grandparent device.
680 """
681 devices = [
682 # The (fake or real) SCSI host of the storage device.
683 {
684 'id': 1,
685 'udi': self.UDI_SATA_CONTROLLER_SCSI,
686 'properties': {},
687 },
688 # The (possibly fake) SCSI disk.
689 {
690 'id': 2,
691 'udi': self.UDI_SATA_DISK,
692 'properties': {
693 'info.bus': ('scsi', 'str'),
694 'info.parent': (self.UDI_SATA_CONTROLLER_SCSI, 'str'),
695 },
696 },
697 ]
698 parsed_data = {
699 'hardware': {
700 'hal': {
701 'devices': devices,
702 },
703 },
704 }
705
706 parser = SubmissionParser(self.log)
707 parser.submission_key = 'SCSI device without grandparent device'
708 parser.buildDeviceList(parsed_data)
709
710 scsi_device = parser.hal_devices[self.UDI_SATA_DISK]
711 self.assertEqual(None, scsi_device.scsi_controller)
712 self.assertWarningMessage(
713 parser.submission_key,
714 "Found SCSI device without a grandparent: %s."
715 % self.UDI_SATA_DISK)
716
717 def test_HALDevice_scsi_controller_no_parent(self):
718 """test of HALDevice.scsi_controller.
719
720 Variant for a SCSI device without a parent device.
721 """
722 devices = [
723 # The (possibly fake) SCSI disk.
724 {
725 'id': 1,
726 'udi': self.UDI_SATA_DISK,
727 'properties': {
728 'info.bus': ('scsi', 'str'),
729 },
730 },
731 ]
732 parsed_data = {
733 'hardware': {
734 'hal': {
735 'devices': devices,
736 },
737 },
738 }
739
740 parser = SubmissionParser(self.log)
741 parser.submission_key = 'SCSI device without parent device'
742 parser.buildDeviceList(parsed_data)
743
744 scsi_device = parser.hal_devices[self.UDI_SATA_DISK]
745 self.assertEqual(None, scsi_device.scsi_controller)
746 self.assertWarningMessage(
747 parser.submission_key,
748 "Found SCSI device without a parent: %s." % self.UDI_SATA_DISK)
749
542 def testHALDeviceGetRealBus(self):750 def testHALDeviceGetRealBus(self):
543 """Test of HALDevice.real_bus, generic case.751 """Test of HALDevice.real_bus, generic case.
544752
@@ -965,6 +1173,51 @@
965 parser.submission_key,1173 parser.submission_key,
966 "Unknown bus 'nonsense' for device " + self.UDI_PCCARD_DEVICE)1174 "Unknown bus 'nonsense' for device " + self.UDI_PCCARD_DEVICE)
9671175
1176 def test_HALDevice_is_root_device_for_root_device(self):
1177 """Test of HALDevice.is_root_device for the root device."""
1178 devices = [
1179 {
1180 'id': 1,
1181 'udi': self.UDI_COMPUTER,
1182 'properties': {},
1183 },
1184 ]
1185 parsed_data = {
1186 'hardware': {
1187 'hal': {
1188 'devices': devices,
1189 },
1190 },
1191 }
1192
1193 parser = SubmissionParser()
1194 parser.submission_key = 'Test of HALDevice.is_root_device'
1195 parser.buildDeviceList(parsed_data)
1196 self.assertTrue(parser.hal_devices[self.UDI_COMPUTER].is_root_device)
1197
1198 def test_HALDevice_is_root_device_for_non_root_device(self):
1199 """Test of HALDevice.is_root_device for a non-root device."""
1200 devices = [
1201 {
1202 'id': 1,
1203 'udi': self.UDI_PCCARD_DEVICE,
1204 'properties': {},
1205 },
1206 ]
1207 parsed_data = {
1208 'hardware': {
1209 'hal': {
1210 'devices': devices,
1211 },
1212 },
1213 }
1214
1215 parser = SubmissionParser()
1216 parser.submission_key = 'Test of HALDevice.is_root_device'
1217 parser.buildDeviceList(parsed_data)
1218 self.assertFalse(
1219 parser.hal_devices[self.UDI_PCCARD_DEVICE].is_root_device)
1220
968 def renameInfoBusToInfoSubsystem(self, devices):1221 def renameInfoBusToInfoSubsystem(self, devices):
969 """Rename the property info.bus in a device list to info.subsystem.1222 """Rename the property info.bus in a device list to info.subsystem.
9701223
@@ -2585,65 +2838,260 @@
2585 'property not treated as a real device.')2838 'property not treated as a real device.')
25862839
25872840
2588class TestUdevDevice(TestCase):2841class TestUdevDevice(TestCaseHWDB):
2589 """Tests of class UdevDevice."""2842 """Tests of class UdevDevice."""
25902843
2591 layer = BaseLayer2844 def setUp(self):
25922845 """Setup the test environment."""
2593 root_device = {2846 super(TestUdevDevice, self).setUp()
2594 'P': '/devices/LNXSYSTM:00',2847 self.root_device = {
2595 'E': {2848 'P': '/devices/LNXSYSTM:00',
2596 'UDEV_LOG': '3',2849 'E': {
2597 'DEVPATH': '/devices/LNXSYSTM:00',2850 'UDEV_LOG': '3',
2598 'MODALIAS': 'acpi:LNXSYSTM:',2851 'DEVPATH': '/devices/LNXSYSTM:00',
2599 'SUBSYSTEM': 'acpi',2852 'MODALIAS': 'acpi:LNXSYSTM:',
2600 }2853 'SUBSYSTEM': 'acpi',
2601 }2854 }
26022855 }
2603 root_device_dmi_data = {2856
2604 '/sys/class/dmi/id/sys_vendor': 'FUJITSU SIEMENS',2857 self.root_device_dmi_data = {
2605 '/sys/class/dmi/id/product_name': 'LIFEBOOK E8210',2858 '/sys/class/dmi/id/sys_vendor': 'FUJITSU SIEMENS',
2606 }2859 '/sys/class/dmi/id/product_name': 'LIFEBOOK E8210',
26072860 }
2608 pci_device_data = {2861
2609 'P': '/devices/pci0000:00/0000:00:1f.2',2862 self.pci_device_data = {
2610 'E': {2863 'P': '/devices/pci0000:00/0000:00:1f.2',
2611 'PCI_CLASS': '10602',2864 'E': {
2612 'PCI_ID': '8086:27C5',2865 'PCI_CLASS': '10602',
2613 'PCI_SUBSYS_ID': '10CF:1387',2866 'PCI_ID': '8086:27C5',
2614 'PCI_SLOT_NAME': '0000:00:1f.2',2867 'PCI_SUBSYS_ID': '10CF:1387',
2615 'SUBSYSTEM': 'pci',2868 'PCI_SLOT_NAME': '0000:00:1f.2',
2616 }2869 'SUBSYSTEM': 'pci',
2617 }2870 'DRIVER': 'ahci',
26182871 }
2619 usb_device_data = {2872 }
2620 'P': '/devices/pci0000:00/0000:00:1d.1/usb3/3-2',2873
2621 'E': {2874 self.usb_device_data = {
2622 'SUBSYSTEM': 'usb',2875 'P': '/devices/pci0000:00/0000:00:1d.1/usb3/3-2',
2623 'DEVTYPE': 'usb_device',2876 'E': {
2624 'PRODUCT': '46d/a01/1013',2877 'SUBSYSTEM': 'usb',
2625 'TYPE': '0/0/0',2878 'DEVTYPE': 'usb_device',
2626 },2879 'PRODUCT': '46d/a01/1013',
2627 }2880 'TYPE': '0/0/0',
26282881 'DRIVER': 'usb',
2629 scsi_device_data = {2882 },
2630 'P': '/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0',2883 }
2631 'E': {2884
2632 'SUBSYSTEM': 'scsi',2885 self.pci_pccard_bridge = {
2633 'DEVTYPE': 'scsi_device',2886 'P': '/devices/pci0000:00/0000:00:1e.0/0000:08:03.0',
2634 },2887 'E': {
2635 }2888 'DRIVER': 'yenta_cardbus',
26362889 'PCI_CLASS': '60700',
2637 scsi_device_sysfs_data = {2890 'PCI_ID': '1217:7134',
2638 'vendor': 'MATSHITA',2891 'PCI_SUBSYS_ID': '10CF:131E',
2639 'model': 'DVD-RAM UJ-841S',2892 'PCI_SLOT_NAME': '0000:08:03.0',
2640 'type': '5',2893 'SUBSYSTEM': 'pci',
2641 }2894 }
26422895 }
2643 no_subsystem_device_data = {2896
2644 'P': '/devices/pnp0/00:00',2897 self.pccard_scsi_controller_data = {
2645 'E': {}2898 'P': '/devices/pci0000:00/0000:00:1e.0/0000:08:03.0/0000:09:00.0',
2646 }2899 'E': {
2900 'DRIVER': 'aic7xxx',
2901 'PCI_CLASS': '10000',
2902 'PCI_ID': '9004:6075',
2903 'PCI_SUBSYS_ID': '9004:7560',
2904 'SUBSYSTEM': 'pci',
2905 },
2906 }
2907
2908 self.pci_scsi_controller_scsi_side_1 = {
2909 'P': ('/devices/pci0000:00/0000:00:1e.0/0000:08:03.0/'
2910 '0000:09:00.0/host6'),
2911 'E': {
2912 'DEVTYPE': 'scsi_host',
2913 'SUBSYSTEM': 'scsi',
2914 },
2915 }
2916
2917 self.pci_bridge_pccard_hierarchy_data = [
2918 {'udev_data': self.root_device},
2919 {'udev_data': self.pci_pccard_bridge},
2920 {'udev_data': self.pccard_scsi_controller_data},
2921 ]
2922
2923 self.pci_scsi_controller_scsi_side_2 = {
2924 'P': ('/devices/pci0000:00/0000:00:1e.0/0000:08:03.0/'
2925 '0000:09:00.0/host6/scsi_host/host6'),
2926 'E': {
2927 'SUBSYSTEM': 'scsi_host',
2928 },
2929 }
2930
2931 self.scsi_scanner_target_data = {
2932 'P': ('/devices/pci0000:00/0000:00:1e.0/0000:08:03.0/'
2933 '0000:09:00.0/host6/target6:0:1'),
2934 'E': {
2935 'DEVTYPE': 'scsi_target',
2936 'SUBSYSTEM': 'scsi'
2937 },
2938 }
2939
2940 self.scsi_scanner_device_data = {
2941 'P': ('/devices/pci0000:00/0000:00:1e.0/0000:08:03.0/'
2942 '0000:09:00.0/host6/target6:0:1/6:0:1:0'),
2943 'E': {
2944 'DEVTYPE': 'scsi_device',
2945 'SUBSYSTEM': 'scsi',
2946 },
2947 }
2948
2949 self.scsi_scanner_device_sysfs_data = {
2950 'vendor': 'FUJITSU',
2951 'model': 'fi-5120Cdj',
2952 'type': '6',
2953 }
2954
2955 self.scsi_device_hierarchy_data = [
2956 {'udev_data': self.pccard_scsi_controller_data},
2957 {'udev_data': self.pci_scsi_controller_scsi_side_1},
2958 {'udev_data': self.pci_scsi_controller_scsi_side_2},
2959 {'udev_data': self.scsi_scanner_target_data},
2960 {
2961 'udev_data': self.scsi_scanner_device_data,
2962 'sysfs_data': self.scsi_scanner_device_sysfs_data,
2963 },
2964 ]
2965
2966 self.pci_ide_controller = {
2967 'P': '/devices/pci0000:00/0000:00:1f.1',
2968 'E': {
2969 'DRIVER': 'ata_piix',
2970 'PCI_CLASS': '1018A',
2971 'PCI_ID': '8086:27DF',
2972 'PCI_SUBSYS_ID': '10CF:1385',
2973 'SUBSYSTEM': 'pci',
2974 },
2975 }
2976
2977 self.pci_ide_controller_scsi_side_1 = {
2978 'P': '/devices/pci0000:00/0000:00:1f.1/host4',
2979 'E': {
2980 'DEVTYPE': 'scsi_host',
2981 'SUBSYSTEM': 'scsi',
2982 },
2983 }
2984
2985 self.pci_ide_controller_scsi_side_2 = {
2986 'P': '/devices/pci0000:00/0000:00:1f.1/host4/scsi_host/host4',
2987 'E': {
2988 'SUBSYSTEM': 'scsi_host',
2989 },
2990 }
2991
2992 self.ide_device_target_data = {
2993 'P': '/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0',
2994 'E': {
2995 'DEVTYPE': 'scsi_target',
2996 'SUBSYSTEM': 'scsi',
2997 },
2998 }
2999
3000 self.ide_cdrom_device_data = {
3001 'P': ('/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/'
3002 '4:0:0:0'),
3003 'E': {
3004 'SUBSYSTEM': 'scsi',
3005 'DEVTYPE': 'scsi_device',
3006 'DRIVER': 'sr',
3007 },
3008 }
3009
3010 self.ide_cdrom_device_sysfs_data = {
3011 'vendor': 'MATSHITA',
3012 'model': 'DVD-RAM UJ-841S',
3013 'type': '5',
3014 }
3015
3016 self.ide_device_hierarchy_data = [
3017 {'udev_data': self.pci_ide_controller},
3018 {'udev_data': self.pci_ide_controller_scsi_side_1},
3019 {'udev_data': self.pci_ide_controller_scsi_side_2},
3020 {'udev_data': self.ide_device_target_data},
3021 {
3022 'udev_data': self.ide_cdrom_device_data,
3023 'sysfs_data': self.ide_cdrom_device_sysfs_data,
3024 },
3025 ]
3026
3027 self.usb_storage_usb_interface = {
3028 'P': '/devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1:1.0',
3029 'E': {
3030 'DRIVER': 'usb-storage',
3031 'PRODUCT': '1307/163/100',
3032 'TYPE': '0/0/0',
3033 'INTERFACE': '8/6/80',
3034 'DEVTYPE': 'usb_interface',
3035 'SUBSYSTEM': 'usb',
3036 },
3037 }
3038
3039 self.usb_storage_scsi_host_1 = {
3040 'P': '/devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1:1.0/host7',
3041 'E': {
3042 'DEVTYPE': 'scsi_host',
3043 'SUBSYSTEM': 'scsi',
3044 },
3045 }
3046
3047 self.usb_storage_scsi_host_2 = {
3048 'P': ('/devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1:1.0/host7/'
3049 'scsi_host/host7'),
3050 'E': {
3051 'SUBSYSTEM': 'scsi_host',
3052 },
3053 }
3054
3055 self.usb_storage_scsi_target = {
3056 'P': ('/devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1:1.0/host7/'
3057 'target7:0:0'),
3058 'E': {
3059 'DEVTYPE': 'scsi_target',
3060 'SUBSYSTEM': 'scsi',
3061 },
3062 }
3063
3064 self.usb_storage_scsi_device = {
3065 'P': ('/devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1:1.0/host7/'
3066 'target7:0:0/7:0:0:0'),
3067 'E': {
3068 'DEVTYPE': 'scsi_device',
3069 'DRIVER': 'sd',
3070 'SUBSYSTEM': 'scsi',
3071 },
3072 }
3073
3074 self.usb_storage_scsi_device_sysfs = {
3075 'vendor': 'Ut163',
3076 'model': 'USB2FlashStorage',
3077 'type': '0',
3078 }
3079
3080 self.usb_storage_hierarchy_data = [
3081 {'udev_data': self.usb_storage_usb_interface},
3082 {'udev_data': self.usb_storage_scsi_host_1},
3083 {'udev_data': self.usb_storage_scsi_host_2},
3084 {'udev_data': self.usb_storage_scsi_target},
3085 {
3086 'udev_data': self.usb_storage_scsi_device,
3087 'sysfs_data': self.usb_storage_scsi_device_sysfs,
3088 },
3089 ]
3090
3091 self.no_subsystem_device_data = {
3092 'P': '/devices/pnp0/00:00',
3093 'E': {}
3094 }
26473095
2648 def test_device_id(self):3096 def test_device_id(self):
2649 """Test of UdevDevice.device_id."""3097 """Test of UdevDevice.device_id."""
@@ -2790,7 +3238,8 @@
2790 def test_is_scsi_device(self):3238 def test_is_scsi_device(self):
2791 """Test of UdevDevice.is_scsi_device."""3239 """Test of UdevDevice.is_scsi_device."""
2792 device = UdevDevice(3240 device = UdevDevice(
2793 None, self.scsi_device_data, self.scsi_device_sysfs_data)3241 None, self.scsi_scanner_device_data,
3242 self.scsi_scanner_device_sysfs_data)
2794 self.assertTrue(device.is_scsi_device)3243 self.assertTrue(device.is_scsi_device)
27953244
2796 device = UdevDevice(None, self.root_device)3245 device = UdevDevice(None, self.root_device)
@@ -2799,16 +3248,18 @@
2799 def test_scsi_vendor(self):3248 def test_scsi_vendor(self):
2800 """Test of UdevDevice.scsi_vendor."""3249 """Test of UdevDevice.scsi_vendor."""
2801 device = UdevDevice(3250 device = UdevDevice(
2802 None, self.scsi_device_data, self.scsi_device_sysfs_data, None)3251 None, self.scsi_scanner_device_data,
2803 self.assertEqual('MATSHITA', device.scsi_vendor)3252 self.scsi_scanner_device_sysfs_data)
3253 self.assertEqual('FUJITSU', device.scsi_vendor)
2804 device = UdevDevice(None, self.root_device)3254 device = UdevDevice(None, self.root_device)
2805 self.assertEqual(None, device.scsi_vendor)3255 self.assertEqual(None, device.scsi_vendor)
28063256
2807 def test_scsi_model(self):3257 def test_scsi_model(self):
2808 """Test of UdevDevice.scsi_model."""3258 """Test of UdevDevice.scsi_model."""
2809 device = UdevDevice(3259 device = UdevDevice(
2810 None, self.scsi_device_data, self.scsi_device_sysfs_data)3260 None, self.scsi_scanner_device_data,
2811 self.assertEqual('DVD-RAM UJ-841S', device.scsi_model)3261 self.scsi_scanner_device_sysfs_data)
3262 self.assertEqual('fi-5120Cdj', device.scsi_model)
28123263
2813 device = UdevDevice(None, self.root_device)3264 device = UdevDevice(None, self.root_device)
2814 self.assertEqual(None, device.scsi_model)3265 self.assertEqual(None, device.scsi_model)
@@ -2827,6 +3278,14 @@
2827 device = UdevDevice(None, self.no_subsystem_device_data)3278 device = UdevDevice(None, self.no_subsystem_device_data)
2828 self.assertEqual(None, device.raw_bus)3279 self.assertEqual(None, device.raw_bus)
28293280
3281 def test_is_root_device(self):
3282 """Test of UdevDevice.is_root_device."""
3283 device = UdevDevice(None, self.root_device)
3284 self.assertTrue(device.is_root_device)
3285
3286 device = UdevDevice(None, self.pci_device_data)
3287 self.assertFalse(device.is_root_device)
3288
2830 def test_getVendorOrProduct(self):3289 def test_getVendorOrProduct(self):
2831 """Test of UdevDevice.getVendorOrProduct()."""3290 """Test of UdevDevice.getVendorOrProduct()."""
2832 device = UdevDevice(3291 device = UdevDevice(
@@ -2847,10 +3306,10 @@
2847 self.assertEqual('Unknown', device.getVendorOrProduct('product'))3306 self.assertEqual('Unknown', device.getVendorOrProduct('product'))
28483307
2849 device = UdevDevice(3308 device = UdevDevice(
2850 None, self.scsi_device_data, self.scsi_device_sysfs_data)3309 None, self.scsi_scanner_device_data,
2851 self.assertEqual('MATSHITA', device.getVendorOrProduct('vendor'))3310 self.scsi_scanner_device_sysfs_data)
2852 self.assertEqual(3311 self.assertEqual('FUJITSU', device.getVendorOrProduct('vendor'))
2853 'DVD-RAM UJ-841S', device.getVendorOrProduct('product'))3312 self.assertEqual('fi-5120Cdj', device.getVendorOrProduct('product'))
28543313
2855 device = UdevDevice(None, self.no_subsystem_device_data)3314 device = UdevDevice(None, self.no_subsystem_device_data)
2856 self.assertEqual(None, device.getVendorOrProduct('vendor'))3315 self.assertEqual(None, device.getVendorOrProduct('vendor'))
@@ -2888,10 +3347,10 @@
2888 self.assertEqual(0xa01, device.getVendorOrProductID('product'))3347 self.assertEqual(0xa01, device.getVendorOrProductID('product'))
28893348
2890 device = UdevDevice(3349 device = UdevDevice(
2891 None, self.scsi_device_data, self.scsi_device_sysfs_data)3350 None, self.scsi_scanner_device_data,
2892 self.assertEqual('MATSHITA', device.getVendorOrProductID('vendor'))3351 self.scsi_scanner_device_sysfs_data)
2893 self.assertEqual(3352 self.assertEqual('FUJITSU', device.getVendorOrProductID('vendor'))
2894 'DVD-RAM UJ-841S', device.getVendorOrProductID('product'))3353 self.assertEqual('fi-5120Cdj', device.getVendorOrProductID('product'))
28953354
2896 device = UdevDevice(3355 device = UdevDevice(
2897 None, self.no_subsystem_device_data)3356 None, self.no_subsystem_device_data)
@@ -2910,6 +3369,179 @@
2910 None, self.root_device, None, self.root_device_dmi_data)3369 None, self.root_device, None, self.root_device_dmi_data)
2911 self.assertEqual('LIFEBOOK E8210', device.product_id)3370 self.assertEqual('LIFEBOOK E8210', device.product_id)
29123371
3372 def test_vendor_id_for_db(self):
3373 """Test of UdevDevice.vendor_id_for_db."""
3374 device = UdevDevice(
3375 None, self.root_device, None, self.root_device_dmi_data)
3376 self.assertEqual('FUJITSU SIEMENS', device.vendor_id_for_db)
3377
3378 device = UdevDevice(None, self.pci_device_data)
3379 self.assertEqual('0x8086', device.vendor_id_for_db)
3380
3381 device = UdevDevice(None, self.usb_device_data)
3382 self.assertEqual('0x046d', device.vendor_id_for_db)
3383
3384 device = UdevDevice(
3385 None, self.scsi_scanner_device_data,
3386 self.scsi_scanner_device_sysfs_data)
3387 self.assertEqual('FUJITSU ', device.vendor_id_for_db)
3388
3389 def test_product_id_for_db(self):
3390 """Test of UdevDevice.product_id_for_db."""
3391 device = UdevDevice(
3392 None, self.root_device, None, self.root_device_dmi_data)
3393 self.assertEqual('LIFEBOOK E8210', device.product_id_for_db)
3394
3395 device = UdevDevice(None, self.pci_device_data)
3396 self.assertEqual('0x27c5', device.product_id_for_db)
3397
3398 device = UdevDevice(None, self.usb_device_data)
3399 self.assertEqual('0x0a01', device.product_id_for_db)
3400
3401 device = UdevDevice(
3402 None, self.scsi_scanner_device_data,
3403 self.scsi_scanner_device_sysfs_data)
3404 self.assertEqual('fi-5120Cdj ', device.product_id_for_db)
3405
3406 def test_driver_name(self):
3407 """Test of UdevDevice.driver_name."""
3408 device = UdevDevice(None, self.pci_device_data)
3409 self.assertEqual('ahci', device.driver_name)
3410
3411 device = UdevDevice(
3412 None, self.root_device, None, self.root_device_dmi_data)
3413 self.assertEqual(None, device.driver_name)
3414
3415 def buildUdevDeviceHierarchy(self, device_data, parser=None):
3416 """Build a UdevDevice hierarchy from device_data.
3417
3418 :param device_data: A sequence of arguments that are passed
3419 to the UdevDevice constructor. Each element must be a
3420 dictionary that can be used as a **kwargs argument.
3421
3422 Element N of the sequence is the parent of element N+1.
3423 :param parser: A SubmissionParser instance to be passed to
3424 the constructor of UdevDevice.
3425 """
3426 parent = None
3427 devices = []
3428 for kwargs in device_data:
3429 device = UdevDevice(parser, **kwargs)
3430 devices.append(device)
3431 if parent is not None:
3432 parent.addChild(device)
3433 parent = device
3434 return devices
3435
3436 def test_scsi_controller(self):
3437 """Test of UdevDevice.scsi_controller for a PCI controller."""
3438 devices = self.buildUdevDeviceHierarchy(
3439 self.scsi_device_hierarchy_data)
3440 controller = devices[0]
3441 scsi_device = devices[-1]
3442 self.assertEqual(controller, scsi_device.scsi_controller)
3443
3444 def test_scsi_controller_insufficient_anchestors(self):
3445 """Test of UdevDevice.scsi_controller for a PCI controller.
3446
3447 If a SCSI device does not have a sufficient number of ancestors,
3448 UdevDevice.scsi_controller returns None.
3449 """
3450 parser = SubmissionParser(self.log)
3451 parser.submission_key = 'UdevDevice.scsi_controller ancestor missing'
3452 devices = self.buildUdevDeviceHierarchy(
3453 self.scsi_device_hierarchy_data[1:], parser)
3454 scsi_device = devices[-1]
3455 self.assertEqual(None, scsi_device.scsi_controller)
3456 self.assertWarningMessage(
3457 parser.submission_key,
3458 'Found a SCSI device without a sufficient number of ancestors: '
3459 '/devices/pci0000:00/0000:00:1e.0/0000:08:03.0/0000:09:00.0/'
3460 'host6/target6:0:1/6:0:1:0')
3461
3462 def test_scsi_controller_no_scsi_device(self):
3463 """Test of UdevDevice.scsi_controller for a PCI controller.
3464
3465 For non-SCSI devices, this property is None.
3466 """
3467 device = UdevDevice(None, self.pci_device_data)
3468 self.assertEqual(None, device.scsi_controller)
3469
3470 def test_translateScsiBus_real_scsi_device(self):
3471 """Test of UdevDevice.translateScsiBus() with a real SCSI device."""
3472 devices = self.buildUdevDeviceHierarchy(
3473 self.scsi_device_hierarchy_data)
3474 scsi_device = devices[-1]
3475 self.assertEqual(
3476 HWBus.SCSI, scsi_device.translateScsiBus())
3477
3478 def test_translateScsiBus_ide_device(self):
3479 """Test of UdevDevice.translateScsiBus() with an IDE device."""
3480 devices = self.buildUdevDeviceHierarchy(
3481 self.ide_device_hierarchy_data)
3482 ide_device = devices[-1]
3483 self.assertEqual(HWBus.IDE, ide_device.translateScsiBus())
3484
3485 def test_translateScsiBus_usb_device(self):
3486 """Test of UdevDevice.translateScsiBus() with a USB device."""
3487 devices = self.buildUdevDeviceHierarchy(
3488 self.usb_storage_hierarchy_data)
3489 usb_scsi_device = devices[-1]
3490 self.assertEqual(None, usb_scsi_device.translateScsiBus())
3491
3492 def test_translateScsiBus_non_scsi_device(self):
3493 """Test of UdevDevice.translateScsiBus() for a non-SCSI device."""
3494 device = UdevDevice(None, self.root_device)
3495 self.assertEqual(None, device.translateScsiBus())
3496
3497 def test_translatePciBus(self):
3498 """Test of UdevDevice.translatePciBus()."""
3499 devices = self.buildUdevDeviceHierarchy(
3500 self.pci_bridge_pccard_hierarchy_data)
3501 pci_device = devices[1]
3502 pccard_device = devices[2]
3503 self.assertEqual(HWBus.PCI, pci_device.translatePciBus())
3504 self.assertEqual(HWBus.PCCARD, pccard_device.translatePciBus())
3505
3506 def test_real_bus_usb_device(self):
3507 """Test of UdevDevice.real_bus for a USB device."""
3508 usb_device = UdevDevice(None, self.usb_device_data)
3509 self.assertEqual(HWBus.USB, usb_device.real_bus)
3510
3511 def test_real_bus_usb_interface(self):
3512 """Test of UdevDevice.real_bus for a USB interface."""
3513 parser = SubmissionParser(self.log)
3514 parser.submission_key = 'UdevDevice.real_bus for a not-real device'
3515 usb_interface = UdevDevice(parser, self.usb_storage_usb_interface)
3516 self.assertEqual(None, usb_interface.real_bus)
3517 # UdevDevice.real_bus should only be accessed for real devices,
3518 # which a USB is not. Hence we get a warning.
3519 self.assertWarningMessage(
3520 parser.submission_key,
3521 "Unknown bus 'usb_interface' for device "
3522 "/devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1:1.0")
3523
3524 def test_real_bus_pci(self):
3525 """Test of UdevDevice.real_bus for PCI devices."""
3526 devices = self.buildUdevDeviceHierarchy(
3527 self.pci_bridge_pccard_hierarchy_data)
3528 pci_device = devices[1]
3529 pccard_device = devices[2]
3530 self.assertEqual(HWBus.PCI, pci_device.real_bus)
3531 self.assertEqual(HWBus.PCCARD, pccard_device.real_bus)
3532
3533 def test_real_bus_scsi(self):
3534 """Test of UdevDevice.real_bus for a SCSI device."""
3535 devices = self.buildUdevDeviceHierarchy(
3536 self.scsi_device_hierarchy_data)
3537 scsi_device = devices[-1]
3538 self.assertEqual(HWBus.SCSI, scsi_device.real_bus)
3539
3540 def test_real_bus_system(self):
3541 """Test of UdevDevice.real_bus for a system."""
3542 root_device = UdevDevice(None, self.root_device)
3543 self.assertEqual(HWBus.SYSTEM, root_device.real_bus)
3544
29133545
2914class TestHWDBSubmissionTablePopulation(TestCaseHWDB):3546class TestHWDBSubmissionTablePopulation(TestCaseHWDB):
2915 """Tests of the HWDB popoluation with submitted data."""3547 """Tests of the HWDB popoluation with submitted data."""