Changes in / [86ad276:5da9d6a]
- Location:
- src/tests
- Files:
-
- 66 added
- 68 deleted
- 4 edited
-
.expect/32/KRfunctions.txt (added)
-
.expect/32/attributes.txt (added)
-
.expect/32/declarationSpecifier.txt (added)
-
.expect/32/extension.txt (added)
-
.expect/32/functions.txt (added)
-
.expect/32/gccExtensions.txt (added)
-
.expect/32/literals.txt (added)
-
.expect/32/math1.txt (added)
-
.expect/32/math2.txt (added)
-
.expect/32/math3.txt (added)
-
.expect/64/KRfunctions.txt (added)
-
.expect/64/attributes.txt (added)
-
.expect/64/declarationSpecifier.txt (added)
-
.expect/64/extension.txt (added)
-
.expect/64/functions.txt (added)
-
.expect/64/gccExtensions.txt (added)
-
.expect/64/gmp.txt (added)
-
.expect/64/literals.txt (added)
-
.expect/64/math1.txt (added)
-
.expect/64/math2.txt (added)
-
.expect/64/math3.txt (added)
-
.expect/KRfunctions.x64.txt (deleted)
-
.expect/KRfunctions.x86.txt (deleted)
-
.expect/attributes.x64.txt (deleted)
-
.expect/attributes.x86.txt (deleted)
-
.expect/concurrent/boundedBuffer.txt (added)
-
.expect/concurrent/coroutine.txt (added)
-
.expect/concurrent/datingService.txt (added)
-
.expect/concurrent/fmtLines.txt (added)
-
.expect/concurrent/matrixSum.txt (added)
-
.expect/concurrent/monitor.txt (added)
-
.expect/concurrent/multi-monitor.txt (added)
-
.expect/concurrent/pingpong.txt (added)
-
.expect/concurrent/preempt.txt (added)
-
.expect/concurrent/prodcons.txt (added)
-
.expect/concurrent/sched-ext-barge.txt (added)
-
.expect/concurrent/sched-ext-dtor.txt (added)
-
.expect/concurrent/sched-ext-else.txt (added)
-
.expect/concurrent/sched-ext-recurse.txt (added)
-
.expect/concurrent/sched-ext-statment.txt (added)
-
.expect/concurrent/sched-ext-when.txt (added)
-
.expect/concurrent/sched-int-block.txt (added)
-
.expect/concurrent/sched-int-disjoint.txt (added)
-
.expect/concurrent/sched-int-wait.txt (added)
-
.expect/concurrent/thread.txt (added)
-
.expect/declarationSpecifier.x64.txt (deleted)
-
.expect/declarationSpecifier.x86.txt (deleted)
-
.expect/extension.x64.txt (deleted)
-
.expect/extension.x86.txt (deleted)
-
.expect/functions.x64.txt (deleted)
-
.expect/functions.x86.txt (deleted)
-
.expect/gccExtensions.x64.txt (deleted)
-
.expect/gccExtensions.x86.txt (deleted)
-
.expect/gmp.x64.txt (deleted)
-
.expect/literals.x64.txt (deleted)
-
.expect/literals.x86.txt (deleted)
-
.expect/math1.x64.txt (deleted)
-
.expect/math1.x86.txt (deleted)
-
.expect/math2.x64.txt (deleted)
-
.expect/math2.x86.txt (deleted)
-
.expect/math3.x64.txt (deleted)
-
.expect/math3.x86.txt (deleted)
-
.in/fmtLines.txt (added)
-
Makefile.am (modified) (4 diffs)
-
Makefile.in (modified) (4 diffs)
-
boundedBuffer.c (added)
-
concurrent/.expect/monitor.txt (deleted)
-
concurrent/.expect/multi-monitor.txt (deleted)
-
concurrent/.expect/preempt.txt (deleted)
-
concurrent/.expect/thread.txt (deleted)
-
concurrent/examples/.expect/boundedBuffer.txt (deleted)
-
concurrent/examples/.expect/datingService.txt (deleted)
-
concurrent/examples/.expect/matrixSum.txt (deleted)
-
concurrent/examples/boundedBuffer.c (deleted)
-
concurrent/examples/datingService.c (deleted)
-
concurrent/examples/matrixSum.c (deleted)
-
concurrent/monitor.c (deleted)
-
concurrent/multi-monitor.c (deleted)
-
concurrent/preempt.c (deleted)
-
concurrent/signal/.expect/block.txt (deleted)
-
concurrent/signal/.expect/disjoint.txt (deleted)
-
concurrent/signal/.expect/wait.txt (deleted)
-
concurrent/signal/barge.c (deleted)
-
concurrent/signal/block.c (deleted)
-
concurrent/signal/disjoint.c (deleted)
-
concurrent/signal/wait.c (deleted)
-
concurrent/thread.c (deleted)
-
concurrent/waitfor/.expect/barge.txt (deleted)
-
concurrent/waitfor/.expect/dtor.txt (deleted)
-
concurrent/waitfor/.expect/else.txt (deleted)
-
concurrent/waitfor/.expect/recurse.txt (deleted)
-
concurrent/waitfor/.expect/statment.txt (deleted)
-
concurrent/waitfor/.expect/when.txt (deleted)
-
concurrent/waitfor/barge.c (deleted)
-
concurrent/waitfor/dtor.c (deleted)
-
concurrent/waitfor/else.c (deleted)
-
concurrent/waitfor/parse.c (deleted)
-
concurrent/waitfor/parse2.c (deleted)
-
concurrent/waitfor/recurse.c (deleted)
-
concurrent/waitfor/simple.c (deleted)
-
concurrent/waitfor/statment.c (deleted)
-
concurrent/waitfor/when.c (deleted)
-
coroutine.c (added)
-
coroutine/.expect/coroutine.txt (deleted)
-
coroutine/.expect/fmtLines.txt (deleted)
-
coroutine/.expect/pingpong.txt (deleted)
-
coroutine/.expect/prodcons.txt (deleted)
-
coroutine/.in/fmtLines.txt (deleted)
-
coroutine/coroutine.c (deleted)
-
coroutine/fmtLines.c (deleted)
-
coroutine/pingpong.c (deleted)
-
coroutine/prodcons.c (deleted)
-
datingService.c (added)
-
fmtLines.c (added)
-
matrixSum.c (added)
-
monitor.c (added)
-
multi-monitor.c (added)
-
pingpong.c (added)
-
preempt.c (added)
-
prodcons.c (added)
-
pybin/settings.py (deleted)
-
pybin/test_run.py (deleted)
-
pybin/tools.py (modified) (4 diffs)
-
sched-ext-barge.c (added)
-
sched-ext-dtor.c (added)
-
sched-ext-else.c (added)
-
sched-ext-parse.c (added)
-
sched-ext-recurse.c (added)
-
sched-ext-statment.c (added)
-
sched-ext-when.c (added)
-
sched-ext.c (added)
-
sched-int-barge.c (added)
-
sched-int-block.c (added)
-
sched-int-disjoint.c (added)
-
sched-int-wait.c (added)
-
test.py (modified) (11 diffs)
-
thread.c (added)
-
waitfor.c (added)
Legend:
- Unmodified
- Added
- Removed
-
src/tests/Makefile.am
r86ad276 r5da9d6a 20 20 21 21 if BUILD_CONCURRENCY 22 concurrent= 22 concurrent = yes 23 quick_test += coroutine thread monitor 24 concurrent_test = \ 25 coroutine \ 26 fmtLines \ 27 pingpong \ 28 prodcons \ 29 thread \ 30 matrixSum \ 31 monitor \ 32 multi-monitor \ 33 boundedBuffer \ 34 preempt \ 35 sched-int-block \ 36 sched-int-disjoint \ 37 sched-int-wait \ 38 sched-ext-barge \ 39 sched-ext-dtor \ 40 sched-ext-else \ 41 sched-ext-parse \ 42 sched-ext-recurse \ 43 sched-ext-statment \ 44 sched-ext-when 23 45 else 24 concurrent='-Econcurrent' 46 concurrent=no 47 concurrent_test= 25 48 endif 26 49 … … 39 62 endif 40 63 41 TEST_FLAGS = $(if $(test), 2> $(test), )64 TEST_FLAGS = $(if $(test), 2> .err/${@}.log, ) 42 65 AM_CFLAGS = ${TEST_FLAGS} ${BUILD_FLAGS} 43 66 CC = @CFA_BINDIR@/@CFA_NAME@ … … 47 70 48 71 fstream_test_SOURCES = fstream_test.c 49 fstream_test_CFLAGS = $(if $(test), 2>> $(test), ) ${BUILD_FLAGS}72 fstream_test_CFLAGS = $(if $(test), 2>> .err/fstream_test.log, ) ${BUILD_FLAGS} 50 73 51 74 vector_test_SOURCES = vector/vector_int.c vector/array.c vector/vector_test.c 52 vector_test_CFLAGS = $(if $(test), 2>> $(test), ) ${BUILD_FLAGS}75 vector_test_CFLAGS = $(if $(test), 2>> .err/vector_test.log, ) ${BUILD_FLAGS} 53 76 54 77 avl_test_SOURCES = avltree/avl_test.c avltree/avl0.c avltree/avl1.c avltree/avl2.c avltree/avl3.c avltree/avl4.c avltree/avl-private.c 55 avl_test_CFLAGS = $(if $(test), 2>> $(test), ) ${BUILD_FLAGS}78 avl_test_CFLAGS = $(if $(test), 2>> .err/avl_test.log, ) ${BUILD_FLAGS} 56 79 57 80 all-local : 58 @+python test.py --debug=${debug} ${concurrent} ${quick_test}81 @+python test.py --debug=${debug} --concurrent=${concurrent} ${quick_test} 59 82 60 83 all-tests : 61 @+python test.py --all --debug=${debug} ${concurrent} # '@' => do not echo command (SILENT), '+' => allows recursive make from within python program84 @+python test.py --all --debug=${debug} --concurrent=${concurrent} # '@' => do not echo command (SILENT), '+' => allows recursive make from within python program 62 85 63 86 clean-local : … … 65 88 66 89 list : 67 @+python test.py --list ${concurrent}90 @+python test.py --list --concurrent=${concurrent} 68 91 69 92 concurrency : 70 @+python test.py --debug=${debug} ${concurrent} ${concurrent_test}93 @+python test.py --debug=${debug} --concurrent=${concurrent} ${concurrent_test} 71 94 72 95 .dummy : .dummy.c @CFA_BINDIR@/@CFA_NAME@ -
src/tests/Makefile.in
r86ad276 r5da9d6a 91 91 build_triplet = @build@ 92 92 host_triplet = @host@ 93 @BUILD_DEBUG_FALSE@am__append_1 = -nodebug 94 @BUILD_DEBUG_TRUE@@BUILD_RELEASE_FALSE@am__append_2 = -debug 95 @BUILD_DEBUG_TRUE@@BUILD_RELEASE_TRUE@am__append_3 = ${DEBUG_FLAGS} 93 @BUILD_CONCURRENCY_TRUE@am__append_1 = coroutine thread monitor 94 @BUILD_DEBUG_FALSE@am__append_2 = -nodebug 95 @BUILD_DEBUG_TRUE@@BUILD_RELEASE_FALSE@am__append_3 = -debug 96 @BUILD_DEBUG_TRUE@@BUILD_RELEASE_TRUE@am__append_4 = ${DEBUG_FLAGS} 96 97 EXTRA_PROGRAMS = fstream_test$(EXEEXT) vector_test$(EXEEXT) \ 97 98 avl_test$(EXEEXT) … … 313 314 top_srcdir = @top_srcdir@ 314 315 debug = yes 315 quick_test = vector_test avl_test operators numericConstants expression enum array typeof cast dtor-early-exit init_once attributes 316 @BUILD_CONCURRENCY_FALSE@concurrent = '-Econcurrent' 317 @BUILD_CONCURRENCY_TRUE@concurrent = 316 quick_test = vector_test avl_test operators numericConstants \ 317 expression enum array typeof cast dtor-early-exit init_once \ 318 attributes $(am__append_1) 319 @BUILD_CONCURRENCY_FALSE@concurrent = no 320 @BUILD_CONCURRENCY_TRUE@concurrent = yes 321 @BUILD_CONCURRENCY_FALSE@concurrent_test = 322 @BUILD_CONCURRENCY_TRUE@concurrent_test = \ 323 @BUILD_CONCURRENCY_TRUE@ coroutine \ 324 @BUILD_CONCURRENCY_TRUE@ fmtLines \ 325 @BUILD_CONCURRENCY_TRUE@ pingpong \ 326 @BUILD_CONCURRENCY_TRUE@ prodcons \ 327 @BUILD_CONCURRENCY_TRUE@ thread \ 328 @BUILD_CONCURRENCY_TRUE@ matrixSum \ 329 @BUILD_CONCURRENCY_TRUE@ monitor \ 330 @BUILD_CONCURRENCY_TRUE@ multi-monitor \ 331 @BUILD_CONCURRENCY_TRUE@ boundedBuffer \ 332 @BUILD_CONCURRENCY_TRUE@ preempt \ 333 @BUILD_CONCURRENCY_TRUE@ sched-int-block \ 334 @BUILD_CONCURRENCY_TRUE@ sched-int-disjoint \ 335 @BUILD_CONCURRENCY_TRUE@ sched-int-wait \ 336 @BUILD_CONCURRENCY_TRUE@ sched-ext-barge \ 337 @BUILD_CONCURRENCY_TRUE@ sched-ext-dtor \ 338 @BUILD_CONCURRENCY_TRUE@ sched-ext-else \ 339 @BUILD_CONCURRENCY_TRUE@ sched-ext-parse \ 340 @BUILD_CONCURRENCY_TRUE@ sched-ext-recurse \ 341 @BUILD_CONCURRENCY_TRUE@ sched-ext-statment \ 342 @BUILD_CONCURRENCY_TRUE@ sched-ext-when 343 318 344 319 345 # applies to both programs 320 346 DEBUG_FLAGS = 321 347 BUILD_FLAGS = -g -Wall -Wno-unused-function -quiet @CFA_FLAGS@ \ 322 $(am__append_ 1) $(am__append_2) $(am__append_3)323 TEST_FLAGS = $(if $(test), 2> $(test), )348 $(am__append_2) $(am__append_3) $(am__append_4) 349 TEST_FLAGS = $(if $(test), 2> .err/${@}.log, ) 324 350 AM_CFLAGS = ${TEST_FLAGS} ${BUILD_FLAGS} 325 351 fstream_test_SOURCES = fstream_test.c 326 fstream_test_CFLAGS = $(if $(test), 2>> $(test), ) ${BUILD_FLAGS}352 fstream_test_CFLAGS = $(if $(test), 2>> .err/fstream_test.log, ) ${BUILD_FLAGS} 327 353 vector_test_SOURCES = vector/vector_int.c vector/array.c vector/vector_test.c 328 vector_test_CFLAGS = $(if $(test), 2>> $(test), ) ${BUILD_FLAGS}354 vector_test_CFLAGS = $(if $(test), 2>> .err/vector_test.log, ) ${BUILD_FLAGS} 329 355 avl_test_SOURCES = avltree/avl_test.c avltree/avl0.c avltree/avl1.c avltree/avl2.c avltree/avl3.c avltree/avl4.c avltree/avl-private.c 330 avl_test_CFLAGS = $(if $(test), 2>> $(test), ) ${BUILD_FLAGS}356 avl_test_CFLAGS = $(if $(test), 2>> .err/avl_test.log, ) ${BUILD_FLAGS} 331 357 all: all-am 332 358 … … 807 833 808 834 all-local : 809 @+python test.py --debug=${debug} ${concurrent} ${quick_test}835 @+python test.py --debug=${debug} --concurrent=${concurrent} ${quick_test} 810 836 811 837 all-tests : 812 @+python test.py --all --debug=${debug} ${concurrent} # '@' => do not echo command (SILENT), '+' => allows recursive make from within python program838 @+python test.py --all --debug=${debug} --concurrent=${concurrent} # '@' => do not echo command (SILENT), '+' => allows recursive make from within python program 813 839 814 840 clean-local : … … 816 842 817 843 list : 818 @+python test.py --list ${concurrent}844 @+python test.py --list --concurrent=${concurrent} 819 845 820 846 concurrency : 821 @+python test.py --debug=${debug} ${concurrent} ${concurrent_test}847 @+python test.py --debug=${debug} --concurrent=${concurrent} ${concurrent_test} 822 848 823 849 .dummy : .dummy.c @CFA_BINDIR@/@CFA_NAME@ -
src/tests/pybin/tools.py
r86ad276 r5da9d6a 1 from __future__ import print_function2 3 1 import __main__ 4 2 import argparse 5 import multiprocessing6 3 import os 7 4 import re 8 import signal9 5 import stat 10 import sys11 6 12 from pybin import settings13 7 from subprocess import Popen, PIPE, STDOUT 14 8 15 ################################################################################16 # shell helpers17 ################################################################################18 19 9 # helper functions to run terminal commands 20 def 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 : 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 27 12 print("cmd: %s" % cmd) 28 13 return 0, None 29 30 # otherwise create a pipe and run the desired command 31 else : 14 else : # otherwise create a pipe and run the desired command 32 15 proc = Popen(cmd, stdout=None if print2stdout else PIPE, stderr=STDOUT, shell=True) 33 16 out, err = proc.communicate() … … 35 18 36 19 # Remove 1 or more files silently 37 def rm( files ):20 def rm( files, dry_run = False ): 38 21 try: 39 22 for file in files: 40 sh("rm -f %s > /dev/null 2>&1" % file )23 sh("rm -f %s > /dev/null 2>&1" % file, dry_run) 41 24 except TypeError: 42 sh("rm -f %s > /dev/null 2>&1" % files )25 sh("rm -f %s > /dev/null 2>&1" % files, dry_run) 43 26 44 27 def chdir( dest = __main__.__file__ ): … … 47 30 os.chdir(dname) 48 31 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 spacific 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 49 76 # diff two files 50 def diff( lhs, rhs ):77 def diff( lhs, rhs, dry_run ): 51 78 # diff the output of the files 52 79 diff_cmd = ("diff --ignore-all-space " … … 67 94 68 95 # fetch return code and error from the diff command 69 return sh(diff_cmd % (lhs, rhs), False) 70 71 # call make 72 def 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 settings.debug.flags, 79 flags, 80 target, 81 redirects 82 ]) 83 return sh(cmd) 84 85 ################################################################################ 86 # file handling 87 ################################################################################ 88 89 # helper function to replace patterns in a file 90 def file_replace(fname, pat, s_after): 91 # first, see if the pattern is even in the file. 92 with open(fname) as f: 93 if not any(re.search(pat, line) for line in f): 94 return # pattern does not occur in file so we are done. 95 96 # pattern is in the file, so perform replace operation. 97 with open(fname) as f: 98 out_fname = fname + ".tmp" 99 out = open(out_fname, "w") 100 for line in f: 101 out.write(re.sub(pat, s_after, line)) 102 out.close() 103 os.rename(out_fname, fname) 104 105 # helper function to check if a files contains only a specific string 106 def fileContainsOnly(file, text) : 107 with open(file) as f: 108 ff = f.read().strip() 109 result = ff == text.strip() 110 111 return result; 112 113 # check whether or not a file is executable 114 def fileIsExecutable(file) : 115 try : 116 fileinfo = os.stat(file) 117 return bool(fileinfo.st_mode & stat.S_IXUSR) 118 except Exception as inst: 119 print(type(inst)) # the exception instance 120 print(inst.args) # arguments stored in .args 121 print(inst) 122 return False 123 124 # transform path to canonical form 125 def canonicalPath(path): 126 return os.path.join('.', os.path.normpath(path) ) 127 128 # compare path even if form is different 129 def pathCmp(lhs, rhs): 130 return canonicalPath( lhs ) == canonicalPath( rhs ) 131 132 # walk all files in a path 133 def pathWalk( op ): 134 def step(_, dirname, names): 135 for name in names: 136 path = os.path.join(dirname, name) 137 138 op( path ) 139 140 # Start the walk 141 os.path.walk('.', step, '') 142 143 ################################################################################ 144 # system 145 ################################################################################ 146 147 # parses the Makefile to find the machine type (32-bit / 64-bit) 148 def getMachineType(): 149 sh('echo "void ?{}(int&a,int b){}int main(){return 0;}" > .dummy.c') 150 ret, out = make('.dummy', silent = True) 151 152 if ret != 0: 153 print("Failed to identify architecture:") 154 print(out) 155 print("Stopping") 156 rm( (".dummy.c",".dummy") ) 157 sys.exit(1) 158 159 _, out = sh("file .dummy", print2stdout=False) 160 rm( (".dummy.c",".dummy") ) 161 162 if settings.dry_run : 163 return 'x64' 164 165 return re.search(r"[^,]+,([^,]+),", out).group(1).strip() 166 167 # count number of jobs to create 168 def jobCount( options, tests ): 169 # check if the user already passed in a number of jobs for multi-threading 170 make_flags = os.environ.get('MAKEFLAGS') 171 make_jobs_fds = re.search("--jobserver-(auth|fds)=\s*([0-9]+),([0-9]+)", make_flags) if make_flags else None 172 if make_jobs_fds : 173 tokens = os.read(int(make_jobs_fds.group(2)), 1024) 174 options.jobs = len(tokens) 175 os.write(int(make_jobs_fds.group(3)), tokens) 176 else : 177 options.jobs = multiprocessing.cpu_count() 178 179 # make sure we have a valid number of jobs that corresponds to user input 180 if options.jobs <= 0 : 181 print('ERROR: Invalid number of jobs', file=sys.stderr) 182 sys.exit(1) 183 184 return min( options.jobs, len(tests) ), True if make_flags else False 185 186 # setup a proper processor pool with correct signal handling 187 def setupPool(jobs): 188 original_sigint_handler = signal.signal(signal.SIGINT, signal.SIG_IGN) 189 pool = multiprocessing.Pool(jobs) 190 signal.signal(signal.SIGINT, original_sigint_handler) 191 192 return pool 193 194 # handle signals in scope 195 class SignalHandling(): 196 def __enter__(self): 197 # enable signal handling 198 signal.signal(signal.SIGINT, signal.SIG_DFL) 199 200 def __exit__(self, type, value, traceback): 201 # disable signal handling 202 signal.signal(signal.SIGINT, signal.SIG_IGN) 203 204 ################################################################################ 205 # misc 206 ################################################################################ 207 208 # check if arguments is yes or no 209 def yes_no(string): 210 if string == "yes" : 211 return True 212 if string == "no" : 213 return False 214 raise argparse.ArgumentTypeError(msg) 215 return False 216 217 218 settings.set_machine_default( getMachineType ) 96 return sh(diff_cmd % (lhs, rhs), dry_run, False) -
src/tests/test.py
r86ad276 r5da9d6a 2 2 from __future__ import print_function 3 3 4 from functools import partial 5 from multiprocessing import Pool 6 from os import listdir, environ 7 from os.path import isfile, join, splitext 4 8 from pybin.tools import * 5 from pybin.test_run import *6 from pybin import settings7 9 8 10 import argparse 11 import multiprocessing 12 import os 9 13 import re 14 import signal 10 15 import sys 11 16 … … 14 19 ################################################################################ 15 20 16 def findTests(): 17 expected = [] 18 19 def matchTest(path): 20 match = re.search("(\.[\w\/\-_]*)\/.expect\/([\w\-_]+)(\.[\w\-_]+)?\.txt", path) 21 if match : 22 test = Test() 23 test.name = match.group(2) 24 test.path = match.group(1) 25 test.arch = match.group(3)[1:] if match.group(3) else None 26 if settings.arch.match(test.arch): 27 expected.append(test) 28 29 pathWalk( matchTest ) 30 31 return expected 21 # Test class that defines what a test is 22 class Test: 23 def __init__(self, name, path): 24 self.name, self.path = name, path 25 26 class TestResult: 27 SUCCESS = 0 28 FAILURE = 1 29 TIMEOUT = 124 30 31 # parses the Makefile to find the machine type (32-bit / 64-bit) 32 def getMachineType(): 33 sh('echo "void ?{}(int&a,int b){}int main(){return 0;}" > .dummy.c') 34 ret, out = sh("make .dummy -s", print2stdout=True) 35 36 if ret != 0: 37 print("Failed to identify architecture:") 38 print(out) 39 print("Stopping") 40 rm( (".dummy.c",".dummy") ) 41 sys.exit(1) 42 43 _, out = sh("file .dummy", print2stdout=False) 44 rm( (".dummy.c",".dummy") ) 45 46 return re.search("ELF\s([0-9]+)-bit", out).group(1) 47 48 def listTestsFolder(folder) : 49 path = ('./.expect/%s/' % folder) if folder else './.expect/' 50 subpath = "%s/" % folder if folder else "" 51 52 # tests directly in the .expect folder will always be processed 53 return map(lambda fname: Test(fname, subpath + fname), 54 [splitext(f)[0] for f in listdir( path ) 55 if not f.startswith('.') and f.endswith('.txt') 56 ]) 32 57 33 58 # reads the directory ./.expect and indentifies the tests 34 def listTests( includes, excludes ): 35 includes = [canonicalPath( i ) for i in includes] if includes else None 36 excludes = [canonicalPath( i ) for i in excludes] if excludes else None 59 def listTests( concurrent ): 60 machineType = getMachineType() 37 61 38 62 # tests directly in the .expect folder will always be processed 39 test_list = findTests() 40 41 # if we have a limited number of includes, filter by them 42 if includes: 43 test_list = [x for x in test_list if 44 x.path.startswith( tuple(includes) ) 45 ] 46 47 # # if we have a folders to excludes, filter by them 48 if excludes: 49 test_list = [x for x in test_list if not 50 x.path.startswith( tuple(excludes) ) 51 ] 52 53 return test_list 63 generic_list = listTestsFolder( "" ) 64 65 # tests in the machineType folder will be ran only for the corresponding compiler 66 typed_list = listTestsFolder( machineType ) 67 68 # tests in the concurrent folder will be ran only if concurrency is enabled 69 concurrent_list = listTestsFolder( "concurrent" ) if concurrent else [] 70 71 # append both lists to get 72 return generic_list + typed_list + concurrent_list; 54 73 55 74 # from the found tests, filter all the valid tests/desired tests … … 61 80 if options.regenerate_expected : 62 81 for testname in options.tests : 63 if Test.valid_name(testname): 64 found = [test for test in allTests if test.target() == testname] 65 tests.append( found[0] if len(found) == 1 else Test.from_target(testname) ) 82 if testname.endswith( (".c", ".cc", ".cpp") ): 83 print('ERROR: "%s", tests are not allowed to end with a C/C++/CFA extension, ignoring it' % testname, file=sys.stderr) 66 84 else : 67 print('ERROR: "%s", tests are not allowed to end with a C/C++/CFA extension, ignoring it' % testname, file=sys.stderr) 85 found = [test for test in allTests if test.name == testname] 86 tests.append( found[0] if len(found) == 1 else Test(testname, testname) ) 68 87 69 88 else : 70 89 # otherwise we only need to validate that all tests are present in the complete list 71 90 for testname in options.tests: 72 test = [t for t in allTests if pathCmp( t.target(), testname )]73 74 if test:91 test = [t for t in allTests if t.name == testname] 92 93 if len(test) != 0 : 75 94 tests.append( test[0] ) 76 95 else : … … 78 97 79 98 # make sure we have at least some test to run 80 if not tests:99 if len(tests) == 0 : 81 100 print('ERROR: No valid test to run', file=sys.stderr) 82 101 sys.exit(1) … … 89 108 parser = argparse.ArgumentParser(description='Script which runs cforall tests') 90 109 parser.add_argument('--debug', help='Run all tests in debug or release', type=yes_no, default='no') 91 parser.add_argument('-- arch', help='Test for specific architecture', type=str, default='')110 parser.add_argument('--concurrent', help='Run concurrent tests', type=yes_no, default='yes') 92 111 parser.add_argument('--dry-run', help='Don\'t run the tests, only output the commands', action='store_true') 93 112 parser.add_argument('--list', help='List all test available', action='store_true') … … 96 115 parser.add_argument('-j', '--jobs', help='Number of tests to run simultaneously', type=int, default='8') 97 116 parser.add_argument('--list-comp', help='List all valide arguments', action='store_true') 98 parser.add_argument('-I','--include', help='Directory of test to include, can be used multiple time, All if omitted', action='append')99 parser.add_argument('-E','--exclude', help='Directory of test to exclude, can be used multiple time, None if omitted', action='append')100 117 parser.add_argument('tests', metavar='test', type=str, nargs='*', help='a list of tests to run') 101 118 … … 106 123 all_tests = options.all 107 124 some_tests = len(options.tests) > 0 108 some_dirs = len(options.include) > 0 if options.include else 0109 125 110 126 # check that exactly one of the booleans is set to true 111 if not sum( (listing, all_tests, some_tests , some_dirs) ) > 0:112 print('ERROR: must have option \'--all\', \'--list\' , \'--include\', \'-I\'or non-empty test list', file=sys.stderr)127 if not sum( (listing, all_tests, some_tests) ) == 1 : 128 print('ERROR: must have option \'--all\', \'--list\' or non-empty test list', file=sys.stderr) 113 129 parser.print_help() 114 130 sys.exit(1) … … 116 132 return options 117 133 134 def jobCount( options ): 135 # check if the user already passed in a number of jobs for multi-threading 136 make_flags = environ.get('MAKEFLAGS') 137 make_jobs_fds = re.search("--jobserver-(auth|fds)=\s*([0-9]+),([0-9]+)", make_flags) if make_flags else None 138 if make_jobs_fds : 139 tokens = os.read(int(make_jobs_fds.group(2)), 1024) 140 options.jobs = len(tokens) 141 os.write(int(make_jobs_fds.group(3)), tokens) 142 else : 143 options.jobs = multiprocessing.cpu_count() 144 145 # make sure we have a valid number of jobs that corresponds to user input 146 if options.jobs <= 0 : 147 print('ERROR: Invalid number of jobs', file=sys.stderr) 148 sys.exit(1) 149 150 return min( options.jobs, len(tests) ), True if make_flags else False 151 118 152 ################################################################################ 119 153 # running test functions 120 154 ################################################################################ 121 155 # logic to run a single test and return the result (No handling of printing or other test framework logic) 122 def run_single_test(test ):156 def run_single_test(test, generate, dry_run, debug): 123 157 124 158 # find the output file based on the test name and options flag 125 out_file = test.target_output() 126 err_file = test.error_log() 127 cmp_file = test.expect() 128 in_file = test.input() 129 130 # prepare the proper directories 131 test.prepare() 159 out_file = (".out/%s.log" % test.name) if not generate else (".expect/%s.txt" % test.path) 160 err_file = ".err/%s.log" % test.name 132 161 133 162 # remove any outputs from the previous tests to prevent side effects 134 rm( (out_file, err_file, test.target()) ) 163 rm( (out_file, err_file, test.name), dry_run ) 164 165 options = "-debug" if debug else "-nodebug" 135 166 136 167 # build, skipping to next test on error 137 make_ret, _ = make( test.target(),138 redirects = "2> %s 1> /dev/null" % out_file, 139 error_file = err_file140 )168 make_ret, _ = sh("""%s test=yes DEBUG_FLAGS="%s" %s 2> %s 1> /dev/null""" % (make_cmd, options, test.name, out_file), dry_run) 169 170 retcode = 0 171 error = None 141 172 142 173 # if the make command succeds continue otherwise skip to diff 143 if make_ret == 0 or settings.dry_run: 144 if settings.dry_run or fileIsExecutable(test.target()) : 174 if make_ret == 0 : 175 # fetch optional input 176 stdinput = "< .in/%s.txt" % test.name if isfile(".in/%s.txt" % test.name) else "" 177 178 if fileIsExecutable(test.name) : 145 179 # run test 146 retcode, _ = sh("timeout 60 %s > %s 2>&1" % (test.target(), out_file), input = in_file)180 retcode, _ = sh("timeout 60 ./%s %s > %s 2>&1" % (test.name, stdinput, out_file), dry_run) 147 181 else : 148 182 # simply cat the result into the output 149 retcode, _ = sh("cat %s > %s" % (test.target(), out_file)) 150 else: 151 retcode, _ = sh("mv %s %s" % (err_file, out_file)) 152 183 sh("cat %s > %s" % (test.name, out_file), dry_run) 184 185 else : 186 # command failed save the log to less temporary file 187 sh("mv %s %s" % (err_file, out_file), dry_run) 153 188 154 189 if retcode == 0: 155 if settings.generating:190 if generate : 156 191 # if we are ounly generating the output we still need to check that the test actually exists 157 if not settings.dry_run and fileContainsOnly(out_file, "make: *** No rule to make target `%s'. Stop." % test.target()) :192 if not dry_run and fileContainsOnly(out_file, "make: *** No rule to make target `%s'. Stop." % test.name) : 158 193 retcode = 1; 159 error = "\t\tNo make target for test %s!" % test. target()194 error = "\t\tNo make target for test %s!" % test.name 160 195 sh("rm %s" % out_file, False) 161 else:162 error = None163 196 else : 164 197 # fetch return code and error from the diff command 165 retcode, error = diff( cmp_file, out_file)198 retcode, error = diff(".expect/%s.txt" % test.path, ".out/%s.log" % test.name, dry_run) 166 199 167 200 else: … … 171 204 172 205 # clean the executable 173 sh("rm -f %s > /dev/null 2>&1" % test. target())206 sh("rm -f %s > /dev/null 2>&1" % test.name, dry_run) 174 207 175 208 return retcode, error 176 209 177 210 # run a single test and handle the errors, outputs, printing, exception handling, etc. 178 def run_test_worker(t) : 179 180 with SignalHandling(): 181 # print formated name 182 name_txt = "%20s " % t.name 183 184 retcode, error = run_single_test(t) 185 186 # update output based on current action 187 result_txt = TestResult.toString( retcode ) 188 189 #print result with error if needed 190 text = name_txt + result_txt 191 out = sys.stdout 192 if error : 193 text = text + "\n" + error 194 out = sys.stderr 195 196 print(text, file = out) 197 sys.stdout.flush() 198 sys.stderr.flush() 211 def run_test_worker(t, generate, dry_run, debug) : 212 213 signal.signal(signal.SIGINT, signal.SIG_DFL) 214 # print formated name 215 name_txt = "%20s " % t.name 216 217 retcode, error = run_single_test(t, generate, dry_run, debug) 218 219 # update output based on current action 220 if generate : 221 if retcode == TestResult.SUCCESS: result_txt = "Done" 222 elif retcode == TestResult.TIMEOUT: result_txt = "TIMEOUT" 223 else : result_txt = "ERROR code %d" % retcode 224 else : 225 if retcode == TestResult.SUCCESS: result_txt = "PASSED" 226 elif retcode == TestResult.TIMEOUT: result_txt = "TIMEOUT" 227 else : result_txt = "FAILED with code %d" % retcode 228 229 #print result with error if needed 230 text = name_txt + result_txt 231 out = sys.stdout 232 if error : 233 text = text + "\n" + error 234 out = sys.stderr 235 236 print(text, file = out) 237 sys.stdout.flush() 238 sys.stderr.flush() 239 signal.signal(signal.SIGINT, signal.SIG_IGN) 199 240 200 241 return retcode != TestResult.SUCCESS 201 242 202 243 # run the given list of tests with the given parameters 203 def run_tests(tests, jobs) :244 def run_tests(tests, generate, dry_run, jobs, debug) : 204 245 # clean the sandbox from previous commands 205 make('clean', redirects = '> /dev/null 2>&1') 246 sh("%s clean > /dev/null 2>&1" % make_cmd, dry_run) 247 248 # make sure the required folder are present 249 sh('mkdir -p .out .expect .err', dry_run) 250 251 if generate : 252 print( "Regenerate tests for: " ) 206 253 207 254 # create the executor for our jobs and handle the signal properly 208 pool = setupPool(jobs) 255 original_sigint_handler = signal.signal(signal.SIGINT, signal.SIG_IGN) 256 pool = Pool(jobs) 257 signal.signal(signal.SIGINT, original_sigint_handler) 209 258 210 259 # for each test to run 211 260 try : 212 results = pool.map_async( 213 run_test_worker, 214 tests, 215 chunksize = 1 216 ).get(7200) 261 results = pool.map_async(partial(run_test_worker, generate=generate, dry_run=dry_run, debug=debug), tests, chunksize = 1 ).get(7200) 217 262 except KeyboardInterrupt: 218 263 pool.terminate() … … 221 266 222 267 # clean the workspace 223 make('clean', redirects = '> /dev/null 2>&1')268 sh("%s clean > /dev/null 2>&1" % make_cmd, dry_run) 224 269 225 270 for failed in results: … … 240 285 options = getOptions() 241 286 242 # init global settings243 settings.init( options )244 245 287 # fetch the liest of all valid tests 246 allTests = listTests( options. include, options.exclude)288 allTests = listTests( options.concurrent ) 247 289 248 290 # if user wants all tests than no other treatement of the test list is required 249 if options.all or options.list or options.list_comp or options.include:291 if options.all or options.list or options.list_comp : 250 292 tests = allTests 251 293 252 #otherwise we need to validate that the test list that was entered is valid253 else :294 else : 295 #otherwise we need to validate that the test list that was entered is valid 254 296 tests = validTests( options ) 255 297 256 298 # sort the test alphabetically for convenience 257 tests.sort(key=lambda t: (t.arch if t.arch else '') + t.target())299 tests.sort(key=lambda t: t.name) 258 300 259 301 # users may want to simply list the tests 260 302 if options.list_comp : 261 print("-h --help --debug -- dry-run --list --arch--all --regenerate-expected -j --jobs ", end='')262 print(" ".join(map(lambda t: "%s" % (t. target()), tests)))303 print("-h --help --debug --concurrent --dry-run --list --all --regenerate-expected -j --jobs ", end='') 304 print(" ".join(map(lambda t: "%s" % (t.name), tests))) 263 305 264 306 elif options.list : 265 print("Listing for %s:%s"% (settings.arch.string, settings.debug.string)) 266 print("\n".join(map(lambda t: "%s" % (t.toString()), tests))) 267 268 else : 269 options.jobs, forceJobs = jobCount( options, tests ) 270 settings.updateMakeCmd(forceJobs, options.jobs) 271 272 print('%s (%s:%s) on %i cores' % ( 273 'Regenerate tests' if settings.generating else 'Running', 274 settings.arch.string, 275 settings.debug.string, 276 options.jobs 277 )) 307 print("\n".join(map(lambda t: "%s (%s)" % (t.name, t.path), tests))) 308 309 else : 310 options.jobs, forceJobs = jobCount( options ) 311 312 print('Running (%s) on %i cores' % ("debug" if options.debug else "no debug", options.jobs)) 313 make_cmd = "make" if forceJobs else ("make -j%i" % options.jobs) 278 314 279 315 # otherwise run all tests and make sure to return the correct error code 280 sys.exit( run_tests(tests, options. jobs) )316 sys.exit( run_tests(tests, options.regenerate_expected, options.dry_run, options.jobs, options.debug) )
Note:
See TracChangeset
for help on using the changeset viewer.