diff options
author | Robin Hack <rhack@redhat.com> | 2014-01-21 08:07:03 +0100 |
---|---|---|
committer | Robin Hack <rhack@redhat.com> | 2014-01-21 08:07:03 +0100 |
commit | ee8aafdece792b36a9483b51cc40579942222a65 (patch) | |
tree | df078da3a1eca5f66c051388096b679024133375 /src/hardware | |
parent | 7dc02e6dd0e5a6ae2b3b440b1d3762629210288b (diff) | |
download | openlmi-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/README | 18 | ||||
-rw-r--r-- | src/hardware/test/TestHardware.py | 176 | ||||
-rw-r--r-- | src/hardware/test/TestHardwareBase.py | 356 |
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) |