aboutsummaryrefslogtreecommitdiff
path: root/tests/runner.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/runner.py')
-rw-r--r--tests/runner.py214
1 files changed, 145 insertions, 69 deletions
diff --git a/tests/runner.py b/tests/runner.py
index 3b5b03f2..f26ac370 100644
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -35,6 +35,7 @@ class RunnerCore(unittest.TestCase):
save_JS = 0
def setUp(self):
+ Settings.reset()
self.banned_js_engines = []
if not self.save_dir:
dirname = tempfile.mkdtemp(prefix="ems_" + self.__class__.__name__ + "_", dir=TEMP_DIR)
@@ -211,6 +212,8 @@ class RunnerCore(unittest.TestCase):
###################################################################################################
+sys.argv = map(lambda arg: arg if not arg.startswith('test_') else 'default.' + arg, sys.argv)
+
if 'benchmark' not in str(sys.argv):
# Tests
@@ -509,6 +512,36 @@ if 'benchmark' not in str(sys.argv):
def test_unaligned(self):
if Settings.QUANTUM_SIZE == 1: return self.skip('No meaning to unaligned addresses in q1')
+
+ src = r'''
+ #include<stdio.h>
+
+ struct S {
+ double x;
+ int y;
+ };
+
+ int main() {
+ // the 64-bit value here will not always be 8-byte aligned
+ S s[3] = { {0x12a751f430142, 22}, {0x17a5c85bad144, 98}, {1, 1}};
+ printf("*%d : %d : %d\n", sizeof(S), ((unsigned int)&s[0]) % 8 != ((unsigned int)&s[1]) % 8,
+ ((unsigned int)&s[1]) - ((unsigned int)&s[0]));
+ s[0].x++;
+ s[0].y++;
+ s[1].x++;
+ s[1].y++;
+ printf("%.1f,%d,%.1f,%d\n", s[0].x, s[0].y, s[1].x, s[1].y);
+ return 0;
+ }
+ '''
+
+ # TODO: A version of this with int64s as well
+ self.do_run(src, '*12 : 1 : 12\n328157500735811.0,23,416012775903557.0,99\n')
+
+ return # TODO: continue to the next part here
+
+ # Test for undefined behavior in C. This is not legitimate code, but does exist
+
if Settings.USE_TYPED_ARRAYS != 2: return self.skip('No meaning to unaligned addresses without t2')
src = r'''
@@ -693,7 +726,7 @@ if 'benchmark' not in str(sys.argv):
#include <cmath>
int main()
{
- printf("*%.2f,%.2f,%f,%f", M_PI, -M_PI, 1/0.0, -1/0.0);
+ 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);
@@ -706,9 +739,11 @@ if 'benchmark' not in str(sys.argv):
return 0;
}
'''
- self.do_run(src, '*3.14,-3.14,inf,-inf,0,0,0,1,0,1,1,0*')
+ self.do_run(src, '*3.14,-3.14,1,0,0,0,1,0,1,1,0*')
def test_math_hyperbolic(self):
+ if Settings.DOUBLE_MODE == 1: return self.skip('store-load doubles will make NaNs into actual numbers')
+
src = open(path_from_root('tests', 'hyperbolic', 'src.c'), 'r').read()
expected = open(path_from_root('tests', 'hyperbolic', 'output.txt'), 'r').read()
self.do_run(src, expected)
@@ -1578,13 +1613,14 @@ if 'benchmark' not in str(sys.argv):
def test_emscripten_api(self):
#if Settings.MICRO_OPTS or Settings.RELOOP or Building.LLVM_OPTS: return self.skip('FIXME')
- src = '''
+ src = r'''
#include <stdio.h>
#include "emscripten.h"
int main() {
// EMSCRIPTEN_COMMENT("hello from the source");
emscripten_run_script("print('hello world' + '!')");
+ printf("*%d*\n", emscripten_run_script_int("5*20"));
return 0;
}
'''
@@ -1593,7 +1629,47 @@ if 'benchmark' not in str(sys.argv):
src = open(filename, 'r').read()
# TODO: restore this (see comment in emscripten.h) assert '// hello from the source' in src
- self.do_run(src, 'hello world!', post_build=check)
+ self.do_run(src, 'hello world!\n*100*', post_build=check)
+
+ def test_memorygrowth(self):
+ # With typed arrays in particular, it is dangerous to use more memory than TOTAL_MEMORY,
+ # since we then need to enlarge the heap(s).
+ src = r'''
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <assert.h>
+ #include "emscripten.h"
+
+ int main()
+ {
+ char *buf1 = (char*)malloc(100);
+ char *data1 = "hello";
+ memcpy(buf1, data1, strlen(data1)+1);
+
+ float *buf2 = (float*)malloc(100);
+ float pie = 4.955;
+ memcpy(buf2, &pie, sizeof(float));
+
+ printf("*pre: %s,%.3f*\n", buf1, buf2[0]);
+
+ int totalMemory = emscripten_run_script_int("TOTAL_MEMORY");
+ char *buf3 = (char*)malloc(totalMemory+1);
+ char *buf4 = (char*)malloc(100);
+ float *buf5 = (float*)malloc(100);
+ //printf("totalMemory: %d bufs: %d,%d,%d,%d,%d\n", totalMemory, buf1, buf2, buf3, buf4, buf5);
+ assert((int)buf4 > (int)totalMemory && (int)buf5 > (int)totalMemory);
+
+ printf("*%s,%.3f*\n", buf1, buf2[0]); // the old heap data should still be there
+
+ memcpy(buf4, buf1, strlen(data1)+1);
+ memcpy(buf5, buf2, sizeof(float));
+ printf("*%s,%.3f*\n", buf4, buf5[0]); // and the new heap space should work too
+
+ return 0;
+ }
+ '''
+ self.do_run(src, '*pre: hello,4.955*\n*hello,4.955*\n*hello,4.955*')
def test_ssr(self): # struct self-ref
src = '''
@@ -1964,7 +2040,6 @@ if 'benchmark' not in str(sys.argv):
def test_time(self):
# XXX Not sure what the right output is here. Looks like the test started failing with daylight savings changes. Modified it to pass again.
- if Settings.USE_TYPED_ARRAYS == 2: return self.skip('Typed arrays = 2 truncate i64s')
src = open(path_from_root('tests', 'time', 'src.c'), 'r').read()
expected = open(path_from_root('tests', 'time', 'output.txt'), 'r').read()
self.do_run(src, expected,
@@ -2610,7 +2685,6 @@ if 'benchmark' not in str(sys.argv):
self.do_run(src, re.sub(r'(^|\n)\s+', r'\1', expected))
def test_strtod(self):
- if Settings.USE_TYPED_ARRAYS == 2: return self.skip('Typed arrays = 2 truncate doubles')
src = r'''
#include <stdio.h>
#include <stdlib.h>
@@ -2665,18 +2739,16 @@ if 'benchmark' not in str(sys.argv):
self.do_run(src, re.sub(r'\n\s+', '\n', expected))
def test_parseInt(self):
- if Settings.USE_TYPED_ARRAYS != 0: return self.skip('Typed arrays truncate i64')
+ Settings.I64_MODE = 1 # Necessary to prevent i64s being truncated into i32s, but we do still get doubling
+ # FIXME: The output here is wrong, due to double rounding of i64s!
src = open(path_from_root('tests', 'parseInt', 'src.c'), 'r').read()
- if Settings.I64_MODE == 0:
- expected = open(path_from_root('tests', 'parseInt', 'output.txt'), 'r').read()
- else:
- expected = open(path_from_root('tests', 'parseInt', 'output_i64mode1.txt'), 'r').read() # some rounding issues, etc.
+ expected = open(path_from_root('tests', 'parseInt', 'output.txt'), 'r').read()
self.do_run(src, expected)
def test_printf(self):
- if Settings.USE_TYPED_ARRAYS != 0: return self.skip('Typed arrays truncate i64')
src = open(path_from_root('tests', 'printf', 'test.c'), 'r').read()
- expected = open(path_from_root('tests', 'printf', 'output.txt'), 'r').read()
+ # I64 mode 1 has some rounding and un-NaNing effects
+ expected = open(path_from_root('tests', 'printf', 'output.txt' if Settings.I64_MODE == 0 else 'output_i64_1.txt'), 'r').read()
self.do_run(src, expected)
def test_printf_types(self):
@@ -2878,8 +2950,6 @@ if 'benchmark' not in str(sys.argv):
self.do_run(src, re.sub('(^|\n)\s+', '\\1', expected), post_build=add_pre_run)
def test_stat(self):
- if Settings.I64_MODE == 1: return self.skip('TODO')
-
def add_pre_run(filename):
src = open(filename, 'r').read().replace(
'// {{PRE_RUN_ADDITIONS}}',
@@ -3399,7 +3469,7 @@ if 'benchmark' not in str(sys.argv):
self.do_run(src, 'Pfannkuchen(%d) = %d.' % (i,j), [str(i)], no_build=i>1)
def test_raytrace(self):
- if Settings.USE_TYPED_ARRAYS == 2: return self.skip('Relies on double values')
+ if Settings.USE_TYPED_ARRAYS == 2: return self.skip('Relies on double value rounding, extremely sensitive')
src = open(path_from_root('tests', 'raytrace.cpp'), 'r').read().replace('double', 'float')
output = open(path_from_root('tests', 'raytrace.ppm'), 'r').read()
@@ -3579,8 +3649,6 @@ if 'benchmark' not in str(sys.argv):
def test_the_bullet(self): # Called thus so it runs late in the alphabetical cycle... it is long
if Building.LLVM_OPTS: Settings.SAFE_HEAP = 0 # Optimizations make it so we do not have debug info on the line we need to ignore
- if Settings.USE_TYPED_ARRAYS == 2: return self.skip('We have slightly different rounding here for some reason. TODO: activate this')
-
# Note: this is also a good test of per-file and per-line changes (since we have multiple files, and correct specific lines)
if Settings.SAFE_HEAP:
# Ignore bitfield warnings
@@ -3600,7 +3668,7 @@ if 'benchmark' not in str(sys.argv):
def test_poppler(self):
# llvm-link failure when using clang, LLVM bug 9498, still relevant?
if Settings.RELOOP or Building.LLVM_OPTS: return self.skip('TODO')
- if Settings.USE_TYPED_ARRAYS == 2 or Settings.QUANTUM_SIZE == 1: return self.skip('TODO: Figure out and try to fix')
+ if Settings.QUANTUM_SIZE == 1: return self.skip('TODO: Figure out and try to fix')
Settings.USE_TYPED_ARRAYS = 0 # XXX bug - we fail with this FIXME
@@ -3756,7 +3824,7 @@ if 'benchmark' not in str(sys.argv):
output_nicerizer=image_compare)#, build_ll_hook=self.do_autodebug)
def test_python(self):
- if Settings.QUANTUM_SIZE == 1 or Settings.USE_TYPED_ARRAYS == 2: return self.skip('TODO: make this work')
+ if Settings.QUANTUM_SIZE == 1: return self.skip('TODO: make this work')
# Overflows in string_hash
Settings.CORRECT_OVERFLOWS = 1
@@ -3902,8 +3970,6 @@ Block 0: ''', post_build=post1)
# Part 2: old JS version
- if Settings.USE_TYPED_ARRAYS == 2: return self.skip('LLVM opts inline out the inner func')
-
Settings.PROFILE = 1
Settings.INVOKE_RUN = 0
@@ -4188,7 +4254,6 @@ Child2:9
def test_typeinfo(self):
Settings.RUNTIME_TYPE_INFO = 1
if Settings.QUANTUM_SIZE != 4: return self.skip('We assume normal sizes in the output here')
- if Settings.USE_TYPED_ARRAYS == 2: return self.skip('LLVM unsafe opts optimize out the type info')
src = '''
#include<stdio.h>
@@ -4457,8 +4522,6 @@ Child2:9
Settings.CHECK_SIGNS = 0
Settings.CHECK_OVERFLOWS = 0
- if Settings.USE_TYPED_ARRAYS == 2: return self.skip('LLVM opts optimize out the things we check')
-
# Signs
src = '''
@@ -4579,37 +4642,37 @@ Child2:9
}
'''
- Settings.CORRECT_ROUNDINGS = 0
- self.do_run(src.replace('TYPE', 'long long'), '*-3**2**-6**5*') # JS floor operations, always to the negative. This is an undetected error here!
- self.do_run(src.replace('TYPE', 'int'), '*-2**2**-5**5*') # We get these right, since they are 32-bit and we can shortcut using the |0 trick
- self.do_run(src.replace('TYPE', 'unsigned int'), '*-3**2**-6**5*') # We fail, since no fast shortcut for 32-bit unsigneds
+ if Settings.I64_MODE == 0: # the errors here are very specific to non-i64 mode 1
+ Settings.CORRECT_ROUNDINGS = 0
+ self.do_run(src.replace('TYPE', 'long long'), '*-3**2**-6**5*') # JS floor operations, always to the negative. This is an undetected error here!
+ self.do_run(src.replace('TYPE', 'int'), '*-2**2**-5**5*') # We get these right, since they are 32-bit and we can shortcut using the |0 trick
+ self.do_run(src.replace('TYPE', 'unsigned int'), '*-3**2**-6**5*') # We fail, since no fast shortcut for 32-bit unsigneds
Settings.CORRECT_ROUNDINGS = 1
+ Settings.CORRECT_SIGNS = 1 # To be correct here, we need sign corrections as well
self.do_run(src.replace('TYPE', 'long long'), '*-2**2**-5**5*') # Correct
self.do_run(src.replace('TYPE', 'int'), '*-2**2**-5**5*') # Correct
- Settings.CORRECT_SIGNS = 1 # To be correct here, we need sign corrections as well
self.do_run(src.replace('TYPE', 'unsigned int'), '*2147483645**2**-5**5*') # Correct
- return
Settings.CORRECT_SIGNS = 0
- Settings.CORRECT_ROUNDINGS = 2
- Settings.CORRECT_ROUNDINGS_LINES = ["src.cpp:13"] # Fix just the last mistake
- self.do_run(src.replace('TYPE', 'long long'), '*-3**2**-5**5*')
- self.do_run(src.replace('TYPE', 'int'), '*-2**2**-5**5*') # Here we are lucky and also get the first one right
- self.do_run(src.replace('TYPE', 'unsigned int'), '*-3**2**-5**5*') # No such luck here
+ if Settings.I64_MODE == 0: # the errors here are very specific to non-i64 mode 1
+ Settings.CORRECT_ROUNDINGS = 2
+ Settings.CORRECT_ROUNDINGS_LINES = ["src.cpp:13"] # Fix just the last mistake
+ self.do_run(src.replace('TYPE', 'long long'), '*-3**2**-5**5*')
+ self.do_run(src.replace('TYPE', 'int'), '*-2**2**-5**5*') # Here we are lucky and also get the first one right
+ self.do_run(src.replace('TYPE', 'unsigned int'), '*-3**2**-5**5*') # No such luck here
# And reverse the check with = 2
- Settings.CORRECT_ROUNDINGS = 3
- Settings.CORRECT_ROUNDINGS_LINES = ["src.cpp:999"]
- self.do_run(src.replace('TYPE', 'long long'), '*-2**2**-5**5*')
- self.do_run(src.replace('TYPE', 'int'), '*-2**2**-5**5*')
- Settings.CORRECT_SIGNS = 1 # To be correct here, we need sign corrections as well
- self.do_run(src.replace('TYPE', 'unsigned int'), '*2147483645**2**-5**5*')
- Settings.CORRECT_SIGNS = 0
+ if Settings.I64_MODE == 0: # the errors here are very specific to non-i64 mode 1
+ Settings.CORRECT_ROUNDINGS = 3
+ Settings.CORRECT_ROUNDINGS_LINES = ["src.cpp:999"]
+ self.do_run(src.replace('TYPE', 'long long'), '*-2**2**-5**5*')
+ self.do_run(src.replace('TYPE', 'int'), '*-2**2**-5**5*')
+ Settings.CORRECT_SIGNS = 1 # To be correct here, we need sign corrections as well
+ self.do_run(src.replace('TYPE', 'unsigned int'), '*2147483645**2**-5**5*')
+ Settings.CORRECT_SIGNS = 0
def test_pgo(self):
- if Settings.USE_TYPED_ARRAYS == 2: return self.skip('LLVM opts optimize out the things we check')
-
Settings.PGO = Settings.CHECK_OVERFLOWS = Settings.CORRECT_OVERFLOWS = Settings.CHECK_SIGNS = Settings.CORRECT_SIGNS = 1
src = '''
@@ -4673,8 +4736,8 @@ Child2:9
'''
self.do_run(src, 'hello, world!\nExit Status: 118')
- # Generate tests for all our compilers
- def make_run(name, compiler, llvm_opts, embetter, quantum_size, typed_arrays):
+ # Generate tests for everything
+ def make_run(name=-1, compiler=-1, llvm_opts=0, embetter=0, quantum_size=0, typed_arrays=0, defaults=False):
exec('''
class %s(T):
def tearDown(self):
@@ -4682,8 +4745,16 @@ class %s(T):
def setUp(self):
super(%s, self).setUp()
-
+
+ Building.COMPILER_TEST_OPTS = ['-g']
+ os.chdir(self.get_dir()) # Ensure the directory exists and go there
Building.COMPILER = %r
+
+ use_defaults = %d
+ if use_defaults:
+ Settings.load_defaults()
+ return
+
llvm_opts = %d # 1 is yes, 2 is yes and unsafe
embetter = %d
quantum_size = %d
@@ -4712,6 +4783,7 @@ class %s(T):
Settings.CATCH_EXIT_CODE = 0
Settings.TOTAL_MEMORY = Settings.FAST_MEMORY = None
Settings.EMULATE_UNALIGNED_ACCESSES = Settings.USE_TYPED_ARRAYS == 2 and Building.LLVM_OPTS == 2
+ Settings.DOUBLE_MODE = 1 if Settings.USE_TYPED_ARRAYS and Building.LLVM_OPTS == 0 else 0
if Settings.USE_TYPED_ARRAYS == 2:
Settings.I64_MODE = 1
Settings.SAFE_HEAP = 1 # only checks for alignment problems, which is very important with unsafe opts
@@ -4723,35 +4795,39 @@ class %s(T):
Building.pick_llvm_opts(3, safe=Building.LLVM_OPTS != 2)
- Building.COMPILER_TEST_OPTS = ['-g']
-
- os.chdir(self.get_dir()) # Ensure the directory exists and go there
-
TT = %s
-''' % (fullname, fullname, fullname, compiler, llvm_opts, embetter, quantum_size, typed_arrays, fullname))
+''' % (fullname, fullname, fullname, compiler, defaults, llvm_opts, embetter, quantum_size, typed_arrays, fullname))
return TT
- for name, compiler, quantum, embetter, typed_arrays, llvm_opts in [
- ('clang', CLANG, 1, 0, 0, 0),
- ('clang', CLANG, 1, 0, 0, 1),
- ('clang', CLANG, 4, 0, 0, 0),
- ('clang', CLANG, 4, 0, 0, 1),
- ('clang', CLANG, 1, 1, 1, 0),
- ('clang', CLANG, 1, 1, 1, 1),
- ('clang', CLANG, 4, 1, 1, 0),
- ('clang', CLANG, 4, 1, 1, 1),
- ('clang', CLANG, 4, 1, 2, 0),
- ('clang', CLANG, 4, 1, 2, 1),
- #('clang', CLANG, 4, 1, 2, 2),
+ # Make one run with the defaults
+ fullname = 'default'
+ exec(fullname + ' = make_run(compiler=CLANG, defaults=True)')
+
+ # Make custom runs with various options
+ for compiler, quantum, embetter, typed_arrays, llvm_opts in [
+ (CLANG, 1, 0, 0, 0),
+ (CLANG, 1, 0, 0, 1),
+ (CLANG, 4, 0, 0, 0),
+ (CLANG, 4, 0, 0, 1),
+ (CLANG, 1, 1, 1, 0),
+ (CLANG, 1, 1, 1, 1),
+ (CLANG, 4, 1, 1, 0),
+ (CLANG, 4, 1, 1, 1),
+ (CLANG, 4, 1, 2, 0),
+ (CLANG, 4, 1, 2, 1),
+ #(CLANG, 4, 1, 2, 2),
]:
- fullname = '%s_%d_%d%s%s' % (
- name, llvm_opts, embetter, '' if quantum == 4 else '_q' + str(quantum), '' if typed_arrays in [0, 1] else '_t' + str(typed_arrays)
+ fullname = 's_%d_%d%s%s' % (
+ llvm_opts, embetter, '' if quantum == 4 else '_q' + str(quantum), '' if typed_arrays in [0, 1] else '_t' + str(typed_arrays)
)
exec('%s = make_run(%r,%r,%d,%d,%d,%d)' % (fullname, fullname, compiler, llvm_opts, embetter, quantum, typed_arrays))
del T # T is just a shape for the specific subclasses, we don't test it itself
class other(RunnerCore):
+ def test_reminder(self):
+ raise Exception('update Getting Started to use defaults instead of clang_0_0')
+
def test_emcc(self):
pass
# TODO: make sure all of these match gcc
@@ -4831,6 +4907,8 @@ else:
class benchmark(RunnerCore):
def setUp(self):
+ super(benchmark, self).setUp()
+
Settings.RELOOP = Settings.MICRO_OPTS = 1
Settings.USE_TYPED_ARRAYS = 1
Settings.QUANTUM_SIZE = 1
@@ -4848,8 +4926,6 @@ else:
Building.LLVM_OPTS = 1 if Settings.USE_TYPED_ARRAYS != 2 else 2
Building.pick_llvm_opts(2, safe=Building.LLVM_OPTS != 2)
- super(benchmark, self).setUp()
-
def print_stats(self, times, native_times, last=False):
mean = sum(times)/len(times)
squared_times = map(lambda x: x*x, times)