Merge lp:~adeuring/launchpad/hwdb-test-natty-mess into lp:launchpad

Proposed by Abel Deuring
Status: Merged
Approved by: Abel Deuring
Approved revision: no longer in the source branch.
Merged at revision: 13870
Proposed branch: lp:~adeuring/launchpad/hwdb-test-natty-mess
Merge into: lp:launchpad
Diff against target: 560 lines (+529/-1)
3 files modified
lib/canonical/launchpad/scripts/tests/hardwaretest-natty.xml (+473/-0)
lib/lp/hardwaredb/scripts/hwdbsubmissions.py (+37/-1)
lib/lp/hardwaredb/tests/test_hwdb_submission_validation.py (+19/-0)
To merge this branch: bzr merge lp:~adeuring/launchpad/hwdb-test-natty-mess
Reviewer Review Type Date Requested Status
Francis J. Lacoste (community) Approve
Review via email: mp+73722@code.launchpad.net

Commit message

[r=flacoste][bug=839102] allow processing of HWDB submissions from Natty

Description of the change

This branch fixes the problem that HWDB submissions from Natty can not be processed.

The reason for the failure is simple: The submission processing script expects an XML file with a structure as defined in lib/canonical/launchpad/scripts/hardware-1_0.rng

One part of the required XML data looks like

  <hardware>
    <udev>(lots of text data)
    </udev>
    <dmi>(more text data)
    </dmi>
    (other tags)
  </hardware>

The reports from Natty do not contain the tags <udev> and <dmi>; their content is instead stored in

  <context>
    <info command="udevadm info --export-db">(text data)
    </info>
    <info command="grep -r . /sys/class/dmi/id/ 2&gt;/dev/null">(test data)
    </info>
  </context>

The fix is quite simple: Two regular expressions check if the tags <udev> and <dmi> exist within <hardware>; if not, these tags are inserted, provided that the corresponding <info> nodes can be found.

This is a bit of a "brute force" fix. I tried at first to modify the etree structure, but then flacoste gave me the hint that the RelaxNG validation is _not_ on the etree representaion of the data, but on the "text string". Creating the etree, modifying it, writing its contents into a StringIO buffer, and finally passing the buffer's content to the RNG validator should have worked too, but would be much slower.

A note about the diff: The first 480 lines are the content of a new file with test data. Its content is a variant of the already existing file lib/canonical/launchpad/scripts/tests/hardwaretest-udev.xml and hence probably easier to understand by running

  diff -u hardwaretest-udev.xml hardwaretest-natty.xml

in lib/canonical/launchpad/scripts/tests

test: ./bin/test hardwaredb -vvt test_hwdb_submission_validation

To post a comment you must log in.
Revision history for this message
Francis J. Lacoste (flacoste) wrote :

I find the test a bit weak as it just checks that result isn't None. But I guess that's fine since the result from runValidator is a parsed etree that we know match the expected structure.

