packages feed

liquidhaskell-0.8.0.2: tests/rtest.py

import time, os, os.path
import pmap
import itertools as it
import threading, Queue

class LogWriter (threading.Thread):
    def __init__ (self, logfile, q):
        threading.Thread.__init__ (self)
        self.log  = open (logfile, "w")
        self.q    = q
        self.halt = False
        self.log.write("test, time(s), result \n")

    def __del__ (self):
        self.log.close ()

    def run (self):
        while not self.halt:
            try:
                file, runtime, ok = self.q.get (timeout=1)
                self.log.write("%s, %f, %s \n" % (file, runtime, ok))
                self.log.flush()
                self.q.task_done ()
            except Queue.Empty:
                pass

class TestConfig:
    def __init__ (self, testdirs, logfile = None, threadcount = 1):
        self.testdirs    = testdirs
        self.valid_exits = [x for d, i, x in self.testdirs]
        if logfile != None:
            self.logq   = Queue.Queue ()
            self.logger = LogWriter (logfile, self.logq)
            self.logger.start ()
        else:
            self.logger = None
        self.exceptions  = list()
        self.threadcount = threadcount

    def finalize (self):
        if self.logger != None:
            self.logger.halt = True

    def is_test (self, file):
        pass

    def run_test (self, file):
        pass

    def log_test (self, file, runtime, ok):
        if self.logger != None:
            self.logq.put ((file, runtime, ok))

        if ok not in self.valid_exits:
            self.exceptions.append (file)
  
class TestRunner:
    def __init__ (self, config):
        self.config = config

    def run_test (self, (dir, file, expected_statuses)):
        path    = os.path.join(dir, file)
        start   = time.time ()
        status  = self.config.run_test (dir, file)
        runtime = time.time () - start
        print "%f seconds" % (runtime)

        if hasattr (expected_statuses, '__iter__'):
          ok = (status in expected_statuses) 
        else:
          ok = (status == expected_statuses)
        if ok:
            print "\033[1;32mSUCCESS!\033[1;0m (%s)\n" % (path)
        else:
            print "\033[1;31mFAILURE :(\033[1;0m (%s) \n" % (path)
        self.config.log_test(path, runtime, ok)
        
        return (dir + "/" + file, ok, status not in self.config.valid_exits)

    def run_tests (self, tests):
        results   = pmap.map (self.config.threadcount, self.run_test, tests)
        self.config.finalize()
        failed    = sorted([(result[0], result[2]) for result in results if result[1] == False])
        failcount = len(failed)
        if failcount == 0:
            print "\n\033[1;32mPassed all tests! :D\033[1;0m"
        else:
            failnames  = [fail[0] for fail in failed]
            print "\n\033[1;31mFailed %d tests:\033[1;0m \n %s \n" % (failcount, ",\n  ".join(failnames))

            exceptions = [fail[0] for fail in failed if fail[1]]
            if exceptions != []:
                print "\n\033[1;31mExceptions thrown on %d tests:\033[1;0m \n  %s \n" % (len(exceptions), ",\n  ".join(exceptions))

        return (failcount != 0)

    def directory_tests (self, dir, ignored, expected_status):
        paths = [(dir, os.path.relpath(os.path.join(d, f), dir))
                 for d,_,files in os.walk(dir)
                 for f in files]
        return it.chain([(dir, file, expected_status)
                         for dir, file in paths
                         if self.config.is_test (file) and file not in ignored])

        # return it.chain(*[[(dir, os.path.relpath(os.path.join (dir_, file),dir),
        #                     expected_status)
        #                    for file in files
        #                    if self.config.is_test (file) and file not in ignored]
        #                   for dir_, _, files in os.walk(dir)])

    def run (self):
        return self.run_tests (it.chain (*[self.directory_tests (dir, ignored, expected_status)
                                           for dir, ignored, expected_status
                                           in self.config.testdirs]))