#!/usr/bin/env python #.awk '$0 ~ /case [0-9]+: .. 3/ { sys.stdout.write($2 }' src/dmidecode.c|tr ':\n' ', ' from pprint import pprint import os, sys, subprocess, random, tempfile, time if sys.version_info[0] < 3: import commands as subprocess from getopt import getopt # Setup temporary sys.path() with our build dir (sysname, nodename, release, version, machine) = os.uname() pyver = sys.version[:3] sys.path.insert(0,'../build/lib.%s-%s-%s' % (sysname.lower(), machine, pyver)) root_user = (os.getuid() == 0 and True or False) ERROR = False HELP = False VERBOSITY = 0 COLOR = False DUMPS_D = "private" try: opts, args = getopt( sys.argv[1:], "hcv", ["help", "color", "verbose"] ) for o, a in opts: if o in ("-v", "--verbose"): VERBOSITY += 1 elif o in ("-c", "--color"): COLOR = True elif o in ("-h", "--help"): HELP = True except getopt.GetoptError as err: # print help information and exit: HELP = True ERROR = True if HELP: sys.stdout.write(""" Usage: %s [] OPTIONS [-h|--help] #. Take a wild guess. [-c|--color] #. Add pretty ANSI colors. [-v|--verbose] #. The more you add, the louder it gets. NOTES Due to developer laziness, a single verbosity flag does nothing, so if you actually want to get some verbosity, add two verbosity flags (-vv) """ % os.path.basename(sys.argv[0])) sys.exit(ERROR and 1 or 0) def ascii(s, i): return (COLOR and "\033[%d;1m%s\033[0m" or "%d%s") % (30+i, str(s)) def black(s): return (COLOR and "\033[30;1m%s\033[0m" or "%s")%(str(s)) def red(s): return (COLOR and "\033[31;1m%s\033[0m" or "%s")%(str(s)) def green(s): return (COLOR and "\033[32;1m%s\033[0m" or "%s")%(str(s)) def yellow(s): return (COLOR and "\033[33;1m%s\033[0m" or "%s")%(str(s)) def blue(s): return (COLOR and "\033[34;1m%s\033[0m" or "%s")%(str(s)) def magenta(s): return (COLOR and "\033[35;1m%s\033[0m" or "%s")%(str(s)) def cyan(s): return (COLOR and "\033[36;1m%s\033[0m" or "%s")%(str(s)) def white(s): return (COLOR and "\033[37;1m%s\033[0m" or "%s")%(str(s)) DISPATCH = { 1 : red, 2 : green, 3 : yellow, 4 : blue, 5 : magenta, 6 : cyan, 7 : white, } LINE = "%s\n"%(magenta("="*80)) score = { "total" : 0, "skipped" : 0, "passed" : 0, "warned" : 0, "failed" : 0, } def passed(msg=None, indent=1): global score score["total"] += 1 score["passed"] += 1 vwrite("%s\n"%green("PASS"), 1) if msg: vwrite("%s %s %s\n"%(" "*indent, green("P"), msg), 1) def skipped(msg=None, indent=1): global score score["total"] += 1 score["skipped"] += 1 vwrite("%s\n"%yellow("SKIP"), 1) if msg: vwrite("%s %s %s\n"%(" "*indent, yellow("S"), msg), 1) def warned(msg=None, indent=1): global score score["total"] += 1 score["warned"] += 1 vwrite("%s\n"%yellow("WARN"), 1) if msg: vwrite("%s %s %s\n"%(" "*indent, yellow("S"), msg), 1) def failed(msg=None, indent=1): global score score["total"] += 1 score["failed"] += 1 vwrite("%s\n"%red("FAIL"), 1) if msg: vwrite("%s %s %s\n"%(" "*indent, red("F"), msg), 1) def test(r, msg=None, indent=1, bad=failed): if r: passed(msg, indent) return True else: bad(msg, indent) return False def vwrite(msg, vLevel=0): if vLevel < VERBOSITY: sys.stdout.write(msg) sys.stdout.flush() ################################################################################ #. Let's ignore warnings from the module for the test units... err = open('/dev/null', 'a+', 1) os.dup2(err.fileno(), sys.stderr.fileno()) vwrite(LINE, 1) vwrite(" * Testing for command line version of dmidecode ...", 1) dmidecode_bin = True in [ os.path.exists( os.path.join(_, "dmidecode") ) for _ in os.getenv("PATH").split(':') ] test(dmidecode_bin, bad=warned) if root_user: vwrite(" * Running test as root user, all tests will be executed\n", 1) else: vwrite(" * %s\n"%red("Running test as normal user, some tests will be skipped"), 1) vwrite(" * Creation of temporary files...", 1) try: FH, DUMP = tempfile.mkstemp() os.unlink(DUMP) os.close(FH) passed() except: failed() vwrite(LINE, 1) try: vwrite(" * Importing module...", 1) import libxml2 import dmidecode if not root_user: vwrite("\n%s"%cyan("Not running as root, a warning above can be expected..."), 1) passed() vwrite(" * Version: %s\n"%blue(dmidecode.version), 1) vwrite(" * DMI Version String: %s\n"%blue(dmidecode.dmi), 1) vwrite(" * Testing that default device is /dev/mem...", 1) test(dmidecode.get_dev() == "/dev/mem") if root_user: vwrite(" * Testing that write-lock will not break on dump()...", 1) test(not dmidecode.dump()) vwrite(" * Testing ability to change device to %s..."%DUMP, 1) test(dmidecode.set_dev(DUMP)) vwrite(" * Testing that device has changed to %s..."%DUMP, 1) test(dmidecode.get_dev() == DUMP) if root_user and dmidecode.dmi is not None: vwrite(" * Testing that write on new file is ok...", 1) test(dmidecode.dump()) vwrite(" * Testing that file was actually written...", 1) time.sleep(0.1) if test(os.path.exists(DUMP)): os.unlink(DUMP) else: if dmidecode.dmi is None: vwrite( " * %s\n" % yellow( "Skipped testing dump() function, dmidecode does not have access to DMI data" ), 1) else: vwrite( " * %s\n" % red( "Skip testing API function, missing root privileges: dmidecode.dump()" ), 1) types = list(range(0, 42))+list(range(126, 128)) bad_types = [-1, -1000, 256] sections = [ "bios", "system", "baseboard", "chassis", "processor", "memory", "cache", "connector", "slot" ] devices = [] if os.path.exists(DUMPS_D): devices.extend([os.path.join(DUMPS_D, _) for _ in os.listdir(DUMPS_D)]) else: vwrite(" * If you have memory dumps to test, create a directory called `%s' and drop them in there.\n" % DUMPS_D, 1) if root_user and dmidecode.dmi is not None: devices.append("/dev/mem") else: if dmidecode.dmi is not None: vwrite(" * %s\n"%red("Running test as normal user, will not try to read /dev/mem"), 1) try: pymap = '../src/pymap.xml' vwrite(" * Loading %s for XML->Python dictonary mapping..." % pymap, 1) dmidecode.pythonmap(pymap) passed() except: failed() random.shuffle(types) random.shuffle(devices) random.shuffle(sections) for dev in devices: vwrite(LINE, 1) vwrite(" * Testing %s..."%yellow(dev), 1) try: fH = open(dev, 'r') fH.close() passed() vwrite(" * Testing set_dev/get_dev on %s..."%(yellow(dev)), 1) if test(dmidecode.set_dev(dev) and dmidecode.get_dev() == dev): i = 0 for section in sections: i += 1 vwrite(" * Testing %s (%d/%d)..."%(cyan(section), i, len(sections)), 1) try: output = getattr(dmidecode, section)() test(output is not False) if output: vwrite(" * %s\n"%black(output.keys()), 1) except LookupError as e: failed(e, 1) for i in bad_types: vwrite(" * Testing bad type %s..."%red(i), 1) try: output = dmidecode.type(i) test(output is False) except SystemError: failed() for i in types: vwrite(" * Testing type %s..."%red(i), 1) try: output = dmidecode.type(i) if dmidecode_bin: _output = subprocess.getoutput("dmidecode -t %d"%i).strip().split('\n') test(len(_output) == 1 and len(output) == 0 or True) else: test(output is not False) if output: vwrite(" * %s\n"%output.keys(), 1) except IOError as e: failed(e, 1) except LookupError as e: failed(e, 1) dmixml = dmidecode.dmidecodeXML() try: vwrite(" * XML: Swapping result type dmidecodeXML::SetResultType('-') - invalid type... ", 1) test(not dmixml.SetResultType('-')) except TypeError: vwrite("Not working => ", 1) passed() except: vwrite("Accepted => ", 1) failed() try: vwrite(" * XML: Swapping result type - dmidecodeXML::SetResultType(dmidecode.DMIXML_DOC) - valid type...", 1) test(dmixml.SetResultType(dmidecode.DMIXML_DOC)) vwrite(" * XML: Swapping result type - dmidecodeXML::SetResultType(dmidecode.DMIXML_NODE) - valid type...", 1) test(dmixml.SetResultType(dmidecode.DMIXML_NODE)) except: failed() for i in bad_types: vwrite(" * XML: Testing bad type - dmidecodeXML::QueryTypeId(%s)..." % red(i), 1) try: output_node = dmixml.QueryTypeId(i) test(not isinstance(output_node, libxml2.xmlNode)) except SystemError: vwrite("Accepted => ", 1) failed() except TypeError: vwrite("Not working => ", 1) passed() except ValueError: vwrite("Not working => ", 1) passed() for i in types: vwrite(" * XML: Testing dmidecodeXML::QueryTypeId(%s)..." % red(i), 1) try: output_node = dmixml.QueryTypeId(i) test(isinstance(output_node, libxml2.xmlNode)) except Exception as e: failed(e, 1) except: failed() dmixml.SetResultType(dmidecode.DMIXML_DOC) i = 0 for section in sections: i += 1 vwrite(" * %s (%d/%d)..." % ( "XML: Testing dmidecodeXML::QuerySection('%s')" % cyan( section ), i, len(sections) ), 1) try: output_doc = dmixml.QuerySection(section) test(isinstance(output_doc, libxml2.xmlDoc)) except Exception as e: failed(e, 1) except: failed() except IOError: skipped() except ImportError as err: failed() print(err) vwrite(LINE, 1) vwrite("Devices : %s\n"%cyan(len(devices)), 1) vwrite("Total : %s\n"%blue(score["total"]), 1) vwrite("Skipped : %s\n"%yellow(score["skipped"]), 1) vwrite("Warned : %s\n"%yellow(score["warned"]), 1) vwrite("Passed : %s\n"%green(score["passed"]), 1) vwrite("Failed : %s\n"%red(score["failed"]), 1) sys.exit(score["failed"] != 0 and 1 or 0)