Home | History | Annotate | Download | only in kvmtest
      1 import random, os, logging
      2 from autotest_lib.client.bin import test, utils
      3 from autotest_lib.client.common_lib import error
      4 
      5 
      6 class kvmtest(test.test):
      7     version = 1
      8 
      9     def initialize(self):
     10         self.job.require_gcc()
     11 
     12 
     13     def setup(self, tarball = 'kvm-test.tar.gz'):
     14         tarball = utils.unmap_url(self.bindir, tarball, self.tmpdir)
     15         utils.extract_tarball_to_dir(tarball, self.srcdir)
     16         os.chdir(self.srcdir)
     17         utils.system('python setup.py install')
     18 
     19 
     20     def execute(self, testdir = '', args = ''):
     21         dirs = []
     22         results = []
     23         passed = 0
     24         failed = 0
     25 
     26         # spawn vncserver if needed
     27         if not os.environ.has_key('DISPLAY'):
     28             logging.info("No DISPLAY set in environment, spawning vncserver...")
     29             display = self.__create_vncserver(os.path.expanduser("~/.vnc"))
     30             logging.info("Setting DISPLAY=%s"%(display))
     31             os.environ['DISPLAY'] = display
     32 
     33         # build a list of dirs with 'vm.log' files
     34         os.path.walk(testdir, self.__has_vmlog, dirs)
     35 
     36         for d in dirs:
     37             replaydir = os.path.join(self.resultsdir, os.path.basename(d))
     38             os.mkdir(replaydir)
     39             logfile = replaydir + "/%s.log" %(os.path.basename(d))
     40 
     41             os.chdir(d)
     42             rv = utils.system("kvm-test-replay > %s" %(logfile), 1)
     43 
     44             results.append((d, rv))
     45             if rv != 0:
     46                 screenshot = self.__get_expected_file(logfile)
     47                 expected = "expected-%03d.png" % random.randint(0, 999)
     48                 dest = os.path.join(replaydir,expected)
     49 
     50                 # make a copy of the screen shot
     51                 utils.system("cp %s %s" % (screenshot, dest), 1)
     52 
     53                 # move the failure
     54                 utils.system("mv failure-*.png %s" % replaydir, 1)
     55 
     56         # generate html output
     57         self.__format_results(results)
     58 
     59         # produce pass/fail output
     60         for (x, y) in results:
     61             if y != 0:
     62                 logging.error("FAIL: '%s' with rv %s" % (x, y))
     63                 failed = failed + 1
     64             else:
     65                 logging.info("PASS: '%s' with rv %s" % (x, y))
     66                 passed = passed + 1
     67 
     68         logging.info("Summary: Passed %d Failed %d" % (passed, failed))
     69         # if we had any tests not passed, fail entire test
     70         if failed != 0:
     71             raise error.TestError('kvm-test-replay')
     72 
     73 
     74     def __get_expected_file(self, logfile):
     75         # pull out screeshot name from logfile
     76         return filter(lambda x: "Expected" in x,
     77                       open(logfile, 'r').readlines())\
     78                       [0].split('{')[1].split('}')[0]
     79 
     80 
     81     def __create_vncserver(self, dirname):
     82         """
     83         this test may run without an X connection in kvm/qemu needs
     84         a DISPLAY to push the vga buffer.  If a DISPLAY is not set
     85         in the environment, then attempt to spawn a vncserver, and
     86         change env DISPLAY so that kvmtest can run
     87         """
     88         for pidfile in utils.locate("*:*.pid", dirname):
     89             pid = open(pidfile, 'r').readline().strip()
     90             # if the server is still active, just use it for display
     91             if os.path.exists('/proc/%s/status' % pid):
     92                 vncdisplay = os.path.basename(pidfile)\
     93                                .split(":")[1].split(".")[0]
     94                 logging.info("Found vncserver on port %s, using it" % vncdisplay)
     95                 return ':%s.0' %(vncdisplay)
     96 
     97         # none of the vncserver were still alive, spawn our own and
     98         # return the display whack existing server first, then spawn it
     99         vncdisplay = "1"
    100         logging.info("Spawning vncserver on port %s" % vncdisplay)
    101         utils.system('vncserver :%s' % vncdisplay)
    102         return ':%s.0' % vncdisplay
    103 
    104 
    105     def __has_vmlog(self, arg, dirname, names):
    106         if os.path.exists(os.path.join(dirname, 'vm.log')):
    107             arg.append(dirname)
    108 
    109 
    110     def __gen_fail_html(self, testdir):
    111         # generate a failure index.html to display the expected and failure
    112         # images
    113         fail_dir = os.path.join(self.resultsdir, os.path.basename(testdir))
    114         fail_index = os.path.join(fail_dir, "index.html")
    115 
    116         # lambda helpers for pulling out image files
    117         is_png = lambda x: x.endswith('.png')
    118         failure_filter = lambda x: x.startswith('failure') and is_png(x)
    119         expected_filter = lambda x: x.startswith('expected') and is_png(x)
    120 
    121         failure_img = filter(failure_filter, os.listdir(fail_dir))[0]
    122         expected_img = filter(expected_filter, os.listdir(fail_dir))[0]
    123         if not failure_img or not expected_img:
    124             raise "Failed to find images"
    125 
    126         fail_buff = "<html><table border=1><tr><th>Barrier Diff</th>\n" + \
    127                  "<th>Expected Barrier</th><th>Failure</th></tr><tr><td></td>\n"
    128         for img in expected_img, failure_img:
    129             fail_buff = fail_buff + "<td><a href=\"%s\"><img width=320 " \
    130                         "height=200 src=\"%s\"></a></td>\n" % (img, img)
    131 
    132         fail_buff = fail_buff + "</tr></table></html>\n"
    133 
    134         fh = open(fail_index, "w+")
    135         fh.write(fail_buff)
    136         fh.close()
    137 
    138     def __format_results(self, results):
    139         # generate kvmtest/index.html and an index.html for each fail
    140         test_index = os.path.join(self.outputdir, "index.html")
    141         test_buff = "<html><table border=1><tr><th>Test</th>\n"
    142 
    143         for (x,y) in results:
    144             test_buff = test_buff + "<th>%s</th>\n" % os.path.basename(x)
    145 
    146         test_buff = test_buff + "</tr><tr><td></td>\n"
    147 
    148         for (x,y) in results:
    149             if y != 0:
    150                 fail = "<td><a href=\"results/%s/\">FAIL</a></td>\n" % os.path.basename(x)
    151                 test_buff = test_buff + fail
    152                 self.__gen_fail_html(x)
    153             else:
    154                 test_buff = test_buff + "<td>GOOD</td>\n"
    155 
    156         test_buff = test_buff + "</tr></table></html>"
    157 
    158         fh = open(test_index, "w+")
    159         fh.write(test_buff)
    160         fh.close()
    161