diff options
Diffstat (limited to 'tests/runner.py')
-rwxr-xr-x | tests/runner.py | 718 |
1 files changed, 476 insertions, 242 deletions
diff --git a/tests/runner.py b/tests/runner.py index f04413cf..7c049ede 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 # This Python file uses the following encoding: utf-8 ''' @@ -199,7 +199,7 @@ sys.path += [%r] process(sys.argv[1]) ''') transform.close() - transform_args = ['--js-transform', "python %s" % transform_filename] + transform_args = ['--js-transform', "%s %s" % (PYTHON, transform_filename)] Building.emcc(filename + '.o.ll', Settings.serialize() + self.emcc_args + transform_args + Building.COMPILER_TEST_OPTS, filename + '.o.js') run_post(post2) @@ -279,7 +279,7 @@ process(sys.argv[1]) return ret def build_native(self, filename): - process = Popen([CLANG, '-O2', filename, '-o', filename+'.native'], stdout=PIPE); + process = Popen([CLANG, '-O2', '-fno-math-errno', filename, '-o', filename+'.native'], stdout=PIPE); output = process.communicate() if process.returncode is not 0: print >> sys.stderr, "Building native executable with command '%s' failed with a return code %d!" % (' '.join([CLANG, '-O2', filename, '-o', filename+'.native']), process.returncode) @@ -428,7 +428,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, 's_0_0.'+test, 's_0_1.'+test, 's_0_1_q1.'+test, 's_1_0.'+test, 's_1_1.'+test, 's_1_1_q1.'+test] + sys.argv = [sys.argv[0], 'default.'+test, 'o1.'+test, 'o2.'+test, 'asm2.'+test, 's_0_0.'+test, 's_0_1.'+test, 's_0_1_q1.'+test, 's_1_0.'+test, 's_1_1.'+test, 's_1_1_q1.'+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. @@ -836,6 +836,7 @@ if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv) and 'brows def test_i64_cmp2(self): if Settings.USE_TYPED_ARRAYS != 2: return self.skip('full i64 stuff only in ta2') + src = r''' #include <inttypes.h> #include <stdio.h> @@ -881,6 +882,8 @@ m_divisor is 1091269979 def test_i64_double(self): if Settings.USE_TYPED_ARRAYS != 2: return self.skip('full i64 stuff only in ta2') + + src = r''' #include <stdio.h> @@ -923,6 +926,7 @@ m_divisor is 1091269979 def test_i64_umul(self): if Settings.USE_TYPED_ARRAYS != 2: return self.skip('full i64 stuff only in ta2') + src = r''' #include <inttypes.h> #include <stdio.h> @@ -1151,15 +1155,19 @@ m_divisor is 1091269979 ''' self.do_run(src, ',0,,2,C!,0,C!,0,,65535,C!,0,') - def test_bswap(self): + def test_llvm_intrinsics(self): if self.emcc_args == None: return self.skip('needs ta2') src = r''' #include <stdio.h> + #include <sys/types.h> extern "C" { extern unsigned short llvm_bswap_i16(unsigned short x); extern unsigned int llvm_bswap_i32(unsigned int x); + extern int32_t llvm_ctlz_i32(int32_t x); + extern int64_t llvm_ctlz_i64(int64_t x); + extern int llvm_expect_i32(int x, int y); } int main(void) { @@ -1172,6 +1180,11 @@ m_divisor is 1091269979 printf("%x,%x,%x,%x\n", y&0xff, (y>>8)&0xff, (y>>16)&0xff, (y>>24)&0xff); y = llvm_bswap_i32(y); printf("%x,%x,%x,%x\n", y&0xff, (y>>8)&0xff, (y>>16)&0xff, (y>>24)&0xff); + + printf("%d,%d\n", (int)llvm_ctlz_i64(((int64_t)1) << 40), llvm_ctlz_i32(1<<10)); + + printf("%d\n", llvm_expect_i32(x % 27, 3)); + return 0; } ''' @@ -1179,6 +1192,76 @@ m_divisor is 1091269979 c8,ef 8a,15,de,c5 c5,de,15,8a +23,21 +13 +''') + + def test_bswap64(self): + if Settings.USE_TYPED_ARRAYS != 2: return self.skip('needs ta2') + + src = r''' + #include <stdio.h> + #include <stdlib.h> + + #include <iostream> + #include <string> + #include <sstream> + + typedef unsigned long long quint64; + + using namespace std; + + inline quint64 qbswap(quint64 source) + { + return 0 + | ((source & quint64(0x00000000000000ffLL)) << 56) + | ((source & quint64(0x000000000000ff00LL)) << 40) + | ((source & quint64(0x0000000000ff0000LL)) << 24) + | ((source & quint64(0x00000000ff000000LL)) << 8) + | ((source & quint64(0x000000ff00000000LL)) >> 8) + | ((source & quint64(0x0000ff0000000000LL)) >> 24) + | ((source & quint64(0x00ff000000000000LL)) >> 40) + | ((source & quint64(0xff00000000000000LL)) >> 56); + } + + int main() + { + quint64 v = strtoull("4433ffeeddccbb00", NULL, 16); + printf("%lld\n", v); + + const string string64bitInt = "4433ffeeddccbb00"; + stringstream s(string64bitInt); + quint64 int64bitInt = 0; + 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; + } + else + { + cout << "Succeeded!" << endl; + } + + return 0; + } + ''' + self.do_run(src, '''4914553019779824384 +1 +2 +bbccddeeff3344 +4433ffeeddccbb00 +4433ffeeddccbb00 +Succeeded! ''') def test_sha1(self): @@ -1193,6 +1276,7 @@ c5,de,15,8a self.do_run(open(path_from_root('tests', 'cube2md5.cpp')).read(), open(path_from_root('tests', 'cube2md5.ok')).read()) def test_cube2hash(self): + try: old_chunk_size = os.environ.get('EMSCRIPT_MAX_CHUNK_SIZE') or '' os.environ['EMSCRIPT_MAX_CHUNK_SIZE'] = '1' # test splitting out each function to a chunk in emscripten.py (21 functions here) @@ -1322,7 +1406,7 @@ c5,de,15,8a # corrections otherwise if Settings.USE_TYPED_ARRAYS == 2: Settings.CORRECT_SIGNS = 0 - Settings.CHECK_SIGNS = 1 + Settings.CHECK_SIGNS = 1 if not Settings.ASM_JS else 0 else: Settings.CORRECT_SIGNS = 1 Settings.CHECK_SIGNS = 0 @@ -1679,15 +1763,14 @@ c5,de,15,8a return 0; } ''' - for named, expected in [(0, 100), (1, 0)]: + for named in (0, 1): 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\n', ['wowie', 'too', '74']) if self.emcc_args == []: gen = open(self.in_dir('src.cpp.o.js')).read() - count = gen.count('GLOBAL_BASE') - assert count == expected - print ' counted' + assert ('var __str1;' in gen) == named + assert (gen.count('ALLOC_NONE') < 8) == named def test_strcmp_uni(self): src = ''' @@ -1998,6 +2081,8 @@ c5,de,15,8a self.do_run(src, 'Assertion failed: 1 == false') def test_longjmp(self): + if Settings.ASM_JS: return self.skip('asm does not support longjmp') + src = r''' #include <stdio.h> #include <setjmp.h> @@ -2033,6 +2118,8 @@ c5,de,15,8a self.do_run(src, 'second\nmain: 0\n') def test_longjmp2(self): + if Settings.ASM_JS: return self.skip('asm does not support longjmp') + src = r''' #include <setjmp.h> #include <stdio.h> @@ -2079,6 +2166,8 @@ Exiting stack_manipulate_func, level: 0 ''') def test_longjmp3(self): + if Settings.ASM_JS: return self.skip('asm does not support longjmp') + src = r''' #include <setjmp.h> #include <stdio.h> @@ -2131,6 +2220,8 @@ Exiting setjmp function, level: 0 ''') def test_longjmp4(self): + if Settings.ASM_JS: return self.skip('asm does not support longjmp') + src = r''' #include <setjmp.h> #include <stdio.h> @@ -2275,7 +2366,6 @@ Exception execution path of first function! 1 if '-O2' in self.emcc_args: self.emcc_args += ['--closure', '1'] # Use closure here for some additional coverage - Settings.EXCEPTION_DEBUG = 0 # Messes up expected output. Settings.DISABLE_EXCEPTION_CATCHING = 0 src = r''' @@ -2315,14 +2405,12 @@ Exception execution path of first function! 1 def test_typed_exceptions(self): Settings.DISABLE_EXCEPTION_CATCHING = 0 Settings.SAFE_HEAP = 0 # Throwing null will cause an ignorable null pointer access. - Settings.EXCEPTION_DEBUG = 0 # Messes up expected output. src = open(path_from_root('tests', 'exceptions', 'typed.cpp'), 'r').read() expected = open(path_from_root('tests', 'exceptions', 'output.txt'), 'r').read() self.do_run(src, expected) def test_multiexception(self): Settings.DISABLE_EXCEPTION_CATCHING = 0 - Settings.EXCEPTION_DEBUG = 0 # Messes up expected output. src = r''' #include <stdio.h> @@ -2383,6 +2471,53 @@ setjmp exception execution path, level: 0, prev_jmp: -1 Exiting setjmp function, level: 0, prev_jmp: -1 ''') + def test_exit_stack(self): + if self.emcc_args is None: return self.skip('requires emcc') + if Settings.ASM_JS: return self.skip('uses report_stack without exporting') + + Settings.CATCH_EXIT_CODE = 1 + + src = r''' + #include <stdio.h> + #include <stdlib.h> + + extern "C" { + extern void report_stack(int x); + } + + char moar() { + char temp[125]; + for (int i = 0; i < 125; i++) temp[i] = i*i; + for (int i = 1; i < 125; i++) temp[i] += temp[i-1]/2; + if (temp[100] != 99) exit(1); + return temp[120]; + } + + int main(int argc, char *argv[]) { + report_stack((int)alloca(4)); + printf("*%d*\n", moar()); + return 0; + } + ''' + + open(os.path.join(self.get_dir(), 'pre.js'), 'w').write(''' + var initialStack = -1; + var _report_stack = function(x) { + Module.print('reported'); + initialStack = x; + } + var Module = { + postRun: function() { + Module.print('postRun'); + assert(initialStack == STACKTOP, [initialStack, STACKTOP]); + Module.print('ok.'); + } + }; + ''') + + self.emcc_args += ['--pre-js', 'pre.js'] + self.do_run(src, '''reported\npostRun\nok.\nExit Status: 1\n''') + def test_class(self): src = ''' #include <stdio.h> @@ -2491,6 +2626,7 @@ Exiting setjmp function, level: 0, prev_jmp: -1 def test_segfault(self): if self.emcc_args is None: return self.skip('SAFE_HEAP without ta2 means we check types too, which hide segfaults') + if Settings.ASM_JS: return self.skip('asm does not support safe heap') Settings.SAFE_HEAP = 1 @@ -3027,7 +3163,7 @@ Exiting setjmp function, level: 0, prev_jmp: -1 #include "emscripten.h" extern "C" { - void EMSCRIPTEN_KEEPALIVE save_me_aimee() { printf("mann\n"); } + void save_me_aimee() { printf("mann\n"); } } int main() { @@ -3035,7 +3171,7 @@ Exiting setjmp function, level: 0, prev_jmp: -1 emscripten_run_script("Module.print('hello world' + '!')"); printf("*%d*\n", emscripten_run_script_int("5*20")); printf("*%s*\n", emscripten_run_script_string("'five'+'six'")); - emscripten_run_script("_save_me_aimee()"); + emscripten_run_script("Module['_save_me_aimee']()"); return 0; } ''' @@ -3045,7 +3181,7 @@ def process(filename): src = open(filename, 'r').read() # TODO: restore this (see comment in emscripten.h) assert '// hello from the source' in src ''' - + Settings.EXPORTED_FUNCTIONS = ['_main', '_save_me_aimee'] self.do_run(src, 'hello world!\n*100*\n*fivesix*\nmann\n', post_build=check) def test_inlinejs(self): @@ -3069,6 +3205,7 @@ def process(filename): def test_memorygrowth(self): if Settings.USE_TYPED_ARRAYS == 0: return self.skip('memory growth is only supported with typed arrays') + if Settings.ASM_JS: return self.skip('asm does not support memory growth yet') # With typed arrays in particular, it is dangerous to use more memory than TOTAL_MEMORY, # since we then need to enlarge the heap(s). @@ -3259,6 +3396,7 @@ def process(filename): def test_varargs(self): if Settings.QUANTUM_SIZE == 1: return self.skip('FIXME: Add support for this') + if Settings.ASM_JS: return self.skip('varargs by function pointer not yet supported') src = ''' #include <stdio.h> @@ -3499,7 +3637,7 @@ The current type of b is: 9 Building.link([supp_name + '.o', main_name + '.o'], all_name) # 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() + 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' @@ -3605,6 +3743,25 @@ The current type of b is: 9 extra_emscripten_args=['-H', 'libc/time.h']) #extra_emscripten_args=['-H', 'libc/fcntl.h,libc/sys/unistd.h,poll.h,libc/math.h,libc/langinfo.h,libc/time.h']) + def test_timeb(self): + # Confirms they are called in reverse order + src = r''' + #include <stdio.h> + #include <assert.h> + #include <sys/timeb.h> + + int main() { + timeb tb; + tb.timezone = 1; + printf("*%d\n", ftime(&tb)); + assert(tb.time > 10000); + assert(tb.timezone == 0); + assert(tb.dstflag == 0); + return 0; + } + ''' + self.do_run(src, '*0\n') + def test_intentional_fault(self): # Some programs intentionally segfault themselves, we should compile that into a throw src = r''' @@ -3912,13 +4069,14 @@ The current type of b is: 9 def test_runtimelink(self): 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.NAMED_GLOBALS == 0: return self.skip('dlopen cannot work without named globals, TODO') + if Settings.ASM_JS: return self.skip('asm does not support runtime linking') main, supp = self.setup_runtimelink_test() self.banned_js_engines = [NODE_JS] # node's global scope behaves differently than everything else, needs investigation FIXME Settings.LINKABLE = 1 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')) @@ -3928,6 +4086,9 @@ The current type of b is: 9 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') + + Settings.NAMED_GLOBALS = 1 Settings.LINKABLE = 1 lib_src = ''' @@ -3979,7 +4140,10 @@ def process(filename): post_build=add_pre_run_and_checks) def test_dlfcn_qsort(self): + if Settings.ASM_JS: return self.skip('TODO: dlopen in asm') + Settings.LINKABLE = 1 + Settings.NAMED_GLOBALS = 1 if Settings.USE_TYPED_ARRAYS == 2: Settings.CORRECT_SIGNS = 1 # Needed for unsafe optimizations @@ -4071,10 +4235,11 @@ def process(filename): post_build=add_pre_run_and_checks) 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.NAMED_GLOBALS == 0: return self.skip('dlopen cannot work without named globals, TODO') Settings.LINKABLE = 1 + Settings.NAMED_GLOBALS = 1 lib_src = ''' #include <stdio.h> @@ -4174,10 +4339,12 @@ def process(filename): post_build=add_pre_run_and_checks) def test_dlfcn_alias(self): + if Settings.ASM_JS: return self.skip('TODO: dlopen in asm') + Settings.LINKABLE = 1 + Settings.NAMED_GLOBALS = 1 if Building.LLVM_OPTS == 2: return self.skip('LLVM LTO will optimize away stuff we expect from the shared library') - if Settings.NAMED_GLOBALS == 0: return self.skip('dlopen cannot work without named globals, TODO') lib_src = r''' #include <stdio.h> @@ -4229,7 +4396,10 @@ def process(filename): Settings.INCLUDE_FULL_LIBRARY = 0 def test_dlfcn_varargs(self): + if Settings.ASM_JS: return self.skip('TODO: dlopen in asm') + 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') @@ -4895,7 +5065,7 @@ def process(filename): other.close() src = open(path_from_root('tests', 'files.cpp'), 'r').read() - self.do_run(src, 'size: 7\ndata: 100,-56,50,25,10,77,123\nloop: 100 -56 50 25 10 77 123 \ninput:hi there!\ntexto\ntexte\n$\n5 : 10,30,20,11,88\nother=some data.\nseeked=me da.\nseeked=ata.\nseeked=ta.\nfscanfed: 10 - hello\n', + self.do_run(src, 'size: 7\ndata: 100,-56,50,25,10,77,123\nloop: 100 -56 50 25 10 77 123 \ninput:hi there!\ntexto\ntexte\n$\n5 : 10,30,20,11,88\nother=some data.\nseeked=me da.\nseeked=ata.\nseeked=ta.\nfscanfed: 10 - hello\nok.\n', post_build=post, extra_emscripten_args=['-H', 'libc/fcntl.h']) def test_files_m(self): @@ -5306,6 +5476,8 @@ def process(filename): def test_utf(self): self.banned_js_engines = [SPIDERMONKEY_ENGINE] # only node handles utf well + Settings.EXPORTED_FUNCTIONS = ['_main', '_malloc'] + src = r''' #include <stdio.h> #include <emscripten.h> @@ -5358,6 +5530,7 @@ def process(filename): } ''' for linkable in [0, 1]: + print linkable Settings.LINKABLE = linkable # regression check for issue #273 self.do_run(src, "1 2 3") @@ -5937,9 +6110,10 @@ int main(int argc, char **argv) { def test_dlmalloc(self): if self.emcc_args is None: self.emcc_args = [] # dlmalloc auto-inclusion is only done if we use emcc + self.banned_js_engines = [NODE_JS] # slower, and fail on 64-bit Settings.CORRECT_SIGNS = 2 Settings.CORRECT_SIGNS_LINES = ['src.cpp:' + str(i+4) for i in [4816, 4191, 4246, 4199, 4205, 4235, 4227]] - Settings.TOTAL_MEMORY = 100*1024*1024 # needed with typed arrays + Settings.TOTAL_MEMORY = 128*1024*1024 # needed with typed arrays src = open(path_from_root('system', 'lib', 'dlmalloc.c'), 'r').read() + '\n\n\n' + open(path_from_root('tests', 'dlmalloc_test.c'), 'r').read() self.do_run(src, '*1,0*', ['200', '1']) @@ -5954,7 +6128,7 @@ int main(int argc, char **argv) { # emcc should build in dlmalloc automatically, and do all the sign correction etc. for it try_delete(os.path.join(self.get_dir(), 'src.cpp.o.js')) - output = Popen(['python', EMCC, path_from_root('tests', 'dlmalloc_test.c'), '-s', 'TOTAL_MEMORY=100000000', + output = Popen([PYTHON, EMCC, path_from_root('tests', 'dlmalloc_test.c'), '-s', 'TOTAL_MEMORY=' + str(128*1024*1024), '-o', os.path.join(self.get_dir(), 'src.cpp.o.js')], stdout=PIPE, stderr=self.stderr_redirect).communicate() self.do_run('x', '*1,0*', ['200', '1'], no_build=True) @@ -6139,9 +6313,11 @@ void*:16 } ''' self.do_run(src, '*10,22*') - + def test_mmap(self): - Settings.TOTAL_MEMORY = 100*1024*1024 + self.banned_js_engines = [NODE_JS] # slower, and fail on 64-bit + + Settings.TOTAL_MEMORY = 128*1024*1024 src = ''' #include <stdio.h> @@ -6149,13 +6325,20 @@ void*:16 #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, + MAP_SHARED | MAP_ANON, -1, 0); + assert(((int)map) % 4096 == 0); // aligned + assert(munmap(map, 5000) == 0); + } + 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++) { @@ -6175,6 +6358,33 @@ void*:16 self.do_run(src, 'hello,world') self.do_run(src, 'hello,world', force_c=True) + def test_mmap_file(self): + if self.emcc_args is None: return self.skip('requires emcc') + self.emcc_args += ['--embed-file', 'data.dat'] + + open(self.in_dir('data.dat'), 'w').write('data from the file ' + ('.' * 9000)) + + src = r''' + #include <stdio.h> + #include <sys/mman.h> + + int main() { + printf("*\n"); + FILE *f = fopen("data.dat", "r"); + char *m; + m = (char*)mmap(NULL, 9000, PROT_READ, MAP_PRIVATE, fileno(f), 0); + for (int i = 0; i < 20; i++) putchar(m[i]); + munmap(m, 9000); + printf("\n"); + m = (char*)mmap(NULL, 9000, PROT_READ, MAP_PRIVATE, fileno(f), 5); + for (int i = 0; i < 20; i++) putchar(m[i]); + munmap(m, 9000); + printf("\n*\n"); + return 0; + } + ''' + self.do_run(src, '*\ndata from the file .\nfrom the file ......\n*\n') + def test_cubescript(self): 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 @@ -6192,7 +6402,7 @@ void*:16 self.do_run(path_from_root('tests', 'cubescript'), '*\nTemp is 33\n9\n5\nhello, everyone\n*', main_file='command.cpp') def test_gcc_unmangler(self): - Settings.NAMED_GLOBALS = 0 # test coverage for this + Settings.NAMED_GLOBALS = 1 # test coverage for this Building.COMPILER_TEST_OPTS = ['-I' + path_from_root('third_party')] @@ -6238,6 +6448,7 @@ void*:16 def test_freetype(self): if Settings.QUANTUM_SIZE == 1: return self.skip('TODO: Figure out and try to fix') + if Settings.ASM_JS: return self.skip('asm does not support longjmp') if Settings.CORRECT_SIGNS == 0: Settings.CORRECT_SIGNS = 1 # Not sure why, but needed @@ -6294,16 +6505,13 @@ def process(filename): if self.emcc_args is None: return self.skip('Very slow without ta2, and we would also need to include dlmalloc manually without emcc') if Settings.QUANTUM_SIZE == 1: return self.skip('TODO FIXME') - pgo_data = read_pgo_data(path_from_root('tests', 'sqlite', 'sqlite-autooptimize.fails.txt')) - Settings.CORRECT_SIGNS = 1 # XXX: in default, we fail with 2 here, even though the pgo_data should be correct (and works in s_0_0). Investigate this. - Settings.CORRECT_SIGNS_LINES = pgo_data['signs_lines'] Settings.CORRECT_OVERFLOWS = 0 Settings.CORRECT_ROUNDINGS = 0 if self.emcc_args is None: Settings.SAFE_HEAP = 0 # uses time.h to set random bytes, other stuff Settings.DISABLE_EXCEPTION_CATCHING = 1 Settings.FAST_MEMORY = 4*1024*1024 - Settings.EXPORTED_FUNCTIONS = ['_main', '_sqlite3_open', '_sqlite3_close', '_sqlite3_exec', '_sqlite3_free', '_callback']; + Settings.EXPORTED_FUNCTIONS += ['_sqlite3_open', '_sqlite3_close', '_sqlite3_exec', '_sqlite3_free', '_callback']; self.do_run(r''' #define SQLITE_DISABLE_LFS @@ -6349,6 +6557,7 @@ 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 @@ -6519,7 +6728,7 @@ def process(filename): 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 = ['_main', '_PyRun_SimpleStringFlags'] # for the demo + Settings.EXPORTED_FUNCTIONS += ['_PyRun_SimpleStringFlags'] # for the demo self.do_ll_run(path_from_root('tests', 'python', 'python.small.bc'), 'hello python world!\n[0, 2, 4, 6]\n5\n22\n5.470000', @@ -6557,6 +6766,9 @@ def process(filename): if '_ta2' in shortname and not Settings.USE_TYPED_ARRAYS == 2: print self.skip('case "%s" only relevant for ta2' % shortname) continue + if '_noasm' in shortname and Settings.ASM_JS: + print self.skip('case "%s" not relevant for asm.js' % shortname) + continue print >> sys.stderr, "Testing case '%s'..." % shortname output_file = path_from_root('tests', 'cases', shortname + '.txt') if Settings.QUANTUM_SIZE == 1: @@ -6580,7 +6792,7 @@ def process(filename): # Autodebug the code def do_autodebug(self, filename): - output = Popen(['python', AUTODEBUGGER, filename+'.o.ll', filename+'.o.ll.ll'], stdout=PIPE, stderr=self.stderr_redirect).communicate()[0] + output = Popen([PYTHON, AUTODEBUGGER, filename+'.o.ll', filename+'.o.ll.ll'], stdout=PIPE, stderr=self.stderr_redirect).communicate()[0] assert 'Success.' in output, output self.prep_ll_run(filename, filename+'.o.ll.ll', force_recompile=True) # rebuild .bc # TODO: use code in do_autodebug_post for this @@ -6592,7 +6804,7 @@ def process(filename): return True print 'Autodebugging during post time' delattr(self, 'post') - output = Popen(['python', AUTODEBUGGER, filename+'.o.ll', filename+'.o.ll.ll'], stdout=PIPE, stderr=self.stderr_redirect).communicate()[0] + output = Popen([PYTHON, AUTODEBUGGER, filename+'.o.ll', filename+'.o.ll.ll'], stdout=PIPE, stderr=self.stderr_redirect).communicate()[0] assert 'Success.' in output, output shutil.copyfile(filename + '.o.ll.ll', filename + '.o.ll') Building.llvm_as(filename) @@ -6630,6 +6842,8 @@ def process(filename): self.do_run(src, '''AD:-1,1''', build_ll_hook=self.do_autodebug) def test_profiling(self): + if Settings.ASM_JS: return self.skip('asm does not support profiling') + src = ''' #include <emscripten.h> #include <unistd.h> @@ -6671,18 +6885,15 @@ Block 0: ''', post_build=post1) src = r''' #include <stdio.h> - // Optimizations might wipe out our functions without this - #define KEEPALIVE __attribute__((used)) - extern "C" { - int KEEPALIVE get_int() { return 5; } - float KEEPALIVE get_float() { return 3.14; } - char * KEEPALIVE get_string() { return "hello world"; } - void KEEPALIVE print_int(int x) { printf("%d\n", x); } - void KEEPALIVE print_float(float x) { printf("%.2f\n", x); } - void KEEPALIVE print_string(char *x) { printf("%s\n", x); } - int KEEPALIVE multi(int x, float y, int z, char *str) { if (x) puts(str); return (x+y)*z; } - int * KEEPALIVE pointer(int *in) { printf("%d\n", *in); static int ret = 21; return &ret; } + int get_int() { return 5; } + float get_float() { return 3.14; } + char * get_string() { return "hello world"; } + void print_int(int x) { printf("%d\n", x); } + void print_float(float x) { printf("%.2f\n", x); } + void print_string(char *x) { printf("%s\n", x); } + int multi(int x, float y, int z, char *str) { if (x) puts(str); return (x+y)*z; } + int * pointer(int *in) { printf("%d\n", *in); static int ret = 21; return &ret; } } int main(int argc, char **argv) { @@ -6734,11 +6945,13 @@ def process(filename): open(filename, 'w').write(src) ''' - Settings.EXPORTED_FUNCTIONS = ['_get_int', '_get_float', '_get_string', '_print_int', '_print_float', '_print_string', '_multi', '_pointer', '_malloc'] + Settings.EXPORTED_FUNCTIONS += ['_get_int', '_get_float', '_get_string', '_print_int', '_print_float', '_print_string', '_multi', '_pointer', '_malloc'] self.do_run(src, '*\nnumber,5\nnumber,3.14\nstring,hello world\n12\nundefined\n14.56\nundefined\ncheez\nundefined\narr-ay\nundefined\nmore\nnumber,10\n650\nnumber,21\n*\natr\n10\nbret\n53\n*\nstack is ok.\n', post_build=post) def test_scriptaclass(self): + if Settings.ASM_JS: return self.skip('asm does not bindings generator yet') + header_filename = os.path.join(self.get_dir(), 'header.h') header = ''' struct ScriptMe { @@ -6773,8 +6986,8 @@ def process(filename): ''' post = ''' def process(filename): - Popen(['python', DEMANGLER, filename], stdout=open(filename + '.tmp', 'w')).communicate() - Popen(['python', NAMESPACER, filename, filename + '.tmp'], stdout=open(filename + '.tmp2', 'w')).communicate() + Popen([PYTHON, DEMANGLER, filename], stdout=open(filename + '.tmp', 'w')).communicate() + Popen([PYTHON, NAMESPACER, filename, filename + '.tmp'], stdout=open(filename + '.tmp2', 'w')).communicate() src = open(filename, 'r').read().replace( '// {{MODULE_ADDITIONS}', 'Module["_"] = ' + open(filename + '.tmp2', 'r').read().replace('var ModuleNames = ', '').rstrip() + ';\n\n' + script_src + '\n\n' + @@ -6829,7 +7042,7 @@ def process(filename): open(header_filename, 'w').write(header) basename = os.path.join(self.get_dir(), 'bindingtest') - output = Popen(['python', BINDINGS_GENERATOR, basename, header_filename], stdout=PIPE, stderr=self.stderr_redirect).communicate()[0] + output = Popen([PYTHON, BINDINGS_GENERATOR, basename, header_filename], stdout=PIPE, stderr=self.stderr_redirect).communicate()[0] #print output assert 'Traceback' not in output, 'Failure in binding generation: ' + output @@ -6983,6 +7196,8 @@ Child2:9 ''', post_build=[post2, post3]) def test_scriptaclass_2(self): + if Settings.ASM_JS: return self.skip('asm does not bindings generator yet') + header_filename = os.path.join(self.get_dir(), 'header.h') header = ''' #include <stdio.h> @@ -7002,7 +7217,7 @@ Child2:9 open(header_filename, 'w').write(header) basename = os.path.join(self.get_dir(), 'bindingtest') - output = Popen(['python', BINDINGS_GENERATOR, basename, header_filename], stdout=PIPE, stderr=self.stderr_redirect).communicate()[0] + output = Popen([PYTHON, BINDINGS_GENERATOR, basename, header_filename], stdout=PIPE, stderr=self.stderr_redirect).communicate()[0] #print output assert 'Traceback' not in output, 'Failure in binding generation: ' + output @@ -7186,6 +7401,8 @@ def process(filename): assert 'Assertion failed: Load-store consistency assumption failure!' in str(e), str(e) def test_check_overflow(self): + if Settings.ASM_JS: return self.skip('asm always corrects, and cannot check') + Settings.CHECK_OVERFLOWS = 1 Settings.CORRECT_OVERFLOWS = 0 @@ -7240,6 +7457,8 @@ def process(filename): assert 'Assertion failed' in str(e), str(e) def test_linespecific(self): + if Settings.ASM_JS: return self.skip('asm always has corrections on') + if '-g' not in Building.COMPILER_TEST_OPTS: Building.COMPILER_TEST_OPTS.append('-g') if self.emcc_args: self.emcc_args += ['--llvm-opts', '0'] # llvm full opts make the expected failures here not happen @@ -7397,6 +7616,8 @@ def process(filename): Settings.CORRECT_SIGNS = 0 def test_pgo(self): + if Settings.ASM_JS: return self.skip('asm does not support pgo') + if '-g' not in Building.COMPILER_TEST_OPTS: Building.COMPILER_TEST_OPTS.append('-g') Settings.PGO = Settings.CHECK_OVERFLOWS = Settings.CORRECT_OVERFLOWS = Settings.CHECK_SIGNS = Settings.CORRECT_SIGNS = 1 @@ -7472,6 +7693,7 @@ def process(filename): def test_gc(self): if self.emcc_args == None: return self.skip('needs ta2') + if Settings.ASM_JS: return self.skip('asm cannot support generic function table') Settings.GC_SUPPORT = 1 @@ -7654,6 +7876,10 @@ TT = %s # Make one run with -O2, but without closure (we enable closure in specific tests, otherwise on everything it is too slow) exec('o2 = make_run("o2", compiler=CLANG, emcc_args=["-O2", "--closure", "0"])') + # asm.js + #exec('asm = make_run("asm", compiler=CLANG, emcc_args=["-O0", "--closure", "0", "-s", "ASM_JS=1"])') + exec('asm2 = make_run("asm2", compiler=CLANG, emcc_args=["-O2", "--closure", "0", "-s", "ASM_JS=1"])') + # Make custom runs with various options for compiler, quantum, embetter, typed_arrays, llvm_opts in [ (CLANG, 1, 1, 0, 0), @@ -7677,7 +7903,7 @@ TT = %s suffix = '.c' if compiler == EMCC else '.cpp' # --version - output = Popen(['python', compiler, '--version'], stdout=PIPE, stderr=PIPE).communicate() + output = Popen([PYTHON, compiler, '--version'], stdout=PIPE, stderr=PIPE).communicate() self.assertContained('''emcc (Emscripten GCC-like replacement) 2.0 Copyright (C) 2012 the Emscripten authors. This is free and open source software under the MIT license. @@ -7685,11 +7911,11 @@ There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR P ''', output[0].replace('\r', ''), output[1].replace('\r', '')) # -v, without input files - output = Popen(['python', compiler, '-v'], stdout=PIPE, stderr=PIPE).communicate() + output = Popen([PYTHON, compiler, '-v'], stdout=PIPE, stderr=PIPE).communicate() self.assertContained('''clang version''', output[1].replace('\r', ''), output[1].replace('\r', '')) # --help - output = Popen(['python', compiler, '--help'], stdout=PIPE, stderr=PIPE).communicate() + output = Popen([PYTHON, compiler, '--help'], stdout=PIPE, stderr=PIPE).communicate() self.assertContained('''%s [options] file... Most normal gcc/g++ options will work, for example: @@ -7702,7 +7928,7 @@ Options that are modified or new in %s include: # emcc src.cpp ==> writes a.out.js self.clear() - output = Popen(['python', compiler, path_from_root('tests', 'hello_world' + suffix)], stdout=PIPE, stderr=PIPE).communicate() + output = Popen([PYTHON, compiler, path_from_root('tests', 'hello_world' + suffix)], stdout=PIPE, stderr=PIPE).communicate() assert len(output[0]) == 0, output[0] assert os.path.exists('a.out.js'), '\n'.join(output) self.assertContained('hello, world!', run_js('a.out.js')) @@ -7710,7 +7936,7 @@ Options that are modified or new in %s include: # properly report source code errors, and stop there self.clear() assert not os.path.exists('a.out.js') - process = Popen(['python', compiler, path_from_root('tests', 'hello_world_error' + suffix)], stdout=PIPE, stderr=PIPE) + process = Popen([PYTHON, compiler, path_from_root('tests', 'hello_world_error' + suffix)], stdout=PIPE, stderr=PIPE) output = process.communicate() assert not os.path.exists('a.out.js'), 'compilation failed, so no output file is expected' assert len(output[0]) == 0, output[0] @@ -7718,38 +7944,38 @@ Options that are modified or new in %s include: self.assertNotContained('IOError', output[1]) # no python stack self.assertNotContained('Traceback', output[1]) # no python stack self.assertContained('error: invalid preprocessing directive', output[1]) - self.assertContained("error: use of undeclared identifier 'cheez", output[1]) - self.assertContained('2 errors generated', output[1]) - assert 'emcc: compiler frontend failed to generate LLVM bitcode, halting' in output[1].split('2 errors generated.')[1] + self.assertContained(["error: use of undeclared identifier 'cheez", "error: unknown type name 'cheez'"], output[1]) + self.assertContained('errors generated', output[1]) + assert 'emcc: compiler frontend failed to generate LLVM bitcode, halting' in output[1].split('errors generated.')[1] # emcc src.cpp -c and emcc src.cpp -o src.[o|bc] ==> should give a .bc file # regression check: -o js should create "js", with bitcode content for args in [['-c'], ['-o', 'src.o'], ['-o', 'src.bc'], ['-o', 'src.so'], ['-o', 'js']]: target = args[1] if len(args) == 2 else 'hello_world.o' self.clear() - Popen(['python', compiler, path_from_root('tests', 'hello_world' + suffix)] + args, stdout=PIPE, stderr=PIPE).communicate() + Popen([PYTHON, compiler, path_from_root('tests', 'hello_world' + suffix)] + args, stdout=PIPE, stderr=PIPE).communicate() syms = Building.llvm_nm(target) assert len(syms.defs) == 1 and 'main' in syms.defs, 'Failed to generate valid bitcode' if target == 'js': # make sure emcc can recognize the target as a bitcode file shutil.move(target, target + '.bc') target += '.bc' - output = Popen(['python', compiler, target, '-o', target + '.js'], stdout = PIPE, stderr = PIPE).communicate() + output = Popen([PYTHON, compiler, target, '-o', target + '.js'], stdout = PIPE, stderr = PIPE).communicate() assert len(output[0]) == 0, output[0] assert os.path.exists(target + '.js'), 'Expected %s to exist since args are %s : %s' % (target + '.js', str(args), '\n'.join(output)) self.assertContained('hello, world!', run_js(target + '.js')) # handle singleton archives self.clear() - Popen(['python', compiler, path_from_root('tests', 'hello_world' + suffix), '-o', 'a.bc'], stdout=PIPE, stderr=PIPE).communicate() + |