diff options
Diffstat (limited to 'tests/runner.py')
-rwxr-xr-x | tests/runner.py | 776 |
1 files changed, 550 insertions, 226 deletions
diff --git a/tests/runner.py b/tests/runner.py index 5602fd94..570bfbf2 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -78,6 +78,8 @@ class RunnerCore(unittest.TestCase): 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 +240,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'] @@ -358,7 +357,8 @@ 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, @@ -455,7 +455,7 @@ if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv) and 'brows if len(sys.argv) == 2 and 'ALL.' in sys.argv[1]: 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], 'default.'+test, 'o1.'+test, 'o2.'+test, 'asm1.'+test, 'asm2.'+test, 'asm2g.'+test, 'asm2le32.'+test, 's_0_0.'+test, 's_0_1.'+test, 's_1_0.'+test, 's_1_1.'+test] 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 +506,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 'le32-unknown-nacl' in COMPILER_OPTS or self.env.get('EMCC_LLVM_TARGET') == 'le32-unknown-nacl' + def test_hello_world(self): src = ''' #include <stdio.h> @@ -1118,6 +1121,7 @@ m_divisor is 1091269979 { a = argc; b = argv[1][0]; + printf("%d,%d\n", a, b); if (a > a + b || a > a + b + 1) { printf("one %lld, %lld", a, b); return 0; @@ -1132,10 +1136,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 @@ -1198,9 +1203,9 @@ m_divisor is 1091269979 // from cube2, zlib licensed - #define N (624) - #define M (397) - #define K (0x9908B0DFU) + #define N (624) + #define M (397) + #define K (0x9908B0DFU) static uint state[N]; static int next = N; @@ -1378,7 +1383,7 @@ c5,de,15,8a #include <string> #include <sstream> - typedef unsigned long long quint64; + typedef unsigned long long quint64; using namespace std; @@ -1406,14 +1411,14 @@ c5,de,15,8a printf("1\n"); s >> hex >> int64bitInt; printf("2\n"); - + stringstream out; out << hex << qbswap(int64bitInt); - + cout << out.str() << endl; cout << hex << int64bitInt << endl; cout << string64bitInt << endl; - + if (out.str() != "bbccddeeff3344") { cout << "Failed!" << endl; @@ -1455,7 +1460,7 @@ Succeeded! # A good test of i64 math if Settings.USE_TYPED_ARRAYS != 2: return self.skip('requires ta2 C-style memory aliasing') self.do_run('', 'Usage: hashstring <seed>', - libraries=self.get_library('cube2hash', ['cube2hash.bc'], configure=None), + libraries=self.get_library('cube2hash', ['cube2hash.bc'], configure=None), includes=[path_from_root('tests', 'cube2hash')]) for text, output in [('fleefl', '892BDB6FD3F62E863D63DA55851700FDE3ACF30204798CE9'), @@ -1498,7 +1503,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 @@ -1532,6 +1541,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 @@ -1752,10 +1817,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); @@ -2238,7 +2303,7 @@ cat |umber one top notchfi FI FO FUM WHEN WHERE WHY HOW WHO|''', ['wowie', 'too' total += c->value; c = c->next; } while (c != chunk); - + printf("*%d,%d*\\n", total, b.next); // NULL *is* 0, in C/C++. No JS null! (null == 0 is false, etc.) @@ -2330,19 +2395,19 @@ cat |umber one top notchfi FI FO FUM WHEN WHERE WHY HOW WHO|''', ['wowie', 'too' src = r''' #include <stdio.h> #include <setjmp.h> - + 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 } - + void first(void) { second(); printf("first\n"); // does not print } - + int main() { volatile int x = 0; if ( ! setjmp(buf) ) { @@ -2351,7 +2416,7 @@ cat |umber one top notchfi FI FO FUM WHEN WHERE WHY HOW WHO|''', ['wowie', 'too' } else { // when longjmp jumps back, setjmp returns 1 printf("main: %d\n", x); // prints } - + return 0; } ''' @@ -2510,7 +2575,7 @@ Exception execution path of first function! 1 src = r''' #include <stdio.h> #include <setjmp.h> - + static jmp_buf buf; void (*fp)() = NULL; @@ -2519,12 +2584,12 @@ Exception execution path of first function! 1 printf("second\n"); // prints longjmp(buf,1); // jumps back to where setjmp was called - making setjmp now return 1 } - + void first(void) { fp(); printf("first\n"); // does not print } - + int main(int argc, char **argv) { fp = argc == 200 ? NULL : second; @@ -2535,7 +2600,7 @@ Exception execution path of first function! 1 } else { // when longjmp jumps back, setjmp returns 1 printf("main: %d\n", x); // prints } - + return 0; } ''' @@ -2547,15 +2612,15 @@ Exception execution path of first function! 1 src = r''' #include <stdio.h> #include <setjmp.h> - + static jmp_buf buf; - + int main() { volatile int x = 0; printf("setjmp:%d\n", setjmp(buf)); x++; printf("x:%d\n", x); - if (x < 4) longjmp(buf, x*2); + if (x < 4) longjmp(buf, x*2); return 0; } ''' @@ -2629,6 +2694,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> @@ -2685,7 +2781,7 @@ back src = ''' #include <iostream> - + class MyException { public: @@ -2693,21 +2789,21 @@ back MyException( const MyException & ) { std::cout << "Copy..."; } ~MyException(){ std::cout << "Destruct..."; } }; - + int function() { std::cout << "Throw..."; throw MyException(); } - + int function2() { return function(); } - + int main() { - try + try { function2(); } @@ -2715,8 +2811,8 @@ back { std::cout << "Catched..."; } - - try + + try { function2(); } @@ -2724,11 +2820,11 @@ back { std::cout << "Catched..."; } - + return 0; } ''' - + Settings.DISABLE_EXCEPTION_CATCHING = 0 if '-O2' in self.emcc_args: self.emcc_args.pop() ; self.emcc_args.pop() # disable closure to work around a closure bug @@ -2741,7 +2837,7 @@ back src = ''' #include <stdio.h> - + void thrower() { printf("infunc..."); throw(99); @@ -3239,6 +3335,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 = ''' @@ -3358,7 +3484,7 @@ Exiting setjmp function, level: 0, prev_jmp: -1 static char s[100]="aaaaa"; static int func(void) { - if(s[0]!='a') return 0; + if(s[0]!='a') return 0; printf("iso open %s\n", s, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001); return 0; } @@ -3375,17 +3501,41 @@ Exiting setjmp function, level: 0, prev_jmp: -1 if self.emcc_args is None: return self.skip('need c99') self.emcc_args += ['-std=c99'] src = open(path_from_root('tests', 'life.c'), 'r').read() - self.do_run(src, '''-------- - [][][] -[][] - [] - [] -[][] - - - --------- -''', ['8', '8', '25000'], force_c=True) + self.do_run(src, '''-------------------------------- +[] [] [][][] + [] [] [] [][] [] [] [] +[] [][] [][] [][][] [] + [] [] [] [] [][] [] [] + [] [][] [] [] [] [] [][][][] + [][] [][] [] [][][] [] [] + [] [][] [][] [][] [][][] + [][] [][][] [] [] + [][] [][] [] + [][][] + [] + + + + + [][][] + [] [][] [][] + [][] [] [][] [][] + [][] [][] + [] + [][] + [][] [] +[] [][] [] + [][][] [] + [] [][] +[] [] [] + [] +[] [] [] + [][][] + + [] + [][][] [] +-------------------------------- +''', ['2'], force_c=True) def test_array2(self): src = ''' @@ -3593,7 +3743,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') @@ -3844,7 +3997,7 @@ def process(filename): def test_cxx03_do_run(self): src = ''' #include <stdio.h> - + #if __cplusplus != 199711L #error By default, if no -std is specified, emscripten should be compiling with -std=c++03! #endif @@ -3916,7 +4069,7 @@ def process(filename): #pragma pack(push,1) typedef struct header - { + { unsigned char id; unsigned short colour; unsigned char desc; @@ -3924,7 +4077,7 @@ def process(filename): #pragma pack(pop) typedef struct fatheader - { + { unsigned char id; unsigned short colour; unsigned char desc; @@ -3960,7 +4113,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); @@ -4016,6 +4169,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> @@ -4190,7 +4344,10 @@ The current type of b is: 9 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 another with a different number of arguments' 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') @@ -4269,14 +4426,14 @@ The current type of b is: 9 src = r''' #include <stdio.h> #include <stdlib.h> - + static void cleanA() { printf("A"); } static void cleanB() { printf("B"); } - + int main() { atexit(cleanA); atexit(cleanB); @@ -4810,9 +4967,9 @@ The current type of b is: 9 chain *c = NULL; printf("*%d,%d,%d,%d,%d,%d|%d,%d,%d,%d,%d,%d,%d,%d|%d,%d,%d,%d,%d,%d,%d,%d,%d,%d*\\n", sizeof(base), - int(&(b->x)), int(&(b->y)), int(&(b->a)), int(&(b->b)), int(&(b->c)), + int(&(b->x)), int(&(b->y)), int(&(b->a)), int(&(b->b)), int(&(b->c)), sizeof(hashtableentry), - int(&(e->key)), int(&(e->data)), int(&(e->data.x)), int(&(e->data.y)), int(&(e->data.a)), int(&(e->data.b)), int(&(e->data.c)), + int(&(e->key)), int(&(e->data)), int(&(e->data.x)), int(&(e->data.y)), int(&(e->data.a)), int(&(e->data.b)), int(&(e->data.c)), sizeof(hashset::chain), int(&(c->elem)), int(&(c->next)), int(&(c->elem.key)), int(&(c->elem.data)), int(&(c->elem.data.x)), int(&(c->elem.data.y)), int(&(c->elem.data.a)), int(&(c->elem.data.b)), int(&(c->elem.data.c)) ); @@ -5425,7 +5582,7 @@ at function.:blag src = open(path_from_root('tests', 'parseInt', 'src.c'), 'r').read() expected = open(path_from_root('tests', 'parseInt', 'output.txt'), 'r').read() self.do_run(src, expected) - + def test_transtrcase(self): src = ''' #include <stdio.h> @@ -5565,7 +5722,7 @@ at function.:blag } ''' self.do_run(src, '22 : me and myself 25 1.34\n21 waka 95\n') - + def test_perrar(self): src = r''' #include <sys/types.h> @@ -5869,20 +6026,21 @@ Pass: 0.000012 0.000012''') return 0; } ''' - self.do_run(src, '''0:173,16 1:16,173 2:183,173 3:17,287 4:98,123''') + self.do_run(src, '''0:173,16 1:16,173 2:183,173 3:17,287 4:98,123''') 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(){ - + int64_t s, m, l; printf("%d\n", sscanf("123 1073741823 1125899906842620", "%lld %lld %lld", &s, &m, &l)); printf("%lld,%lld,%lld\n", s, m, l); - + int64_t negS, negM, negL; printf("%d\n", sscanf("-123 -1073741823 -1125899906842620", "%lld %lld %lld", &negS, &negM, &negL)); printf("%lld,%lld,%lld\n", negS, negM, negL); @@ -5890,8 +6048,8 @@ Pass: 0.000012 0.000012''') return 0; } ''' - - self.do_run(src, '3\n123,1073741823,1125899906842620\n' + + + self.do_run(src, '3\n123,1073741823,1125899906842620\n' + '3\n-123,-1073741823,-1125899906842620\n') def test_sscanf_4(self): @@ -5934,6 +6092,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(){ @@ -6482,7 +6641,7 @@ def process(filename): ''' self.do_run(src, "some string constant") - + def test_istream(self): if self.emcc_args is None: return self.skip('requires libcxx') @@ -6490,15 +6649,15 @@ def process(filename): #include <string> #include <sstream> #include <iostream> - + int main() { std::string mystring("1 2 3"); std::istringstream is(mystring); int one, two, three; - + is >> one >> two >> three; - + printf( "%i %i %i", one, two, three ); } ''' @@ -6520,19 +6679,19 @@ def process(filename): src = ''' #include <dirent.h> #include <stdio.h> - + int main() { DIR * dir; dirent * entity; - + dir = opendir( "test" ); - + while( ( entity = readdir( dir ) ) ) { printf( "%s is a %s\\n", entity->d_name, entity->d_type & DT_DIR ? "directory" : "file" ); } - + return 0; } @@ -7051,7 +7210,7 @@ int main(int argc, char **argv) { int main ( int argc, char *argv[] ) { - std::vector<S> ar; + std::vector<S> ar; S s; s.a = 789; @@ -7130,7 +7289,7 @@ extern "C" { int main() { const char* jsonString = "{\\"key\\": \\"value\\",\\"array\\": [\\"array_item1\\",\\"array_item2\\",\\"array_item3\\"],\\"dict\\":{\\"number\\": 3,\\"float\\": 2.2}}"; - + json_error_t error; json_t *root = json_loadb(jsonString, strlen(jsonString), 0, &error); @@ -7145,7 +7304,7 @@ extern "C" { } printf("%s\\n", json_string_value(json_object_get(root, "key"))); - + json_t *array = json_object_get(root, "array"); if(!array) { printf("Node `array` is `null`."); @@ -7171,7 +7330,7 @@ extern "C" { json_t *numberNode = json_object_get(dict, "number"); json_t *floatNode = json_object_get(dict, "float"); - + if(!numberNode || !json_is_number(numberNode) || !floatNode || !json_is_real(floatNode)) return 0; @@ -7261,7 +7420,7 @@ extern "C" { def test_dlmalloc_partial(self): if self.emcc_args is None: return self.skip('only emcc will link in dlmalloc') # present part of the symbols of dlmalloc, not all - src = open(path_from_root('tests', 'new.cpp')).read().replace('{{{ NEW }}}', 'new int').replace('{{{ DELETE }}}', 'delete') + ''' + src = open(path_from_root('tests', 'new.cpp')).read().replace('{{{ NEW }}}', 'new int').replace('{{{ DELETE }}}', 'delete') + ''' void * operator new(size_t size) { @@ -7272,7 +7431,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> @@ -7393,7 +7552,7 @@ void*:16 struct DATA { int value; - + DATA() { value = 0; @@ -7403,7 +7562,7 @@ void*:16 DATA & GetData() { static DATA data; - + return data; } @@ -7437,7 +7596,7 @@ void*:16 #include <stdio.h> #include <sys/mman.h> #include <assert.h> - + int main(int argc, char *argv[]) { for (int i = 0; i < 10; i++) { int* map = (int*)mmap(0, 5000, PROT_READ | PROT_WRITE, @@ -7448,23 +7607,23 @@ void*:16 const int NUM_BYTES = 8 * 1024 * 1024; const int NUM_INTS = NUM_BYTES / sizeof(int); - + int* map = (int*)mmap(0, NUM_BYTES, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0); assert(map != MAP_FAILED); int i; - + for (i = 0; i < NUM_INTS; i++) { map[i] = i; } - + for (i = 0; i < NUM_INTS; i++) { assert(map[i] == i); } - + assert(munmap(map, NUM_BYTES) == 0); - + printf("hello,world"); return 0; } @@ -7535,20 +7694,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_'] @@ -7577,7 +7730,7 @@ def process(filename): ''' # Not needed for js, but useful for debugging - shutil.copyfile(path_from_root('tests', 'freetype', 'LiberationSansBold.ttf'), os.path.join(self.get_dir(), 'font.ttf')) + shutil.copyfile(path_from_root('tests', 'freetype', 'LiberationSansBold.ttf'), os.path.join(self.get_dir(), 'font.ttf')) # Main self.do_run(open(path_from_root('tests', 'freetype', 'main.c'), 'r').read(), @@ -7676,7 +7829,6 @@ def process(filename): def test_poppler(self): if self.emcc_args is None: return self.skip('very slow, we only do this in emcc runs') - if Settings.ASM_JS: return self.skip('asm does not support relying on function pointers being cast to different types') Settings.CORRECT_OVERFLOWS = 1 Settings.CORRECT_SIGNS = 1 @@ -7854,14 +8006,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''']) @@ -8329,7 +8481,7 @@ def process(filename): script_src = ''' var sme = Module._.ScriptMe.__new__(83); // malloc(sizeof(ScriptMe)), ScriptMe::ScriptMe(sme, 83) / new ScriptMe(83) (at addr sme) Module._.ScriptMe.mulVal(sme, 2); // ScriptMe::mulVal(sme, 2) sme.mulVal(2) - Module.print('*' + Module._.ScriptMe.getVal(sme) + '*'); + Module.print('*' + Module._.ScriptMe.getVal(sme) + '*'); _free(sme); Module.print('*ok*'); ''' @@ -9097,15 +9249,24 @@ 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): + 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 + Building.COMPILER_TEST_OPTS = ['-g'] os.chdir(self.get_dir()) # Ensure the directory exists and go there Building.COMPILER = %r @@ -9149,7 +9310,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, env, fullname, fullname, compiler, str(emcc_args), llvm_opts, embetter, quantum_size, typed_arrays, fullname)) return TT # Make one run with the defaults @@ -9162,9 +9323,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('''asm2le32 = make_run("asm2le32", compiler=CLANG, emcc_args=["-O2", "-g", "-s", "CHECK_HEAP_ALIGN=1"], env='{"EMCC_LLVM_TARGET": "le32-unknown-nacl"}')''') # Make custom runs with various options for compiler, quantum, embetter, typed_arrays, llvm_opts in [ @@ -9404,7 +9566,7 @@ Options that are modified or new in %s include: output = Popen([PYTHON, compiler, 'twopart_main.o'] + args, stdout=PIPE, stderr=PIPE).communicate() assert os.path.exists(target), '\n'.join(output) #print '\n'.join(output) - self.assertContained('is not a function', run_js(target, stderr=STDOUT)) + self.assertContained('missing function', run_js(target, stderr=STDOUT)) try_delete(target) # Combining those bc files into js should work @@ -9457,16 +9619,16 @@ f.close() cmake_outputs = ['hello_world.js', 'hello_world_gles.html'] for i in range(0, 2): for configuration in ['Debug', 'Release']: - + # Create a temp workspace folder cmakelistsdir = path_from_root('t |