diff options
Diffstat (limited to 'tests/runner.py')
-rw-r--r-- | tests/runner.py | 745 |
1 files changed, 303 insertions, 442 deletions
diff --git a/tests/runner.py b/tests/runner.py index 979b5978..3fd63574 100644 --- a/tests/runner.py +++ b/tests/runner.py @@ -5,14 +5,14 @@ See settings.py file for options¶ms. Edit as needed. These tests can be run in parallel using nose, for example - nosetests --processes=4 -v -s tests/runner.py + nosetests --processes=4 -v -s tests/runner.py will use 4 processes. To install nose do something like |pip install nose| or |sudo apt-get install python-nose|. ''' from subprocess import Popen, PIPE, STDOUT -import os, unittest, tempfile, shutil, time, inspect, sys, math, glob, tempfile, re, json, difflib +import os, unittest, tempfile, shutil, time, inspect, sys, math, glob, tempfile, re, difflib # Setup @@ -28,40 +28,30 @@ try: except: raise Exception('Cannot find "COMPILER_OPTS" definition. Is ~/.emscripten set up properly? You may need to copy the template from settings.py into it.') -# Paths - -EMSCRIPTEN = path_from_root('emscripten.py') -DEMANGLER = path_from_root('third_party', 'demangler.py') -NAMESPACER = path_from_root('tools', 'namespacer.py') -EMMAKEN = path_from_root('tools', 'emmaken.py') -AUTODEBUGGER = path_from_root('tools', 'autodebugger.py') -DFE = path_from_root('tools', 'dead_function_eliminator.py') - -# Global cache for tests (we have multiple TestCase instances; this object lets them share data) - -GlobalCache = {} - -class Dummy: pass -Settings = Dummy() -Settings.saveJS = 0 - # Core test runner class, shared between normal tests and benchmarks class RunnerCore(unittest.TestCase): + save_dir = 0 + save_JS = 0 + def setUp(self): - dirname = tempfile.mkdtemp(prefix="ems_" + self.__class__.__name__ + "_", dir=TEMP_DIR) + if not self.save_dir: + dirname = tempfile.mkdtemp(prefix="ems_" + self.__class__.__name__ + "_", dir=TEMP_DIR) + else: + dirname = os.path.join(TEMP_DIR, 'tmp') if not os.path.exists(dirname): os.makedirs(dirname) self.working_dir = dirname def tearDown(self): - if Settings.saveJS: + if self.save_JS: for name in os.listdir(self.get_dir()): if name.endswith(('.o.js', '.cc.js')): suff = '.'.join(name.split('.')[-2:]) shutil.copy(os.path.join(self.get_dir(), name), os.path.join(TEMP_DIR, self.id().replace('__main__.', '').replace('.test_', '.')+'.'+suff)) - shutil.rmtree(self.get_dir()) + if not self.save_dir: + shutil.rmtree(self.get_dir()) def skip(self, why): print >> sys.stderr, '<skipping: %s> ' % why, @@ -71,73 +61,33 @@ class RunnerCore(unittest.TestCase): # Similar to LLVM::createStandardModulePasses() def pick_llvm_opts(self, optimization_level, handpicked=None): - global LLVM_OPT_OPTS, QUANTUM_SIZE, USE_TYPED_ARRAYS + global LLVM_OPT_OPTS if handpicked is None: handpicked = True # Not even TA2 can withstand instruction combining - LLVM_OPT_OPTS = pick_llvm_opts(optimization_level, handpicked, quantum_size=QUANTUM_SIZE) - - # Emscripten optimizations that we run on the .ll file - def do_ll_opts(self, filename): - # Remove target info. This helps LLVM opts, if we run them later - cleaned = filter(lambda line: not line.startswith('target datalayout = ') and not line.startswith('target triple = '), - open(filename + '.o.ll', 'r').readlines()) - os.unlink(filename + '.o.ll') - open(filename + '.o.ll.orig', 'w').write(''.join(cleaned)) - - output = Popen(['python', DFE, filename + '.o.ll.orig', filename + '.o.ll'], stdout=PIPE, stderr=STDOUT).communicate()[0] - assert os.path.exists(filename + '.o.ll'), 'Failed to run ll optimizations' - - # Optional LLVM optimizations - def do_llvm_opts(self, filename): - if LLVM_OPTS: - shutil.move(filename + '.o', filename + '.o.pre') - output = Popen([LLVM_OPT, filename + '.o.pre'] + LLVM_OPT_OPTS + ['-o=' + filename + '.o'], stdout=PIPE, stderr=STDOUT).communicate()[0] - assert os.path.exists(filename + '.o'), 'Failed to run llvm optimizations: ' + output - - def do_llvm_dis(self, filename): - # LLVM binary ==> LLVM assembly - try: - os.remove(filename + '.o.ll') - except: - pass - output = Popen([LLVM_DIS, filename + '.o'] + LLVM_DIS_OPTS + ['-o=' + filename + '.o.ll'], stdout=PIPE, stderr=STDOUT).communicate()[0] - assert os.path.exists(filename + '.o.ll'), 'Could not create .ll file: ' + output - - def do_llvm_as(self, source, target): - # LLVM assembly ==> LLVM binary - try: - os.remove(target) - except: - pass - output = Popen([LLVM_AS, source, '-o=' + target], stdout=PIPE, stderr=STDOUT).communicate()[0] - assert os.path.exists(target), 'Could not create bc file: ' + output - - def do_link(self, files, target): - output = Popen([LLVM_LINK] + files + ['-o', target], stdout=PIPE, stderr=STDOUT).communicate()[0] - assert output is None or 'Could not open input file' not in output, 'Linking error: ' + output + LLVM_OPT_OPTS = pick_llvm_opts(optimization_level, handpicked, quantum_size=Settings.QUANTUM_SIZE) def prep_ll_run(self, filename, ll_file, force_recompile=False, build_ll_hook=None): if ll_file.endswith(('.bc', '.o')): if ll_file != filename + '.o': shutil.copy(ll_file, filename + '.o') - self.do_llvm_dis(filename) + Building.llvm_dis(filename) else: shutil.copy(ll_file, filename + '.o.ll') force_recompile = force_recompile or os.stat(filename + '.o.ll').st_size > 50000 # if the file is big, recompile just to get ll_opts - if LLVM_OPTS or force_recompile or build_ll_hook: - self.do_ll_opts(filename) + if Building.LLVM_OPTS or force_recompile or build_ll_hook: + Building.ll_opts(filename) if build_ll_hook: build_ll_hook(filename) shutil.move(filename + '.o.ll', filename + '.o.ll.pre') - self.do_llvm_as(filename + '.o.ll.pre', filename + '.o') + Building.llvm_as(filename + '.o.ll.pre', filename + '.o') output = Popen([LLVM_AS, filename + '.o.ll.pre'] + ['-o=' + filename + '.o'], stdout=PIPE, stderr=STDOUT).communicate()[0] assert 'error:' not in output, 'Error in llvm-as: ' + output - self.do_llvm_opts(filename) - self.do_llvm_dis(filename) + Building.llvm_opts(filename) + Building.llvm_dis(filename) # Build JavaScript code from source code def build(self, src, dirname, filename, output_processor=None, main_file=None, additional_files=[], libraries=[], includes=[], build_ll_hook=None, extra_emscripten_args=[]): @@ -166,7 +116,7 @@ class RunnerCore(unittest.TestCase): os.remove(f + '.o.ll') except: pass - output = Popen([COMPILER, '-emit-llvm'] + COMPILER_OPTS + COMPILER_TEST_OPTS + + output = Popen([Building.COMPILER, '-emit-llvm'] + COMPILER_OPTS + Building.COMPILER_TEST_OPTS + ['-I', dirname, '-I', os.path.join(dirname, 'include')] + map(lambda include: '-I' + include, includes) + ['-c', f, '-o', f + '.o'], @@ -178,8 +128,8 @@ class RunnerCore(unittest.TestCase): # Link all files if len(additional_files) + len(libraries) > 0: shutil.move(filename + '.o', filename + '.o.alone') - self.do_link([filename + '.o.alone'] + map(lambda f: f + '.o', additional_files) + libraries, - filename + '.o') + Building.link([filename + '.o.alone'] + map(lambda f: f + '.o', additional_files) + libraries, + filename + '.o') if not os.path.exists(filename + '.o'): print "Failed to link LLVM binaries:\n\n", output raise Exception("Linkage error"); @@ -187,32 +137,7 @@ class RunnerCore(unittest.TestCase): # Finalize self.prep_ll_run(filename, filename + '.o', build_ll_hook=build_ll_hook) - self.do_emscripten(filename, output_processor, extra_args=extra_emscripten_args) - - def do_emscripten(self, filename, output_processor=None, append_ext=True, extra_args=[]): - # Add some headers by default. TODO: remove manually adding these in each test - if '-H' not in extra_args: - extra_args += ['-H', 'libc/fcntl.h,libc/sys/unistd.h,poll.h,libc/math.h,libc/langinfo.h,libc/time.h'] - - # Run Emscripten - exported_settings = {} - for setting in ['QUANTUM_SIZE', 'RELOOP', 'OPTIMIZE', 'ASSERTIONS', 'USE_TYPED_ARRAYS', 'SAFE_HEAP', 'CHECK_OVERFLOWS', 'CORRECT_OVERFLOWS', 'CORRECT_SIGNS', 'CHECK_SIGNS', 'CORRECT_OVERFLOWS_LINES', 'CORRECT_SIGNS_LINES', 'CORRECT_ROUNDINGS', 'CORRECT_ROUNDINGS_LINES', 'INVOKE_RUN', 'SAFE_HEAP_LINES', 'INIT_STACK', 'AUTO_OPTIMIZE', 'EXPORTED_FUNCTIONS', 'EXPORTED_GLOBALS', 'BUILD_AS_SHARED_LIB', 'INCLUDE_FULL_LIBRARY', 'RUNTIME_TYPE_INFO', 'DISABLE_EXCEPTION_CATCHING', 'TOTAL_MEMORY', 'FAST_MEMORY', 'EXCEPTION_DEBUG', 'PROFILE']: - try: - value = eval(setting) - if value is not None: - exported_settings[setting] = value - except: - pass - settings = ['-s %s=%s' % (k, json.dumps(v)) for k, v in exported_settings.items()] - compiler_output = timeout_run(Popen(['python', EMSCRIPTEN, filename + ('.o.ll' if append_ext else ''), '-o', filename + '.o.js'] + settings + extra_args, stdout=PIPE, stderr=STDOUT), TIMEOUT, 'Compiling') - #print compiler_output - - # Detect compilation crashes and errors - if compiler_output is not None and 'Traceback' in compiler_output and 'in test_' in compiler_output: print compiler_output; assert 0 - assert os.path.exists(filename + '.o.js') and len(open(filename + '.o.js', 'r').read()) > 0, 'Emscripten failed to generate .js: ' + str(compiler_output) - - if output_processor is not None: - output_processor(open(filename + '.o.js').read()) + Building.emscripten(filename, output_processor, extra_args=extra_emscripten_args) def run_generated_code(self, engine, filename, args=[], check_timeout=True): stdout = os.path.join(self.get_dir(), 'stdout') # use files, as PIPE can get too full and hang us @@ -256,6 +181,28 @@ class RunnerCore(unittest.TestCase): limit_size(''.join([a.rstrip()+'\n' for a in difflib.unified_diff(value.split('\n'), string.split('\n'), fromfile='expected', tofile='actual')])) )) + library_cache = {} + + def get_library(self, name, generated_libs, configure=['./configure'], configure_args=[], make=['make'], make_args=['-j', '2'], cache=True): + build_dir = self.get_build_dir() + output_dir = self.get_dir() + + cache_name = name + '|' + Building.COMPILER + if self.library_cache is not None: + if cache and self.library_cache.get(cache_name): + print >> sys.stderr, '<load build from cache> ', + bc_file = os.path.join(output_dir, 'lib' + name + '.bc') + f = open(bc_file, 'wb') + f.write(self.library_cache[cache_name]) + f.close() + return bc_file + + print >> sys.stderr, '<building and saving into cache> ', + + return Building.build_library(name, build_dir, output_dir, generated_libs, configure, configure_args, make, make_args, self.library_cache, cache_name, + copy_project=True) + + ################################################################################################### if 'benchmark' not in str(sys.argv): @@ -266,11 +213,9 @@ if 'benchmark' not in str(sys.argv): class T(RunnerCore): # Short name, to make it more fun to use manually on the commandline ## Does a complete test - builds, runs, checks output, etc. def do_run(self, src, expected_output=None, args=[], output_nicerizer=None, output_processor=None, no_build=False, main_file=None, additional_files=[], js_engines=None, post_build=None, basename='src.cpp', libraries=[], includes=[], force_c=False, build_ll_hook=None, extra_emscripten_args=[]): - #print 'Running test:', inspect.stack()[1][3].replace('test_', ''), '[%s,%s,%s]' % (COMPILER.split(os.sep)[-1], 'llvm-optimizations' if LLVM_OPTS else '', 'reloop&optimize' if RELOOP else '') if force_c or (main_file is not None and main_file[-2:]) == '.c': basename = 'src.c' - global COMPILER - COMPILER = to_cc(COMPILER) + Building.COMPILER = to_cc(Building.COMPILER) dirname = self.get_dir() filename = os.path.join(dirname, basename) @@ -289,7 +234,7 @@ if 'benchmark' not in str(sys.argv): # Run in both JavaScript engines, if optimizing - significant differences there (typed arrays) if js_engines is None: js_engines = [SPIDERMONKEY_ENGINE, V8_ENGINE] - if USE_TYPED_ARRAYS == 2: + if Settings.USE_TYPED_ARRAYS == 2: js_engines = [SPIDERMONKEY_ENGINE] # when oh when will v8 support typed arrays in the console for engine in js_engines: js_output = self.run_generated_code(engine, filename + '.o.js', args) @@ -306,7 +251,7 @@ if 'benchmark' not in str(sys.argv): filename = os.path.join(self.get_dir(), 'src.cpp') self.prep_ll_run(filename, ll_file, force_recompile, build_ll_hook) - self.do_emscripten(filename, extra_args=extra_emscripten_args) + Building.emscripten(filename, extra_args=extra_emscripten_args) self.do_run(None, expected_output, args, @@ -380,7 +325,7 @@ if 'benchmark' not in str(sys.argv): self.do_run(src, '*5,23,10,19,121,1,37,1,0*\n0:-1,1:134217727,2:4194303,3:131071,4:4095,5:127,6:3,7:0,8:0*\n*56,09*\nfixed:320434\n*21*') def test_sintvars(self): - global CORRECT_SIGNS; CORRECT_SIGNS = 1 # Relevant to this test + Settings.CORRECT_SIGNS = 1 # Relevant to this test src = ''' #include <stdio.h> struct S { @@ -407,11 +352,11 @@ if 'benchmark' not in str(sys.argv): } ''' output = '*32780,32522,258*\n*258,2*\n*32780,32999,-219*\n*65317,510*' - global CORRECT_OVERFLOWS; CORRECT_OVERFLOWS = 0 # We should not need overflow correction to get this right + Settings.CORRECT_OVERFLOWS = 0 # We should not need overflow correction to get this right self.do_run(src, output, force_c=True) def test_bigint(self): - if USE_TYPED_ARRAYS != 0: return self.skip('Typed arrays truncate i64') + if Settings.USE_TYPED_ARRAYS != 0: return self.skip('Typed arrays truncate i64') src = ''' #include <stdio.h> int main() @@ -435,8 +380,8 @@ if 'benchmark' not in str(sys.argv): self.do_run(src, '*245127260211081,579378795077769,808077213656969,16428841631881,791648372025088*\n*13.00,6.00,3.00,*3*') def test_unsigned(self): - global CORRECT_SIGNS; CORRECT_SIGNS = 1 # We test for exactly this sort of thing here - global CHECK_SIGNS; CHECK_SIGNS = 0 + Settings.CORRECT_SIGNS = 1 # We test for exactly this sort of thing here + Settings.CHECK_SIGNS = 0 src = ''' #include <stdio.h> const signed char cvals[2] = { -1, -2 }; // compiler can store this is a string, so -1 becomes \FF, and needs re-signing @@ -477,12 +422,12 @@ if 'benchmark' not in str(sys.argv): # Now let's see some code that should just work in USE_TYPED_ARRAYS == 2, but requires # corrections otherwise - if USE_TYPED_ARRAYS == 2: - CORRECT_SIGNS = 0 - CHECK_SIGNS = 1 + if Settings.USE_TYPED_ARRAYS == 2: + Settings.CORRECT_SIGNS = 0 + Settings.CHECK_SIGNS = 1 else: - CORRECT_SIGNS = 1 - CHECK_SIGNS = 0 + Settings.CORRECT_SIGNS = 1 + Settings.CHECK_SIGNS = 0 src = ''' #include <stdio.h> @@ -530,7 +475,7 @@ if 'benchmark' not in str(sys.argv): self.do_run(src, '*255*\n*65535*\n*-1*\n*-1*\n*-1*') def test_bitfields(self): - global SAFE_HEAP; SAFE_HEAP = 0 # bitfields do loads on invalid areas, by design + Settings.SAFE_HEAP = 0 # bitfields do loads on invalid areas, by design src = ''' #include <stdio.h> struct bitty { @@ -641,7 +586,7 @@ if 'benchmark' not in str(sys.argv): self.do_run(src, '*yes*') # Test for issue 39 - if not LLVM_OPTS: + if not Building.LLVM_OPTS: self.do_ll_run(path_from_root('tests', 'issue_39.ll'), '*yes*') def test_if_else(self): @@ -960,7 +905,7 @@ if 'benchmark' not in str(sys.argv): return 1; } ''' - if QUANTUM_SIZE == 1: + if Settings.QUANTUM_SIZE == 1: self.do_run(src, 'sizeofs:6,8\n*C___: 0,3,6,9<24*\n*Carr: 0,3,6,9<24*\n*C__w: 0,3,9,12<24*\n*Cp1_: 1,2,5,8<24*\n*Cp2_: 0,2,5,8<24*\n*Cint: 0,3,4,7<24*\n*C4__: 0,3,4,7<24*\n*C4_2: 0,3,5,8<20*\n*C__z: 0,3,5,8<28*') else: self.do_run(src, 'sizeofs:6,8\n*C___: 0,6,12,20<24*\n*Carr: 0,6,12,20<24*\n*C__w: 0,6,12,20<24*\n*Cp1_: 4,6,12,20<24*\n*Cp2_: 0,6,12,20<24*\n*Cint: 0,8,12,20<24*\n*C4__: 0,8,12,20<24*\n*C4_2: 0,6,10,16<20*\n*C__z: 0,8,16,24<28*') @@ -1003,15 +948,14 @@ if 'benchmark' not in str(sys.argv): ''' self.do_run(src, '*throw...caught!infunc...done!*') - global DISABLE_EXCEPTION_CATCHING - DISABLE_EXCEPTION_CATCHING = 1 + Settings.DISABLE_EXCEPTION_CATCHING = 1 self.do_run(src, 'Compiled code throwing an exception') def test_typed_exceptions(self): return self.skip('TODO: fix this for llvm 3.0') - global SAFE_HEAP; SAFE_HEAP = 0 # Throwing null will cause an ignorable null pointer access. - global EXCEPTION_DEBUG; EXCEPTION_DEBUG = 0 # Messes up expected output. + Settings.SAFE_HEAP = 0 # Throwing null will cause an ignorable null pointer access. + Settings.EXCEPTION_DEBUG = 0 # Messes up expected output. src = open(path_from_root('tests', 'exceptions', 'typed.cpp'), 'r').read() expected = open(path_from_root('tests', 'exceptions', 'output.txt'), 'r').read() self.do_run(src, expected) @@ -1372,7 +1316,7 @@ if 'benchmark' not in str(sys.argv): printf("*%d,%d,%d*\\n", sizeof(PyGC_Head), sizeof(gc_generation), int(GEN_HEAD(2)) - int(GEN_HEAD(1))); } ''' - if QUANTUM_SIZE == 1: + if Settings.QUANTUM_SIZE == 1: # Compressed memory. Note that sizeof() does give the fat sizes, however! self.do_run(src, '*0,0,0,1,2,3,4,5*\n*1,0,0*\n*0*\n0:1,1\n1:1,1\n2:1,1\n*12,20,5*') else: @@ -1402,7 +1346,7 @@ if 'benchmark' not in str(sys.argv): def test_sizeof(self): # Has invalid writes between printouts - global SAFE_HEAP; SAFE_HEAP = 0 + Settings.SAFE_HEAP = 0 src = ''' #include <stdio.h> @@ -1436,8 +1380,7 @@ if 'benchmark' not in str(sys.argv): self.do_run(src, '*2,2,5,8,8***8,8,5,8,8***7,2,6,990,7,2*', [], lambda x: x.replace('\n', '*')) def test_emscripten_api(self): - global OPTIMIZE, RELOOP, LLVM_OPTS - if OPTIMIZE or RELOOP or LLVM_OPTS: return self.skip('FIXME') + #if Settings.OPTIMIZE or Settings.RELOOP or Building.LLVM_OPTS: return self.skip('FIXME') src = ''' #include <stdio.h> @@ -1481,7 +1424,7 @@ if 'benchmark' not in str(sys.argv): return 0; } ''' - if QUANTUM_SIZE == 1: + if Settings.QUANTUM_SIZE == 1: self.do_run(src, '''*4*\n0:22016,0,8,12\n1:22018,1,12,8\n''') else: self.do_run(src, '''*16*\n0:22016,0,32,48\n1:22018,1,48,32\n''') @@ -1580,13 +1523,13 @@ if 'benchmark' not in str(sys.argv): return 0; } ''' - if QUANTUM_SIZE == 1: + if Settings.QUANTUM_SIZE == 1: self.do_run(src, '*4,2,3*\n*6,2,3*') else: self.do_run(src, '*4,3,4*\n*6,4,6*') def test_varargs(self): - if QUANTUM_SIZE == 1: return self.skip('FIXME: Add support for this') + if Settings.QUANTUM_SIZE == 1: return self.skip('FIXME: Add support for this') src = ''' #include <stdio.h> @@ -1653,9 +1596,9 @@ if 'benchmark' not in str(sys.argv): self.do_run(src, '*cheez: 0+24*\n*cheez: 0+24*\n*albeit*\n*albeit*\nQ85*\nmaxxi:21*\nmaxxD:22.10*\n') def test_stdlibs(self): - if USE_TYPED_ARRAYS == 2: + if Settings.USE_TYPED_ARRAYS == 2: # Typed arrays = 2 + safe heap prints a warning that messes up our output. - global SAFE_HEAP; SAFE_HEAP = 0 + Settings.SAFE_HEAP = 0 src = ''' #include <stdio.h> #include <stdlib.h> @@ -1708,7 +1651,7 @@ if 'benchmark' not in str(sys.argv): self.do_run(src, '*1,2,3,5,5,6*\n*stdin==0:0*\n*%*\n*5*\n*66.0*\n*10*\n*0*\n*-10*\n*18*\n*10*\n*0*\n*4294967286*\n*cleaned*') def test_time(self): - if USE_TYPED_ARRAYS == 2: return self.skip('Typed arrays = 2 truncate i64s') + if Settings.USE_TYPED_ARRAYS == 2: return self.skip('Typed arrays = 2 truncate i64s') src = open(path_from_root('tests', 'time', 'src.c'), 'r').read() expected = open(path_from_root('tests', 'time', 'output.txt'), 'r').read() self.do_run(src, expected, @@ -1717,10 +1660,9 @@ if 'benchmark' not in str(sys.argv): def test_statics(self): # static initializers save i16 but load i8 for some reason - global SAFE_HEAP, SAFE_HEAP_LINES - if SAFE_HEAP: - SAFE_HEAP = 3 - SAFE_HEAP_LINES = ['src.cpp:19', 'src.cpp:26'] + if Settings.SAFE_HEAP: + Settings.SAFE_HEAP = 3 + Settings.SAFE_HEAP_LINES = ['src.cpp:19', 'src.cpp:26'] src = ''' #include <stdio.h> @@ -1906,7 +1848,7 @@ if 'benchmark' not in str(sys.argv): return 0; } ''' - if QUANTUM_SIZE == 1: + if Settings.QUANTUM_SIZE == 1: # Compressed memory. Note that sizeof() does give the fat sizes, however! self.do_run(src, '*16,0,1,2,2,3|20,0,1,1,2,3,3,4|24,0,5,0,1,1,2,3,3,4*\n*0,0,0,1,2,62,63,64,72*\n*2*') else: @@ -1914,7 +1856,6 @@ if 'benchmark' not in str(sys.argv): self.do_run(src, '*16,0,4,8,8,12|20,0,4,4,8,12,12,16|24,0,20,0,4,4,8,12,12,16*\n*0,0,0,1,2,64,68,69,72*\n*2*') def test_dlfcn_basic(self): - global BUILD_AS_SHARED_LIB lib_src = ''' #include <cstdio> @@ -1929,7 +1870,7 @@ if 'benchmark' not in str(sys.argv): ''' dirname = self.get_dir() filename = os.path.join(dirname, 'liblib.cpp') - BUILD_AS_SHARED_LIB = 1 + Settings.BUILD_AS_SHARED_LIB = 1 self.build(lib_src, dirname, filename) shutil.move(filename + '.o.js', os.path.join(dirname, 'liblib.so')) @@ -1951,7 +1892,7 @@ if 'benchmark' not in str(sys.argv): return 0; } ''' - BUILD_AS_SHARED_LIB = 0 + Settings.BUILD_AS_SHARED_LIB = 0 def add_pre_run_and_checks(filename): src = open(filename, 'r').read().replace( '// {{PRE_RUN_ADDITIONS}}', @@ -1962,7 +1903,6 @@ if 'benchmark' not in str(sys.argv): post_build=add_pre_run_and_checks) def test_dlfcn_qsort(self): - global BUILD_AS_SHARED_LIB, EXPORTED_FUNCTIONS lib_src = ''' int lib_cmp(const void* left, const void* right) { const int* a = (const int*) left; @@ -1980,8 +1920,8 @@ if 'benchmark' not in str(sys.argv): ''' dirname = self.get_dir() filename = os.path.join(dirname, 'liblib.cpp') - BUILD_AS_SHARED_LIB = 1 - EXPORTED_FUNCTIONS = ['_get_cmp'] + Settings.BUILD_AS_SHARED_LIB = 1 + Settings.EXPORTED_FUNCTIONS = ['_get_cmp'] self.build(lib_src, dirname, filename) shutil.move(filename + '.o.js', os.path.join(dirname, 'liblib.so')) @@ -2035,8 +1975,8 @@ if 'benchmark' not in str(sys.argv): return 0; } ''' - BUILD_AS_SHARED_LIB = 0 - EXPORTED_FUNCTIONS = ['_main'] + Settings.BUILD_AS_SHARED_LIB = 0 + Settings.EXPORTED_FUNCTIONS = ['_main'] def add_pre_run_and_checks(filename): src = open(filename, 'r').read().replace( '// {{PRE_RUN_ADDITIONS}}', @@ -2048,10 +1988,8 @@ if 'benchmark' not in str(sys.argv): post_build=add_pre_run_and_checks) def test_dlfcn_data_and_fptr(self): - global LLVM_OPTS - if LLVM_OPTS: return self.skip('LLVM opts will optimize out parent_func') + if Building.LLVM_OPTS: return self.skip('LLVM opts will optimize out parent_func') - global BUILD_AS_SHARED_LIB, EXPORTED_FUNCTIONS, EXPORTED_GLOBALS lib_src = ''' #include <stdio.h> @@ -2076,9 +2014,9 @@ if 'benchmark' not in str(sys.argv): ''' dirname = self.get_dir() filename = os.path.join(dirname, 'liblib.cpp') - BUILD_AS_SHARED_LIB = 1 - EXPORTED_FUNCTIONS = ['_func'] - EXPORTED_GLOBALS = ['_global'] + Settings.BUILD_AS_SHARED_LIB = 1 + Settings.EXPORTED_FUNCTIONS = ['_func'] + Settings.EXPORTED_GLOBALS = ['_global'] self.build(lib_src, dirname, filename) shutil.move(filename + '.o.js', os.path.join(dirname, 'liblib.so')) @@ -2134,9 +2072,9 @@ if 'benchmark' not in str(sys.argv): return 0; } ''' - BUILD_AS_SHARED_LIB = 0 - EXPORTED_FUNCTIONS = ['_main'] - EXPORTED_GLOBALS = [] + Settings.BUILD_AS_SHARED_LIB = 0 + Settings.EXPORTED_FUNCTIONS = ['_main'] + Settings.EXPORTED_GLOBALS = [] def add_pre_run_and_checks(filename): src = open(filename, 'r').read().replace( '// {{PRE_RUN_ADDITIONS}}', @@ -2148,7 +2086,6 @@ if 'benchmark' not in str(sys.argv): post_build=add_pre_run_and_checks) def test_dlfcn_alias(self): - global BUILD_AS_SHARED_LIB, EXPORTED_FUNCTIONS, INCLUDE_FULL_LIBRARY lib_src = r''' #include <stdio.h> extern int parent_global; @@ -2158,8 +2095,8 @@ if 'benchmark' not in str(sys.argv): ''' dirname = self.get_dir() filename = os.path.join(dirname, 'liblib.cpp') - BUILD_AS_SHARED_LIB = 1 - EXPORTED_FUNCTIONS = ['_func'] + Settings.BUILD_AS_SHARED_LIB = 1 + Settings.EXPORTED_FUNCTIONS = ['_func'] self.build(lib_src, dirname, filename) shutil.move(filename + '.o.js', os.path.join(dirname, 'liblib.so')) @@ -2181,9 +2118,9 @@ if 'benchmark' not in str(sys.argv): return 0; } ''' - BUILD_AS_SHARED_LIB = 0 - INCLUDE_FULL_LIBRARY = 1 - EXPORTED_FUNCTIONS = ['_main'] + Settings.BUILD_AS_SHARED_LIB = 0 + Settings.INCLUDE_FULL_LIBRARY = 1 + Settings.EXPORTED_FUNCTIONS = ['_main'] def add_pre_run_and_checks(filename): src = open(filename, 'r').read().replace( '// {{PRE_RUN_ADDITIONS}}', @@ -2194,11 +2131,10 @@ if 'benchmark' not in str(sys.argv): output_nicerizer=lambda x: x.replace('\n', '*'), post_build=add_pre_run_and_checks, extra_emscripten_args=['-H', 'libc/fcntl.h,libc/sys/unistd.h,poll.h,libc/math.h,libc/time.h,libc/langinfo.h']) - INCLUDE_FULL_LIBRARY = 0 + Settings.INCLUDE_FULL_LIBRARY = 0 def test_dlfcn_varargs(self): - if QUANTUM_SIZE == 1: return self.skip('FIXME: Add support for this') - global BUILD_AS_SHARED_LIB, EXPORTED_FUNCTIONS + if Settings.QUANTUM_SIZE == 1: return self.skip('FIXME: Add support for this') lib_src = r''' void print_ints(int n, ...); extern "C" void func() { @@ -2207,8 +2143,8 @@ if 'benchmark' not in str(sys.argv): ''' dirname = self.get_dir() filename = os.path.join(dirname, 'liblib.cpp') - BUILD_AS_SHARED_LIB = 1 - EXPORTED_FUNCTIONS = ['_func'] + Settings.BUILD_AS_SHARED_LIB = 1 + Settings.EXPORTED_FUNCTIONS = ['_func'] self.build(lib_src, dirname, filename) shutil.move(filename + '.o.js', os.path.join(dirname, 'liblib.so')) @@ -2239,8 +2175,8 @@ if 'benchmark' not in str(sys.argv): return 0; } ''' - BUILD_AS_SHARED_LIB = 0 - EXPORTED_FUNCTIONS = ['_main'] + Settings.BUILD_AS_SHARED_LIB = 0 + Settings.EXPORTED_FUNCTIONS = ['_main'] def add_pre_run_and_checks(filename): src = open(filename, 'r').read().replace( '// {{PRE_RUN_ADDITIONS}}', @@ -2294,7 +2230,7 @@ if 'benchmark' not in str(sys.argv): self.do_run(src, re.sub(r'(^|\n)\s+', r'\1', expected)) def test_strtod(self): - if USE_TYPED_ARRAYS == 2: return self.skip('Typed arrays = 2 truncate doubles') + if Settings.USE_TYPED_ARRAYS == 2: return self.skip('Typed arrays = 2 truncate doubles') src = r''' #include <stdio.h> #include <stdlib.h> @@ -2349,13 +2285,13 @@ if 'benchmark' not in str(sys.argv): self.do_run(src, re.sub(r'\n\s+', '\n', expected)) def test_parseInt(self): - if USE_TYPED_ARRAYS != 0: return self.skip('Typed arrays truncate i64') + if Settings.USE_TYPED_ARRAYS != 0: return self.skip('Typed arrays truncate i64') src = open(path_from_root('tests', 'parseInt', 'src.c'), 'r').read() expected = open(path_from_root('tests', 'parseInt', 'output.txt'), 'r').read() self.do_run(src, expected) def test_printf(self): - if USE_TYPED_ARRAYS != 0: return self.skip('Typed arrays truncate i64') + if Settings.USE_TYPED_ARRAYS != 0: return self.skip('Typed arrays truncate i64') src = open(path_from_root('tests', 'printf', 'test.c'), 'r').read() expected = open(path_from_root('tests', 'printf', 'output.txt'), 'r').read() self.do_run(src, expected) @@ -2410,7 +2346,7 @@ if 'benchmark' not in str(sys.argv): self.do_run(src, expected, extra_emscripten_args=['-H', 'libc/langinfo.h']) def test_files(self): - global CORRECT_SIGNS; CORRECT_SIGNS = 1 # Just so our output is what we expect. Can flip them both. + Settings.CORRECT_SIGNS = 1 # Just so our output is what we expect. Can flip them both. def post(filename): src = open(filename, 'r').read().replace( '// {{PRE_RUN_ADDITIONS}}', @@ -2762,7 +2698,7 @@ if 'benchmark' not in str(sys.argv): self.do_run(src, re.sub('(^|\n)\s+', '\\1', expected), post_build=add_pre_run_and_checks) def test_fs_base(self): - global INCLUDE_FULL_LIBRARY; INCLUDE_FULL_LIBRARY = 1 + Settings.INCLUDE_FULL_LIBRARY = 1 try: def addJS(filename): src = open(filename, 'r').read().replace( @@ -2773,7 +2709,7 @@ if 'benchmark' not in str(sys.argv): expected = open(path_from_root('tests', 'filesystem', 'output.txt'), 'r').read() self.do_run(src, expected, post_build=addJS, extra_emscripten_args=['-H', 'libc/fcntl.h,libc/sys/unistd.h,poll.h,libc/math.h,libc/langinfo.h,libc/time.h']) finally: - INCLUDE_FULL_LIBRARY = 0 + Settings.INCLUDE_FULL_LIBRARY = 0 def test_unistd_access(self): def add_pre_run(filename): @@ -2968,12 +2904,25 @@ if 'benchmark' not in str(sys.argv): def test_ctype(self): # The bit fiddling done by the macros using __ctype_b_loc requires this. - global CORRECT_SIGNS; CORRECT_SIGNS = 1 + Settings.CORRECT_SIGNS = 1 src = open(path_from_root('tests', 'ctype', 'src.c'), 'r').read() expected = open(path_from_root('tests', 'ctype', 'output.txt'), 'r').read() self.do_run(src, expected) CORRECT_SIGNS = 0 + def test_iostream(self): + src = ''' + #include <iostream> + + int main() + { + std::cout << "hello world"; + return 0; + } + ''' + + self.do_run(src, 'hello world') + ### 'Big' tests def test_fannkuch(self): @@ -2983,8 +2932,7 @@ if 'benchmark' not in str(sys.argv): self.do_run(src, 'Pfannkuchen(%d) = %d.' % (i,j), [str(i)], no_build=i>1) def test_raytrace(self): - global USE_TYPED_ARRAYS - if USE_TYPED_ARRAYS == 2: return self.skip('Relies on double values') + if Settings.USE_TYPED_ARRAYS == 2: return self.skip('Relies on double values') src = open(path_from_root('tests', 'raytrace.cpp'), 'r').read() output = open(path_from_root('tests', 'raytrace.ppm'), 'r').read() @@ -2998,9 +2946,9 @@ if 'benchmark' not in str(sys.argv): self.do_run(src, j, [str(i)], lambda x: x.replace('\n', '*'), no_build=i>1) def test_dlmalloc(self): - global CORRECT_SIGNS; CORRECT_SIGNS = 2 - global CORRECT_SIGNS_LINES; CORRECT_SIGNS_LINES = ['src.cpp:' + str(i+4) for i in [4816, 4191, 4246, 4199, 4205, 4235, 4227]] - global TOTAL_MEMORY; TOTAL_MEMORY = 100*1024*1024 # needed with typed arrays + Settings.CORRECT_SIGNS = 2 + Settings.CORRECT_SIGNS_LINES = ['src.cpp:' + str(i+4) for i in [4816, 4191, 4246, 4199, 4205, 4235, 4227]] + Settings.TOTAL_MEMORY = 100*1024*1024 # needed with typed arrays src = open(path_from_root('src', 'dlmalloc.c'), 'r').read() + '\n\n\n' + open(path_from_root('tests', 'dlmalloc_test.c'), 'r').read() self.do_run(src, '*1,0*', ['200', '1']) @@ -3011,21 +2959,6 @@ if 'benchmark' not in str(sys.argv): self.do_run(src, '*1,0*', ['200', '1'], extra_emscripten_args=['-m']) self.do_run(src, '*400,0*', ['400', '400'], extra_emscripten_args=['-m'], no_build=True) - def zzztest_gl(self): - # Switch to gcc from g++ - we don't compile properly otherwise (why?) - global COMPILER - COMPILER = COMPILER.replace('++', '') - - def post(filename): - src = open(filename, 'r').read().replace( - '// {{PRE_RUN_ADDITIONS}}', - '''Module["__CANVAS__"] = { - getContext: function() {}, - };''' - ) - open(filename, 'w').write(src) - self.do_run(path_from_root('tests', 'gl'), '*?*', main_file='sdl_ogl.c', post_build=post) - def test_libcxx(self): self.do_run(path_from_root('tests', 'libcxx'), 'june -> 30\nPrevious (in alphabetical order) is july\nNext (in alphabetical order) is march', @@ -3046,13 +2979,13 @@ if 'benchmark' not in str(sys.argv): ''', 'hello world', includes=[path_from_root('tests', 'libcxx', 'include')]); def test_cubescript(self): - global COMPILER_TEST_OPTS; COMPILER_TEST_OPTS = [] # remove -g, so we have one test without it by default + Building.COMPILER_TEST_OPTS = [] # remove -g, so we have one test without it by default - global SAFE_HEAP; SAFE_HEAP = 0 # Has some actual loads of unwritten-to places, in the C++ code... + Settings.SAFE_HEAP = 0 # Has some actual loads of unwritten-to places, in the C++ code... # Overflows happen in hash loop - global CORRECT_OVERFLOWS; CORRECT_OVERFLOWS = 1 - global CHECK_OVERFLOWS; CHECK_OVERFLOWS = 0 + Settings.CORRECT_OVERFLOWS = 1 + Settings.CHECK_OVERFLOWS = 0 self.do_run(path_from_root('tests', 'cubescript'), '*\nTemp is 33\n9\n5\nhello, everyone\n*', main_file='command.cpp') #build_ll_hook=self.do_autodebug) @@ -3071,15 +3004,14 @@ if 'benchmark' not in str(sys.argv): # print opt, "FAIL" def test_lua(self): - global QUANTUM_SIZE - if QUANTUM_SIZE == 1: return self.skip('TODO: make this work') + if Settings.QUANTUM_SIZE == 1: return self.skip('TODO: make this work') # Overflows in luaS_newlstr hash loop - global SAFE_HEAP; SAFE_HEAP = 0 # Has various warnings, with copied HEAP_HISTORY values (fixed if we copy 'null' as the type) - global CORRECT_OVERFLOWS; CORRECT_OVERFLOWS = 1 - global CHECK_OVERFLOWS; CHECK_OVERFLOWS = 0 - global CORRECT_SIGNS; CORRECT_SIGNS = 1 # Not sure why, but needed - global INIT_STACK; INIT_STACK = 1 # TODO: Investigate why this is necessary + Settings.SAFE_HEAP = 0 # Has various warnings, with copied HEAP_HISTORY values (fixed if we copy 'null' as the type) + Settings.CORRECT_OVERFLOWS = 1 + Settings.CHECK_OVERFLOWS = 0 + Settings.CORRECT_SIGNS = 1 # Not sure why, but needed + Settings.INIT_STACK = 1 # TODO: Investigate why this is necessary self.do_ll_run(path_from_root('tests', 'lua', 'lua.ll'), 'hello lua world!\n17\n1\n2\n3\n4\n7', @@ -3087,68 +3019,20 @@ if 'benchmark' not in str(sys.argv): output_nicerizer=lambda string: string.replace('\n\n', '\n').replace('\n\n', '\n'), extra_emscripten_args=['-H', 'libc/fcntl.h,libc/sys/unistd.h,poll.h,libc/math.h,libc/langinfo.h,libc/time.h']) - def get_building_dir(self): + def get_build_dir(self): return os.path.join(self.get_dir(), 'building') - # Build a library into a .bc file. We build the .bc file once and cache it for all our tests. (We cache in - # memory since the test directory is destroyed and recreated for each test. Note that we cache separately - # for different compilers) - def get_library(self, name, generated_libs, configure=['./configure'], configure_args=[], make=['make'], make_args=['-j', '2'], cache=True, build_subdir=None): - if type(generated_libs) is not list: generated_libs = [generated_libs] - if build_subdir and configure.startswith('./'): - configure = '.' + configure - - if GlobalCache is not None: - cache_name = name + '|' + COMPILER - if cache and GlobalCache.get(cache_name): - print >> sys.stderr, '<load build from cache> ', - bc_file = os.path.join(self.get_dir(), 'lib' + name + '.bc') - f = open(bc_file, 'wb') - f.write(GlobalCache[cache_name]) - f.close() - return bc_file - - temp_dir = self.get_building_dir() - project_dir = os.path.join(temp_dir, name) - shutil.copytree(path_from_root('tests', name), project_dir) # Useful in debugging sometimes to comment this out - os.chdir(project_dir) - if build_subdir: - try: - os.mkdir('cbuild') - except: - pass - os.chdir(os.path.join(project_dir, 'cbuild')) - env = os.environ.copy() - env['RANLIB'] = env['AR'] = env['CXX'] = env['CC'] = env['LIBTOOL'] = EMMAKEN - env['EMMAKEN_COMPILER'] = COMPILER - env['EMSCRIPTEN_TOOLS'] = path_from_root('tools') - env['CFLAGS'] = env['EMMAKEN_CFLAGS'] = ' '.join(COMPILER_OPTS + COMPILER_TEST_OPTS) # Normal CFLAGS is ignored by some configure's. - if configure: # Useful in debugging sometimes to comment this out (and the lines below up to and including the |make| call) - env['EMMAKEN_JUST_CONFIGURE'] = '1' - Popen(configure + configure_args, stdout=open(os.path.join(self.get_dir(), 'configure'), 'w'), - stderr=open(os.path.join(self.get_dir(), 'configure_err'), 'w'), env=env).communicate()[0] - del env['EMMAKEN_JUST_CONFIGURE'] - Popen(make + make_args, stdout=open(os.path.join(self.get_dir(), 'make'), 'w'), - stderr=open(os.path.join(self.get_dir(), 'make_err'), 'w'), env=env).communicate()[0] - bc_file = os.path.join(project_dir, 'bc.bc') - self.do_link(map(lambda lib: os.path.join(project_dir, 'cbuild', lib) if build_subdir else os.path.join(project_dir, lib), generated_libs), bc_file) - if cache and GlobalCache is not None: - print >> sys.stderr, '<save build into cache> ', - GlobalCache[cache_name] = open(bc_file, 'rb').read() - return bc_file - def get_freetype(self): - global INIT_STACK; INIT_STACK = 1 # TODO: Investigate why this is necessary + Settings.INIT_STACK = 1 # TODO: Investigate why this is necessary return self.get_library('freetype', os.path.join('objs', '.libs', 'libfreetype.a.bc')) def test_freetype(self): - if QUANTUM_SIZE == 1: return self.skip('TODO: Figure out and try to fix') + if Settings.QUANTUM_SIZE == 1: return self.skip('TODO: Figure out and try to fix') - if LLVM_OPTS: global RELOOP; RELOOP = 0 # Too slow; we do care about typed arrays and OPTIMIZE though + if Building.LLVM_OPTS: Settings.RELOOP = 0 # Too slow; we do care about typed arrays and OPTIMIZE though - glo |