Changeset bacc36c for src/tests/pybin


Ignore:
Timestamp:
Dec 4, 2017, 6:01:29 PM (6 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
Children:
209383b
Parents:
0ad0c55
Message:

Major test cleanup by modularizing further into pybin

Location:
src/tests/pybin
Files:
1 added
2 edited

Legend:

Unmodified
Added
Removed
  • src/tests/pybin/test_run.py

    r0ad0c55 rbacc36c  
    33from pybin.tools import *
    44
     5import pybin.settings
    56
    67# Test class that defines what a test is
     
    1415                return "{:25s} ({:5s} {:s})".format( self.name, self.arch if self.arch else "Any", self.target() )
    1516
    16         def prepare(self, dry_run):
    17                 sh("mkdir -p %s" % os.path.join(self.path, '.err'), dry_run)
    18                 sh("mkdir -p %s" % os.path.join(self.path, '.out'), dry_run)
    19                 sh("mkdir -p %s" % os.path.join(self.path, '.in' ), dry_run)
     17        def prepare(self):
     18                sh("mkdir -p %s" % os.path.join(self.path, '.err'))
     19                sh("mkdir -p %s" % os.path.join(self.path, '.out'))
     20                sh("mkdir -p %s" % os.path.join(self.path, '.in' ))
    2021
    21         def expect_file(self):
     22        def expect(self):
    2223                return ("%s/.expect/%s.txt" % (self.path, self.name))
    2324
    24         def error_file(self):
     25        def error_log(self):
    2526                return ("%s/.err/%s.log"    % (self.path, self.name))
    2627
    27         def output_file(self):
     28        def output_log(self):
    2829                return ("%s/.out/%s.log"    % (self.path, self.name))
    2930
    30         def input_file(self):
     31        def input(self):
    3132                return ("%s/.in/%s.txt"     % (self.path, self.name))
     33
     34        def target_output(self):
     35                return self.output_log() if not settings.generating else self.expect()
    3236
    3337        def target(self):
    3438                return os.path.join(self.path, self.name)
     39
     40        @classmethod
     41        def valid_name(cls, name):
     42                return not name.endswith( ('.c', '.cc', '.cpp', '.cfa') )
     43
     44        @classmethod
     45        def from_target(cls, target):
     46                test = Test()
     47                test.name = os.path.basename(target)
     48                test.path = os.path.dirname (target)
     49                test.arch = settings.arch.toString() if settings.arch.cross_compile else ''
     50                return test
     51
     52
     53class TestResult:
     54        SUCCESS = 0
     55        FAILURE = 1
     56        TIMEOUT = 124
     57
     58        @classmethod
     59        def toString( cls, retcode ):
     60                if settings.generating :
     61                        if   retcode == TestResult.SUCCESS:     return "Done"
     62                        elif retcode == TestResult.TIMEOUT:     return "TIMEOUT"
     63                        else :                                          return "ERROR code %d" % retcode
     64                else :
     65                        if   retcode == TestResult.SUCCESS:     return "PASSED"
     66                        elif retcode == TestResult.TIMEOUT:     return "TIMEOUT"
     67                        else :                                          return "FAILED with code %d" % retcode
  • src/tests/pybin/tools.py

    r0ad0c55 rbacc36c  
     1from __future__ import print_function
     2
    13import __main__
    24import argparse
     5import multiprocessing
    36import os
    47import re
     8import signal
    59import stat
    6 
     10import sys
     11
     12from pybin import settings
    713from subprocess import Popen, PIPE, STDOUT
    814
     15################################################################################
     16#               shell helpers
     17################################################################################
     18
    919# helper functions to run terminal commands
    10 def sh(cmd, dry_run = False, print2stdout = True):
    11         if dry_run :    # if this is a dry_run, only print the commands that would be ran
     20def sh(cmd, print2stdout = True, input = None):
     21        # add input redirection if needed
     22        if input and os.path.isfile(input):
     23                cmd += " < %s" % input
     24
     25        # if this is a dry_run, only print the commands that would be ran
     26        if settings.dry_run :
    1227                print("cmd: %s" % cmd)
    1328                return 0, None
    14         else :                  # otherwise create a pipe and run the desired command
     29
     30        # otherwise create a pipe and run the desired command
     31        else :
    1532                proc = Popen(cmd, stdout=None if print2stdout else PIPE, stderr=STDOUT, shell=True)
    1633                out, err = proc.communicate()
     
    1835
    1936# Remove 1 or more files silently
    20 def rm( files, dry_run = False ):
     37def rm( files ):
    2138        try:
    2239                for file in files:
    23                         sh("rm -f %s > /dev/null 2>&1" % file, dry_run)
     40                        sh("rm -f %s > /dev/null 2>&1" % file )
    2441        except TypeError:
    25                 sh("rm -f %s > /dev/null 2>&1" % files, dry_run)
     42                sh("rm -f %s > /dev/null 2>&1" % files )
    2643
    2744def chdir( dest = __main__.__file__ ):
     
    3047        os.chdir(dname)
    3148
    32 # helper function to replace patterns in a file
    33 def file_replace(fname, pat, s_after):
    34     # first, see if the pattern is even in the file.
    35     with open(fname) as f:
    36         if not any(re.search(pat, line) for line in f):
    37             return # pattern does not occur in file so we are done.
    38 
    39     # pattern is in the file, so perform replace operation.
    40     with open(fname) as f:
    41         out_fname = fname + ".tmp"
    42         out = open(out_fname, "w")
    43         for line in f:
    44             out.write(re.sub(pat, s_after, line))
    45         out.close()
    46         os.rename(out_fname, fname)
    47 
    48 # helper function to check if a files contains only a specific string
    49 def fileContainsOnly(file, text) :
    50         with open(file) as f:
    51                 ff = f.read().strip()
    52                 result = ff == text.strip()
    53 
    54                 return result;
    55 
    56 # check whether or not a file is executable
    57 def fileIsExecutable(file) :
    58         try :
    59                 fileinfo = os.stat(file)
    60                 return bool(fileinfo.st_mode & stat.S_IXUSR)
    61         except Exception as inst:
    62                 print(type(inst))    # the exception instance
    63                 print(inst.args)     # arguments stored in .args
    64                 print(inst)
    65                 return False
    66 
    67 # check if arguments is yes or no
    68 def yes_no(string):
    69         if string == "yes" :
    70                 return True
    71         if string == "no" :
    72                 return False
    73         raise argparse.ArgumentTypeError(msg)
    74         return False
    75 
    7649# diff two files
    77 def diff( lhs, rhs, dry_run ):
     50def diff( lhs, rhs ):
    7851        # diff the output of the files
    7952        diff_cmd = ("diff --ignore-all-space "
     
    9467
    9568        # fetch return code and error from the diff command
    96         return sh(diff_cmd % (lhs, rhs), dry_run, False)
     69        return sh(diff_cmd % (lhs, rhs), False)
     70
     71# call make
     72def make(target, flags = '', redirects = '', error_file = None, silent = False):
     73        test_param = """test="%s" """ % (error_file) if error_file else ''
     74        cmd = ' '.join([
     75                settings.make,
     76                '-s' if silent else '',
     77                test_param,
     78                flags,
     79                target,
     80                redirects
     81        ])
     82        return sh(cmd)
     83
     84################################################################################
     85#               file handling
     86################################################################################
     87
     88# helper function to replace patterns in a file
     89def file_replace(fname, pat, s_after):
     90    # first, see if the pattern is even in the file.
     91    with open(fname) as f:
     92        if not any(re.search(pat, line) for line in f):
     93            return # pattern does not occur in file so we are done.
     94
     95    # pattern is in the file, so perform replace operation.
     96    with open(fname) as f:
     97        out_fname = fname + ".tmp"
     98        out = open(out_fname, "w")
     99        for line in f:
     100            out.write(re.sub(pat, s_after, line))
     101        out.close()
     102        os.rename(out_fname, fname)
     103
     104# helper function to check if a files contains only a specific string
     105def fileContainsOnly(file, text) :
     106        with open(file) as f:
     107                ff = f.read().strip()
     108                result = ff == text.strip()
     109
     110                return result;
     111
     112# check whether or not a file is executable
     113def fileIsExecutable(file) :
     114        try :
     115                fileinfo = os.stat(file)
     116                return bool(fileinfo.st_mode & stat.S_IXUSR)
     117        except Exception as inst:
     118                print(type(inst))    # the exception instance
     119                print(inst.args)     # arguments stored in .args
     120                print(inst)
     121                return False
     122
     123# transform path to canonical form
     124def canonicalPath(path):
     125        return os.path.join('.', os.path.normpath(path) )
     126
     127# compare path even if form is different
     128def pathCmp(lhs, rhs):
     129        return canonicalPath( lhs ) == canonicalPath( rhs )
     130
     131# walk all files in a path
     132def pathWalk( op ):
     133        def step(_, dirname, names):
     134                for name in names:
     135                        path = os.path.join(dirname, name)
     136
     137                        op( path )
     138
     139        # Start the walk
     140        os.path.walk('.', step, '')
     141
     142################################################################################
     143#               system
     144################################################################################
    97145
    98146# parses the Makefile to find the machine type (32-bit / 64-bit)
     
    100148        return 'x64'
    101149        sh('echo "void ?{}(int&a,int b){}int main(){return 0;}" > .dummy.c')
    102         ret, out = sh("make .dummy -s", print2stdout=True)
     150        ret, out = make('.dummy', silent = True)
    103151
    104152        if ret != 0:
     
    114162        return out
    115163        return re.search("ELF\s([0-9]+)-bit", out).group(1)
     164
     165# count number of jobs to create
     166def jobCount( options, tests ):
     167        # check if the user already passed in a number of jobs for multi-threading
     168        make_flags = os.environ.get('MAKEFLAGS')
     169        make_jobs_fds = re.search("--jobserver-(auth|fds)=\s*([0-9]+),([0-9]+)", make_flags) if make_flags else None
     170        if make_jobs_fds :
     171                tokens = os.read(int(make_jobs_fds.group(2)), 1024)
     172                options.jobs = len(tokens)
     173                os.write(int(make_jobs_fds.group(3)), tokens)
     174        else :
     175                options.jobs = multiprocessing.cpu_count()
     176
     177        # make sure we have a valid number of jobs that corresponds to user input
     178        if options.jobs <= 0 :
     179                print('ERROR: Invalid number of jobs', file=sys.stderr)
     180                sys.exit(1)
     181
     182        return min( options.jobs, len(tests) ), True if make_flags else False
     183
     184# setup a proper processor pool with correct signal handling
     185def setupPool(jobs):
     186        original_sigint_handler = signal.signal(signal.SIGINT, signal.SIG_IGN)
     187        pool = multiprocessing.Pool(jobs)
     188        signal.signal(signal.SIGINT, original_sigint_handler)
     189
     190        return pool
     191
     192# handle signals in scope
     193class SignalHandling():
     194        def __enter__(self):
     195                # enable signal handling
     196                signal.signal(signal.SIGINT, signal.SIG_DFL)
     197
     198        def __exit__(self, type, value, traceback):
     199                # disable signal handling
     200                signal.signal(signal.SIGINT, signal.SIG_IGN)
     201
     202################################################################################
     203#               misc
     204################################################################################
     205
     206# check if arguments is yes or no
     207def yes_no(string):
     208        if string == "yes" :
     209                return True
     210        if string == "no" :
     211                return False
     212        raise argparse.ArgumentTypeError(msg)
     213        return False
Note: See TracChangeset for help on using the changeset viewer.