Changes in / [866f560:65197c2]
- Location:
- src
- Files:
-
- 68 added
- 66 deleted
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
src/SymTab/Validate.cc
r866f560 r65197c2 311 311 } // if 312 312 // Always remove the hoisted aggregate from the inner structure. 313 GuardAction( [ this,aggregateDecl]() { filter( aggregateDecl->members, isStructOrUnion, false ); } );313 GuardAction( [aggregateDecl]() { filter( aggregateDecl->members, isStructOrUnion, false ); } ); 314 314 } 315 315 -
src/tests/Makefile.am
r866f560 r65197c2 20 20 21 21 if BUILD_CONCURRENCY 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 22 concurrent= 45 23 else 46 concurrent=no 47 concurrent_test= 24 concurrent='-Econcurrent' 48 25 endif 49 26 … … 62 39 endif 63 40 64 TEST_FLAGS = $(if $(test), 2> .err/${@}.log, )41 TEST_FLAGS = $(if $(test), 2> $(test), ) 65 42 AM_CFLAGS = ${TEST_FLAGS} ${BUILD_FLAGS} 66 43 CC = @CFA_BINDIR@/@CFA_NAME@ … … 70 47 71 48 fstream_test_SOURCES = fstream_test.c 72 fstream_test_CFLAGS = $(if $(test), 2>> .err/fstream_test.log, ) ${BUILD_FLAGS}49 fstream_test_CFLAGS = $(if $(test), 2>> $(test), ) ${BUILD_FLAGS} 73 50 74 51 vector_test_SOURCES = vector/vector_int.c vector/array.c vector/vector_test.c 75 vector_test_CFLAGS = $(if $(test), 2>> .err/vector_test.log, ) ${BUILD_FLAGS}52 vector_test_CFLAGS = $(if $(test), 2>> $(test), ) ${BUILD_FLAGS} 76 53 77 54 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 78 avl_test_CFLAGS = $(if $(test), 2>> .err/avl_test.log, ) ${BUILD_FLAGS}55 avl_test_CFLAGS = $(if $(test), 2>> $(test), ) ${BUILD_FLAGS} 79 56 80 57 all-local : 81 @+python test.py --debug=${debug} --concurrent=${concurrent} ${quick_test}58 @+python test.py --debug=${debug} ${concurrent} ${quick_test} 82 59 83 60 all-tests : 84 @+python test.py --all --debug=${debug} --concurrent=${concurrent} # '@' => do not echo command (SILENT), '+' => allows recursive make from within python program61 @+python test.py --all --debug=${debug} ${concurrent} # '@' => do not echo command (SILENT), '+' => allows recursive make from within python program 85 62 86 63 clean-local : … … 88 65 89 66 list : 90 @+python test.py --list --concurrent=${concurrent}67 @+python test.py --list ${concurrent} 91 68 92 69 concurrency : 93 @+python test.py --debug=${debug} --concurrent=${concurrent} ${concurrent_test}70 @+python test.py --debug=${debug} ${concurrent} ${concurrent_test} 94 71 95 72 .dummy : .dummy.c @CFA_BINDIR@/@CFA_NAME@ -
src/tests/Makefile.in
r866f560 r65197c2 91 91 build_triplet = @build@ 92 92 host_triplet = @host@ 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} 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} 97 96 EXTRA_PROGRAMS = fstream_test$(EXEEXT) vector_test$(EXEEXT) \ 98 97 avl_test$(EXEEXT) … … 314 313 top_srcdir = @top_srcdir@ 315 314 debug = yes 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 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 = 344 318 345 319 # applies to both programs 346 320 DEBUG_FLAGS = 347 321 BUILD_FLAGS = -g -Wall -Wno-unused-function -quiet @CFA_FLAGS@ \ 348 $(am__append_ 2) $(am__append_3) $(am__append_4)349 TEST_FLAGS = $(if $(test), 2> .err/${@}.log, )322 $(am__append_1) $(am__append_2) $(am__append_3) 323 TEST_FLAGS = $(if $(test), 2> $(test), ) 350 324 AM_CFLAGS = ${TEST_FLAGS} ${BUILD_FLAGS} 351 325 fstream_test_SOURCES = fstream_test.c 352 fstream_test_CFLAGS = $(if $(test), 2>> .err/fstream_test.log, ) ${BUILD_FLAGS}326 fstream_test_CFLAGS = $(if $(test), 2>> $(test), ) ${BUILD_FLAGS} 353 327 vector_test_SOURCES = vector/vector_int.c vector/array.c vector/vector_test.c 354 vector_test_CFLAGS = $(if $(test), 2>> .err/vector_test.log, ) ${BUILD_FLAGS}328 vector_test_CFLAGS = $(if $(test), 2>> $(test), ) ${BUILD_FLAGS} 355 329 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 356 avl_test_CFLAGS = $(if $(test), 2>> .err/avl_test.log, ) ${BUILD_FLAGS}330 avl_test_CFLAGS = $(if $(test), 2>> $(test), ) ${BUILD_FLAGS} 357 331 all: all-am 358 332 … … 833 807 834 808 all-local : 835 @+python test.py --debug=${debug} --concurrent=${concurrent} ${quick_test}809 @+python test.py --debug=${debug} ${concurrent} ${quick_test} 836 810 837 811 all-tests : 838 @+python test.py --all --debug=${debug} --concurrent=${concurrent} # '@' => do not echo command (SILENT), '+' => allows recursive make from within python program812 @+python test.py --all --debug=${debug} ${concurrent} # '@' => do not echo command (SILENT), '+' => allows recursive make from within python program 839 813 840 814 clean-local : … … 842 816 843 817 list : 844 @+python test.py --list --concurrent=${concurrent}818 @+python test.py --list ${concurrent} 845 819 846 820 concurrency : 847 @+python test.py --debug=${debug} --concurrent=${concurrent} ${concurrent_test}821 @+python test.py --debug=${debug} ${concurrent} ${concurrent_test} 848 822 849 823 .dummy : .dummy.c @CFA_BINDIR@/@CFA_NAME@ -
src/tests/pybin/tools.py
r866f560 r65197c2 1 from __future__ import print_function 2 1 3 import __main__ 2 4 import argparse 5 import multiprocessing 3 6 import os 4 7 import re 8 import signal 5 9 import stat 6 10 import sys 11 12 from pybin import settings 7 13 from subprocess import Popen, PIPE, STDOUT 8 14 15 ################################################################################ 16 # shell helpers 17 ################################################################################ 18 9 19 # 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 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 : 12 27 print("cmd: %s" % cmd) 13 28 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 : 15 32 proc = Popen(cmd, stdout=None if print2stdout else PIPE, stderr=STDOUT, shell=True) 16 33 out, err = proc.communicate() … … 18 35 19 36 # Remove 1 or more files silently 20 def rm( files , dry_run = False):37 def rm( files ): 21 38 try: 22 39 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 ) 24 41 except TypeError: 25 sh("rm -f %s > /dev/null 2>&1" % files , dry_run)42 sh("rm -f %s > /dev/null 2>&1" % files ) 26 43 27 44 def chdir( dest = __main__.__file__ ): … … 30 47 os.chdir(dname) 31 48 32 # helper function to replace patterns in a file33 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 string49 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 executable57 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 instance63 print(inst.args) # arguments stored in .args64 print(inst)65 return False66 67 # check if arguments is yes or no68 def yes_no(string):69 if string == "yes" :70 return True71 if string == "no" :72 return False73 raise argparse.ArgumentTypeError(msg)74 return False75 76 49 # diff two files 77 def diff( lhs, rhs , dry_run):50 def diff( lhs, rhs ): 78 51 # diff the output of the files 79 52 diff_cmd = ("diff --ignore-all-space " … … 94 67 95 68 # 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 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 ) -
src/tests/test.py
r866f560 r65197c2 2 2 from __future__ import print_function 3 3 4 from functools import partial5 from multiprocessing import Pool6 from os import listdir, environ7 from os.path import isfile, join, splitext8 4 from pybin.tools import * 5 from pybin.test_run import * 6 from pybin import settings 9 7 10 8 import argparse 11 import multiprocessing12 import os13 9 import re 14 import signal15 10 import sys 16 11 … … 19 14 ################################################################################ 20 15 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 "" 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 32 33 # 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 51 37 52 38 # 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 ]) 57 58 # reads the directory ./.expect and indentifies the tests 59 def listTests( concurrent ): 60 machineType = getMachineType() 61 62 # tests directly in the .expect folder will always be processed 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; 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 73 54 74 55 # from the found tests, filter all the valid tests/desired tests … … 80 61 if options.regenerate_expected : 81 62 for testname in options.tests : 82 if testname.endswith( (".c", ".cc", ".cpp") ): 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) ) 66 else : 83 67 print('ERROR: "%s", tests are not allowed to end with a C/C++/CFA extension, ignoring it' % testname, file=sys.stderr) 84 else :85 found = [test for test in allTests if test.name == testname]86 tests.append( found[0] if len(found) == 1 else Test(testname, testname) )87 68 88 69 else : 89 70 # otherwise we only need to validate that all tests are present in the complete list 90 71 for testname in options.tests: 91 test = [t for t in allTests if t.name == testname]92 93 if len(test) != 0:72 test = [t for t in allTests if pathCmp( t.target(), testname )] 73 74 if test : 94 75 tests.append( test[0] ) 95 76 else : … … 97 78 98 79 # make sure we have at least some test to run 99 if len(tests) == 0:80 if not tests : 100 81 print('ERROR: No valid test to run', file=sys.stderr) 101 82 sys.exit(1) … … 108 89 parser = argparse.ArgumentParser(description='Script which runs cforall tests') 109 90 parser.add_argument('--debug', help='Run all tests in debug or release', type=yes_no, default='no') 110 parser.add_argument('-- concurrent', help='Run concurrent tests', type=yes_no, default='yes')91 parser.add_argument('--arch', help='Test for specific architecture', type=str, default='') 111 92 parser.add_argument('--dry-run', help='Don\'t run the tests, only output the commands', action='store_true') 112 93 parser.add_argument('--list', help='List all test available', action='store_true') … … 115 96 parser.add_argument('-j', '--jobs', help='Number of tests to run simultaneously', type=int, default='8') 116 97 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') 117 100 parser.add_argument('tests', metavar='test', type=str, nargs='*', help='a list of tests to run') 118 101 … … 123 106 all_tests = options.all 124 107 some_tests = len(options.tests) > 0 108 some_dirs = len(options.include) > 0 if options.include else 0 125 109 126 110 # check that exactly one of the booleans is set to true 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)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) 129 113 parser.print_help() 130 114 sys.exit(1) … … 132 116 return options 133 117 134 def jobCount( options ):135 # check if the user already passed in a number of jobs for multi-threading136 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 None138 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 input146 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 False151 152 118 ################################################################################ 153 119 # running test functions 154 120 ################################################################################ 155 121 # logic to run a single test and return the result (No handling of printing or other test framework logic) 156 def run_single_test(test , generate, dry_run, debug):122 def run_single_test(test): 157 123 158 124 # find the output file based on the test name and options flag 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 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() 161 132 162 133 # remove any outputs from the previous tests to prevent side effects 163 rm( (out_file, err_file, test.name), dry_run ) 164 165 options = "-debug" if debug else "-nodebug" 134 rm( (out_file, err_file, test.target()) ) 166 135 167 136 # build, skipping to next test on error 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 = 0171 error = None137 make_ret, _ = make( test.target(), 138 redirects = "2> %s 1> /dev/null" % out_file, 139 error_file = err_file 140 ) 172 141 173 142 # if the make command succeds continue otherwise skip to diff 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) : 143 if make_ret == 0 or settings.dry_run: 144 if settings.dry_run or fileIsExecutable(test.target()) : 179 145 # run test 180 retcode, _ = sh("timeout 60 ./%s %s > %s 2>&1" % (test.name, stdinput, out_file), dry_run)146 retcode, _ = sh("timeout 60 %s > %s 2>&1" % (test.target(), out_file), input = in_file) 181 147 else : 182 148 # simply cat the result into the output 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) 149 retcode, _ = sh("cat %s > %s" % (test.target(), out_file)) 150 else: 151 retcode, _ = sh("mv %s %s" % (err_file, out_file)) 152 188 153 189 154 if retcode == 0: 190 if generate:155 if settings.generating : 191 156 # if we are ounly generating the output we still need to check that the test actually exists 192 if not dry_run and fileContainsOnly(out_file, "make: *** No rule to make target `%s'. Stop." % test.name) :157 if not settings.dry_run and fileContainsOnly(out_file, "make: *** No rule to make target `%s'. Stop." % test.target()) : 193 158 retcode = 1; 194 error = "\t\tNo make target for test %s!" % test. name159 error = "\t\tNo make target for test %s!" % test.target() 195 160 sh("rm %s" % out_file, False) 161 else: 162 error = None 196 163 else : 197 164 # fetch return code and error from the diff command 198 retcode, error = diff( ".expect/%s.txt" % test.path, ".out/%s.log" % test.name, dry_run)165 retcode, error = diff(cmp_file, out_file) 199 166 200 167 else: … … 204 171 205 172 # clean the executable 206 sh("rm -f %s > /dev/null 2>&1" % test. name, dry_run)173 sh("rm -f %s > /dev/null 2>&1" % test.target()) 207 174 208 175 return retcode, error 209 176 210 177 # run a single test and handle the errors, outputs, printing, exception handling, etc. 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) 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() 240 199 241 200 return retcode != TestResult.SUCCESS 242 201 243 202 # run the given list of tests with the given parameters 244 def run_tests(tests, generate, dry_run, jobs, debug) :203 def run_tests(tests, jobs) : 245 204 # clean the sandbox from previous commands 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: " ) 205 make('clean', redirects = '> /dev/null 2>&1') 253 206 254 207 # create the executor for our jobs and handle the signal properly 255 original_sigint_handler = signal.signal(signal.SIGINT, signal.SIG_IGN) 256 pool = Pool(jobs) 257 signal.signal(signal.SIGINT, original_sigint_handler) 208 pool = setupPool(jobs) 258 209 259 210 # for each test to run 260 211 try : 261 results = pool.map_async(partial(run_test_worker, generate=generate, dry_run=dry_run, debug=debug), tests, chunksize = 1 ).get(7200) 212 results = pool.map_async( 213 run_test_worker, 214 tests, 215 chunksize = 1 216 ).get(7200) 262 217 except KeyboardInterrupt: 263 218 pool.terminate() … … 266 221 267 222 # clean the workspace 268 sh("%s clean > /dev/null 2>&1" % make_cmd, dry_run)223 make('clean', redirects = '> /dev/null 2>&1') 269 224 270 225 for failed in results: … … 285 240 options = getOptions() 286 241 242 # init global settings 243 settings.init( options ) 244 287 245 # fetch the liest of all valid tests 288 allTests = listTests( options. concurrent)246 allTests = listTests( options.include, options.exclude ) 289 247 290 248 # if user wants all tests than no other treatement of the test list is required 291 if options.all or options.list or options.list_comp :249 if options.all or options.list or options.list_comp or options.include : 292 250 tests = allTests 293 251 252 #otherwise we need to validate that the test list that was entered is valid 294 253 else : 295 #otherwise we need to validate that the test list that was entered is valid296 254 tests = validTests( options ) 297 255 298 256 # sort the test alphabetically for convenience 299 tests.sort(key=lambda t: t.name)257 tests.sort(key=lambda t: (t.arch if t.arch else '') + t.target()) 300 258 301 259 # users may want to simply list the tests 302 260 if options.list_comp : 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)))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))) 305 263 306 264 elif options.list : 307 print("\n".join(map(lambda t: "%s (%s)" % (t.name, t.path), tests))) 265 print("Listing for %s:%s"% (settings.arch.string, settings.debug.string)) 266 print("\n".join(map(lambda t: "%s" % (t.toString()), tests))) 308 267 309 268 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) 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 )) 314 278 315 279 # otherwise run all tests and make sure to return the correct error code 316 sys.exit( run_tests(tests, options. regenerate_expected, options.dry_run, options.jobs, options.debug) )280 sys.exit( run_tests(tests, options.jobs) )
Note: See TracChangeset
for help on using the changeset viewer.