summaryrefslogtreecommitdiffstats
path: root/src/hardware
diff options
context:
space:
mode:
authorRobin Hack <rhack@redhat.com>2014-01-21 08:07:03 +0100
committerRobin Hack <rhack@redhat.com>2014-01-21 08:07:03 +0100
commitee8aafdece792b36a9483b51cc40579942222a65 (patch)
treedf078da3a1eca5f66c051388096b679024133375 /src/hardware
parent7dc02e6dd0e5a6ae2b3b440b1d3762629210288b (diff)
downloadopenlmi-providers-ee8aafdece792b36a9483b51cc40579942222a65.tar.gz
openlmi-providers-ee8aafdece792b36a9483b51cc40579942222a65.tar.xz
openlmi-providers-ee8aafdece792b36a9483b51cc40579942222a65.zip
Hardware: Added upstream test suite.
Diffstat (limited to 'src/hardware')
-rw-r--r--src/hardware/test/README18
-rw-r--r--src/hardware/test/TestHardware.py176
-rw-r--r--src/hardware/test/TestHardwareBase.py356
3 files changed, 550 insertions, 0 deletions
diff --git a/src/hardware/test/README b/src/hardware/test/README
new file mode 100644
index 0000000..a375d9f
--- /dev/null
+++ b/src/hardware/test/README
@@ -0,0 +1,18 @@
+Testing
+=======
+
+Dependencies
+------------
+ * python-hwdata
+
+Preparation
+-----------
+``lmi.test`` module must be on python path. The easiest way to get it there is
+to export ``PYTHONPATH`` environment variable like this: ::
+
+ export PYTHONPATH="${PATH_TO_GIT_ROOT}/src/python"
+
+Running tests
+-------------
+For example: ::
+ nosetests -v ./TestHardware.py
diff --git a/src/hardware/test/TestHardware.py b/src/hardware/test/TestHardware.py
new file mode 100644
index 0000000..4c5ae59
--- /dev/null
+++ b/src/hardware/test/TestHardware.py
@@ -0,0 +1,176 @@
+# Copyright (C) 2012-2013 Red Hat, Inc. All rights reserved.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+#
+# Authors: Robin Hack <rhack@redhat.com>
+#
+
+from TestHardwareBase import *
+from lmi.shell import LMIInstance
+import os
+import unittest
+
+class TestHardwareProcessor(HardwareProcessorTestCase):
+ """
+ Class for testing LMI_Processor class
+ """
+
+ CLASS_NAME = "LMI_Processor"
+
+ def test_processor_flags_x86(self):
+ """
+ Hardware: Test for processor flags.
+ This test is valid only on x86 architectures.
+ """
+
+ cpu_instances = self.cim_class.instances()
+ self.assertTrue(cpu_instances)
+
+ # same count of cpus?
+ cpu_info = self.get_cpu_info()
+ self.assertTrue(cpu_info)
+
+ self.assertEqual(len(cpu_instances), len(cpu_info))
+
+ my_arch = self.get_my_arch()
+
+ cpu_num = 0
+ for cpu in cpu_instances:
+
+ # same architecture on all cpus?
+ self.assertEqual(my_arch, cpu.Architecture)
+
+ # same flags?
+ cpu_flags = cpu_info[cpu_num]["flags"].split()
+ cpu_flags = map (lambda f: self.proc_flag_table[f], cpu_flags)
+ self.assertTrue (cpu_flags)
+
+ lmi_cpu_flags = cpu.Flags
+ self.assertTrue (lmi_cpu_flags)
+
+ # same flags?
+ self.assertEqual(sorted(cpu_flags), sorted(lmi_cpu_flags))
+ ++cpu_num
+
+class TestHardwareMemory(HardwareMemoryTestCase):
+ """
+ Class for testing LMI_Memory class
+ """
+
+ CLASS_NAME = "LMI_Memory"
+
+ def test_huge_page_sizes(self):
+ """ Get supported sizes of hugepages """
+ lmi_mem_instances = self.cim_class.instances()
+ self.assertTrue(lmi_mem_instances)
+
+ huge_pages_sizes = self.get_huge_pages_sizes()
+ self.assertEqual(len(lmi_mem_instances), len(huge_pages_sizes))
+
+ for lmi_mem in lmi_mem_instances:
+ self.assertEqual(lmi_mem.SupportedHugeMemoryPageSizes, huge_pages_sizes)
+
+ def test_memory_page_size(self):
+ lmi_mem_instance = self.cim_class.first_instance()
+ self.assertTrue(lmi_mem_instance)
+
+ page_size = os.sysconf("SC_PAGE_SIZE") / 1024
+ lmi_page_size = lmi_mem_instance.StandardMemoryPageSize
+
+ self.assertEqual (page_size, lmi_page_size)
+
+
+class TestHardwarePhysicalMemory(HardwarePhysicalMemoryTestCase):
+ """
+ Class for testing LMI_PhysicalMemory class
+ """
+
+ CLASS_NAME = "LMI_PhysicalMemory"
+
+ def setUp(self):
+ self.lmi_phymem_instances = self.cim_class.instances()
+ self.assertTrue(self.lmi_phymem_instances)
+
+ def test_physical_memory_sizes(self):
+ phymem_sizes = self.get_physical_memory_sizes()
+ lmi_phymem_sizes = map(lambda x: x.Capacity, self.lmi_phymem_instances)
+
+ self.assertEqual(sorted(lmi_phymem_sizes), sorted(phymem_sizes))
+
+ def test_physical_memory_current_speed(self):
+ cur_speeds = self.get_physical_memory_current_speed()
+ lmi_phymem_cur_speeds = map(lambda x: x.Speed, self.lmi_phymem_instances)
+
+ self.assertEqual(sorted(lmi_phymem_cur_speeds), sorted(cur_speeds))
+
+
+class TestHardwareBaseboard(HardwareBaseboardTestCase):
+ """
+ Class for testing LMI_Baseboard class
+ """
+
+ CLASS_NAME = "LMI_Baseboard"
+
+ def setUp(self):
+ self.lmi_baseboard_instances = self.cim_class.instances()
+ # On virtual machines there can be blank
+ #self.assertTrue(self.lmi_baseboard_instances)
+
+ def test_baseboard_basic_info(self):
+ manufacturer = self.get_baseboard_manufacturers()
+ serials = self.get_baseboard_serials()
+
+ lmi_manufacturers = map(lambda x: x.Manufacturer, self.lmi_baseboard_instances)
+ lmi_serials = map(lambda x: x.SerialNumber, self.lmi_baseboard_instances)
+
+ self.assertEqual(sorted(lmi_manufacturers), sorted(manufacturer))
+ self.assertEqual(sorted(lmi_serials), sorted(serials))
+
+
+class TestHardwarePCIDevice(HardwarePCITestCase):
+ """
+ Class for testing LMI_PCIDevice class
+ """
+
+ CLASS_NAME = "LMI_PCIDevice"
+
+ def setUp(self):
+ self.lmi_pci_devices_instances = self.cim_class.instances()
+ self.assertTrue(self.lmi_pci_devices_instances)
+
+ def test_pci_devices(self):
+ lmi_pci_devices = map(lambda x: (x.DeviceID, x.PCIDeviceID, x.ClassCode, x.VendorID, x.VendorName, x.PCIDeviceName, x.SubsystemID, x.SubsystemVendorID, x.SubsystemVendorName), self.lmi_pci_devices_instances)
+ pci_devices = self.get_pci_devices(self.IS_DEVICE)
+
+ self.assertEqual(sorted(lmi_pci_devices), sorted(pci_devices))
+
+
+class TestHardwarePCIBridge(HardwarePCITestCase):
+ """
+ Class for testing LMI_PCIBridge class
+ """
+
+ CLASS_NAME = "LMI_PCIBridge"
+
+ def setUp(self):
+ self.lmi_pci_bridges_instances = self.cim_class.instances()
+ self.assertTrue(self.lmi_pci_bridges_instances)
+
+
+ def test_pci_bridges(self):
+ lmi_pci_bridges = map(lambda x: (x.DeviceID, x.PCIDeviceID, x.ClassCode, x.VendorID, x.VendorName, x.PCIDeviceName, x.SubsystemID, x.SubsystemVendorID, x.SubsystemVendorName), self.lmi_pci_bridges_instances)
+ pci_bridges = self.get_pci_devices(self.IS_BRIDGE)
+
+ self.assertEqual(sorted(lmi_pci_bridges), sorted(pci_bridges))
diff --git a/src/hardware/test/TestHardwareBase.py b/src/hardware/test/TestHardwareBase.py
new file mode 100644
index 0000000..71ecfe9
--- /dev/null
+++ b/src/hardware/test/TestHardwareBase.py
@@ -0,0 +1,356 @@
+# -*- encoding: utf-8 -*-
+# Copyright (C) 2012-2013 Red Hat, Inc. All rights reserved.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+#
+# Authors: Robin Hack <rhack@redhat.com>
+#
+"""
+Common utilities and base class for all hardware tests.
+"""
+
+from collections import OrderedDict
+from lmi.test.lmibase import LmiTestCase
+import os
+import re
+import subprocess
+from hwdata import PCI
+
+class HardwareTestCase(LmiTestCase):
+ """
+ Base class for all LMI Hardware test classes.
+ """
+ USE_EXCEPTIONS = True
+
+ @classmethod
+ def setUpClass(cls):
+ LmiTestCase.setUpClass.im_func(cls)
+ cls.dmi_output_cached_type = -1
+
+ def get_dmi_output(self, type_p):
+ if self.dmi_output_cached_type != type_p:
+ self.dmi_output_cache = subprocess.check_output("dmidecode -t %d" % type_p, shell=True).split("\n")
+ self.dmi_output_cached_type = type_p
+ return self.dmi_output_cache
+
+
+class HardwareProcessorTestCase(HardwareTestCase):
+ """
+ Base class for all LMI ProcessorHardware test classes.
+ """
+ # this is stolen from:
+ # linux/arch/x86/include/asm/cpufeature.h
+ proc_flag_table = {
+ 'fpu' : 0,
+ 'vme' : 1,
+ 'de' : 2,
+ 'pse' : 3,
+ 'tsc' : 4,
+ 'msr' : 5,
+ 'pae' : 6,
+ 'mce' : 7,
+ 'cx8' : 8,
+ 'apic' : 9,
+ 'sep' : 11,
+ 'mtrr' : 12,
+ 'pge' : 13,
+ 'mca' : 14,
+ 'cmov' : 15,
+ 'pat' : 16,
+ 'pse36' : 17,
+ 'pn' : 18,
+ 'clflush' : 19,
+ 'dts' : 21,
+ 'acpi' : 22,
+ 'mmx' : 23,
+ 'fxsr' : 24,
+ 'sse' : 25,
+ 'sse2' : 26,
+ 'ss' : 27,
+ 'ht' : 28,
+ 'tm' : 29,
+ 'ia64' : 30,
+ 'pbe' : 31,
+ 'syscall' : 43,
+ 'mp' : 51,
+ 'nx' : 52,
+ 'mmxext' : 54,
+ 'fxsr_opt' : 57,
+ 'pdpe1gb' : 58,
+ 'rdtscp' : 59,
+ 'lm' : 61,
+ '3dnowext' : 62,
+ '3dnow' : 63,
+ 'recovery' : 64,
+ 'longrun' : 65,
+ 'lrti' : 67,
+ 'cxmmx' : 96,
+ 'k6_mtrr' : 97,
+ 'cyrix_arr' : 98,
+ 'centaur_mcr' : 99,
+ 'k8' : 100,
+ 'k7' : 101,
+ 'p3' : 102,
+ 'p4' : 103,
+ 'constant_tsc' : 104,
+ 'up' : 105,
+ 'fxsave_leak' : 106,
+ 'arch_perfmon' : 107,
+ 'pebs' : 108,
+ 'bts' : 109,
+ 'syscall32' : 110,
+ 'sysenter32' : 111,
+ 'rep_good' : 112,
+ 'mfence_rdtsc' : 113,
+ 'lfence_rdtsc' : 114,
+ '11ap' : 115,
+ 'nopl' : 116,
+ 'xtopology' : 118,
+ 'tsc_reliable' : 119,
+ 'nonstop_tsc' : 120,
+ 'clflush_monitor' : 121,
+ 'extd_apicid' : 122,
+ 'amd_dcm' : 123,
+ 'aperfmperf' : 124,
+ 'eagerfpu' : 125,
+ 'pni' : 128,
+ 'pclmulqdq' : 129,
+ 'dtes64' : 130,
+ 'monitor' : 131,
+ 'ds_cpl' : 132,
+ 'vmx' : 133,
+ 'smx' : 134,
+ 'est' : 135,
+ 'tm2' : 136,
+ 'ssse3' : 137,
+ 'cid' : 138,
+ 'fma' : 140,
+ 'cx16' : 141,
+ 'xtpr' : 142,
+ 'pdcm' : 143,
+ 'pcid' : 145,
+ 'dca' : 146,
+ 'sse4_1' : 147,
+ 'sse4_2' : 148,
+ 'x2apic' : 149,
+ 'movbe' : 150,
+ 'popcnt' : 151,
+ 'tsc_deadline_timer' : 152,
+ 'aes' : 153,
+ 'xsave' : 154,
+ 'osxsave' : 155,
+ 'avx' : 156,
+ 'f16c' : 157,
+ 'rdrand' : 158,
+ 'hypervisor' : 159,
+ 'rng' : 162,
+ 'rng_en' : 163,
+ 'ace' : 166,
+ 'ace_en' : 167,
+ 'ace2' : 168,
+ 'ace2_en' : 169,
+ 'phe' : 170,
+ 'phe_en' : 171,
+ 'pmm' : 172,
+ 'pmm_en' : 173,
+ 'lahf_lm' : 192,
+ 'cmp_legacy' : 193,
+ 'svm' : 194,
+ 'extapic' : 195,
+ 'cr8_legacy' : 196,
+ 'abm' : 197,
+ 'sse4a' : 198,
+ 'misalignsse' : 199,
+ '3dnowprefetch' : 200,
+ 'osvw' : 201,
+ 'ibs' : 202,
+ 'xop' : 203,
+ 'skinit' : 204,
+ 'wdt' : 205,
+ 'lwp' : 207,
+ 'fma4' : 208,
+ 'tce' : 209,
+ 'nodeid_msr' : 211,
+ 'tbm' : 213,
+ 'topoext' : 214,
+ 'perfctr_core' : 215,
+ 'ida' : 224,
+ 'arat' : 225,
+ 'cpb' : 226,
+ 'epb' : 227,
+ 'xsaveopt' : 228,
+ 'pln' : 229,
+ 'pts' : 230,
+ 'dtherm' : 231,
+ 'hw_pstate' : 232,
+ 'tpr_shadow' : 256,
+ 'vnmi' : 257,
+ 'flexpriority' : 258,
+ 'ept' : 259,
+ 'vpid' : 260,
+ 'npt' : 261,
+ 'lbrv' : 262,
+ 'svm_lock' : 263,
+ 'nrip_save' : 264,
+ 'tsc_scale' : 265,
+ 'vmcb_clean' : 266,
+ 'flushbyasid' : 267,
+ 'decodeassists' : 268,
+ 'pausefilter' : 269,
+ 'pfthreshold' : 270,
+ 'fsgsbase' : 288,
+ 'tsc_adjust' : 289,
+ 'bmi1' : 291,
+ 'hle' : 292,
+ 'avx2' : 293,
+ 'smep' : 295,
+ 'bmi2' : 296,
+ 'erms' : 297,
+ 'invpcid' : 298,
+ 'rtm' : 299,
+ 'rdseed' : 306,
+ 'adx' : 307,
+ 'smap' : 308
+ }
+
+ # stolen from: http://amitsaha.github.io/site/notes/articles/python_linux/article.html
+ def get_cpu_info(self):
+ """
+ Return the information in /proc/cpuinfo
+ as a dictionary in the following format:
+ cpu_info[0]={...}
+ cpu_info[1]={...}
+ """
+ cpu_info = OrderedDict()
+ proc_info = OrderedDict()
+ nprocs = 0
+ with open('/proc/cpuinfo') as f:
+ for line in f:
+ if not line.strip():
+ # end of one processor
+ cpu_info[nprocs] = proc_info
+ nprocs = nprocs+1
+ # Reset
+ proc_info = OrderedDict()
+ else:
+ if len(line.split(':')) == 2:
+ proc_info[line.split(':')[0].strip()] = line.split(':')[1].strip()
+ else:
+ proc_info[line.split(':')[0].strip()] = ''
+ return cpu_info
+
+ def get_my_arch(self):
+ return os.uname()[4]
+
+
+class HardwareMemoryTestCase(HardwareTestCase):
+
+ def get_huge_pages_sizes(self):
+ # regexp is perfect because:
+ # ./mm/hugetlb.c: snprintf(h->name, HSTATE_NAME_LEN, "hugepages-%lukB", huge_page_size(h)/1024);
+
+ r = re.compile('hugepages-(\d+)kB')
+ dirs = os.listdir("/sys/kernel/mm/hugepages/")
+ huge_pages_sizes = []
+ for dir in dirs:
+ huge_pages_sizes.append(int(r.findall(dir)[0]))
+ return huge_pages_sizes
+
+
+class HardwarePhysicalMemoryTestCase(HardwareTestCase):
+
+ # return physical memory size in bytes
+ def get_physical_memory_sizes(self):
+ dmidecode_raw = self.get_dmi_output(17)
+ mem_sizes = filter (lambda x: "Size: " in x, dmidecode_raw)
+ mem_sizes = filter (lambda x: "Size: No Module Installed" not in x, mem_sizes)
+ mem_sizes = [(int(x.split(" ")[1]) * 1024 * 1024) for x in mem_sizes]
+ return mem_sizes
+
+ def get_physical_memory_current_speed(self):
+ dmidecode_raw = self.get_dmi_output(6)
+ current_speed = filter (lambda x: "Current Speed: " in x, dmidecode_raw)
+ current_speed = [int(x.split(" ")[2]) for x in current_speed]
+ if not current_speed:
+ current_speed.append(0)
+ return current_speed
+
+
+class HardwareBaseboardTestCase(HardwareTestCase):
+
+ def get_baseboard_manufacturers(self):
+ dmidecode_raw = self.get_dmi_output(2)
+ manufacturers = filter (lambda x: "Manufacturer: " in x, dmidecode_raw)
+ print manufacturers
+ manufacturers = [x.split(" ")[1] for x in manufacturers]
+ return manufacturers
+
+ def get_baseboard_serials(self):
+ dmidecode_raw = self.get_dmi_output(2)
+ serials = filter (lambda x: "Serial Number: " in x, dmidecode_raw)
+ serials = [x.split(" ")[1] for x in serials]
+ return serials
+
+
+class HardwarePCITestCase(HardwareTestCase):
+
+ def get_pci_device_attr(self, device, attr_p):
+ f = open ("%s/%s/%s" % ("/sys/bus/pci/devices/", device, attr_p), "r")
+ attr = f.readline ()
+ f.close()
+ return attr
+
+ IS_BRIDGE = 1 << 0
+ IS_DEVICE = 1 << 1
+ IS_BOTH = (IS_BRIDGE | IS_DEVICE)
+
+ def get_pci_devices(self, mask):
+ pci_devices = []
+ for device in os.listdir("/sys/bus/pci/devices/"):
+ device_class = self.get_pci_device_attr(device, "class")
+ vendor_id = self.get_pci_device_attr(device, "vendor")
+ device_id = self.get_pci_device_attr(device, "device")
+ subsystem_device_id = self.get_pci_device_attr(device, "subsystem_device")
+ subsystem_vendor_id = self.get_pci_device_attr(device, "subsystem_vendor")
+ # Is device bridge?
+
+ is_bridge = ((int(device_class, 16) >> 16) == 0x06)
+ device = device.replace("0000:","")
+
+ if (mask & self.IS_BRIDGE):
+ if (is_bridge):
+ pci_devices.append((device, int(device_id, 16), int(device_class, 16) >> 16, int(vendor_id, 16), self.lookup_pci_vendor(vendor_id), self.lookup_pci_name(vendor_id, device_id), int(subsystem_device_id, 16), int(subsystem_vendor_id, 16), self.lookup_pci_vendor(subsystem_vendor_id)))
+ continue
+
+ if (mask & self.IS_DEVICE):
+ if (not is_bridge):
+ pci_devices.append((device, int(device_id, 16), int(device_class, 16) >> 16, int(vendor_id, 16), self.lookup_pci_vendor(vendor_id), self.lookup_pci_name(vendor_id, device_id), int(subsystem_device_id, 16), int(subsystem_vendor_id, 16), self.lookup_pci_vendor(subsystem_vendor_id)))
+ continue
+ return pci_devices
+
+
+ def lookup_pci_vendor(self, vendor_id):
+ pci = PCI()
+ # Convert to string without conversion to decimal.
+ # Achieve format of 4 hex numbers.
+ vendor_id = "%.4x" % int(vendor_id, 16)
+ return pci.get_vendor(vendor_id)
+
+
+ def lookup_pci_name(self, vendor_id, device_id):
+ pci = PCI()
+ vendor_id = "%.4x" % int(vendor_id, 16)
+ device_id = "%.4x" % int(device_id, 16)
+ return pci.get_device(vendor_id, device_id)