Ignore:
Timestamp:
May 24, 2019, 10:19:41 AM (6 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, arm-eh, ast-experimental, cleanup-dtors, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
d908563
Parents:
6a9d4b4 (diff), 292642a (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' into cleanup-dtors

File:
1 edited

Legend:

Unmodified
Added
Removed
  • tests/pybin/tools.py

    r6a9d4b4 r933f32f  
    1 from __future__ import print_function
    2 
    31import __main__
    42import argparse
     3import contextlib
    54import fileinput
    65import multiprocessing
     
    109import signal
    1110import stat
     11import subprocess
    1212import sys
     13import tempfile
    1314import time
     15import types
    1416
    1517from pybin import settings
    16 from subprocess import Popen, PIPE, STDOUT
    1718
    1819################################################################################
     
    2122
    2223# helper functions to run terminal commands
    23 def sh(cmd, print2stdout = True, input = None):
    24         # add input redirection if needed
    25         if input and os.path.isfile(input):
    26                 cmd += " < %s" % input
     24def sh(*cmd, timeout = False, output = None, input = None, error = subprocess.STDOUT):
     25        cmd = list(cmd)
    2726
    2827        # if this is a dry_run, only print the commands that would be ran
    2928        if settings.dry_run :
    30                 print("cmd: %s" % cmd)
     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)
    3143                return 0, None
    3244
    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
     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)
    3867
    3968def is_ascii(fname):
     
    4574                return False
    4675
    47         code, out = sh("file %s" % fname, print2stdout = False)
     76        code, out = sh("file %s" % fname, output=subprocess.PIPE)
    4877        if code != 0:
    4978                return False
     
    5685        return match.group(1).startswith("ASCII text")
    5786
     87def is_exe(fname):
     88        return os.path.isfile(fname) and os.access(fname, os.X_OK)
     89
     90def 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
     103
    58104# Remove 1 or more files silently
    59105def rm( files ):
    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 )
     106        if isinstance(files, str ): files = [ files ]
     107        for file in files:
     108                sh( 'rm', '-f', file, output=subprocess.DEVNULL, error=subprocess.DEVNULL )
    65109
    66110# Create 1 or more directory
    67111def mkdir( files ):
    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) )
     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 )
    73117
    74118
     
    80124# diff two files
    81125def 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 
    100126        # fetch return code and error from the diff command
    101         return sh(diff_cmd % (lhs, rhs), False)
     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        )
    102141
    103142# call make
    104 def 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 '',
     143def 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,
    109148                test_param,
    110149                settings.arch.flags,
     
    112151                settings.install.flags,
    113152                flags,
    114                 target,
    115                 redirects
    116         ])
    117         return sh(cmd)
     153                target
     154        ]
     155        cmd = [s for s in cmd if s]
     156        return sh(*cmd, output=output, error=error)
    118157
    119158def which(program):
    120     import os
    121     def is_exe(fpath):
    122         return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
    123 
    124159    fpath, fname = os.path.split(program)
    125160    if fpath:
     
    134169    return None
    135170
    136 def run(exe, output, input):
    137         ret, _ = sh("timeout %d %s > %s 2>&1" % (settings.timeout.single, exe, output), input = input)
    138         return ret
     171@contextlib.contextmanager
     172def 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)
    139180
    140181################################################################################
     
    143184# move a file
    144185def mv(source, dest):
    145         ret, _ = sh("mv %s %s" % (source, dest))
     186        ret, _ = sh("mv", source, dest)
    146187        return ret
    147188
    148189# cat one file into the other
    149190def cat(source, dest):
    150         ret, _ = sh("cat %s > %s" % (source, dest))
     191        ret, _ = sh("cat", source, output=dest)
    151192        return ret
    152193
     
    163204
    164205# helper function to check if a files contains only a specific string
    165 def fileContainsOnly(file, text) :
     206def file_contains_only(file, text) :
    166207        with open(file) as f:
    167208                ff = f.read().strip()
    168209                result = ff == text.strip()
    169210
    170                 return result;
    171 
    172 # check whether or not a file is executable
    173 def 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
     211                return result
    182212
    183213# transform path to canonical form
    184 def canonicalPath(path):
     214def canonical_path(path):
    185215        abspath = os.path.abspath(__main__.__file__)
    186216        dname = os.path.dirname(abspath)
     
    188218
    189219# compare path even if form is different
    190 def pathCmp(lhs, rhs):
    191         return canonicalPath( lhs ) == canonicalPath( rhs )
     220def path_cmp(lhs, rhs):
     221        return canonical_path( lhs ) == canonical_path( rhs )
    192222
    193223# walk all files in a path
    194 def pathWalk( op ):
    195         def step(_, dirname, names):
     224def path_walk( op ):
     225        dname = settings.SRCDIR
     226        for dirname, _, names in os.walk(dname):
    196227                for name in names:
    197228                        path = os.path.join(dirname, name)
    198229                        op( path )
    199230
    200         # Start the walk
    201         dname = settings.SRCDIR
    202         os.path.walk(dname, step, '')
    203 
    204231################################################################################
    205232#               system
    206233################################################################################
    207234# count number of jobs to create
    208 def jobCount( options, tests ):
     235def job_count( options, tests ):
    209236        # check if the user already passed in a number of jobs for multi-threading
    210237        if not options.jobs:
     
    228255        return min( options.jobs, len(tests) ), force
    229256
    230 # setup a proper processor pool with correct signal handling
    231 def 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
    239 class 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 
    249257# enable core dumps for all the test children
    250258resource.setrlimit(resource.RLIMIT_CORE, (resource.RLIM_INFINITY, resource.RLIM_INFINITY))
     
    261269                return False
    262270        raise argparse.ArgumentTypeError(msg)
    263         return False
    264271
    265272def fancy_print(text):
    266273        column = which('column')
    267274        if column:
    268                 cmd = "%s 2> /dev/null" % column
    269                 proc = Popen(cmd, stdin=PIPE, stderr=None, shell=True)
    270                 proc.communicate(input=text + "\n")
     275                subprocess.run(column, input=bytes(text + "\n", "UTF-8"))
    271276        else:
    272277                print(text)
    273278
    274279
    275 def coreInfo(path):
     280def core_info(path):
     281        if not os.path.isfile(path):
     282                return 1, "ERR Executable path is wrong"
     283
    276284        cmd   = os.path.join(settings.SRCDIR, "pybin/print-core.gdb")
    277285        if not os.path.isfile(cmd):
    278286                return 1, "ERR Printing format for core dumps not found"
    279287
    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"
     288        core  = os.path.join(os.getcwd(), "core" )
    284289
    285290        if not os.path.isfile(core):
    286291                return 1, "ERR No core dump"
    287292
    288         return sh("gdb -n %s %s -batch -x %s" % (path, core, cmd), print2stdout=False)
     293        return sh('gdb', '-n', path, core, '-batch', '-x', cmd, output=subprocess.PIPE)
    289294
    290295class Timed:
Note: See TracChangeset for help on using the changeset viewer.