Merge lp:~pwlars/lava-test/hwprofile into lp:lava-test/0.0

Proposed by Paul Larson
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
Reviewer Review Type Date Requested Status
Linaro Infrastructure Pending
Review via email: mp+31980@code.launchpad.net
To post a comment you must log in.
Revision history for this message
James Westby (james-w) wrote :

On Fri, 06 Aug 2010 18:25:59 -0000, Paul Larson <email address hidden> wrote:
> Paul Larson has proposed merging lp:~pwlars/abrek/hwprofile into lp:abrek.
>
> Requested reviews:
> Linaro Infrastructure (arm-infrastructure)
>
> --
> https://code.launchpad.net/~pwlars/abrek/hwprofile/+merge/31980
> 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.urlsplit(url).path
> filename = os.path.basename(urlpath)
> @@ -19,7 +21,24 @@
> raise RuntimeError("Could not retrieve %s" % url)
> return filename
>
> -def write_file(data,path):
> +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

Revision history for this message
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.

Revision history for this message
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

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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'])

Subscribers

People subscribed via source and target branches