Merge lp:~adeuring/launchpad/hwdb-class-udev-device-5 into lp:launchpad/db-devel

Proposed by Abel Deuring
Status: Merged
Approved by: Gavin Panella
Approved revision: no longer in the source branch.
Merged at revision: not available
Proposed branch: lp:~adeuring/launchpad/hwdb-class-udev-device-5
Merge into: lp:launchpad/db-devel
Diff against target: 1059 lines
2 files modified
lib/canonical/launchpad/scripts/hwdbsubmissions.py (+200/-36)
lib/canonical/launchpad/scripts/tests/test_hwdb_submission_processing.py (+473/-67)
To merge this branch: bzr merge lp:~adeuring/launchpad/hwdb-class-udev-device-5
Reviewer Review Type Date Requested Status
Gavin Panella (community) Approve
Review via email: mp+13350@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Abel Deuring (adeuring) wrote :
Download full text (3.4 KiB)

This branch is another step to prepare the BWDB submission processing script for submissions from Karmic's HWDB client.

- a fix of two properties for class UdevDevice:

BaseDevice.vendor_id_for_db and BaseDevice.product_id_for_db look up the dictionaries DB_FORMAT_FOR_VENDOR_ID and DB_FORMAT_FOR_PRODUCT_ID, respectively, using BaseDevice,raw_bus as the key. The udev data contains slightly different bus/subsystem data, so we get the raw_value "scsi_device" for submissions with udev data, while we have raw_bus == "scsi" for HAL-based submissions. Hence I added a "scsi_device" entry to the dicitionaries. Since the raw_bus value "scsi_device" is not used by HAL, there are no side effects for HAL-based submissions.

- a new property UdevDevice.driver_name

