aboutsummaryrefslogtreecommitdiff
path: root/tests/runner.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/runner.py')
-rwxr-xr-xtests/runner.py718
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()
+