Changeset 933f32f for tests/pybin/tools.py
- Timestamp:
- May 24, 2019, 10:19:41 AM (6 years ago)
- 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. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
tests/pybin/tools.py
r6a9d4b4 r933f32f 1 from __future__ import print_function2 3 1 import __main__ 4 2 import argparse 3 import contextlib 5 4 import fileinput 6 5 import multiprocessing … … 10 9 import signal 11 10 import stat 11 import subprocess 12 12 import sys 13 import tempfile 13 14 import time 15 import types 14 16 15 17 from pybin import settings 16 from subprocess import Popen, PIPE, STDOUT17 18 18 19 ################################################################################ … … 21 22 22 23 # 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 24 def sh(*cmd, timeout = False, output = None, input = None, error = subprocess.STDOUT): 25 cmd = list(cmd) 27 26 28 27 # if this is a dry_run, only print the commands that would be ran 29 28 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) 31 43 return 0, None 32 44 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) 38 67 39 68 def is_ascii(fname): … … 45 74 return False 46 75 47 code, out = sh("file %s" % fname, print2stdout = False)76 code, out = sh("file %s" % fname, output=subprocess.PIPE) 48 77 if code != 0: 49 78 return False … … 56 85 return match.group(1).startswith("ASCII text") 57 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 103 58 104 # Remove 1 or more files silently 59 105 def 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 ) 65 109 66 110 # Create 1 or more directory 67 111 def 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 ) 73 117 74 118 … … 80 124 # diff two files 81 125 def diff( lhs, rhs ): 82 # diff the output of the files83 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 100 126 # 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 ) 102 141 103 142 # 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 '',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, 109 148 test_param, 110 149 settings.arch.flags, … … 112 151 settings.install.flags, 113 152 flags, 114 target ,115 redirects116 ])117 return sh( cmd)153 target 154 ] 155 cmd = [s for s in cmd if s] 156 return sh(*cmd, output=output, error=error) 118 157 119 158 def which(program): 120 import os121 def is_exe(fpath):122 return os.path.isfile(fpath) and os.access(fpath, os.X_OK)123 124 159 fpath, fname = os.path.split(program) 125 160 if fpath: … … 134 169 return None 135 170 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 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) 139 180 140 181 ################################################################################ … … 143 184 # move a file 144 185 def mv(source, dest): 145 ret, _ = sh("mv %s %s" % (source, dest))186 ret, _ = sh("mv", source, dest) 146 187 return ret 147 188 148 189 # cat one file into the other 149 190 def cat(source, dest): 150 ret, _ = sh("cat %s > %s" % (source, dest))191 ret, _ = sh("cat", source, output=dest) 151 192 return ret 152 193 … … 163 204 164 205 # helper function to check if a files contains only a specific string 165 def file ContainsOnly(file, text) :206 def file_contains_only(file, text) : 166 207 with open(file) as f: 167 208 ff = f.read().strip() 168 209 result = ff == text.strip() 169 210 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 182 212 183 213 # transform path to canonical form 184 def canonical Path(path):214 def canonical_path(path): 185 215 abspath = os.path.abspath(__main__.__file__) 186 216 dname = os.path.dirname(abspath) … … 188 218 189 219 # compare path even if form is different 190 def path Cmp(lhs, rhs):191 return canonical Path( lhs ) == canonicalPath( rhs )220 def path_cmp(lhs, rhs): 221 return canonical_path( lhs ) == canonical_path( rhs ) 192 222 193 223 # walk all files in a path 194 def pathWalk( op ): 195 def step(_, dirname, names): 224 def path_walk( op ): 225 dname = settings.SRCDIR 226 for dirname, _, names in os.walk(dname): 196 227 for name in names: 197 228 path = os.path.join(dirname, name) 198 229 op( path ) 199 230 200 # Start the walk201 dname = settings.SRCDIR202 os.path.walk(dname, step, '')203 204 231 ################################################################################ 205 232 # system 206 233 ################################################################################ 207 234 # count number of jobs to create 208 def job Count( options, tests ):235 def job_count( options, tests ): 209 236 # check if the user already passed in a number of jobs for multi-threading 210 237 if not options.jobs: … … 228 255 return min( options.jobs, len(tests) ), force 229 256 230 # setup a proper processor pool with correct signal handling231 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 pool237 238 # handle signals in scope239 class SignalHandling():240 def __enter__(self):241 # enable signal handling242 signal.signal(signal.SIGINT, signal.SIG_DFL)243 244 def __exit__(self, type, value, traceback):245 # disable signal handling246 signal.signal(signal.SIGINT, signal.SIG_IGN)247 248 249 257 # enable core dumps for all the test children 250 258 resource.setrlimit(resource.RLIMIT_CORE, (resource.RLIM_INFINITY, resource.RLIM_INFINITY)) … … 261 269 return False 262 270 raise argparse.ArgumentTypeError(msg) 263 return False264 271 265 272 def fancy_print(text): 266 273 column = which('column') 267 274 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")) 271 276 else: 272 277 print(text) 273 278 274 279 275 def coreInfo(path): 280 def core_info(path): 281 if not os.path.isfile(path): 282 return 1, "ERR Executable path is wrong" 283 276 284 cmd = os.path.join(settings.SRCDIR, "pybin/print-core.gdb") 277 285 if not os.path.isfile(cmd): 278 286 return 1, "ERR Printing format for core dumps not found" 279 287 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" ) 284 289 285 290 if not os.path.isfile(core): 286 291 return 1, "ERR No core dump" 287 292 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) 289 294 290 295 class Timed:
Note:
See TracChangeset
for help on using the changeset viewer.