- The method BaseDevice.translateScsiBus() figures out, if a given device where rw_bus is "scsi" (submission with HAL data) or "scsi_device" (submissions with udev data) is a real SCSI device or if it is in fact a USB storage device or a IDE/ATA/SATA device. (Since most od today's storage devices understand SCSI commands, the Linux kernel accesses them via the SCSI layer.) We detect the real device type of given device with raw_bus in ("scsi", "scsi_device") by looking at the device that controls the given (fake) SCSI device: If the controller is a USB device, we have a memory stick, a card reader or a "real" IDE/SATA disk connected to USB adapter; if the controller is a PCI device, we have a real SCSI device, or an IDE/ATA/SATA device. What exactly ww have in the latter case, can be derived from the PCI class/subclass of the controller.

For submissions with HAL, the controller is the grandparent of the SCSI device, but for submissions with udev data, the controller is the grand-grand-grand-grand-grandparent (6th ancestor).

Since the core logic of translateScsiBus() is identical for HAL and udev data, I did not move the method to the two classes HALDevice, UdevDevice derived from BaseDevice. Instead, I defined a new property BaseDevice.scsi_controller that must be implemented by both HALDevice and UdevDevice.

A implementation of UdevDevice.scsi_controller is still missing -- when I started to write tests for that property, I noticed that the diff of the branch would probably exceed our 800 lines limit, so I left that for another sequel.

The change in test_hwdb_submission_processing.py: replace scsi_device_data by scsi_scanner_device_data may look a bit odd. There are two reasons for this change:

(1) I wanted a real-world SCSI vendor name that is shorter than 8 characters in order to have proper test data for UdevDevice.vendor_id_for_db, which right-pads vendor names with spaces to length 8.

(2) The old test device "MATSHITA DVD-RAM UJ-841S" is in fact an IDE device; it might show up as an IDE device later again in a test of BaseDevice.translateScsiBus().

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_submi...

Read more...

Revision history for this message
Gavin Panella (allenap) wrote :

This all looks good.

As discussed on IRC, this is really meant for devel, not db-devel, so
I've attached the diff I actually reviewed.

Gavin.

1=== modified file 'lib/canonical/launchpad/scripts/hwdbsubmissions.py'
2--- lib/canonical/launchpad/scripts/hwdbsubmissions.py 2009-10-13 21:03:31 +0000
3+++ lib/canonical/launchpad/scripts/hwdbsubmissions.py 2009-10-14 16:00:26 +0000
4@@ -87,12 +87,14 @@
5 'pci': '0x%04x',
6 'usb_device': '0x%04x',
7 'scsi': '%-8s',
8+ 'scsi_device': '%-8s',
9 }
10
11 DB_FORMAT_FOR_PRODUCT_ID = {
12 'pci': '0x%04x',
13 'usb_device': '0x%04x',
14 'scsi': '%-16s',
15+ 'scsi_device': '%-16s',
16 }
17
18 UDEV_USB_DEVICE_PROPERTIES = set(('DEVTYPE', 'PRODUCT', 'TYPE'))
19@@ -1609,6 +1611,11 @@
20 """The name of the driver contolling this device. May be None."""
21 raise NotImplementedError
22
23+ @property
24+ def scsi_controller(self):
25+ """Return the SCSI host controller for this device."""
26+ raise NotImplementedError
27+
28 def translateScsiBus(self):
29 """Return the real bus of a device where raw_bus=='scsi'.
30
31@@ -1617,37 +1624,27 @@
32 for more details. This method determines the real bus
33 of a device accessed via the kernel's SCSI subsystem.
34 """
35- # While SCSI devices from valid submissions should have a
36- # parent and a grandparent, we can't be sure for bogus or
37- # broken submissions.
38- parent = self.parent
39- if parent is None:
40- self.parser._logWarning(
41- 'Found SCSI device without a parent: %s.' % self.device_id)
42- return None
43- grandparent = parent.parent
44- if grandparent is None:
45- self.parser._logWarning(
46- 'Found SCSI device without a grandparent: %s.'
47- % self.device_id)
48+ scsi_controller = self.scsi_controller
49+ if scsi_controller is None:
50 return None
51
52- grandparent_bus = grandparent.raw_bus
53- if grandparent_bus == 'pci':
54- if (grandparent.pci_class != PCI_CLASS_STORAGE):
55+ scsi_controller_bus = scsi_controller.raw_bus
56+ if scsi_controller_bus == 'pci':
57+ if (scsi_controller.pci_class != PCI_CLASS_STORAGE):
58 # This is not a storage class PCI device? This
59 # indicates a bug somewhere in HAL or in the hwdb
60 # client, or a fake submission.
61- device_class = grandparent.pci_class
62+ device_class = scsi_controller.pci_class
63 self.parser._logWarning(
64 'A (possibly fake) SCSI device %s is connected to '
65 'PCI device %s that has the PCI device class %s; '
66 'expected class 1 (storage).'
67- % (self.device_id, grandparent.device_id, device_class))
68+ % (self.device_id, scsi_controller.device_id,
69+ device_class))
70 return None
71- pci_subclass = grandparent.pci_subclass
72+ pci_subclass = scsi_controller.pci_subclass
73 return self.pci_storage_subclass_hwbus.get(pci_subclass)
74- elif grandparent_bus == 'usb':
75+ elif scsi_controller_bus == 'usb':
76 # USB storage devices have the following HAL device hierarchy:
77 # - HAL node for the USB device. info.bus == 'usb_device',
78 # device class == 0, device subclass == 0
79@@ -2357,6 +2354,27 @@
80 """See `BaseDevice`."""
81 return self.getVendorOrProductID('product')
82
83+ @property
84+ def scsi_controller(self):
85+ """See `BaseDevice`."""
86+ # While SCSI devices from valid submissions should have a
87+ # parent and a grandparent, we can't be sure for bogus or
88+ # broken submissions.
89+ if self.raw_bus != 'scsi':
90+ return None
91+ parent = self.parent
92+ if parent is None:
93+ self.parser._logWarning(
94+ 'Found SCSI device without a parent: %s.' % self.device_id)
95+ return None
96+ grandparent = parent.parent
97+ if grandparent is None:
98+ self.parser._logWarning(
99+ 'Found SCSI device without a grandparent: %s.'
100+ % self.device_id)
101+ return None
102+ return grandparent
103+
104
105 class UdevDevice(BaseDevice):
106 """The representation of a udev device node."""
107@@ -2617,6 +2635,11 @@
108 """See `BaseDevice`."""
109 return self.getVendorOrProductID('product')
110
111+ @property
112+ def driver_name(self):
113+ """See `BaseDevice`."""
114+ return self.udev['E'].get('DRIVER')
115+
116
117 class ProcessingLoop(object):
118 """An `ITunableLoop` for processing HWDB submissions."""
119
120=== modified file 'lib/canonical/launchpad/scripts/tests/test_hwdb_submission_processing.py'
121--- lib/canonical/launchpad/scripts/tests/test_hwdb_submission_processing.py 2009-10-13 21:02:35 +0000
122+++ lib/canonical/launchpad/scripts/tests/test_hwdb_submission_processing.py 2009-10-14 16:00:26 +0000
123@@ -539,6 +539,214 @@
124 'HAL property info.bus.')
125
126
127+ def test_HALDevice_scsi_controller_usb_storage_device(self):
128+ """test of HALDevice.scsi_controller.
129+
130+ The physical device is a USB storage device.
131+ """
132+ devices = [
133+ # The main node of the USB storage device.
134+ {
135+ 'id': 1,
136+ 'udi': self.UDI_USB_STORAGE,
137+ 'properties': {
138+ 'info.bus': ('usb_device', 'str'),
139+ },
140+ },
141+ # The storage interface of the USB device.
142+ {
143+ 'id': 2,
144+ 'udi': self.UDI_USB_STORAGE_IF0,
145+ 'properties': {
146+ 'info.bus': ('usb', 'str'),
147+ 'info.parent': (self.UDI_USB_STORAGE, 'str'),
148+ },
149+ },
150+ # The fake SCSI host of the storage device. Note that HAL does
151+ # _not_ provide the info.bus property.
152+ {
153+ 'id': 3,
154+ 'udi': self.UDI_USB_STORAGE_SCSI_HOST,
155+ 'properties': {
156+ 'info.parent': (self.UDI_USB_STORAGE_IF0, 'str'),
157+ },
158+ },
159+ # The fake SCSI disk.
160+ {
161+ 'id': 3,
162+ 'udi': self.UDI_USB_STORAGE_SCSI_DEVICE,
163+ 'properties': {
164+ 'info.bus': ('scsi', 'str'),
165+ 'info.parent': (self.UDI_USB_STORAGE_SCSI_HOST, 'str'),
166+ },
167+ },
168+ ]
169+ parsed_data = {
170+ 'hardware': {
171+ 'hal': {
172+ 'devices': devices,
173+ },
174+ },
175+ }
176+
177+ parser = SubmissionParser()
178+ parser.buildDeviceList(parsed_data)
179+
180+ usb_fake_scsi_disk = parser.hal_devices[
181+ self.UDI_USB_STORAGE_SCSI_DEVICE]
182+ usb_main_device = parser.hal_devices[self.UDI_USB_STORAGE_IF0]
183+ self.assertEqual(usb_main_device, usb_fake_scsi_disk.scsi_controller)
184+
185+ def test_HALDevice_scsi_controller_pci_controller(self):
186+ """test of HALDevice.scsi_controller.
187+
188+ Variant for a SCSI device connected to a PCI controller.
189+ """
190+ devices = [
191+ # The PCI host controller.
192+ {
193+ 'id': 1,
194+ 'udi': self.UDI_SATA_CONTROLLER,
195+ 'properties': {
196+ 'info.bus': ('pci', 'str'),
197+ 'pci.device_class': (PCI_CLASS_STORAGE, 'int'),
198+ 'pci.device_subclass': (PCI_SUBCLASS_STORAGE_SATA,
199+ 'int'),
200+ },
201+ },
202+ # The (fake or real) SCSI host of the storage device.
203+ {
204+ 'id': 2,
205+ 'udi': self.UDI_SATA_CONTROLLER_SCSI,
206+ 'properties': {
207+ 'info.parent': (self.UDI_SATA_CONTROLLER, 'str'),
208+ },
209+ },
210+ # The (possibly fake) SCSI disk.
211+ {
212+ 'id': 3,
213+ 'udi': self.UDI_SATA_DISK,
214+ 'properties': {
215+ 'info.bus': ('scsi', 'str'),
216+ 'info.parent': (self.UDI_SATA_CONTROLLER_SCSI, 'str'),
217+ },
218+ },
219+ ]
220+ parsed_data = {
221+ 'hardware': {
222+ 'hal': {
223+ 'devices': devices,
224+ },
225+ },
226+ }
227+
228+ parser = SubmissionParser()
229+ parser.buildDeviceList(parsed_data)
230+
231+ scsi_device = parser.hal_devices[self.UDI_SATA_DISK]
232+ controller = parser.hal_devices[self.UDI_SATA_CONTROLLER]
233+ self.assertEqual(controller, scsi_device.scsi_controller)
234+
235+ def test_HALDevice_scsi_controller_non_scsi_device(self):
236+ """test of HALDevice.scsi_controller.
237+
238+ Variant for non-SCSI devices.
239+ """
240+ devices = [
241+ {
242+ 'id': 1,
243+ 'udi': self.UDI_COMPUTER,
244+ 'properties': {},
245+ },
246+ ]
247+ parsed_data = {
248+ 'hardware': {
249+ 'hal': {
250+ 'devices': devices,
251+ },
252+ },
253+ }
254+
255+ parser = SubmissionParser()
256+ parser.buildDeviceList(parsed_data)
257+
258+ device = parser.hal_devices[self.UDI_COMPUTER]
259+ self.assertEqual(None, device.scsi_controller)
260+
261+ def test_HALDevice_scsi_controller_no_grandparent(self):
262+ """test of HALDevice.scsi_controller.
263+
264+ Variant for a SCSI device without a grandparent device.
265+ """
266+ devices = [
267+ # The (fake or real) SCSI host of the storage device.
268+ {
269+ 'id': 1,
270+ 'udi': self.UDI_SATA_CONTROLLER_SCSI,
271+ 'properties': {},
272+ },
273+ # The (possibly fake) SCSI disk.
274+ {
275+ 'id': 2,
276+ 'udi': self.UDI_SATA_DISK,
277+ 'properties': {
278+ 'info.bus': ('scsi', 'str'),
279+ 'info.parent': (self.UDI_SATA_CONTROLLER_SCSI, 'str'),
280+ },
281+ },
282+ ]
283+ parsed_data = {
284+ 'hardware': {
285+ 'hal': {
286+ 'devices': devices,
287+ },
288+ },
289+ }
290+
291+ parser = SubmissionParser(self.log)
292+ parser.submission_key = 'SCSI device without grandparent device'
293+ parser.buildDeviceList(parsed_data)
294+
295+ scsi_device = parser.hal_devices[self.UDI_SATA_DISK]
296+ self.assertEqual(None, scsi_device.scsi_controller)
297+ self.assertWarningMessage(
298+ parser.submission_key,
299+ "Found SCSI device without a grandparent: %s."
300+ % self.UDI_SATA_DISK)
301+
302+ def test_HALDevice_scsi_controller_no_parent(self):
303+ """test of HALDevice.scsi_controller.
304+
305+ Variant for a SCSI device without a parent device.
306+ """
307+ devices = [
308+ # The (possibly fake) SCSI disk.
309+ {
310+ 'id': 1,
311+ 'udi': self.UDI_SATA_DISK,
312+ 'properties': {
313+ 'info.bus': ('scsi', 'str'),
314+ },
315+ },
316+ ]
317+ parsed_data = {
318+ 'hardware': {
319+ 'hal': {
320+ 'devices': devices,
321+ },
322+ },
323+ }
324+
325+ parser = SubmissionParser(self.log)
326+ parser.submission_key = 'SCSI device without parent device'
327+ parser.buildDeviceList(parsed_data)
328+
329+ scsi_device = parser.hal_devices[self.UDI_SATA_DISK]
330+ self.assertEqual(None, scsi_device.scsi_controller)
331+ self.assertWarningMessage(
332+ parser.submission_key,
333+ "Found SCSI device without a parent: %s." % self.UDI_SATA_DISK)
334+
335 def testHALDeviceGetRealBus(self):
336 """Test of HALDevice.real_bus, generic case.
337
338@@ -2613,6 +2821,7 @@
339 'PCI_SUBSYS_ID': '10CF:1387',
340 'PCI_SLOT_NAME': '0000:00:1f.2',
341 'SUBSYSTEM': 'pci',
342+ 'DRIVER': 'ahci',
343 }
344 }
345
346@@ -2623,21 +2832,23 @@
347 'DEVTYPE': 'usb_device',
348 'PRODUCT': '46d/a01/1013',
349 'TYPE': '0/0/0',
350+ 'DRIVER': 'usb',
351 },
352 }
353
354- scsi_device_data = {
355- 'P': '/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0',
356+ scsi_scanner_device_data = {
357+ 'P': ('/devices/pci0000:00/0000:00:1e.0/0000:08:03.0/0000:09:00.0/'
358+ 'host6/target6:0:1/6:0:1:0'),
359 'E': {
360+ 'DEVTYPE': 'scsi_device',
361 'SUBSYSTEM': 'scsi',
362- 'DEVTYPE': 'scsi_device',
363 },
364 }
365
366- scsi_device_sysfs_data = {
367- 'vendor': 'MATSHITA',
368- 'model': 'DVD-RAM UJ-841S',
369- 'type': '5',
370+ scsi_scanner_device_sysfs_data = {
371+ 'vendor': 'FUJITSU',
372+ 'model': 'fi-5120Cdj',
373+ 'type': '6',
374 }
375
376 no_subsystem_device_data = {
377@@ -2790,7 +3001,8 @@
378 def test_is_scsi_device(self):
379 """Test of UdevDevice.is_scsi_device."""
380 device = UdevDevice(
381- None, self.scsi_device_data, self.scsi_device_sysfs_data)
382+ None, self.scsi_scanner_device_data,
383+ self.scsi_scanner_device_sysfs_data)
384 self.assertTrue(device.is_scsi_device)
385
386 device = UdevDevice(None, self.root_device)
387@@ -2799,16 +3011,18 @@
388 def test_scsi_vendor(self):
389 """Test of UdevDevice.scsi_vendor."""
390 device = UdevDevice(
391- None, self.scsi_device_data, self.scsi_device_sysfs_data, None)
392- self.assertEqual('MATSHITA', device.scsi_vendor)
393+ None, self.scsi_scanner_device_data,
394+ self.scsi_scanner_device_sysfs_data)
395+ self.assertEqual('FUJITSU', device.scsi_vendor)
396 device = UdevDevice(None, self.root_device)
397 self.assertEqual(None, device.scsi_vendor)
398
399 def test_scsi_model(self):
400 """Test of UdevDevice.scsi_model."""
401 device = UdevDevice(
402- None, self.scsi_device_data, self.scsi_device_sysfs_data)
403- self.assertEqual('DVD-RAM UJ-841S', device.scsi_model)
404+ None, self.scsi_scanner_device_data,
405+ self.scsi_scanner_device_sysfs_data)
406+ self.assertEqual('fi-5120Cdj', device.scsi_model)
407
408 device = UdevDevice(None, self.root_device)
409 self.assertEqual(None, device.scsi_model)
410@@ -2847,10 +3061,10 @@
411 self.assertEqual('Unknown', device.getVendorOrProduct('product'))
412
413 device = UdevDevice(
414- None, self.scsi_device_data, self.scsi_device_sysfs_data)
415- self.assertEqual('MATSHITA', device.getVendorOrProduct('vendor'))
416- self.assertEqual(
417- 'DVD-RAM UJ-841S', device.getVendorOrProduct('product'))
418+ None, self.scsi_scanner_device_data,
419+ self.scsi_scanner_device_sysfs_data)
420+ self.assertEqual('FUJITSU', device.getVendorOrProduct('vendor'))
421+ self.assertEqual('fi-5120Cdj', device.getVendorOrProduct('product'))
422
423 device = UdevDevice(None, self.no_subsystem_device_data)
424 self.assertEqual(None, device.getVendorOrProduct('vendor'))
425@@ -2888,10 +3102,10 @@
426 self.assertEqual(0xa01, device.getVendorOrProductID('product'))
427
428 device = UdevDevice(
429- None, self.scsi_device_data, self.scsi_device_sysfs_data)
430- self.assertEqual('MATSHITA', device.getVendorOrProductID('vendor'))
431- self.assertEqual(
432- 'DVD-RAM UJ-841S', device.getVendorOrProductID('product'))
433+ None, self.scsi_scanner_device_data,
434+ self.scsi_scanner_device_sysfs_data)
435+ self.assertEqual('FUJITSU', device.getVendorOrProductID('vendor'))
436+ self.assertEqual('fi-5120Cdj', device.getVendorOrProductID('product'))
437
438 device = UdevDevice(
439 None, self.no_subsystem_device_data)
440@@ -2910,6 +3124,49 @@
441 None, self.root_device, None, self.root_device_dmi_data)
442 self.assertEqual('LIFEBOOK E8210', device.product_id)
443
444+ def test_vendor_id_for_db(self):
445+ """Test of UdevDevice.vendor_id_for_db."""
446+ device = UdevDevice(
447+ None, self.root_device, None, self.root_device_dmi_data)
448+ self.assertEqual('FUJITSU SIEMENS', device.vendor_id_for_db)
449+
450+ device = UdevDevice(None, self.pci_device_data)
451+ self.assertEqual('0x8086', device.vendor_id_for_db)
452+
453+ device = UdevDevice(None, self.usb_device_data)
454+ self.assertEqual('0x046d', device.vendor_id_for_db)
455+
456+ device = UdevDevice(
457+ None, self.scsi_scanner_device_data,
458+ self.scsi_scanner_device_sysfs_data)
459+ self.assertEqual('FUJITSU ', device.vendor_id_for_db)
460+
461+ def test_product_id_for_db(self):
462+ """Test of UdevDevice.product_id_for_db."""
463+ device = UdevDevice(
464+ None, self.root_device, None, self.root_device_dmi_data)
465+ self.assertEqual('LIFEBOOK E8210', device.product_id_for_db)
466+
467+ device = UdevDevice(None, self.pci_device_data)
468+ self.assertEqual('0x27c5', device.product_id_for_db)
469+
470+ device = UdevDevice(None, self.usb_device_data)
471+ self.assertEqual('0x0a01', device.product_id_for_db)
472+
473+ device = UdevDevice(
474+ None, self.scsi_scanner_device_data,
475+ self.scsi_scanner_device_sysfs_data)
476+ self.assertEqual('fi-5120Cdj ', device.product_id_for_db)
477+
478+ def test_driver_name(self):
479+ """Test of UdevDevice.driver_name."""
480+ device = UdevDevice(None, self.pci_device_data)
481+ self.assertEqual('ahci', device.driver_name)
482+
483+ device = UdevDevice(
484+ None, self.root_device, None, self.root_device_dmi_data)
485+ self.assertEqual(None, device.driver_name)
486+
487
488 class TestHWDBSubmissionTablePopulation(TestCaseHWDB):
489 """Tests of the HWDB popoluation with submitted data."""
Revision history for this message
Gavin Panella (allenap) wrote :

 review approve
 merge approve

review: Approve
Revision history for this message
Gavin Panella (allenap) wrote :

Review sent by email but not arrived yet... but it's all good :)

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/canonical/launchpad/scripts/hwdbsubmissions.py'
2--- lib/canonical/launchpad/scripts/hwdbsubmissions.py 2009-10-12 15:36:04 +0000
3+++ lib/canonical/launchpad/scripts/hwdbsubmissions.py 2009-10-14 15:20:31 +0000
4@@ -59,6 +59,7 @@
5 re.VERBOSE)
6
7 ROOT_UDI = '/org/freedesktop/Hal/devices/computer'
8+UDEV_ROOT_PATH = '/devices/LNXSYSTM:00'
9
10 # These UDIs appears in some submissions more than once.
11 KNOWN_DUPLICATE_UDIS = set((
12@@ -86,12 +87,14 @@
13 'pci': '0x%04x',
14 'usb_device': '0x%04x',
15 'scsi': '%-8s',
16+ 'scsi_device': '%-8s',
17 }
18
19 DB_FORMAT_FOR_PRODUCT_ID = {
20 'pci': '0x%04x',
21 'usb_device': '0x%04x',
22 'scsi': '%-16s',
23+ 'scsi_device': '%-16s',
24 }
25
26 UDEV_USB_DEVICE_PROPERTIES = set(('DEVTYPE', 'PRODUCT', 'TYPE'))
27@@ -1606,6 +1609,12 @@
28 @property
29 def driver_name(self):
30 """The name of the driver contolling this device. May be None."""
31+ raise NotImplementedError
32+
33+ @property
34+ def scsi_controller(self):
35+ """Return the SCSI host controller for this device."""
36+ raise NotImplementedError
37
38 def translateScsiBus(self):
39 """Return the real bus of a device where raw_bus=='scsi'.
40@@ -1615,37 +1624,27 @@
41 for more details. This method determines the real bus
42 of a device accessed via the kernel's SCSI subsystem.
43 """
44- # While SCSI devices from valid submissions should have a
45- # parent and a grandparent, we can't be sure for bogus or
46- # broken submissions.
47- parent = self.parent
48- if parent is None:
49- self.parser._logWarning(
50- 'Found SCSI device without a parent: %s.' % self.device_id)
51- return None
52- grandparent = parent.parent
53- if grandparent is None:
54- self.parser._logWarning(
55- 'Found SCSI device without a grandparent: %s.'
56- % self.device_id)
57+ scsi_controller = self.scsi_controller
58+ if scsi_controller is None:
59 return None
60
61- grandparent_bus = grandparent.raw_bus
62- if grandparent_bus == 'pci':
63- if (grandparent.pci_class != PCI_CLASS_STORAGE):
64+ scsi_controller_bus = scsi_controller.raw_bus
65+ if scsi_controller_bus == 'pci':
66+ if (scsi_controller.pci_class != PCI_CLASS_STORAGE):
67 # This is not a storage class PCI device? This
68 # indicates a bug somewhere in HAL or in the hwdb
69 # client, or a fake submission.
70- device_class = grandparent.pci_class
71+ device_class = scsi_controller.pci_class
72 self.parser._logWarning(
73 'A (possibly fake) SCSI device %s is connected to '
74 'PCI device %s that has the PCI device class %s; '
75 'expected class 1 (storage).'
76- % (self.device_id, grandparent.device_id, device_class))
77+ % (self.device_id, scsi_controller.device_id,
78+ device_class))
79 return None
80- pci_subclass = grandparent.pci_subclass
81+ pci_subclass = scsi_controller.pci_subclass
82 return self.pci_storage_subclass_hwbus.get(pci_subclass)
83- elif grandparent_bus == 'usb':
84+ elif scsi_controller_bus == 'usb':
85 # USB storage devices have the following HAL device hierarchy:
86 # - HAL node for the USB device. info.bus == 'usb_device',
87 # device class == 0, device subclass == 0
88@@ -2067,10 +2066,15 @@
89 # it is hard to find a better heuristic to separate
90 # the vendor name from the product name.
91 splitted_name = self.scsi_model.split(' ', 1)
92- if len(splitted_name) < 2:
93- return 'ATA', splitted_name[0]
94- return splitted_name
95- return (vendor, self.scsi_model)
96+ if len(splitted_name) == 2:
97+ return {
98+ 'vendor': splitted_name[0],
99+ 'product': splitted_name[1],
100+ }
101+ return {
102+ 'vendor': vendor,
103+ 'product': self.scsi_model,
104+ }
105
106 def getDriver(self):
107 """Return the HWDriver instance associated with this device.
108@@ -2289,11 +2293,7 @@
109 # below does not work properly.
110 return self.getProperty('system.hardware.' + type_)
111 elif bus == 'scsi':
112- vendor, product = self.getScsiVendorAndModelName()
113- if type_ == 'vendor':
114- return vendor
115- else:
116- return product
117+ return self.getScsiVendorAndModelName()[type_]
118 else:
119 result = self.getProperty('info.' + type_)
120 if result is None:
121@@ -2354,11 +2354,32 @@
122 """See `BaseDevice`."""
123 return self.getVendorOrProductID('product')
124
125+ @property
126+ def scsi_controller(self):
127+ """See `BaseDevice`."""
128+ # While SCSI devices from valid submissions should have a
129+ # parent and a grandparent, we can't be sure for bogus or
130+ # broken submissions.
131+ if self.raw_bus != 'scsi':
132+ return None
133+ parent = self.parent
134+ if parent is None:
135+ self.parser._logWarning(
136+ 'Found SCSI device without a parent: %s.' % self.device_id)
137+ return None
138+ grandparent = parent.parent
139+ if grandparent is None:
140+ self.parser._logWarning(
141+ 'Found SCSI device without a grandparent: %s.'
142+ % self.device_id)
143+ return None
144+ return grandparent
145+
146
147 class UdevDevice(BaseDevice):
148 """The representation of a udev device node."""
149
150- def __init__(self, udev_data, sysfs_data, parser):
151+ def __init__(self, parser, udev_data, sysfs_data=None, dmi_data=None):
152 """HALDevice constructor.
153
154 :param udevdata: The udev data for this device
155@@ -2369,6 +2390,7 @@
156 super(UdevDevice, self).__init__(parser)
157 self.udev = udev_data
158 self.sysfs = sysfs_data
159+ self.dmi = dmi_data
160
161 @property
162 def device_id(self):
163@@ -2376,6 +2398,14 @@
164 return self.udev['P']
165
166 @property
167+ def root_device_ids(self):
168+ """The vendor and product IDs of the root device."""
169+ return {
170+ 'vendor': self.dmi.get('/sys/class/dmi/id/sys_vendor'),
171+ 'product': self.dmi.get('/sys/class/dmi/id/product_name')
172+ }
173+
174+ @property
175 def is_pci(self):
176 """True, if this is a PCI device, else False."""
177 return self.udev['E'].get('SUBSYSTEM') == 'pci'
178@@ -2410,6 +2440,30 @@
179 return self.pci_class_info[1]
180
181 @property
182+ def pci_ids(self):
183+ """The PCI vendor and product IDs.
184+
185+ :return: A dictionary containing the vendor and product IDs.
186+ The IDs are set to None for Non-PCI devices.
187+ """
188+ if self.is_pci:
189+ # SubmissionParser.checkUdevPciProperties() ensures that
190+ # each PCI device has the property PCI_ID and that is
191+ # consists of two 4-digit hexadecimal numbers, separated
192+ # by a ':'.
193+ id_string = self.udev['E']['PCI_ID']
194+ ids = id_string.split(':')
195+ return {
196+ 'vendor': int(ids[0], 16),
197+ 'product': int(ids[1], 16),
198+ }
199+ else:
200+ return {
201+ 'vendor': None,
202+ 'product': None,
203+ }
204+
205+ @property
206 def is_usb(self):
207 """True, if this is a USB device, else False."""
208 return self.udev['E'].get('SUBSYSTEM') == 'usb'
209@@ -2418,8 +2472,9 @@
210 def usb_ids(self):
211 """The vendor ID, product ID, product version for USB devices.
212
213- :return: [vendor_id, product_id, version] for USB devices
214- or [None, None, None] for other devices.
215+ :return: A dictionary containing the vendor and product IDs and
216+ the product version for USB devices.
217+ The IDs are set to None for Non-USB devices.
218 """
219 if self.is_usb:
220 # udev represents USB device IDs as strings
221@@ -2428,19 +2483,27 @@
222 # SubmissionParser.checkUdevUsbProperties() ensures that
223 # the string PRODUCT is in the format required below.
224 product_info = self.udev['E']['PRODUCT'].split('/')
225- return [int(part, 16) for part in product_info]
226+ return {
227+ 'vendor': int(product_info[0], 16),
228+ 'product': int(product_info[1], 16),
229+ 'version': int(product_info[2], 16),
230+ }
231 else:
232- return [None, None, None]
233+ return {
234+ 'vendor': None,
235+ 'product': None,
236+ 'version': None,
237+ }
238
239 @property
240 def usb_vendor_id(self):
241 """See `BaseDevice`."""
242- return self.usb_ids[0]
243+ return self.usb_ids['vendor']
244
245 @property
246 def usb_product_id(self):
247 """See `BaseDevice`."""
248- return self.usb_ids[1]
249+ return self.usb_ids['product']
250
251 @property
252 def is_scsi_device(self):
253@@ -2476,6 +2539,107 @@
254 else:
255 return None
256
257+ @property
258+ def raw_bus(self):
259+ """See `BaseDevice`."""
260+ # udev specifies the property SUBSYSTEM for most devices;
261+ # some devices have additionally the more specific property
262+ # DEVTYPE. DEVTYPE is preferable.
263+ # The root device has the subsystem/bus value "acpi", which
264+ # is a bit nonsensical.
265+ if self.device_id == UDEV_ROOT_PATH:
266+ return None
267+ properties = self.udev['E']
268+ devtype = properties.get('DEVTYPE')
269+ if devtype is not None:
270+ return devtype
271+ return properties.get('SUBSYSTEM')
272+
273+ def getVendorOrProduct(self, type_):
274+ """Return the vendor or product of this device.
275+
276+ :return: The vendor or product data for this device.
277+ :param type_: 'vendor' or 'product'
278+ """
279+ assert type_ in ('vendor', 'product'), (
280+ 'Unexpected value of type_: %r' % type_)
281+
282+ bus = self.raw_bus
283+ if self.device_id == UDEV_ROOT_PATH:
284+ # udev does not known about any product information for
285+ # the root device. We use DMI data instead.
286+ return self.root_device_ids[type_]
287+ elif bus == 'scsi_device':
288+ return self.getScsiVendorAndModelName()[type_]
289+ elif bus in ('pci', 'usb_device'):
290+ # XXX Abel Deuring 2009-10-13, bug 450480: udev does not
291+ # provide human-readable vendor and product names for
292+ # USB and PCI devices. We should retrieve these from
293+ # http://www.linux-usb.org/usb.ids and
294+ # http://pciids.sourceforge.net/v2.2/pci.ids
295+ return 'Unknown'
296+ else:
297+ # We don't process yet other devices than complete systems,
298+ # PCI, USB devices and those devices that are represented
299+ # in udev as SCSI devices: real SCSI devices, and
300+ # IDE/ATA/SATA devices.
301+ return None
302+
303+ @property
304+ def vendor(self):
305+ """See `BaseDevice`."""
306+ return self.getVendorOrProduct('vendor')
307+
308+ @property
309+ def product(self):
310+ """See `BaseDevice`."""
311+ return self.getVendorOrProduct('product')
312+
313+ def getVendorOrProductID(self, type_):
314+ """Return the vendor or product ID of this device.
315+
316+ :return: The vendor or product ID for this device.
317+ :param type_: 'vendor' or 'product'
318+ """
319+ assert type_ in ('vendor', 'product'), (
320+ 'Unexpected value of type_: %r' % type_)
321+
322+ bus = self.raw_bus
323+ if self.device_id == UDEV_ROOT_PATH:
324+ # udev does not known about any product information for
325+ # the root device. We use DMI data instead.
326+ if type_ == 'vendor':
327+ return self.dmi.get('/sys/class/dmi/id/sys_vendor')
328+ else:
329+ return self.dmi.get('/sys/class/dmi/id/product_name')
330+ elif bus == 'scsi_device':
331+ return self.getScsiVendorAndModelName()[type_]
332+ elif bus == 'pci':
333+ return self.pci_ids[type_]
334+ elif bus == 'usb_device':
335+ return self.usb_ids[type_]
336+ else:
337+ # We don't process yet other devices than complete systems,
338+ # PCI, USB devices and those devices that are represented
339+ # in udev as SCSI devices: real SCSI devices, and
340+ # IDE/ATA/SATA devices.
341+ return None
342+
343+ @property
344+ def vendor_id(self):
345+ """See `BaseDevice`."""
346+ return self.getVendorOrProductID('vendor')
347+
348+ @property
349+ def product_id(self):
350+ """See `BaseDevice`."""
351+ return self.getVendorOrProductID('product')
352+
353+ @property
354+ def driver_name(self):
355+ """See `BaseDevice`."""
356+ return self.udev['E'].get('DRIVER')
357+
358
359 class ProcessingLoop(object):
360 """An `ITunableLoop` for processing HWDB submissions."""
361
362=== modified file 'lib/canonical/launchpad/scripts/tests/test_hwdb_submission_processing.py'
363--- lib/canonical/launchpad/scripts/tests/test_hwdb_submission_processing.py 2009-10-12 14:50:22 +0000
364+++ lib/canonical/launchpad/scripts/tests/test_hwdb_submission_processing.py 2009-10-14 15:20:31 +0000
365@@ -539,6 +539,214 @@
366 'HAL property info.bus.')
367
368
369+ def test_HALDevice_scsi_controller_usb_storage_device(self):
370+ """test of HALDevice.scsi_controller.
371+
372+ The physical device is a USB storage device.
373+ """
374+ devices = [
375+ # The main node of the USB storage device.
376+ {
377+ 'id': 1,
378+ 'udi': self.UDI_USB_STORAGE,
379+ 'properties': {
380+ 'info.bus': ('usb_device', 'str'),
381+ },
382+ },
383+ # The storage interface of the USB device.
384+ {
385+ 'id': 2,
386+ 'udi': self.UDI_USB_STORAGE_IF0,
387+ 'properties': {
388+ 'info.bus': ('usb', 'str'),
389+ 'info.parent': (self.UDI_USB_STORAGE, 'str'),
390+ },
391+ },
392+ # The fake SCSI host of the storage device. Note that HAL does
393+ # _not_ provide the info.bus property.
394+ {
395+ 'id': 3,
396+ 'udi': self.UDI_USB_STORAGE_SCSI_HOST,
397+ 'properties': {
398+ 'info.parent': (self.UDI_USB_STORAGE_IF0, 'str'),
399+ },
400+ },
401+ # The fake SCSI disk.
402+ {
403+ 'id': 3,
404+ 'udi': self.UDI_USB_STORAGE_SCSI_DEVICE,
405+ 'properties': {
406+ 'info.bus': ('scsi', 'str'),
407+ 'info.parent': (self.UDI_USB_STORAGE_SCSI_HOST, 'str'),
408+ },
409+ },
410+ ]
411+ parsed_data = {
412+ 'hardware': {
413+ 'hal': {
414+ 'devices': devices,
415+ },
416+ },
417+ }
418+
419+ parser = SubmissionParser()
420+ parser.buildDeviceList(parsed_data)
421+
422+ usb_fake_scsi_disk = parser.hal_devices[
423+ self.UDI_USB_STORAGE_SCSI_DEVICE]
424+ usb_main_device = parser.hal_devices[self.UDI_USB_STORAGE_IF0]
425+ self.assertEqual(usb_main_device, usb_fake_scsi_disk.scsi_controller)
426+
427+ def test_HALDevice_scsi_controller_pci_controller(self):
428+ """test of HALDevice.scsi_controller.
429+
430+ Variant for a SCSI device connected to a PCI controller.
431+ """
432+ devices = [
433+ # The PCI host controller.
434+ {
435+ 'id': 1,
436+ 'udi': self.UDI_SATA_CONTROLLER,
437+ 'properties': {
438+ 'info.bus': ('pci', 'str'),
439+ 'pci.device_class': (PCI_CLASS_STORAGE, 'int'),
440+ 'pci.device_subclass': (PCI_SUBCLASS_STORAGE_SATA,
441+ 'int'),
442+ },
443+ },
444+ # The (fake or real) SCSI host of the storage device.
445+ {
446+ 'id': 2,
447+ 'udi': self.UDI_SATA_CONTROLLER_SCSI,
448+ 'properties': {
449+ 'info.parent': (self.UDI_SATA_CONTROLLER, 'str'),
450+ },
451+ },
452+ # The (possibly fake) SCSI disk.
453+ {
454+ 'id': 3,
455+ 'udi': self.UDI_SATA_DISK,
456+ 'properties': {
457+ 'info.bus': ('scsi', 'str'),
458+ 'info.parent': (self.UDI_SATA_CONTROLLER_SCSI, 'str'),
459+ },
460+ },
461+ ]
462+ parsed_data = {
463+ 'hardware': {
464+ 'hal': {
465+ 'devices': devices,
466+ },
467+ },
468+ }
469+
470+ parser = SubmissionParser()
471+ parser.buildDeviceList(parsed_data)
472+
473+ scsi_device = parser.hal_devices[self.UDI_SATA_DISK]
474+ controller = parser.hal_devices[self.UDI_SATA_CONTROLLER]
475+ self.assertEqual(controller, scsi_device.scsi_controller)
476+
477+ def test_HALDevice_scsi_controller_non_scsi_device(self):
478+ """test of HALDevice.scsi_controller.
479+
480+ Variant for non-SCSI devices.
481+ """
482+ devices = [
483+ {
484+ 'id': 1,
485+ 'udi': self.UDI_COMPUTER,
486+ 'properties': {},
487+ },
488+ ]
489+ parsed_data = {
490+ 'hardware': {
491+ 'hal': {
492+ 'devices': devices,
493+ },
494+ },
495+ }
496+
497+ parser = SubmissionParser()
498+ parser.buildDeviceList(parsed_data)
499+
500+ device = parser.hal_devices[self.UDI_COMPUTER]
501+ self.assertEqual(None, device.scsi_controller)
502+
503+ def test_HALDevice_scsi_controller_no_grandparent(self):
504+ """test of HALDevice.scsi_controller.
505+
506+ Variant for a SCSI device without a grandparent device.
507+ """
508+ devices = [
509+ # The (fake or real) SCSI host of the storage device.
510+ {
511+ 'id': 1,
512+ 'udi': self.UDI_SATA_CONTROLLER_SCSI,
513+ 'properties': {},
514+ },
515+ # The (possibly fake) SCSI disk.
516+ {
517+ 'id': 2,
518+ 'udi': self.UDI_SATA_DISK,
519+ 'properties': {
520+ 'info.bus': ('scsi', 'str'),
521+ 'info.parent': (self.UDI_SATA_CONTROLLER_SCSI, 'str'),
522+ },
523+ },
524+ ]
525+ parsed_data = {
526+ 'hardware': {
527+ 'hal': {
528+ 'devices': devices,
529+ },
530+ },
531+ }
532+
533+ parser = SubmissionParser(self.log)
534+ parser.submission_key = 'SCSI device without grandparent device'
535+ parser.buildDeviceList(parsed_data)
536+
537+ scsi_device = parser.hal_devices[self.UDI_SATA_DISK]
538+ self.assertEqual(None, scsi_device.scsi_controller)
539+ self.assertWarningMessage(
540+ parser.submission_key,
541+ "Found SCSI device without a grandparent: %s."
542+ % self.UDI_SATA_DISK)
543+
544+ def test_HALDevice_scsi_controller_no_parent(self):
545+ """test of HALDevice.scsi_controller.
546+
547+ Variant for a SCSI device without a parent device.
548+ """
549+ devices = [
550+ # The (possibly fake) SCSI disk.
551+ {
552+ 'id': 1,
553+ 'udi': self.UDI_SATA_DISK,
554+ 'properties': {
555+ 'info.bus': ('scsi', 'str'),
556+ },
557+ },
558+ ]
559+ parsed_data = {
560+ 'hardware': {
561+ 'hal': {
562+ 'devices': devices,
563+ },
564+ },
565+ }
566+
567+ parser = SubmissionParser(self.log)
568+ parser.submission_key = 'SCSI device without parent device'
569+ parser.buildDeviceList(parsed_data)
570+
571+ scsi_device = parser.hal_devices[self.UDI_SATA_DISK]
572+ self.assertEqual(None, scsi_device.scsi_controller)
573+ self.assertWarningMessage(
574+ parser.submission_key,
575+ "Found SCSI device without a parent: %s." % self.UDI_SATA_DISK)
576+
577 def testHALDeviceGetRealBus(self):
578 """Test of HALDevice.real_bus, generic case.
579
580@@ -1598,18 +1806,16 @@
581 parser = SubmissionParser(self.log)
582 parser.buildDeviceList(parsed_data)
583 device = parser.hal_devices[self.UDI_SCSI_DISK]
584- vendor, model = device.getScsiVendorAndModelName()
585+ vendor_model = device.getScsiVendorAndModelName()
586 self.assertEqual(
587- vendor, 'SHARP',
588+ {
589+ 'vendor': 'SHARP',
590+ 'product': 'JX250 SCSI',
591+ },
592+ vendor_model,
593 'Unexpected result of HWDevice.getScsiVendorAndModelName '
594 'for a regular SCSI device. Expected vendor name SHARP, got %r.'
595- % vendor)
596- self.assertEqual(
597- model, 'JX250 SCSI',
598- 'Unexpected result of HWDevice.getScsiVendorAndModelName '
599- 'for a regular SCSI device. Expected model name JX250 SCSI , '
600- 'got %r.'
601- % model)
602+ % vendor_model)
603
604 def testHALDeviceSCSIVendorModelNameATADiskShortModelName(self):
605 """Test of HALDevice.getScsiVendorAndModelName, ATA disk (1).
606@@ -1639,18 +1845,16 @@
607 parser = SubmissionParser(self.log)
608 parser.buildDeviceList(parsed_data)
609 device = parser.hal_devices[self.UDI_SCSI_DISK]
610- vendor, model = device.getScsiVendorAndModelName()
611- self.assertEqual(
612- vendor, 'Hitachi',
613- 'Unexpected result of HWDevice.getScsiVendorAndModelName '
614- 'for an ATA SCSI device. Expected vendor name Hitachi, got %r.'
615- % vendor)
616- self.assertEqual(
617- model, 'HTS54161',
618- 'Unexpected result of HWDevice.getScsiVendorAndModelName '
619- 'for a reguale SCSI device. Expected vendor name HTS54161, '
620- 'got %r.'
621- % model)
622+ vendor_model = device.getScsiVendorAndModelName()
623+ self.assertEqual(
624+ {
625+ 'vendor': 'Hitachi',
626+ 'product': 'HTS54161',
627+ },
628+ vendor_model,
629+ 'Unexpected result of HWDevice.getScsiVendorAndModelName '
630+ 'for an ATA SCSI device: %r.'
631+ % vendor_model)
632
633 def testHALDeviceSCSIVendorModelNameATADiskLongModelName(self):
634 """Test of HALDevice.getScsiVendorAndModelName, ATA disk (2).
635@@ -1679,18 +1883,16 @@
636 parser = SubmissionParser(self.log)
637 parser.buildDeviceList(parsed_data)
638 device = parser.hal_devices[self.UDI_SCSI_DISK]
639- vendor, model = device.getScsiVendorAndModelName()
640- self.assertEqual(
641- vendor, 'ATA',
642- 'Unexpected result of HWDevice.getScsiVendorAndModelName '
643- 'for a reguale SCSI device. Expected vendor name ATA, got %r.'
644- % vendor)
645- self.assertEqual(
646- model, 'HTC426060G9AT00',
647- 'Unexpected result of HWDevice.getScsiVendorAndModelName '
648- 'for a reguale SCSI device. Expected vendor name '
649- 'HTC426060G9AT00 , got %r.'
650- % model)
651+ vendor_product = device.getScsiVendorAndModelName()
652+ self.assertEqual(
653+ {
654+ 'vendor': 'ATA',
655+ 'product': 'HTC426060G9AT00',
656+ },
657+ vendor_product,
658+ 'Unexpected result of HWDevice.getScsiVendorAndModelName '
659+ 'for a reguale SCSI device: %r.'
660+ % vendor_product)
661
662 def testHALDeviceVendorFromInfoVendor(self):
663 """Test of HALDevice.vendor, regular case.
664@@ -2606,6 +2808,11 @@
665 }
666 }
667
668+ root_device_dmi_data = {
669+ '/sys/class/dmi/id/sys_vendor': 'FUJITSU SIEMENS',
670+ '/sys/class/dmi/id/product_name': 'LIFEBOOK E8210',
671+ }
672+
673 pci_device_data = {
674 'P': '/devices/pci0000:00/0000:00:1f.2',
675 'E': {
676@@ -2614,6 +2821,7 @@
677 'PCI_SUBSYS_ID': '10CF:1387',
678 'PCI_SLOT_NAME': '0000:00:1f.2',
679 'SUBSYSTEM': 'pci',
680+ 'DRIVER': 'ahci',
681 }
682 }
683
684@@ -2624,114 +2832,168 @@
685 'DEVTYPE': 'usb_device',
686 'PRODUCT': '46d/a01/1013',
687 'TYPE': '0/0/0',
688+ 'DRIVER': 'usb',
689 },
690 }
691
692- scsi_device_data = {
693- 'P': '/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0',
694+ scsi_scanner_device_data = {
695+ 'P': ('/devices/pci0000:00/0000:00:1e.0/0000:08:03.0/0000:09:00.0/'
696+ 'host6/target6:0:1/6:0:1:0'),
697 'E': {
698+ 'DEVTYPE': 'scsi_device',
699 'SUBSYSTEM': 'scsi',
700- 'DEVTYPE': 'scsi_device',
701 },
702 }
703
704- scsi_device_sysfs_data = {
705- 'vendor': 'MATSHITA',
706- 'model': 'DVD-RAM UJ-841S',
707- 'type': '5',
708+ scsi_scanner_device_sysfs_data = {
709+ 'vendor': 'FUJITSU',
710+ 'model': 'fi-5120Cdj',
711+ 'type': '6',
712+ }
713+
714+ no_subsystem_device_data = {
715+ 'P': '/devices/pnp0/00:00',
716+ 'E': {}
717 }
718
719 def test_device_id(self):
720 """Test of UdevDevice.device_id."""
721- device = UdevDevice(self.pci_device_data, None, None)
722+ device = UdevDevice(None, self.pci_device_data)
723 self.assertEqual(
724 '/devices/pci0000:00/0000:00:1f.2', device.device_id,
725 'Unexpected value of UdevDevice.device_id.')
726
727+ def test_root_device_ids(self):
728+ device = UdevDevice(
729+ None, self.root_device, None, self.root_device_dmi_data)
730+ self.assertEqual(
731+ {
732+ 'vendor': 'FUJITSU SIEMENS',
733+ 'product': 'LIFEBOOK E8210',
734+ },
735+ device.root_device_ids)
736+
737+ device = UdevDevice(
738+ None, self.root_device, None, {})
739+ self.assertEqual(
740+ {
741+ 'vendor': None,
742+ 'product': None,
743+ },
744+ device.root_device_ids)
745+
746 def test_is_pci(self):
747 """Test of UdevDevice.is_pci."""
748- device = UdevDevice(self.pci_device_data, None, None)
749+ device = UdevDevice(None, self.pci_device_data)
750 self.assertTrue(device.is_pci)
751
752- device = UdevDevice(self.root_device, None, None)
753+ device = UdevDevice(None, self.root_device)
754 self.assertFalse(device.is_pci)
755
756 def test_pci_class_info(self):
757 """Test of UdevDevice.pci_class_info"""
758- device = UdevDevice(self.pci_device_data, None, None)
759+ device = UdevDevice(None, self.pci_device_data)
760 self.assertEqual(
761 (1, 6, 2), device.pci_class_info,
762 'Invalid value of UdevDevice.pci_class_info for PCI device.')
763
764- device = UdevDevice(self.root_device, None, None)
765+ device = UdevDevice(None, self.root_device)
766 self.assertEqual(
767 (None, None, None), device.pci_class_info,
768 'Invalid value of UdevDevice.pci_class_info for Non-PCI device.')
769
770 def test_pci_class(self):
771 """Test of UdevDevice.pci_class"""
772- device = UdevDevice(self.pci_device_data, None, None)
773+ device = UdevDevice(None, self.pci_device_data)
774 self.assertEqual(
775 1, device.pci_class,
776 'Invalid value of UdevDevice.pci_class for PCI device.')
777
778- device = UdevDevice(self.root_device, None, None)
779+ device = UdevDevice(None, self.root_device)
780 self.assertEqual(
781 None, device.pci_class,
782 'Invalid value of UdevDevice.pci_class for Non-PCI device.')
783
784 def test_pci_subclass(self):
785 """Test of UdevDevice.pci_subclass"""
786- device = UdevDevice(self.pci_device_data, None, None)
787+ device = UdevDevice(None, self.pci_device_data)
788 self.assertEqual(
789 6, device.pci_subclass,
790 'Invalid value of UdevDevice.pci_class for PCI device.')
791
792- device = UdevDevice(self.root_device, None, None)
793+ device = UdevDevice(None, self.root_device)
794 self.assertEqual(
795 None, device.pci_class,
796 'Invalid value of UdevDevice.pci_class for Non-PCI device.')
797
798+ def test_pci_ids(self):
799+ """Test of UdevDevice.pci_ids"""
800+ device = UdevDevice(None, self.pci_device_data)
801+ self.assertEqual(
802+ {'vendor': 0x8086,
803+ 'product': 0x27C5,
804+ },
805+ device.pci_ids,
806+ 'Invalid value of UdevDevice.pci_ids for PCI device.')
807+
808+ device = UdevDevice(None, self.usb_device_data)
809+ self.assertEqual(
810+ {'vendor': None,
811+ 'product': None,
812+ },
813+ device.pci_ids,
814+ 'Invalid value of UdevDevice.pci_ids for Non-PCI device.')
815+
816 def test_is_usb(self):
817 """Test of UdevDevice.is_usb"""
818- device = UdevDevice(self.usb_device_data, None, None)
819+ device = UdevDevice(None, self.usb_device_data)
820 self.assertTrue(device.is_usb)
821
822- device = UdevDevice(self.pci_device_data, None, None)
823+ device = UdevDevice(None, self.pci_device_data)
824 self.assertFalse(device.is_usb)
825
826 def test_usb_ids(self):
827 """Test of UdevDevice.usb_ids"""
828- device = UdevDevice(self.usb_device_data, None, None)
829+ device = UdevDevice(None, self.usb_device_data)
830 self.assertEqual(
831- [0x46d, 0xa01, 0x1013], device.usb_ids,
832+ {
833+ 'vendor': 0x46d,
834+ 'product': 0xa01,
835+ 'version': 0x1013,
836+ },
837+ device.usb_ids,
838 'Invalid value of UdevDevice.usb_ids for USB device.')
839
840- device = UdevDevice(self.root_device, None, None)
841+ device = UdevDevice(None, self.root_device)
842 self.assertEqual(
843- [None, None, None], device.usb_ids,
844+ {
845+ 'vendor': None,
846+ 'product': None,
847+ 'version': None,
848+ },
849+ device.usb_ids,
850 'Invalid value of UdevDevice.usb_ids for Non-USB device.')
851
852 def test_usb_vendor_id(self):
853 """Test of UdevDevice.usb_vendor_id"""
854- device = UdevDevice(self.usb_device_data, None, None)
855+ device = UdevDevice(None, self.usb_device_data)
856 self.assertEqual(
857 0x46d, device.usb_vendor_id,
858 'Invalid value of UdevDevice.usb_vendor_id for USB device.')
859
860- device = UdevDevice(self.root_device, None, None)
861+ device = UdevDevice(None, self.root_device)
862 self.assertEqual(
863 None, device.usb_vendor_id,
864 'Invalid value of UdevDevice.usb_vendor_id for Non-USB device.')
865
866 def test_usb_product_id(self):
867 """Test of UdevDevice.usb_product_id"""
868- device = UdevDevice(self.usb_device_data, None, None)
869+ device = UdevDevice(None, self.usb_device_data)
870 self.assertEqual(
871 0xa01, device.usb_product_id,
872 'Invalid value of UdevDevice.usb_product_id for USB device.')
873
874- device = UdevDevice(self.root_device, None, None)
875+ device = UdevDevice(None, self.root_device)
876 self.assertEqual(
877 None, device.usb_product_id,
878 'Invalid value of UdevDevice.usb_product_id for Non-USB device.')
879@@ -2739,29 +3001,173 @@
880 def test_is_scsi_device(self):
881 """Test of UdevDevice.is_scsi_device."""
882 device = UdevDevice(
883- self.scsi_device_data, self.scsi_device_sysfs_data, None)
884+ None, self.scsi_scanner_device_data,
885+ self.scsi_scanner_device_sysfs_data)
886 self.assertTrue(device.is_scsi_device)
887
888- device = UdevDevice(self.root_device, None, None)
889+ device = UdevDevice(None, self.root_device)
890 self.assertFalse(device.is_scsi_device)
891
892 def test_scsi_vendor(self):
893 """Test of UdevDevice.scsi_vendor."""
894 device = UdevDevice(
895- self.scsi_device_data, self.scsi_device_sysfs_data, None)
896- self.assertEqual('MATSHITA', device.scsi_vendor)
897- device = UdevDevice(self.root_device, None, None)
898+ None, self.scsi_scanner_device_data,
899+ self.scsi_scanner_device_sysfs_data)
900+ self.assertEqual('FUJITSU', device.scsi_vendor)
901+ device = UdevDevice(None, self.root_device)
902 self.assertEqual(None, device.scsi_vendor)
903
904 def test_scsi_model(self):
905 """Test of UdevDevice.scsi_model."""
906 device = UdevDevice(
907- self.scsi_device_data, self.scsi_device_sysfs_data, None)
908- self.assertEqual('DVD-RAM UJ-841S', device.scsi_model)
909+ None, self.scsi_scanner_device_data,
910+ self.scsi_scanner_device_sysfs_data)
911+ self.assertEqual('fi-5120Cdj', device.scsi_model)
912
913- device = UdevDevice(self.root_device, None, None)
914+ device = UdevDevice(None, self.root_device)
915 self.assertEqual(None, device.scsi_model)
916
917+ def test_raw_bus(self):
918+ """Test of UdevDevice.raw_bus."""
919+ device = UdevDevice(None, self.root_device)
920+ self.assertEqual(None, device.raw_bus)
921+
922+ device = UdevDevice(None, self.pci_device_data)
923+ self.assertEqual('pci', device.raw_bus)
924+
925+ device = UdevDevice(None, self.usb_device_data)
926+ self.assertEqual('usb_device', device.raw_bus)
927+
928+ device = UdevDevice(None, self.no_subsystem_device_data)
929+ self.assertEqual(None, device.raw_bus)
930+
931+ def test_getVendorOrProduct(self):
932+ """Test of UdevDevice.getVendorOrProduct()."""
933+ device = UdevDevice(
934+ None, self.root_device, None, self.root_device_dmi_data)
935+ self.assertEqual(
936+ 'FUJITSU SIEMENS', device.getVendorOrProduct('vendor'))
937+ self.assertEqual(
938+ 'LIFEBOOK E8210', device.getVendorOrProduct('product'))
939+ self.assertRaises(
940+ AssertionError, device.getVendorOrProduct, 'nonsense')
941+
942+ device = UdevDevice(None, self.pci_device_data)
943+ self.assertEqual('Unknown', device.getVendorOrProduct('vendor'))
944+ self.assertEqual('Unknown', device.getVendorOrProduct('product'))
945+
946+ device = UdevDevice(None, self.usb_device_data)
947+ self.assertEqual('Unknown', device.getVendorOrProduct('vendor'))
948+ self.assertEqual('Unknown', device.getVendorOrProduct('product'))
949+
950+ device = UdevDevice(
951+ None, self.scsi_scanner_device_data,
952+ self.scsi_scanner_device_sysfs_data)
953+ self.assertEqual('FUJITSU', device.getVendorOrProduct('vendor'))
954+ self.assertEqual('fi-5120Cdj', device.getVendorOrProduct('product'))
955+
956+ device = UdevDevice(None, self.no_subsystem_device_data)
957+ self.assertEqual(None, device.getVendorOrProduct('vendor'))
958+ self.assertEqual(None, device.getVendorOrProduct('product'))
959+
960+ def test_vendor(self):
961+ """Test of UdevDevice.vendor."""
962+ device = UdevDevice(
963+ None, self.root_device, None, self.root_device_dmi_data)
964+ self.assertEqual('FUJITSU SIEMENS', device.vendor)
965+
966+ def test_product(self):
967+ """Test of UdevDevice.product."""
968+ device = UdevDevice(
969+ None, self.root_device, None, self.root_device_dmi_data)
970+ self.assertEqual('LIFEBOOK E8210', device.product)
971+
972+ def test_getVendorOrProductID(self):
973+ """Test of UdevDevice.getVendorOrProduct()."""
974+ device = UdevDevice(
975+ None, self.root_device, None, self.root_device_dmi_data)
976+ self.assertEqual(
977+ 'FUJITSU SIEMENS', device.getVendorOrProductID('vendor'))
978+ self.assertEqual(
979+ 'LIFEBOOK E8210', device.getVendorOrProductID('product'))
980+ self.assertRaises(
981+ AssertionError, device.getVendorOrProductID, 'nonsense')
982+
983+ device = UdevDevice(None, self.pci_device_data)
984+ self.assertEqual(0x8086, device.getVendorOrProductID('vendor'))
985+ self.assertEqual(0x27C5, device.getVendorOrProductID('product'))
986+
987+ device = UdevDevice(None, self.usb_device_data)
988+ self.assertEqual(0x46d, device.getVendorOrProductID('vendor'))
989+ self.assertEqual(0xa01, device.getVendorOrProductID('product'))
990+
991+ device = UdevDevice(
992+ None, self.scsi_scanner_device_data,
993+ self.scsi_scanner_device_sysfs_data)
994+ self.assertEqual('FUJITSU', device.getVendorOrProductID('vendor'))
995+ self.assertEqual('fi-5120Cdj', device.getVendorOrProductID('product'))
996+
997+ device = UdevDevice(
998+ None, self.no_subsystem_device_data)
999+ self.assertEqual(None, device.getVendorOrProductID('vendor'))
1000+ self.assertEqual(None, device.getVendorOrProductID('product'))
1001+
1002+ def test_vendor_id(self):
1003+ """Test of UdevDevice.vendor_id."""
1004+ device = UdevDevice(
1005+ None, self.root_device, None, self.root_device_dmi_data)
1006+ self.assertEqual('FUJITSU SIEMENS', device.vendor_id)
1007+
1008+ def test_product_id(self):
1009+ """Test of UdevDevice.product_id."""
1010+ device = UdevDevice(
1011+ None, self.root_device, None, self.root_device_dmi_data)
1012+ self.assertEqual('LIFEBOOK E8210', device.product_id)
1013+
1014+ def test_vendor_id_for_db(self):
1015+ """Test of UdevDevice.vendor_id_for_db."""
1016+ device = UdevDevice(
1017+ None, self.root_device, None, self.root_device_dmi_data)
1018+ self.assertEqual('FUJITSU SIEMENS', device.vendor_id_for_db)
1019+
1020+ device = UdevDevice(None, self.pci_device_data)
1021+ self.assertEqual('0x8086', device.vendor_id_for_db)
1022+
1023+ device = UdevDevice(None, self.usb_device_data)
1024+ self.assertEqual('0x046d', device.vendor_id_for_db)
1025+
1026+ device = UdevDevice(
1027+ None, self.scsi_scanner_device_data,
1028+ self.scsi_scanner_device_sysfs_data)
1029+ self.assertEqual('FUJITSU ', device.vendor_id_for_db)
1030+
1031+ def test_product_id_for_db(self):
1032+ """Test of UdevDevice.product_id_for_db."""
1033+ device = UdevDevice(
1034+ None, self.root_device, None, self.root_device_dmi_data)
1035+ self.assertEqual('LIFEBOOK E8210', device.product_id_for_db)
1036+
1037+ device = UdevDevice(None, self.pci_device_data)
1038+ self.assertEqual('0x27c5', device.product_id_for_db)
1039+
1040+ device = UdevDevice(None, self.usb_device_data)
1041+ self.assertEqual('0x0a01', device.product_id_for_db)
1042+
1043+ device = UdevDevice(
1044+ None, self.scsi_scanner_device_data,
1045+ self.scsi_scanner_device_sysfs_data)
1046+ self.assertEqual('fi-5120Cdj ', device.product_id_for_db)
1047+
1048+ def test_driver_name(self):
1049+ """Test of UdevDevice.driver_name."""
1050+ device = UdevDevice(None, self.pci_device_data)
1051+ self.assertEqual('ahci', device.driver_name)
1052+
1053+ device = UdevDevice(
1054+ None, self.root_device, None, self.root_device_dmi_data)
1055+ self.assertEqual(None, device.driver_name)
1056+
1057+
1058 class TestHWDBSubmissionTablePopulation(TestCaseHWDB):
1059 """Tests of the HWDB popoluation with submitted data."""
1060

Subscribers

People subscribed via source and target branches

to status/vote changes: