Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • tests/pybin/tools.py

    rf806b61 r0c13238  
     1from __future__ import print_function
     2
    13import __main__
    24import argparse
    3 import contextlib
    45import fileinput
    56import multiprocessing
     
    910import signal
    1011import stat
    11 import subprocess
    1212import sys
    13 import tempfile
    1413import time
    15 import types
    1614
    1715from pybin import settings
     16from subprocess import Popen, PIPE, STDOUT
    1817
    1918################################################################################
     
    2221
    2322# helper functions to run terminal commands
    24 def sh(*cmd, timeout = False, output = None, input = None, error = subprocess.STDOUT):
    25         cmd = list(cmd)
     23def sh(cmd, print2stdout = True, input = None):
     24        # add input redirection if needed
     25        if input and os.path.isfile(input):
     26                cmd += " < %s" % input
    2627
    2728        # if this is a dry_run, only print the commands that would be ran
    2829        if settings.dry_run :
    29                 cmd = "{} cmd: {}".format(os.getcwd(), ' '.join(cmd))
    30                 if output and not isinstance(output, int):
    31                         cmd += " > "
    32                         cmd += output
    33 
    34                 if error and not isinstance(error, int):
    35                         cmd += " 2> "
    36                         cmd += error
    37 
    38                 if input and not isinstance(input, int) and os.path.isfile(input):
    39                         cmd += " < "
    40                         cmd += input
    41 
    42                 print(cmd)
     30                print("cmd: %s" % cmd)
    4331                return 0, None
    4432
    45         with contextlib.ExitStack() as onexit:
    46                 # add input redirection if needed
    47                 input = openfd(input, 'r', onexit, True)
    48 
    49                 # add output redirection if needed
    50                 output = openfd(output, 'w', onexit, False)
    51 
    52                 # add error redirection if needed
    53                 error = openfd(error, 'w', onexit, False)
    54 
    55                 # run the desired command
    56                 try:
    57                         proc = subprocess.run(
    58                                 cmd,
    59                                 stdin =input,
    60                                 stdout=output,
    61                                 stderr=error,
    62                                 timeout=settings.timeout.single if timeout else None
    63                         )
    64                         return proc.returncode, proc.stdout.decode("utf-8") if proc.stdout else None
    65                 except subprocess.TimeoutExpired:
    66                         return 124, str(None)
     33        # otherwise create a pipe and run the desired command
     34        else :
     35                proc = Popen(cmd, stdout=None if print2stdout else PIPE, stderr=STDOUT, shell=True)
     36                out, err = proc.communicate()
     37                return proc.returncode, out
    6738
    6839def is_ascii(fname):
     
    7445                return False
    7546
    76         code, out = sh("file %s" % fname, output=subprocess.PIPE)
     47        code, out = sh("file %s" % fname, print2stdout = False)
    7748        if code != 0:
    7849                return False
     
    8455
    8556        return match.group(1).startswith("ASCII text")
    86 
    87 def is_exe(fname):
    88         return os.path.isfile(fname) and os.access(fname, os.X_OK)
    89 
    90 def openfd(file, mode, exitstack, checkfile):
    91         if not file:
    92                 return file
    93 
    94         if isinstance(file, int):
    95                 return file
    96 
    97         if checkfile and not os.path.isfile(file):
    98                 return None
    99 
    100         file = open(file, mode)
    101         exitstack.push(file)
    102         return file
    10357
    10458# Remove 1 or more files silently
    10559def rm( files ):
    106         if isinstance(files, str ): files = [ files ]
    107         for file in files:
    108                 sh( 'rm', '-f', file, output=subprocess.DEVNULL, error=subprocess.DEVNULL )
     60        if isinstance( files, basestring ):
     61                sh("rm -f %s > /dev/null 2>&1" % files )
     62        else:
     63                for file in files:
     64                        sh("rm -f %s > /dev/null 2>&1" % file )
    10965
    11066# Create 1 or more directory
    11167def mkdir( files ):
    112         if isinstance(files, str ): files = [ files ]
    113         for file in files:
    114                 p = os.path.normpath( file )
    115                 d = os.path.dirname ( p )
    116                 sh( 'mkdir', '-p', d, output=subprocess.DEVNULL, error=subprocess.DEVNULL )
     68        if isinstance( files, basestring ):
     69                sh("mkdir -p %s" % os.path.dirname(files) )
     70        else:
     71                for file in files:
     72                        sh("mkdir -p %s" % os.path.dirname(file) )
    11773
    11874
     
    12480# diff two files
    12581def diff( lhs, rhs ):
     82        # diff the output of the files
     83        diff_cmd = ("diff --text "
     84#                               "--ignore-all-space "
     85#                               "--ignore-blank-lines "
     86                                "--old-group-format='\t\tmissing lines :\n"
     87                                "%%<' \\\n"
     88                                "--new-group-format='\t\tnew lines :\n"
     89                                "%%>' \\\n"
     90                                "--unchanged-group-format='%%=' \\"
     91                                "--changed-group-format='\t\texpected :\n"
     92                                "%%<"
     93                                "\t\tgot :\n"
     94                                "%%>\n' \\\n"
     95                                "--new-line-format='\t\t%%dn\t%%L' \\\n"
     96                                "--old-line-format='\t\t%%dn\t%%L' \\\n"
     97                                "--unchanged-line-format='' \\\n"
     98                                "%s %s")
     99
    126100        # fetch return code and error from the diff command
    127         return sh(
    128                 '''diff''',
    129                 '''--text''',
    130                 '''--old-group-format=\t\tmissing lines :\n%<''',
    131                 '''--new-line-format=\t\t%dn\t%L''',
    132                 '''--new-group-format=\t\tnew lines : \n%>''',
    133                 '''--old-line-format=\t\t%dn\t%L''',
    134                 '''--unchanged-group-format=%=''',
    135                 '''--changed-group-format=\t\texpected :\n%<\t\tgot :\n%>''',
    136                 '''--unchanged-line-format=''',
    137                 lhs,
    138                 rhs,
    139                 output=subprocess.PIPE
    140         )
     101        return sh(diff_cmd % (lhs, rhs), False)
    141102
    142103# call make
    143 def make(target, *, flags = '', output = None, error = None, error_file = None, silent = False):
    144         test_param = """test="%s" """ % (error_file) if error_file else None
    145         cmd = [
    146                 *settings.make,
    147                 '-s' if silent else None,
     104def make(target, flags = '', redirects = '', error_file = None, silent = False):
     105        test_param = """test="%s" """ % (error_file) if error_file else ''
     106        cmd = ' '.join([
     107                settings.make,
     108                '-s' if silent else '',
    148109                test_param,
    149110                settings.arch.flags,
     
    151112                settings.install.flags,
    152113                flags,
    153                 target
    154         ]
    155         cmd = [s for s in cmd if s]
    156         return sh(*cmd, output=output, error=error)
     114                target,
     115                redirects
     116        ])
     117        return sh(cmd)
    157118
    158119def which(program):
     120    import os
     121    def is_exe(fpath):
     122        return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
     123
    159124    fpath, fname = os.path.split(program)
    160125    if fpath:
     
    169134    return None
    170135
    171 @contextlib.contextmanager
    172 def tempdir():
    173         cwd = os.getcwd()
    174         with tempfile.TemporaryDirectory() as temp:
    175                 os.chdir(temp)
    176                 try:
    177                         yield temp
    178                 finally:
    179                         os.chdir(cwd)
     136def run(exe, output, input):
     137        ret, _ = sh("timeout %d %s > %s 2>&1" % (settings.timeout.single, exe, output), input = input)
     138        return ret
    180139
    181140################################################################################
     
    184143# move a file
    185144def mv(source, dest):
    186         ret, _ = sh("mv", source, dest)
     145        ret, _ = sh("mv %s %s" % (source, dest))
    187146        return ret
    188147
    189148# cat one file into the other
    190149def cat(source, dest):
    191         ret, _ = sh("cat", source, output=dest)
     150        ret, _ = sh("cat %s > %s" % (source, dest))
    192151        return ret
    193152
     
    204163
    205164# helper function to check if a files contains only a specific string
    206 def file_contains_only(file, text) :
     165def fileContainsOnly(file, text) :
    207166        with open(file) as f:
    208167                ff = f.read().strip()
    209168                result = ff == text.strip()
    210169
    211                 return result
     170                return result;
     171
     172# check whether or not a file is executable
     173def fileIsExecutable(file) :
     174        try :
     175                fileinfo = os.stat(file)
     176                return bool(fileinfo.st_mode & stat.S_IXUSR)
     177        except Exception as inst:
     178                print(type(inst))    # the exception instance
     179                print(inst.args)     # arguments stored in .args
     180                print(inst)
     181                return False
    212182
    213183# transform path to canonical form
    214 def canonical_path(path):
     184def canonicalPath(path):
    215185        abspath = os.path.abspath(__main__.__file__)
    216186        dname = os.path.dirname(abspath)
     
    218188
    219189# compare path even if form is different
    220 def path_cmp(lhs, rhs):
    221         return canonical_path( lhs ) == canonical_path( rhs )
     190def pathCmp(lhs, rhs):
     191        return canonicalPath( lhs ) == canonicalPath( rhs )
    222192
    223193# walk all files in a path
    224 def path_walk( op ):
    225         dname = settings.SRCDIR
    226         for dirname, _, names in os.walk(dname):
     194def pathWalk( op ):
     195        def step(_, dirname, names):
    227196                for name in names:
    228197                        path = os.path.join(dirname, name)
    229198                        op( path )
    230199
     200        # Start the walk
     201        dname = settings.SRCDIR
     202        os.path.walk(dname, step, '')
     203
    231204################################################################################
    232205#               system
    233206################################################################################
    234207# count number of jobs to create
    235 def job_count( options, tests ):
     208def jobCount( options, tests ):
    236209        # check if the user already passed in a number of jobs for multi-threading
    237210        if not options.jobs:
     
    255228        return min( options.jobs, len(tests) ), force
    256229
     230# setup a proper processor pool with correct signal handling
     231def setupPool(jobs):
     232        original_sigint_handler = signal.signal(signal.SIGINT, signal.SIG_IGN)
     233        pool = multiprocessing.Pool(jobs)
     234        signal.signal(signal.SIGINT, original_sigint_handler)
     235
     236        return pool
     237
     238# handle signals in scope
     239class SignalHandling():
     240        def __enter__(self):
     241                # enable signal handling
     242                signal.signal(signal.SIGINT, signal.SIG_DFL)
     243
     244        def __exit__(self, type, value, traceback):
     245                # disable signal handling
     246                signal.signal(signal.SIGINT, signal.SIG_IGN)
     247
     248
    257249# enable core dumps for all the test children
    258250resource.setrlimit(resource.RLIMIT_CORE, (resource.RLIM_INFINITY, resource.RLIM_INFINITY))
     
    269261                return False
    270262        raise argparse.ArgumentTypeError(msg)
     263        return False
    271264
    272265def fancy_print(text):
    273266        column = which('column')
    274267        if column:
    275                 subprocess.run(column, input=bytes(text + "\n", "UTF-8"))
     268                cmd = "%s 2> /dev/null" % column
     269                proc = Popen(cmd, stdin=PIPE, stderr=None, shell=True)
     270                proc.communicate(input=text + "\n")
    276271        else:
    277272                print(text)
    278273
    279274
    280 def core_info(path):
    281         if not os.path.isfile(path):
    282                 return 1, "ERR Executable path is wrong"
    283 
     275def coreInfo(path):
    284276        cmd   = os.path.join(settings.SRCDIR, "pybin/print-core.gdb")
    285277        if not os.path.isfile(cmd):
    286278                return 1, "ERR Printing format for core dumps not found"
    287279
    288         core  = os.path.join(os.getcwd(), "core" )
     280        dname = os.path.dirname(path)
     281        core  = os.path.join(dname, "core" )
     282        if not os.path.isfile(path):
     283                return 1, "ERR Executable path is wrong"
    289284
    290285        if not os.path.isfile(core):
    291286                return 1, "ERR No core dump"
    292287
    293         return sh('gdb', '-n', path, core, '-batch', '-x', cmd, output=subprocess.PIPE)
     288        return sh("gdb -n %s %s -batch -x %s" % (path, core, cmd), print2stdout=False)
    294289
    295290class Timed:
Note: See TracChangeset for help on using the changeset viewer.