aboutsummaryrefslogtreecommitdiff
path: root/tests/runner.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/runner.py')
-rwxr-xr-xtests/runner.py692
1 files changed, 576 insertions, 116 deletions
diff --git a/tests/runner.py b/tests/runner.py
index 7913c249..a419ff0d 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -41,6 +41,12 @@ To run a specific set of tests, you can do things like
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
+
==============================================================================
'''
@@ -102,6 +108,9 @@ class RunnerCore(unittest.TestCase):
def get_dir(self):
return self.working_dir
+ def in_dir(self, *pathelems):
+ return os.path.join(self.get_dir(), *pathelems)
+
def get_shared_library_name(self, linux_name):
if platform.system() == 'Linux':
return linux_name
@@ -325,6 +334,62 @@ process(sys.argv[1])
for name in os.listdir(EMSCRIPTEN_TEMP_DIR):
try_delete(os.path.join(EMSCRIPTEN_TEMP_DIR, name))
+ # Shared test code between main suite and others
+
+ def setup_runtimelink_test(self):
+ header = r'''
+ struct point
+ {
+ int x, y;
+ };
+
+ '''
+ open(os.path.join(self.get_dir(), 'header.h'), 'w').write(header)
+
+ supp = r'''
+ #include <stdio.h>
+ #include "header.h"
+
+ extern void mainFunc(int x);
+ extern int mainInt;
+
+ void suppFunc(struct point &p) {
+ printf("supp: %d,%d\n", p.x, p.y);
+ mainFunc(p.x+p.y);
+ printf("supp see: %d\n", mainInt);
+ }
+
+ int suppInt = 76;
+ '''
+ supp_name = os.path.join(self.get_dir(), 'supp.c')
+ open(supp_name, 'w').write(supp)
+
+ main = r'''
+ #include <stdio.h>
+ #include "header.h"
+
+ extern void suppFunc(struct point &p);
+ extern int suppInt;
+
+ void mainFunc(int x) {
+ printf("main: %d\n", x);
+ }
+
+ int mainInt = 543;
+
+ int main( int argc, const char *argv[] ) {
+ struct point p = { 54, 2 };
+ suppFunc(p);
+ printf("main see: %d\nok.\n", suppInt);
+ #ifdef BROWSER
+ int result = suppInt;
+ REPORT_RESULT();
+ #endif
+ return 0;
+ }
+ '''
+
+ return (main, supp)
###################################################################################################
@@ -335,6 +400,11 @@ if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv) and 'brows
print "Running Emscripten tests..."
+ 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]
+
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=[]):
@@ -1124,16 +1194,11 @@ c5,de,15,8a
}
'''
- Settings.EMULATE_UNALIGNED_ACCESSES = 0
-
try:
self.do_run(src, '*300:1*\n*515559*\n*42949672960*\n')
except Exception, e:
assert 'must be aligned' in str(e), e # expected to fail without emulation
- # XXX TODO Settings.EMULATE_UNALIGNED_ACCESSES = 1
- #self.do_run(src, '*300:1*\n*515559*\n*42949672960*\n') # but succeeds with it
-
def test_unsigned(self):
Settings.CORRECT_SIGNS = 1 # We test for exactly this sort of thing here
Settings.CHECK_SIGNS = 0
@@ -3432,62 +3497,14 @@ def process(filename):
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')
- Settings.LINKABLE = 1
+ main, supp = self.setup_runtimelink_test()
self.banned_js_engines = [NODE_JS] # node's global scope behaves differently than everything else, needs investigation FIXME
-
- header = r'''
- struct point
- {
- int x, y;
- };
-
- '''
- open(os.path.join(self.get_dir(), 'header.h'), 'w').write(header)
-
- supp = r'''
- #include <stdio.h>
- #include "header.h"
-
- extern void mainFunc(int x);
- extern int mainInt;
-
- void suppFunc(struct point &p) {
- printf("supp: %d,%d\n", p.x, p.y);
- mainFunc(p.x+p.y);
- printf("supp see: %d\n", mainInt);
- }
-
- int suppInt = 76;
- '''
- supp_name = os.path.join(self.get_dir(), 'supp.c')
- open(supp_name, 'w').write(supp)
-
- main = r'''
- #include <stdio.h>
- #include "header.h"
-
- extern void suppFunc(struct point &p);
- extern int suppInt;
-
- void mainFunc(int x) {
- printf("main: %d\n", x);
- }
-
- int mainInt = 543;
-
- int main( int argc, const char *argv[] ) {
- struct point p = { 54, 2 };
- suppFunc(p);
- printf("main see: %d\nok.\n", suppInt);
- return 0;
- }
- '''
-
+ Settings.LINKABLE = 1
Settings.BUILD_AS_SHARED_LIB = 2
- dirname = self.get_dir()
- self.build(supp, dirname, supp_name)
- shutil.move(supp_name + '.o.js', os.path.join(dirname, 'liblib.so'))
+
+ 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'))
Settings.BUILD_AS_SHARED_LIB = 0
Settings.RUNTIME_LINKED_LIBS = ['liblib.so'];
@@ -4253,13 +4270,20 @@ at function.:blag
printf("%d\n", sscanf("-123 -765 -34-6", "%d %u %d", &neg, &neg2, &neg3));
printf("%d,%u,%d\n", neg, neg2, neg3);
+ {
+ int a = 0;
+ sscanf("1", "%i", &a);
+ printf("%i\n", a);
+ }
+
return 0;
}
'''
self.do_run(src, 'en-us : 2\nen-r : 99\nen : 3\n1.234567, 0.000000\n2.8208\n-3.0300\n|some|\n|something|\n|somethingmoar|\n' +
'1\n1499\n' +
'5\n87,0.481565,0.059481,0,1\n' +
- '3\n-123,4294966531,-34\n')
+ '3\n-123,4294966531,-34\n' +
+ '1\n')
def test_sscanf_2(self):
# doubles
@@ -5069,10 +5093,56 @@ def process(filename):
int main() {
printf("*%x,%x,%x,%x,%x,%x*\n", htonl(0xa1b2c3d4), htonl(0xfe3572e0), htonl(0x07abcdf0), htons(0xabcd), ntohl(0x43211234), ntohs(0xbeaf));
+ in_addr_t i = inet_addr("190.180.10.78");
+ printf("%x\n", i);
return 0;
}
'''
- self.do_run(src, '*d4c3b2a1,e07235fe,f0cdab07,cdab,34122143,afbe*')
+ self.do_run(src, '*d4c3b2a1,e07235fe,f0cdab07,cdab,34122143,afbe*\n4e0ab4be\n')
+
+ def test_gethostbyname(self):
+ if Settings.USE_TYPED_ARRAYS != 2: return self.skip("assume t2 in gethostbyname")
+
+ src = r'''
+ #include <netdb.h>
+ #include <stdio.h>
+
+ void test(char *hostname) {
+ hostent *host = gethostbyname(hostname);
+ if (!host) {
+ printf("no such thing\n");
+ return;
+ }
+ printf("%s : %d : %d\n", host->h_name, host->h_addrtype, host->h_length);
+ char **name = host->h_aliases;
+ while (*name) {
+ printf("- %s\n", *name);
+ name++;
+ }
+ name = host->h_addr_list;
+ while (name && *name) {
+ printf("* ");
+ for (int i = 0; i < host->h_length; i++)
+ printf("%d.", (*name)[i]);
+ printf("\n");
+ name++;
+ }
+ }
+
+ int main() {
+ test("www.cheezburger.com");
+ test("fail.on.this.never.work"); // we will "work" on this - because we are just making aliases of names to ips
+ test("localhost");
+ return 1;
+ }
+ '''
+ self.do_run(src, '''www.cheezburger.com : 1 : 4
+* -84.29.1.0.
+fail.on.this.never.work : 1 : 4
+* -84.29.2.0.
+localhost : 1 : 4
+* -84.29.3.0.
+''')
def test_ctype(self):
# The bit fiddling done by the macros using __ctype_b_loc requires this.
@@ -5201,6 +5271,62 @@ int main(int argc, char **argv) {
self.do_run(src, '789:123.46\n0:100.1')
+ def test_jansson(self):
+ if Settings.USE_TYPED_ARRAYS != 2: return self.skip('requires ta2')
+ if Settings.SAFE_HEAP: return self.skip('jansson is not safe-heap safe')
+
+ src = '''
+ #include <jansson.h>
+ #include <stdio.h>
+ #include <string.h>
+
+ int main()
+ {
+ const char* jsonString = "{\\"key\\": \\"value\\",\\"array\\": [\\"array_item1\\",\\"array_item2\\",\\"array_item3\\"],\\"dict\\":{\\"number\\": 3,\\"float\\": 2.2}}";
+
+ json_error_t error;
+ json_t *root = json_loadb(jsonString, strlen(jsonString), 0, &error);
+
+ if(!root || !json_is_object(root))
+ return 0;
+ printf("%s\\n", json_string_value(json_object_get(root, "key")));
+
+ json_t *array = json_object_get(root, "array");
+ if(!array || !json_is_array(array))
+ return 0;
+ for(size_t i=0; i<json_array_size(array); ++i)
+ {
+ json_t *arrayNode = json_array_get(array, i);
+ if(!root || !json_is_string(arrayNode))
+ return 0;
+ printf("%s\\n", json_string_value(arrayNode));
+ }
+
+ json_t *dict = json_object_get(root, "dict");
+ if(!dict || !json_is_object(dict))
+ return 0;
+
+ json_t *numberNode = json_object_get(dict, "number");
+ json_t *floatNode = json_object_get(dict, "float");
+
+ if(!numberNode || !json_is_number(numberNode) ||
+ !floatNode || !json_is_real(floatNode))
+ return 0;
+
+ printf("%i\\n", json_integer_value(numberNode));
+ printf("%.2f\\n", json_number_value(numberNode));
+ printf("%.2f\\n", json_real_value(floatNode));
+
+ json_decref(root);
+
+ if(!json_is_object(root))
+ printf("jansson!\\n");
+
+ return 0;
+ }
+ '''
+ self.do_run(src, 'value\narray_item1\narray_item2\narray_item3\n3\n3.00\n2.20\njansson!')
+
### 'Medium' tests
def test_fannkuch(self):
@@ -7131,6 +7257,14 @@ f.close()
# TODO: test normal project linking, static and dynamic: get_library should not need to be told what to link!
# TODO: deprecate llvm optimizations, dlmalloc, etc. in emscripten.py.
+ def test_Os(self):
+ for opt in ['s', '0']:
+ output = Popen(['python', EMCC, path_from_root('tests', 'hello_world.c'), '-O' + opt], stdout=PIPE, stderr=PIPE).communicate()
+ assert len(output[0]) == 0, output[0]
+ assert ('emcc: warning: -Os is ignored (use -O0, -O1, -O2)' in output[1]) == (opt == 's'), 'warn on -Os when necessary'
+ assert os.path.exists('a.out.js'), '\n'.join(output)
+ self.assertContained('hello, world!', run_js('a.out.js'))
+
def test_catch_undef(self):
open(os.path.join(self.get_dir(), 'test.cpp'), 'w').write(r'''
#include <vector>
@@ -7151,6 +7285,26 @@ f.close()
Popen(['python', EMCC, os.path.join(self.get_dir(), 'test.cpp'), '-fcatch-undefined-behavior']).communicate()
self.assertContained('hello, world!', run_js(os.path.join(self.get_dir(), 'a.out.js')))
+ def test_unaligned_memory(self):
+ open(os.path.join(self.get_dir(), 'test.cpp'), 'w').write(r'''
+ #include <stdio.h>
+
+ typedef unsigned char Bit8u;
+ typedef unsigned short Bit16u;
+ typedef unsigned int Bit32u;
+
+ int main()
+ {
+ Bit8u data[4] = {0x01,0x23,0x45,0x67};
+
+ printf("data: %x\n", *(Bit32u*)data);
+ printf("data[0,1] 16bit: %x\n", *(Bit16u*)data);
+ printf("data[1,2] 16bit: %x\n", *(Bit16u*)(data+1));
+ }
+ ''')
+ Popen(['python', EMCC, os.path.join(self.get_dir(), 'test.cpp'), '-s', 'UNALIGNED_MEMORY=1']).communicate()
+ self.assertContained('data: 67452301\ndata[0,1] 16bit: 2301\ndata[1,2] 16bit: 4523', run_js(os.path.join(self.get_dir(), 'a.out.js')))
+
def test_l_link(self):
# Linking with -lLIBNAME and -L/DIRNAME should work
@@ -7222,6 +7376,70 @@ f.close()
Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp'), os.path.join(self.get_dir(), 'subdir', 'libfile.so'), '-L.']).communicate()
self.assertContained('hello from lib', run_js(os.path.join(self.get_dir(), 'a.out.js')))
+ def test_runtimelink_multi(self):
+ open('testa.h', 'w').write(r'''
+ #ifndef _TESTA_H_
+ #define _TESTA_H_
+
+ class TestA {
+ public:
+ TestA();
+ };
+
+ #endif
+ ''')
+ open('testb.h', 'w').write(r'''
+ #ifndef _TESTB_H_
+ #define _TESTB_H_
+
+ class TestB {
+ public:
+ TestB();
+ };
+
+ #endif
+ ''')
+ open('testa.cpp', 'w').write(r'''
+ #include <stdio.h>
+ #include <testa.h>
+
+ TestA::TestA() {
+ printf("TestA\n");
+ }
+ ''')
+ open('testb.cpp', 'w').write(r'''
+ #include <stdio.h>
+ #include <testb.h>
+ #include <testa.h>
+ /*
+ */
+ TestB::TestB() {
+ printf("TestB\n");
+ TestA* testa = new TestA();
+ }
+ ''')
+ open('main.cpp', 'w').write(r'''
+ #include <stdio.h>
+ #include <testa.h>
+ #include <testb.h>
+
+ /*
+ */
+ int main(int argc, char** argv) {
+ printf("Main\n");
+ TestA* testa = new TestA();
+ TestB* testb = new TestB();
+ }
+ ''')
+
+ Popen(['python', EMCC, 'testa.cpp', '-o', 'liba.js', '-s', 'BUILD_AS_SHARED_LIB=2', '-s', 'LINKABLE=1', '-I.']).communicate()
+ Popen(['python', EMCC, 'testb.cpp', '-o', 'libb.js', '-s', 'BUILD_AS_SHARED_LIB=2', '-s', 'LINKABLE=1', '-I.']).communicate()
+ Popen(['python', EMCC, 'main.cpp', '-o', 'main.js', '-s', 'RUNTIME_LINKED_LIBS=["liba.js", "libb.js"]', '-I.']).communicate()
+
+ Popen(['python', EMCC, 'main.cpp', 'testa.cpp', 'testb.cpp', '-o', 'full.js', '-I.']).communicate()
+
+ self.assertContained('TestA\nTestB\nTestA\n', run_js('main.js', engine=SPIDERMONKEY_ENGINE))
+
def test_js_libraries(self):
open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write('''
#include <stdio.h>
@@ -7339,6 +7557,37 @@ f.close()
self.assertContained('result: 12346.', run_js(os.path.join(self.get_dir(), 'a.out.js')))
+ def test_dup_o_in_a(self):
+ open('common.c', 'w').write(r'''
+ #include <stdio.h>
+ void a(void) {
+ printf("a\n");
+ }
+ ''')
+ Popen(['python', EMCC, 'common.c', '-c', '-o', 'common.o']).communicate()
+ Popen(['python', EMAR, 'rc', 'liba.a', 'common.o']).communicate()
+
+ open('common.c', 'w').write(r'''
+ #include <stdio.h>
+ void b(void) {
+ printf("b\n");
+ }
+ ''')
+ Popen(['python', EMCC, 'common.c', '-c', '-o', 'common.o']).communicate()
+ Popen(['python', EMAR, 'rc', 'libb.a', 'common.o']).communicate()
+
+ open('main.c', 'w').write(r'''
+ void a(void);
+ void b(void);
+ int main() {
+ a();
+ b();
+ }
+ ''')
+ Popen(['python', EMCC, 'main.c', '-L.', '-la', '-lb']).communicate()
+
+ self.assertContained('a\nb\n', run_js(os.path.join(self.get_dir(), 'a.out.js')))
+
def test_embed_file(self):
open(os.path.join(self.get_dir(), 'somefile.txt'), 'w').write('''hello from a file with lots of data and stuff in it thank you very much''')
open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write(r'''
@@ -7361,6 +7610,38 @@ f.close()
Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--embed-file', 'somefile.txt', '--embed-file', 'somefile.txt']).communicate()
self.assertContained('|hello from a file wi|', run_js(os.path.join(self.get_dir(), 'a.out.js')))
+ def test_embed_file_dup(self):
+ try_delete(os.path.join(self.get_dir(), 'tst'))
+ os.mkdir(os.path.join(self.get_dir(), 'tst'))
+ os.mkdir(os.path.join(self.get_dir(), 'tst', 'test1'))
+ os.mkdir(os.path.join(self.get_dir(), 'tst', 'test2'))
+
+ open(os.path.join(self.get_dir(), 'tst', 'aa.txt'), 'w').write('''frist''')
+ open(os.path.join(self.get_dir(), 'tst', 'test1', 'aa.txt'), 'w').write('''sacond''')
+ open(os.path.join(self.get_dir(), 'tst', 'test2', 'aa.txt'), 'w').write('''thard''')
+ open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write(r'''
+ #include <stdio.h>
+ #include <string.h>
+ void print_file(const char *name) {
+ FILE *f = fopen(name, "r");
+ char buf[100];
+ memset(buf, 0, 100);
+ fread(buf, 1, 20, f);
+ buf[20] = 0;
+ fclose(f);
+ printf("|%s|\n", buf);
+ }
+ int main() {
+ print_file("tst/aa.txt");
+ print_file("tst/test1/aa.txt");
+ print_file("tst/test2/aa.txt");
+ return 0;
+ }
+ ''')
+
+ Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--embed-file', 'tst']).communicate()
+ self.assertContained('|frist|\n|sacond|\n|thard|\n', run_js(os.path.join(self.get_dir(), 'a.out.js')))
+
def test_multidynamic_link(self):
# Linking the same dynamic library in will error, normally, since we statically link it, causing dupe symbols
# A workaround is to use --ignore-dynamic-linking, see emcc --help for details
@@ -7600,6 +7881,68 @@ f.close()
output = run_js('scons_integration.js')
assert 'If you see this - the world is all right!' in output
+ def test_embind(self):
+ for args, fail in [
+ ([], True), # without --bind, we fail
+ (['--bind'], False),
+ (['--bind', '-O1'], False)
+ # XXX TODO (['--bind', '-O2'], False)
+ ]:
+ print args, fail
+ try_delete(self.in_dir('a.out.js'))
+ Popen(['python', EMCC, path_from_root('tests', 'embind', 'embind_test.cpp'), '--post-js', path_from_root('tests', 'embind', 'embind_test.js')] + args, stderr=PIPE if fail else None).communicate()
+ assert os.path.exists(self.in_dir('a.out.js')) == (not fail)
+ if not fail:
+ output = run_js(self.in_dir('a.out.js'))
+ self.assertContained('''fixture: embind
+--test: test value creation
+--test: test passthrough
+--test: test void return converts to undefined
+--test: test booleans can be marshalled
+--test: test convert double to unsigned
+--test: test get length of array
+--test: test add a bunch of things
+--test: test sum array
+--test: test strings
+--test: test no memory leak when passing strings in by const reference
+fixture: classes
+--test: test class instance
+--test: test class methods
+--test: test can't call methods on deleted class instances
+--test: test isinstance
+--test: test can return class instances by value
+--test: test can pass class instances to functions by reference
+--test: test can access struct fields
+--test: test can set struct fields
+--test: test assignment returns value
+--test: test assigning string to integer raises TypeError
+--test: test can return tuples by value
+--test: test tuples can contain tuples
+--test: test can pass tuples by value
+--test: test can return structs by value
+--test: test can pass structs by value
+--test: test can pass and return tuples in structs
+--test: test can clone handles
+--test: test can't clone if already deleted
+--test: test moving handles is a clone+delete
+--test: test StringHolder
+fixture: embind enumerations
+--test: test can compare enumeration values
+--test: test repr includes enum value
+--test: test instanceof
+--test: test can pass and return enumeration values to functions
+fixture: C++11 enum class
+--test: test can compare enumeration values
+--test: test repr includes enum value
+--test: test instanceof
+--test: test can pass and return enumeration values to functions
+fixture: emval call tests
+--test: test can call functions from C++
+fixture: interfaces
+--test: test can wrap JS object in native interface
+--test: test can pass arguments and return complicated values
+--test: test can call interface methods that return nothing''', output)
+
def test_llvm_nativizer(self):
# avoid impure_ptr problems etc.
shutil.copyfile(path_from_root('tests', 'files.cpp'), os.path.join(self.get_dir(), 'files.cpp'))
@@ -7803,6 +8146,8 @@ elif 'browser' in str(sys.argv):
def with_report_result(self, code):
return r'''
+ #if EMSCRIPTEN
+ #include <emscripten.h>
#define REPORT_RESULT_INTERNAL(sync) \
char output[1000]; \
sprintf(output, \
@@ -7812,6 +8157,7 @@ elif 'browser' in str(sys.argv):
emscripten_run_script(output); \
emscripten_run_script("setTimeout(function() { window.close() }, 1000)");
#define REPORT_RESULT() REPORT_RESULT_INTERNAL(0)
+ #endif
''' + code
def reftest(self, expected):
@@ -8252,6 +8598,16 @@ elif 'browser' in str(sys.argv):
shutil.move(os.path.join(self.get_dir(), basename), basename + '.renamedsoitcannotbefound');
self.run_browser('page.html', '', '/report_result?' + str(width))
+ def test_sdl_image_prepare(self):
+ # load an image file, get pixel data. Also O2 coverage for --preload-file
+ shutil.copyfile(path_from_root('tests', 'screenshot.jpg'), os.path.join(self.get_dir(), 'screenshot.not'))
+ self.btest('sdl_image_prepare.c', reference='screenshot.jpg', args=['--preload-file', 'screenshot.not'])
+
+ def test_sdl_image_prepare_data(self):
+ # load an image file, get pixel data. Also O2 coverage for --preload-file
+ shutil.copyfile(path_from_root('tests', 'screenshot.jpg'), os.path.join(self.get_dir(), 'screenshot.not'))
+ self.btest('sdl_image_prepare_data.c', reference='screenshot.jpg', args=['--preload-file', 'screenshot.not'])
+
def test_sdl_canvas(self):
open(os.path.join(self.get_dir(), 'sdl_canvas.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_canvas.c')).read()))
@@ -8590,7 +8946,12 @@ elif 'browser' in str(sys.argv):
def btest(self, filename, expected=None, reference=None, reference_slack=0, args=[]): # TODO: use in all other tests
if not reference:
- open(os.path.join(self.get_dir(), filename), 'w').write(self.with_report_result(open(path_from_root('tests', filename)).read()))
+ if '\n' in filename: # if we are provided the source and not a path, use that
+ src = filename
+ filename = 'main.cpp'
+ else:
+ src = open(path_from_root('tests', filename)).read()
+ open(os.path.join(self.get_dir(), filename), 'w').write(self.with_report_result(src))
else:
expected = [str(i) for i in range(0, reference_slack+1)]
shutil.copyfile(path_from_root('tests', filename), os.path.join(self.get_dir(), filename))
@@ -8603,6 +8964,9 @@ elif 'browser' in str(sys.argv):
def test_emscripten_api(self):
self.btest('emscripten_api_browser.cpp', '1')
+ def test_emscripten_api_infloop(self):
+ self.btest('emscripten_api_browser_infloop.cpp', '7')
+
def test_emscripten_fs_api(self):
shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) # preloaded *after* run
self.btest('emscripten_fs_api_browser.cpp', '1')
@@ -8610,6 +8974,9 @@ elif 'browser' in str(sys.argv):
def test_sdl_quit(self):
self.btest('sdl_quit.c', '1')
+ def test_sdl_resize(self):
+ self.btest('sdl_resize.c', '1')
+
def test_gc(self):
self.btest('browser_gc.cpp', '1')
@@ -8628,52 +8995,52 @@ elif 'browser' in str(sys.argv):
self.btest('gl_matrix_identity.c', expected=['-1882984448', '460451840'])
def test_cubegeom_pre(self):
- self.btest('cubegeom_pre.c', expected=['-1472804742', '-1626058463'])
+ self.btest('cubegeom_pre.c', expected=['-1472804742', '-1626058463', '-2046234971'])
def test_cubegeom_pre2(self):
- self.btest('cubegeom_pre2.c', expected=['-1472804742', '-1626058463'], args=['-s', 'GL_DEBUG=1']) # some coverage for GL_DEBUG not breaking the build
+ self.btest('cubegeom_pre2.c', expected=['-1472804742', '-1626058463', '-2046234971'], args=['-s', 'GL_DEBUG=1']) # some coverage for GL_DEBUG not breaking the build
def test_cubegeom_pre3(self):
- self.btest('cubegeom_pre3.c', expected=['-1472804742', '-1626058463'])
+ self.btest('cubegeom_pre3.c', expected=['-1472804742', '-1626058463', '-2046234971'])
def test_cubegeom(self):
- self.btest('cubegeom.c', expected=['188641320', '1522377227', '-1054007155'])
+ self.btest('cubegeom.c', expected=['188641320', '1522377227', '-1054007155', '-1111866053'])
def test_cubegeom_color(self):
- self.btest('cubegeom_color.c', expected=['588472350', '-687660609'])
+ self.btest('cubegeom_color.c', expected=['588472350', '-687660609', '-818120875'])
def test_cubegeom_normal(self):
- self.btest('cubegeom_normal.c', expected=['752917084', '-251570256'])
+ self.btest('cubegeom_normal.c', expected=['752917084', '-251570256', '-291655550'])
def test_cubegeom_normal_dap(self): # draw is given a direct pointer to clientside memory, no element array buffer
- self.btest('cubegeom_normal_dap.c', expected=['752917084', '-251570256'])
+ self.btest('cubegeom_normal_dap.c', expected=['752917084', '-251570256', '-291655550'])
def test_cubegeom_normal_dap_far(self): # indices do nto start from 0
- self.btest('cubegeom_normal_dap_far.c', expected=['752917084', '-251570256'])
+ self.btest('cubegeom_normal_dap_far.c', expected=['752917084', '-251570256', '-291655550'])
def test_cubegeom_normal_dap_far_range(self): # glDrawRangeElements
- self.btest('cubegeom_normal_dap_far_range.c', expected=['752917084', '-251570256'])
+ self.btest('cubegeom_normal_dap_far_range.c', expected=['752917084', '-251570256', '-291655550'])
def test_cubegeom_normal_dap_far_glda(self): # use glDrawArrays
- self.btest('cubegeom_normal_dap_far_glda.c', expected=['-218745386', '-263951846'])
+ self.btest('cubegeom_normal_dap_far_glda.c', expected=['-218745386', '-263951846', '-375182658'])
def test_cubegeom_normal_dap_far_glda_quad(self): # with quad
- self.btest('cubegeom_normal_dap_far_glda_quad.c', expected=['1757386625', '-677777235'])
+ self.btest('cubegeom_normal_dap_far_glda_quad.c', expected=['1757386625', '-677777235', '-690699597'])
def test_cubegeom_mt(self):
- self.btest('cubegeom_mt.c', expected=['-457159152', '910983047']) # multitexture
+ self.btest('cubegeom_mt.c', expected=['-457159152', '910983047', '870576921']) # multitexture
def test_cubegeom_color2(self):
- self.btest('cubegeom_color2.c', expected=['1121999515', '-391668088'])
+ self.btest('cubegeom_color2.c', expected=['1121999515', '-391668088', '-522128354'])
def test_cubegeom_texturematrix(self):
- self.btest('cubegeom_texturematrix.c', expected=['1297500583', '-791216738'])
+ self.btest('cubegeom_texturematrix.c', expected=['1297500583', '-791216738', '-783804685'])
def test_cubegeom_fog(self):
- self.btest('cubegeom_fog.c', expected=['1617140399', '-898782526'])
+ self.btest('cubegeom_fog.c', expected=['1617140399', '-898782526', '-946179526'])
def test_cube_explosion(self):
- self.btest('cube_explosion.c', expected=['667220544', '-1543354600'])
+ self.btest('cube_explosion.c', expected=['667220544', '-1543354600', '-1485258415'])
def test_sdl_canvas_palette(self):
self.btest('sdl_canvas_palette.c', reference='sdl_canvas_palette.png')
@@ -8724,6 +9091,15 @@ elif 'browser' in str(sys.argv):
def test_float_tex(self):
self.btest('float_tex.cpp', reference='float_tex.png')
+ def test_runtimelink(self):
+ main, supp = self.setup_runtimelink_test()
+
+ open(self.in_dir('supp.cpp'), 'w').write(supp)
+ Popen(['python', EMCC, self.in_dir('supp.cpp'), '-o', 'supp.js', '-s', 'LINKABLE=1', '-s', 'BUILD_AS_SHARED_LIB=2', '-O2', '--closure', '0']).communicate()
+ shutil.move(self.in_dir('supp.js'), self.in_dir('supp.so'))
+
+ self.btest(main, args=['-s', 'LINKABLE=1', '-s', 'RUNTIME_LINKED_LIBS=["supp.so"]', '-DBROWSER=1', '-O2', '--closure', '0'], expected='76')
+
def test_pre_run_deps(self):
# Adding a dependency in preRun will delay run
open(os.path.join(self.get_dir(), 'pre.js'), 'w').write('''
@@ -8738,51 +9114,135 @@ elif 'browser' in str(sys.argv):
''')
self.btest('pre_run_deps.cpp', expected='10', args=['--pre-js', 'pre.js'])
- class WebsockHarness:
- def __enter__(self):
- self.pids = []
+ pids_to_clean = []
+ def clean_pids(self):
+ return
+ import signal
+ for pid in browser.pids_to_clean:
+ print '[killing %d]' % pid
+ try:
+ os.kill(pid, signal.SIGKILL) # With this commented, we leave no children, but we hang the test harness on exit XXX
+ print '[kill succeeded]'
+ except:
+ print '[kill fail]'
+ browser.pids_to_clean = []
- def server_func(q):
- proc = Popen([path_from_root('tests', 'socket_server.sh')])
- q.put(proc.pid)
- proc.communicate()
+ # Runs a websocket server at a specific port. port is the true tcp socket we forward to, port+1 is the websocket one
+ class WebsockHarness:
+ def __init__(self, port, server_func=None, no_server=False):
+ self.port = port
+ self.server_func = server_func
+ self.no_server = no_server
- server_queue = multiprocessing.Queue()
- self.server = multiprocessing.Process(target=server_func, args=(server_queue,))
- self.server.start()
- self.pids.append(self.server.pid)
- while True:
- if not server_queue.empty():
- self.pids.append(server_queue.get())
- break
- time.sleep(0.1)
- print '[Socket server on processes %s]' % str(self.pids[-2:])
+ def __enter__(self):
+ if not self.no_server:
+ def server_func(q):
+ proc = Popen([path_from_root('tests', 'socket_server.sh'), str(self.port)])
+ q.put(proc.pid)
+ proc.communicate()
+
+ server_func = self.server_func or server_func
+
+ server_queue = multiprocessing.Queue()
+ self.server = multiprocessing.Process(target=server_func, args=(server_queue,))
+ self.server.start()
+ browser.pids_to_clean.append(self.server.pid)
+ while True:
+ if not server_queue.empty():
+ browser.pids_to_clean.append(server_queue.get())
+ break
+ time.sleep(0.1)
+ print '[Socket server on processes %s]' % str(browser.pids_to_clean[-2:])
def websockify_func(q):
- proc = Popen([path_from_root('third_party', 'websockify', 'other', 'websockify'), '-vvv', '8991', '127.0.0.1:8990'])
+ print >> sys.stderr, 'running websockify on %d, forward to tcp %d' % (self.port+1, self.port)
+ proc = Popen([path_from_root('third_party', 'websockify', 'other', 'websockify'), '-vvv', str(self.port+1), '127.0.0.1:' + str(self.port)])
+ #proc = Popen([path_from_root('third_party', 'websockify', 'websockify.py'), '-vvv', str(self.port+1), '127.0.0.1:' + str(self.port)])
q.put(proc.pid)
proc.communicate()
websockify_queue = multiprocessing.Queue()
self.websockify = multiprocessing.Process(target=websockify_func, args=(websockify_queue,))
self.websockify.start()
- self.pids.append(self.websockify.pid)
+ browser.pids_to_clean.append(self.websockify.pid)
while True:
if not websockify_queue.empty():
- self.pids.append(websockify_queue.get())
+ browser.pids_to_clean.append(websockify_queue.get())
break
time.sleep(0.1)
- print '[Websockify on processes %s]' % str(self.pids[-2:])
+ print '[Websockify on processes %s]' % str(browser.pids_to_clean[-2:])
def __exit__(self, *args, **kwargs):
- import signal
- for pid in self.pids:
- #os.kill(pid, signal.SIGTERM) # With this commented, we leave no children, but we hang the test harness on exit XXX
- print '[%d should be cleaned up automatically]' % pid
+ time.sleep(1)
+
+ # always run these tests last
+ # make sure to use different ports in each one because it takes a while for the processes to be cleaned up
+ def test_zz_websockets(self):
+ try:
+ with self.WebsockHarness(8990):
+ self.btest('websockets.c', expected='571')
+ finally:
+ self.clean_pids()
+
+ def make_relay_server(self, port1, port2):
+ def relay_server(q):
+ print >> sys.stderr, 'creating relay server on ports %d,%d' % (port1, port2)
+ proc = Popen(['python', path_from_root('tests', 'socket_relay.py'), str(port1), str(port2)])
+ q.put(proc.pid)
+ proc.communicate()
+ return relay_server
+
+ def test_zz_websockets_bi(self):
+ try:
+ with self.WebsockHarness(8992, self.make_relay_server(8992, 8994)):
+ with self.WebsockHarness(8994, no_server=True):
+ Popen(['python', EMCC, path_from_root('tests', 'websockets_bi_side.c'), '-o', 'side.html', '-DSOCKK=8995']).communicate()
+ self.btest('websockets_bi.c', expected='2499')
+ finally:
+ self.clean_pids()
- def test_zz_websockets(self): # always run this test last
- with self.WebsockHarness():
- self.btest('websockets.c', expected='571')
+ def test_zz_websockets_bi_listen(self):
+ try:
+ with self.WebsockHarness(6992, self.make_relay_server(6992, 6994)):
+ with self.WebsockHarness(6994, no_server=True):
+ Popen(['python', EMCC, path_from_root('tests', 'websockets_bi_side.c'), '-o', 'side.html', '-DSOCKK=6995']).communicate()
+ self.btest('websockets_bi_listener.c', expected='2499')
+ finally:
+ self.clean_pids()
+
+ def test_zz_websockets_gethostbyname(self):
+ try:
+ with self.WebsockHarness(7000):
+ self.btest('websockets_gethostbyname.c', expected='571', args=['-O2'])
+ finally:
+ self.clean_pids()
+
+ def zzztest_zz_websockets_bi_bigdata(self):
+ try:
+ with self.WebsockHarness(3992, self.make_relay_server(3992, 3994)):
+ with self.WebsockHarness(3994, no_server=True):
+ Popen(['python', EMCC, path_from_root('tests', 'websockets_bi_side_bigdata.c'), '-o', 'side.html', '-DSOCKK=3995', '-s', 'SOCKET_DEBUG=0', '-I' + path_from_root('tests')]).communicate()
+ self.btest('websockets_bi_bigdata.c', expected='0', args=['-s', 'SOCKET_DEBUG=0', '-I' + path_from_root('tests')])
+ finally:
+ self.clean_pids()
+
+ def zzztest_zz_enet(self):
+ try_delete(self.in_dir('enet'))
+ shutil.copytree(path_from_root('tests', 'enet'), self.in_dir('enet'))
+ pwd = os.getcwd()
+ os.chdir(self.in_dir('enet'))
+ Popen(['python', path_from_root('emconfigure'), './configure']).communicate()
+ Popen(['python', path_from_root('emmake'), 'make']).communicate()
+ enet = [self.in_dir('enet', '.libs', 'libenet.a'), '-I'+path_from_root('tests', 'enet', 'include')]
+ os.chdir(pwd)
+ Popen(['python', EMCC, path_from_root('tests', 'enet_server.c'), '-o', 'server.html', '-s', 'SOCKET_DEBUG=1'] + enet).communicate()
+
+ try:
+ with self.WebsockHarness(1234, self.make_relay_server(1234, 1236)):
+ with self.WebsockHarness(1236, no_server=True):
+ self.btest('enet_client.c', expected='cheez', args=enet+['-s', 'SOCKET_DEBUG=1'])
+ finally:
+ self.clean_pids()
elif 'benchmark' in str(sys.argv):
# Benchmarks. Run them with argument |benchmark|. To run a specific test, do
@@ -8869,13 +9329,13 @@ elif 'benchmark' in str(sys.argv):
print ' JavaScript: mean: %.3f (+-%.3f) secs median: %.3f range: %.3f-%.3f (noise: %3.3f%%) (%d runs)' % (mean, std, median, min(times), max(times), 100*std/mean, TEST_REPS)
print ' Native : mean: %.3f (+-%.3f) secs median: %.3f range: %.3f-%.3f (noise: %3.3f%%) JS is %.2f X slower' % (mean_native, std_native, median_native, min(native_times), max(native_times), 100*std_native/mean_native, final)
- def do_benchmark(self, src, args=[], expected_output='FAIL', emcc_args=[]):
+ def do_benchmark(self, name, src, args=[], expected_output='FAIL', emcc_args=[]):
dirname = self.get_dir()
- filename = os.path.join(dirname, 'src.cpp')
+ filename = os.path.join(dirname, name + '.cpp')
f = open(filename, 'w')
f.write(src)
f.close()
- final_filename = os.path.join(dirname, 'src.js')
+ final_filename = os.path.join(dirname, name + '.js')
try_delete(final_filename)
output = Popen(['python', EMCC, filename, '-O3',
@@ -8938,7 +9398,7 @@ elif 'benchmark' in str(sys.argv):
return 1;
}
'''
- self.do_benchmark(src, [], 'lastprime: 1297001.')
+ self.do_benchmark('primes', src, [], 'lastprime: 1297001.')
def test_memops(self):
src = '''
@@ -8961,7 +9421,7 @@ elif 'benchmark' in str(sys.argv):
return 1;
}
'''
- self.do_benchmark(src, [], 'final: 720.')
+ self.do_benchmark('memops', src, [], 'final: 720.')
def zzztest_files(self):
src = r'''
@@ -9047,11 +9507,11 @@ elif 'benc