aboutsummaryrefslogtreecommitdiff
path: root/tests/runner.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/runner.py')
-rwxr-xr-xtests/runner.py255
1 files changed, 250 insertions, 5 deletions
diff --git a/tests/runner.py b/tests/runner.py
index e599d30e..c2240141 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -653,6 +653,97 @@ if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv):
self.do_run(src, '*1*\n*0*\n*0*\n')
+ def test_i64_b(self):
+ if Settings.USE_TYPED_ARRAYS != 2: return self.skip('full i64 stuff only in ta2')
+
+ src = r'''
+ #include <stdio.h>
+ #include <sys/time.h>
+
+ typedef long long int64;
+
+ #define PRMJ_USEC_PER_SEC 1000000L
+
+ int main(int argc, char * argv[]) {
+ int64 sec = 1329409675 + argc;
+ int64 usec = 2329509675;
+ int64 mul = int64(sec) * PRMJ_USEC_PER_SEC;
+ int64 add = mul + int64(usec);
+ int add_low = add;
+ int add_high = add >> 32;
+ printf("*%lld,%lld,%u,%u*\n", mul, add, add_low, add_high);
+ return 0;
+ }
+ '''
+
+ self.do_run(src, '*1329409676000000,1329412005509675,3663280683,309527*\n')
+
+ def test_i64_cmp(self):
+ if Settings.USE_TYPED_ARRAYS != 2: return self.skip('full i64 stuff only in ta2')
+
+ src = r'''
+ #include <stdio.h>
+
+ typedef long long int64;
+
+ bool compare(int64 val) {
+ return val == -12;
+ }
+
+ bool compare2(int64 val) {
+ return val < -12;
+ }
+
+ int main(int argc, char * argv[]) {
+ printf("*%d,%d,%d,%d,%d,%d*\n", argc, compare(argc-1-12), compare(1000+argc), compare2(argc-1-10), compare2(argc-1-14), compare2(argc+1000));
+ return 0;
+ }
+ '''
+
+ self.do_run(src, '*1,1,0,0,1,0*\n')
+
+ 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>
+
+ typedef long long int64;
+ #define JSDOUBLE_HI32_SIGNBIT 0x80000000
+
+ bool JSDOUBLE_IS_NEGZERO(double d)
+ {
+ union {
+ struct {
+ unsigned int lo, hi;
+ } s;
+ double d;
+ } x;
+ if (d != 0)
+ return false;
+ x.d = d;
+ return (x.s.hi & JSDOUBLE_HI32_SIGNBIT) != 0;
+ }
+
+ bool JSINT64_IS_NEGZERO(int64 l)
+ {
+ union {
+ int64 i;
+ double d;
+ } x;
+ if (l != 0)
+ return false;
+ x.i = l;
+ return x.d == -0;
+ }
+
+ int main(int argc, char * argv[]) {
+ printf("*%d,%d,%d,%d*\n", JSDOUBLE_IS_NEGZERO(0), JSDOUBLE_IS_NEGZERO(-0), JSDOUBLE_IS_NEGZERO(-1), JSDOUBLE_IS_NEGZERO(+1));
+ printf("*%d,%d,%d,%d*\n", JSINT64_IS_NEGZERO(0), JSINT64_IS_NEGZERO(-0), JSINT64_IS_NEGZERO(-1), JSINT64_IS_NEGZERO(+1));
+ return 0;
+ }
+ '''
+ self.do_run(src, '*0,0,0,0*\n*1,1,0,0*\n') # same as gcc
+
def test_unaligned(self):
if Settings.QUANTUM_SIZE == 1: return self.skip('No meaning to unaligned addresses in q1')
@@ -1319,6 +1410,41 @@ if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv):
'''
self.do_run(src, 'Assertion failed: 1 == false')
+ def test_longjmp(self):
+ 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() {
+ int x = 0;
+ if ( ! setjmp(buf) ) {
+ x++;
+ first(); // when executed, setjmp returns 0
+ } else { // when longjmp jumps back, setjmp returns 1
+ printf("main: %d\n", x); // prints
+ }
+
+ return 0;
+ }
+ '''
+ # gcc -O0 and -O2 differ in what they do with the saved state of local vars - and we match that
+ if self.emcc_args is None or ('-O1' not in self.emcc_args and '-O2' not in self.emcc_args):
+ self.do_run(src, 'second\nmain: 1\n')
+ else:
+ self.do_run(src, 'second\nmain: 0\n')
+
def test_exceptions(self):
if Settings.QUANTUM_SIZE == 1: return self.skip("we don't support libcxx in q1")
@@ -1547,6 +1673,25 @@ if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv):
self.do_run(src, '*11,74,32,1012*\n*11*\n*22*')
def test_dynamic_cast(self):
+ src = r'''
+ #include <stdio.h>
+
+ struct Support {
+ virtual void f() {
+ printf("f()\n");
+ }
+ };
+
+ struct Derived : Support {
+ };
+
+ int main() {
+ Support * p = new Derived;
+ dynamic_cast<Derived*>(p)->f();
+ }
+ '''
+ self.do_run(src, 'f()\n')
+
src = '''
#include <stdio.h>
@@ -2418,6 +2563,27 @@ def process(filename):
self.do_run(src, '*1*', force_c=True)
+ def test_atexit(self):
+ # Confirms they are called in reverse order
+ src = r'''
+ #include <stdio.h>
+ #include <stdlib.h>
+
+ static void cleanA() {
+ printf("A");
+ }
+ static void cleanB() {
+ printf("B");
+ }
+
+ int main() {
+ atexit(cleanA);
+ atexit(cleanB);
+ return 0;
+ }
+ '''
+ self.do_run(src, 'BA')
+
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.
src = open(path_from_root('tests', 'time', 'src.c'), 'r').read()
@@ -4792,6 +4958,69 @@ Block 0: ''', post_build=post1)
### Integration tests
+ def test_ccall(self):
+ if self.emcc_args is not None and '-O2' in self.emcc_args:
+ self.emcc_args += ['--closure', '1'] # Use closure here, to test we export things right
+
+ 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) { puts(str); return (x+y)*z; }
+ int * KEEPALIVE pointer(int *in) { printf("%d\n", *in); static int ret = 21; return &ret; }
+ }
+
+ int main(int argc, char **argv) {
+ // keep them alive
+ if (argc == 10) return get_int();
+ if (argc == 11) return get_float();
+ if (argc == 12) return get_string()[0];
+ if (argc == 13) print_int(argv[0][0]);
+ if (argc == 14) print_float(argv[0][0]);
+ if (argc == 15) print_string(argv[0]);
+ if (argc == 16) pointer((int*)argv[0]);
+ if (argc % 17 == 12) return multi(argc, float(argc)/2, argc+1, argv[0]);
+ return 0;
+ }
+ '''
+
+ post = '''
+def process(filename):
+ src = \'\'\'
+ var Module = {
+ 'postRun': function() {
+ print('*');
+ var ret;
+ ret = ccall('get_int', 'number'); print([typeof ret, ret]);
+ ret = ccall('get_float', 'number'); print([typeof ret, ret.toFixed(2)]);
+ ret = ccall('get_string', 'string'); print([typeof ret, ret]);
+ ret = ccall('print_int', null, ['number'], [12]); print(typeof ret);
+ ret = ccall('print_float', null, ['number'], [14.56]); print(typeof ret);
+ ret = ccall('print_string', null, ['string'], ["cheez"]); print(typeof ret);
+ ret = ccall('multi', 'number', ['number', 'number', 'number', 'string'], [2, 1.4, 3, 'more']); print([typeof ret, ret]);
+ var p = ccall('malloc', 'pointer', ['number'], [4]);
+ setValue(p, 650, 'i32');
+ ret = ccall('pointer', 'pointer', ['pointer'], [p]); print([typeof ret, getValue(ret, 'i32')]);
+ print('*');
+ }
+ };
+ \'\'\' + open(filename, 'r').read()
+ open(filename, 'w').write(src)
+'''
+
+ 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\nmore\nnumber,10\n650\nnumber,21\n*\n', post_build=post)
+
def test_scriptaclass(self):
header_filename = os.path.join(self.get_dir(), 'header.h')
header = '''
@@ -5457,16 +5686,21 @@ def process(filename):
def test_exit_status(self):
Settings.CATCH_EXIT_CODE = 1
- src = '''
+ src = r'''
#include <stdio.h>
#include <stdlib.h>
+ static void cleanup() {
+ printf("cleanup\n");
+ }
+
int main()
{
- printf("hello, world!\\n");
+ atexit(cleanup); // this atexit should still be called
+ printf("hello, world!\n");
exit(118); // Unusual exit status to make sure it's working!
}
'''
- self.do_run(src, 'hello, world!\nExit Status: 118')
+ self.do_run(src, 'hello, world!\ncleanup\nExit Status: 118')
# Generate tests for everything
@@ -5615,7 +5849,7 @@ Options that are modified or new in %s include:
# 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', 'js']]:
+ 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'
clear()
Popen([compiler, path_from_root('tests', 'hello_world' + suffix)] + args, stdout=PIPE, stderr=PIPE).communicate()
@@ -5629,6 +5863,16 @@ Options that are modified or new in %s include:
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
+ clear()
+ Popen([compiler, path_from_root('tests', 'hello_world' + suffix), '-o', 'a.bc'], stdout=PIPE, stderr=PIPE).communicate()
+ Popen([LLVM_AR, 'r', 'a.a', 'a.bc'], stdout=PIPE, stderr=PIPE).communicate()
+ assert os.path.exists('a.a')
+ shutil.copyfile('a.a', '/home/alon/a.a')
+ output = Popen([compiler, 'a.a']).communicate()
+ assert os.path.exists('a.out.js'), output
+ self.assertContained('hello, world!', run_js('a.out.js'))
+
# emcc src.ll ==> generates .js
clear()
output = Popen([compiler, path_from_root('tests', 'hello_world.ll')], stdout=PIPE, stderr=PIPE).communicate()
@@ -5915,6 +6159,7 @@ elif 'benchmark' in str(sys.argv):
pass
finally:
os.chdir(d)
+ fingerprint.append('llvm: ' + LLVM_ROOT)
print 'Running Emscripten benchmarks... [ %s ]' % ' | '.join(fingerprint)
sys.argv = filter(lambda x: x != 'benchmark', sys.argv)
@@ -6075,7 +6320,7 @@ elif 'benchmark' in str(sys.argv):
'''
self.do_benchmark(src, [], 'final: 720.')
- def test_files(self):
+ def zzztest_files(self):
src = r'''
#include<stdio.h>
#include<stdlib.h>