aboutsummaryrefslogtreecommitdiff
path: root/tests/test_core.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_core.py')
-rw-r--r--tests/test_core.py781
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