Merge lp:~roadmr/ubuntu/oneiric/checkbox/0.13 into lp:ubuntu/oneiric/checkbox
- Oneiric (11.10)
- 0.13
- Merge into oneiric
Status: | Superseded |
---|---|
Proposed branch: | lp:~roadmr/ubuntu/oneiric/checkbox/0.13 |
Merge into: | lp:ubuntu/oneiric/checkbox |
Diff against target: |
18858 lines (+9936/-3266) 93 files modified
checkbox/application.py (+5/-5) checkbox/contrib/persist.py (+5/-4) checkbox/dispatcher.py (+201/-0) checkbox/lib/bit.py (+5/-4) checkbox/lib/config.py (+15/-2) checkbox/lib/conversion.py (+131/-42) checkbox/lib/dmi.py (+169/-18) checkbox/lib/safe.py (+5/-0) checkbox/lib/template.py (+1/-1) checkbox/message.py (+4/-3) checkbox/parsers/cpuinfo.py (+30/-41) checkbox/parsers/cputable (+40/-0) checkbox/parsers/cputable.py (+42/-0) checkbox/parsers/deferred.py (+27/-0) checkbox/parsers/dmidecode.py (+123/-0) checkbox/parsers/meminfo.py (+46/-0) checkbox/parsers/submission.py (+474/-383) checkbox/parsers/udevadm.py (+178/-317) checkbox_cli/cli_interface.py (+9/-1) checkbox_gtk/gtk_interface.py (+4/-4) data/whitelists/default.whitelist (+1/-0) debian/changelog (+59/-0) debian/po/ro.po (+118/-0) examples/checkbox.ini (+1/-1) gtk/checkbox-gtk.ui (+37/-37) jobs/apport.txt.in (+0/-5) jobs/audio.txt.in (+44/-24) jobs/autotest.txt.in (+4/-2) jobs/bluetooth.txt.in (+64/-52) jobs/camera.txt.in (+19/-12) jobs/codecs.txt.in (+16/-38) jobs/cpu.txt.in (+3/-3) jobs/daemons.txt.in (+11/-11) jobs/disk.txt.in (+6/-5) jobs/evolution.txt.in (+0/-26) jobs/fingerprint.txt.in (+24/-20) jobs/firewire.txt.in (+9/-8) jobs/gcalctool.txt.in (+0/-52) jobs/gedit.txt.in (+0/-22) jobs/gnome-terminal.txt.in (+0/-12) jobs/graphics.txt.in (+63/-51) jobs/hibernate.txt.in (+9/-7) jobs/info.txt.in (+47/-27) jobs/input.txt.in (+15/-7) jobs/install.txt.in (+1/-1) jobs/keys.txt.in (+58/-45) jobs/local.txt.in (+41/-6) jobs/ltp.txt.in (+3/-2) jobs/mago.txt.in (+4/-2) jobs/mediacard.txt.in (+106/-84) jobs/memory.txt.in (+8/-5) jobs/miscellanea.txt.in (+19/-8) jobs/monitor.txt.in (+43/-24) jobs/networking.txt.in (+31/-32) jobs/optical.txt.in (+56/-42) jobs/panel_clock_test.txt.in (+18/-15) jobs/panel_reboot.txt.in (+8/-6) jobs/pcmcia-pcix.txt.in (+6/-3) jobs/peripheral.txt.in (+27/-22) jobs/phoronix.txt.in (+4/-2) jobs/power-management.txt.in (+32/-18) jobs/qa_regression.txt.in (+4/-2) jobs/resource.txt.in (+15/-0) jobs/screenshot.txt.in (+0/-13) jobs/server-services.txt.in (+12/-12) jobs/stress.txt.in (+18/-10) jobs/suspend.txt.in (+52/-31) jobs/usb.txt.in (+55/-36) jobs/user_apps.txt.in (+337/-110) jobs/wireless.txt.in (+9/-9) plugins/apport_prompt.py (+1/-1) plugins/launchpad_report.py (+6/-4) plugins/persist_info.py (+2/-1) plugins/resource_info.py (+14/-1) plugins/system_info.py (+2/-2) po/POTFILES.in (+0/-6) po/ca@valencia.po (+2897/-0) po/el.po (+229/-293) po/en_GB.po (+240/-240) po/gd.po (+2606/-0) po/ja.po (+297/-335) po/lt.po (+294/-357) po/tr.po (+217/-177) scripts/connect_wireless (+1/-1) scripts/cpuinfo_resource (+13/-17) scripts/dmi_resource (+55/-0) scripts/hal_resource (+0/-5) scripts/meminfo_resource (+15/-27) scripts/package_resource (+6/-0) scripts/udev_resource (+2/-2) scripts/usb_test (+5/-3) setup.cfg (+1/-7) setup.py (+2/-0) |
To merge this branch: | bzr merge lp:~roadmr/ubuntu/oneiric/checkbox/0.13 |
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu Sponsors | Pending | ||
Review via email: mp+82719@code.launchpad.net |
This proposal has been superseded by a proposal from 2011-11-24.
Commit message
Description of the change
Sebastien Bacher (seb128) wrote : | # |
Unmerged revisions
- 36. By Daniel Manrique
-
New upstream release (LP: #892268):
* Generate a submission.xml file that contains all device and attachment
* Write the report before reporting the validation error.
* Changed device.product to dmi.product for the formfactor (LP: #875312)
* Use gettext for string (LP: #869267)
* Move progress indicator to main checkbox dialog instead of a
transient window (LP: #868995)
* Ignore malformed dpkg entries in package_resource (LP: #794747)
* Reset window title after finishing a manual test (LP: #874690)
* Handle "@" in locale names (as in ca@valencia).
* Went through all the job files and:
* Updated descriptions to match Unity UI structure
* Added descriptions where necessary
* Added further details to some descriptions
* Moved some jobs to more appropriate files
* Fixed job names in older job files to match new naming scheme
(suite/testname)
* Added jobs to local.txt to ensure all job files are now parsed
(this allows easier addition of existing tests to whitelists)
* Changed remaining manual job descriptions to match the new format
* Updated CD and DVD write tests to be more clear about when to skip
them (LP: #772794)
* Rewrote all job descriptions to match OEM QA syntax
* Fix the code that assigns keys in checkbox-cli so that it never assigns
keys which have other uses. (LP: #877467)
* Show details of unmet job requirements (LP: #855852)
* Ensure that connect_wireless chooses a wireless connection from the list
of available connections (LP: #877752)
* Have the bluetooth/detect tests require a device with the category
BLUETOOTH to run, thus preventing the test from failing on systems with
no Bluetooth device (LP: #862322)
* Rename attachment jobs to not have a forward slash in their name
(LP: #887964)
* Guard against trying to write files to logical partitions on USB sticks
(which will obviously fail) in usb_test (LP: #887049)
* Make the OpenGL test ignore the return value of glxgears and improve
the test description (LP: #890725)
* Allow input/mouse test to run if a TOUCH device is present
(LP: #886129)
* Broken job dependencies fixed (LP: #888447)
* Regex support when specifying blacklists and whitelists on the
commandline (LP: #588647)
Preview Diff
1 | === modified file 'checkbox/application.py' | |||
2 | --- checkbox/application.py 2011-02-14 18:19:27 +0000 | |||
3 | +++ checkbox/application.py 2011-11-18 18:04:27 +0000 | |||
4 | @@ -81,13 +81,13 @@ | |||
5 | 81 | default=[], | 81 | default=[], |
6 | 82 | help=_("Configuration override parameters.")) | 82 | help=_("Configuration override parameters.")) |
7 | 83 | parser.add_option("-b", "--blacklist", | 83 | parser.add_option("-b", "--blacklist", |
9 | 84 | help=_("Shorthand for --config=checkbox/plugins/jobs_info/blacklist.")) | 84 | help=_("Shorthand for --config=.*/jobs_info/blacklist.")) |
10 | 85 | parser.add_option("-B", "--blacklist-file", | 85 | parser.add_option("-B", "--blacklist-file", |
12 | 86 | help=_("Shorthand for --config=checkbox/plugins/jobs_info/blacklist_file.")) | 86 | help=_("Shorthand for --config=.*/jobs_info/blacklist_file.")) |
13 | 87 | parser.add_option("-w", "--whitelist", | 87 | parser.add_option("-w", "--whitelist", |
15 | 88 | help=_("Shorthand for --config=checkbox/plugins/jobs_info/whitelist.")) | 88 | help=_("Shorthand for --config=.*/jobs_info/whitelist.")) |
16 | 89 | parser.add_option("-W", "--whitelist-file", | 89 | parser.add_option("-W", "--whitelist-file", |
18 | 90 | help=_("Shorthand for --config=checkbox/plugins/jobs_info/whitelist_file.")) | 90 | help=_("Shorthand for --config=.*/jobs_info/whitelist_file.")) |
19 | 91 | return parser.parse_args(args) | 91 | return parser.parse_args(args) |
20 | 92 | 92 | ||
21 | 93 | def create_application(self, args=sys.argv): | 93 | def create_application(self, args=sys.argv): |
22 | @@ -102,7 +102,7 @@ | |||
23 | 102 | 102 | ||
24 | 103 | # Replace shorthands | 103 | # Replace shorthands |
25 | 104 | for shorthand in "blacklist", "blacklist_file", "whitelist", "whitelist_file": | 104 | for shorthand in "blacklist", "blacklist_file", "whitelist", "whitelist_file": |
27 | 105 | key = "checkbox/plugins/jobs_info/%s" % shorthand | 105 | key = ".*/jobs_info/%s" % shorthand |
28 | 106 | value = getattr(options, shorthand) | 106 | value = getattr(options, shorthand) |
29 | 107 | if value: | 107 | if value: |
30 | 108 | options.config.append("=".join([key, value])) | 108 | options.config.append("=".join([key, value])) |
31 | 109 | 109 | ||
32 | === modified file 'checkbox/contrib/persist.py' | |||
33 | --- checkbox/contrib/persist.py 2011-02-14 18:19:27 +0000 | |||
34 | +++ checkbox/contrib/persist.py 2011-11-18 18:04:27 +0000 | |||
35 | @@ -23,6 +23,7 @@ | |||
36 | 23 | import re | 23 | import re |
37 | 24 | import posixpath | 24 | import posixpath |
38 | 25 | 25 | ||
39 | 26 | from checkbox.lib.safe import safe_close | ||
40 | 26 | 27 | ||
41 | 27 | __all__ = ["Persist", "MemoryBackend", "PickleBackend", "BPickleBackend", | 28 | __all__ = ["Persist", "MemoryBackend", "PickleBackend", "BPickleBackend", |
42 | 28 | "path_string_to_tuple", "path_tuple_to_string", "RootedPersist", | 29 | "path_string_to_tuple", "path_tuple_to_string", "RootedPersist", |
43 | @@ -517,14 +518,14 @@ | |||
44 | 517 | try: | 518 | try: |
45 | 518 | return self._pickle.load(file) | 519 | return self._pickle.load(file) |
46 | 519 | finally: | 520 | finally: |
48 | 520 | file.close() | 521 | safe_close(file) |
49 | 521 | 522 | ||
50 | 522 | def save(self, filepath, map): | 523 | def save(self, filepath, map): |
51 | 523 | file = open(filepath, "w") | 524 | file = open(filepath, "w") |
52 | 524 | try: | 525 | try: |
53 | 525 | self._pickle.dump(map, file, 2) | 526 | self._pickle.dump(map, file, 2) |
54 | 526 | finally: | 527 | finally: |
56 | 527 | file.close() | 528 | safe_close(file) |
57 | 528 | 529 | ||
58 | 529 | 530 | ||
59 | 530 | class BPickleBackend(Backend): | 531 | class BPickleBackend(Backend): |
60 | @@ -538,11 +539,11 @@ | |||
61 | 538 | try: | 539 | try: |
62 | 539 | return self._bpickle.loads(file.read()) | 540 | return self._bpickle.loads(file.read()) |
63 | 540 | finally: | 541 | finally: |
65 | 541 | file.close() | 542 | safe_close(file) |
66 | 542 | 543 | ||
67 | 543 | def save(self, filepath, map): | 544 | def save(self, filepath, map): |
68 | 544 | file = open(filepath, "w") | 545 | file = open(filepath, "w") |
69 | 545 | try: | 546 | try: |
70 | 546 | file.write(self._bpickle.dumps(map)) | 547 | file.write(self._bpickle.dumps(map)) |
71 | 547 | finally: | 548 | finally: |
73 | 548 | file.close() | 549 | safe_close(file) |
74 | 549 | 550 | ||
75 | === added file 'checkbox/dispatcher.py' | |||
76 | --- checkbox/dispatcher.py 1970-01-01 00:00:00 +0000 | |||
77 | +++ checkbox/dispatcher.py 2011-11-18 18:04:27 +0000 | |||
78 | @@ -0,0 +1,201 @@ | |||
79 | 1 | # Copyright 2010-2011 Canonical Ltd. This software is licensed under the | ||
80 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | ||
81 | 3 | |||
82 | 4 | __metaclass__ = type | ||
83 | 5 | |||
84 | 6 | __all__ = [ | ||
85 | 7 | "Dispatcher", | ||
86 | 8 | "DispatcherList", | ||
87 | 9 | "DispatcherQueue", | ||
88 | 10 | ] | ||
89 | 11 | |||
90 | 12 | import logging | ||
91 | 13 | |||
92 | 14 | from itertools import product | ||
93 | 15 | |||
94 | 16 | |||
95 | 17 | class Event: | ||
96 | 18 | """Event payload containing the positional and keywoard arguments | ||
97 | 19 | passed to the handler in the event listener.""" | ||
98 | 20 | |||
99 | 21 | def __init__(self, type, *args, **kwargs): | ||
100 | 22 | self.type = type | ||
101 | 23 | self.args = args | ||
102 | 24 | self.kwargs = kwargs | ||
103 | 25 | |||
104 | 26 | |||
105 | 27 | class Listener: | ||
106 | 28 | """Event listener notified when events are published by the dispatcher.""" | ||
107 | 29 | |||
108 | 30 | def __init__(self, event_type, handler, count): | ||
109 | 31 | self.event_type = event_type | ||
110 | 32 | self.handler = handler | ||
111 | 33 | self.count = count | ||
112 | 34 | |||
113 | 35 | def notify(self, event): | ||
114 | 36 | """Notify the handler with the payload of the event. | ||
115 | 37 | |||
116 | 38 | :param event: The event containint the payload for the handler. | ||
117 | 39 | """ | ||
118 | 40 | if self.count is None or self.count: | ||
119 | 41 | self.handler(*event.args, **event.kwargs) | ||
120 | 42 | if self.count: | ||
121 | 43 | self.count -= 1 | ||
122 | 44 | |||
123 | 45 | |||
124 | 46 | class ListenerList(Listener): | ||
125 | 47 | """Event listener notified for lists of events.""" | ||
126 | 48 | |||
127 | 49 | def __init__(self, *args, **kwargs): | ||
128 | 50 | super(ListenerList, self).__init__(*args, **kwargs) | ||
129 | 51 | self.event_types = set(self.event_type) | ||
130 | 52 | self.kwargs = {} | ||
131 | 53 | |||
132 | 54 | def notify(self, event): | ||
133 | 55 | """Only notify the handler when all the events for this listener | ||
134 | 56 | have been published by the dispatcher. When duplicate events | ||
135 | 57 | occur, the latest event is preserved and the previous one are | ||
136 | 58 | overwritten until all events have been published. | ||
137 | 59 | """ | ||
138 | 60 | if self.count is None or self.count: | ||
139 | 61 | self.kwargs[event.type] = event.args[0] | ||
140 | 62 | if self.event_types.issubset(self.kwargs): | ||
141 | 63 | self.handler(**self.kwargs) | ||
142 | 64 | if self.count: | ||
143 | 65 | self.count -= 1 | ||
144 | 66 | |||
145 | 67 | |||
146 | 68 | class ListenerQueue(ListenerList): | ||
147 | 69 | |||
148 | 70 | def notify(self, event): | ||
149 | 71 | """Only notify the handler when all the events for this listener | ||
150 | 72 | have been published by the dispatcher. Duplicate events are enqueued | ||
151 | 73 | and dequeued only when all events have been published. | ||
152 | 74 | """ | ||
153 | 75 | arg = event.args[0] | ||
154 | 76 | queue = self.kwargs.setdefault(event.type, []) | ||
155 | 77 | |||
156 | 78 | # Strip duplicates from the queue. | ||
157 | 79 | if arg not in queue: | ||
158 | 80 | queue.append(arg) | ||
159 | 81 | |||
160 | 82 | # Once the queue has handler has been called, the queue | ||
161 | 83 | # then behaves like a list using the latest events. | ||
162 | 84 | if self.event_types.issubset(self.kwargs): | ||
163 | 85 | self.notify = notify = super(ListenerQueue, self).notify | ||
164 | 86 | keys = self.kwargs.keys() | ||
165 | 87 | for values in product(*self.kwargs.values()): | ||
166 | 88 | self.kwargs = dict(zip(keys, values)) | ||
167 | 89 | notify(event) | ||
168 | 90 | |||
169 | 91 | |||
170 | 92 | class Dispatcher: | ||
171 | 93 | """Register handlers and publish events for them identified by strings.""" | ||
172 | 94 | |||
173 | 95 | listener_factory = Listener | ||
174 | 96 | |||
175 | 97 | def __init__(self, listener_factory=None): | ||
176 | 98 | self._event_listeners = {} | ||
177 | 99 | |||
178 | 100 | if listener_factory is not None: | ||
179 | 101 | self.listener_factory = listener_factory | ||
180 | 102 | |||
181 | 103 | def registerHandler(self, event_type, handler, count=None): | ||
182 | 104 | """Register an event handler and return its listener. | ||
183 | 105 | |||
184 | 106 | :param event_type: The name of the event type to handle. | ||
185 | 107 | :param handler: The function handling the given event type. | ||
186 | 108 | :param count: Optionally, the number times to call the handler. | ||
187 | 109 | """ | ||
188 | 110 | listener = self.listener_factory(event_type, handler, count) | ||
189 | 111 | |||
190 | 112 | listeners = self._event_listeners.setdefault(event_type, []) | ||
191 | 113 | listeners.append(listener) | ||
192 | 114 | |||
193 | 115 | return listener | ||
194 | 116 | |||
195 | 117 | def unregisterHandler(self, handler): | ||
196 | 118 | """Unregister a handler. | ||
197 | 119 | |||
198 | 120 | :param handler: The handler to unregister. | ||
199 | 121 | """ | ||
200 | 122 | for event_type, listeners in self._event_listeners.items(): | ||
201 | 123 | listeners = [ | ||
202 | 124 | listener for listener in listeners | ||
203 | 125 | if listener.handler == handler] | ||
204 | 126 | if listeners: | ||
205 | 127 | self._event_listeners[event_type] = listeners | ||
206 | 128 | else: | ||
207 | 129 | del self._event_listeners[event_type] | ||
208 | 130 | |||
209 | 131 | def unregisterListener(self, listener, event_type=None): | ||
210 | 132 | """Unregister a listener. | ||
211 | 133 | |||
212 | 134 | :param listener: The listener of the handler to unregister. | ||
213 | 135 | :param event_type: Optionally, the event_type to unregister. | ||
214 | 136 | """ | ||
215 | 137 | if event_type is None: | ||
216 | 138 | event_type = listener.event_type | ||
217 | 139 | |||
218 | 140 | self._event_listeners[event_type].remove(listener) | ||
219 | 141 | if not self._event_listeners[event_type]: | ||
220 | 142 | del self._event_listeners[event_type] | ||
221 | 143 | |||
222 | 144 | def publishEvent(self, event_type, *args, **kwargs): | ||
223 | 145 | """Publish an event of a given type and notify all listeners. | ||
224 | 146 | |||
225 | 147 | :param event_type: The name of the event type to publish. | ||
226 | 148 | :param args: Positional arguments to pass to the registered handlers. | ||
227 | 149 | :param kwargs: Keyword arguments to pass to the registered handlers. | ||
228 | 150 | """ | ||
229 | 151 | if event_type in self._event_listeners: | ||
230 | 152 | event = Event(event_type, *args, **kwargs) | ||
231 | 153 | for listener in list(self._event_listeners[event_type]): | ||
232 | 154 | try: | ||
233 | 155 | listener.notify(event) | ||
234 | 156 | if listener.count is not None and not listener.count: | ||
235 | 157 | self.unregisterListener(listener) | ||
236 | 158 | except: | ||
237 | 159 | logging.exception( | ||
238 | 160 | "Error running event handler for %r with args %r %r", | ||
239 | 161 | event_type, args, kwargs) | ||
240 | 162 | |||
241 | 163 | |||
242 | 164 | class DispatcherList(Dispatcher): | ||
243 | 165 | """ | ||
244 | 166 | Register handlers and publish events for them identified by lists | ||
245 | 167 | of strings. | ||
246 | 168 | """ | ||
247 | 169 | |||
248 | 170 | listener_factory = ListenerList | ||
249 | 171 | |||
250 | 172 | def registerHandler(self, event_types, handler, count=None): | ||
251 | 173 | """See Dispatcher.""" | ||
252 | 174 | if not isinstance(event_types, (list, tuple,)): | ||
253 | 175 | event_types = (event_types,) | ||
254 | 176 | |||
255 | 177 | listener = self.listener_factory(event_types, handler, count) | ||
256 | 178 | for event_type in event_types: | ||
257 | 179 | listeners = self._event_listeners.setdefault(event_type, []) | ||
258 | 180 | listeners.append(listener) | ||
259 | 181 | |||
260 | 182 | return listener | ||
261 | 183 | |||
262 | 184 | def unregisterListener(self, listener): | ||
263 | 185 | """See Dispatcher.""" | ||
264 | 186 | for event_type in listener.event_types: | ||
265 | 187 | super(DispatcherList, self).unregisterListener( | ||
266 | 188 | listener, event_type) | ||
267 | 189 | |||
268 | 190 | def publishEvent(self, event_type, arg): | ||
269 | 191 | """See Dispatcher.""" | ||
270 | 192 | super(DispatcherList, self).publishEvent(event_type, arg) | ||
271 | 193 | |||
272 | 194 | |||
273 | 195 | class DispatcherQueue(DispatcherList): | ||
274 | 196 | """ | ||
275 | 197 | Register handlers and publish events for them identified by lists | ||
276 | 198 | of strings in queue order. | ||
277 | 199 | """ | ||
278 | 200 | |||
279 | 201 | listener_factory = ListenerQueue | ||
280 | 0 | 202 | ||
281 | === modified file 'checkbox/lib/bit.py' | |||
282 | --- checkbox/lib/bit.py 2011-02-14 18:19:27 +0000 | |||
283 | +++ checkbox/lib/bit.py 2011-11-18 18:04:27 +0000 | |||
284 | @@ -36,10 +36,11 @@ | |||
285 | 36 | 36 | ||
286 | 37 | return bitcount | 37 | return bitcount |
287 | 38 | 38 | ||
292 | 39 | def test_bit(bit, bitmask): | 39 | def test_bit(bit, bitmask, bits=None): |
293 | 40 | bits_per_long = calcsize("l") * 8 | 40 | if bits is None: |
294 | 41 | offset = bit % bits_per_long | 41 | bits = calcsize("l") * 8 |
295 | 42 | long = int(bit / bits_per_long) | 42 | offset = bit % bits |
296 | 43 | long = int(bit / bits) | ||
297 | 43 | if long >= len(bitmask): | 44 | if long >= len(bitmask): |
298 | 44 | return 0 | 45 | return 0 |
299 | 45 | return (bitmask[long] >> offset) & 1 | 46 | return (bitmask[long] >> offset) & 1 |
300 | 46 | 47 | ||
301 | === modified file 'checkbox/lib/config.py' | |||
302 | --- checkbox/lib/config.py 2011-07-01 11:37:27 +0000 | |||
303 | +++ checkbox/lib/config.py 2011-11-18 18:04:27 +0000 | |||
304 | @@ -122,10 +122,23 @@ | |||
305 | 122 | raise Exception, "Invalid config string: %s" % config | 122 | raise Exception, "Invalid config string: %s" % config |
306 | 123 | 123 | ||
307 | 124 | (name, option, value) = match.groups() | 124 | (name, option, value) = match.groups() |
309 | 125 | if not self._parser.has_section(name): | 125 | |
310 | 126 | # Match section names | ||
311 | 127 | name_regex = re.compile(name) | ||
312 | 128 | sections = [section for section in self._parser.sections() | ||
313 | 129 | if name_regex.match(section)] | ||
314 | 130 | |||
315 | 131 | if not sections: | ||
316 | 126 | self._parser.add_section(name) | 132 | self._parser.add_section(name) |
317 | 133 | sections.append(name) | ||
318 | 127 | 134 | ||
320 | 128 | self._parser.set(name, option, value) | 135 | for section in sections: |
321 | 136 | logging.debug('Setting configuration parameter: ' | ||
322 | 137 | '%(section)s/%(option)s = %(value)s' | ||
323 | 138 | % {'section': section, | ||
324 | 139 | 'option': option, | ||
325 | 140 | 'value': value}) | ||
326 | 141 | self._parser.set(section, option, value) | ||
327 | 129 | 142 | ||
328 | 130 | def read_file(self, file, filename="<stream>"): | 143 | def read_file(self, file, filename="<stream>"): |
329 | 131 | logging.info("Reading configurations from: %s", filename) | 144 | logging.info("Reading configurations from: %s", filename) |
330 | 132 | 145 | ||
331 | === modified file 'checkbox/lib/conversion.py' | |||
332 | --- checkbox/lib/conversion.py 2009-01-20 18:55:20 +0000 | |||
333 | +++ checkbox/lib/conversion.py 2011-11-18 18:04:27 +0000 | |||
334 | @@ -18,48 +18,110 @@ | |||
335 | 18 | # | 18 | # |
336 | 19 | import re | 19 | import re |
337 | 20 | 20 | ||
380 | 21 | 21 | from dateutil import tz | |
381 | 22 | def string_to_type(value): | 22 | from datetime import ( |
382 | 23 | conversion_table = ( | 23 | datetime, |
383 | 24 | ("(yes|true)", lambda v: True), | 24 | timedelta, |
384 | 25 | ("(no|false)", lambda v: False), | 25 | ) |
385 | 26 | ("\d+", lambda v: int(v.group(0))), | 26 | |
386 | 27 | ("\d+\.\d+", lambda v: float(v.group(0))), | 27 | |
387 | 28 | ("(\d+) ?([kmgt]?b?)", lambda v: int(v.group(1))), | 28 | DATETIME_RE = re.compile(r""" |
388 | 29 | ("(\d+\.\d+) ?([kmgt]?b?)", lambda v: float(v.group(1))), | 29 | ^(?P<year>\d\d\d\d)-?(?P<month>\d\d)-?(?P<day>\d\d) |
389 | 30 | ("(\d+) ?([kmgt]?hz?)", lambda v: int(v.group(1))), | 30 | T(?P<hour>\d\d):?(?P<minute>\d\d):?(?P<second>\d\d) |
390 | 31 | ("(\d+\.\d+) ?([kmgt]?hz?)", lambda v: float(v.group(1)))) | 31 | (?:\.(?P<second_fraction>\d{0,6}))? |
391 | 32 | 32 | (?P<tz> | |
392 | 33 | multiplier_table = ( | 33 | (?:(?P<tz_sign>[-+])(?P<tz_hour>\d\d):(?P<tz_minute>\d\d)) |
393 | 34 | ("b", 1), | 34 | | Z)?$ |
394 | 35 | ("kb?", 1024), | 35 | """, re.VERBOSE) |
395 | 36 | ("mb?", 1024 * 1024), | 36 | |
396 | 37 | ("gb?", 1024 * 1024 * 1024), | 37 | TYPE_FORMATS = ( |
397 | 38 | ("tb?", 1024 * 1024 * 1024 * 1024), | 38 | (r"(yes|true)", lambda v: True), |
398 | 39 | ("hz", 1), | 39 | (r"(no|false)", lambda v: False), |
399 | 40 | ("khz?", 1024), | 40 | (r"-?\d+", lambda v: int(v.group(0))), |
400 | 41 | ("mhz?", 1024 * 1024), | 41 | (r"-?\d+\.\d+", lambda v: float(v.group(0))), |
401 | 42 | ("ghz?", 1024 * 1024 * 1024), | 42 | (r"(-?\d+) ?([kmgt]?b?)", lambda v: int(v.group(1))), |
402 | 43 | ("thz?", 1024 * 1024 * 1024 * 1024)) | 43 | (r"(-?\d+\.\d+) ?([kmgt]?b?)", lambda v: float(v.group(1))), |
403 | 44 | 44 | (r"(-?\d+) ?([kmgt]?hz)", lambda v: int(v.group(1))), | |
404 | 45 | if isinstance(value, basestring): | 45 | (r"(-?\d+\.\d+) ?([kmgt]?hz)", lambda v: float(v.group(1)))) |
405 | 46 | for regex, conversion in conversion_table: | 46 | TYPE_FORMATS = tuple( |
406 | 47 | match = re.match("^%s$" % regex, value, re.IGNORECASE) | 47 | (re.compile(r"^%s$" % pattern, re.IGNORECASE), format) |
407 | 48 | if match: | 48 | for pattern, format in TYPE_FORMATS) |
408 | 49 | value = conversion(match) | 49 | |
409 | 50 | if len(match.groups()) < 2: | 50 | TYPE_MULTIPLIERS = ( |
410 | 51 | return value | 51 | (r"b", 1), |
411 | 52 | 52 | (r"kb?", 1024), | |
412 | 53 | unit = match.group(2) | 53 | (r"mb?", 1024 * 1024), |
413 | 54 | for regex, multiplier in multiplier_table: | 54 | (r"gb?", 1024 * 1024 * 1024), |
414 | 55 | match = re.match("^%s$" % regex, unit, re.IGNORECASE) | 55 | (r"tb?", 1024 * 1024 * 1024 * 1024), |
415 | 56 | if match: | 56 | (r"hz", 1), |
416 | 57 | value *= multiplier | 57 | (r"khz?", 1024), |
417 | 58 | return value | 58 | (r"mhz?", 1024 * 1024), |
418 | 59 | else: | 59 | (r"ghz?", 1024 * 1024 * 1024), |
419 | 60 | raise Exception, "Unknown multiplier: %s" % unit | 60 | (r"thz?", 1024 * 1024 * 1024 * 1024)) |
420 | 61 | 61 | TYPE_MULTIPLIERS = tuple( | |
421 | 62 | return value | 62 | (re.compile(r"^%s$" % pattern, re.IGNORECASE), multiplier) |
422 | 63 | for pattern, multiplier in TYPE_MULTIPLIERS) | ||
423 | 64 | |||
424 | 65 | |||
425 | 66 | def datetime_to_string(dt): | ||
426 | 67 | """Return a consistent string representation for a given datetime. | ||
427 | 68 | |||
428 | 69 | :param dt: The datetime object. | ||
429 | 70 | """ | ||
430 | 71 | return dt.isoformat() | ||
431 | 72 | |||
432 | 73 | def string_to_datetime(string): | ||
433 | 74 | """Return a datetime object from a consistent string representation. | ||
434 | 75 | |||
435 | 76 | :param string: The string representation. | ||
436 | 77 | """ | ||
437 | 78 | # we cannot use time.strptime: this function accepts neither fractions | ||
438 | 79 | # of a second nor a time zone given e.g. as '+02:30'. | ||
439 | 80 | match = DATETIME_RE.match(string) | ||
440 | 81 | |||
441 | 82 | # The Relax NG schema allows a leading minus sign and year numbers | ||
442 | 83 | # with more than four digits, which are not "covered" by _time_regex. | ||
443 | 84 | if not match: | ||
444 | 85 | raise ValueError("Datetime with unreasonable value: %s" % string) | ||
445 | 86 | |||
446 | 87 | time_parts = match.groupdict() | ||
447 | 88 | |||
448 | 89 | year = int(time_parts['year']) | ||
449 | 90 | month = int(time_parts['month']) | ||
450 | 91 | day = int(time_parts['day']) | ||
451 | 92 | hour = int(time_parts['hour']) | ||
452 | 93 | minute = int(time_parts['minute']) | ||
453 | 94 | second = int(time_parts['second']) | ||
454 | 95 | second_fraction = time_parts['second_fraction'] | ||
455 | 96 | if second_fraction is not None: | ||
456 | 97 | milliseconds = second_fraction + '0' * (6 - len(second_fraction)) | ||
457 | 98 | milliseconds = int(milliseconds) | ||
458 | 99 | else: | ||
459 | 100 | milliseconds = 0 | ||
460 | 101 | |||
461 | 102 | # The Relax NG validator accepts leap seconds, but the datetime | ||
462 | 103 | # constructor rejects them. The time values submitted by the HWDB | ||
463 | 104 | # client are not necessarily very precise, hence we can round down | ||
464 | 105 | # to 59.999999 seconds without losing any real precision. | ||
465 | 106 | if second > 59: | ||
466 | 107 | second = 59 | ||
467 | 108 | milliseconds = 999999 | ||
468 | 109 | |||
469 | 110 | dt = datetime( | ||
470 | 111 | year, month, day, hour, minute, second, milliseconds, | ||
471 | 112 | tzinfo=tz.tzutc()) | ||
472 | 113 | |||
473 | 114 | tz_sign = time_parts['tz_sign'] | ||
474 | 115 | tz_hour = time_parts['tz_hour'] | ||
475 | 116 | tz_minute = time_parts['tz_minute'] | ||
476 | 117 | if tz_sign in ('-', '+'): | ||
477 | 118 | delta = timedelta(hours=int(tz_hour), minutes=int(tz_minute)) | ||
478 | 119 | if tz_sign == '-': | ||
479 | 120 | dt = dt + delta | ||
480 | 121 | else: | ||
481 | 122 | dt = dt - delta | ||
482 | 123 | |||
483 | 124 | return dt | ||
484 | 63 | 125 | ||
485 | 64 | def sizeof_bytes(bytes): | 126 | def sizeof_bytes(bytes): |
486 | 65 | for x in ["bytes", "KB", "MB", "GB", "TB"]: | 127 | for x in ["bytes", "KB", "MB", "GB", "TB"]: |
487 | @@ -78,3 +140,30 @@ | |||
488 | 78 | hertz /= 1000.0 | 140 | hertz /= 1000.0 |
489 | 79 | 141 | ||
490 | 80 | return string | 142 | return string |
491 | 143 | |||
492 | 144 | def string_to_type(string): | ||
493 | 145 | """Return a typed representation for the given string. | ||
494 | 146 | |||
495 | 147 | The result might be a bool, int or float. The string might also be | ||
496 | 148 | supplemented by a multiplier like KB which would return an int or | ||
497 | 149 | float multiplied by 1024 for example. | ||
498 | 150 | |||
499 | 151 | :param string: The string representation. | ||
500 | 152 | """ | ||
501 | 153 | if isinstance(string, basestring): | ||
502 | 154 | for regex, formatter in TYPE_FORMATS: | ||
503 | 155 | match = regex.match(string) | ||
504 | 156 | if match: | ||
505 | 157 | string = formatter(match) | ||
506 | 158 | if len(match.groups()) > 1: | ||
507 | 159 | unit = match.group(2) | ||
508 | 160 | for regex, multiplier in TYPE_MULTIPLIERS: | ||
509 | 161 | match = regex.match(unit) | ||
510 | 162 | if match: | ||
511 | 163 | string *= multiplier | ||
512 | 164 | break | ||
513 | 165 | else: | ||
514 | 166 | raise ValueError("Unknown multiplier: %s" % unit) | ||
515 | 167 | break | ||
516 | 168 | |||
517 | 169 | return string | ||
518 | 81 | 170 | ||
519 | === modified file 'checkbox/lib/dmi.py' | |||
520 | --- checkbox/lib/dmi.py 2009-09-08 23:01:38 +0000 | |||
521 | +++ checkbox/lib/dmi.py 2011-11-18 18:04:27 +0000 | |||
522 | @@ -16,13 +16,15 @@ | |||
523 | 16 | # You should have received a copy of the GNU General Public License | 16 | # You should have received a copy of the GNU General Public License |
524 | 17 | # along with Checkbox. If not, see <http://www.gnu.org/licenses/>. | 17 | # along with Checkbox. If not, see <http://www.gnu.org/licenses/>. |
525 | 18 | # | 18 | # |
526 | 19 | import os | ||
527 | 20 | |||
528 | 19 | 21 | ||
529 | 20 | # See also 3.3.4.1 of the "System Management BIOS Reference Specification, | 22 | # See also 3.3.4.1 of the "System Management BIOS Reference Specification, |
530 | 21 | # Version 2.6.1" (Preliminary Standard) document, available from | 23 | # Version 2.6.1" (Preliminary Standard) document, available from |
531 | 22 | # http://www.dmtf.org/standards/smbios. | 24 | # http://www.dmtf.org/standards/smbios. |
532 | 23 | class Dmi: | 25 | class Dmi: |
533 | 24 | chassis = ( | 26 | chassis = ( |
535 | 25 | ("Undefined", "unknown"), # 0x00 | 27 | ("Undefined", "unknown"), # 0x00 |
536 | 26 | ("Other", "unknown"), | 28 | ("Other", "unknown"), |
537 | 27 | ("Unknown", "unknown"), | 29 | ("Unknown", "unknown"), |
538 | 28 | ("Desktop", "desktop"), | 30 | ("Desktop", "desktop"), |
539 | @@ -53,22 +55,171 @@ | |||
540 | 53 | ("Blade", "server"), | 55 | ("Blade", "server"), |
541 | 54 | ("Blade Enclosure", "unknown")) | 56 | ("Blade Enclosure", "unknown")) |
542 | 55 | 57 | ||
545 | 56 | chassis_names = [c[0] for c in chassis] | 58 | chassis_names = tuple(c[0] for c in chassis) |
546 | 57 | chassis_types = [c[1] for c in chassis] | 59 | chassis_types = tuple(c[1] for c in chassis) |
547 | 58 | chassis_name_to_type = dict(chassis) | 60 | chassis_name_to_type = dict(chassis) |
548 | 59 | 61 | ||
564 | 60 | 62 | type_names = ( | |
565 | 61 | class DmiNotAvailable(object): | 63 | "BIOS", # 0x00 |
566 | 62 | def __init__(self, function): | 64 | "System", |
567 | 63 | self._function = function | 65 | "Base Board", |
568 | 64 | 66 | "Chassis", | |
569 | 65 | def __get__(self, instance, cls=None): | 67 | "Processor", |
570 | 66 | self._instance = instance | 68 | "Memory Controller", |
571 | 67 | return self | 69 | "Memory Module", |
572 | 68 | 70 | "Cache", | |
573 | 69 | def __call__(self, *args, **kwargs): | 71 | "Port Connector", |
574 | 70 | name = self._function(self._instance, *args, **kwargs) | 72 | "System Slots", |
575 | 71 | if name == "Not Available": | 73 | "On Board Devices", |
576 | 72 | name = None | 74 | "OEM Strings", |
577 | 73 | 75 | "System Configuration Options", | |
578 | 74 | return name | 76 | "BIOS Language", |
579 | 77 | "Group Associations", | ||
580 | 78 | "System Event Log", | ||
581 | 79 | "Physical Memory Array", | ||
582 | 80 | "Memory Device", | ||
583 | 81 | "32-bit Memory Error", | ||
584 | 82 | "Memory Array Mapped Address", | ||
585 | 83 | "Memory Device Mapped Address", | ||
586 | 84 | "Built-in Pointing Device", | ||
587 | 85 | "Portable Battery", | ||
588 | 86 | "System Reset", | ||
589 | 87 | "Hardware Security", | ||
590 | 88 | "System Power Controls", | ||
591 | 89 | "Voltage Probe", | ||
592 | 90 | "Cooling Device", | ||
593 | 91 | "Temperature Probe", | ||
594 | 92 | "Electrical Current Probe", | ||
595 | 93 | "Out-of-band Remote Access", | ||
596 | 94 | "Boot Integrity Services", | ||
597 | 95 | "System Boot", | ||
598 | 96 | "64-bit Memory Error", | ||
599 | 97 | "Management Device", | ||
600 | 98 | "Management Device Component", | ||
601 | 99 | "Management Device Threshold Data", | ||
602 | 100 | "Memory Channel", | ||
603 | 101 | "IPMI Device", | ||
604 | 102 | "Power Supply", | ||
605 | 103 | ) | ||
606 | 104 | |||
607 | 105 | |||
608 | 106 | class DmiDevice: | ||
609 | 107 | |||
610 | 108 | bus = "dmi" | ||
611 | 109 | driver = None | ||
612 | 110 | product_id = None | ||
613 | 111 | vendor_id = None | ||
614 | 112 | |||
615 | 113 | _product_blacklist = ( | ||
616 | 114 | "<BAD INDEX>", | ||
617 | 115 | "N/A", | ||
618 | 116 | "Not Available", | ||
619 | 117 | "INVALID", | ||
620 | 118 | "OEM", | ||
621 | 119 | "Product Name", | ||
622 | 120 | "System Product Name", | ||
623 | 121 | "To be filled by O.E.M.", | ||
624 | 122 | "To Be Filled By O.E.M.", | ||
625 | 123 | "To Be Filled By O.E.M. by More String", | ||
626 | 124 | "Unknown", | ||
627 | 125 | "Uknown", | ||
628 | 126 | "Unknow", | ||
629 | 127 | "xxxxxxxxxxxxxx", | ||
630 | 128 | ) | ||
631 | 129 | _vendor_blacklist = ( | ||
632 | 130 | "<BAD INDEX>", | ||
633 | 131 | "Not Available", | ||
634 | 132 | "OEM", | ||
635 | 133 | "OEM Manufacturer", | ||
636 | 134 | "System manufacturer", | ||
637 | 135 | "System Manufacturer", | ||
638 | 136 | "System Name", | ||
639 | 137 | "To be filled by O.E.M.", | ||
640 | 138 | "To Be Filled By O.E.M.", | ||
641 | 139 | "To Be Filled By O.E.M. by More String", | ||
642 | 140 | "Unknow", # XXX This is correct mispelling | ||
643 | 141 | "Unknown", | ||
644 | 142 | ) | ||
645 | 143 | _serial_blacklist = ( | ||
646 | 144 | "0", | ||
647 | 145 | "00000000", | ||
648 | 146 | "00 00 00 00 00 00 00 00", | ||
649 | 147 | "0123456789", | ||
650 | 148 | "Base Board Serial Number", | ||
651 | 149 | "Chassis Serial Number", | ||
652 | 150 | "N/A", | ||
653 | 151 | "None", | ||
654 | 152 | "Not Applicable", | ||
655 | 153 | "Not Available", | ||
656 | 154 | "Not Specified", | ||
657 | 155 | "OEM", | ||
658 | 156 | "System Serial Number", | ||
659 | 157 | ) | ||
660 | 158 | _version_blacklist = ( | ||
661 | 159 | "-1", | ||
662 | 160 | "<BAD INDEX>", | ||
663 | 161 | "N/A", | ||
664 | 162 | "None", | ||
665 | 163 | "Not Applicable", | ||
666 | 164 | "Not Available", | ||
667 | 165 | "Not Specified", | ||
668 | 166 | "OEM", | ||
669 | 167 | "System Version", | ||
670 | 168 | "Unknown", | ||
671 | 169 | "x.x", | ||
672 | 170 | ) | ||
673 | 171 | |||
674 | 172 | def __init__(self, attributes, category): | ||
675 | 173 | self._attributes = attributes | ||
676 | 174 | self.category = category | ||
677 | 175 | |||
678 | 176 | @property | ||
679 | 177 | def path(self): | ||
680 | 178 | path = "/devices/virtual/dmi/id" | ||
681 | 179 | return os.path.join(path, self.category.lower()) | ||
682 | 180 | |||
683 | 181 | @property | ||
684 | 182 | def product(self): | ||
685 | 183 | if self.category == "CHASSIS": | ||
686 | 184 | type_string = self._attributes.get("chassis_type", "0") | ||
687 | 185 | try: | ||
688 | 186 | type_index = int(type_string) | ||
689 | 187 | return Dmi.chassis_names[type_index] | ||
690 | 188 | except ValueError: | ||
691 | 189 | return type_string | ||
692 | 190 | |||
693 | 191 | for name in "name", "version": | ||
694 | 192 | attribute = "%s_%s" % (self.category.lower(), name) | ||
695 | 193 | product = self._attributes.get(attribute) | ||
696 | 194 | if product and product not in self._product_blacklist: | ||
697 | 195 | return product | ||
698 | 196 | |||
699 | 197 | return None | ||
700 | 198 | |||
701 | 199 | @property | ||
702 | 200 | def vendor(self): | ||
703 | 201 | for name in "manufacturer", "vendor": | ||
704 | 202 | attribute = "%s_%s" % (self.category.lower(), name) | ||
705 | 203 | vendor = self._attributes.get(attribute) | ||
706 | 204 | if vendor and vendor not in self._vendor_blacklist: | ||
707 | 205 | return vendor | ||
708 | 206 | |||
709 | 207 | return None | ||
710 | 208 | |||
711 | 209 | @property | ||
712 | 210 | def serial(self): | ||
713 | 211 | attribute = "%s_serial" % self.category.lower() | ||
714 | 212 | serial = self._attributes.get(attribute) | ||
715 | 213 | if serial and serial not in self._serial_blacklist: | ||
716 | 214 | return serial | ||
717 | 215 | |||
718 | 216 | return None | ||
719 | 217 | |||
720 | 218 | @property | ||
721 | 219 | def version(self): | ||
722 | 220 | attribute = "%s_version" % self.category.lower() | ||
723 | 221 | version = self._attributes.get(attribute) | ||
724 | 222 | if version and version not in self._version_blacklist: | ||
725 | 223 | return version | ||
726 | 224 | |||
727 | 225 | return None | ||
728 | 75 | 226 | ||
729 | === modified file 'checkbox/lib/safe.py' | |||
730 | --- checkbox/lib/safe.py 2009-03-17 09:46:16 +0000 | |||
731 | +++ checkbox/lib/safe.py 2011-11-18 18:04:27 +0000 | |||
732 | @@ -94,3 +94,8 @@ | |||
733 | 94 | md5sum = digest.hexdigest() | 94 | md5sum = digest.hexdigest() |
734 | 95 | 95 | ||
735 | 96 | return md5sum | 96 | return md5sum |
736 | 97 | |||
737 | 98 | def safe_close(file): | ||
738 | 99 | file.flush() | ||
739 | 100 | os.fsync(file.fileno()) | ||
740 | 101 | file.close() | ||
741 | 97 | 102 | ||
742 | === modified file 'checkbox/lib/template.py' | |||
743 | --- checkbox/lib/template.py 2010-04-06 14:17:46 +0000 | |||
744 | +++ checkbox/lib/template.py 2011-11-18 18:04:27 +0000 | |||
745 | @@ -95,7 +95,7 @@ | |||
746 | 95 | if line.startswith("#"): | 95 | if line.startswith("#"): |
747 | 96 | continue | 96 | continue |
748 | 97 | 97 | ||
750 | 98 | match = re.search(r"^([-_.A-Za-z0-9]*):\s?(.*)", line) | 98 | match = re.search(r"^([-_.A-Za-z0-9@]*):\s?(.*)", line) |
751 | 99 | if match: | 99 | if match: |
752 | 100 | _save(field, value, extended) | 100 | _save(field, value, extended) |
753 | 101 | field = match.groups()[0].lower() | 101 | field = match.groups()[0].lower() |
754 | 102 | 102 | ||
755 | === modified file 'checkbox/message.py' | |||
756 | --- checkbox/message.py 2010-03-09 16:58:36 +0000 | |||
757 | +++ checkbox/message.py 2011-11-18 18:04:27 +0000 | |||
758 | @@ -22,7 +22,7 @@ | |||
759 | 22 | import posixpath | 22 | import posixpath |
760 | 23 | 23 | ||
761 | 24 | from checkbox.contrib import bpickle | 24 | from checkbox.contrib import bpickle |
763 | 25 | 25 | from checkbox.lib.safe import safe_close | |
764 | 26 | 26 | ||
765 | 27 | HELD = "h" | 27 | HELD = "h" |
766 | 28 | BROKEN = "b" | 28 | BROKEN = "b" |
767 | @@ -215,7 +215,7 @@ | |||
768 | 215 | try: | 215 | try: |
769 | 216 | return file.read() | 216 | return file.read() |
770 | 217 | finally: | 217 | finally: |
772 | 218 | file.close() | 218 | safe_close(file) |
773 | 219 | 219 | ||
774 | 220 | def _get_flags(self, path): | 220 | def _get_flags(self, path): |
775 | 221 | basename = posixpath.basename(path) | 221 | basename = posixpath.basename(path) |
776 | @@ -253,7 +253,8 @@ | |||
777 | 253 | 253 | ||
778 | 254 | file = open(filename + ".tmp", "w") | 254 | file = open(filename + ".tmp", "w") |
779 | 255 | file.write(message_data) | 255 | file.write(message_data) |
781 | 256 | file.close() | 256 | safe_close(file) |
782 | 257 | |||
783 | 257 | os.rename(filename + ".tmp", filename) | 258 | os.rename(filename + ".tmp", filename) |
784 | 258 | 259 | ||
785 | 259 | # For now we use the inode as the message id, as it will work | 260 | # For now we use the inode as the message id, as it will work |
786 | 260 | 261 | ||
787 | === modified file 'checkbox/parsers/cpuinfo.py' | |||
788 | --- checkbox/parsers/cpuinfo.py 2011-06-13 14:22:39 +0000 | |||
789 | +++ checkbox/parsers/cpuinfo.py 2011-11-18 18:04:27 +0000 | |||
790 | @@ -16,24 +16,26 @@ | |||
791 | 16 | # You should have received a copy of the GNU General Public License | 16 | # You should have received a copy of the GNU General Public License |
792 | 17 | # along with Checkbox. If not, see <http://www.gnu.org/licenses/>. | 17 | # along with Checkbox. If not, see <http://www.gnu.org/licenses/>. |
793 | 18 | # | 18 | # |
794 | 19 | import os | ||
795 | 20 | import re | 19 | import re |
796 | 21 | 20 | ||
797 | 21 | from os import uname | ||
798 | 22 | |||
799 | 22 | from checkbox.lib.conversion import string_to_type | 23 | from checkbox.lib.conversion import string_to_type |
806 | 23 | from checkbox.parsers.utils import implement_from_dict | 24 | |
807 | 24 | 25 | ||
808 | 25 | 26 | class CpuinfoParser: | |
809 | 26 | class CpuinfoParser(object): | 27 | """Parser for the /proc/cpuinfo file.""" |
810 | 27 | 28 | ||
811 | 28 | def __init__(self, stream, uname=None): | 29 | def __init__(self, stream, machine=None): |
812 | 29 | self.stream = stream | 30 | self.stream = stream |
814 | 30 | self.uname = uname or os.uname()[4].lower() | 31 | self.machine = machine or uname()[4].lower() |
815 | 31 | 32 | ||
816 | 32 | def getAttributes(self): | 33 | def getAttributes(self): |
817 | 33 | count = 0 | 34 | count = 0 |
818 | 34 | attributes = {} | 35 | attributes = {} |
819 | 35 | cpuinfo = self.stream.read() | 36 | cpuinfo = self.stream.read() |
821 | 36 | for block in cpuinfo.split("\n\n"): | 37 | for block in re.split(r"\n{2,}", cpuinfo): |
822 | 38 | block = block.strip() | ||
823 | 37 | if not block: | 39 | if not block: |
824 | 38 | continue | 40 | continue |
825 | 39 | 41 | ||
826 | @@ -54,19 +56,23 @@ | |||
827 | 54 | 56 | ||
828 | 55 | attributes[key.lower()] = value | 57 | attributes[key.lower()] = value |
829 | 56 | 58 | ||
831 | 57 | attributes["count"] = count | 59 | if attributes: |
832 | 60 | attributes["count"] = count | ||
833 | 61 | |||
834 | 58 | return attributes | 62 | return attributes |
835 | 59 | 63 | ||
836 | 60 | def run(self, result): | 64 | def run(self, result): |
837 | 61 | uname = self.uname | ||
838 | 62 | attributes = self.getAttributes() | 65 | attributes = self.getAttributes() |
839 | 66 | if not attributes: | ||
840 | 67 | return | ||
841 | 63 | 68 | ||
842 | 64 | # Default values | 69 | # Default values |
843 | 70 | machine = self.machine | ||
844 | 65 | processor = { | 71 | processor = { |
846 | 66 | "platform": uname, | 72 | "platform": machine, |
847 | 67 | "count": 1, | 73 | "count": 1, |
850 | 68 | "type": self.uname, | 74 | "type": machine, |
851 | 69 | "model": self.uname, | 75 | "model": machine, |
852 | 70 | "model_number": "", | 76 | "model_number": "", |
853 | 71 | "model_version": "", | 77 | "model_version": "", |
854 | 72 | "model_revision": "", | 78 | "model_revision": "", |
855 | @@ -113,7 +119,6 @@ | |||
856 | 113 | "type": "platform", | 119 | "type": "platform", |
857 | 114 | "model": "cpu", | 120 | "model": "cpu", |
858 | 115 | "model_version": "revision", | 121 | "model_version": "revision", |
859 | 116 | "vendor": "machine", | ||
860 | 117 | "speed": "clock"}, | 122 | "speed": "clock"}, |
861 | 118 | ("sparc64", "sparc",): { | 123 | ("sparc64", "sparc",): { |
862 | 119 | "count": "ncpus probed", | 124 | "count": "ncpus probed", |
863 | @@ -126,7 +131,7 @@ | |||
864 | 126 | bogompips_string = attributes.get("bogomips", "0.0") | 131 | bogompips_string = attributes.get("bogomips", "0.0") |
865 | 127 | processor["bogomips"] = int(round(float(bogompips_string))) | 132 | processor["bogomips"] = int(round(float(bogompips_string))) |
866 | 128 | for platform, conversion in platform_to_conversion.iteritems(): | 133 | for platform, conversion in platform_to_conversion.iteritems(): |
868 | 129 | if uname in platform: | 134 | if machine in platform: |
869 | 130 | for pkey, ckey in conversion.iteritems(): | 135 | for pkey, ckey in conversion.iteritems(): |
870 | 131 | if isinstance(ckey, (list, tuple)): | 136 | if isinstance(ckey, (list, tuple)): |
871 | 132 | processor[pkey] = "/".join([attributes[k] | 137 | processor[pkey] = "/".join([attributes[k] |
872 | @@ -134,13 +139,11 @@ | |||
873 | 134 | elif ckey in attributes: | 139 | elif ckey in attributes: |
874 | 135 | processor[pkey] = attributes[ckey] | 140 | processor[pkey] = attributes[ckey] |
875 | 136 | 141 | ||
883 | 137 | # Adjust platform and vendor | 142 | # Adjust platform |
884 | 138 | if uname[0] == "i" and uname[-2:] == "86": | 143 | if machine[0] == "i" and machine[-2:] == "86": |
885 | 139 | processor["platform"] = "i386" | 144 | processor["platform"] = u"i386" |
886 | 140 | elif uname[:5] == "alpha": | 145 | elif machine[:5] == "alpha": |
887 | 141 | processor["platform"] = "alpha" | 146 | processor["platform"] = u"alpha" |
881 | 142 | elif uname[:5] == "sparc": | ||
882 | 143 | processor["vendor"] = "sun" | ||
888 | 144 | 147 | ||
889 | 145 | # Adjust cache | 148 | # Adjust cache |
890 | 146 | if processor["cache"]: | 149 | if processor["cache"]: |
891 | @@ -148,14 +151,14 @@ | |||
892 | 148 | 151 | ||
893 | 149 | # Adjust speed | 152 | # Adjust speed |
894 | 150 | try: | 153 | try: |
896 | 151 | if uname[:5] == "alpha": | 154 | if machine[:5] == "alpha": |
897 | 152 | speed = processor["speed"].split()[0] | 155 | speed = processor["speed"].split()[0] |
898 | 153 | processor["speed"] = int(round(float(speed))) / 1000000 | 156 | processor["speed"] = int(round(float(speed))) / 1000000 |
900 | 154 | elif uname[:5] == "sparc": | 157 | elif machine[:5] == "sparc": |
901 | 155 | speed = processor["speed"] | 158 | speed = processor["speed"] |
902 | 156 | processor["speed"] = int(round(float(speed))) / 2 | 159 | processor["speed"] = int(round(float(speed))) / 2 |
903 | 157 | else: | 160 | else: |
905 | 158 | if uname[:3] == "ppc": | 161 | if machine[:3] == "ppc": |
906 | 159 | # String is appended with "mhz" | 162 | # String is appended with "mhz" |
907 | 160 | speed = processor["speed"][:-3] | 163 | speed = processor["speed"][:-3] |
908 | 161 | else: | 164 | else: |
909 | @@ -174,18 +177,4 @@ | |||
910 | 174 | if processor["count"] == 0: | 177 | if processor["count"] == 0: |
911 | 175 | processor["count"] = 1 | 178 | processor["count"] = 1 |
912 | 176 | 179 | ||
928 | 177 | for key, value in processor.iteritems(): | 180 | result.setProcessor(processor) |
914 | 178 | camel_case = key.replace("_", " ").title().replace(" ", "") | ||
915 | 179 | method_name = "set%s" % camel_case | ||
916 | 180 | method = getattr(result, method_name) | ||
917 | 181 | method(value) | ||
918 | 182 | |||
919 | 183 | |||
920 | 184 | class CpuinfoResult(dict): | ||
921 | 185 | |||
922 | 186 | def __getattr__(self, name): | ||
923 | 187 | name = re.sub(r"([A-Z])", "_\\1", name)[4:].lower() | ||
924 | 188 | def setAll(value): | ||
925 | 189 | self[name] = value | ||
926 | 190 | |||
927 | 191 | return setAll | ||
929 | 192 | 181 | ||
930 | === added file 'checkbox/parsers/cputable' | |||
931 | --- checkbox/parsers/cputable 1970-01-01 00:00:00 +0000 | |||
932 | +++ checkbox/parsers/cputable 2011-11-18 18:04:27 +0000 | |||
933 | @@ -0,0 +1,40 @@ | |||
934 | 1 | # This file contains the table of known CPU names. | ||
935 | 2 | # | ||
936 | 3 | # Architecture names are formed as a combination of the system name | ||
937 | 4 | # (from ostable) and CPU name (from this table) after mapping from | ||
938 | 5 | # the Debian triplet (from triplettable). A list of architecture | ||
939 | 6 | # names in the Debian ‘sid’ distribution can be found in the archtable | ||
940 | 7 | # file. | ||
941 | 8 | # | ||
942 | 9 | # Column 1 is the Debian name for the CPU, used to form the cpu part in | ||
943 | 10 | # the Debian triplet. | ||
944 | 11 | # Column 2 is the GNU name for the CPU, used to output build and host | ||
945 | 12 | # targets in ‘dpkg-architecture’. | ||
946 | 13 | # Column 3 is an extended regular expression used to match against the | ||
947 | 14 | # CPU part of the output of the GNU config.guess script. | ||
948 | 15 | # Column 4 is the size (in bits) of the integers/pointers | ||
949 | 16 | # Column 5 is the endianness (byte ordering in numbers) | ||
950 | 17 | # | ||
951 | 18 | # <Debian name> <GNU name> <config.guess regex> <Bits> <Endianness> | ||
952 | 19 | i386 i686 (i[3456]86|pentium) 32 little | ||
953 | 20 | ia64 ia64 ia64 64 little | ||
954 | 21 | alpha alpha alpha.* 64 little | ||
955 | 22 | amd64 x86_64 x86_64 64 little | ||
956 | 23 | armeb armeb arm.*b 32 big | ||
957 | 24 | arm arm arm.* 32 little | ||
958 | 25 | avr32 avr32 avr32 32 big | ||
959 | 26 | hppa hppa hppa.* 32 big | ||
960 | 27 | m32r m32r m32r 32 big | ||
961 | 28 | m68k m68k m68k 32 big | ||
962 | 29 | mips mips mips(eb)? 32 big | ||
963 | 30 | mipsel mipsel mipsel 32 little | ||
964 | 31 | powerpc powerpc (powerpc|ppc) 32 big | ||
965 | 32 | ppc64 powerpc64 (powerpc|ppc)64 64 big | ||
966 | 33 | s390 s390 s390 32 big | ||
967 | 34 | s390x s390x s390x 64 big | ||
968 | 35 | sh3 sh3 sh3 32 little | ||
969 | 36 | sh3eb sh3eb sh3eb 32 big | ||
970 | 37 | sh4 sh4 sh4 32 little | ||
971 | 38 | sh4eb sh4eb sh4eb 32 big | ||
972 | 39 | sparc sparc sparc 32 big | ||
973 | 40 | sparc64 sparc64 sparc64 64 big | ||
974 | 0 | 41 | ||
975 | === added file 'checkbox/parsers/cputable.py' | |||
976 | --- checkbox/parsers/cputable.py 1970-01-01 00:00:00 +0000 | |||
977 | +++ checkbox/parsers/cputable.py 2011-11-18 18:04:27 +0000 | |||
978 | @@ -0,0 +1,42 @@ | |||
979 | 1 | # | ||
980 | 2 | # This file is part of Checkbox. | ||
981 | 3 | # | ||
982 | 4 | # Copyright 2011 Canonical Ltd. | ||
983 | 5 | # | ||
984 | 6 | # Checkbox is free software: you can redistribute it and/or modify | ||
985 | 7 | # it under the terms of the GNU General Public License as published by | ||
986 | 8 | # the Free Software Foundation, either version 3 of the License, or | ||
987 | 9 | # (at your option) any later version. | ||
988 | 10 | # | ||
989 | 11 | # Checkbox is distributed in the hope that it will be useful, | ||
990 | 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
991 | 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
992 | 14 | # GNU General Public License for more details. | ||
993 | 15 | # | ||
994 | 16 | # You should have received a copy of the GNU General Public License | ||
995 | 17 | # along with Checkbox. If not, see <http://www.gnu.org/licenses/>. | ||
996 | 18 | # | ||
997 | 19 | import re | ||
998 | 20 | |||
999 | 21 | |||
1000 | 22 | CPUTABLE_RE = re.compile( | ||
1001 | 23 | r"^(?!\#)(?P<debian_name>\S+)" | ||
1002 | 24 | r"\s+(?P<gnu_name>\S+)" | ||
1003 | 25 | r"\s+(?P<regex>\S+)" | ||
1004 | 26 | r"\s+(?P<bits>\d+)" | ||
1005 | 27 | r"\s+(?P<endianness>big|little)") | ||
1006 | 28 | |||
1007 | 29 | |||
1008 | 30 | class CputableParser: | ||
1009 | 31 | """Parser for the /usr/share/dpkg/cputable file.""" | ||
1010 | 32 | |||
1011 | 33 | def __init__(self, stream): | ||
1012 | 34 | self.stream = stream | ||
1013 | 35 | |||
1014 | 36 | def run(self, result): | ||
1015 | 37 | for line in self.stream.readlines(): | ||
1016 | 38 | match = CPUTABLE_RE.match(line) | ||
1017 | 39 | if match: | ||
1018 | 40 | cpu = match.groupdict() | ||
1019 | 41 | cpu["bits"] = int(cpu["bits"]) | ||
1020 | 42 | result.addCpu(cpu) | ||
1021 | 0 | 43 | ||
1022 | === added file 'checkbox/parsers/deferred.py' | |||
1023 | --- checkbox/parsers/deferred.py 1970-01-01 00:00:00 +0000 | |||
1024 | +++ checkbox/parsers/deferred.py 2011-11-18 18:04:27 +0000 | |||
1025 | @@ -0,0 +1,27 @@ | |||
1026 | 1 | # | ||
1027 | 2 | # This file is part of Checkbox. | ||
1028 | 3 | # | ||
1029 | 4 | # Copyright 2011 Canonical Ltd. | ||
1030 | 5 | # | ||
1031 | 6 | # Checkbox is free software: you can redistribute it and/or modify | ||
1032 | 7 | # it under the terms of the GNU General Public License as published by | ||
1033 | 8 | # the Free Software Foundation, either version 3 of the License, or | ||
1034 | 9 | # (at your option) any later version. | ||
1035 | 10 | # | ||
1036 | 11 | # Checkbox is distributed in the hope that it will be useful, | ||
1037 | 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1038 | 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1039 | 14 | # GNU General Public License for more details. | ||
1040 | 15 | # | ||
1041 | 16 | # You should have received a copy of the GNU General Public License | ||
1042 | 17 | # along with Checkbox. If not, see <http://www.gnu.org/licenses/>. | ||
1043 | 18 | # | ||
1044 | 19 | class DeferredParser: | ||
1045 | 20 | """Parser for deferred dispatching of events.""" | ||
1046 | 21 | |||
1047 | 22 | def __init__(self, dispatcher, event_type="result"): | ||
1048 | 23 | self.dispatcher = dispatcher | ||
1049 | 24 | self.event_type = event_type | ||
1050 | 25 | |||
1051 | 26 | def run(self, result): | ||
1052 | 27 | self.dispatcher.publishEvent(self.event_type, result) | ||
1053 | 0 | 28 | ||
1054 | === added file 'checkbox/parsers/dmidecode.py' | |||
1055 | --- checkbox/parsers/dmidecode.py 1970-01-01 00:00:00 +0000 | |||
1056 | +++ checkbox/parsers/dmidecode.py 2011-11-18 18:04:27 +0000 | |||
1057 | @@ -0,0 +1,123 @@ | |||
1058 | 1 | # | ||
1059 | 2 | # This file is part of Checkbox. | ||
1060 | 3 | # | ||
1061 | 4 | # Copyright 2011 Canonical Ltd. | ||
1062 | 5 | # | ||
1063 | 6 | # Checkbox is free software: you can redistribute it and/or modify | ||
1064 | 7 | # it under the terms of the GNU General Public License as published by | ||
1065 | 8 | # the Free Software Foundation, either version 3 of the License, or | ||
1066 | 9 | # (at your option) any later version. | ||
1067 | 10 | # | ||
1068 | 11 | # Checkbox is distributed in the hope that it will be useful, | ||
1069 | 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1070 | 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1071 | 14 | # GNU General Public License for more details. | ||
1072 | 15 | # | ||
1073 | 16 | # You should have received a copy of the GNU General Public License | ||
1074 | 17 | # along with Checkbox. If not, see <http://www.gnu.org/licenses/>. | ||
1075 | 18 | # | ||
1076 | 19 | import re | ||
1077 | 20 | |||
1078 | 21 | from string import ( | ||
1079 | 22 | hexdigits, | ||
1080 | 23 | uppercase, | ||
1081 | 24 | ) | ||
1082 | 25 | |||
1083 | 26 | from checkbox.lib.dmi import ( | ||
1084 | 27 | Dmi, | ||
1085 | 28 | DmiDevice, | ||
1086 | 29 | ) | ||
1087 | 30 | |||
1088 | 31 | |||
1089 | 32 | HANDLE_RE = re.compile( | ||
1090 | 33 | r"^Handle (?P<handle>0x[%s]{4}), " | ||
1091 | 34 | r"DMI type (?P<type>\d+), " | ||
1092 | 35 | r"(?P<size>\d+) bytes$" | ||
1093 | 36 | % hexdigits) | ||
1094 | 37 | KEY_VALUE_RE = re.compile( | ||
1095 | 38 | r"^\t(?P<key>[%s].+):( (?P<value>.+))?$" | ||
1096 | 39 | % uppercase) | ||
1097 | 40 | |||
1098 | 41 | |||
1099 | 42 | class DmidecodeParser: | ||
1100 | 43 | """Parser for the dmidecode command.""" | ||
1101 | 44 | |||
1102 | 45 | _key_map = { | ||
1103 | 46 | "ID": "serial", | ||
1104 | 47 | "Manufacturer": "vendor", | ||
1105 | 48 | "Product Name": "name", | ||
1106 | 49 | "Serial Number": "serial", | ||
1107 | 50 | "Type": "type", | ||
1108 | 51 | "Vendor": "vendor", | ||
1109 | 52 | "Version": "version", | ||
1110 | 53 | } | ||
1111 | 54 | |||
1112 | 55 | def __init__(self, stream): | ||
1113 | 56 | self.stream = stream | ||
1114 | 57 | |||
1115 | 58 | def _parseKey(self, key): | ||
1116 | 59 | return self._key_map.get(key) | ||
1117 | 60 | |||
1118 | 61 | def _parseValue(self, value): | ||
1119 | 62 | if value is not None: | ||
1120 | 63 | value = value.strip() | ||
1121 | 64 | if not value: | ||
1122 | 65 | value = None | ||
1123 | 66 | |||
1124 | 67 | return value | ||
1125 | 68 | |||
1126 | 69 | def run(self, result): | ||
1127 | 70 | output = self.stream.read() | ||
1128 | 71 | for record in re.split(r"\n{2,}", output): | ||
1129 | 72 | record = record.strip() | ||
1130 | 73 | # Skip empty records | ||
1131 | 74 | if not record: | ||
1132 | 75 | continue | ||
1133 | 76 | |||
1134 | 77 | # Skip header record | ||
1135 | 78 | lines = record.split("\n") | ||
1136 | 79 | line = lines.pop(0) | ||
1137 | 80 | if line.startswith("#"): | ||
1138 | 81 | continue | ||
1139 | 82 | |||
1140 | 83 | # Skip records with an unsupported handle | ||
1141 | 84 | match = HANDLE_RE.match(line) | ||
1142 | 85 | if not match: | ||
1143 | 86 | continue | ||
1144 | 87 | |||
1145 | 88 | # Skip records that are empty or inactive | ||
1146 | 89 | if not lines or lines.pop(0) == "Inactive": | ||
1147 | 90 | continue | ||
1148 | 91 | |||
1149 | 92 | # Skip disabled entries and end-of-table marker | ||
1150 | 93 | type_index = int(match.group("type")) | ||
1151 | 94 | if type_index >= len(Dmi.type_names): | ||
1152 | 95 | continue | ||
1153 | 96 | |||
1154 | 97 | category = Dmi.type_names[type_index] | ||
1155 | 98 | category = category.upper().split(" ")[-1] | ||
1156 | 99 | if category not in ( | ||
1157 | 100 | "BOARD", "BIOS", "CHASSIS", "PROCESSOR", "SYSTEM"): | ||
1158 | 101 | continue | ||
1159 | 102 | |||
1160 | 103 | # Parse attributes | ||
1161 | 104 | attributes = {} | ||
1162 | 105 | for line in lines: | ||
1163 | 106 | # Skip lines with an unsupported key/value pair | ||
1164 | 107 | match = KEY_VALUE_RE.match(line) | ||
1165 | 108 | if not match: | ||
1166 | 109 | continue | ||
1167 | 110 | |||
1168 | 111 | # Skip lines with an unsupported key | ||
1169 | 112 | key = self._parseKey(match.group("key")) | ||
1170 | 113 | if not key: | ||
1171 | 114 | continue | ||
1172 | 115 | |||
1173 | 116 | key = "%s_%s" % (category.lower(), key) | ||
1174 | 117 | value = self._parseValue(match.group("value")) | ||
1175 | 118 | attributes[key] = value | ||
1176 | 119 | |||
1177 | 120 | device = DmiDevice(attributes, category) | ||
1178 | 121 | result.addDmiDevice(device) | ||
1179 | 122 | |||
1180 | 123 | return result | ||
1181 | 0 | 124 | ||
1182 | === added file 'checkbox/parsers/meminfo.py' | |||
1183 | --- checkbox/parsers/meminfo.py 1970-01-01 00:00:00 +0000 | |||
1184 | +++ checkbox/parsers/meminfo.py 2011-11-18 18:04:27 +0000 | |||
1185 | @@ -0,0 +1,46 @@ | |||
1186 | 1 | # | ||
1187 | 2 | # This file is part of Checkbox. | ||
1188 | 3 | # | ||
1189 | 4 | # Copyright 2011 Canonical Ltd. | ||
1190 | 5 | # | ||
1191 | 6 | # Checkbox is free software: you can redistribute it and/or modify | ||
1192 | 7 | # it under the terms of the GNU General Public License as published by | ||
1193 | 8 | # the Free Software Foundation, either version 3 of the License, or | ||
1194 | 9 | # (at your option) any later version. | ||
1195 | 10 | # | ||
1196 | 11 | # Checkbox is distributed in the hope that it will be useful, | ||
1197 | 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1198 | 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1199 | 14 | # GNU General Public License for more details. | ||
1200 | 15 | # | ||
1201 | 16 | # You should have received a copy of the GNU General Public License | ||
1202 | 17 | # along with Checkbox. If not, see <http://www.gnu.org/licenses/>. | ||
1203 | 18 | # | ||
1204 | 19 | import re | ||
1205 | 20 | |||
1206 | 21 | |||
1207 | 22 | class MeminfoParser: | ||
1208 | 23 | """Parser for the /proc/meminfo file.""" | ||
1209 | 24 | |||
1210 | 25 | def __init__(self, stream): | ||
1211 | 26 | self.stream = stream | ||
1212 | 27 | |||
1213 | 28 | def run(self, result): | ||
1214 | 29 | key_value_pattern = re.compile(r"(?P<key>.*):\s+(?P<value>.*)") | ||
1215 | 30 | meminfo_map = { | ||
1216 | 31 | "MemTotal": "total", | ||
1217 | 32 | "SwapTotal": "swap"} | ||
1218 | 33 | |||
1219 | 34 | meminfo = {} | ||
1220 | 35 | for line in self.stream.readlines(): | ||
1221 | 36 | line = line.strip() | ||
1222 | 37 | match = key_value_pattern.match(line) | ||
1223 | 38 | if match: | ||
1224 | 39 | key = match.group("key") | ||
1225 | 40 | if key in meminfo_map: | ||
1226 | 41 | key = meminfo_map[key] | ||
1227 | 42 | value = match.group("value") | ||
1228 | 43 | (integer, factor) = value.split() | ||
1229 | 44 | meminfo[key] = int(integer) * 1024 | ||
1230 | 45 | |||
1231 | 46 | result.setMemory(meminfo) | ||
1232 | 0 | 47 | ||
1233 | === modified file 'checkbox/parsers/submission.py' | |||
1234 | --- checkbox/parsers/submission.py 2011-06-13 14:22:39 +0000 | |||
1235 | +++ checkbox/parsers/submission.py 2011-11-18 18:04:27 +0000 | |||
1236 | @@ -16,430 +16,521 @@ | |||
1237 | 16 | # You should have received a copy of the GNU General Public License | 16 | # You should have received a copy of the GNU General Public License |
1238 | 17 | # along with Checkbox. If not, see <http://www.gnu.org/licenses/>. | 17 | # along with Checkbox. If not, see <http://www.gnu.org/licenses/>. |
1239 | 18 | # | 18 | # |
1240 | 19 | import re | ||
1241 | 20 | |||
1242 | 21 | import logging | ||
1243 | 22 | |||
1244 | 23 | from datetime import ( | ||
1245 | 24 | datetime, | ||
1246 | 25 | timedelta, | ||
1247 | 26 | ) | ||
1248 | 27 | from dateutil import tz | ||
1249 | 28 | |||
1250 | 29 | from checkbox.parsers.device import DeviceResult | ||
1251 | 30 | from checkbox.parsers.udev import UdevParser | ||
1252 | 31 | from checkbox.parsers.utils import implement_from_dict | ||
1253 | 32 | |||
1254 | 33 | try: | 19 | try: |
1255 | 34 | import xml.etree.cElementTree as etree | 20 | import xml.etree.cElementTree as etree |
1256 | 35 | except ImportError: | 21 | except ImportError: |
1257 | 36 | import cElementTree as etree | 22 | import cElementTree as etree |
1258 | 37 | 23 | ||
1352 | 38 | 24 | from StringIO import StringIO | |
1353 | 39 | _time_regex = re.compile(r""" | 25 | from logging import getLogger |
1354 | 40 | ^(?P<year>\d\d\d\d)-(?P<month>\d\d)-(?P<day>\d\d) | 26 | from pkg_resources import resource_string |
1355 | 41 | T(?P<hour>\d\d):(?P<minute>\d\d):(?P<second>\d\d) | 27 | |
1356 | 42 | (?:\.(?P<second_fraction>\d{0,6}))? | 28 | from checkbox.lib.conversion import string_to_datetime |
1357 | 43 | (?P<tz> | 29 | |
1358 | 44 | (?:(?P<tz_sign>[-+])(?P<tz_hour>\d\d):(?P<tz_minute>\d\d)) | 30 | from checkbox import parsers |
1359 | 45 | | Z)?$ | 31 | from checkbox.dispatcher import DispatcherQueue |
1360 | 46 | """, | 32 | from checkbox.parsers.cpuinfo import CpuinfoParser |
1361 | 47 | re.VERBOSE) | 33 | from checkbox.parsers.cputable import CputableParser |
1362 | 48 | 34 | from checkbox.parsers.deferred import DeferredParser | |
1363 | 49 | _xml_illegal_regex = re.compile( | 35 | from checkbox.parsers.dmidecode import DmidecodeParser |
1364 | 50 | u"([\u0000-\u0008\u000b-\u000c\u000e-\u001f\ufffe-\uffff])" | 36 | from checkbox.parsers.meminfo import MeminfoParser |
1365 | 51 | + u"|([%s-%s][^%s-%s])|([^%s-%s][%s-%s])|([%s-%s]$)|(^[%s-%s])" % ( | 37 | from checkbox.parsers.udevadm import UdevadmParser |
1366 | 52 | unichr(0xd800),unichr(0xdbff),unichr(0xdc00),unichr(0xdfff), | 38 | from checkbox.job import (FAIL, PASS, UNINITIATED, UNRESOLVED, |
1367 | 53 | unichr(0xd800),unichr(0xdbff),unichr(0xdc00),unichr(0xdfff), | 39 | UNSUPPORTED, UNTESTED) |
1368 | 54 | unichr(0xd800),unichr(0xdbff),unichr(0xdc00),unichr(0xdfff))) | 40 | |
1369 | 55 | 41 | ||
1370 | 56 | 42 | class SubmissionResult: | |
1371 | 57 | class HALDevice(object): | 43 | |
1372 | 58 | 44 | def __init__(self, test_run_factory, **kwargs): | |
1373 | 59 | def __init__(self, id, udi, properties): | 45 | self.test_run_factory = test_run_factory |
1374 | 60 | self.id = id | 46 | self.test_run_kwargs = kwargs |
1375 | 61 | self.udi = udi | 47 | self.dispatcher = DispatcherQueue() |
1376 | 62 | self.properties = properties | 48 | |
1377 | 63 | 49 | # Register handlers to incrementally add information | |
1378 | 64 | 50 | register = self.dispatcher.registerHandler | |
1379 | 65 | class SubmissionStream(object): | 51 | register(("cpu", "architecture",), self.addCpuArchitecture) |
1380 | 66 | 52 | register(("identifier",), self.addIdentifier) | |
1381 | 67 | default_size = 4096 | 53 | register(("test_run", "attachment",), self.addAttachment) |
1382 | 68 | 54 | register(("test_run", "device",), self.addDeviceState) | |
1383 | 69 | def __init__(self, stream): | 55 | register(("test_run", "distribution",), self.setDistribution) |
1384 | 70 | self.stream = stream | 56 | register(("test_run", "package_version",), self.addPackageVersion) |
1385 | 71 | self._buffer = "" | 57 | register(("test_run", "test_result",), self.addTestResult) |
1386 | 72 | self._buffers = [] | 58 | |
1387 | 73 | 59 | # Register handlers to set information once | |
1388 | 74 | def read(self, size=None): | 60 | register(("architecture",), self.setArchitecture, count=1) |
1389 | 75 | if size is None: | 61 | register( |
1390 | 76 | size = self.default_size | 62 | ("cpuinfo", "machine", "cpuinfo_result",), |
1391 | 77 | 63 | self.setCpuinfo, count=1) | |
1392 | 78 | info_start_regex = re.compile("^<info .*>$") | 64 | register( |
1393 | 79 | info_end_regex = re.compile("^</info>$") | 65 | ("meminfo", "meminfo_result",), |
1394 | 80 | 66 | self.setMeminfo, count=1) | |
1395 | 81 | in_info = False | 67 | register( |
1396 | 82 | length = sum(len(buffer) for buffer in self._buffers) | 68 | ("project", "series",), |
1397 | 83 | 69 | self.setTestRun, count=1) | |
1398 | 84 | while length < size: | 70 | register( |
1399 | 85 | try: | 71 | ("test_run", "architecture",), |
1400 | 86 | buffer = self.stream.next() | 72 | self.setArchitectureState, count=1) |
1401 | 87 | except StopIteration: | 73 | register( |
1402 | 88 | break | 74 | ("test_run", "memory",), |
1403 | 89 | 75 | self.setMemoryState, count=1) | |
1404 | 90 | if not in_info: | 76 | register( |
1405 | 91 | if info_start_regex.match(buffer): | 77 | ("test_run", "processor",), |
1406 | 92 | in_info = True | 78 | self.setProcessorState, count=1) |
1407 | 93 | self._buffer += "".join(self._buffers) | 79 | register( |
1408 | 94 | self._buffers = [buffer] | 80 | ("udevadm", "bits", "udevadm_result",), |
1409 | 95 | else: | 81 | self.setUdevadm, count=1) |
1410 | 96 | length += len(buffer) | 82 | |
1411 | 97 | self._buffers.append(buffer) | 83 | # Publish events passed as keyword arguments |
1412 | 98 | else: | 84 | if "project" in kwargs: |
1413 | 99 | self._buffers.append(buffer) | 85 | self.dispatcher.publishEvent("project", kwargs.pop("project")) |
1414 | 100 | if info_end_regex.match(buffer): | 86 | self.dispatcher.publishEvent("series", kwargs.pop("series", None)) |
1415 | 101 | in_info = False | 87 | |
1416 | 102 | 88 | def addAttachment(self, test_run, attachment): | |
1417 | 103 | buffer = "".join(self._buffers) | 89 | test_run.addAttachment(**attachment) |
1418 | 104 | self._buffers = [] | 90 | |
1419 | 105 | 91 | def addContext(self, text, command=None): | |
1420 | 106 | if not _xml_illegal_regex.search(buffer): | 92 | if text.strip() == "Command not found.": |
1421 | 107 | length += len(buffer) | 93 | return |
1422 | 108 | self._buffer += buffer | 94 | |
1423 | 109 | 95 | self.dispatcher.publishEvent( | |
1424 | 110 | if self._buffers: | 96 | "attachment", {"name": command, "content": text }) |
1425 | 111 | self._buffer += "".join(self._buffers) | 97 | |
1426 | 112 | self._buffers = [] | 98 | parsers = { |
1427 | 113 | 99 | "cat /proc/cpuinfo": self.parseCpuinfo, | |
1428 | 114 | if not self._buffer: | 100 | "cat /proc/meminfo": self.parseMeminfo, |
1429 | 115 | return None | 101 | "dmidecode": DmidecodeParser, |
1430 | 116 | 102 | "udevadm info --export-db": self.parseUdevadm, | |
1431 | 117 | data = self._buffer[:size] | 103 | } |
1432 | 118 | self._buffers = [self._buffer[size:]] | 104 | parser = parsers.get(command) |
1433 | 119 | self._buffer = "" | 105 | if parser: |
1434 | 120 | 106 | if not isinstance(text, unicode): | |
1435 | 121 | return data | 107 | text = text.decode("utf-8") |
1436 | 122 | 108 | stream = StringIO(text) | |
1437 | 123 | 109 | p = parser(stream) | |
1438 | 124 | class SubmissionParser(object): | 110 | p.run(self) |
1439 | 125 | 111 | ||
1440 | 126 | default_name = "unknown" | 112 | def addCpu(self, cpu): |
1441 | 127 | 113 | self.dispatcher.publishEvent("cpu", cpu) | |
1442 | 128 | def __init__(self, stream, name=None): | 114 | |
1443 | 129 | self.stream = SubmissionStream(stream) | 115 | def addCpuArchitecture(self, cpu, architecture): |
1444 | 130 | self.name = name or self.default_name | 116 | if cpu["debian_name"] == architecture: |
1445 | 117 | self.dispatcher.publishEvent("machine", cpu["gnu_name"]) | ||
1446 | 118 | self.dispatcher.publishEvent("bits", cpu["bits"]) | ||
1447 | 119 | |||
1448 | 120 | def addDevice(self, device): | ||
1449 | 121 | self.dispatcher.publishEvent("device", device) | ||
1450 | 122 | |||
1451 | 123 | def addDeviceState(self, test_run, device): | ||
1452 | 124 | test_run.addDeviceState( | ||
1453 | 125 | bus_name=device.bus, category_name=device.category, | ||
1454 | 126 | product_name=device.product, vendor_name=device.vendor, | ||
1455 | 127 | product_id=device.product_id, vendor_id=device.vendor_id, | ||
1456 | 128 | subproduct_id=device.subproduct_id, | ||
1457 | 129 | subvendor_id=device.subvendor_id, | ||
1458 | 130 | driver_name=device.driver, path=device.path) | ||
1459 | 131 | |||
1460 | 132 | def addDmiDevice(self, device): | ||
1461 | 133 | if device.serial: | ||
1462 | 134 | self.dispatcher.publishEvent("identifier", device.serial) | ||
1463 | 135 | |||
1464 | 136 | if device.category in ("BOARD", "SYSTEM") \ | ||
1465 | 137 | and device.vendor != device.product \ | ||
1466 | 138 | and device.product is not None: | ||
1467 | 139 | self.dispatcher.publishEvent("model", device.product) | ||
1468 | 140 | self.dispatcher.publishEvent("make", device.vendor) | ||
1469 | 141 | self.dispatcher.publishEvent("version", device.version) | ||
1470 | 142 | |||
1471 | 143 | def addIdentifier(self, identifier): | ||
1472 | 144 | try: | ||
1473 | 145 | self.identifiers.append(identifier) | ||
1474 | 146 | except AttributeError: | ||
1475 | 147 | self.identifiers = [identifier] | ||
1476 | 148 | self.dispatcher.publishEvent("identifiers", self.identifiers) | ||
1477 | 149 | |||
1478 | 150 | def addPackage(self, package): | ||
1479 | 151 | package_version = { | ||
1480 | 152 | "name": package["name"], | ||
1481 | 153 | "version": package["properties"]["version"], | ||
1482 | 154 | } | ||
1483 | 155 | self.dispatcher.publishEvent("package_version", package_version) | ||
1484 | 156 | |||
1485 | 157 | def addPackageVersion(self, test_run, package_version): | ||
1486 | 158 | test_run.addPackageVersion(**package_version) | ||
1487 | 159 | |||
1488 | 160 | def addQuestion(self, question): | ||
1489 | 161 | answer_to_status = { | ||
1490 | 162 | "fail": FAIL, | ||
1491 | 163 | "no": FAIL, | ||
1492 | 164 | "pass": PASS, | ||
1493 | 165 | "skip": UNTESTED, | ||
1494 | 166 | "uninitiated": UNINITIATED, | ||
1495 | 167 | "unresolved": UNRESOLVED, | ||
1496 | 168 | "unsupported": UNSUPPORTED, | ||
1497 | 169 | "untested": UNTESTED, | ||
1498 | 170 | "yes": PASS, | ||
1499 | 171 | } | ||
1500 | 172 | |||
1501 | 173 | test_result = dict( | ||
1502 | 174 | name=question["name"], | ||
1503 | 175 | output=question["comment"], | ||
1504 | 176 | status=answer_to_status[question["answer"]["value"]], | ||
1505 | 177 | ) | ||
1506 | 178 | test_result.update(self.test_run_kwargs) | ||
1507 | 179 | self.dispatcher.publishEvent("test_result", test_result) | ||
1508 | 180 | |||
1509 | 181 | def addTestResult(self, test_run, test_result): | ||
1510 | 182 | test_run.addTestResult(**test_result) | ||
1511 | 183 | |||
1512 | 184 | def addSummary(self, name, value): | ||
1513 | 185 | if name == "architecture": | ||
1514 | 186 | self.dispatcher.publishEvent("architecture", value) | ||
1515 | 187 | elif name == "distribution": | ||
1516 | 188 | self.dispatcher.publishEvent("project", value) | ||
1517 | 189 | elif name == "distroseries": | ||
1518 | 190 | self.dispatcher.publishEvent("series", value) | ||
1519 | 191 | |||
1520 | 192 | def parseCpuinfo(self, cpuinfo): | ||
1521 | 193 | self.dispatcher.publishEvent("cpuinfo", cpuinfo) | ||
1522 | 194 | return DeferredParser(self.dispatcher, "cpuinfo_result") | ||
1523 | 195 | |||
1524 | 196 | def parseMeminfo(self, meminfo): | ||
1525 | 197 | self.dispatcher.publishEvent("meminfo", meminfo) | ||
1526 | 198 | return DeferredParser(self.dispatcher, "meminfo_result") | ||
1527 | 199 | |||
1528 | 200 | def parseUdevadm(self, udevadm): | ||
1529 | 201 | self.dispatcher.publishEvent("udevadm", udevadm) | ||
1530 | 202 | return DeferredParser(self.dispatcher, "udevadm_result") | ||
1531 | 203 | |||
1532 | 204 | def setArchitecture(self, architecture): | ||
1533 | 205 | string = resource_string(parsers.__name__, "cputable") | ||
1534 | 206 | stream = StringIO(string.decode("utf-8")) | ||
1535 | 207 | parser = CputableParser(stream) | ||
1536 | 208 | parser.run(self) | ||
1537 | 209 | |||
1538 | 210 | def setArchitectureState(self, test_run, architecture): | ||
1539 | 211 | test_run.setArchitectureState(architecture) | ||
1540 | 212 | |||
1541 | 213 | def setCpuinfo(self, cpuinfo, machine, cpuinfo_result): | ||
1542 | 214 | parser = CpuinfoParser(cpuinfo, machine) | ||
1543 | 215 | parser.run(cpuinfo_result) | ||
1544 | 216 | |||
1545 | 217 | def setMeminfo(self, meminfo, meminfo_result): | ||
1546 | 218 | parser = MeminfoParser(meminfo) | ||
1547 | 219 | parser.run(meminfo_result) | ||
1548 | 220 | |||
1549 | 221 | def setDistribution(self, test_run, distribution): | ||
1550 | 222 | test_run.setDistribution(**distribution) | ||
1551 | 223 | |||
1552 | 224 | def setLSBRelease(self, lsb_release): | ||
1553 | 225 | self.dispatcher.publishEvent("distribution", lsb_release) | ||
1554 | 226 | |||
1555 | 227 | def setMemory(self, memory): | ||
1556 | 228 | self.dispatcher.publishEvent("memory", memory) | ||
1557 | 229 | |||
1558 | 230 | def setMemoryState(self, test_run, memory): | ||
1559 | 231 | test_run.setMemoryState(**memory) | ||
1560 | 232 | |||
1561 | 233 | def setProcessor(self, processor): | ||
1562 | 234 | self.dispatcher.publishEvent("processor", processor) | ||
1563 | 235 | |||
1564 | 236 | def setProcessorState(self, test_run, processor): | ||
1565 | 237 | test_run.setProcessorState( | ||
1566 | 238 | platform_name=processor["platform"], | ||
1567 | 239 | make=processor["type"], model=processor["model"], | ||
1568 | 240 | model_number=processor["model_number"], | ||
1569 | 241 | model_version=processor["model_version"], | ||
1570 | 242 | model_revision=processor["model_revision"], | ||
1571 | 243 | cache=processor["cache"], other=processor["other"], | ||
1572 | 244 | bogomips=processor["bogomips"], speed=processor["speed"], | ||
1573 | 245 | count=processor["count"]) | ||
1574 | 246 | |||
1575 | 247 | def setTestRun(self, project, series): | ||
1576 | 248 | test_run = self.test_run_factory( | ||
1577 | 249 | **self.test_run_kwargs) | ||
1578 | 250 | self.dispatcher.publishEvent("test_run", test_run) | ||
1579 | 251 | |||
1580 | 252 | def setUdevadm(self, udevadm, bits, udevadm_result): | ||
1581 | 253 | parser = UdevadmParser(udevadm, bits) | ||
1582 | 254 | parser.run(udevadm_result) | ||
1583 | 255 | |||
1584 | 256 | |||
1585 | 257 | class SubmissionParser: | ||
1586 | 258 | |||
1587 | 259 | def __init__(self, file): | ||
1588 | 260 | self.file = file | ||
1589 | 261 | self.logger = getLogger() | ||
1590 | 131 | 262 | ||
1591 | 132 | def _getClient(self, node): | 263 | def _getClient(self, node): |
1593 | 133 | return "_".join([node.get('name'), node.get('version')]) | 264 | """Return a dictionary with the name and version of the client.""" |
1594 | 265 | return { | ||
1595 | 266 | "name": node.get("name"), | ||
1596 | 267 | "version": node.get("version"), | ||
1597 | 268 | } | ||
1598 | 134 | 269 | ||
1599 | 135 | def _getProperty(self, node): | 270 | def _getProperty(self, node): |
1605 | 136 | """Parse a <property> node. | 271 | """Return the (name, value) of a property.""" |
1606 | 137 | 272 | return (node.get("name"), self._getValueAsType(node)) | |
1602 | 138 | :return: (name, (value, type)) of a property. | ||
1603 | 139 | """ | ||
1604 | 140 | return (node.get('name'), self._getValueAttribute(node)) | ||
1607 | 141 | 273 | ||
1608 | 142 | def _getProperties(self, node): | 274 | def _getProperties(self, node): |
1614 | 143 | """Parse <property> sub-nodes of node. | 275 | """Return a dictionary of properties.""" |
1610 | 144 | |||
1611 | 145 | :return: A dictionary, where each key is the name of a property; | ||
1612 | 146 | the values are the tuples (value, type) of a property. | ||
1613 | 147 | """ | ||
1615 | 148 | properties = {} | 276 | properties = {} |
1616 | 149 | for child in node.getchildren(): | 277 | for child in node.getchildren(): |
1617 | 278 | assert child.tag == "property", \ | ||
1618 | 279 | "Unexpected tag <%s>, expected <property>" % child.tag | ||
1619 | 150 | name, value = self._getProperty(child) | 280 | name, value = self._getProperty(child) |
1620 | 151 | if name in properties: | ||
1621 | 152 | raise ValueError( | ||
1622 | 153 | '<property name="%s"> found more than once in <%s>' | ||
1623 | 154 | % (name, node.tag)) | ||
1624 | 155 | properties[name] = value | 281 | properties[name] = value |
1625 | 156 | 282 | ||
1626 | 157 | return properties | 283 | return properties |
1627 | 158 | 284 | ||
1635 | 159 | def _getValueAttribute(self, node): | 285 | def _getValueAsType(self, node): |
1636 | 160 | """Return (value, type) of a <property> or <value> node.""" | 286 | """Return value of a node as the type attribute.""" |
1637 | 161 | type_ = node.get('type') | 287 | type_ = node.get("type") |
1638 | 162 | if type_ in ('dbus.Boolean', 'bool'): | 288 | if type_ in ("bool",): |
1632 | 163 | value = node.text.strip() == 'True' | ||
1633 | 164 | |||
1634 | 165 | elif type_ in ('str', 'dbus.String', 'dbus.UTF8String'): | ||
1639 | 166 | value = node.text.strip() | 289 | value = node.text.strip() |
1657 | 167 | 290 | assert value in ("True", "False",), \ | |
1658 | 168 | elif type_ in ('dbus.Byte', 'dbus.Int16', 'dbus.Int32', 'dbus.Int64', | 291 | "Unexpected boolean value '%s' in <%s>" % (value, node.tag) |
1659 | 169 | 'dbus.UInt16', 'dbus.UInt32', 'dbus.UInt64', 'int', | 292 | return value == "True" |
1660 | 170 | 'long'): | 293 | elif type_ in ("str",): |
1661 | 171 | value = int(node.text.strip()) | 294 | return unicode(node.text.strip()) |
1662 | 172 | 295 | elif type_ in ("int", "long",): | |
1663 | 173 | elif type_ in ('dbus.Double', 'float'): | 296 | return int(node.text.strip()) |
1664 | 174 | value = float(node.text.strip()) | 297 | elif type_ in ("float",): |
1665 | 175 | 298 | return float(node.text.strip()) | |
1666 | 176 | elif type_ in ('dbus.Array', 'list'): | 299 | elif type_ in ("list",): |
1667 | 177 | value = [self._getValueAttribute(child) | 300 | return list(self._getValueAsType(child) |
1668 | 178 | for child in node.getchildren()] | 301 | for child in node.getchildren()) |
1669 | 179 | 302 | elif type_ in ("dict",): | |
1670 | 180 | elif type_ in ('dbus.Dictionary', 'dict'): | 303 | return dict((child.get("name"), self._getValueAsType(child)) |
1671 | 181 | value = dict((child.get('name'), self._getValueAttribute(child)) | 304 | for child in node.getchildren()) |
1655 | 182 | for child in node.getchildren()) | ||
1656 | 183 | |||
1672 | 184 | else: | 305 | else: |
1673 | 185 | # This should not happen. | ||
1674 | 186 | raise AssertionError( | 306 | raise AssertionError( |
1680 | 187 | 'Unexpected <property> or <value> type: %s' % type_) | 307 | "Unexpected type '%s' in <%s>" % (type_, node.tag)) |
1681 | 188 | 308 | ||
1682 | 189 | return value | 309 | def _getValueAsBoolean(self, node): |
1678 | 190 | |||
1679 | 191 | def _getValueAttributeAsBoolean(self, node): | ||
1683 | 192 | """Return the value of the attribute "value" as a boolean.""" | 310 | """Return the value of the attribute "value" as a boolean.""" |
1687 | 193 | return node.attrib['value'] == "True" | 311 | value = node.attrib["value"] |
1688 | 194 | 312 | assert value in ("True", "False",), \ | |
1689 | 195 | def _getValueAttributeAsString(self, node): | 313 | "Unexpected boolean value '%s' in tag <%s>" % (value, node.tag) |
1690 | 314 | return value == "True" | ||
1691 | 315 | |||
1692 | 316 | def _getValueAsDatetime(self, node): | ||
1693 | 317 | """Return the value of the attribute "value" as a datetime.""" | ||
1694 | 318 | string = node.attrib["value"] | ||
1695 | 319 | return string_to_datetime(string) | ||
1696 | 320 | |||
1697 | 321 | def _getValueAsString(self, node): | ||
1698 | 196 | """Return the value of the attribute "value".""" | 322 | """Return the value of the attribute "value".""" |
1829 | 197 | return node.attrib['value'] | 323 | return unicode(node.attrib["value"]) |
1830 | 198 | 324 | ||
1831 | 199 | def _getValueAttributeAsDateTime(self, node): | 325 | def parseContext(self, result, node): |
1832 | 200 | """Convert a "value" attribute into a datetime object.""" | 326 | """Parse the <context> part of a submission.""" |
1833 | 201 | time_text = node.get('value') | 327 | duplicates = set() |
1834 | 202 | 328 | for child in node.getchildren(): | |
1835 | 203 | # we cannot use time.strptime: this function accepts neither fractions | 329 | assert child.tag == "info", \ |
1836 | 204 | # of a second nor a time zone given e.g. as '+02:30'. | 330 | "Unexpected tag <%s>, expected <info>" % child.tag |
1837 | 205 | match = _time_regex.search(time_text) | 331 | command = child.get("command") |
1838 | 206 | 332 | if command not in duplicates: | |
1839 | 207 | if match is None: | 333 | duplicates.add(command) |
1840 | 208 | raise ValueError( | 334 | result.addContext(child.text, command) |
1841 | 209 | 'Timestamp with unreasonable value: %s' % time_text) | 335 | else: |
1842 | 210 | 336 | self.logger.debug( | |
1843 | 211 | time_parts = match.groupdict() | 337 | "Duplicate command found in tag <info>: %s" % command) |
1844 | 212 | 338 | ||
1845 | 213 | year = int(time_parts['year']) | 339 | def parseHardware(self, result, node): |
1846 | 214 | month = int(time_parts['month']) | 340 | """Parse the <hardware> section of a submission.""" |
1847 | 215 | day = int(time_parts['day']) | 341 | parsers = { |
1848 | 216 | hour = int(time_parts['hour']) | 342 | "dmi": DmidecodeParser, |
1849 | 217 | minute = int(time_parts['minute']) | 343 | "processors": self.parseProcessors, |
1850 | 218 | second = int(time_parts['second']) | 344 | "udev": result.parseUdevadm, |
1851 | 219 | second_fraction = time_parts['second_fraction'] | 345 | } |
1852 | 220 | if second_fraction is not None: | 346 | |
1853 | 221 | milliseconds = second_fraction + '0' * (6 - len(second_fraction)) | 347 | for child in node.getchildren(): |
1854 | 222 | milliseconds = int(milliseconds) | 348 | parser = parsers.get(child.tag) |
1855 | 223 | else: | 349 | if parser: |
1856 | 224 | milliseconds = 0 | 350 | if child.getchildren(): |
1857 | 225 | 351 | parser(result, child) | |
1858 | 226 | if second > 59: | 352 | else: |
1859 | 227 | second = 59 | 353 | text = child.text |
1860 | 228 | milliseconds = 999999 | 354 | if not isinstance(text, unicode): |
1861 | 229 | 355 | text = text.decode("utf-8") | |
1862 | 230 | timestamp = datetime(year, month, day, hour, minute, second, | 356 | stream = StringIO(text) |
1863 | 231 | milliseconds, tzinfo=tz.tzutc()) | 357 | p = parser(stream) |
1864 | 232 | 358 | p.run(result) | |
1865 | 233 | tz_sign = time_parts['tz_sign'] | 359 | else: |
1866 | 234 | tz_hour = time_parts['tz_hour'] | 360 | self.logger.debug( |
1867 | 235 | tz_minute = time_parts['tz_minute'] | 361 | "Unsupported tag <%s> in <hardware>" % child.tag) |
1868 | 236 | if tz_sign in ('-', '+'): | 362 | |
1869 | 237 | delta = timedelta(hours=int(tz_hour), minutes=int(tz_minute)) | 363 | def parseLSBRelease(self, result, node): |
1870 | 238 | if tz_sign == '-': | 364 | """Parse the <lsbrelease> part of a submission.""" |
1741 | 239 | timestamp = timestamp + delta | ||
1742 | 240 | else: | ||
1743 | 241 | timestamp = timestamp - delta | ||
1744 | 242 | |||
1745 | 243 | return timestamp | ||
1746 | 244 | |||
1747 | 245 | def _parseHAL(self, result, node): | ||
1748 | 246 | result.startDevices() | ||
1749 | 247 | for child in node.getchildren(): | ||
1750 | 248 | id = int(child.get('id')) | ||
1751 | 249 | udi = child.get('udi') | ||
1752 | 250 | properties = self._getProperties(child) | ||
1753 | 251 | device = HALDevice(id, udi, properties) | ||
1754 | 252 | result.addDevice(device) | ||
1755 | 253 | |||
1756 | 254 | result.endDevices() | ||
1757 | 255 | |||
1758 | 256 | def _parseInfo(self, result, node): | ||
1759 | 257 | command = node.attrib['command'] | ||
1760 | 258 | if command == "udevadm info --export-db": | ||
1761 | 259 | self._parseUdev(result, node) | ||
1762 | 260 | |||
1763 | 261 | result.addInfo(command, node.text) | ||
1764 | 262 | |||
1765 | 263 | def _parseUdev(self, result, node): | ||
1766 | 264 | result.startDevices() | ||
1767 | 265 | |||
1768 | 266 | stream = StringIO(node.text) | ||
1769 | 267 | udev = UdevParser(stream) | ||
1770 | 268 | udev.run(result) | ||
1771 | 269 | |||
1772 | 270 | result.endDevices() | ||
1773 | 271 | |||
1774 | 272 | def _parseProcessors(self, result, node): | ||
1775 | 273 | result.startProcessors() | ||
1776 | 274 | |||
1777 | 275 | for child in node.getchildren(): | ||
1778 | 276 | id = int(child.get('id')) | ||
1779 | 277 | name = child.get('name') | ||
1780 | 278 | properties = self._getProperties(child) | ||
1781 | 279 | result.addProcessor(id, name, properties) | ||
1782 | 280 | |||
1783 | 281 | result.endProcessors() | ||
1784 | 282 | |||
1785 | 283 | def _parseRoot(self, result, node): | ||
1786 | 284 | parsers = { | ||
1787 | 285 | "summary": self._parseSummary, | ||
1788 | 286 | "hardware": self._parseHardware, | ||
1789 | 287 | "software": self._parseSoftware, | ||
1790 | 288 | "questions": self._parseQuestions, | ||
1791 | 289 | "context": self._parseContext, | ||
1792 | 290 | } | ||
1793 | 291 | |||
1794 | 292 | for child in node.getchildren(): | ||
1795 | 293 | parser = parsers.get(child.tag, self._parseNone) | ||
1796 | 294 | parser(result, child) | ||
1797 | 295 | |||
1798 | 296 | def _parseSummary(self, result, node): | ||
1799 | 297 | parsers = { | ||
1800 | 298 | 'live_cd': self._getValueAttributeAsBoolean, | ||
1801 | 299 | 'system_id': self._getValueAttributeAsString, | ||
1802 | 300 | 'distribution': self._getValueAttributeAsString, | ||
1803 | 301 | 'distroseries': self._getValueAttributeAsString, | ||
1804 | 302 | 'architecture': self._getValueAttributeAsString, | ||
1805 | 303 | 'private': self._getValueAttributeAsBoolean, | ||
1806 | 304 | 'contactable': self._getValueAttributeAsBoolean, | ||
1807 | 305 | 'date_created': self._getValueAttributeAsDateTime, | ||
1808 | 306 | 'client': self._getClient, | ||
1809 | 307 | 'kernel-release': self._getValueAttributeAsString, | ||
1810 | 308 | } | ||
1811 | 309 | |||
1812 | 310 | for child in node.getchildren(): | ||
1813 | 311 | parser = parsers.get(child.tag, self._parseNone) | ||
1814 | 312 | value = parser(child) | ||
1815 | 313 | result.addSummary(child.tag, value) | ||
1816 | 314 | |||
1817 | 315 | def _parseHardware(self, result, node): | ||
1818 | 316 | parsers = { | ||
1819 | 317 | 'hal': self._parseHAL, | ||
1820 | 318 | 'processors': self._parseProcessors, | ||
1821 | 319 | 'udev': self._parseUdev, | ||
1822 | 320 | } | ||
1823 | 321 | |||
1824 | 322 | for child in node.getchildren(): | ||
1825 | 323 | parser = parsers.get(child.tag, self._parseNone) | ||
1826 | 324 | parser(result, child) | ||
1827 | 325 | |||
1828 | 326 | def _parseLSBRelease(self, result, node): | ||
1871 | 327 | properties = self._getProperties(node) | 365 | properties = self._getProperties(node) |
1880 | 328 | result.setDistribution(**properties) | 366 | result.setLSBRelease(properties) |
1881 | 329 | 367 | ||
1882 | 330 | def _parsePackages(self, result, node): | 368 | def parsePackages(self, result, node): |
1883 | 331 | result.startPackages() | 369 | """Parse the <packages> part of a submission.""" |
1884 | 332 | 370 | for child in node.getchildren(): | |
1885 | 333 | for child in node.getchildren(): | 371 | assert child.tag == "package", \ |
1886 | 334 | id = int(child.get('id')) | 372 | "Unexpected tag <%s>, expected <package>" % child.tag |
1887 | 335 | name = child.get('name') | 373 | |
1888 | 374 | package = { | ||
1889 | 375 | "name": child.get("name"), | ||
1890 | 376 | "properties": self._getProperties(child), | ||
1891 | 377 | } | ||
1892 | 378 | result.addPackage(package) | ||
1893 | 379 | |||
1894 | 380 | def parseProcessors(self, result, node): | ||
1895 | 381 | """Parse the <processors> part of a submission.""" | ||
1896 | 382 | processors = [] | ||
1897 | 383 | for child in node.getchildren(): | ||
1898 | 384 | assert child.tag == "processor", \ | ||
1899 | 385 | "Unexpected tag <%s>, expected <processor>" % child.tag | ||
1900 | 386 | |||
1901 | 387 | # Convert lists to space separated strings. | ||
1902 | 336 | properties = self._getProperties(child) | 388 | properties = self._getProperties(child) |
1943 | 337 | 389 | for key, value in properties.iteritems(): | |
1944 | 338 | result.addPackage(id, name, properties) | 390 | if key in ("bogomips", "cache", "count", "speed",): |
1945 | 339 | 391 | properties[key] = int(value) | |
1946 | 340 | result.endPackages() | 392 | elif isinstance(value, list): |
1947 | 341 | 393 | properties[key] = u" ".join(value) | |
1948 | 342 | def _parseXOrg(self, result, node): | 394 | processors.append(properties) |
1949 | 343 | drivers = {} | 395 | |
1950 | 344 | for child in node.getchildren(): | 396 | # Check if /proc/cpuinfo was parsed already. |
1951 | 345 | info = dict(child.attrib) | 397 | if any("platform" in processor for processor in processors): |
1952 | 346 | if 'device' in info: | 398 | result.setProcessor(processors[0]) |
1953 | 347 | info['device'] = int(info['device']) | 399 | else: |
1954 | 348 | 400 | lines = [] | |
1955 | 349 | name = info['name'] | 401 | for processor in processors: |
1956 | 350 | if name in drivers: | 402 | # Convert some keys with underscores to spaces instead. |
1957 | 351 | raise ValueError( | 403 | for key, value in processor.iteritems(): |
1958 | 352 | '<driver name="%s"> appears more than once in <xorg>' | 404 | if "_" in key and key != "vendor_id": |
1959 | 353 | % name) | 405 | key = key.replace("_", " ") |
1960 | 354 | 406 | ||
1961 | 355 | drivers[name] = info | 407 | lines.append(u"%s: %s" % (key, value)) |
1962 | 356 | 408 | ||
1963 | 357 | version = node.get('version') | 409 | lines.append(u"") |
1964 | 358 | result.addXorg(version, drivers) | 410 | |
1965 | 359 | 411 | stream = StringIO(u"\n".join(lines)) | |
1966 | 360 | def _parseSoftware(self, result, node): | 412 | parser = result.parseCpuinfo(stream) |
1967 | 361 | parsers = { | 413 | parser.run(result) |
1968 | 362 | 'lsbrelease': self._parseLSBRelease, | 414 | |
1969 | 363 | 'packages': self._parsePackages, | 415 | def parseQuestions(self, result, node): |
1970 | 364 | 'xorg': self._parseXOrg, | 416 | """Parse the <questions> part of a submission.""" |
1971 | 365 | } | 417 | for child in node.getchildren(): |
1972 | 366 | 418 | assert child.tag == "question", \ | |
1973 | 367 | for child in node.getchildren(): | 419 | "Unexpected tag <%s>, expected <question>" % child.tag |
1974 | 368 | parser = parsers.get(child.tag, self._parseNone) | 420 | question = { |
1975 | 369 | parser(result, child) | 421 | "name": child.get("name"), |
1976 | 370 | 422 | "targets": [], | |
1977 | 371 | def _parseQuestions(self, result, node): | 423 | } |
1978 | 372 | result.startQuestions() | 424 | plugin = child.get("plugin", None) |
1939 | 373 | |||
1940 | 374 | for child in node.getchildren(): | ||
1941 | 375 | question = {'name': child.get('name')} | ||
1942 | 376 | plugin = child.get('plugin', None) | ||
1979 | 377 | if plugin is not None: | 425 | if plugin is not None: |
1982 | 378 | question['plugin'] = plugin | 426 | question["plugin"] = plugin |
1983 | 379 | question['targets'] = targets = [] | 427 | |
1984 | 380 | answer_choices = [] | 428 | answer_choices = [] |
1985 | 381 | |||
1986 | 382 | for sub_node in child.getchildren(): | 429 | for sub_node in child.getchildren(): |
1987 | 383 | sub_tag = sub_node.tag | 430 | sub_tag = sub_node.tag |
1994 | 384 | if sub_tag == 'answer': | 431 | if sub_tag == "answer": |
1995 | 385 | question['answer'] = answer = {} | 432 | question["answer"] = answer = {} |
1996 | 386 | answer['type'] = sub_node.get('type') | 433 | answer["type"] = sub_node.get("type") |
1997 | 387 | if answer['type'] == 'multiple_choice': | 434 | if answer["type"] == "multiple_choice": |
1998 | 388 | question['answer_choices'] = answer_choices | 435 | question["answer_choices"] = answer_choices |
1999 | 389 | unit = sub_node.get('unit', None) | 436 | unit = sub_node.get("unit", None) |
2000 | 390 | if unit is not None: | 437 | if unit is not None: |
2004 | 391 | answer['unit'] = unit | 438 | answer["unit"] = unit |
2005 | 392 | answer['value'] = sub_node.text.strip() | 439 | answer["value"] = sub_node.text.strip() |
2006 | 393 | elif sub_tag == 'answer_choices': | 440 | |
2007 | 441 | elif sub_tag == "answer_choices": | ||
2008 | 394 | for value_node in sub_node.getchildren(): | 442 | for value_node in sub_node.getchildren(): |
2009 | 395 | answer_choices.append( | 443 | answer_choices.append( |
2014 | 396 | self._getValueAttribute(value_node)) | 444 | self._getValueAsType(value_node)) |
2015 | 397 | elif sub_tag == 'target': | 445 | |
2016 | 398 | target = {'id': int(sub_node.get('id'))} | 446 | elif sub_tag == "target": |
2017 | 399 | target['drivers'] = drivers = [] | 447 | # The Relax NG schema ensures that the attribute |
2018 | 448 | # id exists and that it is an integer | ||
2019 | 449 | target = {"id": int(sub_node.get("id"))} | ||
2020 | 450 | target["drivers"] = drivers = [] | ||
2021 | 400 | for driver_node in sub_node.getchildren(): | 451 | for driver_node in sub_node.getchildren(): |
2022 | 401 | drivers.append(driver_node.text.strip()) | 452 | drivers.append(driver_node.text.strip()) |
2025 | 402 | targets.append(target) | 453 | question["targets"].append(target) |
2026 | 403 | elif sub_tag in('comment', 'command'): | 454 | |
2027 | 455 | elif sub_tag in ("comment", "command",): | ||
2028 | 404 | data = sub_node.text | 456 | data = sub_node.text |
2029 | 405 | if data is not None: | 457 | if data is not None: |
2030 | 406 | question[sub_tag] = data.strip() | 458 | question[sub_tag] = data.strip() |
2031 | 407 | 459 | ||
2032 | 460 | else: | ||
2033 | 461 | raise AssertionError( | ||
2034 | 462 | "Unexpected tag <%s> in <question>" % sub_tag) | ||
2035 | 463 | |||
2036 | 408 | result.addQuestion(question) | 464 | result.addQuestion(question) |
2037 | 409 | 465 | ||
2053 | 410 | result.endQuestions() | 466 | def parseSoftware(self, result, node): |
2054 | 411 | 467 | """Parse the <software> section of a submission.""" | |
2055 | 412 | def _parseContext(self, result, node): | 468 | parsers = { |
2056 | 413 | parsers = { | 469 | "lsbrelease": self.parseLSBRelease, |
2057 | 414 | 'info': self._parseInfo, | 470 | "packages": self.parsePackages, |
2058 | 415 | } | 471 | } |
2059 | 416 | 472 | ||
2060 | 417 | for child in node.getchildren(): | 473 | for child in node.getchildren(): |
2061 | 418 | parser = parsers.get(child.tag, self._parseNone) | 474 | parser = parsers.get(child.tag) |
2062 | 419 | parser(result, child) | 475 | if parser: |
2063 | 420 | 476 | parser(result, child) | |
2064 | 421 | def _parseNone(self, result, node): | 477 | else: |
2065 | 422 | pass | 478 | self.logger.debug( |
2066 | 423 | 479 | "Unsupported tag <%s> in <software>" % child.tag) | |
2067 | 424 | def run(self, result): | 480 | |
2068 | 481 | def parseSummary(self, result, node): | ||
2069 | 482 | """Parse the <summary> section of a submission.""" | ||
2070 | 483 | parsers = { | ||
2071 | 484 | "architecture": self._getValueAsString, | ||
2072 | 485 | "client": self._getClient, | ||
2073 | 486 | "contactable": self._getValueAsBoolean, | ||
2074 | 487 | "date_created": self._getValueAsDatetime, | ||
2075 | 488 | "distribution": self._getValueAsString, | ||
2076 | 489 | "distroseries": self._getValueAsString, | ||
2077 | 490 | "kernel-release": self._getValueAsString, | ||
2078 | 491 | "live_cd": self._getValueAsBoolean, | ||
2079 | 492 | "private": self._getValueAsBoolean, | ||
2080 | 493 | "system_id": self._getValueAsString, | ||
2081 | 494 | } | ||
2082 | 495 | |||
2083 | 496 | for child in node.getchildren(): | ||
2084 | 497 | parser = parsers.get(child.tag) | ||
2085 | 498 | if parser: | ||
2086 | 499 | value = parser(child) | ||
2087 | 500 | result.addSummary(child.tag, value) | ||
2088 | 501 | else: | ||
2089 | 502 | self.logger.debug( | ||
2090 | 503 | "Unsupported tag <%s> in <summary>" % child.tag) | ||
2091 | 504 | |||
2092 | 505 | def parseRoot(self, result, node): | ||
2093 | 506 | """Parse the <system> root of a submission.""" | ||
2094 | 507 | parsers = { | ||
2095 | 508 | "context": self.parseContext, | ||
2096 | 509 | "hardware": self.parseHardware, | ||
2097 | 510 | "questions": self.parseQuestions, | ||
2098 | 511 | "software": self.parseSoftware, | ||
2099 | 512 | "summary": self.parseSummary, | ||
2100 | 513 | } | ||
2101 | 514 | |||
2102 | 515 | # Iterate over the root children, "summary" first | ||
2103 | 516 | for child in node.getchildren(): | ||
2104 | 517 | parser = parsers.get(child.tag) | ||
2105 | 518 | if parser: | ||
2106 | 519 | parser(result, child) | ||
2107 | 520 | else: | ||
2108 | 521 | self.logger.debug( | ||
2109 | 522 | "Unsupported tag <%s> in <system>" % child.tag) | ||
2110 | 523 | |||
2111 | 524 | def run(self, test_run_factory, **kwargs): | ||
2112 | 425 | parser = etree.XMLParser() | 525 | parser = etree.XMLParser() |
2113 | 426 | 526 | ||
2120 | 427 | try: | 527 | tree = etree.parse(self.file, parser=parser) |
2115 | 428 | tree = etree.parse(self.stream, parser=parser) | ||
2116 | 429 | except SyntaxError, error: | ||
2117 | 430 | logging.error(error) | ||
2118 | 431 | return | ||
2119 | 432 | |||
2121 | 433 | root = tree.getroot() | 528 | root = tree.getroot() |
2122 | 434 | if root.tag != "system": | 529 | if root.tag != "system": |
2134 | 435 | logging.error("Root node is not '<system>'") | 530 | raise AssertionError( |
2135 | 436 | return | 531 | "Unexpected tag <%s> at root, expected <system>" % root.tag) |
2136 | 437 | 532 | ||
2137 | 438 | self._parseRoot(result, root) | 533 | result = SubmissionResult(test_run_factory, **kwargs) |
2138 | 439 | 534 | self.parseRoot(result, root) | |
2139 | 440 | 535 | ||
2140 | 441 | SubmissionResult = implement_from_dict("SubmissionResult", [ | 536 | return result |
2130 | 442 | "startDevices", "endDevices", "addDevice", "startPackages", | ||
2131 | 443 | "endPackages", "addPackage", "startProcessors", "endProcessors", | ||
2132 | 444 | "addProcessor", "startQuestions", "endQuestions", "addQuestion", | ||
2133 | 445 | "addInfo", "addSummary", "addXorg", "setDistribution"], DeviceResult) | ||
2141 | 446 | 537 | ||
2142 | === renamed file 'checkbox/parsers/udev.py' => 'checkbox/parsers/udevadm.py' | |||
2143 | --- checkbox/parsers/udev.py 2011-09-14 21:16:02 +0000 | |||
2144 | +++ checkbox/parsers/udevadm.py 2011-11-18 18:04:27 +0000 | |||
2145 | @@ -16,38 +16,78 @@ | |||
2146 | 16 | # You should have received a copy of the GNU General Public License | 16 | # You should have received a copy of the GNU General Public License |
2147 | 17 | # along with Checkbox. If not, see <http://www.gnu.org/licenses/>. | 17 | # along with Checkbox. If not, see <http://www.gnu.org/licenses/>. |
2148 | 18 | # | 18 | # |
2149 | 19 | import os | ||
2150 | 20 | import re | 19 | import re |
2151 | 21 | import string | 20 | import string |
2158 | 22 | import posixpath | 21 | |
2159 | 23 | 22 | from checkbox.lib.bit import ( | |
2160 | 24 | from curses.ascii import isprint | 23 | get_bitmask, |
2161 | 25 | 24 | test_bit, | |
2162 | 26 | from checkbox.lib.bit import get_bitmask, test_bit | 25 | ) |
2157 | 27 | from checkbox.lib.dmi import Dmi, DmiNotAvailable | ||
2163 | 28 | from checkbox.lib.input import Input | 26 | from checkbox.lib.input import Input |
2164 | 29 | from checkbox.lib.pci import Pci | 27 | from checkbox.lib.pci import Pci |
2165 | 30 | from checkbox.lib.usb import Usb | 28 | from checkbox.lib.usb import Usb |
2166 | 31 | 29 | ||
2167 | 32 | 30 | ||
2173 | 33 | class UdevDevice(object): | 31 | PCI_RE = re.compile( |
2174 | 34 | __slots__ = ("_environment", "_attributes", "_stack") | 32 | r"^pci:" |
2175 | 35 | 33 | r"v(?P<vendor_id>[%(hex)s]{8})" | |
2176 | 36 | def __init__(self, environment, attributes, stack=[]): | 34 | r"d(?P<product_id>[%(hex)s]{8})" |
2177 | 37 | super(UdevDevice, self).__init__() | 35 | r"sv(?P<subvendor_id>[%(hex)s]{8})" |
2178 | 36 | r"sd(?P<subproduct_id>[%(hex)s]{8})" | ||
2179 | 37 | r"bc(?P<class>[%(hex)s]{2})" | ||
2180 | 38 | r"sc(?P<subclass>[%(hex)s]{2})" | ||
2181 | 39 | r"i(?P<interface>[%(hex)s]{2})" | ||
2182 | 40 | % {"hex": string.hexdigits}) | ||
2183 | 41 | PNP_RE = re.compile( | ||
2184 | 42 | r"^acpi:" | ||
2185 | 43 | r"(?P<vendor_name>[%(upper)s]{3})" | ||
2186 | 44 | r"(?P<product_id>[%(hex)s]{4}):" | ||
2187 | 45 | % {"upper": string.uppercase, "hex": string.hexdigits}) | ||
2188 | 46 | USB_RE = re.compile( | ||
2189 | 47 | r"^usb:" | ||
2190 | 48 | r"v(?P<vendor_id>[%(hex)s]{4})" | ||
2191 | 49 | r"p(?P<product_id>[%(hex)s]{4})" | ||
2192 | 50 | r"d(?P<revision>[%(hex)s]{4})" | ||
2193 | 51 | r"dc(?P<class>[%(hex)s]{2})" | ||
2194 | 52 | r"dsc(?P<subclass>[%(hex)s]{2})" | ||
2195 | 53 | r"dp(?P<protocol>[%(hex)s]{2})" | ||
2196 | 54 | r"ic(?P<interface_class>[%(hex)s]{2})" | ||
2197 | 55 | r"isc(?P<interface_subclass>[%(hex)s]{2})" | ||
2198 | 56 | r"ip(?P<interface_protocol>[%(hex)s]{2})" | ||
2199 | 57 | % {"hex": string.hexdigits}) | ||
2200 | 58 | SCSI_RE = re.compile( | ||
2201 | 59 | r"^scsi:" | ||
2202 | 60 | r"t-0x(?P<type>[%(hex)s]{2})" | ||
2203 | 61 | % {"hex": string.hexdigits}) | ||
2204 | 62 | |||
2205 | 63 | |||
2206 | 64 | class UdevadmDevice: | ||
2207 | 65 | __slots__ = ("_environment", "_bits", "_stack",) | ||
2208 | 66 | |||
2209 | 67 | def __init__(self, environment, bits=None, stack=[]): | ||
2210 | 38 | self._environment = environment | 68 | self._environment = environment |
2212 | 39 | self._attributes = attributes | 69 | self._bits = bits |
2213 | 40 | self._stack = stack | 70 | self._stack = stack |
2214 | 41 | 71 | ||
2215 | 42 | @property | 72 | @property |
2216 | 43 | def bus(self): | 73 | def bus(self): |
2218 | 44 | return self._environment.get("SUBSYSTEM") | 74 | # Change the bus from 'acpi' to 'pnp' for some devices |
2219 | 75 | if PNP_RE.match(self._environment.get("MODALIAS", "")) \ | ||
2220 | 76 | and self.path.endswith(":00"): | ||
2221 | 77 | return "pnp" | ||
2222 | 78 | |||
2223 | 79 | # Change the bus from 'block' to parent | ||
2224 | 80 | if self._environment.get("DEVTYPE") == "disk" and self._stack: | ||
2225 | 81 | return self._stack[-1]._environment.get("SUBSYSTEM") | ||
2226 | 82 | |||
2227 | 83 | bus = self._environment.get("SUBSYSTEM") | ||
2228 | 84 | if bus == "pnp": | ||
2229 | 85 | return None | ||
2230 | 86 | |||
2231 | 87 | return bus | ||
2232 | 45 | 88 | ||
2233 | 46 | @property | 89 | @property |
2234 | 47 | def category(self): | 90 | def category(self): |
2235 | 48 | if "sys_vendor" in self._attributes: | ||
2236 | 49 | return "SYSTEM" | ||
2237 | 50 | |||
2238 | 51 | if "IFINDEX" in self._environment: | 91 | if "IFINDEX" in self._environment: |
2239 | 52 | return "NETWORK" | 92 | return "NETWORK" |
2240 | 53 | 93 | ||
2241 | @@ -69,7 +109,10 @@ | |||
2242 | 69 | return "NETWORK" | 109 | return "NETWORK" |
2243 | 70 | 110 | ||
2244 | 71 | if class_id == Pci.BASE_CLASS_DISPLAY: | 111 | if class_id == Pci.BASE_CLASS_DISPLAY: |
2246 | 72 | return "VIDEO" | 112 | if subclass_id == Pci.CLASS_DISPLAY_VGA: |
2247 | 113 | return "VIDEO" | ||
2248 | 114 | else: | ||
2249 | 115 | return "OTHER" | ||
2250 | 73 | 116 | ||
2251 | 74 | if class_id == Pci.BASE_CLASS_SERIAL \ | 117 | if class_id == Pci.BASE_CLASS_SERIAL \ |
2252 | 75 | and subclass_id == Pci.CLASS_SERIAL_USB: | 118 | and subclass_id == Pci.CLASS_SERIAL_USB: |
2253 | @@ -113,13 +156,9 @@ | |||
2254 | 113 | or subclass_id == Pci.CLASS_BRIDGE_CARDBUS): | 156 | or subclass_id == Pci.CLASS_BRIDGE_CARDBUS): |
2255 | 114 | return "SOCKET" | 157 | return "SOCKET" |
2256 | 115 | 158 | ||
2264 | 116 | if "bInterfaceClass" in self._attributes: | 159 | if "TYPE" in self._environment and "INTERFACE" in self._environment: |
2265 | 117 | interface_class = int( | 160 | interface_class, interface_subclass, interface_protocol = ( |
2266 | 118 | self._attributes["bInterfaceClass"], 16) | 161 | int(i) for i in self._environment["INTERFACE"].split("/")) |
2260 | 119 | interface_subclass = int( | ||
2261 | 120 | self._attributes["bInterfaceSubClass"], 16) | ||
2262 | 121 | interface_protocol = int( | ||
2263 | 122 | self._attributes["bInterfaceProtocol"], 16) | ||
2267 | 123 | 162 | ||
2268 | 124 | if interface_class == Usb.BASE_CLASS_AUDIO: | 163 | if interface_class == Usb.BASE_CLASS_AUDIO: |
2269 | 125 | return "AUDIO" | 164 | return "AUDIO" |
2270 | @@ -143,6 +182,25 @@ | |||
2271 | 143 | else: | 182 | else: |
2272 | 144 | return "WIRELESS" | 183 | return "WIRELESS" |
2273 | 145 | 184 | ||
2274 | 185 | if "KEY" in self._environment: | ||
2275 | 186 | key = self._environment["KEY"].strip("=") | ||
2276 | 187 | bitmask = get_bitmask(key) | ||
2277 | 188 | |||
2278 | 189 | for i in range(Input.KEY_Q, Input.KEY_P + 1): | ||
2279 | 190 | if not test_bit(i, bitmask, self._bits): | ||
2280 | 191 | break | ||
2281 | 192 | else: | ||
2282 | 193 | return "KEYBOARD" | ||
2283 | 194 | |||
2284 | 195 | if test_bit(Input.KEY_CAMERA, bitmask, self._bits): | ||
2285 | 196 | return "CAPTURE" | ||
2286 | 197 | |||
2287 | 198 | if test_bit(Input.BTN_TOUCH, bitmask, self._bits): | ||
2288 | 199 | return "TOUCH" | ||
2289 | 200 | |||
2290 | 201 | if test_bit(Input.BTN_MOUSE, bitmask, self._bits): | ||
2291 | 202 | return "MOUSE" | ||
2292 | 203 | |||
2293 | 146 | if "ID_TYPE" in self._environment: | 204 | if "ID_TYPE" in self._environment: |
2294 | 147 | id_type = self._environment["ID_TYPE"] | 205 | id_type = self._environment["ID_TYPE"] |
2295 | 148 | 206 | ||
2296 | @@ -155,22 +213,6 @@ | |||
2297 | 155 | if id_type == "video": | 213 | if id_type == "video": |
2298 | 156 | return "VIDEO" | 214 | return "VIDEO" |
2299 | 157 | 215 | ||
2300 | 158 | if "KEY" in self._environment: | ||
2301 | 159 | key = self._environment["KEY"].strip("=") | ||
2302 | 160 | bitmask = get_bitmask(key) | ||
2303 | 161 | |||
2304 | 162 | for i in range(Input.KEY_Q, Input.KEY_P + 1): | ||
2305 | 163 | if not test_bit(i, bitmask): | ||
2306 | 164 | break | ||
2307 | 165 | else: | ||
2308 | 166 | return "KEYBOARD" | ||
2309 | 167 | |||
2310 | 168 | if test_bit(Input.BTN_TOUCH, bitmask): | ||
2311 | 169 | return "TOUCH" | ||
2312 | 170 | |||
2313 | 171 | if test_bit(Input.BTN_MOUSE, bitmask): | ||
2314 | 172 | return "MOUSE" | ||
2315 | 173 | |||
2316 | 174 | if "DEVTYPE" in self._environment: | 216 | if "DEVTYPE" in self._environment: |
2317 | 175 | devtype = self._environment["DEVTYPE"] | 217 | devtype = self._environment["DEVTYPE"] |
2318 | 176 | if devtype == "disk": | 218 | if devtype == "disk": |
2319 | @@ -181,8 +223,10 @@ | |||
2320 | 181 | return "FLOPPY" | 223 | return "FLOPPY" |
2321 | 182 | 224 | ||
2322 | 183 | if devtype == "scsi_device": | 225 | if devtype == "scsi_device": |
2325 | 184 | type = int(self._attributes.get("type", "-1")) | 226 | match = SCSI_RE.match(self._environment.get("MODALIAS", "")) |
2326 | 185 | # Check for FLASH drives, see /lib/udev/rules.d/80-udisks.rules | 227 | type = int(match.group("type"), 16) if match else -1 |
2327 | 228 | |||
2328 | 229 | # Check FLASH drives, see /lib/udev/rules.d/80-udisks.rules | ||
2329 | 186 | if type in (0, 7, 14) \ | 230 | if type in (0, 7, 14) \ |
2330 | 187 | and not any(d.driver == "rts_pstor" for d in self._stack): | 231 | and not any(d.driver == "rts_pstor" for d in self._stack): |
2331 | 188 | return "DISK" | 232 | return "DISK" |
2332 | @@ -216,8 +260,11 @@ | |||
2333 | 216 | if "DRIVER" in self._environment: | 260 | if "DRIVER" in self._environment: |
2334 | 217 | return self._environment["DRIVER"] | 261 | return self._environment["DRIVER"] |
2335 | 218 | 262 | ||
2338 | 219 | if "ID_USB_DRIVER" in self._environment: | 263 | # Check parent device for driver |
2339 | 220 | return self._environment["ID_USB_DRIVER"] | 264 | if self._stack: |
2340 | 265 | parent = self._stack[-1] | ||
2341 | 266 | if "DRIVER" in parent._environment: | ||
2342 | 267 | return parent._environment["DRIVER"] | ||
2343 | 221 | 268 | ||
2344 | 222 | return None | 269 | return None |
2345 | 223 | 270 | ||
2346 | @@ -228,48 +275,36 @@ | |||
2347 | 228 | @property | 275 | @property |
2348 | 229 | def product_id(self): | 276 | def product_id(self): |
2349 | 230 | # pci | 277 | # pci |
2365 | 231 | if "PCI_ID" in self._environment: | 278 | match = PCI_RE.match(self._environment.get("MODALIAS", "")) |
2366 | 232 | vendor_id, product_id = self._environment["PCI_ID"].split(":") | 279 | if match: |
2367 | 233 | return int(product_id, 16) | 280 | return int(match.group("product_id"), 16) |
2368 | 234 | 281 | ||
2369 | 235 | # usb interface | 282 | # usb |
2370 | 236 | if "PRODUCT" in self._environment \ | 283 | match = USB_RE.match(self._environment.get("MODALIAS", "")) |
2371 | 237 | and self._environment.get("DEVTYPE") == "usb_interface": | 284 | if match: |
2372 | 238 | vendor_id, product_id, revision \ | 285 | return int(match.group("product_id"), 16) |
2358 | 239 | = self._environment["PRODUCT"].split("/") | ||
2359 | 240 | return int(product_id, 16) | ||
2360 | 241 | |||
2361 | 242 | # usb device and ieee1394 | ||
2362 | 243 | for attribute in "idProduct", "model_id": | ||
2363 | 244 | if attribute in self._attributes: | ||
2364 | 245 | return int(self._attributes[attribute], 16) | ||
2373 | 246 | 286 | ||
2374 | 247 | # pnp | 287 | # pnp |
2380 | 248 | if "id" in self._attributes: | 288 | match = PNP_RE.match(self._environment.get("MODALIAS", "")) |
2381 | 249 | match = re.match(r"^(?P<vendor_name>.*)(?P<product_id>[%s]{4})$" | 289 | if match: |
2382 | 250 | % string.hexdigits, self._attributes["id"]) | 290 | product_id = int(match.group("product_id"), 16) |
2383 | 251 | if match: | 291 | # Ignore interrupt controllers |
2384 | 252 | return int(match.group("product_id"), 16) | 292 | if product_id > 0x0100: |
2385 | 293 | return product_id | ||
2386 | 253 | 294 | ||
2387 | 254 | return None | 295 | return None |
2388 | 255 | 296 | ||
2389 | 256 | @property | 297 | @property |
2390 | 257 | def vendor_id(self): | 298 | def vendor_id(self): |
2391 | 258 | # pci | 299 | # pci |
2406 | 259 | if "PCI_ID" in self._environment: | 300 | match = PCI_RE.match(self._environment.get("MODALIAS", "")) |
2407 | 260 | vendor_id, product_id = self._environment["PCI_ID"].split(":") | 301 | if match: |
2408 | 261 | return int(vendor_id, 16) | 302 | return int(match.group("vendor_id"), 16) |
2409 | 262 | 303 | ||
2410 | 263 | # usb interface | 304 | # usb |
2411 | 264 | if "PRODUCT" in self._environment \ | 305 | match = USB_RE.match(self._environment.get("MODALIAS", "")) |
2412 | 265 | and self._environment.get("DEVTYPE") == "usb_interface": | 306 | if match: |
2413 | 266 | vendor_id, product_id, revision \ | 307 | return int(match.group("vendor_id"), 16) |
2400 | 267 | = self._environment["PRODUCT"].split("/") | ||
2401 | 268 | return int(vendor_id, 16) | ||
2402 | 269 | |||
2403 | 270 | # usb device | ||
2404 | 271 | if "idVendor" in self._attributes: | ||
2405 | 272 | return int(self._attributes["idVendor"], 16) | ||
2414 | 273 | 308 | ||
2415 | 274 | return None | 309 | return None |
2416 | 275 | 310 | ||
2417 | @@ -299,16 +334,19 @@ | |||
2418 | 299 | if element in self._environment: | 334 | if element in self._environment: |
2419 | 300 | return self._environment[element].strip('"') | 335 | return self._environment[element].strip('"') |
2420 | 301 | 336 | ||
2427 | 302 | for attribute in ("description", | 337 | # disk |
2428 | 303 | "model_name_kv", | 338 | if self._environment.get("DEVTYPE") == "scsi_device": |
2429 | 304 | "model", | 339 | for device in reversed(self._stack): |
2430 | 305 | "product_name"): | 340 | if device._environment.get("ID_BUS") == "usb": |
2431 | 306 | if attribute in self._attributes: | 341 | return decode_id(device._environment["ID_MODEL_ENC"]) |
2432 | 307 | return self._attributes[attribute] | 342 | |
2433 | 343 | if self._environment.get("DEVTYPE") == "disk" \ | ||
2434 | 344 | and self._environment.get("ID_BUS") == "ata": | ||
2435 | 345 | return decode_id(self._environment["ID_MODEL_ENC"]) | ||
2436 | 308 | 346 | ||
2437 | 309 | # floppy | 347 | # floppy |
2438 | 310 | if self.driver == "floppy": | 348 | if self.driver == "floppy": |
2440 | 311 | return "Platform Device" | 349 | return u"Platform Device" |
2441 | 312 | 350 | ||
2442 | 313 | return None | 351 | return None |
2443 | 314 | 352 | ||
2444 | @@ -320,168 +358,28 @@ | |||
2445 | 320 | if "POWER_SUPPLY_MANUFACTURER" in self._environment: | 358 | if "POWER_SUPPLY_MANUFACTURER" in self._environment: |
2446 | 321 | return self._environment["POWER_SUPPLY_MANUFACTURER"] | 359 | return self._environment["POWER_SUPPLY_MANUFACTURER"] |
2447 | 322 | 360 | ||
2448 | 323 | if "vendor" in self._attributes: | ||
2449 | 324 | vendor = self._attributes["vendor"] | ||
2450 | 325 | if not re.match(r"^0x[%s]{4}$" % string.hexdigits, vendor): | ||
2451 | 326 | return vendor | ||
2452 | 327 | |||
2453 | 328 | # dmi | ||
2454 | 329 | if "sys_vendor" in self._attributes: | ||
2455 | 330 | return self._attributes["sys_vendor"] | ||
2456 | 331 | |||
2457 | 332 | # pnp | 361 | # pnp |
2608 | 333 | if "id" in self._attributes: | 362 | match = PNP_RE.match(self._environment.get("MODALIAS", "")) |
2609 | 334 | match = re.match(r"^(?P<vendor_name>.*)(?P<product_id>[%s]{4})$" | 363 | if match: |
2610 | 335 | % string.hexdigits, self._attributes["id"]) | 364 | return match.group("vendor_name") |
2611 | 336 | if match: | 365 | |
2612 | 337 | return match.group("vendor_name") | 366 | # disk |
2613 | 338 | 367 | if self._environment.get("DEVTYPE") == "scsi_device": | |
2614 | 339 | return None | 368 | for device in reversed(self._stack): |
2615 | 340 | 369 | if device._environment.get("ID_BUS") == "usb": | |
2616 | 341 | 370 | return decode_id(device._environment["ID_VENDOR_ENC"]) | |
2617 | 342 | class UdevLocalDevice(UdevDevice): | 371 | |
2618 | 343 | 372 | return None | |
2619 | 344 | @property | 373 | |
2620 | 345 | def bus(self): | 374 | |
2621 | 346 | sys_path = posixpath.join( | 375 | class UdevadmParser: |
2622 | 347 | "/sys%s" % self._environment["DEVPATH"], "subsystem") | 376 | """Parser for the udevadm command.""" |
2623 | 348 | if posixpath.islink(sys_path): | 377 | |
2624 | 349 | link = os.readlink(sys_path) | 378 | device_factory = UdevadmDevice |
2625 | 350 | if "/" in link: | 379 | |
2626 | 351 | return posixpath.basename(link) | 380 | def __init__(self, stream, bits=None): |
2477 | 352 | |||
2478 | 353 | return None | ||
2479 | 354 | |||
2480 | 355 | @property | ||
2481 | 356 | def vendor_id(self): | ||
2482 | 357 | vendor_id = super(UdevLocalDevice, self).vendor_id | ||
2483 | 358 | if vendor_id is not None: | ||
2484 | 359 | return vendor_id | ||
2485 | 360 | |||
2486 | 361 | # ieee1394 | ||
2487 | 362 | vendor_id_path = posixpath.join(self.path, "../vendor_id") | ||
2488 | 363 | if posixpath.exists(vendor_id_path): | ||
2489 | 364 | vendor_id = open(vendor_id_path, "r").read().strip() | ||
2490 | 365 | return int(vendor_id, 16) | ||
2491 | 366 | |||
2492 | 367 | return None | ||
2493 | 368 | |||
2494 | 369 | @property | ||
2495 | 370 | def product(self): | ||
2496 | 371 | product = super(UdevLocalDevice, self).product | ||
2497 | 372 | if product is not None: | ||
2498 | 373 | return product | ||
2499 | 374 | |||
2500 | 375 | # sound | ||
2501 | 376 | bus = self.bus | ||
2502 | 377 | if bus == "sound": | ||
2503 | 378 | device = posixpath.basename(self._environment["DEVPATH"]) | ||
2504 | 379 | match = re.match( | ||
2505 | 380 | r"(card|controlC|hwC|midiC)(?P<card>\d+)", device) | ||
2506 | 381 | if match: | ||
2507 | 382 | card = match.group("card") | ||
2508 | 383 | in_card = False | ||
2509 | 384 | file = open("/proc/asound/cards", "r") | ||
2510 | 385 | for line in file.readlines(): | ||
2511 | 386 | line = line.strip() | ||
2512 | 387 | match = re.match(r"(?P<card>\d+) \[", line) | ||
2513 | 388 | if match: | ||
2514 | 389 | in_card = match.group("card") == card | ||
2515 | 390 | |||
2516 | 391 | if in_card: | ||
2517 | 392 | match = re.match(r"""(?P<name>.*) """ | ||
2518 | 393 | """at (?P<address>0x[%s]{8}) """ | ||
2519 | 394 | """irq (?P<irq>\d+)""" % string.hexdigits, line) | ||
2520 | 395 | if match: | ||
2521 | 396 | return match.group("name") | ||
2522 | 397 | |||
2523 | 398 | path = None | ||
2524 | 399 | match = re.match( | ||
2525 | 400 | r"pcmC(?P<card>\d+)D(?P<device>\d+)(?P<type>\w)", device) | ||
2526 | 401 | if match: | ||
2527 | 402 | path = "/proc/asound/card%s/pcm%s%c/info" % match.groups() | ||
2528 | 403 | |||
2529 | 404 | match = re.match( | ||
2530 | 405 | r"(dsp|adsp|midi|amidi|audio|mixer)(?P<card>\d+)?", device) | ||
2531 | 406 | if match: | ||
2532 | 407 | card = match.group("card") or 0 | ||
2533 | 408 | path = "/proc/asound/card%s/pcm0p/info" % card | ||
2534 | 409 | |||
2535 | 410 | if path and posixpath.exists(path): | ||
2536 | 411 | file = open(path, "r") | ||
2537 | 412 | for line in file.readlines(): | ||
2538 | 413 | match = re.match(r"name: (?P<name>.*)", line) | ||
2539 | 414 | if match: | ||
2540 | 415 | return match.group("name") | ||
2541 | 416 | |||
2542 | 417 | return None | ||
2543 | 418 | |||
2544 | 419 | @property | ||
2545 | 420 | def vendor(self): | ||
2546 | 421 | vendor = super(UdevLocalDevice, self).vendor | ||
2547 | 422 | if vendor is not None: | ||
2548 | 423 | return vendor | ||
2549 | 424 | |||
2550 | 425 | # ieee1394 | ||
2551 | 426 | vendor_path = posixpath.join(self.path, "../vendor_oui") | ||
2552 | 427 | if posixpath.exists(vendor_path): | ||
2553 | 428 | return open(vendor_path, "r").read().strip() | ||
2554 | 429 | |||
2555 | 430 | return None | ||
2556 | 431 | |||
2557 | 432 | |||
2558 | 433 | class UdevDmiDevice(UdevDevice): | ||
2559 | 434 | |||
2560 | 435 | def __init__(self, environment, attributes, category): | ||
2561 | 436 | super(UdevDmiDevice, self).__init__(environment, attributes) | ||
2562 | 437 | self._category = category | ||
2563 | 438 | |||
2564 | 439 | @property | ||
2565 | 440 | def category(self): | ||
2566 | 441 | return self._category | ||
2567 | 442 | |||
2568 | 443 | @property | ||
2569 | 444 | def path(self): | ||
2570 | 445 | path = super(UdevDmiDevice, self).path | ||
2571 | 446 | return posixpath.join(path, self._category.lower()) | ||
2572 | 447 | |||
2573 | 448 | @property | ||
2574 | 449 | def product(self): | ||
2575 | 450 | if self._category == "CHASSIS": | ||
2576 | 451 | type_string = self._attributes.get("chassis_type", "0") | ||
2577 | 452 | type_index = int(type_string) | ||
2578 | 453 | return Dmi.chassis_names[type_index] | ||
2579 | 454 | |||
2580 | 455 | for name in "name", "version": | ||
2581 | 456 | attribute = "%s_%s" % (self._category.lower(), name) | ||
2582 | 457 | product = self._attributes.get(attribute) | ||
2583 | 458 | if product and product != "Not Available": | ||
2584 | 459 | return product | ||
2585 | 460 | |||
2586 | 461 | return None | ||
2587 | 462 | |||
2588 | 463 | @DmiNotAvailable | ||
2589 | 464 | def _getVendor(self): | ||
2590 | 465 | attribute = "%s_vendor" % self._category.lower() | ||
2591 | 466 | if attribute in self._attributes: | ||
2592 | 467 | return self._attributes[attribute] | ||
2593 | 468 | |||
2594 | 469 | return None | ||
2595 | 470 | |||
2596 | 471 | @property | ||
2597 | 472 | def vendor(self): | ||
2598 | 473 | return self._getVendor() | ||
2599 | 474 | |||
2600 | 475 | |||
2601 | 476 | class UdevParser(object): | ||
2602 | 477 | """udevadm parser.""" | ||
2603 | 478 | |||
2604 | 479 | device_factory = UdevDevice | ||
2605 | 480 | dmi_device_factory = UdevDmiDevice | ||
2606 | 481 | |||
2607 | 482 | def __init__(self, stream): | ||
2627 | 483 | self.stream = stream | 381 | self.stream = stream |
2629 | 484 | self.stack = [] | 382 | self.bits = bits |
2630 | 485 | 383 | ||
2631 | 486 | def _ignoreDevice(self, device): | 384 | def _ignoreDevice(self, device): |
2632 | 487 | # Ignore devices without bus information | 385 | # Ignore devices without bus information |
2633 | @@ -499,9 +397,8 @@ | |||
2634 | 499 | and device.subvendor_id is None)): | 397 | and device.subvendor_id is None)): |
2635 | 500 | return True | 398 | return True |
2636 | 501 | 399 | ||
2640 | 502 | # Ignore virtual devices except for dmi information | 400 | # Ignore ACPI devices |
2641 | 503 | if device.bus != "dmi" \ | 401 | if device.bus == "acpi": |
2639 | 504 | and "virtual" in device.path.split(posixpath.sep): | ||
2642 | 505 | return True | 402 | return True |
2643 | 506 | 403 | ||
2644 | 507 | return False | 404 | return False |
2645 | @@ -510,96 +407,60 @@ | |||
2646 | 510 | return {} | 407 | return {} |
2647 | 511 | 408 | ||
2648 | 512 | def run(self, result): | 409 | def run(self, result): |
2650 | 513 | line_pattern = re.compile(r"(?P<key>\w):\s*(?P<value>.*)") | 410 | # Some attribute lines have a space character after the |
2651 | 411 | # ':', others don't have it (see udevadm-info.c). | ||
2652 | 412 | line_pattern = re.compile(r"(?P<key>[A-Z]):\s*(?P<value>.*)") | ||
2653 | 514 | multi_pattern = re.compile(r"(?P<key>[^=]+)=(?P<value>.*)") | 413 | multi_pattern = re.compile(r"(?P<key>[^=]+)=(?P<value>.*)") |
2654 | 515 | 414 | ||
2655 | 415 | stack = [] | ||
2656 | 516 | output = self.stream.read() | 416 | output = self.stream.read() |
2658 | 517 | for record in output.split("\n\n"): | 417 | for record in re.split("\n{2,}", output): |
2659 | 418 | record = record.strip() | ||
2660 | 518 | if not record: | 419 | if not record: |
2661 | 519 | continue | 420 | continue |
2662 | 520 | 421 | ||
2663 | 521 | # Determine path and environment | 422 | # Determine path and environment |
2664 | 522 | path = None | 423 | path = None |
2665 | 424 | element = None | ||
2666 | 523 | environment = {} | 425 | environment = {} |
2667 | 524 | for line in record.split("\n"): | 426 | for line in record.split("\n"): |
2669 | 525 | if not line: | 427 | line_match = line_pattern.match(line) |
2670 | 428 | if not line_match: | ||
2671 | 429 | if environment: | ||
2672 | 430 | # Append to last environment element | ||
2673 | 431 | environment[element] += line | ||
2674 | 526 | continue | 432 | continue |
2675 | 527 | 433 | ||
2683 | 528 | match = line_pattern.match(line) | 434 | key = line_match.group("key") |
2684 | 529 | if not match: | 435 | value = line_match.group("value") |
2678 | 530 | raise Exception( | ||
2679 | 531 | "Device line not supported: %s" % line) | ||
2680 | 532 | |||
2681 | 533 | key = match.group("key") | ||
2682 | 534 | value = match.group("value") | ||
2685 | 535 | 436 | ||
2686 | 536 | if key == "P": | 437 | if key == "P": |
2687 | 537 | path = value | 438 | path = value |
2688 | 538 | elif key == "E": | 439 | elif key == "E": |
2691 | 539 | match = multi_pattern.match(value) | 440 | key_match = multi_pattern.match(value) |
2692 | 540 | if not match: | 441 | if not key_match: |
2693 | 541 | raise Exception( | 442 | raise Exception( |
2694 | 542 | "Device property not supported: %s" % value) | 443 | "Device property not supported: %s" % value) |
2696 | 543 | environment[match.group("key")] = match.group("value") | 444 | element = key_match.group("key") |
2697 | 445 | environment[element] = key_match.group("value") | ||
2698 | 544 | 446 | ||
2699 | 545 | # Update stack | 447 | # Update stack |
2702 | 546 | while self.stack: | 448 | while stack: |
2703 | 547 | if self.stack[-1].path + "/" in path: | 449 | if stack[-1].path + "/" in path: |
2704 | 548 | break | 450 | break |
2706 | 549 | self.stack.pop() | 451 | stack.pop() |
2707 | 550 | 452 | ||
2708 | 551 | # Set default DEVPATH | 453 | # Set default DEVPATH |
2709 | 552 | environment.setdefault("DEVPATH", path) | 454 | environment.setdefault("DEVPATH", path) |
2710 | 553 | 455 | ||
2763 | 554 | # Determine attributes | 456 | device = self.device_factory(environment, self.bits, list(stack)) |
2764 | 555 | attributes = self.getAttributes(path) | 457 | if not self._ignoreDevice(device): |
2765 | 556 | 458 | result.addDevice(device) | |
2766 | 557 | if path == "/devices/virtual/dmi/id": | 459 | |
2767 | 558 | device = self.device_factory(environment, attributes) | 460 | stack.append(device) |
2768 | 559 | if not self._ignoreDevice(device): | 461 | |
2769 | 560 | result.addDevice(device) | 462 | |
2770 | 561 | for category in "BIOS", "BOARD", "CHASSIS": | 463 | def decode_id(id): |
2771 | 562 | device = self.dmi_device_factory( | 464 | encoded_id = id.encode("utf-8") |
2772 | 563 | environment, attributes, category) | 465 | decoded_id = encoded_id.decode("string-escape").decode("utf-8") |
2773 | 564 | if not self._ignoreDevice(device): | 466 | return decoded_id.strip() |
2722 | 565 | result.addDevice(device) | ||
2723 | 566 | else: | ||
2724 | 567 | device = self.device_factory(environment, attributes, self.stack) | ||
2725 | 568 | if not self._ignoreDevice(device): | ||
2726 | 569 | result.addDevice(device) | ||
2727 | 570 | |||
2728 | 571 | self.stack.append(device) | ||
2729 | 572 | |||
2730 | 573 | |||
2731 | 574 | class UdevLocalParser(UdevParser): | ||
2732 | 575 | |||
2733 | 576 | device_factory = UdevLocalDevice | ||
2734 | 577 | |||
2735 | 578 | def getAttributes(self, path): | ||
2736 | 579 | attributes = {} | ||
2737 | 580 | sys_path = "/sys%s" % path | ||
2738 | 581 | try: | ||
2739 | 582 | names = os.listdir(sys_path) | ||
2740 | 583 | except OSError: | ||
2741 | 584 | return attributes | ||
2742 | 585 | |||
2743 | 586 | for name in names: | ||
2744 | 587 | name_path = posixpath.join(sys_path, name) | ||
2745 | 588 | if name[0] == "." \ | ||
2746 | 589 | or name in ["dev", "uevent"] \ | ||
2747 | 590 | or posixpath.isdir(name_path) \ | ||
2748 | 591 | or posixpath.islink(name_path): | ||
2749 | 592 | continue | ||
2750 | 593 | |||
2751 | 594 | try: | ||
2752 | 595 | value = open(name_path, "r").read().strip() | ||
2753 | 596 | except IOError: | ||
2754 | 597 | continue | ||
2755 | 598 | |||
2756 | 599 | value = value.split("\n")[0] | ||
2757 | 600 | if [c for c in value if not isprint(c)]: | ||
2758 | 601 | continue | ||
2759 | 602 | |||
2760 | 603 | attributes[name] = value | ||
2761 | 604 | |||
2762 | 605 | return attributes | ||
2774 | 606 | 467 | ||
2775 | === modified file 'checkbox_cli/cli_interface.py' | |||
2776 | --- checkbox_cli/cli_interface.py 2011-06-13 14:22:39 +0000 | |||
2777 | +++ checkbox_cli/cli_interface.py 2011-11-18 18:04:27 +0000 | |||
2778 | @@ -145,7 +145,15 @@ | |||
2779 | 145 | 145 | ||
2780 | 146 | def add_option(self, option, key=None): | 146 | def add_option(self, option, key=None): |
2781 | 147 | if key is None: | 147 | if key is None: |
2783 | 148 | for key in option.lower()+string.lowercase: | 148 | keys = option.lower() + \ |
2784 | 149 | string.ascii_letters + \ | ||
2785 | 150 | string.digits + \ | ||
2786 | 151 | string.punctuation | ||
2787 | 152 | |||
2788 | 153 | keys = keys.replace(' ','') | ||
2789 | 154 | keys = keys.replace('+', '') | ||
2790 | 155 | |||
2791 | 156 | for key in keys: | ||
2792 | 149 | if key not in self.keys: | 157 | if key not in self.keys: |
2793 | 150 | break | 158 | break |
2794 | 151 | self.keys.append(key) | 159 | self.keys.append(key) |
2795 | 152 | 160 | ||
2796 | === modified file 'checkbox_gtk/gtk_interface.py' | |||
2797 | --- checkbox_gtk/gtk_interface.py 2011-09-29 13:12:01 +0000 | |||
2798 | +++ checkbox_gtk/gtk_interface.py 2011-11-18 18:04:27 +0000 | |||
2799 | @@ -102,10 +102,8 @@ | |||
2800 | 102 | image_head.connect("expose-event",self.draw_image_head) | 102 | image_head.connect("expose-event",self.draw_image_head) |
2801 | 103 | 103 | ||
2802 | 104 | # Set wait transient for dialog | 104 | # Set wait transient for dialog |
2807 | 105 | self._wait = self._get_widget("window_wait") | 105 | self._wait = self._get_widget("box_wait") |
2808 | 106 | self._wait.set_transient_for(self._dialog) | 106 | self._wait.hide() |
2805 | 107 | self._wait.realize() | ||
2806 | 108 | self._wait.get_window().set_functions(Gdk.WMFunction.MOVE) | ||
2809 | 109 | 107 | ||
2810 | 110 | # Set shorthand for notebook | 108 | # Set shorthand for notebook |
2811 | 111 | self._notebook = self._get_widget("notebook_main") | 109 | self._notebook = self._get_widget("notebook_main") |
2812 | @@ -539,6 +537,8 @@ | |||
2813 | 539 | test["data"] = self._get_text_view("text_view_comment") | 537 | test["data"] = self._get_text_view("text_view_comment") |
2814 | 540 | test["status"] = self._get_radio_button(BUTTON_TO_STATUS) | 538 | test["status"] = self._get_radio_button(BUTTON_TO_STATUS) |
2815 | 541 | 539 | ||
2816 | 540 | self._set_main_title() | ||
2817 | 541 | |||
2818 | 542 | def show_info(self, text, options=[], default=None): | 542 | def show_info(self, text, options=[], default=None): |
2819 | 543 | message_dialog = Gtk.MessageDialog(parent=self._dialog, | 543 | message_dialog = Gtk.MessageDialog(parent=self._dialog, |
2820 | 544 | type=Gtk.MessageType.INFO, | 544 | type=Gtk.MessageType.INFO, |
2821 | 545 | 545 | ||
2822 | === modified file 'data/whitelists/default.whitelist' | |||
2823 | --- data/whitelists/default.whitelist 2011-09-29 13:12:01 +0000 | |||
2824 | +++ data/whitelists/default.whitelist 2011-11-18 18:04:27 +0000 | |||
2825 | @@ -1,6 +1,7 @@ | |||
2826 | 1 | cdimage | 1 | cdimage |
2827 | 2 | cpuinfo | 2 | cpuinfo |
2828 | 3 | device | 3 | device |
2829 | 4 | dmi | ||
2830 | 4 | dpkg | 5 | dpkg |
2831 | 5 | gconf | 6 | gconf |
2832 | 6 | lsb | 7 | lsb |
2833 | 7 | 8 | ||
2834 | === modified file 'debian/changelog' | |||
2835 | --- debian/changelog 2011-09-29 13:12:01 +0000 | |||
2836 | +++ debian/changelog 2011-11-18 18:04:27 +0000 | |||
2837 | @@ -1,3 +1,62 @@ | |||
2838 | 1 | checkbox (0.13) precise; urgency=low | ||
2839 | 2 | |||
2840 | 3 | New upstream release (LP: #892268): | ||
2841 | 4 | |||
2842 | 5 | [Marc Tardif] | ||
2843 | 6 | * Generate a submission.xml file that contains all device and attachment | ||
2844 | 7 | * Write the report before reporting the validation error. | ||
2845 | 8 | * Changed device.product to dmi.product for the formfactor (LP: #875312) | ||
2846 | 9 | |||
2847 | 10 | [Daniel Manrique] | ||
2848 | 11 | * Use gettext for string (LP: #869267) | ||
2849 | 12 | * Move progress indicator to main checkbox dialog instead of a | ||
2850 | 13 | transient window (LP: #868995) | ||
2851 | 14 | * Ignore malformed dpkg entries in package_resource (LP: #794747) | ||
2852 | 15 | * Reset window title after finishing a manual test (LP: #874690) | ||
2853 | 16 | * Handle "@" in locale names (as in ca@valencia). | ||
2854 | 17 | |||
2855 | 18 | [Jeff Lane] | ||
2856 | 19 | * Went through all the job files and: | ||
2857 | 20 | * Updated descriptions to match Unity UI structure | ||
2858 | 21 | * Added descriptions where necessary | ||
2859 | 22 | * Added further details to some descriptions | ||
2860 | 23 | * Moved some jobs to more appropriate files | ||
2861 | 24 | * Fixed job names in older job files to match new naming scheme | ||
2862 | 25 | (suite/testname) | ||
2863 | 26 | * Added jobs to local.txt to ensure all job files are now parsed | ||
2864 | 27 | (this allows easier addition of existing tests to whitelists) | ||
2865 | 28 | * Changed remaining manual job descriptions to match the new format | ||
2866 | 29 | * Updated CD and DVD write tests to be more clear about when to skip | ||
2867 | 30 | them (LP: #772794) | ||
2868 | 31 | |||
2869 | 32 | [Ara Pulido] | ||
2870 | 33 | * Rewrote all job descriptions to match OEM QA syntax | ||
2871 | 34 | |||
2872 | 35 | [Brendan Donegan] | ||
2873 | 36 | * Fix the code that assigns keys in checkbox-cli so that it never assigns | ||
2874 | 37 | keys which have other uses. (LP: #877467) | ||
2875 | 38 | * Show details of unmet job requirements (LP: #855852) | ||
2876 | 39 | * Ensure that connect_wireless chooses a wireless connection from the list | ||
2877 | 40 | of available connections (LP: #877752) | ||
2878 | 41 | * Have the bluetooth/detect tests require a device with the category | ||
2879 | 42 | BLUETOOTH to run, thus preventing the test from failing on systems with | ||
2880 | 43 | no Bluetooth device (LP: #862322) | ||
2881 | 44 | * Rename attachment jobs to not have a forward slash in their name | ||
2882 | 45 | (LP: #887964) | ||
2883 | 46 | * Guard against trying to write files to logical partitions on USB sticks | ||
2884 | 47 | (which will obviously fail) in usb_test (LP: #887049) | ||
2885 | 48 | * Make the OpenGL test ignore the return value of glxgears and improve | ||
2886 | 49 | the test description (LP: #890725) | ||
2887 | 50 | * Allow input/mouse test to run if a TOUCH device is present | ||
2888 | 51 | (LP: #886129) | ||
2889 | 52 | |||
2890 | 53 | [ Javier Collado ] | ||
2891 | 54 | * Broken job dependencies fixed (LP: #888447) | ||
2892 | 55 | * Regex support when specifying blacklists and whitelists on the | ||
2893 | 56 | commandline (LP: #588647) | ||
2894 | 57 | |||
2895 | 58 | -- Daniel Manrique <daniel.manrique@canonical.com> Thu, 18 Nov 2011 12:46:21 -0500 | ||
2896 | 59 | |||
2897 | 1 | checkbox (0.12.8) oneiric; urgency=low | 60 | checkbox (0.12.8) oneiric; urgency=low |
2898 | 2 | 61 | ||
2899 | 3 | New upstream release (LP: #862579): | 62 | New upstream release (LP: #862579): |
2900 | 4 | 63 | ||
2901 | === added file 'debian/po/ro.po' | |||
2902 | --- debian/po/ro.po 1970-01-01 00:00:00 +0000 | |||
2903 | +++ debian/po/ro.po 2011-11-18 18:04:27 +0000 | |||
2904 | @@ -0,0 +1,118 @@ | |||
2905 | 1 | # Romanian translation for checkbox | ||
2906 | 2 | # Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011 | ||
2907 | 3 | # This file is distributed under the same license as the checkbox package. | ||
2908 | 4 | # FIRST AUTHOR <EMAIL@ADDRESS>, 2011. | ||
2909 | 5 | # | ||
2910 | 6 | msgid "" | ||
2911 | 7 | msgstr "" | ||
2912 | 8 | "Project-Id-Version: checkbox\n" | ||
2913 | 9 | "Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" | ||
2914 | 10 | "POT-Creation-Date: 2011-03-29 15:19+0200\n" | ||
2915 | 11 | "PO-Revision-Date: 2011-10-27 20:38+0000\n" | ||
2916 | 12 | "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" | ||
2917 | 13 | "Language-Team: Romanian <ro@li.org>\n" | ||
2918 | 14 | "MIME-Version: 1.0\n" | ||
2919 | 15 | "Content-Type: text/plain; charset=UTF-8\n" | ||
2920 | 16 | "Content-Transfer-Encoding: 8bit\n" | ||
2921 | 17 | "X-Launchpad-Export-Date: 2011-10-28 05:11+0000\n" | ||
2922 | 18 | "X-Generator: Launchpad (build 14197)\n" | ||
2923 | 19 | |||
2924 | 20 | #. Type: boolean | ||
2925 | 21 | #. Description | ||
2926 | 22 | #: ../checkbox.templates:1001 | ||
2927 | 23 | msgid "Enable bug reporting by default? " | ||
2928 | 24 | msgstr "" | ||
2929 | 25 | |||
2930 | 26 | #. Type: boolean | ||
2931 | 27 | #. Description | ||
2932 | 28 | #: ../checkbox.templates:1001 | ||
2933 | 29 | msgid "" | ||
2934 | 30 | "If this option is set to Yes, then checkbox will ask if the user wants to " | ||
2935 | 31 | "file a bug for failing tests, even if apport is not enabled." | ||
2936 | 32 | msgstr "" | ||
2937 | 33 | |||
2938 | 34 | #. Type: string | ||
2939 | 35 | #. Description | ||
2940 | 36 | #: ../checkbox.templates:2001 | ||
2941 | 37 | msgid "Default package to report bugs against:" | ||
2942 | 38 | msgstr "" | ||
2943 | 39 | |||
2944 | 40 | #. Type: string | ||
2945 | 41 | #. Description | ||
2946 | 42 | #: ../checkbox.templates:2001 | ||
2947 | 43 | msgid "" | ||
2948 | 44 | "When filing a new bug through checkbox, if it does not guess the package, " | ||
2949 | 45 | "the default package that the bug will be file against." | ||
2950 | 46 | msgstr "" | ||
2951 | 47 | |||
2952 | 48 | #. Type: string | ||
2953 | 49 | #. Description | ||
2954 | 50 | #: ../checkbox.templates:3001 | ||
2955 | 51 | msgid "Test suite blacklist:" | ||
2956 | 52 | msgstr "" | ||
2957 | 53 | |||
2958 | 54 | #. Type: string | ||
2959 | 55 | #. Description | ||
2960 | 56 | #: ../checkbox.templates:3001 | ||
2961 | 57 | msgid "List of job files to never run when testing with checkbox." | ||
2962 | 58 | msgstr "" | ||
2963 | 59 | |||
2964 | 60 | #. Type: string | ||
2965 | 61 | #. Description | ||
2966 | 62 | #: ../checkbox.templates:4001 | ||
2967 | 63 | msgid "Test suite whitelist:" | ||
2968 | 64 | msgstr "" | ||
2969 | 65 | |||
2970 | 66 | #. Type: string | ||
2971 | 67 | #. Description | ||
2972 | 68 | #: ../checkbox.templates:4001 | ||
2973 | 69 | msgid "List of jobs to run when testing with checkbox." | ||
2974 | 70 | msgstr "" | ||
2975 | 71 | |||
2976 | 72 | #. Type: string | ||
2977 | 73 | #. Description | ||
2978 | 74 | #: ../checkbox.templates:5001 | ||
2979 | 75 | msgid "Transport URL:" | ||
2980 | 76 | msgstr "" | ||
2981 | 77 | |||
2982 | 78 | #. Type: string | ||
2983 | 79 | #. Description | ||
2984 | 80 | #: ../checkbox.templates:5001 | ||
2985 | 81 | msgid "URL where to send submissions." | ||
2986 | 82 | msgstr "" | ||
2987 | 83 | |||
2988 | 84 | #. Type: string | ||
2989 | 85 | #. Description | ||
2990 | 86 | #: ../checkbox.templates:6001 | ||
2991 | 87 | msgid "Launchpad E-mail:" | ||
2992 | 88 | msgstr "" | ||
2993 | 89 | |||
2994 | 90 | #. Type: string | ||
2995 | 91 | #. Description | ||
2996 | 92 | #: ../checkbox.templates:6001 | ||
2997 | 93 | msgid "E-mail address used to sign in to Launchpad." | ||
2998 | 94 | msgstr "" | ||
2999 | 95 | |||
3000 | 96 | #. Type: string | ||
3001 | 97 | #. Description | ||
3002 | 98 | #: ../checkbox.templates:7001 | ||
3003 | 99 | msgid "HTTP Proxy:" | ||
3004 | 100 | msgstr "" | ||
3005 | 101 | |||
3006 | 102 | #. Type: string | ||
3007 | 103 | #. Description | ||
3008 | 104 | #: ../checkbox.templates:7001 | ||
3009 | 105 | msgid "HTTP proxy to use instead of the one specified in environment." | ||
3010 | 106 | msgstr "" | ||
3011 | 107 | |||
3012 | 108 | #. Type: string | ||
3013 | 109 | #. Description | ||
3014 | 110 | #: ../checkbox.templates:8001 | ||
3015 | 111 | msgid "HTTPS Proxy:" | ||
3016 | 112 | msgstr "" | ||
3017 | 113 | |||
3018 | 114 | #. Type: string | ||
3019 | 115 | #. Description | ||
3020 | 116 | #: ../checkbox.templates:8001 | ||
3021 | 117 | msgid "HTTPS proxy to use instead of the one specified in environment." | ||
3022 | 118 | msgstr "" | ||
3023 | 0 | 119 | ||
3024 | === modified file 'examples/checkbox.ini' | |||
3025 | --- examples/checkbox.ini 2010-03-09 16:58:36 +0000 | |||
3026 | +++ examples/checkbox.ini 2011-11-18 18:04:27 +0000 | |||
3027 | @@ -22,5 +22,5 @@ | |||
3028 | 22 | [checkbox/plugins/jobs_info] | 22 | [checkbox/plugins/jobs_info] |
3029 | 23 | 23 | ||
3030 | 24 | # Blacklist of jobs that are potentially dangerous | 24 | # Blacklist of jobs that are potentially dangerous |
3032 | 25 | blacklist = autotest ltp phoronix qa-regression-testing | 25 | blacklist = autotest/full_suite ltp phoronix qa-regression-testing |
3033 | 26 | clone06.1 ioctl03.1 lchown02.* swapon03.1 | 26 | clone06.1 ioctl03.1 lchown02.* swapon03.1 |
3034 | 27 | 27 | ||
3035 | === modified file 'gtk/checkbox-gtk.ui' | |||
3036 | --- gtk/checkbox-gtk.ui 2011-06-13 14:22:39 +0000 | |||
3037 | +++ gtk/checkbox-gtk.ui 2011-11-18 18:04:27 +0000 | |||
3038 | @@ -374,6 +374,43 @@ | |||
3039 | 374 | <property name="position">2</property> | 374 | <property name="position">2</property> |
3040 | 375 | </packing> | 375 | </packing> |
3041 | 376 | </child> | 376 | </child> |
3042 | 377 | <child> | ||
3043 | 378 | <object class="GtkBox" id="box_wait"> | ||
3044 | 379 | <property name="visible">True</property> | ||
3045 | 380 | <property name="can_focus">False</property> | ||
3046 | 381 | <property name="orientation">vertical</property> | ||
3047 | 382 | <child> | ||
3048 | 383 | <object class="GtkLabel" id="label_wait"> | ||
3049 | 384 | <property name="visible">True</property> | ||
3050 | 385 | <property name="can_focus">False</property> | ||
3051 | 386 | </object> | ||
3052 | 387 | <packing> | ||
3053 | 388 | <property name="expand">False</property> | ||
3054 | 389 | <property name="fill">False</property> | ||
3055 | 390 | <property name="position">0</property> | ||
3056 | 391 | </packing> | ||
3057 | 392 | </child> | ||
3058 | 393 | <child> | ||
3059 | 394 | <object class="GtkProgressBar" id="progressbar_wait"> | ||
3060 | 395 | <property name="visible">True</property> | ||
3061 | 396 | <property name="can_focus">False</property> | ||
3062 | 397 | <property name="pulse_step">0.10000000149</property> | ||
3063 | 398 | </object> | ||
3064 | 399 | <packing> | ||
3065 | 400 | <property name="expand">False</property> | ||
3066 | 401 | <property name="fill">False</property> | ||
3067 | 402 | <property name="position">1</property> | ||
3068 | 403 | </packing> | ||
3069 | 404 | </child> | ||
3070 | 405 | </object> | ||
3071 | 406 | <packing> | ||
3072 | 407 | <property name="expand">False</property> | ||
3073 | 408 | <property name="fill">True</property> | ||
3074 | 409 | <property name="position">3</property> | ||
3075 | 410 | </packing> | ||
3076 | 411 | </child> | ||
3077 | 412 | |||
3078 | 413 | |||
3079 | 377 | <child internal-child="action_area"> | 414 | <child internal-child="action_area"> |
3080 | 378 | <object class="GtkHButtonBox" id="dialog-action_area"> | 415 | <object class="GtkHButtonBox" id="dialog-action_area"> |
3081 | 379 | <property name="visible">True</property> | 416 | <property name="visible">True</property> |
3082 | @@ -452,41 +489,4 @@ | |||
3083 | 452 | <action-widget response="1">button_next</action-widget> | 489 | <action-widget response="1">button_next</action-widget> |
3084 | 453 | </action-widgets> | 490 | </action-widgets> |
3085 | 454 | </object> | 491 | </object> |
3086 | 455 | <object class="GtkWindow" id="window_wait"> | ||
3087 | 456 | <property name="title" translatable="yes"></property> | ||
3088 | 457 | <property name="border_width">6</property> | ||
3089 | 458 | <property name="resizable">False</property> | ||
3090 | 459 | <property name="modal">True</property> | ||
3091 | 460 | <property name="window_position">center-on-parent</property> | ||
3092 | 461 | <property name="type_hint">dialog</property> | ||
3093 | 462 | <property name="skip_taskbar_hint">True</property> | ||
3094 | 463 | <property name="skip_pager_hint">True</property> | ||
3095 | 464 | <child> | ||
3096 | 465 | <object class="GtkVBox" id="vbox_wait"> | ||
3097 | 466 | <property name="visible">True</property> | ||
3098 | 467 | <property name="spacing">12</property> | ||
3099 | 468 | <child> | ||
3100 | 469 | <object class="GtkLabel" id="label_wait"> | ||
3101 | 470 | <property name="visible">True</property> | ||
3102 | 471 | </object> | ||
3103 | 472 | <packing> | ||
3104 | 473 | <property name="expand">False</property> | ||
3105 | 474 | <property name="fill">False</property> | ||
3106 | 475 | <property name="position">0</property> | ||
3107 | 476 | </packing> | ||
3108 | 477 | </child> | ||
3109 | 478 | <child> | ||
3110 | 479 | <object class="GtkProgressBar" id="progressbar_wait"> | ||
3111 | 480 | <property name="visible">True</property> | ||
3112 | 481 | <property name="pulse_step">0.10000000149</property> | ||
3113 | 482 | </object> | ||
3114 | 483 | <packing> | ||
3115 | 484 | <property name="expand">False</property> | ||
3116 | 485 | <property name="fill">False</property> | ||
3117 | 486 | <property name="position">1</property> | ||
3118 | 487 | </packing> | ||
3119 | 488 | </child> | ||
3120 | 489 | </object> | ||
3121 | 490 | </child> | ||
3122 | 491 | </object> | ||
3123 | 492 | </interface> | 492 | </interface> |
3124 | 493 | 493 | ||
3125 | === removed file 'jobs/apport.txt.in' | |||
3126 | --- jobs/apport.txt.in 2011-07-01 11:37:27 +0000 | |||
3127 | +++ jobs/apport.txt.in 1970-01-01 00:00:00 +0000 | |||
3128 | @@ -1,5 +0,0 @@ | |||
3129 | 1 | plugin: shell | ||
3130 | 2 | name: apport-directory | ||
3131 | 3 | requires: package.name == 'apport' | ||
3132 | 4 | command: ! test -d /var/crash || test $(find /var/crash -type f | wc -l) -eq 0 | ||
3133 | 5 | _description: Test that the /var/crash directory doesn't contain anything. | ||
3134 | 6 | 0 | ||
3135 | === modified file 'jobs/audio.txt.in' | |||
3136 | --- jobs/audio.txt.in 2011-09-01 12:23:07 +0000 | |||
3137 | +++ jobs/audio.txt.in 2011-11-18 18:04:27 +0000 | |||
3138 | @@ -1,15 +1,10 @@ | |||
3140 | 1 | plugin: manual | 1 | plugin: shell |
3141 | 2 | name: audio/list_devices | 2 | name: audio/list_devices |
3142 | 3 | requires: | 3 | requires: |
3143 | 4 | device.category == 'AUDIO' | 4 | device.category == 'AUDIO' |
3144 | 5 | package.name == 'alsa-base' | 5 | package.name == 'alsa-base' |
3145 | 6 | command: cat /proc/asound/cards | 6 | command: cat /proc/asound/cards |
3152 | 7 | _description: | 7 | _description: Test to detect audio devices |
3147 | 8 | Detecting your sound device(s): | ||
3148 | 9 | . | ||
3149 | 10 | $output | ||
3150 | 11 | . | ||
3151 | 12 | Is this correct? | ||
3153 | 13 | 8 | ||
3154 | 14 | plugin: manual | 9 | plugin: manual |
3155 | 15 | name: audio/playback_auto | 10 | name: audio/playback_auto |
3156 | @@ -19,9 +14,14 @@ | |||
3157 | 19 | package.name == 'alsa-base' and package.name == 'python-gst0.10' | 14 | package.name == 'alsa-base' and package.name == 'python-gst0.10' |
3158 | 20 | command: gst_pipeline_test -t 2 'audiotestsrc wave=sine freq=512 ! audioconvert ! audioresample ! gconfaudiosink' | 15 | command: gst_pipeline_test -t 2 'audiotestsrc wave=sine freq=512 ! audioconvert ! audioresample ! gconfaudiosink' |
3159 | 21 | _description: | 16 | _description: |
3163 | 22 | Select Test to play a sound on the automatically detected playback device. | 17 | PURPOSE: |
3164 | 23 | . | 18 | This test will check that internal speakers work correctly |
3165 | 24 | Did you hear a sound and was that sound free of any distortion, clicks or other strange noises? | 19 | STEPS: |
3166 | 20 | 1. Make sure that no external speakers or headphones are connected | ||
3167 | 21 | If testing a desktop, external speakers are allowed | ||
3168 | 22 | 2. Click the Test button to play a brief tone on your audio device | ||
3169 | 23 | VERIFICATION: | ||
3170 | 24 | Did you hear a tone? | ||
3171 | 25 | 25 | ||
3172 | 26 | plugin: manual | 26 | plugin: manual |
3173 | 27 | name: audio/playback_headphones | 27 | name: audio/playback_headphones |
3174 | @@ -31,11 +31,13 @@ | |||
3175 | 31 | package.name == 'alsa-base' and package.name == 'python-gst0.10' | 31 | package.name == 'alsa-base' and package.name == 'python-gst0.10' |
3176 | 32 | command: gst_pipeline_test -t 2 'audiotestsrc wave=sine freq=512 ! audioconvert ! audioresample ! gconfaudiosink' | 32 | command: gst_pipeline_test -t 2 'audiotestsrc wave=sine freq=512 ! audioconvert ! audioresample ! gconfaudiosink' |
3177 | 33 | _description: | 33 | _description: |
3183 | 34 | Please connect a pair of headphones to your audio device. | 34 | PURPOSE: |
3184 | 35 | . | 35 | This test will check that headphones connector works correctly |
3185 | 36 | Select Test to play a sound on the automatically detected playback device. | 36 | STEPS: |
3186 | 37 | . | 37 | 1. Connect a pair of headphones to your audio device |
3187 | 38 | Did you hear a sound through the headphones and did the sound play without any distortion, clicks or other strange noises from your headphones? | 38 | 2. Click the Test button to play a sound to your audio device |
3188 | 39 | VERIFICATION: | ||
3189 | 40 | Did you hear a sound through the headphones and did the sound play without any distortion, clicks or other strange noises from your headphones? | ||
3190 | 39 | 41 | ||
3191 | 40 | plugin: manual | 42 | plugin: manual |
3192 | 41 | name: audio/alsa_record_playback_internal | 43 | name: audio/alsa_record_playback_internal |
3193 | @@ -45,9 +47,14 @@ | |||
3194 | 45 | package.name == 'alsa-base' | 47 | package.name == 'alsa-base' |
3195 | 46 | command: alsa_record_playback | 48 | command: alsa_record_playback |
3196 | 47 | _description: | 49 | _description: |
3200 | 48 | Disconnect any external microphones that you have plugged in. Select Test, then speak into your internal microphone. After a few seconds, your speech will be played back to you. | 50 | PURPOSE: |
3201 | 49 | . | 51 | This test will check that recording sound using the onboard microphone works correctly |
3202 | 50 | Did you hear your speech played back? | 52 | STEPS: |
3203 | 53 | 1. Disconnect any external microphones that you have plugged in | ||
3204 | 54 | 2. Click "Test", then speak into your internal microphone | ||
3205 | 55 | 3. After a few seconds, your speech will be played back to you. | ||
3206 | 56 | VERIFICATION: | ||
3207 | 57 | Did you hear your speech played back? | ||
3208 | 51 | 58 | ||
3209 | 52 | plugin: manual | 59 | plugin: manual |
3210 | 53 | name: audio/alsa_record_playback_external | 60 | name: audio/alsa_record_playback_external |
3211 | @@ -57,9 +64,14 @@ | |||
3212 | 57 | package.name == 'alsa-base' | 64 | package.name == 'alsa-base' |
3213 | 58 | command: alsa_record_playback | 65 | command: alsa_record_playback |
3214 | 59 | _description: | 66 | _description: |
3218 | 60 | Connect a microphone to your microphone port. Select Test, then speak into the microphone. After a few seconds, your speech will be played back to you. | 67 | PURPOSE: |
3219 | 61 | . | 68 | This test will check that recording sound using an external microphone works correctly |
3220 | 62 | Did you hear your speech played back? | 69 | STEPS: |
3221 | 70 | 1. Connect a microphone to your microphone port | ||
3222 | 71 | 2. Click "Test", then speak into the external microphone | ||
3223 | 72 | 3. After a few seconds, your speech will be played back to you | ||
3224 | 73 | VERIFICATION: | ||
3225 | 74 | Did you hear your speech played back? | ||
3226 | 63 | 75 | ||
3227 | 64 | plugin: manual | 76 | plugin: manual |
3228 | 65 | name: audio/alsa_record_playback_usb | 77 | name: audio/alsa_record_playback_usb |
3229 | @@ -68,9 +80,17 @@ | |||
3230 | 68 | package.name == 'alsa-base' | 80 | package.name == 'alsa-base' |
3231 | 69 | command: alsa_record_playback | 81 | command: alsa_record_playback |
3232 | 70 | _description: | 82 | _description: |
3236 | 71 | Connect a USB audio device to your system. Then open the volume control application by left-clicking on the speaker icon in the panel and selecting "Sound Preferences". Select the "Input" tab and choose your USB device. Select the "Output" tab and choose your USB device. When you are done, select Test, then speak into the microphone. After a few seconds, your speech will be played back to you. | 83 | PURPOSE: |
3237 | 72 | . | 84 | This test will check that a USB audio device works correctly |
3238 | 73 | Did you hear your speech played back? | 85 | STEPS: |
3239 | 86 | 1. Connect a USB audio device to your system | ||
3240 | 87 | 2. Open the volume control application by left-clicking on the speaker icon in the panel and selecting "Sound Settings" | ||
3241 | 88 | 3. Select the "Input" tab and choose your USB device | ||
3242 | 89 | 4. Select the "Output" tab and choose your USB device | ||
3243 | 90 | 5. Click "Test", then speak into the microphone | ||
3244 | 91 | 6. After a few seconds, your speech will be played back to you | ||
3245 | 92 | VERIFICATION: | ||
3246 | 93 | Did you hear your speech played back through the USB headphones? | ||
3247 | 74 | 94 | ||
3248 | 75 | plugin: shell | 95 | plugin: shell |
3249 | 76 | name: audio/alsa_record_playback_automated | 96 | name: audio/alsa_record_playback_automated |
3250 | 77 | 97 | ||
3251 | === modified file 'jobs/autotest.txt.in' | |||
3252 | --- jobs/autotest.txt.in 2010-03-09 16:58:36 +0000 | |||
3253 | +++ jobs/autotest.txt.in 2011-11-18 18:04:27 +0000 | |||
3254 | @@ -1,6 +1,8 @@ | |||
3256 | 1 | name: autotest | 1 | name: autotest/full_suite |
3257 | 2 | plugin: remote | 2 | plugin: remote |
3258 | 3 | _description: Autotest suite (destructive) | ||
3259 | 4 | user: root | 3 | user: root |
3260 | 5 | timeout: 1200 | 4 | timeout: 1200 |
3261 | 6 | command: autotest_suite | 5 | command: autotest_suite |
3262 | 6 | _description: | ||
3263 | 7 | PURPOSE: | ||
3264 | 8 | This test will attempt to install and run the Autotest Suite. These tests can be destructive, so this test is blacklisted by default. | ||
3265 | 7 | 9 | ||
3266 | === modified file 'jobs/bluetooth.txt.in' | |||
3267 | --- jobs/bluetooth.txt.in 2011-09-01 12:23:07 +0000 | |||
3268 | +++ jobs/bluetooth.txt.in 2011-11-18 18:04:27 +0000 | |||
3269 | @@ -1,88 +1,100 @@ | |||
3270 | 1 | plugin: shell | 1 | plugin: shell |
3271 | 2 | name: bluetooth/detect | 2 | name: bluetooth/detect |
3273 | 3 | requires: package.name == 'bluez' | 3 | requires: |
3274 | 4 | package.name == 'bluez' | ||
3275 | 5 | device.category == 'BLUETOOTH' | ||
3276 | 4 | command: hcitool dev | tail -n+2 | awk '{print $2}' |grep -E "^([0-9a-fA-F]{2}\:){5}[0-9a-fA-F]{2}$" | 6 | command: hcitool dev | tail -n+2 | awk '{print $2}' |grep -E "^([0-9a-fA-F]{2}\:){5}[0-9a-fA-F]{2}$" |
3277 | 5 | _description: | 7 | _description: |
3279 | 6 | Output address of detected Bluetooth device, if any, or exits with error if none is found. | 8 | This test will detect your Bluetooth device and output the device's hardware address. If no device is found, the test will exit with an error. |
3280 | 7 | 9 | ||
3281 | 8 | plugin: shell | 10 | plugin: shell |
3282 | 9 | name: bluetooth/detect-output | 11 | name: bluetooth/detect-output |
3284 | 10 | requires: package.name == 'bluez' | 12 | requires: |
3285 | 13 | package.name == 'bluez' | ||
3286 | 14 | device.category == 'BLUETOOTH' | ||
3287 | 11 | command: hcitool dev | tail -n+2 | awk '{print $2}'; hcitool dev | tail -n+2 | awk '{print $2}' > $CHECKBOX_DATA/bluetooth_address | 15 | command: hcitool dev | tail -n+2 | awk '{print $2}'; hcitool dev | tail -n+2 | awk '{print $2}' > $CHECKBOX_DATA/bluetooth_address |
3288 | 12 | _description: | 16 | _description: |
3290 | 13 | Automated test to store output in checkbox report | 17 | Automated test to store bluetooth device information in checkbox report |
3291 | 14 | 18 | ||
3292 | 15 | plugin: manual | 19 | plugin: manual |
3293 | 16 | name: bluetooth/browse-files | 20 | name: bluetooth/browse-files |
3294 | 17 | depends: bluetooth/detect | 21 | depends: bluetooth/detect |
3295 | 18 | _description: | 22 | _description: |
3308 | 19 | Bluetooth browse files procedure: | 23 | PURPOSE: |
3309 | 20 | 1.- Enable bluetooth on any mobile device (PDA, smartphone, etc.) | 24 | This test will check that bluetooth connection works correctly |
3310 | 21 | 2.- Click on the bluetooth icon in the menu bar | 25 | STEPS: |
3311 | 22 | 3.- Select 'Setup new device' | 26 | 1. Enable bluetooth on any mobile device (PDA, smartphone, etc.) |
3312 | 23 | 3.- Look for the device in the list and select it | 27 | 2. Click on the bluetooth icon in the menu bar |
3313 | 24 | 4.- In the device write the PIN code automatically chosen by the wizard | 28 | 3. Select 'Setup new device' |
3314 | 25 | 5.- The device should pair with the computer | 29 | 4. Look for the device in the list and select it |
3315 | 26 | 6.- Right-click on the bluetooth icon and select browse files | 30 | 5. In the device write the PIN code automatically chosen by the wizard |
3316 | 27 | 7.- Authorize the computer to browse the files in the device if needed | 31 | 6. The device should pair with the computer |
3317 | 28 | 8.- You should be able to browse the files | 32 | 7. Right-click on the bluetooth icon and select browse files |
3318 | 29 | . | 33 | 8. Authorize the computer to browse the files in the device if needed |
3319 | 30 | Did all the steps work? | 34 | 9. You should be able to browse the files |
3320 | 35 | VERIFICATION: | ||
3321 | 36 | Did all the steps work? | ||
3322 | 31 | 37 | ||
3323 | 32 | plugin: manual | 38 | plugin: manual |
3324 | 33 | name: bluetooth/file-transfer | 39 | name: bluetooth/file-transfer |
3325 | 34 | depends: bluetooth/browse-files bluetooth/detect | 40 | depends: bluetooth/browse-files bluetooth/detect |
3326 | 35 | _description: | 41 | _description: |
3335 | 36 | Bluetooth file transfer procedure: | 42 | PURPOSE: |
3336 | 37 | 1.- Make sure that you're able to browse the files in your mobile device | 43 | This test will check that you can transfer information through a bluetooth connection |
3337 | 38 | 2.- Copy a file from the computer to the mobile device | 44 | STEPS: |
3338 | 39 | 3.- Verify that the file was correctly copied | 45 | 1. Make sure that you're able to browse the files in your mobile device |
3339 | 40 | 4.- Copy a file from the mobile device to the computer | 46 | 2. Copy a file from the computer to the mobile device |
3340 | 41 | 5.- Verify that the file was correctly copied | 47 | 3. Copy a file from the mobile device to the computer |
3341 | 42 | . | 48 | VERIFICATION: |
3342 | 43 | Did all the steps work? | 49 | Were all files copied correctly? |
3343 | 44 | 50 | ||
3344 | 45 | plugin: manual | 51 | plugin: manual |
3345 | 46 | name: bluetooth/audio | 52 | name: bluetooth/audio |
3346 | 47 | depends: bluetooth/detect | 53 | depends: bluetooth/detect |
3347 | 48 | requires: package.name == 'alsa-utils' | ||
3348 | 49 | command: arecord -d 5 -D bluetooth -f S16_LE | aplay -D bluetooth -f S16_LE | 54 | command: arecord -d 5 -D bluetooth -f S16_LE | aplay -D bluetooth -f S16_LE |
3349 | 50 | _description: | 55 | _description: |
3360 | 51 | Bluetooth audio procedure: | 56 | PURPOSE: |
3361 | 52 | 1.- Enable the bluetooth headset | 57 | This test will check that you can record and hear audio using a bluetooth audio device |
3362 | 53 | 2.- Click on the bluetooth icon in the menu bar | 58 | STEPS: |
3363 | 54 | 3.- Select 'Setup new device' | 59 | 1. Enable the bluetooth headset |
3364 | 55 | 4.- Look for the device in the list and select it | 60 | 2. Click on the bluetooth icon in the menu bar |
3365 | 56 | 5.- In the device write the PIN code automatically chosen by the wizard | 61 | 3. Select 'Setup new device' |
3366 | 57 | 6.- The device should pair with the computer | 62 | 4. Look for the device in the list and select it |
3367 | 58 | 7.- Select Test to record for five seconds and reproduce in the bluetooth device | 63 | 5. In the device write the PIN code automatically chosen by the wizard |
3368 | 59 | . | 64 | 6. The device should pair with the computer |
3369 | 60 | Did all the steps work? | 65 | 7. Click "Test" to record for five seconds and reproduce in the bluetooth device |
3370 | 66 | VERIFICATION: | ||
3371 | 67 | Did you hear the sound you recorded in the bluetooth | ||
3372 | 61 | 68 | ||
3373 | 62 | plugin: manual | 69 | plugin: manual |
3374 | 63 | name: bluetooth/keyboard | 70 | name: bluetooth/keyboard |
3375 | 64 | command: keyboard_test | 71 | command: keyboard_test |
3376 | 65 | depends: bluetooth/detect | 72 | depends: bluetooth/detect |
3377 | 66 | _description: | 73 | _description: |
3386 | 67 | Bluetooth keyboard procedure: | 74 | PURPOSE: |
3387 | 68 | 1.- Enable the bluetooth keyboard | 75 | This test will check that you can use a bluetooth keyboard |
3388 | 69 | 2.- Click on the bluetooth icon in the menu bar | 76 | STEPS: |
3389 | 70 | 3.- Select 'Setup new device' | 77 | 1. Enable the bluetooth keyboard |
3390 | 71 | 4.- Look for the device in the list and select it | 78 | 2. Click on the bluetooth icon in the menu bar |
3391 | 72 | 5.- Select Test to enter text | 79 | 3. Select 'Setup new device' |
3392 | 73 | . | 80 | 4. Look for the device in the list and select it |
3393 | 74 | Did all the steps work? | 81 | 5. Click "Test" |
3394 | 82 | 6. Enter some text | ||
3395 | 83 | VERIFICATION: | ||
3396 | 84 | Were you able to enter some text with the bluetooth keyboard? | ||
3397 | 75 | 85 | ||
3398 | 76 | plugin: manual | 86 | plugin: manual |
3399 | 77 | name: bluetooth/mouse | 87 | name: bluetooth/mouse |
3400 | 78 | depends: bluetooth/detect | 88 | depends: bluetooth/detect |
3401 | 79 | _description: | 89 | _description: |
3411 | 80 | Bluetooth mouse procedure: | 90 | PURPOSE: |
3412 | 81 | 1.- Enable the bluetooth mouse | 91 | This test will check that you can use a bluetooth mouse |
3413 | 82 | 2.- Click on the bluetooth icon in the menu bar | 92 | STEPS: |
3414 | 83 | 3.- Select 'Setup new device' | 93 | 1. Enable the bluetooth mouse |
3415 | 84 | 4.- Look for the device in the list and select it | 94 | 2. Click on the bluetooth icon in the menu bar |
3416 | 85 | 5.- Move the mouse around the screen | 95 | 3. Select 'Setup new device' |
3417 | 86 | 6.- Perform some single/double/right click operations | 96 | 4. Look for the device in the list and select it |
3418 | 87 | . | 97 | 5. Move the mouse around the screen |
3419 | 88 | Did all the steps work? | 98 | 6. Perform some single/double/right click operations |
3420 | 99 | VERIFICATION: | ||
3421 | 100 | Did the mouse work as expected? | ||
3422 | 89 | 101 | ||
3423 | === modified file 'jobs/camera.txt.in' | |||
3424 | --- jobs/camera.txt.in 2011-07-01 11:37:27 +0000 | |||
3425 | +++ jobs/camera.txt.in 2011-11-18 18:04:27 +0000 | |||
3426 | @@ -4,7 +4,7 @@ | |||
3427 | 4 | package.name == 'xawtv' | 4 | package.name == 'xawtv' |
3428 | 5 | device.category == 'CAPTURE' | 5 | device.category == 'CAPTURE' |
3429 | 6 | command: camera_test -t detect | 6 | command: camera_test -t detect |
3431 | 7 | _description: Automated test case that attempts to detect a camera | 7 | _description: This Automated test attempts to detect a camera. |
3432 | 8 | 8 | ||
3433 | 9 | plugin: manual | 9 | plugin: manual |
3434 | 10 | name: camera/display | 10 | name: camera/display |
3435 | @@ -14,9 +14,12 @@ | |||
3436 | 14 | device.category == 'CAPTURE' | 14 | device.category == 'CAPTURE' |
3437 | 15 | command: camera_test -t display | 15 | command: camera_test -t display |
3438 | 16 | _description: | 16 | _description: |
3442 | 17 | Select Test to display a video capture from the camera | 17 | PURPOSE: |
3443 | 18 | . | 18 | This test will check that the built-in camera works |
3444 | 19 | Did you see the video capture? | 19 | STEPS: |
3445 | 20 | 1. Click on Test to display a video capture from the camera | ||
3446 | 21 | VERIFICATION: | ||
3447 | 22 | Did you see the video capture? | ||
3448 | 20 | 23 | ||
3449 | 21 | plugin: manual | 24 | plugin: manual |
3450 | 22 | name: camera/still | 25 | name: camera/still |
3451 | @@ -28,9 +31,12 @@ | |||
3452 | 28 | device.category == 'CAPTURE' | 31 | device.category == 'CAPTURE' |
3453 | 29 | command: camera_test -t still | 32 | command: camera_test -t still |
3454 | 30 | _description: | 33 | _description: |
3458 | 31 | Select Test to display a still image from the camera | 34 | PURPOSE: |
3459 | 32 | . | 35 | This test will check that the built-in camera works |
3460 | 33 | Did you see the image? | 36 | STEPS: |
3461 | 37 | 1. Click on Test to display a still image from the camera | ||
3462 | 38 | VERIFICATION: | ||
3463 | 39 | Did you see the image? | ||
3464 | 34 | 40 | ||
3465 | 35 | plugin: manual | 41 | plugin: manual |
3466 | 36 | name: camera/video | 42 | name: camera/video |
3467 | @@ -41,8 +47,9 @@ | |||
3468 | 41 | device.category == 'CAPTURE' | 47 | device.category == 'CAPTURE' |
3469 | 42 | command: camera_test -t video | 48 | command: camera_test -t video |
3470 | 43 | _description: | 49 | _description: |
3476 | 44 | Select Test to capture video to a file and open it in totem. | 50 | PURPOSE: |
3477 | 45 | Please make sure that both audio and video is captured. | 51 | This test will check that you can capture video with the built-in camera |
3478 | 46 | . | 52 | STEPS: |
3479 | 47 | Did you see/hear the capture? | 53 | 1. Click on Test to capture video to a file (it will automatically open in Totem) |
3480 | 48 | 54 | VERIFICATION: | |
3481 | 55 | Did you see and hear the capture? | ||
3482 | 49 | 56 | ||
3483 | === modified file 'jobs/codecs.txt.in' | |||
3484 | --- jobs/codecs.txt.in 2011-07-01 11:37:27 +0000 | |||
3485 | +++ jobs/codecs.txt.in 2011-11-18 18:04:27 +0000 | |||
3486 | @@ -1,51 +1,29 @@ | |||
3487 | 1 | plugin: manual | 1 | plugin: manual |
3489 | 2 | name: codecs-ogg-vorbis | 2 | name: codecs/ogg-vorbis |
3490 | 3 | requires: | 3 | requires: |
3491 | 4 | package.name == 'gstreamer0.10-plugins-base' | 4 | package.name == 'gstreamer0.10-plugins-base' |
3492 | 5 | package.name == 'totem' and package.name == 'ubuntu-sounds' | 5 | package.name == 'totem' and package.name == 'ubuntu-sounds' |
3493 | 6 | command: totem /usr/share/sounds/ubuntu/stereo/system-ready.ogg | 6 | command: totem /usr/share/sounds/ubuntu/stereo/system-ready.ogg |
3494 | 7 | _description: | 7 | _description: |
3500 | 8 | Select Test to play an Ogg Vorbis file (.ogg) | 8 | PURPOSE: |
3501 | 9 | . | 9 | This test will verify your system's ability to play Ogg Vorbis audio files. |
3502 | 10 | (Please close Movie Player to proceed.) | 10 | STEPS: |
3503 | 11 | . | 11 | 1. Click Test to play an Ogg Vorbis file (.ogg) |
3504 | 12 | Did the sample play correctly? | 12 | 2. Please close the player to proceed. |
3505 | 13 | VERIFICATION: | ||
3506 | 14 | Did the sample play correctly? | ||
3507 | 13 | 15 | ||
3508 | 14 | plugin: manual | 16 | plugin: manual |
3510 | 15 | name: codecs-wav | 17 | name: codecs/wav |
3511 | 16 | requires: | 18 | requires: |
3512 | 17 | package.name == 'gstreamer0.10-plugins-good' | 19 | package.name == 'gstreamer0.10-plugins-good' |
3513 | 18 | package.name == 'totem' and package.name == 'alsa-utils' | 20 | package.name == 'totem' and package.name == 'alsa-utils' |
3514 | 19 | command: totem /usr/share/sounds/alsa/Noise.wav | 21 | command: totem /usr/share/sounds/alsa/Noise.wav |
3515 | 20 | _description: | 22 | _description: |
3547 | 21 | Select Test to play a Wave Audio format file (.wav) | 23 | PURPOSE: |
3548 | 22 | . | 24 | This test will verify your system's ability to play Wave Audio files. |
3549 | 23 | (Please close Movie Player to proceed.) | 25 | STEPS: |
3550 | 24 | . | 26 | 1. Select Test to play a Wave Audio format file (.wav) |
3551 | 25 | Did the sample play correctly? | 27 | 2. Please close the player to proceed. |
3552 | 26 | 28 | VERIFICATION: | |
3553 | 27 | plugin: manual | 29 | Did the sample play correctly? |
3523 | 28 | name: media-pause-audio | ||
3524 | 29 | requires: | ||
3525 | 30 | package.name == 'totem' | ||
3526 | 31 | package.name == 'gstreamer0.10-plugins-base' | ||
3527 | 32 | command: totem $CHECKBOX_SHARE/data/FrustrationBlues-ColinRoss.oga | ||
3528 | 33 | _description: | ||
3529 | 34 | Select 'Test' to play some audio, and try pausing and resuming playback while the it is playing. | ||
3530 | 35 | . | ||
3531 | 36 | (Please close Movie Player to proceed.) | ||
3532 | 37 | . | ||
3533 | 38 | Did the audio play and pause as expected? | ||
3534 | 39 | |||
3535 | 40 | plugin: manual | ||
3536 | 41 | name: media-pause-video | ||
3537 | 42 | requires: | ||
3538 | 43 | package.name == 'totem' | ||
3539 | 44 | package.name == 'gstreamer0.10-plugins-base' | ||
3540 | 45 | command: totem $CHECKBOX_SHARE/data/UbuntuIsHumanity.ogv | ||
3541 | 46 | _description: | ||
3542 | 47 | Select 'Test' to play a video, and try pausing and resuming playback while the video is playing. | ||
3543 | 48 | . | ||
3544 | 49 | (Please close Movie Player to proceed.) | ||
3545 | 50 | . | ||
3546 | 51 | Did the video play and pause as expected? | ||
3554 | 52 | 30 | ||
3555 | === modified file 'jobs/cpu.txt.in' | |||
3556 | --- jobs/cpu.txt.in 2011-08-10 21:09:56 +0000 | |||
3557 | +++ jobs/cpu.txt.in 2011-11-18 18:04:27 +0000 | |||
3558 | @@ -6,7 +6,7 @@ | |||
3559 | 6 | user: root | 6 | user: root |
3560 | 7 | command: fwts_test -c -l $CHECKBOX_DATA/cpu_scaling_test.log | 7 | command: fwts_test -c -l $CHECKBOX_DATA/cpu_scaling_test.log |
3561 | 8 | _description: | 8 | _description: |
3563 | 9 | Test the CPU scaling capabilities using Colin King's Firmware Test Suite tool. | 9 | Test the CPU scaling capabilities using Firmware Test Suite (fwts cpufreq). |
3564 | 10 | 10 | ||
3565 | 11 | plugin: shell | 11 | plugin: shell |
3566 | 12 | name: cpu/clocktest | 12 | name: cpu/clocktest |
3567 | @@ -28,7 +28,7 @@ | |||
3568 | 28 | requires: int(cpuinfo.count) > 1 and (cpuinfo.platform == 'i386' or cpuinfo.platform == 'x86_64') | 28 | requires: int(cpuinfo.count) > 1 and (cpuinfo.platform == 'i386' or cpuinfo.platform == 'x86_64') |
3569 | 29 | command: cpu_topology | 29 | command: cpu_topology |
3570 | 30 | _description: | 30 | _description: |
3572 | 31 | Checks cpu topology for accuracy | 31 | This test checks cpu topology for accuracy |
3573 | 32 | 32 | ||
3574 | 33 | plugin: shell | 33 | plugin: shell |
3575 | 34 | name: cpu/frequency_governors | 34 | name: cpu/frequency_governors |
3576 | @@ -36,4 +36,4 @@ | |||
3577 | 36 | user: root | 36 | user: root |
3578 | 37 | command: nice -n -20 cpu_scaling_test | 37 | command: nice -n -20 cpu_scaling_test |
3579 | 38 | _description: | 38 | _description: |
3581 | 39 | Checks that CPU frequency governors are obeyed when set. | 39 | This test checks that CPU frequency governors are obeyed when set. |
3582 | 40 | 40 | ||
3583 | === modified file 'jobs/daemons.txt.in' | |||
3584 | --- jobs/daemons.txt.in 2011-07-01 11:37:27 +0000 | |||
3585 | +++ jobs/daemons.txt.in 2011-11-18 18:04:27 +0000 | |||
3586 | @@ -1,59 +1,59 @@ | |||
3587 | 1 | plugin: shell | 1 | plugin: shell |
3589 | 2 | name: atd | 2 | name: daemons/atd |
3590 | 3 | requires: package.name == 'at' | 3 | requires: package.name == 'at' |
3591 | 4 | command: pgrep -f '/usr/sbin/atd' >/dev/null | 4 | command: pgrep -f '/usr/sbin/atd' >/dev/null |
3592 | 5 | _description: Test if the atd daemon is running when the package is installed. | 5 | _description: Test if the atd daemon is running when the package is installed. |
3593 | 6 | 6 | ||
3594 | 7 | plugin: shell | 7 | plugin: shell |
3596 | 8 | name: cron | 8 | name: daemons/cron |
3597 | 9 | requires: package.name == 'cron' | 9 | requires: package.name == 'cron' |
3598 | 10 | command: pgrep -f '/usr/sbin/cron' >/dev/null | 10 | command: pgrep -f '/usr/sbin/cron' >/dev/null |
3599 | 11 | _description: Test if the cron daemon is running when the package is installed. | 11 | _description: Test if the cron daemon is running when the package is installed. |
3600 | 12 | 12 | ||
3601 | 13 | plugin: shell | 13 | plugin: shell |
3603 | 14 | name: cupsd | 14 | name: daemons/cupsd |
3604 | 15 | requires: package.name == 'cupsys' | 15 | requires: package.name == 'cupsys' |
3605 | 16 | command: pgrep -f '/usr/sbin/cupsd' >/dev/null | 16 | command: pgrep -f '/usr/sbin/cupsd' >/dev/null |
3606 | 17 | _description: Test if the cupsd daemon is running when the package is installed. | 17 | _description: Test if the cupsd daemon is running when the package is installed. |
3607 | 18 | 18 | ||
3608 | 19 | plugin: shell | 19 | plugin: shell |
3610 | 20 | name: getty | 20 | name: daemons/getty |
3611 | 21 | requires: package.name == 'util-linux' | 21 | requires: package.name == 'util-linux' |
3612 | 22 | command: pgrep -f '/sbin/getty' >/dev/null | 22 | command: pgrep -f '/sbin/getty' >/dev/null |
3613 | 23 | _description: Test if the getty daemon is running when the package is installed. | 23 | _description: Test if the getty daemon is running when the package is installed. |
3614 | 24 | 24 | ||
3615 | 25 | plugin: shell | 25 | plugin: shell |
3617 | 26 | name: init | 26 | name: daemons/init |
3618 | 27 | requires: package.name == 'upstart' | 27 | requires: package.name == 'upstart' |
3619 | 28 | command: pgrep -f '/sbin/init' >/dev/null | 28 | command: pgrep -f '/sbin/init' >/dev/null |
3620 | 29 | _description: Test if the init daemon is running when the package is installed. | 29 | _description: Test if the init daemon is running when the package is installed. |
3621 | 30 | 30 | ||
3622 | 31 | plugin: shell | 31 | plugin: shell |
3624 | 32 | name: klogd | 32 | name: daemons/klogd |
3625 | 33 | requires: package.name == 'klogd' | 33 | requires: package.name == 'klogd' |
3626 | 34 | command: pgrep -f '/sbin/klogd' >/dev/null | 34 | command: pgrep -f '/sbin/klogd' >/dev/null |
3627 | 35 | _description: Test if the klogd daemon is running when the package is installed. | 35 | _description: Test if the klogd daemon is running when the package is installed. |
3628 | 36 | 36 | ||
3629 | 37 | plugin: shell | 37 | plugin: shell |
3631 | 38 | name: nmbd | 38 | name: daemons/nmbd |
3632 | 39 | requires: package.name == 'samba' | 39 | requires: package.name == 'samba' |
3633 | 40 | command: pgrep -f '/usr/sbin/nmbd' >/dev/null | 40 | command: pgrep -f '/usr/sbin/nmbd' >/dev/null |
3634 | 41 | _description: Test if the nmbd daemon is running when the package is installed. | 41 | _description: Test if the nmbd daemon is running when the package is installed. |
3635 | 42 | 42 | ||
3636 | 43 | plugin: shell | 43 | plugin: shell |
3638 | 44 | name: smbd | 44 | name: daemons/smbd |
3639 | 45 | requires: package.name == 'samba' | 45 | requires: package.name == 'samba' |
3640 | 46 | command: pgrep -f '/usr/sbin/smbd' >/dev/null | 46 | command: pgrep -f '/usr/sbin/smbd' >/dev/null |
3641 | 47 | _description: Test if the smbd daemon is running when the package is installed. | 47 | _description: Test if the smbd daemon is running when the package is installed. |
3642 | 48 | 48 | ||
3643 | 49 | plugin: shell | 49 | plugin: shell |
3645 | 50 | name: syslogd | 50 | name: daemons/syslogd |
3646 | 51 | requires: package.name == 'syslogd' | 51 | requires: package.name == 'syslogd' |
3647 | 52 | command: pgrep -f '/sbin/syslogd' >/dev/null | 52 | command: pgrep -f '/sbin/syslogd' >/dev/null |
3648 | 53 | _description: Test if the syslogd daemon is running when the package is installed. | 53 | _description: Test if the syslogd daemon is running when the package is installed. |
3649 | 54 | 54 | ||
3650 | 55 | plugin: shell | 55 | plugin: shell |
3652 | 56 | name: udevd | 56 | name: daemons/udevd |
3653 | 57 | requires: | 57 | requires: |
3654 | 58 | package.name == 'udevd' | 58 | package.name == 'udevd' |
3655 | 59 | package.name == 'linux' | 59 | package.name == 'linux' |
3656 | @@ -61,7 +61,7 @@ | |||
3657 | 61 | _description: Test if the udevd daemon is running when the package is installed. | 61 | _description: Test if the udevd daemon is running when the package is installed. |
3658 | 62 | 62 | ||
3659 | 63 | plugin: shell | 63 | plugin: shell |
3661 | 64 | name: winbindd | 64 | name: daemons/winbindd |
3662 | 65 | requires: package.name == 'winbind' | 65 | requires: package.name == 'winbind' |
3663 | 66 | command: pgrep -f '/usr/sbin/winbindd' >/dev/null | 66 | command: pgrep -f '/usr/sbin/winbindd' >/dev/null |
3664 | 67 | _description: Test if the winbindd daemon is running when the package is installed. | 67 | _description: Test if the winbindd daemon is running when the package is installed. |
3665 | 68 | 68 | ||
3666 | === modified file 'jobs/disk.txt.in' | |||
3667 | --- jobs/disk.txt.in 2011-09-14 21:16:02 +0000 | |||
3668 | +++ jobs/disk.txt.in 2011-11-18 18:04:27 +0000 | |||
3669 | @@ -14,7 +14,7 @@ | |||
3670 | 14 | requires: device.path == "$path" and package.name == 'linux' | 14 | requires: device.path == "$path" and package.name == 'linux' |
3671 | 15 | user: root | 15 | user: root |
3672 | 16 | command: hdparm -tT /dev/`ls /sys$path/block` | sed 's/:.*= */ = /' | grep -v "^$" | 16 | command: hdparm -tT /dev/`ls /sys$path/block` | sed 's/:.*= */ = /' | grep -v "^$" |
3674 | 17 | description: Benchmark for $path | 17 | description: This test runs hdparm timing tests as a benchmark for $path |
3675 | 18 | EOF | 18 | EOF |
3676 | 19 | 19 | ||
3677 | 20 | plugin: local | 20 | plugin: local |
3678 | @@ -29,7 +29,8 @@ | |||
3679 | 29 | plugin: shell | 29 | plugin: shell |
3680 | 30 | name: disk/smart_`ls /sys$path/block` | 30 | name: disk/smart_`ls /sys$path/block` |
3681 | 31 | requires: device.path == "$path" | 31 | requires: device.path == "$path" |
3683 | 32 | description: SMART test for $product | 32 | description: |
3684 | 33 | This tests the SMART capabilities for $product (Note that this test will not work against removable media (USB, Firewire) and hardware RAID) | ||
3685 | 33 | user: root | 34 | user: root |
3686 | 34 | command: disk_smart -b /dev/`ls /sys$path/block` -s 130 | 35 | command: disk_smart -b /dev/`ls /sys$path/block` -s 130 |
3687 | 35 | EOF | 36 | EOF |
3688 | @@ -44,7 +45,7 @@ | |||
3689 | 44 | plugin: shell | 45 | plugin: shell |
3690 | 45 | name: disk/max_diskspace_used_`ls /sys$path/block` | 46 | name: disk/max_diskspace_used_`ls /sys$path/block` |
3691 | 46 | requires: device.path == "$path" | 47 | requires: device.path == "$path" |
3693 | 47 | description: Max disk space test for $product | 48 | description: Maximum disk space test for $product |
3694 | 48 | user: root | 49 | user: root |
3695 | 49 | command: max_diskspace_used `ls /sys$path/block` | 50 | command: max_diskspace_used `ls /sys$path/block` |
3696 | 50 | EOF | 51 | EOF |
3697 | @@ -61,7 +62,7 @@ | |||
3698 | 61 | requires: | 62 | requires: |
3699 | 62 | device.path == "$path" | 63 | device.path == "$path" |
3700 | 63 | package.name == 'linux' | 64 | package.name == 'linux' |
3702 | 64 | description: Disk performance for $product | 65 | description: Disk performance test for $product |
3703 | 65 | user: root | 66 | user: root |
3704 | 66 | command: disk_read_performance_test `ls /sys$path/block` | 67 | command: disk_read_performance_test `ls /sys$path/block` |
3705 | 67 | EOF | 68 | EOF |
3706 | @@ -79,6 +80,6 @@ | |||
3707 | 79 | requires: | 80 | requires: |
3708 | 80 | device.path == "$path" | 81 | device.path == "$path" |
3709 | 81 | package.name == 'linux' | 82 | package.name == 'linux' |
3711 | 82 | description: I/O stress test for $product | 83 | description: Disk I/O stress test for $product |
3712 | 83 | command: storage_test `ls /sys$path/block` | 84 | command: storage_test `ls /sys$path/block` |
3713 | 84 | EOF | 85 | EOF |
3714 | 85 | 86 | ||
3715 | === removed file 'jobs/evolution.txt.in' | |||
3716 | --- jobs/evolution.txt.in 2011-07-01 11:37:27 +0000 | |||
3717 | +++ jobs/evolution.txt.in 1970-01-01 00:00:00 +0000 | |||
3718 | @@ -1,26 +0,0 @@ | |||
3719 | 1 | plugin: manual | ||
3720 | 2 | name: applications-evolution-pop3 | ||
3721 | 3 | requires: package.name == "evolution" | ||
3722 | 4 | command: evolution | ||
3723 | 5 | _description: | ||
3724 | 6 | Click the "Test" button to launch Evolution, then configure it to connect to a POP3 account. | ||
3725 | 7 | . | ||
3726 | 8 | Were you able to receive and read e-mail correctly? | ||
3727 | 9 | |||
3728 | 10 | plugin: manual | ||
3729 | 11 | name: applications-evolution-imap | ||
3730 | 12 | requires: package.name == "evolution" | ||
3731 | 13 | command: evolution | ||
3732 | 14 | _description: | ||
3733 | 15 | Click the "Test" button to launch Evolution, then configure it to connect to a IMAP account. | ||
3734 | 16 | . | ||
3735 | 17 | Were you able to receive and read e-mail correctly? | ||
3736 | 18 | |||
3737 | 19 | plugin: manual | ||
3738 | 20 | name: applications-evolution-smtp | ||
3739 | 21 | requires: package.name == "evolution" | ||
3740 | 22 | command: evolution | ||
3741 | 23 | _description: | ||
3742 | 24 | Click the "Test" button to launch Evolution, then configure it to connect to a SMTP account. | ||
3743 | 25 | . | ||
3744 | 26 | Were you able to send e-mail without errors? | ||
3745 | 27 | 0 | ||
3746 | === modified file 'jobs/fingerprint.txt.in' | |||
3747 | --- jobs/fingerprint.txt.in 2011-08-10 21:09:56 +0000 | |||
3748 | +++ jobs/fingerprint.txt.in 2011-11-18 18:04:27 +0000 | |||
3749 | @@ -1,27 +1,31 @@ | |||
3750 | 1 | plugin: manual | 1 | plugin: manual |
3751 | 2 | name: fingerprint/login | 2 | name: fingerprint/login |
3752 | 3 | _description: | 3 | _description: |
3764 | 4 | Prerequisites: This test case assumes that there's a testing account from which test cases are run and a personal account that the tester uses to verify the fingerprint reader | 4 | PURPOSE: |
3765 | 5 | . | 5 | This test will verify that a fingerprint reader will work properly for logging into your system. |
3766 | 6 | Fingerprint login verification procedure: | 6 | PREREQUISITES: |
3767 | 7 | 1.- Click on the user switcher applet. | 7 | This test case assumes that there's a testing account from which test cases are run and a personal account that the tester uses to verify the fingerprint reader |
3768 | 8 | 2.- Select your user name. | 8 | STEPS: |
3769 | 9 | 3.- A window should appear that provides the ability to login either typing your password or using fingerprint authentication. | 9 | 1. Click on the user switcher applet. |
3770 | 10 | 4.- Use the fingerprint reader to login. | 10 | 2. Select your user name. |
3771 | 11 | 5.- Click on the user switcher applet. | 11 | 3. A window should appear that provides the ability to login either typing your password or using fingerprint authentication. |
3772 | 12 | 6.- Select the testing account to continue running tests. | 12 | 4. Use the fingerprint reader to login. |
3773 | 13 | . | 13 | 5. Click on the user switcher applet. |
3774 | 14 | Did the authentication procedure work correctly? | 14 | 6. Select the testing account to continue running tests. |
3775 | 15 | VERIFICATION: | ||
3776 | 16 | Did the authentication procedure work correctly? | ||
3777 | 15 | 17 | ||
3778 | 16 | plugin: manual | 18 | plugin: manual |
3779 | 17 | name: fingerprint/unlock | 19 | name: fingerprint/unlock |
3780 | 18 | _description: | 20 | _description: |
3790 | 19 | Fingerprint unlock verification procedure: | 21 | PURPOSE: |
3791 | 20 | 1.- Click on the user switcher applet. | 22 | This test will verify that a fingerprint reader can be used to unlock a locked system. |
3792 | 21 | 2.- Select 'Lock screen'. | 23 | STEPS: |
3793 | 22 | 3.- Press any key or move the mouse. | 24 | 1. Click on the user switcher applet. |
3794 | 23 | 4.- A window should appear that provides the ability to unlock either typing your password or using fingerprint authentication. | 25 | 2. Select 'Lock screen'. |
3795 | 24 | 5.- Use the fingerprint reader to unlock. | 26 | 3. Press any key or move the mouse. |
3796 | 25 | 6.- Your screen should be unlocked. | 27 | 4. A window should appear that provides the ability to unlock either typing your password or using fingerprint authentication. |
3797 | 26 | . | 28 | 5. Use the fingerprint reader to unlock. |
3798 | 27 | Did the authentication procedure work correctly? | 29 | 6. Your screen should be unlocked. |
3799 | 30 | VERIFICATION: | ||
3800 | 31 | Did the authentication procedure work correctly? | ||
3801 | 28 | 32 | ||
3802 | === modified file 'jobs/firewire.txt.in' | |||
3803 | --- jobs/firewire.txt.in 2011-08-10 21:09:56 +0000 | |||
3804 | +++ jobs/firewire.txt.in 2011-11-18 18:04:27 +0000 | |||
3805 | @@ -1,11 +1,12 @@ | |||
3806 | 1 | plugin: manual | 1 | plugin: manual |
3807 | 2 | name: firewire/hdd | 2 | name: firewire/hdd |
3808 | 3 | _description: | 3 | _description: |
3817 | 4 | Firewire HDD verification procedure: | 4 | PURPOSE: |
3818 | 5 | 1.- Plug a Firewire HDD into the computer. | 5 | This test will check that the firewire port works |
3819 | 6 | 2.- A window should be opened asking which action should be performed (open folder, photo manager, etc). | 6 | STEPS: |
3820 | 7 | 3.- Copy some files from your internal HDD to the firewire HDD. | 7 | 1. Plug a Firewire HDD into the computer |
3821 | 8 | 4.- Copy some files from the firewire HDD to your internal HDD. | 8 | 2. Either a window asking which action should be performed (open folder, photo manager, etc) or a file browser will open. |
3822 | 9 | . | 9 | 3. Copy some files from your internal HDD to the firewire HDD |
3823 | 10 | Do the copy operations work as expected? | 10 | 4. Copy some files from the firewire HDD to your internal HDD |
3824 | 11 | 11 | VERIFICATION: | |
3825 | 12 | Do the copy operations work as expected? | ||
3826 | 12 | 13 | ||
3827 | === removed file 'jobs/gcalctool.txt.in' | |||
3828 | --- jobs/gcalctool.txt.in 2011-07-01 11:37:27 +0000 | |||
3829 | +++ jobs/gcalctool.txt.in 1970-01-01 00:00:00 +0000 | |||
3830 | @@ -1,52 +0,0 @@ | |||
3831 | 1 | plugin: manual | ||
3832 | 2 | name: applications-gcalctool | ||
3833 | 3 | requires: package.name == "gcalctool" | ||
3834 | 4 | command: gcalctool | ||
3835 | 5 | _description: | ||
3836 | 6 | Click the "Test" button to open the calculator. | ||
3837 | 7 | . | ||
3838 | 8 | Did it launch correctly? | ||
3839 | 9 | |||
3840 | 10 | plugin: manual | ||
3841 | 11 | name: applications-gcalctool-functions | ||
3842 | 12 | depends: applications-gcalctool | ||
3843 | 13 | requires: package.name == "gcalctool" | ||
3844 | 14 | command: gcalctool | ||
3845 | 15 | _description: | ||
3846 | 16 | Click the "Test" button to open the calculator and perform: | ||
3847 | 17 | . | ||
3848 | 18 | 1. Simple math functions (+,-,/,*) | ||
3849 | 19 | 2. Nested math functions ((,)) | ||
3850 | 20 | 3. Fractional math | ||
3851 | 21 | 4. Decimal math | ||
3852 | 22 | . | ||
3853 | 23 | Did the functions perform as expected? | ||
3854 | 24 | |||
3855 | 25 | plugin: manual | ||
3856 | 26 | name: applications-gcalctool-memory | ||
3857 | 27 | depends: applications-gcalctool | ||
3858 | 28 | requires: package.name == "gcalctool" | ||
3859 | 29 | command: gcalctool | ||
3860 | 30 | _description: | ||
3861 | 31 | Click the "Test" button to open the calculator and perform: | ||
3862 | 32 | . | ||
3863 | 33 | 1. Memory set | ||
3864 | 34 | 2. Memory reset | ||
3865 | 35 | 3. Memory last clear | ||
3866 | 36 | 4. Memory clear | ||
3867 | 37 | . | ||
3868 | 38 | Did the functions perform as expected? | ||
3869 | 39 | |||
3870 | 40 | plugin: manual | ||
3871 | 41 | name: applications-gcalctool-clipboard | ||
3872 | 42 | depends: applications-gcalctool | ||
3873 | 43 | requires: package.name == "gcalctool" | ||
3874 | 44 | command: gcalctool | ||
3875 | 45 | _description: | ||
3876 | 46 | Click the "Test" button to open the calculator and perform: | ||
3877 | 47 | . | ||
3878 | 48 | 1. Cut | ||
3879 | 49 | 2. Copy | ||
3880 | 50 | 3. Paste | ||
3881 | 51 | . | ||
3882 | 52 | Did the functions perform as expected? | ||
3883 | 53 | 0 | ||
3884 | === removed file 'jobs/gedit.txt.in' | |||
3885 | --- jobs/gedit.txt.in 2011-07-01 11:37:27 +0000 | |||
3886 | +++ jobs/gedit.txt.in 1970-01-01 00:00:00 +0000 | |||
3887 | @@ -1,22 +0,0 @@ | |||
3888 | 1 | plugin: manual | ||
3889 | 2 | name: applications-gedit | ||
3890 | 3 | requires: package.name == "gedit" | ||
3891 | 4 | command: gedit | ||
3892 | 5 | _description: | ||
3893 | 6 | Click the "Test" button to open gedit. | ||
3894 | 7 | . | ||
3895 | 8 | Enter some text and save the file (make a note of the file name you use), then close gedit. | ||
3896 | 9 | . | ||
3897 | 10 | Did this perform as expected? | ||
3898 | 11 | |||
3899 | 12 | plugin: manual | ||
3900 | 13 | name: applications-gedit-read | ||
3901 | 14 | depends: applications-gedit | ||
3902 | 15 | requires: package.name == "gedit" | ||
3903 | 16 | command: gedit | ||
3904 | 17 | _description: | ||
3905 | 18 | Click the "Test" button to open gedit, and re-open the file you created previously. | ||
3906 | 19 | . | ||
3907 | 20 | Edit then save the file, then close gedit. | ||
3908 | 21 | . | ||
3909 | 22 | Did this perform as expected? | ||
3910 | 23 | 0 | ||
3911 | === removed file 'jobs/gnome-terminal.txt.in' | |||
3912 | --- jobs/gnome-terminal.txt.in 2011-07-01 11:37:27 +0000 | |||
3913 | +++ jobs/gnome-terminal.txt.in 1970-01-01 00:00:00 +0000 | |||
3914 | @@ -1,12 +0,0 @@ | |||
3915 | 1 | plugin: manual | ||
3916 | 2 | name: applications-gnome-terminal | ||
3917 | 3 | requires: package.name == "gnome-terminal" | ||
3918 | 4 | command: gnome-terminal | ||
3919 | 5 | _description: | ||
3920 | 6 | Click the "Test" button to open Terminal. | ||
3921 | 7 | . | ||
3922 | 8 | Type 'ls' and press enter. You should see a list of files and folder in your home directory. | ||
3923 | 9 | . | ||
3924 | 10 | Close the terminal window. | ||
3925 | 11 | . | ||
3926 | 12 | Did this perform as expected? | ||
3927 | 13 | 0 | ||
3928 | === modified file 'jobs/graphics.txt.in' | |||
3929 | --- jobs/graphics.txt.in 2011-08-10 21:09:56 +0000 | |||
3930 | +++ jobs/graphics.txt.in 2011-11-18 18:04:27 +0000 | |||
3931 | @@ -1,12 +1,8 @@ | |||
3933 | 1 | plugin: manual | 1 | plugin: shell |
3934 | 2 | name: graphics/xorg-version | 2 | name: graphics/xorg-version |
3935 | 3 | requires: package.name == "x11-utils" | 3 | requires: package.name == "x11-utils" |
3936 | 4 | command: xdpyinfo | grep "^X.Org version" | cut -d ':' -f 2 | tr -d ' ' | 4 | command: xdpyinfo | grep "^X.Org version" | cut -d ':' -f 2 | tr -d ' ' |
3942 | 5 | _description: | 5 | _description: Test to output the Xorg version |
3938 | 6 | 2d graphics appears to be working, your running X.Org version is: | ||
3939 | 7 | $output | ||
3940 | 8 | . | ||
3941 | 9 | Is this correct? | ||
3943 | 10 | 6 | ||
3944 | 11 | plugin: shell | 7 | plugin: shell |
3945 | 12 | name: graphics/xorg-version-output | 8 | name: graphics/xorg-version-output |
3946 | @@ -19,41 +15,40 @@ | |||
3947 | 19 | name: graphics/gtkperf | 15 | name: graphics/gtkperf |
3948 | 20 | depends: graphics/xorg-version-output | 16 | depends: graphics/xorg-version-output |
3949 | 21 | requires: package.name == 'gtkperf' | 17 | requires: package.name == 'gtkperf' |
3951 | 22 | command: gtkperf -a | 18 | command: gtkperf -a | grep "Total time:" |
3952 | 23 | _description: | 19 | _description: |
3953 | 24 | Run gtkperf to make sure that GTK based test cases work | 20 | Run gtkperf to make sure that GTK based test cases work |
3954 | 25 | . | ||
3955 | 26 | In the future add the returned time as a benchmark result to the checkbox report | ||
3956 | 27 | 21 | ||
3957 | 28 | plugin: manual | 22 | plugin: manual |
3958 | 29 | name: graphics/resolution-change | 23 | name: graphics/resolution-change |
3959 | 30 | depends: graphics/xorg-version-output | 24 | depends: graphics/xorg-version-output |
3960 | 31 | _description: | 25 | _description: |
3971 | 32 | Display resolution change procedure: | 26 | PURPOSE: |
3972 | 33 | 1.- Open System->Preferences->Monitors | 27 | This test will verify that the GUI is usable after manually changing resolution |
3973 | 34 | 2.- Select a new resolution from the dropdown list | 28 | STEPS: |
3974 | 35 | 3.- Click on Apply | 29 | 1. Open the Displays application |
3975 | 36 | 4.- The resolution should change | 30 | 2. Select a new resolution from the dropdown list |
3976 | 37 | 5.- Select the original resolution from the dropdown list | 31 | 3. Click on Apply |
3977 | 38 | 6.- Click on Apply | 32 | 4. Select the original resolution from the dropdown list |
3978 | 39 | 7.- The resolution should change again | 33 | 5. Click on Apply |
3979 | 40 | . | 34 | VERIFICATION: |
3980 | 41 | Did the resolution change as expected? | 35 | Did the resolution change as expected? |
3981 | 42 | 36 | ||
3982 | 43 | plugin: manual | 37 | plugin: manual |
3983 | 44 | name: graphics/rotation | 38 | name: graphics/rotation |
3984 | 45 | depends: graphics/xorg-version-output | 39 | depends: graphics/xorg-version-output |
3985 | 46 | _description: | 40 | _description: |
3996 | 47 | Display rotation verification procedure: | 41 | PURPOSE: |
3997 | 48 | 1.- Open System->Preferences->Monitors | 42 | This test will test display rotation |
3998 | 49 | 2.- Select a new rotation value from the dropdown list | 43 | STEPS: |
3999 | 50 | 3.- Click on Apply | 44 | 1. Open the Displays application |
4000 | 51 | 4.- The display should be rotated according to the new configuration value | 45 | 2. Select a new rotation value from the dropdown list |
4001 | 52 | 5.- Click on Restore Previous Configuration | 46 | 3. Click on Apply |
4002 | 53 | 6.- The display configuration change should be reverted | 47 | 4. Click on Restore Previous Configuration |
4003 | 54 | 7.- Repeat 2-6 for different rotation values | 48 | 5. Click on Apply |
4004 | 55 | . | 49 | 6. Repeat 2-5 for different rotation values |
4005 | 56 | Did the display rotation change as expected? | 50 | VERIFICATION: |
4006 | 51 | Did the display rotation change as expected? | ||
4007 | 57 | 52 | ||
4008 | 58 | plugin: shell | 53 | plugin: shell |
4009 | 59 | name: graphics/xorg-process | 54 | name: graphics/xorg-process |
4010 | @@ -72,7 +67,7 @@ | |||
4011 | 72 | requires: package.name == 'xorg' and device.driver == 'i915' | 67 | requires: package.name == 'xorg' and device.driver == 'i915' |
4012 | 73 | user: root | 68 | user: root |
4013 | 74 | command: xorg_memory_test xeyes | 69 | command: xorg_memory_test xeyes |
4015 | 75 | _description: Test that X does not leak memory when running programs. | 70 | _description: Test that X does not leak memory when running programs on systems with intel based graphics. |
4016 | 76 | 71 | ||
4017 | 77 | plugin: manual | 72 | plugin: manual |
4018 | 78 | name: graphics/resolution | 73 | name: graphics/resolution |
4019 | @@ -80,11 +75,14 @@ | |||
4020 | 80 | device.category == 'VIDEO' | 75 | device.category == 'VIDEO' |
4021 | 81 | command: resolution_test | 76 | command: resolution_test |
4022 | 82 | _description: | 77 | _description: |
4028 | 83 | This display is using the following resolution: | 78 | PURPOSE: |
4029 | 84 | . | 79 | This test will verify the default display resolution |
4030 | 85 | $output | 80 | STEPS: |
4031 | 86 | . | 81 | 1. This display is using the following resolution: |
4032 | 87 | Is this acceptable for your display? | 82 | INFO: |
4033 | 83 | $output | ||
4034 | 84 | VERIFICATION: | ||
4035 | 85 | Is this acceptable for your display? | ||
4036 | 88 | 86 | ||
4037 | 89 | plugin: shell | 87 | plugin: shell |
4038 | 90 | name: graphics/minimum_resolution | 88 | name: graphics/minimum_resolution |
4039 | @@ -102,30 +100,39 @@ | |||
4040 | 102 | requires: package.name == 'xorg' and package.name == 'python-gst0.10' | 100 | requires: package.name == 'xorg' and package.name == 'python-gst0.10' |
4041 | 103 | command: gst_pipeline_test -t 2 'videotestsrc ! ffmpegcolorspace ! gconfvideosink' | 101 | command: gst_pipeline_test -t 2 'videotestsrc ! ffmpegcolorspace ! gconfvideosink' |
4042 | 104 | _description: | 102 | _description: |
4046 | 105 | Select Test to display a video test. | 103 | PURPOSE: |
4047 | 106 | . | 104 | This test will test the default display |
4048 | 107 | Do you see color bars and static? | 105 | STEPS: |
4049 | 106 | 1. Click "Test" to display a video test. | ||
4050 | 107 | VERIFICATION: | ||
4051 | 108 | Do you see color bars and static? | ||
4052 | 108 | 109 | ||
4053 | 109 | plugin: manual | 110 | plugin: manual |
4054 | 110 | name: graphics/xrandr_detect_modes | 111 | name: graphics/xrandr_detect_modes |
4055 | 111 | requires: package.name == 'xorg' | 112 | requires: package.name == 'xorg' |
4056 | 112 | command: xrandr | 113 | command: xrandr |
4057 | 113 | _description: | 114 | _description: |
4063 | 114 | The following screens and video modes have been detected on your system: | 115 | PURPOSE: |
4064 | 115 | . | 116 | This test checks the detected video modes |
4065 | 116 | $output | 117 | STEPS: |
4066 | 117 | . | 118 | 1. The following screens and video modes have been detected on your system |
4067 | 118 | Is this correct? | 119 | INFO: |
4068 | 120 | $output | ||
4069 | 121 | VERIFICATION: | ||
4070 | 122 | Are those correct? | ||
4071 | 119 | 123 | ||
4072 | 120 | plugin: manual | 124 | plugin: manual |
4073 | 121 | name: graphics/cycle_resolution | 125 | name: graphics/cycle_resolution |
4074 | 122 | requires: package.name == 'xorg' | 126 | requires: package.name == 'xorg' |
4076 | 123 | depends: xrandr_detect_modes | 127 | depends: graphics/xrandr_detect_modes |
4077 | 124 | command: xrandr_cycle | 128 | command: xrandr_cycle |
4078 | 125 | _description: | 129 | _description: |
4082 | 126 | Select Test to cycle through the detected video modes for your system. | 130 | PURPOSE: |
4083 | 127 | . | 131 | This test cycles through the detected video modes |
4084 | 128 | Did the screen appear to be working for each mode? | 132 | STEPS: |
4085 | 133 | 1. Click "Test" to start cycling through the video modes | ||
4086 | 134 | VERIFICATION: | ||
4087 | 135 | Did the screen appear to be working for each mode? | ||
4088 | 129 | 136 | ||
4089 | 130 | plugin: shell | 137 | plugin: shell |
4090 | 131 | name: graphics/compiz_check | 138 | name: graphics/compiz_check |
4091 | @@ -136,8 +143,13 @@ | |||
4092 | 136 | plugin: manual | 143 | plugin: manual |
4093 | 137 | name: graphics/glxgears | 144 | name: graphics/glxgears |
4094 | 138 | requires: package.name == 'mesa-utils' | 145 | requires: package.name == 'mesa-utils' |
4096 | 139 | command: glxgears | 146 | command: glxgears; true |
4097 | 140 | _description: | 147 | _description: |
4101 | 141 | Select Test to execute glxgears to ensure that minimal 3d graphics support is in place. | 148 | PURPOSE: |
4102 | 142 | . | 149 | This test tests the basic 3D capabilities of your video card |
4103 | 143 | Did the 3d animation appear? | 150 | STEPS: |
4104 | 151 | 1. Click "Test" to execute an OpenGL demo. Press ESC at any time to close. | ||
4105 | 152 | 2. Verify that the animation is not jerky or slow. | ||
4106 | 153 | VERIFICATION: | ||
4107 | 154 | 1. Did the 3d animation appear? | ||
4108 | 155 | 2. Was the animation free from slowness/jerkiness? | ||
4109 | 144 | 156 | ||
4110 | === modified file 'jobs/hibernate.txt.in' | |||
4111 | --- jobs/hibernate.txt.in 2011-09-01 12:23:07 +0000 | |||
4112 | +++ jobs/hibernate.txt.in 2011-11-18 18:04:27 +0000 | |||
4113 | @@ -5,10 +5,12 @@ | |||
4114 | 5 | user: root | 5 | user: root |
4115 | 6 | command: sleep_test -s disk -w 120 --debug | 6 | command: sleep_test -s disk -w 120 --debug |
4116 | 7 | _description: | 7 | _description: |
4124 | 8 | This will check to make sure your system can successfully hibernate (if supported). | 8 | PURPOSE: |
4125 | 9 | . | 9 | This test will check to make sure your system can successfully hibernate (if supported) |
4126 | 10 | Select Test to begin. The system will hibernate and should wake itself within 5 minutes. If your system does not wake itself after 5 minutes, please press the power button to wake the system manually. If the system fails to resume from hibernate, please restart System Testing and mark this test as Failed. | 10 | STEPS: |
4127 | 11 | . | 11 | 1. Click on Test |
4128 | 12 | Did the system successfully hibernate and did it work properly after waking up? | 12 | 2. The system will hibernate and should wake itself within 5 minutes |
4129 | 13 | 13 | 3. If your system does not wake itself after 5 minutes, please press the power button to wake the system manually | |
4130 | 14 | 14 | 4. If the system fails to resume from hibernate, please restart System Testing and mark this test as Failed | |
4131 | 15 | VERIFICATION: | ||
4132 | 16 | Did the system successfully hibernate and did it work properly after waking up? | ||
4133 | 15 | 17 | ||
4134 | === modified file 'jobs/info.txt.in' | |||
4135 | --- jobs/info.txt.in 2011-09-14 21:16:02 +0000 | |||
4136 | +++ jobs/info.txt.in 2011-11-18 18:04:27 +0000 | |||
4137 | @@ -1,44 +1,57 @@ | |||
4140 | 1 | 1 | name: codecs_attachment | |
4139 | 2 | name: info/codecs_attachment | ||
4141 | 3 | plugin: attachment | 2 | plugin: attachment |
4142 | 4 | requires: device.driver == 'HDA Intel' | 3 | requires: device.driver == 'HDA Intel' |
4143 | 5 | command: cat /proc/asound/card*/codec#* | 4 | command: cat /proc/asound/card*/codec#* |
4144 | 5 | _description: Attaches a report of installed codecs for Intel HDA | ||
4145 | 6 | 6 | ||
4147 | 7 | name: info/cpuinfo_attachment | 7 | name: cpuinfo_attachment |
4148 | 8 | plugin: attachment | 8 | plugin: attachment |
4149 | 9 | command: cat /proc/cpuinfo | 9 | command: cat /proc/cpuinfo |
4150 | 10 | _description: Attaches a report of CPU information | ||
4151 | 10 | 11 | ||
4153 | 11 | name: info/dmesg_attachment | 12 | name: dmesg_attachment |
4154 | 12 | plugin: attachment | 13 | plugin: attachment |
4155 | 13 | command: cat /var/log/dmesg | ansi_parser | 14 | command: cat /var/log/dmesg | ansi_parser |
4156 | 15 | _description: Attaches a copy of /var/log/dmesg to the test results | ||
4157 | 14 | 16 | ||
4159 | 15 | name: info/dmi_attachment | 17 | name: dmi_attachment |
4160 | 16 | plugin: attachment | 18 | plugin: attachment |
4161 | 17 | command: grep -r . /sys/class/dmi/id/ 2>/dev/null | 19 | command: grep -r . /sys/class/dmi/id/ 2>/dev/null |
4162 | 20 | _description: Attaches info on DMI | ||
4163 | 18 | 21 | ||
4165 | 19 | name: info/dmidecode_attachment | 22 | name: dmidecode_attachment |
4166 | 20 | plugin: attachment | 23 | plugin: attachment |
4167 | 21 | user: root | 24 | user: root |
4168 | 22 | command: dmidecode | 25 | command: dmidecode |
4169 | 26 | _description: Attaches dmidecode output | ||
4170 | 23 | 27 | ||
4172 | 24 | name: info/lspci_attachment | 28 | name: lspci_attachment |
4173 | 25 | plugin: attachment | 29 | plugin: attachment |
4174 | 26 | command: lspci -vvnn | 30 | command: lspci -vvnn |
4177 | 27 | 31 | _description: Attaches very verbose lspci output. | |
4178 | 28 | name: info/modprobe_attachment | 32 | |
4179 | 33 | name: meminfo_attachment | ||
4180 | 34 | plugin: attachment | ||
4181 | 35 | command: cat /proc/meminfo | ||
4182 | 36 | |||
4183 | 37 | name: modprobe_attachment | ||
4184 | 29 | plugin: attachment | 38 | plugin: attachment |
4185 | 30 | command: find /etc/modprobe.* -name \*.conf | xargs cat | 39 | command: find /etc/modprobe.* -name \*.conf | xargs cat |
4186 | 40 | _description: Attaches the contents of the various modprobe conf files. | ||
4187 | 31 | 41 | ||
4189 | 32 | name: info/modules_attachment | 42 | name: modules_attachment |
4190 | 33 | plugin: attachment | 43 | plugin: attachment |
4191 | 34 | command: cat /etc/modules | 44 | command: cat /etc/modules |
4192 | 45 | _description: Attaches the contents of the /etc/modules file. | ||
4193 | 35 | 46 | ||
4195 | 36 | name: info/sysctl_attachment | 47 | name: sysctl_attachment |
4196 | 37 | plugin: attachment | 48 | plugin: attachment |
4197 | 38 | command: find /etc/sysctl.* -name \*.conf | xargs cat | 49 | command: find /etc/sysctl.* -name \*.conf | xargs cat |
4198 | 50 | _description: attaches the contents of various sysctl config files. | ||
4199 | 39 | 51 | ||
4201 | 40 | name: info/sysfs_attachment | 52 | name: sysfs_attachment |
4202 | 41 | plugin: attachment | 53 | plugin: attachment |
4203 | 54 | _description: Attaches a report of sysfs attributes. | ||
4204 | 42 | command: | 55 | command: |
4205 | 43 | for i in `udevadm info --export-db | sed -n 's/^P: //p'`; do | 56 | for i in `udevadm info --export-db | sed -n 's/^P: //p'`; do |
4206 | 44 | echo "P: $i" | 57 | echo "P: $i" |
4207 | @@ -46,19 +59,22 @@ | |||
4208 | 46 | echo | 59 | echo |
4209 | 47 | done | 60 | done |
4210 | 48 | 61 | ||
4212 | 49 | name: info/udev_attachment | 62 | name: udev_attachment |
4213 | 50 | plugin: attachment | 63 | plugin: attachment |
4214 | 51 | command: udevadm info --export-db | 64 | command: udevadm info --export-db |
4215 | 65 | _description: Attaches a dump of the udev database showing system hardware information. | ||
4216 | 52 | 66 | ||
4218 | 53 | name: info/gcov_attachment | 67 | name: gcov_attachment |
4219 | 54 | plugin: attachment | 68 | plugin: attachment |
4220 | 55 | requires: package.name == 'lcov' | 69 | requires: package.name == 'lcov' |
4221 | 56 | user: root | 70 | user: root |
4222 | 57 | command: gcov_tarball | 71 | command: gcov_tarball |
4223 | 72 | _description: Attaches a tarball of gcov data if present. | ||
4224 | 58 | 73 | ||
4226 | 59 | name: info/lsmod_attachment | 74 | name: lsmod_attachment |
4227 | 60 | plugin: attachment | 75 | plugin: attachment |
4228 | 61 | command: lsmod | 76 | command: lsmod |
4229 | 77 | _description: Attaches a list of the currently running kernel modules. | ||
4230 | 62 | 78 | ||
4231 | 63 | plugin: shell | 79 | plugin: shell |
4232 | 64 | name: info/screenshot | 80 | name: info/screenshot |
4233 | @@ -66,25 +82,25 @@ | |||
4234 | 66 | package.name == 'xorg' | 82 | package.name == 'xorg' |
4235 | 67 | package.name == 'imagemagick' | 83 | package.name == 'imagemagick' |
4236 | 68 | command: import -window root ${CHECKBOX_DATA}/screenshot.png | 84 | command: import -window root ${CHECKBOX_DATA}/screenshot.png |
4239 | 69 | _description: | 85 | _description: Captures a screenshot. |
4238 | 70 | Captures a screenshot. | ||
4240 | 71 | 86 | ||
4241 | 72 | plugin: attachment | 87 | plugin: attachment |
4243 | 73 | name: info/screenshot.png | 88 | name: screenshot.png |
4244 | 74 | depends: screenshot | 89 | depends: screenshot |
4245 | 75 | command: cat ${CHECKBOX_DATA}/screenshot.png | 90 | command: cat ${CHECKBOX_DATA}/screenshot.png |
4246 | 91 | _description: Attaches the screenshot captured in info/screenshot. | ||
4247 | 76 | 92 | ||
4248 | 77 | plugin: attachment | 93 | plugin: attachment |
4250 | 78 | name: info/fwts_log | 94 | name: fwts_log |
4251 | 79 | depends: fwts_test | 95 | depends: fwts_test |
4254 | 80 | _description: | 96 | _description: Gather log from the Firmware Test Suite run. |
4253 | 81 | Gather log from the firmware test suite run | ||
4255 | 82 | command: | 97 | command: |
4256 | 83 | cat $CHECKBOX_DATA/fwts_results.log | 98 | cat $CHECKBOX_DATA/fwts_results.log |
4257 | 84 | 99 | ||
4258 | 85 | plugin: attachment | 100 | plugin: attachment |
4261 | 86 | name: info/acpi_sleep_attachment | 101 | name: acpi_sleep_attachment |
4262 | 87 | command: cat /proc/acpi/sleep | 102 | command: [ -e /proc/acpi/sleep ] && cat /proc/acpi/sleep |
4263 | 103 | _description: Attaches the contents of /proc/acpi/sleep if it exists. | ||
4264 | 88 | 104 | ||
4265 | 89 | plugin: local | 105 | plugin: local |
4266 | 90 | name: info/bootchart | 106 | name: info/bootchart |
4267 | @@ -111,25 +127,29 @@ | |||
4268 | 111 | EOF | 127 | EOF |
4269 | 112 | 128 | ||
4270 | 113 | plugin: attachment | 129 | plugin: attachment |
4272 | 114 | name: info/bootchart.png | 130 | name: bootchart.png |
4273 | 115 | depends: info/bootchart | 131 | depends: info/bootchart |
4274 | 116 | requires: (package.name == 'bootchart' and float(lsb.release) < 9.04) or package.name == 'pybootchartgui' | 132 | requires: (package.name == 'bootchart' and float(lsb.release) < 9.04) or package.name == 'pybootchartgui' |
4275 | 133 | _description: Attaches the bootchart png file for bootchart runs | ||
4276 | 117 | command: | 134 | command: |
4277 | 118 | file=`ls /var/log/bootchart/*.png 2>/dev/null | tail -1`; \ | 135 | file=`ls /var/log/bootchart/*.png 2>/dev/null | tail -1`; \ |
4278 | 119 | [ -e "$file" ] && cat "$file" | 136 | [ -e "$file" ] && cat "$file" |
4279 | 120 | 137 | ||
4280 | 121 | plugin: attachment | 138 | plugin: attachment |
4282 | 122 | name: info/bootchart.tgz | 139 | name: bootchart.tgz |
4283 | 123 | depends: info/bootchart | 140 | depends: info/bootchart |
4284 | 124 | requires: package.name == 'bootchart' and float(lsb.release) >= 9.04 | 141 | requires: package.name == 'bootchart' and float(lsb.release) >= 9.04 |
4285 | 142 | _description: Attaches the bootchart log for bootchart test runs. | ||
4286 | 125 | command: | 143 | command: |
4287 | 126 | file=`ls /var/log/bootchart/*.tgz 2>/dev/null | tail -1`; \ | 144 | file=`ls /var/log/bootchart/*.tgz 2>/dev/null | tail -1`; \ |
4288 | 127 | [ -e "$file" ] && cat "$file" | 145 | [ -e "$file" ] && cat "$file" |
4289 | 128 | 146 | ||
4290 | 129 | plugin: attachment | 147 | plugin: attachment |
4292 | 130 | name: info/installer_bootchart.tgz | 148 | name: installer_bootchart.tgz |
4293 | 131 | command: [ -e /var/log/installer/bootchart.tgz ] && cat /var/log/installer/bootchart.tgz | 149 | command: [ -e /var/log/installer/bootchart.tgz ] && cat /var/log/installer/bootchart.tgz |
4294 | 150 | _description: installs the installer bootchart tarball if it exists. | ||
4295 | 132 | 151 | ||
4296 | 133 | plugin: attachment | 152 | plugin: attachment |
4298 | 134 | name: info/installer_debug.gz | 153 | name: installer_debug.gz |
4299 | 135 | command: [ -e /var/log/installer/debug ] && gzip -9 -c /var/log/installer/debug | 154 | command: [ -e /var/log/installer/debug ] && gzip -9 -c /var/log/installer/debug |
4300 | 155 | _description: Attaches the installer debug log if it exists. | ||
4301 | 136 | 156 | ||
4302 | === modified file 'jobs/input.txt.in' | |||
4303 | --- jobs/input.txt.in 2011-08-10 21:09:56 +0000 | |||
4304 | +++ jobs/input.txt.in 2011-11-18 18:04:27 +0000 | |||
4305 | @@ -1,16 +1,24 @@ | |||
4306 | 1 | plugin: manual | 1 | plugin: manual |
4307 | 2 | name: input/mouse | 2 | name: input/mouse |
4309 | 3 | requires: device.category == 'MOUSE' | 3 | requires: device.category == 'MOUSE' or device.category == 'TOUCH' |
4310 | 4 | _description: | 4 | _description: |
4314 | 5 | Moving the mouse should move the cursor on the screen. | 5 | PURPOSE: |
4315 | 6 | . | 6 | This test will test your pointing device |
4316 | 7 | Is your mouse working properly? | 7 | STEPS: |
4317 | 8 | 1. Move the cursor using the pointing device or touch the screen. | ||
4318 | 9 | 2. Perform some single/double/right click operations. | ||
4319 | 10 | VERIFICATION: | ||
4320 | 11 | Did the pointing device work as expected? | ||
4321 | 8 | 12 | ||
4322 | 9 | plugin: manual | 13 | plugin: manual |
4323 | 10 | name: input/keyboard | 14 | name: input/keyboard |
4324 | 11 | command: keyboard_test | 15 | command: keyboard_test |
4325 | 12 | requires: device.category == 'KEYBOARD' | 16 | requires: device.category == 'KEYBOARD' |
4326 | 13 | _description: | 17 | _description: |
4330 | 14 | Select Test to open a text area where to type keys on your keyboard. | 18 | PURPOSE: |
4331 | 15 | . | 19 | This test will test your keyboard |
4332 | 16 | Is your keyboard working properly? | 20 | STEPS: |
4333 | 21 | 1. Click on Test | ||
4334 | 22 | 2. On the open text area, use your keyboard to type something | ||
4335 | 23 | VERIFICATION: | ||
4336 | 24 | Is your keyboard working properly? | ||
4337 | 17 | 25 | ||
4338 | === modified file 'jobs/install.txt.in' | |||
4339 | --- jobs/install.txt.in 2011-09-01 12:23:07 +0000 | |||
4340 | +++ jobs/install.txt.in 2011-11-18 18:04:27 +0000 | |||
4341 | @@ -4,4 +4,4 @@ | |||
4342 | 4 | user: root | 4 | user: root |
4343 | 5 | command: apt-get -d -y --force-yes dist-upgrade && true || false | 5 | command: apt-get -d -y --force-yes dist-upgrade && true || false |
4344 | 6 | _description: | 6 | _description: |
4346 | 7 | Tests to see that apt can access repositories and get updates (does not install updates) | 7 | Tests to see that apt can access repositories and get updates (does not install updates). This is done to confirm that you could recover from an incomplete or broken update. |
4347 | 8 | 8 | ||
4348 | === modified file 'jobs/keys.txt.in' | |||
4349 | --- jobs/keys.txt.in 2011-09-01 12:23:07 +0000 | |||
4350 | +++ jobs/keys.txt.in 2011-11-18 18:04:27 +0000 | |||
4351 | @@ -1,73 +1,86 @@ | |||
4352 | 1 | plugin: manual | 1 | plugin: manual |
4353 | 2 | name: keys/brightness | 2 | name: keys/brightness |
4355 | 3 | requires: device.product in ['Notebook','Laptop','Portable'] | 3 | requires: dmi.product in ['Notebook','Laptop','Portable'] |
4356 | 4 | _description: | 4 | _description: |
4361 | 5 | Press the brightness buttons on the keyboard. A status window should \ | 5 | PURPOSE: |
4362 | 6 | appear and the brightness should change. | 6 | This test will test the brightness key |
4363 | 7 | . | 7 | STEPS: |
4364 | 8 | Do the buttons work? | 8 | 1. Press the brightness buttons on the keyboard |
4365 | 9 | VERIFICATION: | ||
4366 | 10 | Did the brightness change following to your key presses? | ||
4367 | 9 | 11 | ||
4368 | 10 | plugin: manual | 12 | plugin: manual |
4369 | 11 | name: keys/volume | 13 | name: keys/volume |
4370 | 12 | _description: | 14 | _description: |
4375 | 13 | Press the volume buttons on the keyboard. A status window should \ | 15 | PURPOSE: |
4376 | 14 | appear and the volume should change. | 16 | This test will test the volume keys |
4377 | 15 | . | 17 | STEPS: |
4378 | 16 | Do the buttons work? | 18 | 1. Press the volume buttons on the keyboard |
4379 | 19 | VERIFICATION: | ||
4380 | 20 | Did the volume change following to your key presses? | ||
4381 | 17 | 21 | ||
4382 | 18 | plugin: manual | 22 | plugin: manual |
4383 | 19 | name: keys/mute | 23 | name: keys/mute |
4385 | 20 | requires: device.product in ['Notebook','Laptop','Portable'] | 24 | requires: dmi.product in ['Notebook','Laptop','Portable'] |
4386 | 21 | _description: | 25 | _description: |
4391 | 22 | Press the mute key on the keyboard. A status window should appear \ | 26 | PURPOSE: |
4392 | 23 | and the volume should mute/unmute when pressed multiple times. | 27 | This test will test the mute key |
4393 | 24 | . | 28 | STEPS: |
4394 | 25 | Does the key work? | 29 | 1. Press the mute button on the keyboard |
4395 | 30 | VERIFICATION: | ||
4396 | 31 | Did the volume mute following your key presses? | ||
4397 | 26 | 32 | ||
4398 | 27 | plugin: manual | 33 | plugin: manual |
4399 | 28 | name: keys/sleep | 34 | name: keys/sleep |
4401 | 29 | requires: device.product in ['Notebook','Laptop','Portable'] | 35 | requires: dmi.product in ['Notebook','Laptop','Portable'] |
4402 | 30 | depends: suspend/suspend_advanced | 36 | depends: suspend/suspend_advanced |
4403 | 31 | _description: | 37 | _description: |
4408 | 32 | Press the sleep key on the keyboard. The computer should suspend and, \ | 38 | PURPOSE: |
4409 | 33 | after pressing the power button, resume successfully. | 39 | This test will test the sleep key |
4410 | 34 | . | 40 | STEPS: |
4411 | 35 | Does the key work? | 41 | 1. Press the sleep key on the keyboard |
4412 | 42 | 2. Wake your system up by pressing the power button | ||
4413 | 43 | VERIFICATION: | ||
4414 | 44 | Did the system go to sleep after pressing the sleep key? | ||
4415 | 36 | 45 | ||
4416 | 37 | plugin: manual | 46 | plugin: manual |
4417 | 38 | name: keys/battery-info | 47 | name: keys/battery-info |
4419 | 39 | requires: device.product in ['Notebook','Laptop','Portable'] | 48 | requires: dmi.product in ['Notebook','Laptop','Portable'] |
4420 | 40 | _description: | 49 | _description: |
4425 | 41 | Press the battery information key on the keyboard. A status window \ | 50 | PURPOSE: |
4426 | 42 | should appear and the amount of battery remaining should be displayed. | 51 | This test will test the battery information key |
4427 | 43 | . | 52 | STEPS: |
4428 | 44 | Does the key work? | 53 | 1. Press the battery information key on the keyboard |
4429 | 54 | VERIFICATION: | ||
4430 | 55 | Did a notification appear showing the battery status? | ||
4431 | 45 | 56 | ||
4432 | 46 | plugin: manual | 57 | plugin: manual |
4433 | 47 | name: keys/wireless | 58 | name: keys/wireless |
4435 | 48 | requires: device.product in ['Notebook','Laptop','Portable'] | 59 | requires: dmi.product in ['Notebook','Laptop','Portable'] |
4436 | 49 | _description: | 60 | _description: |
4446 | 50 | Press the wireless networking key on the keyboard. The bluetooth icon \ | 61 | PURPOSE: |
4447 | 51 | and the network connnection should go down if connected through the \ | 62 | This test will test the wireless key |
4448 | 52 | wifi interface. | 63 | STEPS: |
4449 | 53 | . | 64 | 1. Press the wireless key on the keyboard |
4450 | 54 | Press the same key again and check that bluetooth icon is again \ | 65 | 2. Press the same key again |
4451 | 55 | displayed and that the network connection is re-established \ | 66 | VERIFICATION: |
4452 | 56 | automatically. | 67 | Did the wireless go off on the first press and on again on the second? |
4444 | 57 | . | ||
4445 | 58 | Does the key work? | ||
4453 | 59 | 68 | ||
4454 | 60 | plugin: manual | 69 | plugin: manual |
4455 | 61 | name: keys/media-control | 70 | name: keys/media-control |
4457 | 62 | requires: device.category == 'KEYBOARD' | 71 | requires: |
4458 | 72 | device.category == 'KEYBOARD' | ||
4459 | 73 | package.name == 'totem' | ||
4460 | 74 | package.name == 'gstreamer0.10-plugins-base' | ||
4461 | 75 | command: totem /usr/share/example-content/Ubuntu_Free_Culture_Showcase/* | ||
4462 | 63 | _description: | 76 | _description: |
4473 | 64 | The keyboard may have dedicated keys for controlling media as follows: | 77 | PURPOSE: |
4474 | 65 | . | 78 | This test will test the media keys of your keyboard |
4475 | 66 | * Play/Pause | 79 | STEPS: |
4476 | 67 | * Stop | 80 | 1. Click test to launch the media player |
4477 | 68 | * Forward | 81 | 2. Press the play/pause key on the keyboard |
4478 | 69 | * Backward (Rewind) | 82 | 3. Press the forward key on the keyboard |
4479 | 70 | . | 83 | 4. Press the backward key on the keyboard |
4480 | 71 | Play a media file and press each key in turn. | 84 | 5. Press stop key on the keyboard |
4481 | 72 | . | 85 | VERIFICATION: |
4482 | 73 | Do the keys work as expected? | 86 | Do the keys work as expected? |
4483 | 74 | 87 | ||
4484 | === modified file 'jobs/local.txt.in' | |||
4485 | --- jobs/local.txt.in 2011-09-01 12:23:07 +0000 | |||
4486 | +++ jobs/local.txt.in 2011-11-18 18:04:27 +0000 | |||
4487 | @@ -3,6 +3,11 @@ | |||
4488 | 3 | _description: Audio tests | 3 | _description: Audio tests |
4489 | 4 | command: cat $CHECKBOX_SHARE/jobs/audio.txt* | 4 | command: cat $CHECKBOX_SHARE/jobs/audio.txt* |
4490 | 5 | 5 | ||
4491 | 6 | name: __autotest__ | ||
4492 | 7 | plugin: local | ||
4493 | 8 | _description: Autotest Suite tests | ||
4494 | 9 | command: cat $CHECKBOX_SHARE/jobs/autotest.txt* | ||
4495 | 10 | |||
4496 | 6 | name: __bluetooth__ | 11 | name: __bluetooth__ |
4497 | 7 | plugin: local | 12 | plugin: local |
4498 | 8 | _description: Bluetooth tests | 13 | _description: Bluetooth tests |
4499 | @@ -13,7 +18,7 @@ | |||
4500 | 13 | _description: Camera tests | 18 | _description: Camera tests |
4501 | 14 | command: cat $CHECKBOX_SHARE/jobs/camera.txt* | 19 | command: cat $CHECKBOX_SHARE/jobs/camera.txt* |
4502 | 15 | 20 | ||
4504 | 16 | name: codecs | 21 | name: __codecs__ |
4505 | 17 | plugin: local | 22 | plugin: local |
4506 | 18 | _description: Codec tests | 23 | _description: Codec tests |
4507 | 19 | command: cat $CHECKBOX_SHARE/jobs/codecs.txt* | 24 | command: cat $CHECKBOX_SHARE/jobs/codecs.txt* |
4508 | @@ -23,7 +28,7 @@ | |||
4509 | 23 | _description: CPU tests | 28 | _description: CPU tests |
4510 | 24 | command: cat $CHECKBOX_SHARE/jobs/cpu.txt* | 29 | command: cat $CHECKBOX_SHARE/jobs/cpu.txt* |
4511 | 25 | 30 | ||
4513 | 26 | name: daemon | 31 | name: __daemons__ |
4514 | 27 | plugin: local | 32 | plugin: local |
4515 | 28 | _description: System Daemon tests | 33 | _description: System Daemon tests |
4516 | 29 | command: cat $CHECKBOX_SHARE/jobs/daemons.txt* | 34 | command: cat $CHECKBOX_SHARE/jobs/daemons.txt* |
4517 | @@ -53,6 +58,11 @@ | |||
4518 | 53 | _description: Graphics tests | 58 | _description: Graphics tests |
4519 | 54 | command: cat $CHECKBOX_SHARE/jobs/graphics.txt* | 59 | command: cat $CHECKBOX_SHARE/jobs/graphics.txt* |
4520 | 55 | 60 | ||
4521 | 61 | name: __hibernate__ | ||
4522 | 62 | plugin: local | ||
4523 | 63 | _description: Hibernation tests | ||
4524 | 64 | command: cat $CHECKBOX_SHARE/jobs/hibernate.txt* | ||
4525 | 65 | |||
4526 | 56 | name: __info__ | 66 | name: __info__ |
4527 | 57 | plugin: local | 67 | plugin: local |
4528 | 58 | _description: Informational tests | 68 | _description: Informational tests |
4529 | @@ -73,10 +83,15 @@ | |||
4530 | 73 | _description: Hotkey tests | 83 | _description: Hotkey tests |
4531 | 74 | command: cat $CHECKBOX_SHARE/jobs/keys.txt* | 84 | command: cat $CHECKBOX_SHARE/jobs/keys.txt* |
4532 | 75 | 85 | ||
4537 | 76 | name: __hibernate__ | 86 | name: __ltp__ |
4538 | 77 | plugin: local | 87 | plugin: local |
4539 | 78 | _description: Hibernation tests | 88 | _description: Linux Test Project tests |
4540 | 79 | command: cat $CHECKBOX_SHARE/jobs/hibernate.txt* | 89 | command: cat $CHECKBOX_SHARE/jobs/ltp.txt* |
4541 | 90 | |||
4542 | 91 | name: __mago__ | ||
4543 | 92 | plugin: local | ||
4544 | 93 | _description: Mago Automated Desktop Testing | ||
4545 | 94 | command: cat $CHECKBOX_SHARE/jobs/mago.txt* | ||
4546 | 80 | 95 | ||
4547 | 81 | name: __mediacard__ | 96 | name: __mediacard__ |
4548 | 82 | plugin: local | 97 | plugin: local |
4549 | @@ -108,6 +123,11 @@ | |||
4550 | 108 | _description: Optical Drive tests | 123 | _description: Optical Drive tests |
4551 | 109 | command: cat $CHECKBOX_SHARE/jobs/optical.txt* | 124 | command: cat $CHECKBOX_SHARE/jobs/optical.txt* |
4552 | 110 | 125 | ||
4553 | 126 | name: __panel_clock__ | ||
4554 | 127 | plugin: local | ||
4555 | 128 | _description: Panel Clock Verification tests | ||
4556 | 129 | command: cat $CHECKBOX_SHARE/jobs/panel_clock_test.txt* | ||
4557 | 130 | |||
4558 | 111 | name: __pcmcia-pcix__ | 131 | name: __pcmcia-pcix__ |
4559 | 112 | plugin: local | 132 | plugin: local |
4560 | 113 | _description: PCMCIA/PCIX Card tests | 133 | _description: PCMCIA/PCIX Card tests |
4561 | @@ -118,11 +138,26 @@ | |||
4562 | 118 | _description: Peripheral tests | 138 | _description: Peripheral tests |
4563 | 119 | command: cat $CHECKBOX_SHARE/jobs/peripheral.txt* | 139 | command: cat $CHECKBOX_SHARE/jobs/peripheral.txt* |
4564 | 120 | 140 | ||
4565 | 141 | name: __phoronix__ | ||
4566 | 142 | plugin: local | ||
4567 | 143 | _description: Phoronix Test Suite tests | ||
4568 | 144 | command: cat $CHECKBOX_SHARE/jobs/peripheral.txt* | ||
4569 | 145 | |||
4570 | 121 | name: __power-management__ | 146 | name: __power-management__ |
4571 | 122 | plugin: local | 147 | plugin: local |
4572 | 123 | _description: Power Management tests | 148 | _description: Power Management tests |
4573 | 124 | command: cat $CHECKBOX_SHARE/jobs/power-management.txt* | 149 | command: cat $CHECKBOX_SHARE/jobs/power-management.txt* |
4574 | 125 | 150 | ||
4575 | 151 | name: __qa__ | ||
4576 | 152 | plugin: local | ||
4577 | 153 | _description: QA Regression tests | ||
4578 | 154 | command: cat $CHECKBOX_SHARE/jobs/qa_regression.txt* | ||
4579 | 155 | |||
4580 | 156 | name: __server-services__ | ||
4581 | 157 | plugin: local | ||
4582 | 158 | _description: Server Services checks | ||
4583 | 159 | command: cat $CHECKBOX_SHARE/jobs/server-services.txt* | ||
4584 | 160 | |||
4585 | 126 | name: __suspend__ | 161 | name: __suspend__ |
4586 | 127 | plugin: local | 162 | plugin: local |
4587 | 128 | _description: Suspend tests | 163 | _description: Suspend tests |
4588 | 129 | 164 | ||
4589 | === modified file 'jobs/ltp.txt.in' | |||
4590 | --- jobs/ltp.txt.in 2010-03-09 16:58:36 +0000 | |||
4591 | +++ jobs/ltp.txt.in 2011-11-18 18:04:27 +0000 | |||
4592 | @@ -1,6 +1,7 @@ | |||
4594 | 1 | name: ltp | 1 | name: ltp/syscalls |
4595 | 2 | plugin: remote | 2 | plugin: remote |
4597 | 3 | _description: Linux Test Project | 3 | _description: |
4598 | 4 | This test installs and runs Linux Test Project syscalls test. This can be destructive, thus this test is blacklisted by default. | ||
4599 | 4 | requires: | 5 | requires: |
4600 | 5 | package.alias == 'linux' | 6 | package.alias == 'linux' |
4601 | 6 | package.name == 'cvs' | 7 | package.name == 'cvs' |
4602 | 7 | 8 | ||
4603 | === modified file 'jobs/mago.txt.in' | |||
4604 | --- jobs/mago.txt.in 2011-07-01 11:37:27 +0000 | |||
4605 | +++ jobs/mago.txt.in 2011-11-18 18:04:27 +0000 | |||
4606 | @@ -1,8 +1,10 @@ | |||
4607 | 1 | plugin: remote | 1 | plugin: remote |
4610 | 2 | name: mago | 2 | name: mago/suite |
4609 | 3 | _description: Automated desktop testing | ||
4611 | 4 | requires: | 3 | requires: |
4612 | 5 | package.name == 'bzr' | 4 | package.name == 'bzr' |
4613 | 6 | package.name == 'python-ldtp' | 5 | package.name == 'python-ldtp' |
4614 | 7 | desktop.gnome.interface.accessibility == True | 6 | desktop.gnome.interface.accessibility == True |
4615 | 8 | command: mago_suite | 7 | command: mago_suite |
4616 | 8 | _description: | ||
4617 | 9 | PURPOSE: | ||
4618 | 10 | This test installs and runs the Mago Automated Desktop Testing suite. | ||
4619 | 9 | 11 | ||
4620 | === modified file 'jobs/mediacard.txt.in' | |||
4621 | --- jobs/mediacard.txt.in 2011-09-29 13:12:01 +0000 | |||
4622 | +++ jobs/mediacard.txt.in 2011-11-18 18:04:27 +0000 | |||
4623 | @@ -1,137 +1,159 @@ | |||
4624 | 1 | plugin: manual | 1 | plugin: manual |
4625 | 2 | name: mediacard/sd | 2 | name: mediacard/sd |
4626 | 3 | _description: | 3 | _description: |
4634 | 4 | Secure Digital (SD) media card support verification: | 4 | PURPOSE: |
4635 | 5 | 1.- Plug a SD media card into the computer. | 5 | This test will check your system Secure Digital (SD) media card support |
4636 | 6 | 2.- An icon should appear on the desktop and in the "Places" menu at the top of the screen. | 6 | STEPS: |
4637 | 7 | 3.- Right click on the deskop icon and select "Safely Remove Drive". | 7 | 1. Plug a SD media card into the computer |
4638 | 8 | 4.- The icon should disappear of both the deskop and the "Places" menu. | 8 | 2. An icon should appear on the Launcher |
4639 | 9 | . | 9 | 3. Right click on the Launcher icon and select "Safely Remove Drive" |
4640 | 10 | Does the icon automatically appear/disappear? | 10 | 4. The icon should disappear from the Launcher |
4641 | 11 | VERIFICATION: | ||
4642 | 12 | Does the icon automatically appear/disappear? | ||
4643 | 11 | 13 | ||
4644 | 12 | plugin: manual | 14 | plugin: manual |
4645 | 13 | name: mediacard/sd_after_suspend | 15 | name: mediacard/sd_after_suspend |
4646 | 14 | depends: suspend/suspend_advanced mediacard/sd | 16 | depends: suspend/suspend_advanced mediacard/sd |
4647 | 15 | _description: | 17 | _description: |
4655 | 16 | Secure Digital (SD) media card support re-verification: | 18 | PURPOSE: |
4656 | 17 | 1.- Plug a SD media card into the computer. | 19 | This test will check your system Secure Digital (SD) media card support after suspend |
4657 | 18 | 2.- An icon should appear on the desktop and in the "Places" menu at the top of the screen. | 20 | STEPS: |
4658 | 19 | 3.- Right click on the deskop icon and select "Safely Remove Drive". | 21 | 1. Plug a SD media card into the computer |
4659 | 20 | 4.- The icon should disappear of both the deskop and the "Places" menu. | 22 | 2. An icon should appear on the Launcher |
4660 | 21 | . | 23 | 3. Right click on the Launcher icon and select "Safely Remove Drive" |
4661 | 22 | Does the icon automatically appear/disappear? | 24 | 4. The icon should disappear from the Launcher |
4662 | 25 | VERIFICATION: | ||
4663 | 26 | Does the icon automatically appear/disappear? | ||
4664 | 23 | 27 | ||
4665 | 24 | plugin: manual | 28 | plugin: manual |
4666 | 25 | name: mediacard/sdhc | 29 | name: mediacard/sdhc |
4667 | 26 | _description: | 30 | _description: |
4675 | 27 | Secure Digital High Capacity (SDHC) media card support verification: | 31 | PURPOSE: |
4676 | 28 | 1.- Plug a SDHC media card into the computer. | 32 | This test will check your system Secure Digital High Capacity (SDHC) media card support |
4677 | 29 | 2.- An icon should appear on the desktop and in the "Places" menu at the top of the screen. | 33 | STEPS: |
4678 | 30 | 3.- Right click on the deskop icon and select "Safely Remove Drive". | 34 | 1. Plug a SDHC media card into the computer |
4679 | 31 | 4.- The icon should disappear of both the deskop and the "Places" menu. | 35 | 2. An icon should appear on the Launcher |
4680 | 32 | . | 36 | 3. Right click on the Launcher icon and select "Safely Remove Drive" |
4681 | 33 | Does the icon automatically appear/disappear? | 37 | 4. The icon should disappear from the Launcher |
4682 | 38 | VERIFICATION: | ||
4683 | 39 | Does the icon automatically appear/disappear? | ||
4684 | 34 | 40 | ||
4685 | 35 | plugin: manual | 41 | plugin: manual |
4686 | 36 | name: mediacard/sdhc_after_suspend | 42 | name: mediacard/sdhc_after_suspend |
4687 | 37 | depends: suspend/suspend_advanced mediacard/sdhc | 43 | depends: suspend/suspend_advanced mediacard/sdhc |
4688 | 38 | _description: | 44 | _description: |
4696 | 39 | Secure Digital High Capacity (SDHC) media card support re-verification: | 45 | This test will check your system Secure Digital High Capacity (SDHC) media card support after suspend |
4697 | 40 | 1.- Plug a SDHC media card into the computer. | 46 | STEPS: |
4698 | 41 | 2.- An icon should appear on the desktop and in the "Places" menu at the top of the screen. | 47 | 1. Plug a SDHC media card into the computer |
4699 | 42 | 3.- Right click on the deskop icon and select "Safely Remove Drive". | 48 | 2. An icon should appear on the Launcher |
4700 | 43 | 4.- The icon should disappear of both the deskop and the "Places" menu. | 49 | 3. Right click on the Launcher icon and select "Safely Remove Drive" |
4701 | 44 | . | 50 | 4. The icon should disappear from the Launcher |
4702 | 45 | Does the icon automatically appear/disappear? | 51 | VERIFICATION: |
4703 | 52 | Does the icon automatically appear/disappear? | ||
4704 | 46 | 53 | ||
4705 | 47 | plugin: manual | 54 | plugin: manual |
4706 | 48 | name: mediacard/mmc | 55 | name: mediacard/mmc |
4707 | 49 | _description: | 56 | _description: |
4715 | 50 | Multi Media Card (MMC) media card support verification: | 57 | PURPOSE: |
4716 | 51 | 1.- Plug a MMC media card into the computer. | 58 | This test will check your system Multi Media Card (MMC) media card support |
4717 | 52 | 2.- An icon should appear on the desktop and in the "Places" menu at the top of the screen. | 59 | STEPS: |
4718 | 53 | 3.- Right click on the deskop icon and select "Safely Remove Drive". | 60 | 1. Plug a MMC media card into the computer |
4719 | 54 | 4.- The icon should disappear of both the deskop and the "Places" menu. | 61 | 2. An icon should appear on the Launcher |
4720 | 55 | . | 62 | 3. Right click on the Launcher icon and select "Safely Remove Drive" |
4721 | 56 | Does the icon automatically appear/disappear? | 63 | 4. The icon should disappear from the Launcher |
4722 | 64 | VERIFICATION: | ||
4723 | 65 | Does the icon automatically appear/disappear? | ||
4724 | 57 | 66 | ||
4725 | 58 | plugin: manual | 67 | plugin: manual |
4726 | 59 | name: mediacard/mmc_after_suspend | 68 | name: mediacard/mmc_after_suspend |
4727 | 60 | depends: suspend/suspend_advanced mediacard/mmc | 69 | depends: suspend/suspend_advanced mediacard/mmc |
4728 | 61 | _description: | 70 | _description: |
4736 | 62 | Multi Media Card (MMC) media card support re-verification: | 71 | PURPOSE: |
4737 | 63 | 1.- Plug a MMC media card into the computer. | 72 | This test will check your system Multi Media Card (MMC) media card support after suspend |
4738 | 64 | 2.- An icon should appear on the desktop and in the "Places" menu at the top of the screen. | 73 | STEPS: |
4739 | 65 | 3.- Right click on the deskop icon and select "Safely Remove Drive". | 74 | 1. Plug a MMC media card into the computer |
4740 | 66 | 4.- The icon should disappear of both the deskop and the "Places" menu. | 75 | 2. An icon should appear on the Launcher |
4741 | 67 | . | 76 | 3. Right click on the Launcher icon and select "Safely Remove Drive" |
4742 | 68 | Does the icon automatically appear/disappear? | 77 | 4. The icon should disappear from the Launcher |
4743 | 78 | VERIFICATION: | ||
4744 | 79 | Does the icon automatically appear/disappear? | ||
4745 | 69 | 80 | ||
4746 | 70 | plugin: manual | 81 | plugin: manual |
4747 | 71 | name: mediacard/ms | 82 | name: mediacard/ms |
4748 | 72 | _description: | 83 | _description: |
4756 | 73 | Memory Stick (MS) media card support verification: | 84 | PURPOSE: |
4757 | 74 | 1.- Plug a MS media card into the computer. | 85 | This test will check your system Memory Stick (MS) media card support |
4758 | 75 | 2.- An icon should appear on the desktop and in the "Places" menu at the top of the screen. | 86 | STEPS: |
4759 | 76 | 3.- Right click on the deskop icon and select "Safely Remove Drive". | 87 | 1. Plug a MS media card into the computer |
4760 | 77 | 4.- The icon should disappear of both the deskop and the "Places" menu. | 88 | 2. An icon should appear on the Launcher |
4761 | 78 | . | 89 | 3. Right click on the Launcher icon and select "Safely Remove Drive" |
4762 | 79 | Does the icon automatically appear/disappear? | 90 | 4. The icon should disappear from the Launcher |
4763 | 91 | VERIFICATION: | ||
4764 | 92 | Does the icon automatically appear/disappear? | ||
4765 | 80 | 93 | ||
4766 | 81 | plugin: manual | 94 | plugin: manual |
4767 | 82 | name: mediacard/ms_after_suspend | 95 | name: mediacard/ms_after_suspend |
4768 | 83 | depends: suspend/suspend_advanced mediacard/ms | 96 | depends: suspend/suspend_advanced mediacard/ms |
4769 | 84 | _description: | 97 | _description: |
4777 | 85 | Memory Stick (MS) media card support re-verification: | 98 | PURPOSE: |
4778 | 86 | 1.- Plug a MS media card into the computer. | 99 | This test will check your system Memory Stick (MS) media card support after suspend |
4779 | 87 | 2.- An icon should appear on the desktop and in the "Places" menu at the top of the screen. | 100 | STEPS: |
4780 | 88 | 3.- Right click on the deskop icon and select "Safely Remove Drive". | 101 | 1. Plug a MS media card into the computer |
4781 | 89 | 4.- The icon should disappear of both the deskop and the "Places" menu. | 102 | 2. An icon should appear on the Launcher |
4782 | 90 | . | 103 | 3. Right click on the Launcher icon and select "Safely Remove Drive" |
4783 | 91 | Does the icon automatically appear/disappear? | 104 | 4. The icon should disappear from the Launcher |
4784 | 105 | VERIFICATION: | ||
4785 | 106 | Does the icon automatically appear/disappear? | ||
4786 | 92 | 107 | ||
4787 | 93 | plugin: manual | 108 | plugin: manual |
4788 | 94 | name: mediacard/msp | 109 | name: mediacard/msp |
4789 | 95 | _description: | 110 | _description: |
4797 | 96 | Memory Stick Pro (MSP) media card support verification: | 111 | PURPOSE: |
4798 | 97 | 1.- Plug a MSP media card into the computer. | 112 | This test will check your system Memory Stick Pro (MSP) media card support |
4799 | 98 | 2.- An icon should appear on the desktop and in the "Places" menu at the top of the screen. | 113 | STEPS: |
4800 | 99 | 3.- Right click on the deskop icon and select "Safely Remove Drive". | 114 | 1. Plug a MSP media card into the computer |
4801 | 100 | 4.- The icon should disappear of both the deskop and the "Places" menu. | 115 | 2. An icon should appear on the Launcher |
4802 | 101 | . | 116 | 3. Right click on the Launcher icon and select "Safely Remove Drive" |
4803 | 102 | Does the icon automatically appear/disappear? | 117 | 4. The icon should disappear from the Launcher |
4804 | 118 | VERIFICATION: | ||
4805 | 119 | Does the icon automatically appear/disappear? | ||
4806 | 103 | 120 | ||
4807 | 104 | plugin: manual | 121 | plugin: manual |
4808 | 105 | name: mediacard/msp_after_suspend | 122 | name: mediacard/msp_after_suspend |
4809 | 106 | depends: suspend/suspend_advanced mediacard/msp | 123 | depends: suspend/suspend_advanced mediacard/msp |
4810 | 107 | _description: | 124 | _description: |
4818 | 108 | Memory Stick Pro (MSP) media card support re-verification: | 125 | PURPOSE: |
4819 | 109 | 1.- Plug a MSP media card into the computer. | 126 | This test will check your system Memory Stick Pro (MSP) media card support after suspend |
4820 | 110 | 2.- An icon should appear on the desktop and in the "Places" menu at the top of the screen. | 127 | STEPS: |
4821 | 111 | 3.- Right click on the deskop icon and select "Safely Remove Drive". | 128 | 1. Plug a MSP media card into the computer |
4822 | 112 | 4.- The icon should disappear of both the deskop and the "Places" menu. | 129 | 2. An icon should appear on the Launcher |
4823 | 113 | . | 130 | 3. Right click on the Launcher icon and select "Safely Remove Drive" |
4824 | 114 | Does the icon automatically appear/disappear? | 131 | 4. The icon should disappear from the Launcher |
4825 | 132 | VERIFICATION: | ||
4826 | 133 | Does the icon automatically appear/disappear? | ||
4827 | 115 | 134 | ||
4828 | 116 | plugin: manual | 135 | plugin: manual |
4829 | 117 | name: mediacard/cf | 136 | name: mediacard/cf |
4830 | 118 | _description: | 137 | _description: |
4838 | 119 | Compact Flash (CF) media card support verification: | 138 | PURPOSE: |
4839 | 120 | 1.- Plug a CF media card into the computer. | 139 | This test will check your system Compact Flash (CF) media card support |
4840 | 121 | 2.- An icon should appear on the desktop and in the "Places" menu at the top of the screen. | 140 | STEPS: |
4841 | 122 | 3.- Right click on the deskop icon and select "Safely Remove Drive". | 141 | 1. Plug a CF media card into the computer |
4842 | 123 | 4.- The icon should disappear of both the deskop and the "Places" menu. | 142 | 2. An icon should appear on the Launcher |
4843 | 124 | . | 143 | 3. Right click on the Launcher icon and select "Safely Remove Drive" |
4844 | 125 | Does the icon automatically appear/disappear? | 144 | 4. The icon should disappear from the Launcher |
4845 | 145 | VERIFICATION: | ||
4846 | 146 | Does the icon automatically appear/disappear? | ||
4847 | 126 | 147 | ||
4848 | 127 | plugin: manual | 148 | plugin: manual |
4849 | 128 | name: mediacard/cf_after_suspend | 149 | name: mediacard/cf_after_suspend |
4850 | 129 | depends: suspend/suspend_advanced mediacard/cf | 150 | depends: suspend/suspend_advanced mediacard/cf |
4851 | 130 | _description: | 151 | _description: |
4859 | 131 | Compact Flash (CF) media card support re-verification: | 152 | This test will check your system Compact Flash (CF) media card support after suspend |
4860 | 132 | 1.- Plug a CF media card into the computer. | 153 | STEPS: |
4861 | 133 | 2.- An icon should appear on the desktop and in the "Places" menu at the top of the screen. | 154 | 1. Plug a CF media card into the computer |
4862 | 134 | 3.- Right click on the deskop icon and select "Safely Remove Drive". | 155 | 2. An icon should appear on the Launcher |
4863 | 135 | 4.- The icon should disappear of both the deskop and the "Places" menu. | 156 | 3. Right click on the Launcher icon and select "Safely Remove Drive" |
4864 | 136 | . | 157 | 4. The icon should disappear from the Launcher |
4865 | 137 | Does the icon automatically appear/disappear? | 158 | VERIFICATION: |
4866 | 159 | Does the icon automatically appear/disappear? | ||
4867 | 138 | 160 | ||
4868 | === modified file 'jobs/memory.txt.in' | |||
4869 | --- jobs/memory.txt.in 2011-09-14 21:16:02 +0000 | |||
4870 | +++ jobs/memory.txt.in 2011-11-18 18:04:27 +0000 | |||
4871 | @@ -2,11 +2,14 @@ | |||
4872 | 2 | name: memory/info | 2 | name: memory/info |
4873 | 3 | command: memory_info | 3 | command: memory_info |
4874 | 4 | _description: | 4 | _description: |
4880 | 5 | The following amount of memory was detected: | 5 | PURPOSE: |
4881 | 6 | . | 6 | This test checks the amount of memory that is detected |
4882 | 7 | $output | 7 | STEPS: |
4883 | 8 | . | 8 | 1. Click Test to see the amount of detected memory |
4884 | 9 | Is this correct? | 9 | INFO: |
4885 | 10 | $output | ||
4886 | 11 | VERIFICATION: | ||
4887 | 12 | Is the amount of detected memory correct? | ||
4888 | 10 | 13 | ||
4889 | 11 | plugin: shell | 14 | plugin: shell |
4890 | 12 | name: memory/check | 15 | name: memory/check |
4891 | 13 | 16 | ||
4892 | === modified file 'jobs/miscellanea.txt.in' | |||
4893 | --- jobs/miscellanea.txt.in 2011-09-29 13:12:01 +0000 | |||
4894 | +++ jobs/miscellanea.txt.in 2011-11-18 18:04:27 +0000 | |||
4895 | @@ -6,11 +6,12 @@ | |||
4896 | 6 | user: root | 6 | user: root |
4897 | 7 | command: cycle_vts | 7 | command: cycle_vts |
4898 | 8 | _description: | 8 | _description: |
4904 | 9 | Select Test to switch to another virtual terminal and then back to X. Your screen will change temporarily to a text console and then switch back to your current session. | 9 | PURPOSE: |
4905 | 10 | . | 10 | This test will check that the system can switch to a virtual terminal and back to X |
4906 | 11 | Note that this test may require you to enter your password. | 11 | STEPS: |
4907 | 12 | . | 12 | 1. Click "Test" to switch to another virtual terminal and then back to X |
4908 | 13 | Did the screen change temporarily to a text console? | 13 | VERIFICATION: |
4909 | 14 | Did your screen change temporarily to a text console and then switch back to your current session? | ||
4910 | 14 | 15 | ||
4911 | 15 | plugin: shell | 16 | plugin: shell |
4912 | 16 | name: miscellanea/fwts_test | 17 | name: miscellanea/fwts_test |
4913 | @@ -18,7 +19,7 @@ | |||
4914 | 18 | package.name == 'linux' | 19 | package.name == 'linux' |
4915 | 19 | package.name == 'fwts' | 20 | package.name == 'fwts' |
4916 | 20 | _description: | 21 | _description: |
4918 | 21 | Run Colin King's Firmware Test Suite automated tests. | 22 | Run Firmware Test Suite (fwts) automated tests. |
4919 | 22 | command: | 23 | command: |
4920 | 23 | fwts_test -l $CHECKBOX_DATA/fwts_results.log | 24 | fwts_test -l $CHECKBOX_DATA/fwts_results.log |
4921 | 24 | 25 | ||
4922 | @@ -39,6 +40,16 @@ | |||
4923 | 39 | plugin: manual | 40 | plugin: manual |
4924 | 40 | name: miscellanea/is_laptop | 41 | name: miscellanea/is_laptop |
4925 | 41 | _description: | 42 | _description: |
4927 | 42 | Is your system a laptop (or netbook)? | 43 | PURPOSE: |
4928 | 44 | This is to determine if we need to run tests specific to portable computers that may not apply to desktops. | ||
4929 | 45 | STEPS: | ||
4930 | 46 | Select "Yes" if your system is a laptop or netbook. Otherwise, select "No" | ||
4931 | 47 | |||
4932 | 48 | plugin: shell | ||
4933 | 49 | name: miscellanea/apport-directory | ||
4934 | 50 | requires: package.name == 'apport' | ||
4935 | 51 | command: ! test -d /var/crash || test $(find /var/crash -type f | wc -l) -eq 0 | ||
4936 | 52 | _description: | ||
4937 | 53 | This test checks /var/crash to see if there are any crash reports present. | ||
4938 | 43 | . | 54 | . |
4940 | 44 | Selecting Yes here will allow us to run tests specific to portable computers that may not apply to desktops. | 55 | If there are, this test will fail. |
4941 | 45 | 56 | ||
4942 | === modified file 'jobs/monitor.txt.in' | |||
4943 | --- jobs/monitor.txt.in 2011-09-14 21:16:02 +0000 | |||
4944 | +++ jobs/monitor.txt.in 2011-11-18 18:04:27 +0000 | |||
4945 | @@ -1,52 +1,71 @@ | |||
4946 | 1 | plugin: manual | 1 | plugin: manual |
4947 | 2 | name: monitor/vga | 2 | name: monitor/vga |
4948 | 3 | _description: | 3 | _description: |
4952 | 4 | If your system does not have a VGA port, please skip this test. | 4 | PURPOSE: |
4953 | 5 | . | 5 | This test will check your VGA port. Skip if your system does not have a VGA port. |
4954 | 6 | Connect a display (if not already connected) to the VGA port on your system. Is the image displayed correctly? | 6 | STEPS: |
4955 | 7 | 1. Connect a display (if not already connected) to the VGA port on your system | ||
4956 | 8 | VERIFICATION: | ||
4957 | 9 | Was the desktop displayed correctly on both screens? | ||
4958 | 7 | 10 | ||
4959 | 8 | plugin: manual | 11 | plugin: manual |
4960 | 9 | name: monitor/dvi | 12 | name: monitor/dvi |
4961 | 10 | _description: | 13 | _description: |
4965 | 11 | If your system does not have a DVI port, please skip this test. | 14 | PURPOSE: |
4966 | 12 | . | 15 | This test will check your DVI port. Skip if your system does not have a DVI port |
4967 | 13 | Connect a display (if not already connected) to the DVI port on your system. Is the image displayed correctly? | 16 | STEPS: |
4968 | 17 | 1. Connect a display (if not already connected) to the DVI port on your system | ||
4969 | 18 | VERIFICATION: | ||
4970 | 19 | Was the desktop displayed correctly on both screens? | ||
4971 | 14 | 20 | ||
4972 | 15 | plugin: manual | 21 | plugin: manual |
4973 | 16 | name: monitor/displayport | 22 | name: monitor/displayport |
4974 | 17 | _description: | 23 | _description: |
4978 | 18 | If your system does not have DisplayPort, please skip this test. | 24 | PURPOSE: |
4979 | 19 | . | 25 | This test will check your DisplayPort port. Skip if your system does not have a DisplayPort port |
4980 | 20 | Connect a display (if not already connected) to the DisplayPort on your system. Is the image displayed correctly? | 26 | STEPS: |
4981 | 27 | 1. Connect a display (if not already connected) to the DisplayPort port on your system | ||
4982 | 28 | VERIFICATION: | ||
4983 | 29 | Was the desktop displayed correctly on both screens? | ||
4984 | 21 | 30 | ||
4985 | 22 | plugin: manual | 31 | plugin: manual |
4986 | 23 | name: monitor/hdmi | 32 | name: monitor/hdmi |
4987 | 24 | _description: | 33 | _description: |
4991 | 25 | If your system does not have a HDMI port, please skip this test. | 34 | PURPOSE: |
4992 | 26 | . | 35 | This test will check your HDMI port. Skip if your system does not have a HDMI port |
4993 | 27 | Connect a display (if not already connected) to the HDMI port on your system. Is the image displayed correctly? | 36 | STEPS: |
4994 | 37 | 1. Connect a display (if not already connected) to the HDMI port on your system | ||
4995 | 38 | VERIFICATION: | ||
4996 | 39 | Was the desktop displayed correctly on both screens? | ||
4997 | 28 | 40 | ||
4998 | 29 | plugin: manual | 41 | plugin: manual |
4999 | 30 | name: monitor/svideo | 42 | name: monitor/svideo |
5000 | 31 | _description: | 43 | _description: |
Thank you for your work, I'm sponsoring it to precise but I can't set the merge request to merged since you targetted oneiric which is the wrong serie and launchpad will not let me edit it, could you do that?