aboutsummaryrefslogtreecommitdiff
path: root/tests/runner.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/runner.py')
-rwxr-xr-xtests/runner.py143
1 files changed, 141 insertions, 2 deletions
diff --git a/tests/runner.py b/tests/runner.py
index 00426b0c..7ae2dc41 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -138,7 +138,7 @@ class RunnerCore(unittest.TestCase):
# Hardcode in the arguments, so js is portable without manual commandlinearguments
if not args: return
js = open(filename).read()
- open(filename, 'w').write(js.replace('var ret = run();', 'var ret = run(%s);' % str(args)))
+ open(filename, 'w').write(js.replace('run();', 'run(%s);' % str(args)))
def prep_ll_run(self, filename, ll_file, force_recompile=False, build_ll_hook=None):
if ll_file.endswith(('.bc', '.o')):
@@ -2505,6 +2505,145 @@ Calling longjmp the second time!
Exception execution path of first function! 1
''')
+ def test_longjmp_funcptr(self):
+ src = r'''
+ #include <stdio.h>
+ #include <setjmp.h>
+
+ static jmp_buf buf;
+
+ void (*fp)() = NULL;
+
+ void second(void) {
+ printf("second\n"); // prints
+ longjmp(buf,1); // jumps back to where setjmp was called - making setjmp now return 1
+ }
+
+ void first(void) {
+ fp();
+ printf("first\n"); // does not print
+ }
+
+ int main(int argc, char **argv) {
+ fp = argc == 200 ? NULL : second;
+
+ volatile int x = 0;
+ if ( ! setjmp(buf) ) {
+ x++;
+ first(); // when executed, setjmp returns 0
+ } else { // when longjmp jumps back, setjmp returns 1
+ printf("main: %d\n", x); // prints
+ }
+
+ return 0;
+ }
+ '''
+ self.do_run(src, 'second\nmain: 1\n')
+
+ def test_longjmp_repeat(self):
+ Settings.MAX_SETJMPS = 1
+
+ src = r'''
+ #include <stdio.h>
+ #include <setjmp.h>
+
+ static jmp_buf buf;
+
+ int main() {
+ volatile int x = 0;
+ printf("setjmp:%d\n", setjmp(buf));
+ x++;
+ printf("x:%d\n", x);
+ if (x < 4) longjmp(buf, x*2);
+ return 0;
+ }
+ '''
+ self.do_run(src, '''setjmp:0
+x:1
+setjmp:2
+x:2
+setjmp:4
+x:3
+setjmp:6
+x:4
+''')
+
+ def test_longjmp_stacked(self):
+ src = r'''
+ #include <stdio.h>
+ #include <setjmp.h>
+ #include <stdlib.h>
+ #include <string.h>
+
+ int bottom, top;
+
+ int run(int y) {
+ // confuse stack
+ char *s = (char*)alloca(100);
+ memset(s, 1, 100);
+ s[y] = y;
+ s[y/2] = y*2;
+ volatile int x = s[y];
+ top = (int)alloca(4);
+ if (x <= 2) return x;
+ jmp_buf buf;
+ printf("setjmp of %d\n", x);
+ if (setjmp(buf) == 0) {
+ printf("going\n");
+ x += run(x/2);
+ longjmp(buf, 1);
+ }
+ printf("back\n");
+ return x/2;
+ }
+
+ int main(int argc, char **argv) {
+ int sum = 0;
+ for (int i = 0; i < argc*2; i++) {
+ bottom = (int)alloca(4);
+ sum += run(10);
+ // scorch the earth
+ if (bottom < top) {
+ memset((void*)bottom, 1, top - bottom);
+ } else {
+ memset((void*)top, 1, bottom - top);
+ }
+ }
+ printf("%d\n", sum);
+ return sum;
+ }
+ '''
+ self.do_run(src, '''setjmp of 10
+going
+setjmp of 5
+going
+back
+back
+setjmp of 10
+going
+setjmp of 5
+going
+back
+back
+12
+''')
+
+ def test_setjmp_many(self):
+ src = r'''
+ #include <stdio.h>
+ #include <setjmp.h>
+
+ int main(int argc) {
+ jmp_buf buf;
+ for (int i = 0; i < NUM; i++) printf("%d\n", setjmp(buf));
+ if (argc-- == 1131) longjmp(buf, 11);
+ return 0;
+ }
+ '''
+ for num in [Settings.MAX_SETJMPS, Settings.MAX_SETJMPS+1]:
+ print num
+ self.do_run(src.replace('NUM', str(num)), '0\n' * num if num <= Settings.MAX_SETJMPS or not Settings.ASM_JS else 'build with a higher value for MAX_SETJMPS')
+
def test_exceptions(self):
if Settings.QUANTUM_SIZE == 1: return self.skip("we don't support libcxx in q1")
if self.emcc_args is None: return self.skip('need emcc to add in libcxx properly')
@@ -8035,7 +8174,7 @@ def process(filename):
Settings.DEAD_FUNCTIONS = []
# Run the same code with argc that uses the dead function, see abort
- test(('abort', 'is not a function'), args=['a', 'b'], no_build=True)
+ test(('dead:_unused' if Settings.ASSERTIONS else 'abort', 'is not a function'), args=['a', 'b'], no_build=True)
# Normal stuff
run_all('normal', r'''