aboutsummaryrefslogtreecommitdiff
path: root/tests/runner.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/runner.py')
-rwxr-xr-xtests/runner.py299
1 files changed, 229 insertions, 70 deletions
diff --git a/tests/runner.py b/tests/runner.py
index cc66068e..8e767e16 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -445,7 +445,7 @@ if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv) and 'brows
if len(sys.argv) == 2 and 'ALL.' in sys.argv[1]:
ignore, test = sys.argv[1].split('.')
print 'Running all test modes on test "%s"' % test
- sys.argv = [sys.argv[0], 'default.'+test, 'o1.'+test, 'o2.'+test, 'asm2.'+test, 's_0_0.'+test, 's_0_1.'+test, 's_0_1_q1.'+test, 's_1_0.'+test, 's_1_1.'+test, 's_1_1_q1.'+test]
+ sys.argv = [sys.argv[0], 'default.'+test, 'o1.'+test, 'o2.'+test, 'asm2.'+test, 'asm2g.'+test, 's_0_0.'+test, 's_0_1.'+test, 's_1_0.'+test, 's_1_1.'+test]
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.
@@ -4271,6 +4271,8 @@ The current type of b is: 9
self.do_run(src, 'ok.');
def test_getopt(self):
+ if self.emcc_args is None: return self.skip('needs emcc for libc')
+
src = '''
#pragma clang diagnostic ignored "-Winvalid-pp-token"
#include <unistd.h>
@@ -4319,6 +4321,8 @@ The current type of b is: 9
self.do_run(src, 'flags=1; tfnd=1; optind=4\nname argument = foobar', args=['-t', '12', '-n', 'foobar'])
def test_getopt_long(self):
+ if self.emcc_args is None: return self.skip('needs emcc for libc')
+
src = '''
#pragma clang diagnostic ignored "-Winvalid-pp-token"
#pragma clang diagnostic ignored "-Wdeprecated-writable-strings"
@@ -5025,6 +5029,8 @@ def process(filename):
self.do_run(src, re.sub(r'(^|\n)\s+', r'\1', expected))
def test_strtod(self):
+ if self.emcc_args is None: return self.skip('needs emcc for libc')
+
src = r'''
#include <stdio.h>
#include <stdlib.h>
@@ -5368,6 +5374,8 @@ at function.:blag
''')
def test_sscanf(self):
+ if self.emcc_args is None: return self.skip('needs emcc for libc')
+
src = r'''
#include <stdio.h>
#include <string.h>
@@ -7139,6 +7147,9 @@ def process(filename):
Settings.DISABLE_EXCEPTION_CATCHING = 1
Settings.FAST_MEMORY = 4*1024*1024
Settings.EXPORTED_FUNCTIONS += ['_sqlite3_open', '_sqlite3_close', '_sqlite3_exec', '_sqlite3_free', '_callback'];
+ if Settings.ASM_JS == 1 and '-g' in self.emcc_args:
+ print "disabling inlining" # without registerize (which -g disables), we generate huge amounts of code
+ Settings.INLINING_LIMIT = 50
self.do_run(r'''
#define SQLITE_DISABLE_LFS
@@ -7240,6 +7251,8 @@ def process(filename):
#, build_ll_hook=self.do_autodebug)
def test_openjpeg(self):
+ if self.emcc_args is None: return self.skip('needs libc for getopt')
+
if Settings.USE_TYPED_ARRAYS == 2:
Settings.CORRECT_SIGNS = 1
else:
@@ -7309,6 +7322,8 @@ def process(filename):
return output
+ self.emcc_args += ['--minify', '0'] # to compare the versions
+
def do_test():
self.do_run(open(path_from_root('tests', 'openjpeg', 'codec', 'j2k_to_image.c'), 'r').read(),
'Successfully generated', # The real test for valid output is in image_compare
@@ -7657,6 +7672,76 @@ def process(filename):
self.do_run(src, '*\nnumber,5\nnumber,3.14\nstring,hello world\n12\nundefined\n14.56\nundefined\ncheez\nundefined\narr-ay\nundefined\nmore\nnumber,10\n650\nnumber,21\n*\natr\n10\nbret\n53\n*\nstack is ok.\n', post_build=post)
+ def test_pgo(self):
+ if Settings.ASM_JS: return self.skip('PGO does not work in asm mode')
+
+ def run_all(name, src):
+ print name
+ def test(expected, args=[], no_build=False):
+ self.do_run(src, expected, args=args, no_build=no_build)
+ return open(self.in_dir('src.cpp.o.js')).read()
+
+ # Sanity check that it works and the dead function is emitted
+ js = test('*9*')
+ assert 'function _unused(' in js
+
+ # Run with PGO, see that unused is true to its name
+ Settings.PGO = 1
+ test("*9*\n-s DEAD_FUNCTIONS='[\"_unused\"]'")
+ Settings.PGO = 0
+
+ # Kill off the dead function, still works and it is not emitted
+ Settings.DEAD_FUNCTIONS = ['_unused']
+ js = test('*9*')
+ assert 'function _unused(' not in js
+ Settings.DEAD_FUNCTIONS = []
+
+ # Run the same code with argc that uses the dead function, see abort
+ test(('ReferenceError: _unused is not defined', 'is not a function'), args=['a', 'b'], no_build=True)
+
+ # Normal stuff
+ run_all('normal', r'''
+ #include <stdio.h>
+ extern "C" {
+ int used(int x) {
+ if (x == 0) return -1;
+ return used(x/3) + used(x/17) + x%5;
+ }
+ int unused(int x) {
+ if (x == 0) return -1;
+ return unused(x/4) + unused(x/23) + x%7;
+ }
+ }
+ int main(int argc, char **argv) {
+ printf("*%d*\n", argc == 3 ? unused(argv[0][0] + 1024) : used(argc + 1555));
+ return 0;
+ }
+ ''')
+
+ # Call by function pointer
+ run_all('function pointers', r'''
+ #include <stdio.h>
+ extern "C" {
+ int used(int x) {
+ if (x == 0) return -1;
+ return used(x/3) + used(x/17) + x%5;
+ }
+ int unused(int x) {
+ if (x == 0) return -1;
+ return unused(x/4) + unused(x/23) + x%7;
+ }
+ }
+ typedef int (*ii)(int);
+ int main(int argc, char **argv) {
+ ii pointers[256];
+ for (int i = 0; i < 256; i++) {
+ pointers[i] = (i == 3) ? unused : used;
+ }
+ printf("*%d*\n", pointers[argc](argc + 1555));
+ return 0;
+ }
+ ''')
+
def test_scriptaclass(self):
if self.emcc_args is None: return self.skip('requires emcc')
if Settings.ASM_JS: return self.skip('asm does not bindings generator yet')
@@ -8522,13 +8607,11 @@ TT = %s
exec('o2 = make_run("o2", compiler=CLANG, emcc_args=["-O2"])')
# asm.js
- #exec('asm = make_run("asm", compiler=CLANG, emcc_args=["-O0", "-s", "ASM_JS=1"])')
exec('asm2 = make_run("asm2", compiler=CLANG, emcc_args=["-O2", "-s", "ASM_JS=1"])')
+ exec('asm2g = make_run("asm2g", compiler=CLANG, emcc_args=["-O2", "-s", "ASM_JS=1", "-g"])')
# Make custom runs with various options
for compiler, quantum, embetter, typed_arrays, llvm_opts in [
- (CLANG, 1, 1, 0, 0),
- (CLANG, 1, 1, 1, 1),
(CLANG, 4, 0, 0, 0),
(CLANG, 4, 0, 0, 1),
(CLANG, 4, 1, 1, 0),
@@ -8696,7 +8779,8 @@ Options that are modified or new in %s include:
assert 'SAFE_HEAP' not in generated, 'safe heap should not be used by default'
assert ': while(' not in generated, 'when relooping we also js-optimize, so there should be no labelled whiles'
if closure:
- assert 'Module._main=' in generated, 'closure compiler should have been run (and output should be minified)'
+ if opt_level <= 1: assert 'Module._main =' in generated, 'closure compiler should have been run'
+ elif opt_level >= 2: assert 'Module._main=' in generated, 'closure compiler should have been run (and output should be minified)'
else:
# closure has not been run, we can do some additional checks. TODO: figure out how to do these even with closure
assert 'Module._main = ' not in generated, 'closure compiler should not have been run'
@@ -8705,14 +8789,16 @@ Options that are modified or new in %s include:
assert ('assert(STACKTOP < STACK_MAX' in generated) == (opt_level == 0), 'assertions should be in opt == 0'
assert 'var $i;' in generated or 'var $i_0' in generated or 'var $storemerge3;' in generated or 'var $storemerge4;' in generated or 'var $i_04;' in generated, 'micro opts should always be on'
if opt_level >= 2:
- assert re.search('HEAP8\[\$?\w+ \+ \(+\$?\w+ ', generated) or re.search('HEAP8\[HEAP32\[', generated), 'eliminator should create compound expressions, and fewer one-time vars' # also in -O1, but easier to test in -O2
+ assert re.search('HEAP8\[\$?\w+ ?\+ ?\(+\$?\w+ ?', generated) or re.search('HEAP8\[HEAP32\[', generated), 'eliminator should create compound expressions, and fewer one-time vars' # also in -O1, but easier to test in -O2
assert ('_puts(' in generated) == (opt_level >= 1), 'with opt >= 1, llvm opts are run and they should optimize printf to puts'
- assert 'function _main() {' in generated, 'Should be unminified, including whitespace'
+ if opt_level <= 1 or '-g' in params: assert 'function _main() {' in generated, 'Should be unminified, including whitespace'
+ elif opt_level >= 2: assert 'function _main(){' in generated, 'Should be whitespace-minified'
# emcc -s RELOOP=1 src.cpp ==> should pass -s to emscripten.py. --typed-arrays is a convenient alias for -s USE_TYPED_ARRAYS
for params, test, text in [
- (['-s', 'ASM_JS=1', '-O2'], lambda generated: 'var i1 = 0' in generated, 'registerize is run by default in -O2'),
- (['-s', 'ASM_JS=1', '-O2', '-g'], lambda generated: 'var i1 = 0' not in generated, 'registerize is cancelled by -g'),
+ (['-s', 'ASM_JS=1', '-O2'], lambda generated: 'var b=0' in generated and not 'function _main' in generated, 'registerize/minify is run by default in -O2'),
+ (['-s', 'ASM_JS=1', '-O2', '--minify', '0'], lambda generated: 'var b = 0' in generated and not 'function _main' in generated, 'minify is cancelled, but not registerize'),
+ (['-s', 'ASM_JS=1', '-O2', '-g'], lambda generated: 'var b=0' not in generated and 'var b = 0' not in generated and 'function _main' in generated, 'registerize/minify is cancelled by -g'),
(['-s', 'INLINING_LIMIT=0'], lambda generated: 'function _dump' in generated, 'no inlining without opts'),
(['-O3', '-s', 'INLINING_LIMIT=0', '--closure', '0'], lambda generated: 'function _dump' not in generated, 'lto/inlining'),
(['-Os', '--llvm-lto', '1'], lambda generated: 'function _dump' in generated, '-Os disables inlining'),
@@ -8927,6 +9013,48 @@ f.close()
Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'test.cpp'), '-s', 'UNALIGNED_MEMORY=1']).communicate()
self.assertContained('testString = Hello, World!', run_js(os.path.join(self.get_dir(), 'a.out.js')))
+ def test_asm_minify(self):
+ def test(args):
+ Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world_loop_malloc.cpp')] + args).communicate()
+ self.assertContained('hello, world!', run_js(self.in_dir('a.out.js')))
+ return open(self.in_dir('a.out.js')).read()
+
+ src = test([])
+ assert 'function _malloc' in src
+
+ src = test(['-O2', '-s', 'ASM_JS=1'])
+ normal_size = len(src)
+ print 'normal', normal_size
+ assert 'function _malloc' not in src
+
+ src = test(['-O2', '-s', 'ASM_JS=1', '--minify', '0'])
+ unminified_size = len(src)
+ print 'unminified', unminified_size
+ assert unminified_size > normal_size
+ assert 'function _malloc' not in src
+
+ src = test(['-O2', '-s', 'ASM_JS=1', '-g'])
+ debug_size = len(src)
+ print 'debug', debug_size
+ assert debug_size > unminified_size
+ assert 'function _malloc' in src
+
+ def test_asm_pgo(self):
+ Popen([PYTHON, EMXX, '-O2', '-s', 'ASM_JS=1', path_from_root('tests', 'hello_libcxx.cpp'), '-o', 'normal.js']).communicate()
+ self.assertContained('hello, world!', run_js(self.in_dir('normal.js')))
+
+ Popen([PYTHON, EMXX, '-O2', '-s', 'PGO=1', path_from_root('tests', 'hello_libcxx.cpp'), '-o', 'pgo.js']).communicate()
+ pgo_output = run_js(self.in_dir('pgo.js'))
+ self.assertContained('hello, world!', pgo_output)
+
+ open('pgo_data', 'w').write(pgo_output.split('\n')[1])
+ Popen([PYTHON, EMXX, '-O2', '-s', 'ASM_JS=1', path_from_root('tests', 'hello_libcxx.cpp'), '-o', 'pgoed.js', '@pgo_data']).communicate()
+ self.assertContained('hello, world!', run_js(self.in_dir('pgoed.js')))
+
+ before = len(open('normal.js').read())
+ after = len(open('pgoed.js').read())
+ assert after < 0.66 * before, [before, after] # expect a big size reduction
+
def test_l_link(self):
# Linking with -lLIBNAME and -L/DIRNAME should work
@@ -9609,6 +9737,22 @@ f.close()
Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--pre-js', 'pre.js', '--pre-js', 'pre2.js']).communicate()
self.assertContained('prepre\npre-run\nhello from main\n', run_js(os.path.join(self.get_dir(), 'a.out.js')))
+ def test_save_bc(self):
+ for save in [0, 1]:
+ self.clear()
+ Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world_loop_malloc.cpp')] + ([] if not save else ['--save-bc', self.in_dir('my_bitcode.bc')])).communicate()
+ assert 'hello, world!' in run_js(self.in_dir('a.out.js'))
+ assert os.path.exists(self.in_dir('my_bitcode.bc')) == save
+ if save:
+ try_delete('a.out.js')
+ Building.llvm_dis(self.in_dir('my_bitcode.bc'), self.in_dir('my_ll.ll'))
+ try:
+ os.environ['EMCC_LEAVE_INPUTS_RAW'] = '1'
+ Popen([PYTHON, EMCC, 'my_ll.ll', '-o', 'two.js']).communicate()
+ assert 'hello, world!' in run_js(self.in_dir('two.js'))
+ finally:
+ del os.environ['EMCC_LEAVE_INPUTS_RAW']
+
def test_fix_closure(self):
input = path_from_root('tests', 'test-fix-closure.js')
expected = path_from_root('tests', 'test-fix-closure.out.js')
@@ -9639,6 +9783,8 @@ f.close()
['asm', 'eliminate']),
(path_from_root('tools', 'test-js-optimizer-asm-regs.js'), open(path_from_root('tools', 'test-js-optimizer-asm-regs-output.js')).read(),
['asm', 'registerize']),
+ (path_from_root('tools', 'test-js-optimizer-asm-regs-min.js'), open(path_from_root('tools', 'test-js-optimizer-asm-regs-min-output.js')).read(),
+ ['asm', 'registerize']),
(path_from_root('tools', 'test-js-optimizer-asm-pre.js'), open(path_from_root('tools', 'test-js-optimizer-asm-pre-output.js')).read(),
['asm', 'simplifyExpressionsPre']),
(path_from_root('tools', 'test-js-optimizer-asm-last.js'), open(path_from_root('tools', 'test-js-optimizer-asm-last-output.js')).read(),
@@ -9660,8 +9806,8 @@ f.close()
try:
os.environ['EMCC_DEBUG'] = '1'
for asm, linkable, chunks, js_chunks in [
- (0, 0, 3, 2), (0, 1, 4, 4),
- (1, 0, 3, 2), (1, 1, 4, 5)
+ (0, 0, 3, 2), (0, 1, 3, 4),
+ (1, 0, 3, 2), (1, 1, 3, 4)
]:
print asm, linkable, chunks, js_chunks
output, err = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_libcxx.cpp'), '-O1', '-s', 'LINKABLE=%d' % linkable, '-s', 'ASM_JS=%d' % asm], stdout=PIPE, stderr=PIPE).communicate()
@@ -10633,6 +10779,15 @@ elif 'browser' in str(sys.argv):
Popen([PYTHON, EMCC, '-O2', '--minify', '0', os.path.join(self.get_dir(), 'sdl_audio.c'), '--preload-file', 'sound.ogg', '--preload-file', 'sound2.wav', '--preload-file', 'bad.ogg', '-o', 'page.html', '-s', 'EXPORTED_FUNCTIONS=["_main", "_play", "_play2"]']).communicate()
self.run_browser('page.html', '', '/report_result?1')
+ def test_sdl_audio_mix(self):
+ shutil.copyfile(path_from_root('tests', 'sounds', 'pluck.ogg'), os.path.join(self.get_dir(), 'sound.ogg'))
+ shutil.copyfile(path_from_root('tests', 'sounds', 'the_entertainer.ogg'), os.path.join(self.get_dir(), 'music.ogg'))
+ open(os.path.join(self.get_dir(), 'sdl_audio_mix.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_audio_mix.c')).read()))
+
+ # use closure to check for a possible bug with closure minifying away newer Audio() attributes
+ Popen([PYTHON, EMCC, '-O2', '--minify', '0', os.path.join(self.get_dir(), 'sdl_audio_mix.c'), '--preload-file', 'sound.ogg', '--preload-file', 'music.ogg', '-o', 'page.html']).communicate()
+ self.run_browser('page.html', '', '/report_result?1')
+
def test_sdl_audio_quickload(self):
open(os.path.join(self.get_dir(), 'sdl_audio_quickload.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_audio_quickload.c')).read()))
@@ -10845,11 +11000,12 @@ elif 'browser' in str(sys.argv):
self.run_browser('something.html', 'You should see animating gears.', '/report_result?0')
def test_glgears_animation(self):
- for full_es2 in [0, 1]:
+ es2_suffix = ['', '_full', '_full_944']
+ for full_es2 in [0, 1, 2]:
for emulation in [0, 1]:
if full_es2 and emulation: continue
print full_es2, emulation
- Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world_gles%s.c' % ('' if not full_es2 else '_full')), '-o', 'something.html',
+ Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world_gles%s.c' % es2_suffix[full_es2]), '-o', 'something.html',
'-DHAVE_BUILTIN_SINCOS', '-s', 'GL_TESTING=1',
'--shell-file', path_from_root('tests', 'hello_world_gles_shell.html')] +
(['-s', 'FORCE_GL_EMULATION=1'] if emulation else []) +
@@ -12024,66 +12180,69 @@ fi
EMCC_CACHE = Cache.dirname
- restore()
-
- Cache.erase()
- assert not os.path.exists(EMCC_CACHE)
+ for compiler in [EMCC, EMXX]:
+ print compiler
- try:
- os.environ['EMCC_DEBUG'] ='1'
- self.working_dir = os.path.join(TEMP_DIR, 'emscripten_temp')
+ restore()
- # Building a file that doesn't need cached stuff should not trigger cache generation
- output = self.do([EMCC, path_from_root('tests', 'hello_world.cpp')])
- assert INCLUDING_MESSAGE.replace('X', 'libc') not in output
- assert BUILDING_MESSAGE.replace('X', 'libc') not in output
- self.assertContained('hello, world!', run_js('a.out.js'))
+ Cache.erase()
assert not os.path.exists(EMCC_CACHE)
- try_delete('a.out.js')
-
- basebc_name = os.path.join(TEMP_DIR, 'emscripten_temp', 'emcc-0-basebc.bc')
- dcebc_name1 = os.path.join(TEMP_DIR, 'emscripten_temp', 'emcc-1-linktime.bc')
- dcebc_name2 = os.path.join(TEMP_DIR, 'emscripten_temp', 'emcc-2-linktime.bc')
- ll_names = [os.path.join(TEMP_DIR, 'emscripten_temp', 'emcc-X-ll.ll').replace('X', str(x)) for x in range(2,5)]
-
- # Building a file that *does* need dlmalloc *should* trigger cache generation, but only the first time
- for filename, libname in [('hello_malloc.cpp', 'libc'), ('hello_libcxx.cpp', 'libcxx')]:
- for i in range(3):
- print filename, libname, i
- self.clear()
- dcebc_name = dcebc_name1 if i == 0 else dcebc_name2
- try_delete(basebc_name) # we might need to check this file later
- try_delete(dcebc_name) # we might need to check this file later
- for ll_name in ll_names: try_delete(ll_name)
- output = self.do([EMCC, '-O' + str(i), '-s', 'RELOOP=0', '--llvm-lto', '0', path_from_root('tests', filename)])
- #print output
- assert INCLUDING_MESSAGE.replace('X', libname) in output
- if libname == 'libc':
- assert INCLUDING_MESSAGE.replace('X', 'libcxx') not in output # we don't need libcxx in this code
- else:
- assert INCLUDING_MESSAGE.replace('X', 'libc') in output # libcxx always forces inclusion of libc
- assert (BUILDING_MESSAGE.replace('X', libname) in output) == (i == 0), 'Must only build the first time'
- self.assertContained('hello, world!', run_js('a.out.js'))
- assert os.path.exists(EMCC_CACHE)
- assert os.path.exists(os.path.join(EMCC_CACHE, libname + '.bc'))
- if libname == 'libcxx':
- print os.stat(os.path.join(EMCC_CACHE, libname + '.bc')).st_size, os.stat(basebc_name).st_size, os.stat(dcebc_name).st_size
- assert os.stat(os.path.join(EMCC_CACHE, libname + '.bc')).st_size > 1800000, 'libc++ is big'
- assert os.stat(basebc_name).st_size > 1800000, 'libc++ is indeed big'
- assert os.stat(dcebc_name).st_size < 750000, 'Dead code elimination must remove most of libc++'
- # should only have metadata in -O0, not 1 and 2
- if i > 0:
- for ll_name in ll_names:
- ll = None
- try:
- ll = open(ll_name).read()
- break
- except:
- pass
- assert ll
- assert ll.count('\n!') < 10 # a few lines are left even in -O1 and -O2
- finally:
- del os.environ['EMCC_DEBUG']
+
+ try:
+ os.environ['EMCC_DEBUG'] ='1'
+ self.working_dir = os.path.join(TEMP_DIR, 'emscripten_temp')
+
+ # Building a file that doesn't need cached stuff should not trigger cache generation
+ output = self.do([compiler, path_from_root('tests', 'hello_world.cpp')])
+ assert INCLUDING_MESSAGE.replace('X', 'libc') not in output
+ assert BUILDING_MESSAGE.replace('X', 'libc') not in output
+ self.assertContained('hello, world!', run_js('a.out.js'))
+ assert not os.path.exists(EMCC_CACHE)
+ try_delete('a.out.js')
+
+ basebc_name = os.path.join(TEMP_DIR, 'emscripten_temp', 'emcc-0-basebc.bc')
+ dcebc_name1 = os.path.join(TEMP_DIR, 'emscripten_temp', 'emcc-1-linktime.bc')
+ dcebc_name2 = os.path.join(TEMP_DIR, 'emscripten_temp', 'emcc-2-linktime.bc')
+ ll_names = [os.path.join(TEMP_DIR, 'emscripten_temp', 'emcc-X-ll.ll').replace('X', str(x)) for x in range(2,5)]
+
+ # Building a file that *does* need dlmalloc *should* trigger cache generation, but only the first time
+ for filename, libname in [('hello_malloc.cpp', 'libc'), ('hello_libcxx.cpp', 'libcxx')]:
+ for i in range(3):
+ print filename, libname, i
+ self.clear()
+ dcebc_name = dcebc_name1 if i == 0 else dcebc_name2
+ try_delete(basebc_name) # we might need to check this file later
+ try_delete(dcebc_name) # we might need to check this file later
+ for ll_name in ll_names: try_delete(ll_name)
+ output = self.do([compiler, '-O' + str(i), '-s', 'RELOOP=0', '--llvm-lto', '0', path_from_root('tests', filename)])
+ #print output
+ assert INCLUDING_MESSAGE.replace('X', libname) in output
+ if libname == 'libc':
+ assert INCLUDING_MESSAGE.replace('X', 'libcxx') not in output # we don't need libcxx in this code
+ else:
+ assert INCLUDING_MESSAGE.replace('X', 'libc') in output # libcxx always forces inclusion of libc
+ assert (BUILDING_MESSAGE.replace('X', libname) in output) == (i == 0), 'Must only build the first time'
+ self.assertContained('hello, world!', run_js('a.out.js'))
+ assert os.path.exists(EMCC_CACHE)
+ assert os.path.exists(os.path.join(EMCC_CACHE, libname + '.bc'))
+ if libname == 'libcxx':
+ print os.stat(os.path.join(EMCC_CACHE, libname + '.bc')).st_size, os.stat(basebc_name).st_size, os.stat(dcebc_name).st_size
+ assert os.stat(os.path.join(EMCC_CACHE, libname + '.bc')).st_size > 1800000, 'libc++ is big'
+ assert os.stat(basebc_name).st_size > 1800000, 'libc++ is indeed big'
+ assert os.stat(dcebc_name).st_size < 750000, 'Dead code elimination must remove most of libc++'
+ # should only have metadata in -O0, not 1 and 2
+ if i > 0:
+ for ll_name in ll_names:
+ ll = None
+ try:
+ ll = open(ll_name).read()
+ break
+ except:
+ pass
+ assert ll
+ assert ll.count('\n!') < 10 # a few lines are left even in -O1 and -O2
+ finally:
+ del os.environ['EMCC_DEBUG']
# Manual cache clearing
assert os.path.exists(EMCC_CACHE)