Merge lp:~pwlars/lava-test/hwprofile into lp:lava-test/0.0
- hwprofile
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 21 |
Proposed branch: | lp:~pwlars/lava-test/hwprofile |
Merge into: | lp:lava-test/0.0 |
Diff against target: |
324 lines (+284/-2) 4 files modified
abrek/hwprofile.py (+184/-0) abrek/utils.py (+20/-1) tests/__init__.py (+2/-1) tests/test_hwprofile.py (+78/-0) |
To merge this branch: | bzr merge lp:~pwlars/lava-test/hwprofile |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Linaro Infrastructure | Pending | ||
Review via email: mp+31980@code.launchpad.net |
Commit message
Description of the change
James Westby (james-w) wrote : | # |
Paul Larson (pwlars) wrote : | # |
> Do you want to error if there are fake files but the path isn't in them?
> That would increase test isolation, but if you intend to read a mix of
> files then it obviously won't work.
No, because I could have places where I may want or need to fake one file, but the others are fine to read from the real path.
James Westby (james-w) wrote : | # |
On Fri, 06 Aug 2010 20:56:11 -0000, Paul Larson <email address hidden> wrote:
> > Do you want to error if there are fake files but the path isn't in them?
> > That would increase test isolation, but if you intend to read a mix of
> > files then it obviously won't work.
> No, because I could have places where I may want or need to fake one file, but the others are fine to read from the real path.
Ok.
You maybe want to consider a whitelist, but I'm fine with what you have
now.
Thanks,
James
Preview Diff
1 | === added file 'abrek/hwprofile.py' |
2 | --- abrek/hwprofile.py 1970-01-01 00:00:00 +0000 |
3 | +++ abrek/hwprofile.py 2010-08-06 18:25:58 +0000 |
4 | @@ -0,0 +1,184 @@ |
5 | +import commands |
6 | +import os |
7 | +import re |
8 | +from utils import read_file |
9 | + |
10 | +INTEL_KEYMAP = { |
11 | + 'vendor_id': 'cpu_vendor_name', |
12 | + 'cpu family': 'cpu_family', |
13 | + 'model': 'cpu_model', |
14 | + 'model name': 'cpu_model_name', |
15 | + 'stepping': 'cpu_stepping', |
16 | + 'cpu MHz': 'cpu_mhz', |
17 | + 'flags': 'cpu_features', |
18 | +} |
19 | + |
20 | +INTEL_VALMAP = { |
21 | + 'cpu family': int, |
22 | + 'model': int, |
23 | + 'stepping': int, |
24 | + 'cpu MHz': float, |
25 | + 'flags': lambda value: list(sorted(value.split())), |
26 | +} |
27 | + |
28 | +ARM_KEYMAP = { |
29 | + 'Processor': 'cpu_model_name', |
30 | + 'Features': 'cpu_features', |
31 | + 'CPU implementer': 'cpu_implementer', |
32 | + 'CPU architecture': 'cpu_architecture', |
33 | + 'CPU variant': 'cpu_variant', |
34 | + 'CPU part': 'cpu_part', |
35 | + 'CPU revision': 'cpu_revision', |
36 | +} |
37 | + |
38 | +ARM_VALMAP = { |
39 | + 'CPU implementer': lambda value: int(value, 16), |
40 | + 'CPU architecture': int, |
41 | + 'CPU variant': lambda value: int(value, 16), |
42 | + 'CPU part': lambda value: int(value, 16), |
43 | + 'CPU revision': int, |
44 | + 'Features': lambda value: list(sorted(value.split())) |
45 | +} |
46 | + |
47 | + |
48 | +def _translate_cpuinfo(keymap, valmap, key, value): |
49 | + """ |
50 | + Translate a key and value using keymap and valmap passed in |
51 | + """ |
52 | + newkey = keymap.get(key, key) |
53 | + newval = valmap.get(key, lambda x: x)(value) |
54 | + return newkey, newval |
55 | + |
56 | +def get_cpu_devs(): |
57 | + """ |
58 | + Return a list of CPU devices |
59 | + """ |
60 | + pattern = re.compile('^(?P<key>.+?)\s*:\s*(?P<value>.*)$') |
61 | + cpunum = 0 |
62 | + devices = [] |
63 | + cpudevs = [] |
64 | + cpudevs.append({}) |
65 | + machine = os.uname()[-1] |
66 | + if machine in ('i686', 'x86_64'): |
67 | + keymap, valmap = INTEL_KEYMAP, INTEL_VALMAP |
68 | + elif machine.startswith('arm'): |
69 | + keymap, valmap = ARM_KEYMAP, ARM_VALMAP |
70 | + |
71 | + cpuinfo = read_file("/proc/cpuinfo") |
72 | + for line in cpuinfo.splitlines(): |
73 | + match = pattern.match(line) |
74 | + if match: |
75 | + key, value = match.groups() |
76 | + key, value = _translate_cpuinfo(keymap, valmap, |
77 | + key, value) |
78 | + if cpudevs[cpunum].get(key): |
79 | + cpunum += 1 |
80 | + cpudevs.append({}) |
81 | + cpudevs[cpunum][key] = value |
82 | + for c in range(len(cpudevs)): |
83 | + device = {} |
84 | + device['device_type'] = 'device.cpu' |
85 | + device['attributes'] = 'Processor #{0}'.format(c) |
86 | + device['desc'] = cpudevs[c] |
87 | + devices.append(device) |
88 | + return devices |
89 | + |
90 | + |
91 | +def get_board_devs(): |
92 | + """ |
93 | + Return a list of board devices |
94 | + """ |
95 | + devices = [] |
96 | + desc = {} |
97 | + device = {} |
98 | + machine = os.uname()[-1] |
99 | + if machine in ('i686', 'x86_64'): |
100 | + name = read_file('/sys/class/dmi/id/board_name') or None |
101 | + vendor = read_file('/sys/class/dmi/id/board_vendor') or None |
102 | + version = read_file('/sys/class/dmi/id/board_version') or None |
103 | + if name: |
104 | + device['attributes'] = name.strip() |
105 | + if vendor: |
106 | + desc['vendor'] = vendor.strip() |
107 | + if version: |
108 | + desc['version'] = version.strip() |
109 | + elif machine.startswith('arm'): |
110 | + cpuinfo = read_file("/proc/cpuinfo") |
111 | + if cpuinfo is None: |
112 | + return devices |
113 | + pattern = re.compile("^Hardware\s*:\s*(?P<hardware>.+)$", re.M) |
114 | + match = pattern.search(cpuinfo) |
115 | + if match is None: |
116 | + return devices |
117 | + desc['hardware'] = match.group('hardware') |
118 | + else: |
119 | + return devices |
120 | + device['desc'] = desc |
121 | + device['device_type'] = 'device.board' |
122 | + devices.append(device) |
123 | + return devices |
124 | + |
125 | +def get_mem_devs(): |
126 | + """ Return a list of memory devices |
127 | + |
128 | + This returns up to two items, one for physical RAM and another for swap |
129 | + """ |
130 | + pattern = re.compile('^(?P<key>.+?)\s*:\s*(?P<value>.+) kB$', re.M) |
131 | + |
132 | + devices = [] |
133 | + meminfo = read_file("/proc/meminfo") |
134 | + for match in pattern.finditer(meminfo): |
135 | + key, value = match.groups() |
136 | + if key not in ('MemTotal', 'SwapTotal'): |
137 | + continue |
138 | + capacity = int(value) << 10 #Kernel reports in 2^10 units |
139 | + if capacity == 0: |
140 | + continue |
141 | + if key == 'MemTotal': |
142 | + kind = 'RAM' |
143 | + else: |
144 | + kind = 'swap' |
145 | + name = "{capacity}MiB of {kind}".format( |
146 | + capacity=capacity >> 20, kind=kind) |
147 | + device = {} |
148 | + device['attributes'] = name |
149 | + device['desc'] = {'capacity': capacity, 'kind': kind} |
150 | + device['device_type'] = "device.mem" |
151 | + devices.append(device) |
152 | + return devices |
153 | + |
154 | +def get_usb_devs(): |
155 | + """ |
156 | + Return a list of usb devices |
157 | + """ |
158 | + pattern = re.compile( |
159 | + "^Bus \d{3} Device \d{3}: ID (?P<vendor_id>[0-9a-f]{4}):" |
160 | + "(?P<product_id>[0-9a-f]{4}) (?P<name>.*)$") |
161 | + devices = [] |
162 | + for line in commands.getoutput('lsusb').splitlines(): |
163 | + match = pattern.match(line) |
164 | + if match: |
165 | + vendor_id, product_id, name = match.groups() |
166 | + desc = {} |
167 | + device = {} |
168 | + desc['vendor_id'] = int(vendor_id, 16) |
169 | + desc['product_id'] = int(product_id, 16) |
170 | + device['desc'] = desc |
171 | + device['attributes'] = name |
172 | + device['device_type'] = 'device.usb' |
173 | + devices.append(device) |
174 | + return devices |
175 | + |
176 | +def get_hw_context(): |
177 | + """ |
178 | + Return a dict with all of the hardware profile information gathered |
179 | + """ |
180 | + hw_context = {} |
181 | + devices = [] |
182 | + devices.extend(get_cpu_devs()) |
183 | + devices.extend(get_board_devs()) |
184 | + devices.extend(get_mem_devs()) |
185 | + devices.extend(get_usb_devs()) |
186 | + hw_context['devices'] = devices |
187 | + return hw_context |
188 | + |
189 | |
190 | === modified file 'abrek/utils.py' |
191 | --- abrek/utils.py 2010-06-29 16:27:42 +0000 |
192 | +++ abrek/utils.py 2010-08-06 18:25:58 +0000 |
193 | @@ -3,6 +3,8 @@ |
194 | import urllib2 |
195 | import urlparse |
196 | |
197 | +_fake_files = None |
198 | + |
199 | def geturl(url, path=""): |
200 | urlpath = urlparse.urlsplit(url).path |
201 | filename = os.path.basename(urlpath) |
202 | @@ -19,7 +21,24 @@ |
203 | raise RuntimeError("Could not retrieve %s" % url) |
204 | return filename |
205 | |
206 | -def write_file(data,path): |
207 | +def write_file(data, path): |
208 | with open(path, "w") as fd: |
209 | fd.write(data) |
210 | |
211 | +def read_file(path): |
212 | + global _fake_files |
213 | + if _fake_files is not None: |
214 | + if path in _fake_files: |
215 | + return _fake_files[path] |
216 | + with open(path) as fd: |
217 | + data = fd.read() |
218 | + return data |
219 | + |
220 | +def fake_file(path, data): |
221 | + """ |
222 | + Set up a fake file to be read with read_file() in testing |
223 | + """ |
224 | + global _fake_files |
225 | + if _fake_files is None: |
226 | + _fake_files = {} |
227 | + _fake_files[path] = data |
228 | |
229 | === modified file 'tests/__init__.py' |
230 | --- tests/__init__.py 2010-08-04 17:29:48 +0000 |
231 | +++ tests/__init__.py 2010-08-06 18:25:58 +0000 |
232 | @@ -6,7 +6,8 @@ |
233 | 'tests.test_abrektestinstaller', |
234 | 'tests.test_abrektestrunner', |
235 | 'tests.test_abrektestparser', |
236 | - 'tests.test_swprofile'] |
237 | + 'tests.test_swprofile', |
238 | + 'tests.test_hwprofile'] |
239 | loader = unittest.TestLoader() |
240 | suite = loader.loadTestsFromNames(module_names) |
241 | return suite |
242 | |
243 | === added file 'tests/test_hwprofile.py' |
244 | --- tests/test_hwprofile.py 1970-01-01 00:00:00 +0000 |
245 | +++ tests/test_hwprofile.py 2010-08-06 18:25:58 +0000 |
246 | @@ -0,0 +1,78 @@ |
247 | +import unittest |
248 | + |
249 | +import abrek.hwprofile |
250 | +from abrek.utils import fake_file |
251 | + |
252 | +class AptCache: |
253 | + def __init__(self, packages=[]): |
254 | + self.packages = packages |
255 | + |
256 | +ARM_CPUINFO_FILE = """Processor : ARMv7 Processor rev 3 (v7l) |
257 | +BogoMIPS : 483.16 |
258 | +Features : swp half thumb fastmult vfp edsp neon vfpv3* |
259 | +CPU implementer : 0x41 |
260 | +CPU architecture: 7 |
261 | +CPU variant : 0x1 |
262 | +CPU part : 0xc08 |
263 | +CPU revision : 3 |
264 | + |
265 | +Hardware : OMAP3 Beagle Board |
266 | +Revision : 0020 |
267 | +Serial : 0000000000000000""" |
268 | + |
269 | +FAKE_BOARDNAME_FILE = "XXXXXXX" |
270 | + |
271 | +FAKE_MEMINFO_FILE = """MemTotal: 238220 kB |
272 | +MemFree: 45992 kB |
273 | +Buffers: 4564 kB |
274 | +Cached: 73220 kB |
275 | +SwapCached: 15536 kB |
276 | +Active: 48460 kB |
277 | +Inactive: 122624 kB |
278 | +Active(anon): 18788 kB |
279 | +Inactive(anon): 75888 kB |
280 | +Active(file): 29672 kB |
281 | +Inactive(file): 46736 kB |
282 | +Unevictable: 0 kB |
283 | +Mlocked: 0 kB |
284 | +SwapTotal: 524284 kB |
285 | +SwapFree: 458436 kB |
286 | +Dirty: 0 kB |
287 | +Writeback: 0 kB |
288 | +AnonPages: 81076 kB |
289 | +Mapped: 9556 kB |
290 | +Shmem: 1376 kB |
291 | +Slab: 11072 kB |
292 | +SReclaimable: 4408 kB |
293 | +SUnreclaim: 6664 kB |
294 | +KernelStack: 1656 kB |
295 | +PageTables: 2748 kB |
296 | +NFS_Unstable: 0 kB |
297 | +Bounce: 0 kB |
298 | +WritebackTmp: 0 kB |
299 | +CommitLimit: 643392 kB |
300 | +Committed_AS: 398812 kB |
301 | +VmallocTotal: 647168 kB |
302 | +VmallocUsed: 1936 kB |
303 | +VmallocChunk: 643316 kB""" |
304 | + |
305 | +class HwprofileTests(unittest.TestCase): |
306 | + def test_get_cpu_devs(self): |
307 | + fake_file('/proc/cpuinfo', ARM_CPUINFO_FILE) |
308 | + devs = abrek.hwprofile.get_cpu_devs() |
309 | + processor = "ARMv7 Processor rev 3 (v7l)" |
310 | + self.assertEqual(processor, devs[0]['desc']['Processor']) |
311 | + |
312 | + def test_get_board_devs(self): |
313 | + fake_file('/sys/class/dmi/id/board_name', FAKE_BOARDNAME_FILE) |
314 | + devs = abrek.hwprofile.get_board_devs() |
315 | + self.assertEqual(FAKE_BOARDNAME_FILE, devs[0]['attributes']) |
316 | + |
317 | + def test_get_mem_devs(self): |
318 | + fake_file('/proc/meminfo', FAKE_MEMINFO_FILE) |
319 | + devs = abrek.hwprofile.get_mem_devs() |
320 | + self.assertEqual(243937280, devs[0]['desc']['capacity']) |
321 | + |
322 | + def test_get_usb_devs(self): |
323 | + devs = abrek.hwprofile.get_usb_devs() |
324 | + self.assertEqual('device.usb', devs[0]['device_type']) |
On Fri, 06 Aug 2010 18:25:59 -0000, Paul Larson <email address hidden> wrote: ture) /code.launchpad .net/~pwlars/ abrek/hwprofile /+merge/ 31980 urlsplit( url).path basename( urlpath) data,path) :
> Paul Larson has proposed merging lp:~pwlars/abrek/hwprofile into lp:abrek.
>
> Requested reviews:
> Linaro Infrastructure (arm-infrastruc
>
> --
> https:/
> Your team Linaro Infrastructure is requested to review the proposed merge of lp:~pwlars/abrek/hwprofile into lp:abrek.
> === modified file 'abrek/utils.py'
> --- abrek/utils.py 2010-06-29 16:27:42 +0000
> +++ abrek/utils.py 2010-08-06 18:25:58 +0000
> @@ -3,6 +3,8 @@
> import urllib2
> import urlparse
>
> +_fake_files = None
> +
> def geturl(url, path=""):
> urlpath = urlparse.
> filename = os.path.
> @@ -19,7 +21,24 @@
> raise RuntimeError("Could not retrieve %s" % url)
> return filename
>
> -def write_file(
> +def write_file(data, path):
> with open(path, "w") as fd:
> fd.write(data)
>
> +def read_file(path):
> + global _fake_files
> + if _fake_files is not None:
> + if path in _fake_files:
> + return _fake_files[path]
> + with open(path) as fd:
> + data = fd.read()
> + return data
Do you want to error if there are fake files but the path isn't in them?
That would increase test isolation, but if you intend to read a mix of
files then it obviously won't work.
Otherwise this looks fine.
Thanks,
James