aboutsummaryrefslogtreecommitdiff
path: root/tests/runner.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/runner.py')
-rwxr-xr-xtests/runner.py166
1 files changed, 153 insertions, 13 deletions
diff --git a/tests/runner.py b/tests/runner.py
index 6404a211..a4bc4944 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -1987,6 +1987,52 @@ c5,de,15,8a
else:
self.do_run(src, 'second\nmain: 0\n')
+ def test_longjmp2(self):
+ src = r'''
+ #include <setjmp.h>
+ #include <stdio.h>
+
+ typedef struct {
+ jmp_buf* jmp;
+ } jmp_state;
+
+ void stack_manipulate_func(jmp_state* s, int level) {
+ jmp_buf buf;
+
+ printf("Entering stack_manipulate_func, level: %d\n", level);
+
+ if (level == 0) {
+ s->jmp = &buf;
+ if (setjmp(*(s->jmp)) == 0) {
+ printf("Setjmp normal execution path, level: %d\n", level);
+ stack_manipulate_func(s, level + 1);
+ } else {
+ printf("Setjmp error execution path, level: %d\n", level);
+ }
+ } else {
+ printf("Perform longjmp at level %d\n", level);
+ longjmp(*(s->jmp), 1);
+ }
+
+ printf("Exiting stack_manipulate_func, level: %d\n", level);
+ }
+
+ int main(int argc, char *argv[]) {
+ jmp_state s;
+ s.jmp = NULL;
+ stack_manipulate_func(&s, 0);
+
+ return 0;
+ }
+ '''
+ self.do_run(src, '''Entering stack_manipulate_func, level: 0
+Setjmp normal execution path, level: 0
+Entering stack_manipulate_func, level: 1
+Perform longjmp at level 1
+Setjmp error execution path, level: 0
+Exiting stack_manipulate_func, level: 0
+''')
+
def test_exceptions(self):
if Settings.QUANTUM_SIZE == 1: return self.skip("we don't support libcxx in q1")
@@ -2777,6 +2823,7 @@ c5,de,15,8a
// EMSCRIPTEN_COMMENT("hello from the source");
emscripten_run_script("Module.print('hello world' + '!')");
printf("*%d*\n", emscripten_run_script_int("5*20"));
+ printf("*%s*\n", emscripten_run_script_string("'five'+'six'"));
emscripten_run_script("_save_me_aimee()");
return 0;
}
@@ -2788,19 +2835,26 @@ def process(filename):
# TODO: restore this (see comment in emscripten.h) assert '// hello from the source' in src
'''
- self.do_run(src, 'hello world!\n*100*\nmann\n', post_build=check)
+ self.do_run(src, 'hello world!\n*100*\n*fivesix*\nmann\n', post_build=check)
def test_inlinejs(self):
src = r'''
#include <stdio.h>
+ double get() {
+ double ret = 0;
+ __asm __volatile__("12/3.3":"=a"(ret));
+ return ret;
+ }
+
int main() {
asm("Module.print('Inline JS is very cool')");
+ printf("%.2f\n", get());
return 0;
}
'''
- self.do_run(src, 'Inline JS is very cool')
+ self.do_run(src, 'Inline JS is very cool\n3.64')
def test_memorygrowth(self):
if Settings.USE_TYPED_ARRAYS == 0: return self.skip('memory growth is only supported with typed arrays')
@@ -6180,7 +6234,9 @@ def process(filename):
finally:
del os.environ['EMCC_DEBUG']
for debug in [1,2]:
- self.assertIdentical(open('release.js').read().replace('\n\n', '\n').replace('\n\n', '\n'), open('debug%d.js' % debug).read().replace('\n\n', '\n').replace('\n\n', '\n')) # EMCC_DEBUG=1 mode must not generate different code!
+ def clean(text):
+ return text.replace('\n\n', '\n').replace('\n\n', '\n').replace('\n\n', '\n').replace('\n\n', '\n').replace('\n\n', '\n')
+ self.assertIdentical(clean(open('release.js').read()), clean(open('debug%d.js' % debug).read())) # EMCC_DEBUG=1 mode must not generate different code!
print >> sys.stderr, 'debug check %d passed too' % debug
try_delete(CANONICAL_TEMP_DIR)
@@ -8287,7 +8343,7 @@ f.close()
(path_from_root('tools', 'test-js-optimizer-t2.js'), open(path_from_root('tools', 'test-js-optimizer-t2-output.js')).read(),
['simplifyExpressionsPre', 'optimizeShiftsAggressive']),
# Make sure that optimizeShifts handles functions with shift statements.
- (path_from_root('tools', 'test-js-optimizer-t3.js'), open(path_from_root('tools', 'test-js-optimizer-t3.js')).read(),
+ (path_from_root('tools', 'test-js-optimizer-t3.js'), open(path_from_root('tools', 'test-js-optimizer-t3-output.js')).read(),
['optimizeShiftsAggressive']),
(path_from_root('tools', 'test-js-optimizer-regs.js'), open(path_from_root('tools', 'test-js-optimizer-regs-output.js')).read(),
['registerize']),
@@ -8306,6 +8362,17 @@ f.close()
assert 'foo.o: ' in output, '-%s failed to produce the right output: %s' % (opt, output)
assert 'error' not in err, 'Unexpected stderr: ' + err
+ def test_chunking(self):
+ if os.environ.get('EMCC_DEBUG'): return self.skip('cannot run in debug mode')
+ if multiprocessing.cpu_count() < 2: return self.skip('need multiple cores')
+ try:
+ os.environ['EMCC_DEBUG'] = '1'
+ output, err = Popen(['python', EMCC, path_from_root('tests', 'hello_libcxx.cpp'), '-O1'], stdout=PIPE, stderr=PIPE).communicate()
+ assert 'phase 2 working on 3 chunks' in err, err
+ assert 'splitting up js optimization into 2 chunks' in err, err
+ finally:
+ del os.environ['EMCC_DEBUG']
+
def test_scons(self): # also incidentally tests c++11 integration in llvm 3.1
try_delete(os.path.join(self.get_dir(), 'test'))
shutil.copytree(path_from_root('tests', 'scons'), os.path.join(self.get_dir(), 'test'))
@@ -10062,6 +10129,8 @@ elif 'sanity' in str(sys.argv):
assert os.path.exists(CONFIG_FILE), 'To run these tests, we need a (working!) %s file to already exist' % EM_CONFIG
+ assert not os.environ.get('EMCC_DEBUG'), 'do not run sanity checks in debug mode!'
+
shutil.copyfile(CONFIG_FILE, CONFIG_FILE + '_backup')
def restore():
shutil.copyfile(CONFIG_FILE + '_backup', CONFIG_FILE)
@@ -10294,10 +10363,11 @@ fi
self.assertContained(SANITY_MESSAGE, output)
# but with EMCC_DEBUG=1 we should check
- assert not os.environ.get('EMCC_DEBUG'), 'do not run sanity checks in debug mode!'
- os.environ['EMCC_DEBUG'] = '1'
- output = self.check_working(EMCC)
- del os.environ['EMCC_DEBUG']
+ try:
+ os.environ['EMCC_DEBUG'] = '1'
+ output = self.check_working(EMCC)
+ finally:
+ del os.environ['EMCC_DEBUG']
self.assertContained(SANITY_MESSAGE, output)
output = self.check_working(EMCC)
self.assertNotContained(SANITY_MESSAGE, output)
@@ -10354,8 +10424,8 @@ fi
assert not os.path.exists(EMCC_CACHE)
try:
- emcc_debug = os.environ.get('EMCC_DEBUG')
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([EMCC, path_from_root('tests', 'hello_world.cpp')])
@@ -10371,8 +10441,6 @@ fi
ll_name1 = os.path.join(TEMP_DIR, 'emscripten_temp', 'emcc-2-ll.ll')
ll_name2 = os.path.join(TEMP_DIR, 'emscripten_temp', 'emcc-3-ll.ll')
- self.working_dir = os.path.join(TEMP_DIR, 'emscripten_temp')
-
# Building a file that *does* need dlmalloc *should* trigger cache generation, but only the first time
for filename, libname in [('hello_malloc.cpp', 'dlmalloc'), ('hello_libcxx.cpp', 'libcxx')]:
for i in range(3):
@@ -10405,8 +10473,7 @@ fi
print i, 'll metadata should be removed in -O1 and O2 by default', ll[-300:]
assert False
finally:
- if emcc_debug:
- os.environ['EMCC_DEBUG'] = emcc_debug
+ del os.environ['EMCC_DEBUG']
# Manual cache clearing
assert os.path.exists(EMCC_CACHE)
@@ -10434,6 +10501,79 @@ fi
assert os.path.exists(RELOOPER) == (i >= 2), 'have relooper on O2: ' + output
assert ('L2 : do {' in open('a.out.js').read()) == (i >= 2), 'reloop code on O2: ' + output
+ def test_jcache(self):
+ PRE_LOAD_MSG = 'loading pre from jcache'
+ PRE_SAVE_MSG = 'saving pre to jcache'
+ FUNC_CHUNKS_LOAD_MSG = ' funcchunks from jcache'
+ FUNC_CHUNKS_SAVE_MSG = ' funcchunks to jcache'
+ JSFUNC_CHUNKS_LOAD_MSG = 'jsfuncchunks from jcache'
+ JSFUNC_CHUNKS_SAVE_MSG = 'jsfuncchunks to jcache'
+
+ restore()
+ Cache.erase()
+
+ try:
+ os.environ['EMCC_DEBUG'] = '1'
+ self.working_dir = os.path.join(TEMP_DIR, 'emscripten_temp')
+ if not os.path.exists(self.working_dir): os.makedirs(self.working_dir)
+
+ assert not os.path.exists(JCache.get_cachename('emscript_files'))
+
+ srcs = {}
+ used_jcache = False
+
+ for args, input_file, expect_pre_save, expect_pre_load, expect_funcs_save, expect_funcs_load, expect_jsfuncs_save, expect_jsfuncs_load, expected in [
+ ([], 'hello_world_loop.cpp', False, False, False, False, False, False, []),
+ (['--jcache'], 'hello_world_loop.cpp', True, False, True, False, True, False, []),
+ (['--jcache'], 'hello_world_loop.cpp', False, True, False, True, False, True, []),
+ ([], 'hello_world_loop.cpp', False, False, False, False, False, False, []),
+ # new
+ ([], 'hello_world.cpp', False, False, False, False, False, False, []),
+ (['--jcache'], 'hello_world.cpp', True, False, True, False, True, False, []),
+ (['--jcache'], 'hello_world.cpp', False, True, False, True, False, True, []),
+ ([], 'hello_world.cpp', False, False, False, False, False, False, []),
+ # go back to old file, experience caching
+ (['--jcache'], 'hello_world_loop.cpp', False, True, False, True, False, True, []),
+ # new, large file
+ ([], 'hello_malloc.cpp', False, False, False, False, False, False, []),
+ (['--jcache'], 'hello_malloc.cpp', True, False, True, False, True, False, []),
+ (['--jcache'], 'hello_malloc.cpp', False, True, False, True, False, True, []),
+ ([], 'hello_malloc.cpp', False, False, False, False, False, False, []),
+ # new, huge file
+ ([], 'hello_libcxx.cpp', False, False, False, False, False, False, ('2 chunks', '3 chunks')),
+ (['--jcache'], 'hello_libcxx.cpp', True, False, True, False, True, False, []),
+ (['--jcache'], 'hello_libcxx.cpp', False, True, False, True, False, True, []),
+ ([], 'hello_libcxx.cpp', False, False, False, False, False, False, []),
+ # finally, build a file close to the previous, to see that some chunks are found in the cache and some not
+ (['--jcache'], 'hello_libcxx_mod1.cpp', False, True, True, True, True, False, []), # win on pre, mix on funcs, fail on jsfuncs
+ (['--jcache'], 'hello_libcxx_mod1.cpp', False, True, False, True, False, True, []),
+ ]:
+ print >> sys.stderr, args, input_file, expect_pre_save, expect_pre_load, expect_funcs_save, expect_funcs_load, expect_jsfuncs_save, expect_jsfuncs_load, expected
+ self.clear()
+ out, err = Popen(['python', EMCC, '-O2', '--closure', '0', path_from_root('tests', input_file)] + args, stdout=PIPE, stderr=PIPE).communicate()
+ errtail = err.split('emcc invocation')[-1]
+ self.assertContained('hello, world!', run_js('a.out.js'), errtail)
+ assert (PRE_SAVE_MSG in err) == expect_pre_save, errtail
+ assert (PRE_LOAD_MSG in err) == expect_pre_load, errtail
+ assert (FUNC_CHUNKS_SAVE_MSG in err) == expect_funcs_save, errtail
+ assert (FUNC_CHUNKS_LOAD_MSG in err) == expect_funcs_load, errtail
+ assert (JSFUNC_CHUNKS_SAVE_MSG in err) == expect_jsfuncs_save, errtail
+ assert (JSFUNC_CHUNKS_LOAD_MSG in err) == expect_jsfuncs_load, errtail
+ for expect in expected: assert expect in err, expect + ' ? ' + errtail
+ curr = open('a.out.js').read()
+ if input_file not in srcs:
+ srcs[input_file] = curr
+ else:
+ open('/home/alon/Dev/emscripten/a', 'w').write(srcs[input_file])
+ open('/home/alon/Dev/emscripten/b', 'w').write(curr)
+ assert abs(len(curr)/float(len(srcs[input_file]))-1)<0.01, 'contents may shift in order, but must remain the same size %d vs %d' % (len(curr), len(srcs[input_file])) + '\n' + errtail
+ used_jcache = used_jcache or ('--jcache' in args)
+ assert used_jcache == os.path.exists(JCache.get_cachename('emscript_files'))
+ #print >> sys.stderr, errtail
+
+ finally:
+ del os.environ['EMCC_DEBUG']
+
else:
raise Exception('Test runner is confused: ' + str(sys.argv))