'''
Simple test runner
See settings.py file for options¶ms. Edit as needed.
'''
from subprocess import Popen, PIPE, STDOUT
import os, unittest, tempfile, shutil, time, inspect, sys, math
# Params
abspath = os.path.abspath(os.path.dirname(__file__))
def path_from_root(pathelems):
return os.path.join(os.path.sep, *(abspath.split(os.sep)[:-1] + pathelems))
EMSCRIPTEN = path_from_root(['emscripten.py'])
exec(open(os.path.join(os.path.abspath(os.path.dirname(__file__)), 'settings.py'), 'r').read())
def timeout_run(proc, timeout, note):
start = time.time()
if timeout is not None:
while time.time() - start < timeout and proc.poll() is None:
time.sleep(0.1)
if proc.poll() is None:
proc.kill() # XXX bug: killing emscripten.py does not kill it's child process!
raise Exception("Timed out: " + note)
return proc.communicate()[0]
class RunnerCore(unittest.TestCase):
def get_dir(self):
dirname = TEMP_DIR + '/tmp' # tempfile.mkdtemp(dir=TEMP_DIR)
if not os.path.exists(dirname):
os.makedirs(dirname)
return dirname
## Build JavaScript code from source code
def build(self, src, dirname, filename, output_processor=None, main_file=None):
# Copy over necessary files for compiling the source
if main_file is None:
f = open(filename, 'w')
f.write(src)
f.close()
else:
# copy whole directory, and use a specific main .cpp file
for f in os.listdir(src):
shutil.copy(os.path.join(src, f), dirname)
shutil.move(os.path.join(dirname, main_file), filename)
# Copy Emscripten C++ API
shutil.copy(path_from_root(['src', 'include', 'emscripten.h']), dirname)
# C++ => LLVM binary
try:
# Make sure we notice if compilation steps failed
os.remove(filename + '.o')
os.remove(filename + '.o.ll')
except:
pass
os.chdir(dirname)
cwd = os.getcwd()
output = Popen([COMPILER, '-DEMSCRIPTEN', '-emit-llvm'] + COMPILER_OPTS + ['-c', filename, '-o', filename + '.o'], stdout=PIPE, stderr=STDOUT).communicate()[0]
os.chdir(cwd)
if not os.path.exists(filename + '.o'):
print "Failed to compile C/C++ source:\n\n", output
raise Exception("Compilation error");
# LLVM binary ==> LLVM assembly
output = Popen([LLVM_DIS, filename + '.o'] + LLVM_DIS_OPTS + ['-o=' + filename + '.o.ll'], stdout=PIPE, stderr=STDOUT).communicate()[0]
self.do_emscripten(filename, output_processor)
def do_emscripten(self, filename, output_processor=None):
# Run Emscripten
exported_settings = {}
for setting in ['QUANTUM_SIZE', 'RELOOP', 'OPTIMIZE', 'GUARD_MEMORY', 'USE_TYPED_ARRAYS']:
exported_settings[setting] = eval(setting)
out = open(filename + '.o.js', 'w') if not OUTPUT_TO_SCREEN else None
timeout_run(Popen([EMSCRIPTEN, filename + '.o.ll', COMPILER_ENGINE[0], str(exported_settings).replace("'", '"')], stdout=out, stderr=STDOUT), TIMEOUT, 'Compiling')
output = open(filename + '.o.js').read()
if output_processor is not None:
output_processor(output)
if output is not None and 'Traceback'