diff options
author | Alon Zakai <alonzakai@gmail.com> | 2013-09-06 18:34:38 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2013-09-06 18:34:38 -0700 |
commit | 38890204ed1f5f8dd34cced7c42fc9cf42dccab5 (patch) | |
tree | 0b6d76adc047a0c81c9e0caf0dbbae93c5461948 /tests/test_core.py | |
parent | b5b49215d4a40566380a769f47a9c1cce74a28b0 (diff) | |
parent | fce749a7066e51d57967889fab0600c285885b4b (diff) |
Merge branch 'incoming'
Diffstat (limited to 'tests/test_core.py')
-rw-r--r-- | tests/test_core.py | 781 |
1 files changed, 475 insertions, 306 deletions
diff --git a/tests/test_core.py b/tests/test_core.py index 6d15da1e..5d4f35e8 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -3742,7 +3742,8 @@ def process(filename): self.do_run(open(path_from_root('tests', 'emscripten_get_now.cpp')).read(), 'Timer resolution is good.') def test_inlinejs(self): - if Settings.ASM_JS: return self.skip('asm does not support random code, TODO: something that works in asm') + if Settings.ASM_JS: Settings.ASM_JS = 2 # skip validation, asm does not support random code + if not self.is_le32(): return self.skip('le32 needed for inline js') src = r''' #include <stdio.h> @@ -3762,7 +3763,8 @@ def process(filename): self.do_run(src, 'Inline JS is very cool\n3.64\n') def test_inlinejs2(self): - if Settings.ASM_JS: return self.skip('asm does not support random code, TODO: something that works in asm') + if Settings.ASM_JS: Settings.ASM_JS = 2 # skip validation, asm does not support random code + if not self.is_le32(): return self.skip('le32 needed for inline js') src = r''' #include <stdio.h> @@ -3773,8 +3775,8 @@ def process(filename): } void mult() { - asm("var $_$1 = Math.abs(-100); $_$1 *= 2;"); // multiline - asm __volatile__("Module.print($_$1); Module.print('\n')"); + asm("var $_$1 = Math.abs(-100); $_$1 *= 2; Module.print($_$1)"); // multiline + asm __volatile__("Module.print('done')"); } int main(int argc, char **argv) { @@ -3784,7 +3786,7 @@ def process(filename): } ''' - self.do_run(src, '4\n200\n') + self.do_run(src, '4\n200\ndone\n') def test_inlinejs3(self): if Settings.ASM_JS: return self.skip('asm does not support random code, TODO: something that works in asm') @@ -5580,11 +5582,53 @@ The current type of b is: 9 Settings.RUNTIME_LINKED_LIBS = ['liblib.so']; self.do_run(main, 'supp: 54,2\nmain: 56\nsupp see: 543\nmain see: 76\nok.') - def test_dlfcn_basic(self): - if Settings.ASM_JS: return self.skip('TODO: dlopen in asm') + def can_dlfcn(self): + if self.emcc_args and '--memory-init-file' in self.emcc_args: + for i in range(len(self.emcc_args)): + if self.emcc_args[i] == '--memory-init-file': + self.emcc_args = self.emcc_args[:i] + self.emcc_args[i+2:] + break - Settings.NAMED_GLOBALS = 1 + if Settings.ASM_JS: + Settings.DLOPEN_SUPPORT = 1 + else: + Settings.NAMED_GLOBALS = 1 + + if not self.is_le32(): + self.skip('need le32 for dlfcn support') + return False + else: + return True + + def prep_dlfcn_lib(self): + if Settings.ASM_JS: + Settings.MAIN_MODULE = 0 + Settings.SIDE_MODULE = 1 + else: + Settings.BUILD_AS_SHARED_LIB = 1 + Settings.INCLUDE_FULL_LIBRARY = 0 + + def prep_dlfcn_main(self): + if Settings.ASM_JS: + Settings.MAIN_MODULE = 1 + Settings.SIDE_MODULE = 0 + else: + Settings.BUILD_AS_SHARED_LIB = 0 + Settings.INCLUDE_FULL_LIBRARY = 1 + + dlfcn_post_build = ''' +def process(filename): + src = open(filename, 'r').read().replace( + '// {{PRE_RUN_ADDITIONS}}', + "FS.createLazyFile('/', 'liblib.so', 'liblib.so', true, false);" + ) + open(filename, 'w').write(src) +''' + + def test_dlfcn_basic(self): + if not self.can_dlfcn(): return + self.prep_dlfcn_lib() lib_src = ''' #include <cstdio> @@ -5599,10 +5643,10 @@ The current type of b is: 9 ''' dirname = self.get_dir() filename = os.path.join(dirname, 'liblib.cpp') - Settings.BUILD_AS_SHARED_LIB = 1 self.build(lib_src, dirname, filename) shutil.move(filename + '.o.js', os.path.join(dirname, 'liblib.so')) + self.prep_dlfcn_main() src = ''' #include <cstdio> #include <dlfcn.h> @@ -5621,28 +5665,17 @@ The current type of b is: 9 return 0; } ''' - Settings.BUILD_AS_SHARED_LIB = 0 - add_pre_run_and_checks = ''' -def process(filename): - src = open(filename, 'r').read().replace( - '// {{PRE_RUN_ADDITIONS}}', - "FS.createLazyFile('/', 'liblib.so', 'liblib.so', true, false);" - ) - open(filename, 'w').write(src) -''' self.do_run(src, 'Constructing main object.\nConstructing lib object.\n', - post_build=add_pre_run_and_checks) + post_build=self.dlfcn_post_build) def test_dlfcn_qsort(self): - if self.emcc_args is None: return self.skip('requires emcc') - if Settings.ASM_JS: return self.skip('TODO: dlopen in asm') - - Settings.LINKABLE = 1 - Settings.NAMED_GLOBALS = 1 + if not self.can_dlfcn(): return if Settings.USE_TYPED_ARRAYS == 2: Settings.CORRECT_SIGNS = 1 # Needed for unsafe optimizations + self.prep_dlfcn_lib() + Settings.EXPORTED_FUNCTIONS = ['_get_cmp'] lib_src = ''' int lib_cmp(const void* left, const void* right) { const int* a = (const int*) left; @@ -5660,11 +5693,11 @@ def process(filename): ''' dirname = self.get_dir() filename = os.path.join(dirname, 'liblib.cpp') - 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')) + self.prep_dlfcn_main() + Settings.EXPORTED_FUNCTIONS = ['_main', '_malloc'] src = ''' #include <stdio.h> #include <stdlib.h> @@ -5686,6 +5719,13 @@ def process(filename): CMP_TYPE lib_cmp_ptr; int arr[5] = {4, 2, 5, 1, 3}; + qsort((void*)arr, 5, sizeof(int), main_cmp); + printf("Sort with main comparison: "); + for (int i = 0; i < 5; i++) { + printf("%d ", arr[i]); + } + printf("\\n"); + lib_handle = dlopen("liblib.so", RTLD_NOW); if (lib_handle == NULL) { printf("Could not load lib.\\n"); @@ -5697,14 +5737,6 @@ def process(filename): return 1; } lib_cmp_ptr = getter_ptr(); - - qsort((void*)arr, 5, sizeof(int), main_cmp); - printf("Sort with main comparison: "); - for (int i = 0; i < 5; i++) { - printf("%d ", arr[i]); - } - printf("\\n"); - qsort((void*)arr, 5, sizeof(int), lib_cmp_ptr); printf("Sort with lib comparison: "); for (int i = 0; i < 5; i++) { @@ -5715,27 +5747,22 @@ def process(filename): return 0; } ''' - Settings.BUILD_AS_SHARED_LIB = 0 - Settings.EXPORTED_FUNCTIONS = ['_main'] - add_pre_run_and_checks = ''' -def process(filename): - src = open(filename, 'r').read().replace( - '// {{PRE_RUN_ADDITIONS}}', - "FS.createLazyFile('/', 'liblib.so', 'liblib.so', true, false);" - ) - open(filename, 'w').write(src) -''' self.do_run(src, 'Sort with main comparison: 5 4 3 2 1 *Sort with lib comparison: 1 2 3 4 5 *', output_nicerizer=lambda x, err: x.replace('\n', '*'), - post_build=add_pre_run_and_checks) + post_build=self.dlfcn_post_build) + + if Settings.ASM_JS and os.path.exists(SPIDERMONKEY_ENGINE[0]): + out = run_js('liblib.so', engine=SPIDERMONKEY_ENGINE, full_output=True, stderr=STDOUT) + if 'asm' in out: + self.validate_asmjs(out) def test_dlfcn_data_and_fptr(self): - if Settings.ASM_JS: return self.skip('TODO: dlopen in asm') - if Building.LLVM_OPTS: return self.skip('LLVM opts will optimize out parent_func') + if Settings.ASM_JS: return self.skip('this is not a valid case - libraries should not be able to access their parents globals willy nilly') + if not self.can_dlfcn(): return - Settings.LINKABLE = 1 - Settings.NAMED_GLOBALS = 1 + if Building.LLVM_OPTS: return self.skip('LLVM opts will optimize out parent_func') + self.prep_dlfcn_lib() lib_src = ''' #include <stdio.h> @@ -5760,21 +5787,23 @@ def process(filename): ''' dirname = self.get_dir() filename = os.path.join(dirname, 'liblib.cpp') - 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')) + self.prep_dlfcn_main() + Settings.LINKABLE = 1 src = ''' #include <stdio.h> #include <dlfcn.h> + #include <emscripten.h> typedef void (*FUNCTYPE(int, void(*)()))(); FUNCTYPE func; - void parent_func() { + void EMSCRIPTEN_KEEPALIVE parent_func() { printf("parent_func called from child\\n"); } @@ -5818,23 +5847,14 @@ def process(filename): return 0; } ''' - Settings.BUILD_AS_SHARED_LIB = 0 Settings.EXPORTED_FUNCTIONS = ['_main'] Settings.EXPORTED_GLOBALS = [] - add_pre_run_and_checks = ''' -def process(filename): - src = open(filename, 'r').read().replace( - '// {{PRE_RUN_ADDITIONS}}', - "FS.createLazyFile('/', 'liblib.so', 'liblib.so', true, false);" - ) - open(filename, 'w').write(src) -''' self.do_run(src, 'In func: 13*First calling main_fptr from lib.*Second calling lib_fptr from main.*parent_func called from child*parent_func called from child*Var: 42*', output_nicerizer=lambda x, err: x.replace('\n', '*'), - post_build=add_pre_run_and_checks) + post_build=self.dlfcn_post_build) def test_dlfcn_alias(self): - if Settings.ASM_JS: return self.skip('TODO: dlopen in asm') + if Settings.ASM_JS: return self.skip('this is not a valid case - libraries should not be able to access their parents globals willy nilly') Settings.LINKABLE = 1 Settings.NAMED_GLOBALS = 1 @@ -5876,29 +5896,23 @@ def process(filename): Settings.BUILD_AS_SHARED_LIB = 0 Settings.INCLUDE_FULL_LIBRARY = 1 Settings.EXPORTED_FUNCTIONS = ['_main'] - add_pre_run_and_checks = ''' -def process(filename): - src = open(filename, 'r').read().replace( - '// {{PRE_RUN_ADDITIONS}}', - "FS.createLazyFile('/', 'liblib.so', 'liblib.so', true, false);" - ) - open(filename, 'w').write(src) -''' self.do_run(src, 'Parent global: 123.*Parent global: 456.*', output_nicerizer=lambda x, err: x.replace('\n', '*'), - post_build=add_pre_run_and_checks, + post_build=self.dlfcn_post_build, extra_emscripten_args=['-H', 'libc/fcntl.h,libc/sys/unistd.h,poll.h,libc/math.h,libc/time.h,libc/langinfo.h']) Settings.INCLUDE_FULL_LIBRARY = 0 def test_dlfcn_varargs(self): - if Settings.ASM_JS: return self.skip('TODO: dlopen in asm') + if Settings.ASM_JS: return self.skip('this is not a valid case - libraries should not be able to access their parents globals willy nilly') + + if not self.can_dlfcn(): return Settings.LINKABLE = 1 - Settings.NAMED_GLOBALS = 1 if Building.LLVM_OPTS == 2: return self.skip('LLVM LTO will optimize things that prevent shared objects from working') if Settings.QUANTUM_SIZE == 1: return self.skip('FIXME: Add support for this') + self.prep_dlfcn_lib() lib_src = r''' void print_ints(int n, ...); extern "C" void func() { @@ -5907,15 +5921,16 @@ def process(filename): ''' dirname = self.get_dir() filename = os.path.join(dirname, 'liblib.cpp') - 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')) + self.prep_dlfcn_main() src = r''' #include <stdarg.h> #include <stdio.h> #include <dlfcn.h> + #include <assert.h> void print_ints(int n, ...) { va_list args; @@ -5933,24 +5948,16 @@ def process(filename): print_ints(2, 100, 200); lib_handle = dlopen("liblib.so", RTLD_NOW); + assert(lib_handle); fptr = (void (*)())dlsym(lib_handle, "func"); fptr(); return 0; } ''' - Settings.BUILD_AS_SHARED_LIB = 0 Settings.EXPORTED_FUNCTIONS = ['_main'] - add_pre_run_and_checks = ''' -def process(filename): - src = open(filename, 'r').read().replace( - '// {{PRE_RUN_ADDITIONS}}', - "FS.createLazyFile('/', 'liblib.so', 'liblib.so', true, false);" - ) - open(filename, 'w').write(src) -''' self.do_run(src, '100\n200\n13\n42\n', - post_build=add_pre_run_and_checks) + post_build=self.dlfcn_post_build) def test_dlfcn_self(self): if Settings.USE_TYPED_ARRAYS == 1: return self.skip('Does not work with USE_TYPED_ARRAYS=1') @@ -5959,14 +5966,15 @@ def process(filename): src = r''' #include <stdio.h> #include <dlfcn.h> +#include <emscripten.h> -int global = 123; +int EMSCRIPTEN_KEEPALIVE global = 123; -extern "C" __attribute__((noinline)) void foo(int x) { +extern "C" EMSCRIPTEN_KEEPALIVE void foo(int x) { printf("%d\n", x); } -extern "C" __attribute__((noinline)) void repeatable() { +extern "C" EMSCRIPTEN_KEEPALIVE void repeatable() { void* self = dlopen(NULL, RTLD_LAZY); int* global_ptr = (int*)dlsym(self, "global"); void (*foo_ptr)(int) = (void (*)(int))dlsym(self, "foo"); @@ -5987,15 +5995,372 @@ return 0; break else: raise Exception('Could not find symbol table!') - import json - table = json.loads(table[table.find('{'):table.rfind('}')+1]) - actual = list(sorted(table.keys())) + table = table[table.find('{'):table.rfind('}')+1] # ensure there aren't too many globals; we don't want unnamed_addr - assert actual == ['_foo', '_global', '_main', '_repeatable'], \ - "Symbol table does not match: %s" % actual - + assert table.count(',') <= 4 self.do_run(src, '123\n123', post_build=(None, post)) + + def test_dlfcn_unique_sig(self): + if not self.can_dlfcn(): return + + self.prep_dlfcn_lib() + lib_src = ''' + #include <stdio.h> + + int myfunc(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, int m) { + return 13; + } + ''' + Settings.EXPORTED_FUNCTIONS = ['_myfunc'] + dirname = self.get_dir() + filename = os.path.join(dirname, 'liblib.c') + self.build(lib_src, dirname, filename) + shutil.move(filename + '.o.js', os.path.join(dirname, 'liblib.so')) + + self.prep_dlfcn_main() + src = ''' + #include <assert.h> + #include <stdio.h> + #include <dlfcn.h> + + typedef int (*FUNCTYPE)(int, int, int, int, int, int, int, int, int, int, int, int, int); + + int main() { + void *lib_handle; + FUNCTYPE func_ptr; + + lib_handle = dlopen("liblib.so", RTLD_NOW); + assert(lib_handle != NULL); + + func_ptr = (FUNCTYPE)dlsym(lib_handle, "myfunc"); + assert(func_ptr != NULL); + assert(func_ptr(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) == 13); + + puts("success"); + + return 0; + } + ''' + Settings.EXPORTED_FUNCTIONS = ['_main', '_malloc'] + self.do_run(src, 'success', force_c=True, post_build=self.dlfcn_post_build) + + def test_dlfcn_stacks(self): + if not self.can_dlfcn(): return + + self.prep_dlfcn_lib() + lib_src = ''' + #include <assert.h> + #include <stdio.h> + #include <string.h> + + int myfunc(const char *input) { + char bigstack[1024] = { 0 }; + + // make sure we didn't just trample the stack! + assert(!strcmp(input, "foobar")); + + snprintf(bigstack, sizeof(bigstack), input); + return strlen(bigstack); + } + ''' + Settings.EXPORTED_FUNCTIONS = ['_myfunc'] + dirname = self.get_dir() + filename = os.path.join(dirname, 'liblib.c') + self.build(lib_src, dirname, filename) + shutil.move(filename + '.o.js', os.path.join(dirname, 'liblib.so')) + + self.prep_dlfcn_main() + src = ''' + #include <assert.h> + #include <stdio.h> + #include <dlfcn.h> + + typedef int (*FUNCTYPE)(const char *); + + int main() { + void *lib_handle; + FUNCTYPE func_ptr; + char str[128]; + + snprintf(str, sizeof(str), "foobar"); + + lib_handle = dlopen("liblib.so", RTLD_NOW); + assert(lib_handle != NULL); + + func_ptr = (FUNCTYPE)dlsym(lib_handle, "myfunc"); + assert(func_ptr != NULL); + assert(func_ptr(str) == 6); + + puts("success"); + + return 0; + } + ''' + Settings.EXPORTED_FUNCTIONS = ['_main', '_malloc'] + self.do_run(src, 'success', force_c=True, post_build=self.dlfcn_post_build) + + def test_dlfcn_funcs(self): + if not self.can_dlfcn(): return + + self.prep_dlfcn_lib() + lib_src = r''' + #include <assert.h> + #include <stdio.h> + #include <string.h> + + typedef void (*voidfunc)(); + typedef void (*intfunc)(int); + + void callvoid(voidfunc f) { f(); } + void callint(voidfunc f, int x) { f(x); } + + void void_0() { printf("void 0\n"); } + void void_1() { printf("void 1\n"); } + voidfunc getvoid(int i) { + switch(i) { + case 0: return void_0; + case 1: return void_1; + default: return NULL; + } + } + + void int_0(int x) { printf("int 0 %d\n", x); } + void int_1(int x) { printf("int 1 %d\n", x); } + intfunc getint(int i) { + switch(i) { + case 0: return int_0; + case 1: return int_1; + default: return NULL; + } + } + ''' + Settings.EXPORTED_FUNCTIONS = ['_callvoid', '_callint', '_getvoid', '_getint'] + dirname = self.get_dir() + filename = os.path.join(dirname, 'liblib.c') + self.build(lib_src, dirname, filename) + shutil.move(filename + '.o.js', os.path.join(dirname, 'liblib.so')) + + self.prep_dlfcn_main() + src = r''' + #include <assert.h> + #include <stdio.h> + #include <dlfcn.h> + + typedef void (*voidfunc)(); + typedef void (*intfunc)(int); + + typedef void (*voidcaller)(voidfunc); + typedef void (*intcaller)(intfunc, int); + + typedef voidfunc (*voidgetter)(int); + typedef intfunc (*intgetter)(int); + + void void_main() { printf("main.\n"); } + void int_main(int x) { printf("main %d\n", x); } + + int main() { + printf("go\n"); + void *lib_handle; + lib_handle = dlopen("liblib.so", RTLD_NOW); + assert(lib_handle != NULL); + + voidcaller callvoid = (voidcaller)dlsym(lib_handle, "callvoid"); + assert(callvoid != NULL); + callvoid(void_main); + + intcaller callint = (intcaller)dlsym(lib_handle, "callint"); + assert(callint != NULL); + callint(int_main, 201); + + voidgetter getvoid = (voidgetter)dlsym(lib_handle, "getvoid"); + assert(getvoid != NULL); + callvoid(getvoid(0)); + callvoid(getvoid(1)); + + intgetter getint = (intgetter)dlsym(lib_handle, "getint"); + assert(getint != NULL); + callint(getint(0), 54); + callint(getint(1), 9000); + + assert(getint(1000) == NULL); + + puts("ok"); + return 0; + } + ''' + Settings.EXPORTED_FUNCTIONS = ['_main', '_malloc'] + self.do_run(src, '''go +main. +main 201 +void 0 +void 1 +int 0 54 +int 1 9000 +ok +''', force_c=True, post_build=self.dlfcn_post_build) + + def test_dlfcn_mallocs(self): + if not Settings.ASM_JS: return self.skip('needs asm') + + if not self.can_dlfcn(): return + + Settings.TOTAL_MEMORY = 64*1024*1024 # will be exhausted without functional malloc/free + + self.prep_dlfcn_lib() + lib_src = r''' + #include <assert.h> + #include <stdio.h> + #include <string.h> + #include <stdlib.h> + + void *mallocproxy(int n) { return malloc(n); } + void freeproxy(void *p) { free(p); } + ''' + Settings.EXPORTED_FUNCTIONS = ['_mallocproxy', '_freeproxy'] + dirname = self.get_dir() + filename = os.path.join(dirname, 'liblib.c') + self.build(lib_src, dirname, filename) + shutil.move(filename + '.o.js', os.path.join(dirname, 'liblib.so')) + + self.prep_dlfcn_main() + src = open(path_from_root('tests', 'dlmalloc_proxy.c')).read() + Settings.EXPORTED_FUNCTIONS = ['_main', '_malloc', '_free'] + self.do_run(src, '''*294,153*''', force_c=True, post_build=self.dlfcn_post_build) + + def test_dlfcn_longjmp(self): + if not self.can_dlfcn(): return + + self.prep_dlfcn_lib() + lib_src = r''' + #include <setjmp.h> + + void jumpy(jmp_buf buf) { + static int i = 0; + i++; + if (i == 10) longjmp(buf, i); + printf("pre %d\n", i); + } + ''' + Settings.EXPORTED_FUNCTIONS = ['_jumpy'] + dirname = self.get_dir() + filename = os.path.join(dirname, 'liblib.c') + self.build(lib_src, dirname, filename) + shutil.move(filename + '.o.js', os.path.join(dirname, 'liblib.so')) + + self.prep_dlfcn_main() + src = r''' + #include <assert.h> + #include <stdio.h> + #include <dlfcn.h> + #include <setjmp.h> + + typedef void (*jumpfunc)(jmp_buf); + + int main() { + printf("go!\n"); + + void *lib_handle; + lib_handle = dlopen("liblib.so", RTLD_NOW); + assert(lib_handle != NULL); + + jumpfunc jumpy = (jumpfunc)dlsym(lib_handle, "jumpy"); + assert(jumpy); + + jmp_buf buf; + int jmpval = setjmp(buf); + if (jmpval == 0) { + while (1) jumpy(buf); + } else { + printf("out!\n"); + } + + return 0; + } + ''' + Settings.EXPORTED_FUNCTIONS = ['_main', '_malloc', '_free'] + self.do_run(src, '''go! +pre 1 +pre 2 +pre 3 +pre 4 +pre 5 +pre 6 +pre 7 +pre 8 +pre 9 +out! +''', post_build=self.dlfcn_post_build, force_c=True) + + def zzztest_dlfcn_exceptions(self): # TODO: make this work. need to forward tempRet0 across modules + if not self.can_dlfcn(): return + + Settings.DISABLE_EXCEPTION_CATCHING = 0 + + self.prep_dlfcn_lib() + lib_src = r''' + extern "C" { + int ok() { + return 65; + } + int fail() { + throw 123; + } + } + ''' + Settings.EXPORTED_FUNCTIONS = ['_ok', '_fail'] + dirname = self.get_dir() + filename = os.path.join(dirname, 'liblib.cpp') + self.build(lib_src, dirname, filename) + shutil.move(filename + '.o.js', os.path.join(dirname, 'liblib.so')) + + self.prep_dlfcn_main() + src = r''' + #include <assert.h> + #include <stdio.h> + #include <dlfcn.h> + + typedef int (*intfunc)(); + + int main() { + printf("go!\n"); + + void *lib_handle; + lib_handle = dlopen("liblib.so", RTLD_NOW); + assert(lib_handle != NULL); + + intfunc okk = (intfunc)dlsym(lib_handle, "ok"); + intfunc faill = (intfunc)dlsym(lib_handle, "fail"); + assert(okk && faill); + + try { + printf("ok: %d\n", okk()); + } catch(...) { + printf("wha\n"); + } + + try { + printf("fail: %d\n", faill()); + } catch(int x) { + printf("int %d\n", x); + } + + try { + printf("fail: %d\n", faill()); + } catch(double x) { + printf("caught %f\n", x); + } + + return 0; + } + ''' + Settings.EXPORTED_FUNCTIONS = ['_main', '_malloc', '_free'] + self.do_run(src, '''go! +ok: 65 +int 123 +ok +''', post_build=self.dlfcn_post_build) + def test_rand(self): return self.skip('rand() is now random') # FIXME @@ -6992,7 +7357,7 @@ def process(filename): FS.registerDevice(dummy_device, {}); FS.createDataFile('/', 'file', 'abcdef', true, true); - FS.mkdev('/device', 0666, dummy_device); + FS.mkdev('/device', dummy_device); \'\'\' ) open(filename, 'w').write(src) @@ -7250,32 +7615,18 @@ def process(filename): Settings.INCLUDE_FULL_LIBRARY = 0 def test_unistd_access(self): - add_pre_run = ''' -def process(filename): - import tools.shared as shared - src = open(filename, 'r').read().replace( - '// {{PRE_RUN_ADDITIONS}}', - open(shared.path_from_root('tests', 'unistd', 'access.js'), 'r').read() - ) - open(filename, 'w').write(src) -''' + if Settings.ASM_JS: Settings.ASM_JS = 2 # skip validation, asm does not support random code + if not self.is_le32(): return self.skip('le32 needed for inline js') src = open(path_from_root('tests', 'unistd', 'access.c'), 'r').read() expected = open(path_from_root('tests', 'unistd', 'access.out'), 'r').read() - self.do_run(src, expected, post_build=add_pre_run) + self.do_run(src, expected) def test_unistd_curdir(self): - add_pre_run = ''' -def process(filename): - import tools.shared as shared - src = open(filename, 'r').read().replace( - '// {{PRE_RUN_ADDITIONS}}', - open(shared.path_from_root('tests', 'unistd', 'curdir.js'), 'r').read() - ) - open(filename, 'w').write(src) -''' + if Settings.ASM_JS: Settings.ASM_JS = 2 # skip validation, asm does not support random code + if not self.is_le32(): return self.skip('le32 needed for inline js') src = open(path_from_root('tests', 'unistd', 'curdir.c'), 'r').read() expected = open(path_from_root('tests', 'unistd', 'curdir.out'), 'r').read() - self.do_run(src, expected, post_build=add_pre_run) + self.do_run(src, expected) def test_unistd_close(self): src = open(path_from_root('tests', 'unistd', 'close.c'), 'r').read() @@ -7302,18 +7653,11 @@ def process(filename): self.do_run(src, expected) def test_unistd_truncate(self): - add_pre_run = ''' -def process(filename): - import tools.shared as shared - src = open(filename, 'r').read().replace( - '// {{PRE_RUN_ADDITIONS}}', - open(shared.path_from_root('tests', 'unistd', 'truncate.js'), 'r').read() - ) - open(filename, 'w').write(src) -''' + if Settings.ASM_JS: Settings.ASM_JS = 2 # skip validation, asm does not support random code + if not self.is_le32(): return self.skip('le32 needed for inline js') src = open(path_from_root('tests', 'unistd', 'truncate.c'), 'r').read() expected = open(path_from_root('tests', 'unistd', 'truncate.out'), 'r').read() - self.do_run(src, expected, post_build=add_pre_run) + self.do_run(src, expected) def test_unistd_swab(self): src = open(path_from_root('tests', 'unistd', 'swab.c'), 'r').read() @@ -7339,18 +7683,11 @@ def process(filename): self.do_run(src, 'success', force_c=True) def test_unistd_links(self): - add_pre_run = ''' -def process(filename): - import tools.shared as shared - src = open(filename, 'r').read().replace( - '// {{PRE_RUN_ADDITIONS}}', - open(shared.path_from_root('tests', 'unistd', 'links.js'), 'r').read() - ) - open(filename, 'w').write(src) -''' + if Settings.ASM_JS: Settings.ASM_JS = 2 # skip validation, asm does not support random code + if not self.is_le32(): return self.skip('le32 needed for inline js') src = open(path_from_root('tests', 'unistd', 'links.c'), 'r').read() expected = open(path_from_root('tests', 'unistd', 'links.out'), 'r').read() - self.do_run(src, expected, post_build=add_pre_run) + self.do_run(src, expected) def test_unistd_sleep(self): src = open(path_from_root('tests', 'unistd', 'sleep.c'), 'r').read() @@ -7358,18 +7695,12 @@ def process(filename): self.do_run(src, expected) def test_unistd_io(self): - add_pre_run = ''' -def process(filename): - import tools.shared as shared - src = open(filename, 'r').read().replace( - '// {{PRE_RUN_ADDITIONS}}', - open(shared.path_from_root('tests', 'unistd', 'io.js'), 'r').read() - ) - open(filename, 'w').write(src) -''' + if Settings.ASM_JS: Settings.ASM_JS = 2 # skip validation, asm does not support random code + if not self.is_le32(): return self.skip('le32 needed for inline js') + if self.run_name == 'o2': return self.skip('non-asm optimized builds can fail with inline js') src = open(path_from_root('tests', 'unistd', 'io.c'), 'r').read() expected = open(path_from_root('tests', 'unistd', 'io.out'), 'r').read() - self.do_run(src, expected, post_build=add_pre_run) + self.do_run(src, expected) def test_unistd_misc(self): src = open(path_from_root('tests', 'unistd', 'misc.c'), 'r').read() @@ -7439,168 +7770,6 @@ def process(filename): ''' self.do_run(src, re.sub('(^|\n)\s+', '\\1', expected)) - def test_inet(self): - src = r''' - #include <stdio.h> - #include <arpa/inet.h> - - int main() { - printf("*%x,%x,%x,%x,%x,%x*\n", htonl(0xa1b2c3d4), htonl(0xfe3572e0), htonl(0x07abcdf0), htons(0xabcd), ntohl(0x43211234), ntohs(0xbeaf)); - in_addr_t i = inet_addr("190.180.10.78"); - printf("%x\n", i); - return 0; - } - ''' - self.do_run(src, '*d4c3b2a1,e07235fe,f0cdab07,cdab,34122143,afbe*\n4e0ab4be\n') - - def test_inet2(self): - src = r''' - #include <stdio.h> - #include <arpa/inet.h> - - int main() { - struct in_addr x, x2; - int *y = (int*)&x; - *y = 0x12345678; - printf("%s\n", inet_ntoa(x)); - int r = inet_aton(inet_ntoa(x), &x2); - printf("%s\n", inet_ntoa(x2)); - return 0; - } - ''' - self.do_run(src, '120.86.52.18\n120.86.52.18\n') - - def test_inet3(self): - src = r''' - #include <stdio.h> - #include <arpa/inet.h> - #include <sys/socket.h> - int main() { - char dst[64]; - struct in_addr x, x2; - int *y = (int*)&x; - *y = 0x12345678; - printf("%s\n", inet_ntop(AF_INET,&x,dst,sizeof dst)); - int r = inet_aton(inet_ntoa(x), &x2); - printf("%s\n", inet_ntop(AF_INET,&x2,dst,sizeof dst)); - return 0; - } - ''' - self.do_run(src, '120.86.52.18\n120.86.52.18\n') - - def test_inet4(self): - if Settings.USE_TYPED_ARRAYS != 2: return self.skip('requires ta2') - - src = r''' - #include <stdio.h> - #include <arpa/inet.h> - #include <sys/socket.h> - - void test(char *test_addr){ - char str[40]; - struct in6_addr addr; - unsigned char *p = (unsigned char*)&addr; - int ret; - ret = inet_pton(AF_INET6,test_addr,&addr); - if(ret == -1) return; - if(ret == 0) return; - if(inet_ntop(AF_INET6,&addr,str,sizeof(str)) == NULL ) return; - printf("%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x - %s\n", - p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7],p[8],p[9],p[10],p[11],p[12],p[13],p[14],p[15],str); - } - int main(){ - test("::"); - test("::1"); - test("::1.2.3.4"); - test("::17.18.19.20"); - test("::ffff:1.2.3.4"); - test("1::ffff"); - test("::255.255.255.255"); - test("0:ff00:1::"); - test("0:ff::"); - test("abcd::"); - test("ffff::a"); - test("ffff::a:b"); - test("ffff::a:b:c"); - test("ffff::a:b:c:d"); - test("ffff::a:b:c:d:e"); - test("::1:2:0:0:0"); - test("0:0:1:2:3::"); - test("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); - test("1::255.255.255.255"); - - //below should fail and not produce results.. - test("1.2.3.4"); - test(""); - test("-"); - } - ''' - self.do_run(src, - "0000:0000:0000:0000:0000:0000:0000:0000 - ::\n" - "0000:0000:0000:0000:0000:0000:0000:0001 - ::1\n" - "0000:0000:0000:0000:0000:0000:0102:0304 - ::1.2.3.4\n" - "0000:0000:0000:0000:0000:0000:1112:1314 - ::17.18.19.20\n" - "0000:0000:0000:0000:0000:ffff:0102:0304 - ::ffff:1.2.3.4\n" - "0001:0000:0000:0000:0000:0000:0000:ffff - 1::ffff\n" - "0000:0000:0000:0000:0000:0000:ffff:ffff - ::255.255.255.255\n" - "0000:ff00:0001:0000:0000:0000:0000:0000 - 0:ff00:1::\n" - "0000:00ff:0000:0000:0000:0000:0000:0000 - 0:ff::\n" - "abcd:0000:0000:0000:0000:0000:0000:0000 - abcd::\n" - "ffff:0000:0000:0000:0000:0000:0000:000a - ffff::a\n" - "ffff:0000:0000:0000:0000:0000:000a:000b - ffff::a:b\n" - "ffff:0000:0000:0000:0000:000a:000b:000c - ffff::a:b:c\n" - "ffff:0000:0000:0000:000a:000b:000c:000d - ffff::a:b:c:d\n" - "ffff:0000:0000:000a:000b:000c:000d:000e - ffff::a:b:c:d:e\n" - "0000:0000:0000:0001:0002:0000:0000:0000 - ::1:2:0:0:0\n" - "0000:0000:0001:0002:0003:0000:0000:0000 - 0:0:1:2:3::\n" - "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff - ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff\n" - "0001:0000:0000:0000:0000:0000:ffff:ffff - 1::ffff:ffff\n" - ) - - def test_gethostbyname(self): - if Settings.USE_TYPED_ARRAYS != 2: return self.skip("assume t2 in gethostbyname") - - src = r''' - #include <netdb.h> - #include <stdio.h> - - void test(char *hostname) { - hostent *host = gethostbyname(hostname); - if (!host) { - printf("no such thing\n"); - return; - } - printf("%s : %d : %d\n", host->h_name, host->h_addrtype, host->h_length); - char **name = host->h_aliases; - while (*name) { - printf("- %s\n", *name); - name++; - } - name = host->h_addr_list; - while (name && *name) { - printf("* "); - for (int i = 0; i < host->h_length; i++) - printf("%d.", (*name)[i]); - printf("\n"); - name++; - } - } - - int main() { - test("www.cheezburger.com"); - test("fail.on.this.never.work"); // we will "work" on this - because we are just making aliases of names to ips - test("localhost"); - return 0; - } - ''' - self.do_run(src, '''www.cheezburger.com : 2 : 4 -* -84.29.1.0. -fail.on.this.never.work : 2 : 4 -* -84.29.2.0. -localhost : 2 : 4 -* -84.29.3.0. -''') - def test_799(self): src = open(path_from_root('tests', '799.cpp'), 'r').read() self.do_run(src, '''Set PORT family: 0, port: 3979 |