Thanks for fixing this Abel!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added file 'lib/canonical/launchpad/scripts/tests/hardwaretest-natty.xml'
--- lib/canonical/launchpad/scripts/tests/hardwaretest-natty.xml 1970-01-01 00:00:00 +0000
+++ lib/canonical/launchpad/scripts/tests/hardwaretest-natty.xml 2011-09-02 07:16:32 +0000
@@ -0,0 +1,473 @@
1<?xml version="1.0" ?>
2<system version="1.0">
3
4 <!-- Reports coming from the checkbox version in Natty do not
5 have the tags <udev> and <dmi> inside <hardware>. Instead,
6 they store the data expected in these tags in the tags
7
8 <info command="udevadm info - -export-db"> and
9 <info command="grep -r . /sys/class/dmi/id/ 2&gt;/dev/null">
10
11 inside <
12 -->
13 <!-- summary: generic information about the submission -->
14 <summary>
15
16 <!-- live_cd: Was this submission made on a system running an Ubuntu Live
17 CD or on a regular Ubuntu/Linux installation?
18 -->
19 <live_cd value="False"/>
20
21 <!-- system_id: A hash of the "system identifier". This value is intended
22 to identify the tested computer model; the value should
23 be derived from the properties
24 system.product, system.vendor of the HAL UDI
25 /org/freedesktop/Hal/devices/computer.
26 -->
27 <system_id value="f982bb1ab536469cebfd6eaadcea0ffc"/>
28
29 <!-- distribution, distroseries: These values are retrieved from
30 /etc/lsb-release, parameters DISTRIB_ID and DISTRIB_RELEASE.
31 -->
32 <distribution value="Ubuntu"/>
33 <distroseries value="7.04"/>
34
35 <!-- architecture: The processor architecture of the operating system.
36 -->
37 <architecture value="amd64"/>
38
39 <!-- private: If False, this submission is publicly accessible from
40 Launchpad, else it is only accesible by the submitter, by
41 Launchpad administrators and by scripts running with
42 administrator rights. Submissions marked "private" should
43 only be used to gather statistical data.
44 -->
45 <private value="False"/>
46
47 <!-- contactable: If True, the owner agrees to be contacted by other
48 persons about devices which appear in his submission.
49 Example of a use case: Developers can ask device owners
50 to perform tests.
51 -->
52 <contactable value="False"/>
53
54 <!-- date_created: Date and time (UTC) of the submission.
55 -->
56 <date_created value="2007-09-28T16:09:20.126842"/>
57
58 <!-- client: The name and version of the program that created the
59 submission data.
60 -->
61 <client name="hwtest" version="0.9">
62
63 <!-- plugin: name and version of a plugin used by the client.
64 This tag may appear more than once.
65 -->
66 <plugin name="architecture_info" version="1.1"/>
67 <plugin name="find_network_controllers" version="2.34"/>
68 <plugin name="internet_ping" version="1.1"/>
69 <plugin name="harddisk_speed" version="0.7"/>
70 </client>
71
72 <!-- The kernel name and version, as shown by "uname -r"
73 -->
74 <kernel-release value="2.6.28-14-generic"/>
75 </summary>
76
77 <!-- hardware: data about the hardware the submission was made on.
78 -->
79 <hardware>
80
81 <!-- udev: The output of running "udevadm info - -export-db" -->
82
83
84 <!-- Additional data for SCSI devices: vendor, model, type
85
86 For each udev node which has DEVTYPE=scsi_device, we need
87 the content of the sysfs files vendor, model, type. The data
88 is stored in the same format as the DMI data:
89 /path/to/file:filecontent
90 -->
91 <sysfs-attributes>
92P: /devices/LNXSYSTM:00/LNXPWRBN:00/input/input0
93A: modalias=input:b0019v0000p0001e0000-e0,1,k74,ramlsfw
94A: uniq=
95A: phys=LNXPWRBN/button/input0
96A: name=Power Button
97
98P: /devices/LNXSYSTM:00/device:00/PNP0A08:00/device:03/input/input8
99A: modalias=input:b0019v0000p0006e0000-e0,1,kE0,E1,E3,F0,F1,F2,F3,F4,F5,ramlsfw
100A: uniq=
101A: phys=/video/input0
102A: name=Video Bus
103</sysfs-attributes>
104
105 <!-- processors: Data about processors installed in a system.
106 The data is retrieved from /proc/cpuinfo.
107 -->
108 <processors>
109
110 <!-- processor: Data from /proc/cpuinfo about a single processor.
111 -->
112 <processor id="123" name="0">
113
114 <!-- property: The data of one line of /proc/cpuinfo.
115 attribute name: The name of the property
116 (the text left of the ':' in a line of /proc/cpuinfo)
117 attribute type: A Python type appropriate for the value.
118 -->
119 <property name="wp" type="bool">
120 True
121 </property>
122 <property name="flags" type="list">
123 <value type="str">
124 fpu
125 </value>
126 <value type="str">
127 vme
128 </value>
129 <value type="str">
130 de
131 </value>
132 </property>
133 <property name="cpu_mhz" type="float">
134 1000.0
135 </property>
136 </processor>
137 </processors>
138
139 <!-- aliases: optional data provided by the user:
140 The name of a peripheral, PCI card etc as shown by a label on
141 the device. OEM devices are often sold under different names
142 by different vendors; having a set of alias names for a device
143 allows users of the HWDB to search for information by these
144 "marketing names".
145 -->
146 <aliases>
147 <!-- alias: The "label name" of a device or system.
148 attribute target: The sysfs path of a device as given
149 in <udev>.
150 -->
151 <alias target="/devices/pci0000:00/0000:00:1f.1/host3/target3:0:0/3:0:0:0">
152
153 <!-- vendor: The vendor name shown on the device label.
154 -->
155 <vendor>Medion</vendor>
156
157 <!-- model: The model name of shown on the label.
158 -->
159 <model>QuickPrint 9876</model>
160 </alias>
161 </aliases>
162 </hardware>
163
164 <!-- software: Data about the software installed on the system.
165 -->
166 <software>
167
168 <!-- lsbrelease: The data from /etc/lsb-release.
169 -->
170 <lsbrelease>
171
172 <!-- property: the data from one line of /etc/lsb-release.
173 attribute type: A Python type appropriate for this
174 property (str).
175 -->
176 <property name="release" type="str">
177 7.04
178 </property>
179 <property name="codename" type="str">
180 feisty
181 </property>
182 <property name="distributor-id" type="str">
183 Ubuntu
184 </property>
185 <property name="description" type="str">
186 Ubuntu 7.04
187 </property>
188 <property name="dict_example" type="dict">
189 <value name="a" type="str">value for key a</value>
190 <value name="b" type="int">1234</value>
191 </property>
192 </lsbrelease>
193
194 <!-- packages: Data about the installed software packages.
195 -->
196 <packages>
197
198 <!-- package: Data about a single package.
199 The <property> sub-tags contain the DEB properties
200 "name", "priority", "section", "source", "version",
201 "installed_size", "size", "summary".
202
203 XXX Abel Deuring 2007-12-12: What about submissions
204 from RPM-based Linux versions? (And "exotic" variants
205 like Gentoo?)
206 -->
207 <package name="metacity" id="200">
208 <property name="installed_size" type="int">
209 868352
210 </property>
211 <property name="section" type="str">
212 x11
213 </property>
214 <property name="summary" type="str">
215 A lightweight GTK2 based Window Manager
216 </property>
217 <property name="priority" type="str">
218 optional
219 </property>
220 <property name="source" type="str">
221 metacity
222 </property>
223 <property name="version" type="str">
224 1:2.18.2-0ubuntu1.1
225 </property>
226 <property name="size" type="int">
227 429128
228 </property>
229 </package>
230 </packages>
231 <!-- Information extracted from Xorg.0.log.
232 HAL does not provide any information about Xorg drivers, so
233 we retrieve that from the xserver's log file.
234 -->
235 <xorg version="1.3.0">
236 <!-- driver: Data about a driver.
237 (optional)
238 attribute name: The name of the driver.
239 attribute version: The version of the driver.
240 attribute class: The module class of the driver
241 attribute device: The ID of a device driven by this driver.
242 -->
243 <driver name="fglrx" version="1.23" class="X.Org Video Driver"
244 device="12"/>
245 </xorg>
246 </software>
247
248 <!-- questions: User's answers to questions asked by the client.
249 -->
250 <questions>
251
252 <!-- question: Data of a question.
253 attribute name: The unique name of the question.
254 attribute plugin: The name of the plugin which asked
255 the question.
256 attribute version: The version of the question.
257 attribute type: Allowed values are "manual" and "automatic".
258 A "manual" question requires user input for the answer;
259 an "automatic" question gets the answer automatically.
260 -->
261 <question name="detected_network_controllers"
262 plugin="find_network_controllers">
263
264 <!-- target: Information about a device or software package the
265 question is about. The attribute "id" is the sysfs path of
266 a device as given in <udev>, or the ID of a software package
267 node.
268 This node may appear multiple times.
269 -->
270 <target id="/devices/pci0000:00/0000:00:1a.0/usb3/3-0:1.0/usb_endpoint/usbdev3.1_ep81">
271 <!-- driver: The driver which controls the target device. This tag
272 may appear more than once.
273
274 While we are working on a project called "Hardware Database",
275 we are not that much interested in the question, if a device
276 works "as such", but if their Linux driver(s) work.
277
278 It is not in every case possible to identify the used driver
279 from HAL data, so we need another way to add this information.
280 (example: HAL does not know, which driver is used for the
281 graphics card.)
282
283 Example for multiple drivers: Some scanners have a SCSI _and_
284 a USB interface; if such a scanner is tested, we not only want
285 to know, which Sane backend is used, but also, which interface
286 is used.
287
288 Also, it might be interesting to know for many USB 2.0 devices,
289 if a USB 1 (uhci_hcd or ohci_hcd driver) or the USB 2 driver
290 (ehci_hcd) was used. A USB 1 driver might for example explain
291 latency problems.
292 -->
293 <driver>ipw3945</driver>
294 </target>
295
296 <!-- ID of the 88E8055 PCI-E Gigabit Ethernet Controller -->
297 <target id="/devices/pci0000:00/0000:00:1f.1"/>
298
299 <!-- command: The command line of an external command required to
300 ask this question.
301 -->
302 <command/>
303
304 <!-- answer: The answer to the question. Two types of answers are
305 defined, "multiple_choice" and "measurement". (See below
306 for an example of the latter.)
307 attribute type: Must be "multiple_choice" or "measurement".
308 -->
309 <answer type="multiple_choice">pass</answer>
310
311 <!-- answer_choices: The list of possible choices.
312 The data should only be used for consistency
313 checks and to detect variants of the question.
314 -->
315 <answer_choices>
316 <value type="str">fail</value>
317 <value type="str">pass</value>
318 <value type="str">skip</value>
319 </answer_choices>
320
321 <!-- A user comment about the device or about the test.
322 -->
323 <comment>
324 The WLAN adapter drops the connection very frequently.
325 </comment>
326 </question>
327
328 <question name="internet_ping"
329 plugin="internet_ping">
330 <target id="/devices/pci0000:00/0000:00:1f.1"/>
331 <command/>
332 <answer type="multiple_choice">pass</answer>
333 <answer_choices>
334 <value type="str">fail</value>
335 <value type="str">pass</value>
336 <value type="str">skip</value>
337 </answer_choices>
338 </question>
339
340 <!-- example for a "measurement question"
341 -->
342 <question name="harddisk_speed"
343 plugin="harddisk_speed">
344 <target id="/devices/pci0000:00/0000:00:1f.1/host3/target3:0:0/3:0:0:0"/>
345 <command>hdparm -t /dev/sda</command>
346 <!-- answer: The answer to a "measurement question".
347 attribute type: See above.
348 attribute unit: The unit of the result of the measurement.
349 XXX Abel Deuring 2007-12-12 bug=175978 We should
350 enumerate a list of allowed units, in order to avoid
351 multiple units for the same dimension. e.g., B/sec,
352 MB/sec or inch, cm, foot.
353
354 For dimensionless values, the attribute unit is omitted.
355
356 "Percentage" and similar "convenience pseudo-units" like
357 ppm are _not_ allowed; instead a dimensionless
358 value must be used, where 0 is equivalent 0% and 1.0 is
359 equivalent to 100%.
360 -->
361 <answer type="measurement" unit="MB/sec">38.4</answer>
362 </question>
363 </questions>
364 <!-- miscellaneous additional text data.
365 -->
366 <context>
367 <info command="udevadm info --export-db">P: /devices/LNXSYSTM:00
368E: UDEV_LOG=3
369E: DEVPATH=/devices/LNXSYSTM:00
370E: MODALIAS=acpi:LNXSYSTM:
371
372P: /devices/pci0000:00/0000:00:1a.0
373E: UDEV_LOG=3
374E: DEVPATH=/devices/pci0000:00/0000:00:1a.0
375E: DRIVER=uhci_hcd
376E: PCI_CLASS=C0300
377E: PCI_ID=8086:2834
378E: PCI_SUBSYS_ID=17AA:20AA
379E: PCI_SLOT_NAME=0000:00:1a.0
380E: MODALIAS=pci:v00008086d00002834sv000017AAsd000020AAbc0Csc03i00
381
382P: /devices/pci0000:00/0000:00:1a.0/usb3
383N: bus/usb/003/001
384S: char/189:256
385E: UDEV_LOG=3
386E: DEVPATH=/devices/pci0000:00/0000:00:1a.0/usb3
387E: MAJOR=189
388E: MINOR=256
389E: DEVTYPE=usb_device
390E: DRIVER=usb
391E: DEVICE=/proc/bus/usb/003/001
392E: PRODUCT=1d6b/1/206
393E: TYPE=9/0/0
394E: BUSNUM=003
395E: DEVNUM=001
396E: DEVNAME=/dev/bus/usb/003/001
397E: DEVLINKS=/dev/char/189:256
398
399P: /devices/pci0000:00/0000:00:1a.0/usb3/3-0:1.0
400E: UDEV_LOG=3
401E: DEVPATH=/devices/pci0000:00/0000:00:1a.0/usb3/3-0:1.0
402E: DEVTYPE=usb_interface
403E: DRIVER=hub
404E: DEVICE=/proc/bus/usb/003/001
405E: PRODUCT=1d6b/1/206
406E: TYPE=9/0/0
407E: INTERFACE=9/0/0
408E: MODALIAS=usb:v1D6Bp0001d0206dc09dsc00dp00ic09isc00ip00
409
410P: /devices/pci0000:00/0000:00:1a.0/usb3/3-0:1.0/usb_endpoint/usbdev3.1_ep81
411N: usbdev3.1_ep81
412S: char/252:4
413E: UDEV_LOG=3
414E: DEVPATH=/devices/pci0000:00/0000:00:1a.0/usb3/3-0:1.0/usb_endpoint/usbdev3.1_ep81
415E: MAJOR=252
416E: MINOR=4
417E: DEVNAME=/dev/usbdev3.1_ep81
418E: DEVLINKS=/dev/char/252:4
419
420P: /devices/pci0000:00/0000:00:1f.1
421E: UDEV_LOG=3
422E: DEVPATH=/devices/pci0000:00/0000:00:1f.1
423E: DRIVER=ata_piix
424E: PCI_CLASS=1018A
425E: PCI_ID=8086:2850
426E: PCI_SUBSYS_ID=17AA:20A6
427E: PCI_SLOT_NAME=0000:00:1f.1
428E: MODALIAS=pci:v00008086d00002850sv000017AAsd000020A6bc01sc01i8a
429
430P: /devices/pci0000:00/0000:00:1f.1/host3
431E: UDEV_LOG=3
432E: DEVPATH=/devices/pci0000:00/0000:00:1f.1/host3
433E: DEVTYPE=scsi_host
434
435P: /devices/pci0000:00/0000:00:1f.1/host3/scsi_host/host3
436E: UDEV_LOG=3
437E: DEVPATH=/devices/pci0000:00/0000:00:1f.1/host3/scsi_host/host3
438
439P: /devices/pci0000:00/0000:00:1f.1/host3/target3:0:0
440E: UDEV_LOG=3
441E: DEVPATH=/devices/pci0000:00/0000:00:1f.1/host3/target3:0:0
442E: DEVTYPE=scsi_target
443
444P: /devices/pci0000:00/0000:00:1f.1/host3/target3:0:0/3:0:0:0
445E: UDEV_LOG=3
446E: DEVPATH=/devices/pci0000:00/0000:00:1f.1/host3/target3:0:0/3:0:0:0
447E: DEVTYPE=scsi_device
448E: DRIVER=sr
449E: MODALIAS=scsi:t-0x05
450</info>
451
452 <!-- The content of publicly accessible files in /sys/class/dmi/id/
453 format: filename:content
454 as for example generated by "grep -r . /sys/class/dmi/id/"
455 -->
456
457 <info command="grep -r . /sys/class/dmi/id/ 2&gt;/dev/null">/sys/class/dmi/id/bios_vendor:LENOVO
458/sys/class/dmi/id/bios_version:7LETB9WW (2.19 )
459/sys/class/dmi/id/bios_date:06/06/2008
460/sys/class/dmi/id/sys_vendor:LENOVO
461/sys/class/dmi/id/product_name:6457BAG
462/sys/class/dmi/id/product_version:ThinkPad T61
463/sys/class/dmi/id/board_vendor:LENOVO
464/sys/class/dmi/id/board_name:6457BAG
465/sys/class/dmi/id/board_version:Not Available
466/sys/class/dmi/id/chassis_vendor:LENOVO
467/sys/class/dmi/id/chassis_type:10
468/sys/class/dmi/id/chassis_version:Not Available
469/sys/class/dmi/id/chassis_asset_tag:No Asset Information
470/sys/class/dmi/id/modalias:dmi:bvnLENOVO:bvr7LETB9WW(2.19)
471</info>
472 </context>
473</system>
0474
=== modified file 'lib/lp/hardwaredb/scripts/hwdbsubmissions.py'
--- lib/lp/hardwaredb/scripts/hwdbsubmissions.py 2011-08-31 16:38:48 +0000
+++ lib/lp/hardwaredb/scripts/hwdbsubmissions.py 2011-09-02 07:16:32 +0000
@@ -72,6 +72,13 @@
72 re.VERBOSE)72 re.VERBOSE)
7373
74_broken_comment_nodes_re = re.compile('(<comment>.*?</comment>)', re.DOTALL)74_broken_comment_nodes_re = re.compile('(<comment>.*?</comment>)', re.DOTALL)
75_missing_udev_node_data = re.compile(
76 '<info command="udevadm info --export-db">(.*?)</info>', re.DOTALL)
77_missing_dmi_node_data = re.compile(
78 r'<info command="grep -r \. /sys/class/dmi/id/ 2&gt;/dev/null">(.*?)'
79 '</info>', re.DOTALL)
80_udev_node_exists = re.compile('<hardware>.*?<udev>.*?</hardware>', re.DOTALL)
81_dmi_node_exists = re.compile('<hardware>.*?<dmi>.*?</hardware>', re.DOTALL)
7582
76ROOT_UDI = '/org/freedesktop/Hal/devices/computer'83ROOT_UDI = '/org/freedesktop/Hal/devices/computer'
77UDEV_ROOT_PATH = '/devices/LNXSYSTM:00'84UDEV_ROOT_PATH = '/devices/LNXSYSTM:00'
@@ -166,7 +173,36 @@
166 # A considerable number of reports for Lucid has ESC characters173 # A considerable number of reports for Lucid has ESC characters
167 # in comment nodes. We don't need the comment nodes at all, so174 # in comment nodes. We don't need the comment nodes at all, so
168 # we can simply empty them.175 # we can simply empty them.
169 return _broken_comment_nodes_re.sub('<comment/>', submission)176 submission = _broken_comment_nodes_re.sub('<comment/>', submission)
177
178 # Submissions from Natty don't have the nodes <dmi> and <udev>
179 # as children of the <hardware> node. Fortunately, they provide
180 # this data in
181 #
182 # <context>
183 # <info command="grep -r . /sys/class/dmi/id/ 2&gt;/dev/null">
184 # ...
185 # </info>
186 # <info command="udevadm info --export-db">
187 # ...
188 # </info>
189 # </context>
190 #
191 # We can try to find the two relevant <info> nodes inside <context>
192 # and move their content into the proper subnodes of <hardware>.
193 if _udev_node_exists.search(submission) is None:
194 mo = _missing_udev_node_data.search(submission)
195 if mo is not None:
196 missing_data = mo.group(1)
197 missing_data = '<udev>%s</udev>\n</hardware>' % missing_data
198 submission = submission.replace('</hardware>', missing_data)
199 if _dmi_node_exists.search(submission) is None:
200 mo = _missing_dmi_node_data.search(submission)
201 if mo is not None:
202 missing_data = mo.group(1)
203 missing_data = '<dmi>%s</dmi>\n</hardware>' % missing_data
204 submission = submission.replace('</hardware>', missing_data)
205 return submission
170206
171 def _getValidatedEtree(self, submission, submission_key):207 def _getValidatedEtree(self, submission, submission_key):
172 """Create an etree doc from the XML string submission and validate it.208 """Create an etree doc from the XML string submission and validate it.
173209
=== modified file 'lib/lp/hardwaredb/tests/test_hwdb_submission_validation.py'
--- lib/lp/hardwaredb/tests/test_hwdb_submission_validation.py 2011-08-31 16:38:48 +0000
+++ lib/lp/hardwaredb/tests/test_hwdb_submission_validation.py 2011-09-02 07:16:32 +0000
@@ -2823,3 +2823,22 @@
2823 submission_id, result,2823 submission_id, result,
2824 'Extra element context in interleave',2824 'Extra element context in interleave',
2825 'detection of an invalid sub.node of <info> failed')2825 'detection of an invalid sub.node of <info> failed')
2826
2827 def test_natty_reports_validate(self):
2828 # HWDB submissions from Natty can be processed.
2829 # the raw data from these reports would be passed directly
2830 # to the RelaxNG validator, they would fail, because they
2831 # do not have the sub-nodes <dmi> and <udev> inside <hardware>.
2832 # The data is stored instead in the nodes
2833 # <info command="grep -r . /sys/class/dmi/id/ 2&gt;/dev/null">
2834 # and <info command="udevadm info --export-db">
2835 #
2836 # The method SubmissionParser.fixFrequentErrors() (called by
2837 # _getValidatedEtree()) creates the missing nodes, so that
2838 # _getValidatedEtree() succeeds.
2839 sample_data_path = os.path.join(
2840 config.root, 'lib', 'canonical', 'launchpad', 'scripts',
2841 'tests', 'hardwaretest-natty.xml')
2842 sample_data = open(sample_data_path).read()
2843 result, submission_id = self.runValidator(sample_data)
2844 self.assertTrue(result is None)