aboutsummaryrefslogtreecommitdiff
path: root/tests/runner.py
diff options
context:
space:
mode:
authorAnthony Pesch <inolen@gmail.com>2013-08-11 21:48:58 -0700
committerAnthony Pesch <inolen@gmail.com>2013-08-11 23:54:37 -0700
commit8d3994c9eb604408fb0a325712c63b96827dee90 (patch)
treef1563566c6d8685fbc306b0b99ee19fd0d4ea9fd /tests/runner.py
parent8cb83003709aa90a3410b6352552342ec97d5116 (diff)
initial work on splitting up runner.py
Diffstat (limited to 'tests/runner.py')
-rwxr-xr-xtests/runner.py15193
1 files changed, 317 insertions, 14876 deletions
diff --git a/tests/runner.py b/tests/runner.py
index 9a8670b6..b9b92445 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -18,47 +18,6 @@ so you may prefer to use fewer cores here.
from subprocess import Popen, PIPE, STDOUT
import os, unittest, tempfile, shutil, time, inspect, sys, math, glob, re, difflib, webbrowser, hashlib, threading, platform, BaseHTTPServer, multiprocessing, functools, stat, string
-if len(sys.argv) == 1:
- print '''
-==============================================================================
-Running the main part of the test suite. Don't forget to run the other parts!
-
- sanity - tests for first run, etc., modifies ~/.emscripten
- benchmark - run before and after each set of changes before pushing to
- master, verify no regressions
- browser - runs pages in a web browser
-
-There are also commands to run specific subsets of the test suite:
-
- browser sockets - runs websocket networking tests
- browser audio - runs audio tests in a web browser (requires human verification)
-
-To run one of those parts, do something like
-
- python tests/runner.py sanity
-
-To run a specific set of tests, you can do things like
-
- python tests/runner.py o1
-
-(that runs the o1 (-O1) tests). You can run individual tests with
-
- python tests/runner.py test_hello_world
-
-Combinations work too, for example
-
- python tests/runner.py browser.test_sdl_image
-
-In the main test suite, you can run all variations (O0, O1, O2, etc.) of
-an individual test with
-
- python tests/runner.py ALL.test_hello_world
-
-==============================================================================
-
-'''
- time.sleep(2)
-
# Setup
__rootpath__ = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
@@ -76,10 +35,13 @@ except:
raise Exception('Cannot find "COMPILER_OPTS" definition. Is %s set up properly? You may need to copy the template settings file into it.' % EM_CONFIG)
# Core test runner class, shared between normal tests and benchmarks
-
checked_sanity = False
+test_modes = ['default', 'o1', 'o2', 'asm1', 'asm2', 'asm2g', 'asm2x86', 's_0_0', 's_0_1']
+test_index = 0
+js_engine_override = None
class RunnerCore(unittest.TestCase):
+ emcc_args = None
save_dir = os.environ.get('EM_SAVE_DIR')
save_JS = 0
stderr_redirect = STDOUT # This avoids cluttering the test runner output, which is stderr too, with compiler warnings etc.
@@ -91,9 +53,7 @@ class RunnerCore(unittest.TestCase):
return self.skip('requested to be skipped')
def setUp(self):
- global Settings
Settings.reset()
- Settings = tools.shared.Settings
self.banned_js_engines = []
if not self.save_dir:
dirname = tempfile.mkdtemp(prefix='emscripten_test_' + self.__class__.__name__ + '_', dir=TEMP_DIR)
@@ -441,14877 +401,327 @@ process(sys.argv[1])
return 0;
}
'''
-
return (main, supp)
-###################################################################################################
-
-sys.argv = map(lambda arg: arg if not arg.startswith('test_') else 'default.' + arg, sys.argv)
-
-test_modes = ['default', 'o1', 'o2', 'asm1', 'asm2', 'asm2g', 'asm2x86', 's_0_0', 's_0_1']
-
-test_index = 0
-
-if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv) and 'browser' not in str(sys.argv):
- # Tests
-
- print "Running Emscripten tests..."
-
- if len(sys.argv) == 2 and sys.argv[1].startswith('ALL.'):
- ignore, test = sys.argv[1].split('.')
- print 'Running all test modes on test "%s"' % test
- sys.argv = [sys.argv[0]] + map(lambda mode: mode+'.'+test, test_modes)
-
- 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.
- def do_run(self, src, expected_output, args=[], output_nicerizer=None, output_processor=None, no_build=False, main_file=None, additional_files=[], js_engines=None, post_build=None, basename='src.cpp', libraries=[], includes=[], force_c=False, build_ll_hook=None, extra_emscripten_args=[]):
- if force_c or (main_file is not None and main_file[-2:]) == '.c':
- basename = 'src.c'
- Building.COMPILER = to_cc(Building.COMPILER)
-
- dirname = self.get_dir()
- filename = os.path.join(dirname, basename)
- if not no_build:
- self.build(src, dirname, filename, main_file=main_file, additional_files=additional_files, libraries=libraries, includes=includes,
- build_ll_hook=build_ll_hook, extra_emscripten_args=extra_emscripten_args, post_build=post_build)
-
- # Run in both JavaScript engines, if optimizing - significant differences there (typed arrays)
- if js_engines is None:
- js_engines = JS_ENGINES
- if Settings.USE_TYPED_ARRAYS:
- js_engines = filter(lambda engine: engine != V8_ENGINE, js_engines) # V8 issue 1822
- js_engines = filter(lambda engine: engine not in self.banned_js_engines, js_engines)
- if len(js_engines) == 0: return self.skip('No JS engine present to run this test with. Check %s and the paths therein.' % EM_CONFIG)
- for engine in js_engines:
- js_output = self.run_generated_code(engine, filename + '.o.js', args, output_nicerizer=output_nicerizer)
- self.assertContained(expected_output, js_output.replace('\r\n', '\n'))
- self.assertNotContained('ERROR', js_output)
-
- #shutil.rmtree(dirname) # TODO: leave no trace in memory. But for now nice for debugging
-
- if self.save_JS:
- global test_index
- self.hardcode_arguments(filename + '.o.js', args)
- shutil.copyfile(filename + '.o.js', os.path.join(TEMP_DIR, str(test_index) + '.js'))
- test_index += 1
-
- # No building - just process an existing .ll file (or .bc, which we turn into .ll)
- def do_ll_run(self, ll_file, expected_output=None, args=[], js_engines=None, output_nicerizer=None, post_build=None, force_recompile=False, build_ll_hook=None, extra_emscripten_args=[]):
- filename = os.path.join(self.get_dir(), 'src.cpp')
-
- self.prep_ll_run(filename, ll_file, force_recompile, build_ll_hook)
-
- self.ll_to_js(filename, extra_emscripten_args, post_build)
-
- self.do_run(None,
- expected_output,
- args,
- no_build=True,
- js_engines=js_engines,
- output_nicerizer=output_nicerizer,
- post_build=None) # post_build was already done in ll_to_js, this do_run call is just to test the output
-
- def is_le32(self):
- return not ('i386-pc-linux-gnu' in COMPILER_OPTS or self.env.get('EMCC_LLVM_TARGET') == 'i386-pc-linux-gnu')
-
- def test_hello_world(self):
- src = '''
- #include <stdio.h>
- int main()
- {
- printf("hello, world!\\n");
- return 0;
- }
- '''
- self.do_run(src, 'hello, world!')
-
- assert 'EMSCRIPTEN_GENERATED_FUNCTIONS' not in open(self.in_dir('src.cpp.o.js')).read(), 'must not emit this unneeded internal thing'
-
- def test_intvars(self):
- if self.emcc_args == None: return self.skip('needs ta2')
-
- src = '''
- #include <stdio.h>
- int global = 20;
- int *far;
- int main()
- {
- int x = 5;
- int y = x+17;
- int z = (y-1)/2; // Should stay an integer after division!
- y += 1;
- int w = x*3+4;
- int k = w < 15 ? 99 : 101;
- far = &k;
- *far += global;
- int i = k > 100; // Should be an int, not a bool!
- int j = i << 6;
- j >>= 1;
- j = j ^ 5;
- int h = 1;
- h |= 0;
- int p = h;
- p &= 0;
- printf("*%d,%d,%d,%d,%d,%d,%d,%d,%d*\\n", x, y, z, w, k, i, j, h, p);
-
- long hash = -1;
- size_t perturb;
- int ii = 0;
- for (perturb = hash; ; perturb >>= 5) {
- printf("%d:%d", ii, perturb);
- ii++;
- if (ii == 9) break;
- printf(",");
- }
- printf("*\\n");
- printf("*%.1d,%.2d*\\n", 56, 9);
-
- // Fixed-point math on 64-bit ints. Tricky to support since we have no 64-bit shifts in JS
- {
- struct Fixed {
- static int Mult(int a, int b) {
- return ((long long)a * (long long)b) >> 16;
- }
- };
- printf("fixed:%d\\n", Fixed::Mult(150000, 140000));
- }
-
- printf("*%ld*%p\\n", (long)21, &hash); // The %p should not enter an infinite loop!
- return 0;
- }
- '''
- self.do_run(src, '*5,23,10,19,121,1,37,1,0*\n0:-1,1:134217727,2:4194303,3:131071,4:4095,5:127,6:3,7:0,8:0*\n*56,09*\nfixed:320434\n*21*')
-
- def test_sintvars(self):
- Settings.CORRECT_SIGNS = 1 # Relevant to this test
- src = '''
- #include <stdio.h>
- struct S {
- char *match_start;
- char *strstart;
- };
- int main()
- {
- struct S _s;
- struct S *s = &_s;
- unsigned short int sh;
-
- s->match_start = (char*)32522;
- s->strstart = (char*)(32780);
- printf("*%d,%d,%d*\\n", (int)s->strstart, (int)s->match_start, (int)(s->strstart - s->match_start));
- sh = s->strstart - s->match_start;
- printf("*%d,%d*\\n", sh, sh>>7);
-
- s->match_start = (char*)32999;
- s->strstart = (char*)(32780);
- printf("*%d,%d,%d*\\n", (int)s->strstart, (int)s->match_start, (int)(s->strstart - s->match_start));
- sh = s->strstart - s->match_start;
- printf("*%d,%d*\\n", sh, sh>>7);
- }
- '''
- output = '*32780,32522,258*\n*258,2*\n*32780,32999,-219*\n*65317,510*'
- Settings.CORRECT_OVERFLOWS = 0 # We should not need overflow correction to get this right
- self.do_run(src, output, force_c=True)
-
- def test_i64(self):
- if Settings.USE_TYPED_ARRAYS != 2: return self.skip('i64 mode 1 requires ta2')
-
- src = '''
- #include <stdio.h>
- int main()
- {
- long long a = 0x2b00505c10;
- long long b = a >> 29;
- long long c = a >> 32;
- long long d = a >> 34;
- printf("*%Ld,%Ld,%Ld,%Ld*\\n", a, b, c, d);
- unsigned long long ua = 0x2b00505c10;
- unsigned long long ub = ua >> 29;
- unsigned long long uc = ua >> 32;
- unsigned long long ud = ua >> 34;
- printf("*%Ld,%Ld,%Ld,%Ld*\\n", ua, ub, uc, ud);
-
- long long x = 0x0000def123450789ULL; // any bigger than this, and we
- long long y = 0x00020ef123456089ULL; // start to run into the double precision limit!
- printf("*%Ld,%Ld,%Ld,%Ld,%Ld*\\n", x, y, x | y, x & y, x ^ y, x >> 2, y << 2);
-
- printf("*");
- long long z = 13;
- int n = 0;
- while (z > 1) {
- printf("%.2f,", (float)z); // these must be integers!
- z = z >> 1;
- n++;
- }
- printf("*%d*\\n", n);
- return 0;
- }
- '''
- self.do_run(src, '*184688860176,344,43,10*\n*184688860176,344,43,10*\n*245127260211081,579378795077769,808077213656969,16428841631881,791648372025088*\n*13.00,6.00,3.00,*3*')
-
- src = r'''
- #include <time.h>
- #include <stdio.h>
- #include <stdint.h>
-
- int64_t returner1() { return 0x0000def123450789ULL; }
- int64_t returner2(int test) {
- while (test > 10) test /= 2; // confuse the compiler so it doesn't eliminate this function
- return test > 5 ? 0x0000def123450123ULL : 0ULL;
- }
-
- void modifier1(int64_t t) {
- t |= 12;
- printf("m1: %Ld\n", t);
- }
- void modifier2(int64_t &t) {
- t |= 12;
- }
-
- int truthy() {
- int x = time(0);
- while (x > 10) {
- x |= 7;
- x /= 2;
- }
- return x < 3;
- }
-
- struct IUB {
- int c;
- long long d;
- };
-
- IUB iub[] = {
- { 55, 17179869201 },
- { 122, 25769803837 },
- };
-
- int main(int argc, char **argv)
- {
- int64_t x1 = 0x1234def123450789ULL;
- int64_t x2 = 0x1234def123450788ULL;
- int64_t x3 = 0x1234def123450789ULL;
- printf("*%Ld\n%d,%d,%d,%d,%d\n%d,%d,%d,%d,%d*\n", x1, x1==x2, x1<x2, x1<=x2, x1>x2, x1>=x2, // note: some rounding in the printing!
- x1==x3, x1<x3, x1<=x3, x1>x3, x1>=x3);
- printf("*%Ld*\n", returner1());
- printf("*%Ld*\n", returner2(30));
-
- uint64_t maxx = -1ULL;
- printf("*%Lu*\n*%Lu*\n", maxx, maxx >> 5);
-
- // Make sure params are not modified if they shouldn't be
- int64_t t = 123;
- modifier1(t);
- printf("*%Ld*\n", t);
- modifier2(t);
- printf("*%Ld*\n", t);
-
- // global structs with i64s
- printf("*%d,%Ld*\n*%d,%Ld*\n", iub[0].c, iub[0].d, iub[1].c, iub[1].d);
-
- // Bitshifts
- {
- int64_t a = -1;
- int64_t b = a >> 29;
- int64_t c = a >> 32;
- int64_t d = a >> 34;
- printf("*%Ld,%Ld,%Ld,%Ld*\n", a, b, c, d);
- uint64_t ua = -1;
- int64_t ub = ua >> 29;
- int64_t uc = ua >> 32;
- int64_t ud = ua >> 34;
- printf("*%Ld,%Ld,%Ld,%Ld*\n", ua, ub, uc, ud);
- }
-
- // Nonconstant bitshifts
- {
- int64_t a = -1;
- int64_t b = a >> (29 - argc + 1);
- int64_t c = a >> (32 - argc + 1);
- int64_t d = a >> (34 - argc + 1);
- printf("*%Ld,%Ld,%Ld,%Ld*\n", a, b, c, d);
- uint64_t ua = -1;
- int64_t ub = ua >> (29 - argc + 1);
- int64_t uc = ua >> (32 - argc + 1);
- int64_t ud = ua >> (34 - argc + 1);
- printf("*%Ld,%Ld,%Ld,%Ld*\n", ua, ub, uc, ud);
- }
-
- // Math mixtures with doubles
- {
- uint64_t a = 5;
- double b = 6.8;
- uint64_t c = a * b;
- if (truthy()) printf("*%d,%d,%d*\n", (int)&a, (int)&b, (int)&c); // printing addresses prevents optimizations
- printf("*prod:%llu*\n", c);
- }
-
- // Basic (rounded, for now) math. Just check compilation.
- int64_t a = 0x1234def123450789ULL;
- a--; if (truthy()) a--; // confuse optimizer
- int64_t b = 0x1234000000450789ULL;
- b++; if (truthy()) b--; // confuse optimizer
- printf("*%Ld,%Ld,%Ld,%Ld*\n", (a+b)/5000, (a-b)/5000, (a*3)/5000, (a/5)/5000);
-
- a -= 17; if (truthy()) a += 5; // confuse optimizer
- b -= 17; if (truthy()) b += 121; // confuse optimizer
- printf("*%Lx,%Lx,%Lx,%Lx*\n", b - a, b - a/2, b/2 - a, b - 20);
-
- if (truthy()) a += 5/b; // confuse optimizer
- if (truthy()) b += 121*(3+a/b); // confuse optimizer
- printf("*%Lx,%Lx,%Lx,%Lx*\n", a - b, a - b/2, a/2 - b, a - 20);
-
- return 0;
- }
- '''
- self.do_run(src, '*1311918518731868041\n' +
- '0,0,0,1,1\n' +
- '1,0,1,0,1*\n' +
- '*245127260211081*\n' +
- '*245127260209443*\n' +
- '*18446744073709551615*\n' +
- '*576460752303423487*\n' +
- 'm1: 127\n' +
- '*123*\n' +
- '*127*\n' +
- '*55,17179869201*\n' +
- '*122,25769803837*\n' +
- '*-1,-1,-1,-1*\n' +
- '*-1,34359738367,4294967295,1073741823*\n' +
- '*-1,-1,-1,-1*\n' +
- '*-1,34359738367,4294967295,1073741823*\n' +
- '*prod:34*\n' +
- '*524718382041609,49025451137,787151111239120,52476740749274*\n' +
- '*ffff210edd000002,91990876ea283be,f6e5210edcdd7c45,1234000000450765*\n' +
- '*def122fffffe,91adef1232283bb,f6e66f78915d7c42,1234def123450763*\n')
-
- src = r'''
- #include <stdio.h>
- #include <limits>
-
- int main()
- {
- long long i,j,k;
-
- i = 0;
- j = -1,
- k = 1;
-
- printf( "*\n" );
- printf( "%s\n", i > j ? "Ok": "Fail" );
- printf( "%s\n", k > i ? "Ok": "Fail" );
- printf( "%s\n", k > j ? "Ok": "Fail" );
- printf( "%s\n", i < j ? "Fail": "Ok" );
- printf( "%s\n", k < i ? "Fail": "Ok" );
- printf( "%s\n", k < j ? "Fail": "Ok" );
- printf( "%s\n", (i-j) >= k ? "Ok": "Fail" );
- printf( "%s\n", (i-j) <= k ? "Ok": "Fail" );
- printf( "%s\n", i > std::numeric_limits<long long>::min() ? "Ok": "Fail" );
- printf( "%s\n", i < std::numeric_limits<long long>::max() ? "Ok": "Fail" );
- printf( "*\n" );
- }
- '''
-
- self.do_run(src, '*\nOk\nOk\nOk\nOk\nOk\nOk\nOk\nOk\nOk\nOk\n*')
-
- # stuff that also needs sign corrections
-
- Settings.CORRECT_SIGNS = 1
-
- src = r'''
- #include <stdio.h>
- #include <stdint.h>
-
- int main()
- {
- // i32 vs i64
- int32_t small = -1;
- int64_t large = -1;
- printf("*%d*\n", small == large);
- small++;
- printf("*%d*\n", small == large);
- uint32_t usmall = -1;
- uint64_t ularge = -1;
- printf("*%d*\n", usmall == ularge);
- return 0;
- }
- '''
-
- 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);
- int64 x = sec + (usec << 25);
- x >>= argc*3;
- printf("*%llu*\n", x);
- return 0;
- }
- '''
-
- self.do_run(src, '*1329409676000000,1329412005509675,3663280683,309527*\n*9770671914067409*\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_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>
-
- typedef int32_t INT32;
- typedef int64_t INT64;
- typedef uint8_t UINT8;
-
- void interface_clock_changed()
- {
- UINT8 m_divshift;
- INT32 m_divisor;
-
- //INT64 attos = m_attoseconds_per_cycle;
- INT64 attos = 279365114840;
- m_divshift = 0;
- while (attos >= (1UL << 31))
- {
- m_divshift++;
- printf("m_divshift is %i, on %Ld >?= %lu\n", m_divshift, attos, 1UL << 31);
- attos >>= 1;
- }
- m_divisor = attos;
-
- printf("m_divisor is %i\n",m_divisor);
- }
-
- int main() {
- interface_clock_changed();
- return 0;
- }
- '''
- self.do_run(src, '''m_divshift is 1, on 279365114840 >?= 2147483648
-m_divshift is 2, on 139682557420 >?= 2147483648
-m_divshift is 3, on 69841278710 >?= 2147483648
-m_divshift is 4, on 34920639355 >?= 2147483648
-m_divshift is 5, on 17460319677 >?= 2147483648
-m_divshift is 6, on 8730159838 >?= 2147483648
-m_divshift is 7, on 4365079919 >?= 2147483648
-m_divshift is 8, on 2182539959 >?= 2147483648
-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>
-
- 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_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>
-
- typedef uint32_t UINT32;
- typedef uint64_t UINT64;
-
- int main() {
- volatile UINT32 testu32a = 2375724032U;
- UINT32 bigu32 = 0xffffffffU;
- volatile UINT64 testu64a = 14746250828952703000U;
-
- while ((UINT64)testu32a * (UINT64)bigu32 < testu64a) {
- printf("testu64a is %llu\n", testu64a);
- testu64a /= 2;
- }
-
- return 0;
- }
- '''
- self.do_run(src, 'testu64a is 14746250828952703000\n')
-
- def test_i64_precise(self):
- if Settings.USE_TYPED_ARRAYS != 2: return self.skip('full i64 stuff only in ta2')
-
- src = r'''
- #include <inttypes.h>
- #include <stdio.h>
-
- int main() {
- uint64_t x = 0, y = 0;
- for (int i = 0; i < 64; i++) {
- x += 1ULL << i;
- y += x;
- x /= 3;
- y *= 5;
- printf("unsigned %d: %llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu\n", i, x, y, x+y, x-y, x*y, y ? x/y : 0, x ? y/x : 0, y ? x%y : 0, x ? y%x : 0);
- }
- int64_t x2 = 0, y2 = 0;
- for (int i = 0; i < 64; i++) {
- x2 += 1LL << i;
- y2 += x2;
- x2 /= 3 * (i % 7 ? -1 : 1);
- y2 *= 5 * (i % 2 ? -1 : 1);
- printf("signed %d: %lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld\n", i, x2, y2, x2+y2, x2-y2, x2*y2, y2 ? x2/y2 : 0, x2 ? y2/x2 : 0, y2 ? x2%y2 : 0, x2 ? y2%x2 : 0);
- }
- return 0;
- }
- '''
- self.do_run(src, open(path_from_root('tests', 'i64_precise.txt')).read())
-
- # Verify that even if we ask for precision, if it is not needed it is not included
- Settings.PRECISE_I64_MATH = 1
- src = '''
- #include <inttypes.h>
- #include <stdio.h>
-
- int main(int argc, char **argv) {
- uint64_t x = 2125299906845564, y = 1225891506842664;
- if (argc == 12) {
- x = x >> 1;
- y = y >> 1;
- }
- x = x & 12ULL;
- y = y | 12ULL;
- x = x ^ y;
- x <<= 2;
- y >>= 3;
- printf("*%llu, %llu*\\n", x, y);
- }
- '''
- self.do_run(src, '*4903566027370624, 153236438355333*')
- code = open(os.path.join(self.get_dir(), 'src.cpp.o.js')).read()
- assert 'goog.math.Long' not in code, 'i64 precise math should not have been included if not actually used'
-
- # But if we force it to be included, it is. First, a case where we don't need it
- Settings.PRECISE_I64_MATH = 2
- self.do_run(open(path_from_root('tests', 'hello_world.c')).read(), 'hello')
- code = open(os.path.join(self.get_dir(), 'src.cpp.o.js')).read()
- assert 'goog.math.Long' in code, 'i64 precise math should be included if forced'
-
- # and now one where we do
- self.do_run(r'''
- #include <stdio.h>
-
- int main( int argc, char ** argv )
- {
- unsigned long a = 0x60DD1695U;
- unsigned long b = 0xCA8C4E7BU;
- unsigned long long c = (unsigned long long)a * b;
- printf( "c = %016llx\n", c );
-
- return 0;
- }
- ''', 'c = 4ca38a6bd2973f97')
-
- def test_i64_llabs(self):
- if Settings.USE_TYPED_ARRAYS != 2: return self.skip('full i64 stuff only in ta2')
- Settings.PRECISE_I64_MATH = 2
- self.do_run(r'''
- #include <stdio.h>
- #include <stdlib.h>
-
- int main(int argc, char ** argv) {
- printf("%lld,%lld\n", llabs(-576460752303423489), llabs(576460752303423489));
- return 0;
- }
- ''', '576460752303423489,576460752303423489')
-
- def test_i64_zextneg(self):
- if Settings.USE_TYPED_ARRAYS != 2: return self.skip('full i64 stuff only in ta2')
-
- src = r'''
- #include <stdint.h>
- #include <stdio.h>
-
- int main(int argc, char *argv[])
- {
- uint8_t byte = 0x80;
- uint16_t two = byte;
- uint32_t four = byte;
- uint64_t eight = byte;
-
- printf("value: %d,%d,%d,%lld.\n", byte, two, four, eight);
-
- return 0;
- }
- '''
- self.do_run(src, 'value: 128,128,128,128.')
-
- def test_i64_7z(self):
- if Settings.USE_TYPED_ARRAYS != 2: return self.skip('full i64 stuff only in ta2')
-
- src = r'''
- #include <stdint.h>
- #include <stdio.h>
- uint64_t a, b;
- int main(int argc, char *argv[])
- {
- a = argc;
- b = argv[1][0];
- printf("%d,%d\n", a, b);
- if (a > a + b || a > a + b + 1) {
- printf("one %lld, %lld", a, b);
- return 0;
- }
- printf("zero %lld, %lld", a, b);
- return 0;
- }
- '''
- self.do_run(src, 'zero 2, 104', ['hallo'])
-
- def test_i64_i16(self):
- if Settings.USE_TYPED_ARRAYS != 2: return self.skip('full i64 stuff only in ta2')
+ ## Does a complete test - builds, runs, checks output, etc.
+ def do_run(self, src, expected_output, args=[], output_nicerizer=None, output_processor=None, no_build=False, main_file=None, additional_files=[], js_engines=None, post_build=None, basename='src.cpp', libraries=[], includes=[], force_c=False, build_ll_hook=None, extra_emscripten_args=[]):
+ if force_c or (main_file is not None and main_file[-2:]) == '.c':
+ basename = 'src.c'
+ Building.COMPILER = to_cc(Building.COMPILER)
+
+ dirname = self.get_dir()
+ filename = os.path.join(dirname, basename)
+ if not no_build:
+ self.build(src, dirname, filename, main_file=main_file, additional_files=additional_files, libraries=libraries, includes=includes,
+ build_ll_hook=build_ll_hook, extra_emscripten_args=extra_emscripten_args, post_build=post_build)
+
+ # Run in both JavaScript engines, if optimizing - significant differences there (typed arrays)
+ if js_engines is None:
+ js_engines = JS_ENGINES
+ if Settings.USE_TYPED_ARRAYS:
+ js_engines = filter(lambda engine: engine != V8_ENGINE, js_engines) # V8 issue 1822
+ js_engines = filter(lambda engine: engine not in self.banned_js_engines, js_engines)
+ if len(js_engines) == 0: return self.skip('No JS engine present to run this test with. Check %s and the paths therein.' % EM_CONFIG)
+ for engine in js_engines:
+ js_output = self.run_generated_code(engine, filename + '.o.js', args, output_nicerizer=output_nicerizer)
+ self.assertContained(expected_output, js_output.replace('\r\n', '\n'))
+ self.assertNotContained('ERROR', js_output)
+
+ #shutil.rmtree(dirname) # TODO: leave no trace in memory. But for now nice for debugging
+
+ if self.save_JS:
+ global test_index
+ self.hardcode_arguments(filename + '.o.js', args)
+ shutil.copyfile(filename + '.o.js', os.path.join(TEMP_DIR, str(test_index) + '.js'))
+ test_index += 1
+
+ # No building - just process an existing .ll file (or .bc, which we turn into .ll)
+ def do_ll_run(self, ll_file, expected_output=None, args=[], js_engines=None, output_nicerizer=None, post_build=None, force_recompile=False, build_ll_hook=None, extra_emscripten_args=[]):
+ filename = os.path.join(self.get_dir(), 'src.cpp')
+
+ self.prep_ll_run(filename, ll_file, force_recompile, build_ll_hook)
- src = r'''
- #include <stdint.h>
- #include <stdio.h>
- int main(int argc, char ** argv){
- int y=-133;
- int64_t x= ((int64_t)((short)(y)))*(100 + argc);
- if(x>0)
- printf(">0\n");
- else
- printf("<=0\n");
- }
- '''
- self.do_run(src, '<=0')
-
- def test_i64_qdouble(self):
- if Settings.USE_TYPED_ARRAYS != 2: return self.skip('full i64 stuff only in ta2')
-
- src = r'''
- #include <stdio.h>
- typedef long long qint64; /* 64 bit signed */
- typedef double qreal;
-
-
- int main(int argc, char **argv)
- {
- qreal c = 111;
- qint64 d = -111 + (argc - 1);
- c += d;
- if (c < -1 || c > 1)
- {
- printf("Failed!\n");
- }
- else
- {
- printf("Succeeded!\n");
- }
- };
- '''
- self.do_run(src, 'Succeeded!')
-
- def test_i64_varargs(self):
- if Settings.USE_TYPED_ARRAYS != 2: return self.skip('full i64 stuff only in ta2')
-
- src = r'''
- #include <stdio.h>
- #include <stdint.h>
- #include <stdarg.h>
-
- int64_t ccv_cache_generate_signature(char *msg, int len, int64_t sig_start, ...) {
- if (sig_start < 10123)
- printf("%s\n", msg+len);
- va_list v;
- va_start(v, sig_start);
- if (sig_start > 1413)
- printf("%d\n", va_arg(v, int));
- else
- printf("nada\n");
- va_end(v);
- return len*sig_start*(msg[0]+1);
- }
-
- int main(int argc, char **argv)
- {
- for (int i = 0; i < argc; i++) {
- int64_t x;
- if (i % 123123 == 0)
- x = ccv_cache_generate_signature(argv[i], i+2, (int64_t)argc*argc, 54.111);
- else
- x = ccv_cache_generate_signature(argv[i], i+2, (int64_t)argc*argc, 13);
- printf("%lld\n", x);
- }
- };
- '''
- self.do_run(src, '''in/this.program
-nada
-1536
-a
-nada
-5760
-fl
-nada
-6592
-sdfasdfasdf
-nada
-7840
-''', 'waka fleefl asdfasdfasdfasdf'.split(' '))
-
- def test_i32_mul_precise(self):
- if self.emcc_args == None: return self.skip('needs ta2')
-
- src = r'''
- #include <stdio.h>
-
- int main(int argc, char **argv) {
- unsigned long d1 = 0x847c9b5d;
- unsigned long q = 0x549530e1;
- if (argc > 1000) { q += argc; d1 -= argc; } // confuse optimizer
- printf("%lu\n", d1*q);
- return 0;
- }
- '''
- self.do_run(src, '3217489085')
-
- def test_i32_mul_semiprecise(self):
- if Settings.ASM_JS: return self.skip('asm is always fully precise')
-
- Settings.PRECISE_I32_MUL = 0 # we want semiprecise here
-
- src = r'''
- #include <stdio.h>
-
- typedef unsigned int uint;
-
- // from cube2, zlib licensed
-
- #define N (624)
- #define M (397)
- #define K (0x9908B0DFU)
-
- static uint state[N];
- static int next = N;
-
- void seedMT(uint seed)
- {
- state[0] = seed;
- for(uint i = 1; i < N; i++) // if we do not do this precisely, at least we should coerce to int immediately, not wait
- state[i] = seed = 1812433253U * (seed ^ (seed >> 30)) + i;
- next = 0;
- }
-
- int main() {
- seedMT(5497);
- for (int i = 0; i < 10; i++) printf("%d: %u\n", i, state[i]);
- return 0;
- }
- '''
- self.do_run(src, '''0: 5497
-1: 2916432318
-2: 2502517762
-3: 3151524867
-4: 2323729668
-5: 2053478917
-6: 2409490438
-7: 848473607
-8: 691103752
-9: 3915535113
-''')
-
- def test_i16_emcc_intrinsic(self):
- Settings.CORRECT_SIGNS = 1 # Relevant to this test
-
- src = r'''
- #include <stdio.h>
-
- int test(unsigned short a, unsigned short b) {
- unsigned short result = a;
- result += b;
- if (result < b) printf("C!");
- return result;
- }
-
- int main(void) {
- printf(",%d,", test(0, 0));
- printf(",%d,", test(1, 1));
- printf(",%d,", test(65535, 1));
- printf(",%d,", test(1, 65535));
- printf(",%d,", test(32768, 32767));
- printf(",%d,", test(32768, 32768));
- return 0;
- }
- '''
- self.do_run(src, ',0,,2,C!,0,C!,0,,65535,C!,0,')
-
- def test_negative_zero(self):
- src = r'''
- #include <stdio.h>
- #include <math.h>
-
- int main() {
- #define TEST(x, y) \
- printf("%.2f, %.2f ==> %.2f\n", x, y, copysign(x, y));
- TEST( 5.0f, 5.0f);
- TEST( 5.0f, -5.0f);
- TEST(-5.0f, 5.0f);
- TEST(-5.0f, -5.0f);
- TEST( 5.0f, 4.0f);
- TEST( 5.0f, -4.0f);
- TEST(-5.0f, 4.0f);
- TEST(-5.0f, -4.0f);
- TEST( 0.0f, 5.0f);
- TEST( 0.0f, -5.0f);
- TEST(-0.0f, 5.0f);
- TEST(-0.0f, -5.0f);
- TEST( 5.0f, 0.0f);
- TEST( 5.0f, -0.0f);