aboutsummaryrefslogtreecommitdiff
path: root/tests/runner.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/runner.py')
-rw-r--r--tests/runner.py745
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&params. 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