aboutsummaryrefslogtreecommitdiff
path: root/tests/runner.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/runner.py')
-rwxr-xr-xtests/runner.py827
1 files changed, 619 insertions, 208 deletions
diff --git a/tests/runner.py b/tests/runner.py
index 77bcc288..f6a2c8b1 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -72,12 +72,16 @@ except:
# Core test runner class, shared between normal tests and benchmarks
+checked_sanity = False
+
class RunnerCore(unittest.TestCase):
save_dir = os.environ.get('EM_SAVE_DIR')
save_JS = 0
stderr_redirect = STDOUT # This avoids cluttering the test runner output, which is stderr too, with compiler warnings etc.
# Change this to None to get stderr reporting, for debugging purposes
+ env = {}
+
def skipme(self): # used by tests we ask on the commandline to be skipped, see right before call to unittest.main
return self.skip('requested to be skipped')
@@ -238,10 +242,7 @@ process(sys.argv[1])
os.remove(f + '.o')
except:
pass
- compiler_flags = ['-emit-llvm']
- if not f.endswith('.c'):
- compiler_flags = compiler_flags + ['-std=c++03']
- args = [Building.COMPILER] + compiler_flags + COMPILER_OPTS + Building.COMPILER_TEST_OPTS + \
+ args = [PYTHON, EMCC] + Building.COMPILER_TEST_OPTS + \
['-I', dirname, '-I', os.path.join(dirname, 'include')] + \
map(lambda include: '-I' + include, includes) + \
['-c', f, '-o', f + '.o']
@@ -290,7 +291,7 @@ process(sys.argv[1])
out = open(stdout, 'r').read()
err = open(stderr, 'r').read()
if engine == SPIDERMONKEY_ENGINE and Settings.ASM_JS:
- if 'Successfully compiled asm.js code' in err and 'asm.js link error' not in err:
+ if 'uccessfully compiled asm.js code' in err and 'asm.js link error' not in err:
print >> sys.stderr, "[was asm.js'ified]"
elif 'asm.js' in err: # if no asm.js error, then not an odin build
raise Exception("did NOT asm.js'ify")
@@ -358,13 +359,14 @@ process(sys.argv[1])
build_dir = self.get_build_dir()
output_dir = self.get_dir()
- cache_name = name + cache_name_extra
+ cache_name = name + cache_name_extra + (self.env.get('EMCC_LLVM_TARGET') or '')
+
if self.library_cache is not None:
if cache and self.library_cache.get(cache_name):
print >> sys.stderr, '<load %s from cache> ' % cache_name,
generated_libs = []
for basename, contents in self.library_cache[cache_name]:
- bc_file = os.path.join(build_dir, basename)
+ bc_file = os.path.join(build_dir, cache_name + '_' + basename)
f = open(bc_file, 'wb')
f.write(contents)
f.close()
@@ -411,7 +413,7 @@ process(sys.argv[1])
int suppInt = 76;
'''
- supp_name = os.path.join(self.get_dir(), 'supp.c')
+ supp_name = os.path.join(self.get_dir(), 'supp.cpp')
open(supp_name, 'w').write(supp)
main = r'''
@@ -445,6 +447,8 @@ process(sys.argv[1])
sys.argv = map(lambda arg: arg if not arg.startswith('test_') else 'default.' + arg, sys.argv)
+test_modes = ['default', 'o1', 'o2', 'asm1', 'asm2', 'asm2g', 'asm2x86', 's_0_0', 's_0_1', 's_1_0', 's_1_1']
+
test_index = 0
if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv) and 'browser' not in str(sys.argv):
@@ -452,10 +456,10 @@ if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv) and 'brows
print "Running Emscripten tests..."
- if len(sys.argv) == 2 and 'ALL.' in sys.argv[1]:
+ if len(sys.argv) == 2 and sys.argv[1].startswith('ALL.'):
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, 'asm1.'+test, 'asm2.'+test, 'asm2g.'+test, 's_0_0.'+test, 's_0_1.'+test, 's_1_0.'+test, 's_1_1.'+test]
+ sys.argv = [sys.argv[0]] + map(lambda mode: mode+'.'+test, test_modes)
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.
@@ -506,6 +510,9 @@ if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv) and 'brows
output_nicerizer=output_nicerizer,
post_build=None) # post_build was already done in ll_to_js, this do_run call is just to test the output
+ def is_le32(self):
+ return not ('i386-pc-linux-gnu' in COMPILER_OPTS or self.env.get('EMCC_LLVM_TARGET') == 'i386-pc-linux-gnu')
+
def test_hello_world(self):
src = '''
#include <stdio.h>
@@ -1133,10 +1140,11 @@ m_divisor is 1091269979
if Settings.USE_TYPED_ARRAYS != 2: return self.skip('full i64 stuff only in ta2')
src = r'''
+ #include <stdint.h>
#include <stdio.h>
int main(int argc, char ** argv){
int y=-133;
- __int64_t x= ((__int64_t)((short)(y)))*(100 + argc);
+ int64_t x= ((int64_t)((short)(y)))*(100 + argc);
if(x>0)
printf(">0\n");
else
@@ -1171,6 +1179,53 @@ m_divisor is 1091269979
'''
self.do_run(src, 'Succeeded!')
+ def test_i64_varargs(self):
+ if Settings.USE_TYPED_ARRAYS != 2: return self.skip('full i64 stuff only in ta2')
+
+ src = r'''
+ #include <stdio.h>
+ #include <stdint.h>
+ #include <stdarg.h>
+
+ int64_t ccv_cache_generate_signature(char *msg, int len, int64_t sig_start, ...) {
+ if (sig_start < 10123)
+ printf("%s\n", msg+len);
+ va_list v;
+ va_start(v, sig_start);
+ if (sig_start > 1413)
+ printf("%d\n", va_arg(v, int));
+ else
+ printf("nada\n");
+ va_end(v);
+ return len*sig_start*(msg[0]+1);
+ }
+
+ int main(int argc, char **argv)
+ {
+ for (int i = 0; i < argc; i++) {
+ int64_t x;
+ if (i % 123123 == 0)
+ x = ccv_cache_generate_signature(argv[i], i+2, (int64_t)argc*argc, 54.111);
+ else
+ x = ccv_cache_generate_signature(argv[i], i+2, (int64_t)argc*argc, 13);
+ printf("%lld\n", x);
+ }
+ };
+ '''
+ self.do_run(src, '''in/this.program
+nada
+1536
+a
+nada
+5760
+fl
+nada
+6592
+sdfasdfasdf
+nada
+7840
+''', 'waka fleefl asdfasdfasdfasdf'.split(' '))
+
def test_i32_mul_precise(self):
if self.emcc_args == None: return self.skip('needs ta2')
@@ -1499,7 +1554,11 @@ Succeeded!
'''
# TODO: A version of this with int64s as well
- self.do_run(src, '*12 : 1 : 12\n328157500735811.0,23,416012775903557.0,99\n')
+
+ if self.is_le32():
+ return self.skip('LLVM marks the reads of s as fully aligned, making this test invalid')
+ else:
+ self.do_run(src, '*12 : 1 : 12\n328157500735811.0,23,416012775903557.0,99\n')
return # TODO: continue to the next part here
@@ -1533,6 +1592,62 @@ Succeeded!
except Exception, e:
assert 'must be aligned' in str(e), e # expected to fail without emulation
+ def test_align64(self):
+ src = r'''
+ #include <stdio.h>
+
+ // inspired by poppler
+
+ enum Type {
+ A = 10,
+ B = 20
+ };
+
+ struct Object {
+ Type type;
+ union {
+ int intg;
+ double real;
+ char *name;
+ };
+ };
+
+ struct Principal {
+ double x;
+ Object a;
+ double y;
+ };
+
+ int main(int argc, char **argv)
+ {
+ int base = argc-1;
+ Object *o = NULL;
+ printf("%d,%d\n", sizeof(Object), sizeof(Principal));
+ printf("%d,%d,%d,%d\n", (int)&o[base].type, (int)&o[base].intg, (int)&o[base].real, (int)&o[base].name);
+ printf("%d,%d,%d,%d\n", (int)&o[base+1].type, (int)&o[base+1].intg, (int)&o[base+1].real, (int)&o[base+1].name);
+ Principal p, q;
+ p.x = p.y = q.x = q.y = 0;
+ p.a.type = A;
+ p.a.real = 123.456;
+ *(&q.a) = p.a;
+ printf("%.2f,%d,%.2f,%.2f : %.2f,%d,%.2f,%.2f\n", p.x, p.a.type, p.a.real, p.y, q.x, q.a.type, q.a.real, q.y);
+ return 0;
+ }
+ '''
+
+ if self.is_le32():
+ self.do_run(src, '''16,32
+0,8,8,8
+16,24,24,24
+0.00,10,123.46,0.00 : 0.00,10,123.46,0.00
+''')
+ else:
+ self.do_run(src, '''12,28
+0,4,4,4
+12,16,16,16
+0.00,10,123.46,0.00 : 0.00,10,123.46,0.00
+''')
+
def test_unsigned(self):
Settings.CORRECT_SIGNS = 1 # We test for exactly this sort of thing here
Settings.CHECK_SIGNS = 0
@@ -1753,10 +1868,10 @@ Succeeded!
int main()
{
printf("*%.2f,%.2f,%d", M_PI, -M_PI, (1/0.0) > 1e300); // could end up as infinity, or just a very very big number
- printf(",%d", finite(NAN) != 0);
- printf(",%d", finite(INFINITY) != 0);
- printf(",%d", finite(-INFINITY) != 0);
- printf(",%d", finite(12.3) != 0);
+ printf(",%d", isfinite(NAN) != 0);
+ printf(",%d", isfinite(INFINITY) != 0);
+ printf(",%d", isfinite(-INFINITY) != 0);
+ printf(",%d", isfinite(12.3) != 0);
printf(",%d", isinf(NAN) != 0);
printf(",%d", isinf(INFINITY) != 0);
printf(",%d", isinf(-INFINITY) != 0);
@@ -1985,8 +2100,9 @@ Succeeded!
char *two = "fa la sa ho fi FI FO FUM WHEN WHERE WHY HOW WHO";
char three[1000];
strcpy(three, &one[argc*2]);
- strcat(three, &two[argc*3]);
+ char *four = strcat(three, &two[argc*3]);
printf("cat |%s|\\n", three);
+ printf("returned |%s|\\n", four);
}
return 0;
@@ -1996,7 +2112,8 @@ Succeeded!
print named
Settings.NAMED_GLOBALS = named
self.do_run(src, '''4:10,177,543,def\n4\nwowie\ntoo\n76\n5\n(null)\n/* a comment */\n// another\ntest\nwaka ....e 1 O...wo 2 T................................
-cat |umber one top notchfi FI FO FUM WHEN WHERE WHY HOW WHO|''', ['wowie', 'too', '74'])
+cat |umber one top notchfi FI FO FUM WHEN WHERE WHY HOW WHO|
+returned |umber one top notchfi FI FO FUM WHEN WHERE WHY HOW WHO|''', ['wowie', 'too', '74'])
if self.emcc_args == []:
gen = open(self.in_dir('src.cpp.o.js')).read()
assert ('var __str1;' in gen) == named
@@ -2335,28 +2452,34 @@ cat |umber one top notchfi FI FO FUM WHEN WHERE WHY HOW WHO|''', ['wowie', 'too'
static jmp_buf buf;
void second(void) {
- printf("second\n"); // prints
- longjmp(buf,1); // jumps back to where setjmp was called - making setjmp now return 1
+ printf("second\n");
+ longjmp(buf,-1);
}
void first(void) {
- second();
- printf("first\n"); // does not print
+ printf("first\n"); // prints
+ longjmp(buf,1); // jumps back to where setjmp was called - making setjmp now return 1
}
int main() {
volatile int x = 0;
- if ( ! setjmp(buf) ) {
+ int jmpval = setjmp(buf);
+ if (!jmpval) {
+ x++; // should be properly restored once longjmp jumps back
+ first(); // when executed, setjmp returns 1
+ printf("skipped\n"); // does not print
+ } else if (jmpval == 1) { // when first() jumps back, setjmp returns 1
+ printf("result: %d %d\n", x, jmpval); // prints
x++;
- first(); // when executed, setjmp returns 0
- } else { // when longjmp jumps back, setjmp returns 1
- printf("main: %d\n", x); // prints
+ second(); // when executed, setjmp returns -1
+ } else if (jmpval == -1) { // when second() jumps back, setjmp returns -1
+ printf("result: %d %d\n", x, jmpval); // prints
}
return 0;
}
'''
- self.do_run(src, 'second\nmain: 1\n')
+ self.do_run(src, 'first\nresult: 1 1\nsecond\nresult: 2 -1')
def test_longjmp2(self):
src = r'''
@@ -2630,6 +2753,37 @@ back
12
''')
+ def test_longjmp_exc(self):
+ src = r'''
+ #include <stdlib.h>
+ #include <stdio.h>
+ #include <setjmp.h>
+ #include <emscripten.h>
+
+ jmp_buf abortframe;
+
+ void dostuff(int a) {
+ printf("pre\n");
+ if (a != 42) emscripten_run_script("waka_waka()"); // this should fail, and never reach "never"
+ printf("never\n");
+
+ if (a == 100) {
+ longjmp (abortframe, -1);
+ }
+
+ if (setjmp(abortframe)) {
+ printf("got 100");
+ }
+ }
+
+ int main(int argc, char **argv) {
+ dostuff(argc);
+ exit(1);
+ return 1;
+ }
+ '''
+ self.do_run(src, 'waka_waka');
+
def test_setjmp_many(self):
src = r'''
#include <stdio.h>
@@ -3035,7 +3189,7 @@ Exiting setjmp function, level: 0, prev_jmp: -1
Settings.SAFE_HEAP = 1
- for addr in ['0', '7', 'new D2()']:
+ for addr in ['0', 'new D2()']:
print addr
src = r'''
#include <stdio.h>
@@ -3210,10 +3364,10 @@ Exiting setjmp function, level: 0, prev_jmp: -1
#include <stdio.h>
int
- main(void) {
- float (*fn)(float) = &sqrtf;
- float (*fn2)(float) = &fabsf;
- float (*fn3)(float) = &erff;
+ main(int argc, char **argv) {
+ float (*fn)(float) = argc != 12 ? &sqrtf : &fabsf;
+ float (*fn2)(float) = argc != 13 ? &fabsf : &sqrtf;
+ float (*fn3)(float) = argc != 14 ? &erff : &fabsf;
printf("fn2(-5) = %d, fn(10) = %.2f, erf(10) = %.2f\\n", (int)fn2(-5), fn(10), fn3(10));
return 0;
}
@@ -3240,6 +3394,36 @@ Exiting setjmp function, level: 0, prev_jmp: -1
'''
self.do_run(src, '*0x1*')
+ def test_funcptr_namecollide(self):
+ src = r'''
+ #include <stdio.h>
+
+ void do_call(void (*puts)(const char *), const char *str);
+
+ void do_print(const char *str) {
+ if (!str) do_call(NULL, "delusion");
+ if ((int)str == -1) do_print(str+10);
+ puts("====");
+ puts(str);
+ puts("====");
+ }
+
+ void do_call(void (*puts)(const char *), const char *str) {
+ if (!str) do_print("confusion");
+ if ((int)str == -1) do_call(NULL, str-10);
+ (*puts)(str);
+ }
+
+ int main(int argc, char **argv)
+ {
+ for (int i = 0; i < argc; i++) {
+ do_call(i != 10 ? do_print : NULL, i != 15 ? "waka waka" : NULL);
+ }
+ return 0;
+ }
+ '''
+ self.do_run(src, 'waka', force_c=True)
+
def test_emptyclass(self):
if self.emcc_args is None: return self.skip('requires emcc')
src = '''
@@ -3273,6 +3457,35 @@ Exiting setjmp function, level: 0, prev_jmp: -1
'''
self.do_run(src, 'z:1*', force_c=True)
+ def test_rename(self):
+ src = '''
+ #include <stdio.h>
+ #include <sys/stat.h>
+ #include <sys/types.h>
+ #include <assert.h>
+
+ int main() {
+ int err;
+ FILE* fid;
+
+ err = mkdir("/foo", 0777);
+ err = mkdir("/bar", 0777);
+ fid = fopen("/foo/bar", "w+");
+ fclose(fid);
+
+ err = rename("/foo/bar", "/foo/bar2");
+ printf("%d\\n", err);
+
+ err = rename("/foo", "/foo/foo");
+ printf("%d\\n", err);
+
+ err = rename("/foo", "/bar/foo");
+ printf("%d\\n", err);
+ return 0;
+ }
+ '''
+ self.do_run(src, '0\n-1\n0\n', force_c=True)
+
def test_alloca_stack(self):
if self.emcc_args is None: return # too slow in other modes
@@ -3410,7 +3623,7 @@ Exiting setjmp function, level: 0, prev_jmp: -1
[]
[][][] []
--------------------------------
-''', ['1'], force_c=True)
+''', ['2'], force_c=True)
def test_array2(self):
src = '''
@@ -3618,7 +3831,10 @@ Exiting setjmp function, level: 0, prev_jmp: -1
# Compressed memory. Note that sizeof() does give the fat sizes, however!
self.do_run(src, '*0,0,0,1,2,3,4,5*\n*1,0,0*\n*0*\n0:1,1\n1:1,1\n2:1,1\n*12,20,5*')
else:
- self.do_run(src, '*0,0,0,4,8,12,16,20*\n*1,0,0*\n*0*\n0:1,1\n1:1,1\n2:1,1\n*12,20,20*')
+ if self.is_le32():
+ self.do_run(src, '*0,0,0,4,8,16,20,24*\n*1,0,0*\n*0*\n0:1,1\n1:1,1\n2:1,1\n*16,24,24*')
+ else:
+ self.do_run(src, '*0,0,0,4,8,12,16,20*\n*1,0,0*\n*0*\n0:1,1\n1:1,1\n2:1,1\n*12,20,20*')
def test_ptrtoint(self):
if self.emcc_args is None: return self.skip('requires emcc')
@@ -3985,7 +4201,7 @@ def process(filename):
// Try it with copying
va_list tempva;
- __va_copy(tempva, v);
+ va_copy(tempva, v);
vsnprintf(d, 20, s, tempva);
puts(d);
@@ -4027,7 +4243,7 @@ def process(filename):
int maxxi = getMaxi(6, 2, 5, 21, 4, -10, 19);
printf("maxxi:%d*\\n", maxxi);
- double maxxD = getMaxD(6, (double)2.1, (double)5.1, (double)22.1, (double)4.1, (double)-10.1, (double)19.1);
+ double maxxD = getMaxD(6, (double)2.1, (double)5.1, (double)22.1, (double)4.1, (double)-10.1, (double)19.1, (double)2);
printf("maxxD:%.2f*\\n", (float)maxxD);
// And, as a function pointer
@@ -4041,6 +4257,7 @@ def process(filename):
def test_varargs_byval(self):
if Settings.USE_TYPED_ARRAYS != 2: return self.skip('FIXME: Add support for this')
+ if self.is_le32(): return self.skip('clang cannot compile this code with that target yet')
src = r'''
#include <stdio.h>
@@ -4213,9 +4430,13 @@ The current type of b is: 9
# This will fail! See explanation near the warning we check for, in the compiler source code
output = Popen([PYTHON, EMCC, all_name], stderr=PIPE).communicate()
+
# Check for warning in the generated code
generated = open(os.path.join(self.get_dir(), 'src.cpp.o.js')).read()
- assert 'Casting a function pointer type to another with a different number of arguments' in output[1], 'Missing expected warning'
+ if 'i386-pc-linux-gnu' in COMPILER_OPTS:
+ assert 'Casting a function pointer type to a potentially incompatible one' in output[1], 'Missing expected warning'
+ else:
+ print >> sys.stderr, 'skipping C/C++ conventions warning check, since not i386-pc-linux-gnu'
def test_stdlibs(self):
if self.emcc_args is None: return self.skip('requires emcc')
@@ -4390,10 +4611,10 @@ The current type of b is: 9
self.do_run(src, 'ok\n')
def test_statics(self):
- # static initializers save i16 but load i8 for some reason
+ # static initializers save i16 but load i8 for some reason (or i64 and load i8)
if Settings.SAFE_HEAP:
Settings.SAFE_HEAP = 3
- Settings.SAFE_HEAP_LINES = ['src.cpp:19', 'src.cpp:26']
+ Settings.SAFE_HEAP_LINES = ['src.cpp:19', 'src.cpp:26', 'src.cpp:28']
src = '''
#include <stdio.h>
@@ -4881,6 +5102,7 @@ The current type of b is: 9
self.do_run(src, '*16,0,4,8,8,12|20,0,4,4,8,12,12,16|24,0,20,0,4,4,8,12,12,16*\n*0,0,0,1,2,64,68,69,72*\n*2*')
def test_runtimelink(self):
+ return self.skip('shared libs are deprecated')
if Building.LLVM_OPTS: return self.skip('LLVM opts will optimize printf into puts in the parent, and the child will still look for puts')
if Settings.ASM_JS: return self.skip('asm does not support runtime linking')
@@ -4891,14 +5113,15 @@ The current type of b is: 9
Settings.BUILD_AS_SHARED_LIB = 2
Settings.NAMED_GLOBALS = 1
- self.build(supp, self.get_dir(), self.in_dir('supp.c'))
- shutil.move(self.in_dir('supp.c.o.js'), self.in_dir('liblib.so'))
+ self.build(supp, self.get_dir(), self.in_dir('supp.cpp'))
+ shutil.move(self.in_dir('supp.cpp.o.js'), self.in_dir('liblib.so'))
Settings.BUILD_AS_SHARED_LIB = 0
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):
+ return self.skip('shared libs are deprecated')
if Settings.ASM_JS: return self.skip('TODO: dlopen in asm')
Settings.NAMED_GLOBALS = 1
@@ -4953,6 +5176,7 @@ def process(filename):
post_build=add_pre_run_and_checks)
def test_dlfcn_qsort(self):
+ return self.skip('shared libs are deprecated')
if self.emcc_args is None: return self.skip('requires emcc')
if Settings.ASM_JS: return self.skip('TODO: dlopen in asm')
@@ -5049,6 +5273,7 @@ def process(filename):
post_build=add_pre_run_and_checks)
def test_dlfcn_data_and_fptr(self):
+ return self.skip('shared libs are deprecated')
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')
@@ -5153,6 +5378,7 @@ def process(filename):
post_build=add_pre_run_and_checks)
def test_dlfcn_alias(self):
+ return self.skip('shared libs are deprecated')
if Settings.ASM_JS: return self.skip('TODO: dlopen in asm')
Settings.LINKABLE = 1
@@ -5210,6 +5436,7 @@ def process(filename):
Settings.INCLUDE_FULL_LIBRARY = 0
def test_dlfcn_varargs(self):
+ return self.skip('shared libs are deprecated')
if Settings.ASM_JS: return self.skip('TODO: dlopen in asm')
Settings.LINKABLE = 1
@@ -5475,7 +5702,7 @@ at function.:blag
open(path_from_root('tests', 'printf', 'output_i64_1.txt'), 'r').read()]
self.do_run(src, expected)
- def test_printf_types(self):
+ def test_printf_2(self):
src = r'''
#include <stdio.h>
@@ -5488,11 +5715,12 @@ at function.:blag
double d = 6.6;
printf("%c,%hd,%d,%lld,%.1f,%.1llf\n", c, s, i, l, f, d);
+ printf("%#x,%#x\n", 1, 0);
return 0;
}
'''
- self.do_run(src, '1,2,3,4,5.5,6.6\n')
+ self.do_run(src, '1,2,3,4,5.5,6.6\n0x1,0\n')
def test_vprintf(self):
src = r'''
@@ -5896,10 +6124,45 @@ Pass: 0.000012 0.000012''')
'''
self.do_run(src, '''0:173,16 1:16,173 2:183,173 3:17,287 4:98,123''')
+ def test_sscanf_other_whitespace(self):
+ Settings.SAFE_HEAP = 0 # use i16s in printf
+
+ src = r'''
+ #include<stdio.h>
+
+ int main() {
+ short int x;
+ short int y;
+
+ const char* buffer[] = {
+ "\t2\t3\t", /* TAB - horizontal tab */
+ "\t\t5\t\t7\t\t",
+ "\n11\n13\n", /* LF - line feed */
+ "\n\n17\n\n19\n\n",
+ "\v23\v29\v", /* VT - vertical tab */
+ "\v\v31\v\v37\v\v",
+ "\f41\f43\f", /* FF - form feed */
+ "\f\f47\f\f53\f\f",
+ "\r59\r61\r", /* CR - carrage return */
+ "\r\r67\r\r71\r\r"
+ };
+
+ for (int i=0; i<10; ++i) {
+ x = 0; y = 0;
+ sscanf(buffer[i], " %d %d ", &x, &y);
+ printf("%d, %d, ", x, y);
+ }
+
+ return 0;
+ }
+ '''
+ self.do_run(src, '''2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, ''')
+
def test_sscanf_3(self):
# i64
if not Settings.USE_TYPED_ARRAYS == 2: return self.skip('64-bit sscanf only supported in ta2')
src = r'''
+ #include <stdint.h>
#include <stdio.h>
int main(){
@@ -5959,6 +6222,7 @@ Pass: 0.000012 0.000012''')
if Settings.USE_TYPED_ARRAYS != 2: return self.skip("need ta2 for full i64")
src = r'''
+ #include <stdint.h>
#include <stdio.h>
int main(){
@@ -6105,6 +6369,31 @@ def process(filename):
self.emcc_args += ['--embed-file', 'eol.txt']
self.do_run(src, 'SUCCESS\n')
+ def test_fscanf(self):
+ if self.emcc_args is None: return self.skip('requires emcc')
+ open(os.path.join(self.get_dir(), 'three_numbers.txt'), 'w').write('''-1 0.1 -.1''')
+ src = r'''
+ #include <stdio.h>
+ #include <assert.h>
+ #include <float.h>
+ int main()
+ {
+ float x = FLT_MAX, y = FLT_MAX, z = FLT_MAX;
+
+ FILE* fp = fopen("three_numbers.txt", "r");
+ if (fp) {
+ int match = fscanf(fp, " %f %f %f ", &x, &y, &z);
+ printf("match = %d\n", match);
+ printf("x = %0.1f, y = %0.1f, z = %0.1f\n", x, y, z);
+ } else {
+ printf("failed to open three_numbers.txt\n");
+ }
+ return 0;
+ }
+ '''
+ self.emcc_args += ['--embed-file', 'three_numbers.txt']
+ self.do_run(src, 'match = 3\nx = -1.0, y = 0.1, z = -0.1\n')
+
def test_folders(self):
add_pre_run = '''
def process(filename):
@@ -7245,6 +7534,10 @@ extern "C" {
src = open(path_from_root('tests', 'fasta.cpp'), 'r').read()
self.do_run(src, j, [str(i)], lambda x, err: x.replace('\n', '*'), no_build=i>1)
+ def test_whets(self):
+ if not Settings.ASM_JS: return self.skip('mainly a test for asm validation here')
+ self.do_run(open(path_from_root('tests', 'whets.cpp')).read(), 'Single Precision C Whetstone Benchmark')
+
def test_dlmalloc(self):
if self.emcc_args is None: self.emcc_args = [] # dlmalloc auto-inclusion is only done if we use emcc
@@ -7297,7 +7590,7 @@ operator new(size_t size)
self.do_run(src, 'new 4!\n*1,0*')
def test_dlmalloc_partial_2(self):
- if self.emcc_args is None or 'SAFE_HEAP' in str(self.emcc_args): return self.skip('only emcc will link in dlmalloc, and we do unsafe stuff')
+ if self.emcc_args is None or 'SAFE_HEAP' in str(self.emcc_args) or 'CHECK_HEAP_ALIGN' in str(self.emcc_args): return self.skip('only emcc will link in dlmalloc, and we do unsafe stuff')
# present part of the symbols of dlmalloc, not all. malloc is harder to link than new which is weak.
src = r'''
#include <stdio.h>
@@ -7526,7 +7819,7 @@ void*:16
def test_cubescript(self):
if self.emcc_args is None: return self.skip('requires emcc')
- if self.emcc_args is not None and '-O2' in self.emcc_args:
+ if self.run_name == 'o2':
self.emcc_args += ['--closure', '1'] # Use closure here for some additional coverage
Building.COMPILER_TEST_OPTS = [] # remove -g, so we have one test without it by default
@@ -7541,6 +7834,23 @@ void*:16
self.do_run(path_from_root('tests', 'cubescript'), '*\nTemp is 33\n9\n5\nhello, everyone\n*', main_file='command.cpp')
+ assert 'asm2g' in test_modes
+ if self.run_name == 'asm2g':
+ results = {}
+ original = open('src.cpp.o.js').read()
+ results[Settings.ALIASING_FUNCTION_POINTERS] = len(original)
+ Settings.ALIASING_FUNCTION_POINTERS = 1 - Settings.ALIASING_FUNCTION_POINTERS
+ self.do_run(path_from_root('tests', 'cubescript'), '*\nTemp is 33\n9\n5\nhello, everyone\n*', main_file='command.cpp')
+ final = open('src.cpp.o.js').read()
+ results[Settings.ALIASING_FUNCTION_POINTERS] = len(final)
+ open('original.js', 'w').write(original)
+ print results
+ assert results[1] < 0.99*results[0]
+ assert ' & 3]()' in original, 'small function table exists'
+ assert ' & 3]()' not in final, 'small function table does not exist'
+ assert ' & 255]()' not in original, 'big function table does not exist'
+ assert ' & 255]()' in final, 'big function table exists'
+
def test_gcc_unmangler(self):
Settings.NAMED_GLOBALS = 1 # test coverage for this
@@ -7560,20 +7870,14 @@ void*:16
def test_lua(self):
if self.emcc_args is None: return self.skip('requires emcc')
-
if Settings.QUANTUM_SIZE == 1: return self.skip('TODO: make this work')
- # Overflows in luaS_newlstr hash loop
- if self.emcc_args is None: Settings.SAFE_HEAP = 0 # Has various warnings, with copied HEAP_HISTORY values (fixed if we copy 'null' as the type)
- Settings.CORRECT_OVERFLOWS = 1
- Settings.CHECK_OVERFLOWS = 0
- Settings.CORRECT_SIGNS = 1 # Not sure why, but needed
-
- self.do_ll_run(path_from_root('tests', 'lua', 'lua.ll'),
- 'hello lua world!\n17\n1\n2\n3\n4\n7',
- args=['-e', '''print("hello lua world!");print(17);for x = 1,4 do print(x) end;print(10-3)'''],
- output_nicerizer=lambda string, err: (string + err).replace('\n\n', '\n').replace('\n\n', '\n'),
- extra_emscripten_args=['-H', 'libc/fcntl.h,libc/sys/unistd.h,poll.h,libc/math.h,libc/langinfo.h,libc/time.h'])
+ self.do_run('',
+ 'hello lua world!\n17\n1\n2\n3\n4\n7',
+ args=['-e', '''print("hello lua world!");print(17);for x = 1,4 do print(x) end;print(10-3)'''],
+ libraries=self.get_library('lua', [os.path.join('src', 'lua'), os.path.join('src', 'liblua.a')], make=['make', 'generic'], configure=None),
+ includes=[path_from_root('tests', 'lua')],
+ output_nicerizer=lambda string, err: (string + err).replace('\n\n', '\n').replace('\n\n', '\n'))
def get_freetype(self):
Settings.DEAD_FUNCTIONS += ['_inflateEnd', '_inflate', '_inflateReset', '_inflateInit2_']
@@ -7665,6 +7969,9 @@ def process(filename):
force_c=True)
def test_zlib(self):
+ if Settings.ASM_JS:
+ self.banned_js_engines = [NODE_JS] # TODO investigate
+
if self.emcc_args is not None and '-O2' in self.emcc_args:
self.emcc_args += ['--closure', '1'] # Use closure here for some additional coverage
@@ -7689,15 +7996,29 @@ def process(filename):
Settings.SAFE_HEAP_LINES = ['btVoronoiSimplexSolver.h:40', 'btVoronoiSimplexSolver.h:41',
'btVoronoiSimplexSolver.h:42', 'btVoronoiSimplexSolver.h:43']
- self.do_run(open(path_from_root('tests', 'bullet', 'Demos', 'HelloWorld', 'HelloWorld.cpp'), 'r').read(),
- [open(path_from_root('tests', 'bullet', 'output.txt'), 'r').read(), # different roundings
- open(path_from_root('tests', 'bullet', 'output2.txt'), 'r').read(),
- open(path_from_root('tests', 'bullet', 'output3.txt'), 'r').read()],
- libraries=self.get_library('bullet', [os.path.join('src', '.libs', 'libBulletDynamics.a'),
- os.path.join('src', '.libs', 'libBulletCollision.a'),
- os.path.join('src', '.libs', 'libLinearMath.a')],
- configure_args=['--disable-demos','--disable-dependency-tracking']),
- includes=[path_from_root('tests', 'bullet', 'src')])
+ def test():
+ self.do_run(open(path_from_root('tests', 'bullet', 'Demos', 'HelloWorld', 'HelloWorld.cpp'), 'r').read(),
+ [open(path_from_root('tests', 'bullet', 'output.txt'), 'r').read(), # different roundings
+ open(path_from_root('tests', 'bullet', 'output2.txt'), 'r').read(),
+ open(path_from_root('tests', 'bullet', 'output3.txt'), 'r').read()],
+ libraries=self.get_library('bullet', [os.path.join('src', '.libs', 'libBulletDynamics.a'),
+ os.path.join('src', '.libs', 'libBulletCollision.a'),
+ os.path.join('src', '.libs', 'libLinearMath.a')],
+ configure_args=['--disable-demos','--disable-dependency-tracking']),
+ includes=[path_from_root('tests', 'bullet', 'src')])
+ test()
+
+ assert 'asm2g' in test_modes
+ if self.run_name == 'asm2g':
+ # Test forced alignment
+ print >> sys.stderr, 'testing FORCE_ALIGNED_MEMORY'
+ old = open('src.cpp.o.js').read()
+ Settings.FORCE_ALIGNED_MEMORY = 1
+ test()
+ new = open('src.cpp.o.js').read()
+ print len(old), len(new), old.count('tempBigInt'), new.count('tempBigInt')
+ assert len(old) > len(new)
+ assert old.count('tempBigInt') > new.count('tempBigInt')
def test_poppler(self):
if self.emcc_args is None: return self.skip('very slow, we only do this in emcc runs')
@@ -7878,14 +8199,14 @@ def process(filename):
if self.emcc_args is None: return self.skip('requires emcc')
if Settings.QUANTUM_SIZE == 1: return self.skip('TODO: make this work')
- # Overflows in string_hash
- Settings.CORRECT_OVERFLOWS = 1
- Settings.CHECK_OVERFLOWS = 0
- if self.emcc_args is None: Settings.SAFE_HEAP = 0 # Has bitfields which are false positives. Also the PyFloat_Init tries to detect endianness.
- Settings.CORRECT_SIGNS = 1 # Not sure why, but needed
- Settings.EXPORTED_FUNCTIONS += ['_PyRun_SimpleStringFlags'] # for the demo
+ #Settings.EXPORTED_FUNCTIONS += ['_PyRun_SimpleStringFlags'] # for the demo
+
+ if self.is_le32():
+ bitcode = path_from_root('tests', 'python', 'python.le32.bc')
+ else:
+ bitcode = path_from_root('tests', 'python', 'python.small.bc')
- self.do_ll_run(path_from_root('tests', 'python', 'python.small.bc'),
+ self.do_ll_run(bitcode,
'hello python world!\n[0, 2, 4, 6]\n5\n22\n5.470000',
args=['-S', '-c' '''print "hello python world!"; print [x*2 for x in range(4)]; t=2; print 10-3-t; print (lambda x: x*2)(11); print '%f' % 5.47'''])
@@ -8319,6 +8640,10 @@ def process(filename):
self.do_run(src, '''Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS.''')
generated = open('src.cpp.o.js').read()
assert 'jsCall' not in generated
+ Settings.RESERVED_FUNCTION_POINTERS = 1
+
+ Settings.ALIASING_FUNCTION_POINTERS = 1 - Settings.ALIASING_FUNCTION_POINTERS # flip the test
+ self.do_run(src, '''Hello 7 from JS!''')
def test_scriptaclass(self):
if self.emcc_args is None: return self.skip('requires emcc')
@@ -8498,7 +8823,7 @@ def process(filename):
Module.Child2.prototype.runVirtualFunc(c2);
c2.virtualFunc2();
-''' + ('' if Settings.ASM_JS else '''
+''' + ('''
// extend the class from JS
var c3 = new Module.Child2;
Module.customizeVTable(c3, [{
@@ -8528,6 +8853,8 @@ def process(filename):
src.close()
'''
+ Settings.RESERVED_FUNCTION_POINTERS = 20
+
self.do_run(src, '''*
84
c1
@@ -8558,7 +8885,7 @@ Child2:9
*static*
*virtualf*
*virtualf*
-*virtualf2*''' + ('' if Settings.ASM_JS else '''
+*virtualf2*''' + ('''
Parent:9
Child2:9
*js virtualf replacement*
@@ -9121,15 +9448,31 @@ finalizing 3 (global == 0)
''')
# Generate tests for everything
- def make_run(fullname, name=-1, compiler=-1, llvm_opts=0, embetter=0, quantum_size=0, typed_arrays=0, emcc_args=None):
+ def make_run(fullname, name=-1, compiler=-1, llvm_opts=0, embetter=0, quantum_size=0, typed_arrays=0, emcc_args=None, env='{}'):
exec('''
class %s(T):
+ run_name = '%s'
+ env = %s
+
def tearDown(self):
super(%s, self).tearDown()
+ for k, v in self.env.iteritems():
+ del os.environ[k]
+
def setUp(self):
super(%s, self).setUp()
+ for k, v in self.env.iteritems():
+ assert k not in os.environ, k + ' should not be in environment'
+ os.environ[k] = v
+
+ global checked_sanity
+ if not checked_sanity:
+ print '(checking sanity from test runner)' # do this after we set env stuff
+ check_sanity(force=True)
+ checked_sanity = True
+
Building.COMPILER_TEST_OPTS = ['-g']
os.chdir(self.get_dir()) # Ensure the directory exists and go there
Building.COMPILER = %r
@@ -9173,7 +9516,7 @@ class %s(T):
Building.pick_llvm_opts(3)
TT = %s
-''' % (fullname, fullname, fullname, compiler, str(emcc_args), llvm_opts, embetter, quantum_size, typed_arrays, fullname))
+''' % (fullname, fullname, env, fullname, fullname, compiler, str(emcc_args), llvm_opts, embetter, quantum_size, typed_arrays, fullname))
return TT
# Make one run with the defaults
@@ -9186,9 +9529,10 @@ TT = %s
exec('o2 = make_run("o2", compiler=CLANG, emcc_args=["-O2", "-s", "ASM_JS=0", "-s", "JS_CHUNK_SIZE=1024"])')
# asm.js
- exec('asm1 = make_run("asm1", compiler=CLANG, emcc_args=["-O1"])')
+ exec('asm1 = make_run("asm1", compiler=CLANG, emcc_args=["-O1", "-s", "CHECK_HEAP_ALIGN=1"])')
exec('asm2 = make_run("asm2", compiler=CLANG, emcc_args=["-O2"])')
exec('asm2g = make_run("asm2g", compiler=CLANG, emcc_args=["-O2", "-g", "-s", "ASSERTIONS=1", "--memory-init-file", "1"])')
+ exec('''asm2x86 = make_run("asm2x86", compiler=CLANG, emcc_args=["-O2", "-g", "-s", "CHECK_HEAP_ALIGN=1"], env='{"EMCC_LLVM_TARGET": "i386-pc-linux-gnu"}')''')
# Make custom runs with various options
for compiler, quantum, embetter, typed_arrays, llvm_opts in [
@@ -9255,7 +9599,7 @@ Options that are modified or new in %s include:
self.assertContained('error: invalid preprocessing directive',