diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/cases/floatundefinvoke_fastcomp.ll | 30 | ||||
-rw-r--r-- | tests/cases/floatundefinvoke_fastcomp.txt | 3 | ||||
-rw-r--r-- | tests/core/test_exceptions_white_list_empty.out | 0 | ||||
-rw-r--r-- | tests/core/test_set_align.c | 50 | ||||
-rw-r--r-- | tests/core/test_set_align.out | 8 | ||||
-rw-r--r-- | tests/gl_teximage.c | 120 | ||||
-rw-r--r-- | tests/test_browser.py | 3 | ||||
-rw-r--r-- | tests/test_core.py | 95 | ||||
-rw-r--r-- | tests/test_other.py | 20 | ||||
-rw-r--r-- | tests/test_sanity.py | 2 |
10 files changed, 312 insertions, 19 deletions
diff --git a/tests/cases/floatundefinvoke_fastcomp.ll b/tests/cases/floatundefinvoke_fastcomp.ll new file mode 100644 index 00000000..215506ef --- /dev/null +++ b/tests/cases/floatundefinvoke_fastcomp.ll @@ -0,0 +1,30 @@ +; ModuleID = 'a.o' +target datalayout = "e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-p:32:32:32-v128:32:128-n32-S128" +target triple = "asmjs-unknown-emscripten" + +@.str = private unnamed_addr constant [11 x i8] c"float: %f\0A\00", align 1 + +define void @_Z10printFloatf(float %f) #0 { +entry: + %conv = fpext float %f to double + %call = tail call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([11 x i8]* @.str, i32 0, i32 0), double %conv) + ret void +} + +define i32 @main() #1 { +entry: + tail call void @_Z10printFloatf(float 1.000000e+00) + call void @emscripten_preinvoke() + call void @_Z10printFloatf(float undef) + %last = call i32 @emscripten_postinvoke() + %lastf = sitofp i32 %last to float + tail call void @_Z10printFloatf(float %lastf) + ret i32 1 +} + +declare void @emscripten_preinvoke() +declare i32 @emscripten_postinvoke() +declare i32 @printf(i8* nocapture, ...) #1 + +attributes #0 = { noinline nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } diff --git a/tests/cases/floatundefinvoke_fastcomp.txt b/tests/cases/floatundefinvoke_fastcomp.txt new file mode 100644 index 00000000..5e19391e --- /dev/null +++ b/tests/cases/floatundefinvoke_fastcomp.txt @@ -0,0 +1,3 @@ +float: 1.000000 +float: 0.000000 +float: 0.000000 diff --git a/tests/core/test_exceptions_white_list_empty.out b/tests/core/test_exceptions_white_list_empty.out new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/tests/core/test_exceptions_white_list_empty.out diff --git a/tests/core/test_set_align.c b/tests/core/test_set_align.c new file mode 100644 index 00000000..26158ef4 --- /dev/null +++ b/tests/core/test_set_align.c @@ -0,0 +1,50 @@ + +#include <stdio.h> +#include <emscripten.h> + +volatile char data[16]; + +__attribute__((noinline)) void *get_aligned(int align) +{ + char *ptr = (char*)(((int)(data + 7)) & ~7); // Make 8-byte aligned + ptr += align; // Now 'align' aligned + return (void*)ptr; +} + +int main() +{ + emscripten_align4_double *d4 = (emscripten_align4_double*)get_aligned(4); + *d4 = 17.0; + printf("addr: %d, value: %f\n", ((int)d4) % 8, *d4); + + emscripten_align2_double *d2 = (emscripten_align2_double*)get_aligned(2); + *d2 = 18.0; + printf("addr: %d, value: %f\n", ((int)d2) % 8, *d2); + + emscripten_align1_double *d1 = (emscripten_align1_double*)get_aligned(1); + *d1 = 19.0; + printf("addr: %d, value: %f\n", ((int)d1) % 8, *d1); + + emscripten_align2_float *f2 = (emscripten_align2_float*)get_aligned(2); + *f2 = 20.0; + printf("addr: %d, value: %f\n", ((int)f2) % 4, *f2); + + emscripten_align1_float *f1 = (emscripten_align1_float*)get_aligned(1); + *f1 = 21.0; + printf("addr: %d, value: %f\n", ((int)f1) % 4, *f1); + + emscripten_align2_int *i2 = (emscripten_align2_int*)get_aligned(2); + *i2 = 22; + printf("addr: %d, value: %d\n", ((int)i2) % 4, *i2); + + emscripten_align1_int *i1 = (emscripten_align1_int*)get_aligned(1); + *i1 = 23; + printf("addr: %d, value: %d\n", ((int)i1) % 4, *i1); + + emscripten_align1_short *s1 = (emscripten_align1_short*)get_aligned(1); + *s1 = 24; + printf("addr: %d, value: %d\n", ((int)s1) % 4, (int)*s1); + + return 0; +} + diff --git a/tests/core/test_set_align.out b/tests/core/test_set_align.out new file mode 100644 index 00000000..55e377b0 --- /dev/null +++ b/tests/core/test_set_align.out @@ -0,0 +1,8 @@ +addr: 4, value: 17.000000 +addr: 2, value: 18.000000 +addr: 1, value: 19.000000 +addr: 2, value: 20.000000 +addr: 1, value: 21.000000 +addr: 2, value: 22 +addr: 1, value: 23 +addr: 1, value: 24 diff --git a/tests/gl_teximage.c b/tests/gl_teximage.c new file mode 100644 index 00000000..9cafce9c --- /dev/null +++ b/tests/gl_teximage.c @@ -0,0 +1,120 @@ +/* + * GLES2 test for glTexImage2D parameters + * + * Original author: Jason Green <jason@transgaming.com> + * + */ +#include "GLES2/gl2.h" +#include "SDL/SDL.h" + +#include <stdio.h> +#include <stdlib.h> +#include <emscripten.h> +#include <unistd.h> + +typedef enum { + TEST_STATUS_SUCCESS = 0, + TEST_STATUS_FAILURE = 1 +} TestStatus; + +/* Report success or failure (1 or 0) to Emscripten's test harness. Also, exit + * with the given error code. */ +static void exit_with_status(TestStatus code) +{ +#ifdef REPORT_RESULT + int result = (code == TEST_STATUS_SUCCESS) ? 1 : 0; + REPORT_RESULT(); +#endif + + exit(code); +} + +/* Loop over all glGetError() results until GL reports GL_NO_ERROR */ +static void clear_gl_errors() +{ + GLenum err; + do { + err = glGetError(); + } while (err != GL_NO_ERROR); +} + +int main(int argc, char *argv[]) +{ + TestStatus passed = TEST_STATUS_SUCCESS; + SDL_Surface *screen; + + if (SDL_Init(SDL_INIT_VIDEO) != 0) { + printf("SDL_Init failed with %s\n", SDL_GetError()); + exit_with_status(TEST_STATUS_FAILURE); + } + + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + screen = SDL_SetVideoMode(640, 480, 16, SDL_OPENGL); + if (!screen) { + printf("SDL_SetVideoMode failed with %s\n", SDL_GetError()); + exit_with_status(TEST_STATUS_FAILURE); + } + + GLuint texture; + glGenTextures(1, &texture); + + glBindTexture(GL_TEXTURE_2D, texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + // Allocate space for a 32x32 image with 4 bytes per pixel. + // No need to fill it with any useful information, as these tests are + // only designed to make sure glTexImage2D doesn't crash on unsupported + // formats. + void* pixels = malloc(4 * 32 * 32); + if (pixels == NULL) { + printf("Unable to allocate pixel data\n"); + exit_with_status(TEST_STATUS_FAILURE); + } + + // First, try 0xffff for the internal format - should fail + glTexImage2D(GL_TEXTURE_2D, 0, 0xffff, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + GLenum err = glGetError(); + if (err == GL_NO_ERROR) { + printf("internal format == 0xffff succeeded, but should have failed\n"); + passed = TEST_STATUS_FAILURE; + } + clear_gl_errors(); + + // Try 0xffff for the format - should fail + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, 0xffff, GL_UNSIGNED_BYTE, pixels); + err = glGetError(); + if (err == GL_NO_ERROR) { + printf("format == 0xffff succeeded, but should have failed\n"); + passed = TEST_STATUS_FAILURE; + } + clear_gl_errors(); + + // Try 0xffff for the type - should fail + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, 0xffff, pixels); + err = glGetError(); + if (err == GL_NO_ERROR) { + printf("type == 0xffff succeeded, but should have failed\n"); + passed = TEST_STATUS_FAILURE; + } + clear_gl_errors(); + + // Try GL_RGBA/GL_UNSIGNED_BYTE - should succeed + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + err = glGetError(); + if (err != GL_NO_ERROR) { + printf("GL_RGBA/GL_UNSIGNED_BYTE failed with %x, but should have succeeded\n", err); + passed = TEST_STATUS_FAILURE; + } + clear_gl_errors(); + + // Clean up objects + glBindTexture(GL_TEXTURE_2D, 0); + glDeleteTextures(1, &texture); + free(pixels); + + // 'screen' is freed implicitly by SDL_Quit() + SDL_Quit(); + + exit_with_status(passed); +} diff --git a/tests/test_browser.py b/tests/test_browser.py index aedc926a..c8e07b25 100644 --- a/tests/test_browser.py +++ b/tests/test_browser.py @@ -1425,6 +1425,9 @@ keydown(100);keyup(100); // trigger the end def test_sdlglshader(self): self.btest('sdlglshader.c', reference='sdlglshader.png', args=['-O2', '--closure', '1', '-s', 'LEGACY_GL_EMULATION=1']) + def test_gl_glteximage(self): + self.btest('gl_teximage.c', '1') + def test_gl_ps(self): # pointers and a shader shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) diff --git a/tests/test_core.py b/tests/test_core.py index 7c317894..505a051b 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -1166,7 +1166,6 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co self.do_run_from_file(src, output) def test_longjmp_repeat(self): - if os.environ.get('EMCC_FAST_COMPILER') == '0': Settings.MAX_SETJMPS = 1 # todo: do this more strict thing in fastcomp too test_path = path_from_root('tests', 'core', 'test_longjmp_repeat') src, output = (test_path + s for s in ('.in', '.out')) self.do_run_from_file(src, output) @@ -1190,8 +1189,6 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co self.do_run_from_file(src, output) def test_setjmp_many(self): - if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('todo in fastcomp: make MAX_SETJMPS take effect') - src = r''' #include <stdio.h> #include <setjmp.h> @@ -1203,9 +1200,42 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co return 0; } ''' - for num in [Settings.MAX_SETJMPS, Settings.MAX_SETJMPS+1]: - print num - self.do_run(src.replace('NUM', str(num)), '0\n' * num if num <= Settings.MAX_SETJMPS or not Settings.ASM_JS else 'build with a higher value for MAX_SETJMPS') + for maxx in [Settings.MAX_SETJMPS/2, Settings.MAX_SETJMPS, 2*Settings.MAX_SETJMPS]: + Settings.MAX_SETJMPS = maxx + for num in [maxx, maxx+1]: + print maxx, num + self.do_run(src.replace('NUM', str(num)), '0\n' * num if num <= Settings.MAX_SETJMPS or not Settings.ASM_JS else 'build with a higher value for MAX_SETJMPS') + + def test_setjmp_many_2(self): + if os.environ.get('EMCC_FAST_COMPILER') == '0': return self.skip('non-fastcomp do not hit the limit.') + + src = r''' +#include <setjmp.h> +#include <stdio.h> + +jmp_buf env; + +void luaWork(int d){ + int x; + printf("d is at %d\n", d); + + longjmp(env, 1); +} + +int main() +{ + const int ITERATIONS=25; + for(int i = 0; i < ITERATIONS; i++){ + if(!setjmp(env)){ + luaWork(i); + } + } + return 0; +} +''' + + self.do_run(src, r'''d is at 19 +too many setjmps in a function call, build with a higher value for MAX_SETJMPS''') def test_exceptions(self): if Settings.QUANTUM_SIZE == 1: return self.skip("we don't support libcxx in q1") @@ -1317,6 +1347,33 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co test_path = path_from_root('tests', 'core', 'test_exceptions_white_list') src, output = (test_path + s for s in ('.in', '.out')) self.do_run_from_file(src, output) + size = len(open('src.cpp.o.js').read()) + shutil.copyfile('src.cpp.o.js', 'orig.js') + + if os.environ.get('EMCC_FAST_COMPILER') != '0': + # check that an empty whitelist works properly (as in, same as exceptions disabled) + empty_output = path_from_root('tests', 'core', 'test_exceptions_white_list_empty.out') + + Settings.EXCEPTION_CATCHING_WHITELIST = [] + self.do_run_from_file(src, empty_output) + empty_size = len(open('src.cpp.o.js').read()) + shutil.copyfile('src.cpp.o.js', 'empty.js') + + Settings.EXCEPTION_CATCHING_WHITELIST = ['fake'] + self.do_run_from_file(src, empty_output) + fake_size = len(open('src.cpp.o.js').read()) + shutil.copyfile('src.cpp.o.js', 'fake.js') + + Settings.DISABLE_EXCEPTION_CATCHING = 1 + self.do_run_from_file(src, empty_output) + disabled_size = len(open('src.cpp.o.js').read()) + shutil.copyfile('src.cpp.o.js', 'disabled.js') + + assert size - empty_size > 2000, [empty_size, size] # big change when we disable entirely + assert size - fake_size > 2000, [fake_size, size] + assert empty_size == fake_size, [empty_size, fake_size] + assert empty_size - disabled_size < 100, [empty_size, disabled_size] # full disable removes a tiny bit more + assert fake_size - disabled_size < 100, [disabled_size, fake_size] def test_exceptions_white_list_2(self): Settings.DISABLE_EXCEPTION_CATCHING = 2 @@ -1923,6 +1980,15 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co self.do_run_from_file(src, output) + def test_set_align(self): + if self.run_name == 'slow2asm': return self.skip('FIXME in slow2asm') + + Settings.SAFE_HEAP = 1 + + test_path = path_from_root('tests', 'core', 'test_set_align') + src, output = (test_path + s for s in ('.c', '.out')) + self.do_run_from_file(src, output) + def test_emscripten_api(self): #if Settings.MICRO_OPTS or Settings.RELOOP or Building.LLVM_OPTS: return self.skip('FIXME') @@ -2038,10 +2104,10 @@ def process(filename): if self.emcc_args and '-O2' in self.emcc_args: # Make sure ALLOW_MEMORY_GROWTH generates different code (should be less optimized) - code_start = 'var TOTAL_MEMORY = ' + code_start = 'var TOTAL_MEMORY' fail = fail[fail.find(code_start):] win = win[win.find(code_start):] - assert len(fail) < len(win), 'failing code - without memory growth on - is more optimized, and smaller' + assert len(fail) < len(win), 'failing code - without memory growth on - is more optimized, and smaller' + str([len(fail), len(win)]) def test_ssr(self): # struct self-ref src = ''' @@ -3214,7 +3280,7 @@ def process(filename): break else: raise Exception('Could not find symbol table!') - table = table[table.find('{'):table.rfind('}')+1] + table = table[table.find('{'):table.find('}')+1] # ensure there aren't too many globals; we don't want unnamed_addr assert table.count(',') <= 4 @@ -4664,8 +4730,7 @@ int main(void) { 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.CORRECT_SIGNS = 1 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() @@ -5424,9 +5489,6 @@ def process(filename): ### 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 - post = ''' def process(filename): src = \'\'\' @@ -5470,6 +5532,11 @@ def process(filename): self.do_run_from_file(src, output, post_build=post) + if self.emcc_args is not None and '-O2' in self.emcc_args: + print 'with closure' + self.emcc_args += ['--closure', '1'] + self.do_run_from_file(src, output, post_build=post) + def test_pgo(self): if Settings.ASM_JS: return self.skip('PGO does not work in asm mode') diff --git a/tests/test_other.py b/tests/test_other.py index 5553a7b1..03859a4e 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -203,6 +203,10 @@ Options that are modified or new in %s include: (['--typed-arrays', '1'], lambda generated: 'IHEAPU = ' in generated, 'typed arrays 1 selected'), (['--typed-arrays', '2'], lambda generated: 'new Uint16Array' in generated and 'new Uint32Array' in generated, 'typed arrays 2 selected'), (['--llvm-opts', '1'], lambda generated: '_puts(' in generated, 'llvm opts requested'), + ([], lambda generated: '// The Module object' in generated, 'without opts, comments in shell code'), + (['-O2'], lambda generated: '// The Module object' not in generated, 'with opts, no comments in shell code'), + (['-O2', '-g2'], lambda generated: '// The Module object' not in generated, 'with -g2, no comments in shell code'), + (['-O2', '-g3'], lambda generated: '// The Module object' in generated, 'with -g3, yes comments in shell code'), ]: print params, text self.clear() @@ -1090,22 +1094,30 @@ This pointer might make sense in another type signature: i: 0 Building.emar('cr', lib_b, [b + '.o', c + '.o']) # libB.a with b.c.o,c.c.o args = ['-s', 'ERROR_ON_UNDEFINED_SYMBOLS=1', main, '-o', 'a.out.js'] - libs = [lib_a, lib_b] + libs_list = [lib_a, lib_b] # lib_a does not satisfy any symbols from main, so it will not be included, # and there will be an unresolved symbol. - output = Popen([PYTHON, EMCC] + args + libs, stdout=PIPE, stderr=PIPE).communicate() + output = Popen([PYTHON, EMCC] + args + libs_list, stdout=PIPE, stderr=PIPE).communicate() self.assertContained('error: unresolved symbol: x', output[1]) # -Wl,--start-group and -Wl,--end-group around the libs will cause a rescan # of lib_a after lib_b adds undefined symbol "x", so a.c.o will now be # included (and the link will succeed). - libs = ['-Wl,--start-group'] + libs + ['-Wl,--end-group'] + libs = ['-Wl,--start-group'] + libs_list + ['-Wl,--end-group'] output = Popen([PYTHON, EMCC] + args + libs, stdout=PIPE, stderr=PIPE).communicate() out_js = os.path.join(self.get_dir(), 'a.out.js') assert os.path.exists(out_js), '\n'.join(output) self.assertContained('result: 42', run_js(out_js)) + # -( and -) should also work. + args = ['-s', 'ERROR_ON_UNDEFINED_SYMBOLS=1', main, '-o', 'a2.out.js'] + libs = ['-Wl,-('] + libs_list + ['-Wl,-)'] + output = Popen([PYTHON, EMCC] + args + libs, stdout=PIPE, stderr=PIPE).communicate() + out_js = os.path.join(self.get_dir(), 'a2.out.js') + assert os.path.exists(out_js), '\n'.join(output) + self.assertContained('result: 42', run_js(out_js)) + def test_redundant_link(self): lib = "int mult() { return 1; }" lib_name = os.path.join(self.get_dir(), 'libA.c') @@ -2210,7 +2222,7 @@ void wakaw::Cm::RasterBase<wakaw::watwat::Polocator?>(unsigned int*, unsigned in test_js_closure_0 = open(path_from_root('tests', 'Module-exports', 'test.js')).read() # Check that test.js compiled with --closure 0 contains "module['exports'] = Module;" - assert "module['exports'] = Module;" in test_js_closure_0 + assert ("module['exports'] = Module;" in test_js_closure_0) or ('module["exports"]=Module' in test_js_closure_0) # Check that main.js (which requires test.js) completes successfully when run in node.js # in order to check that the exports are indeed functioning correctly. diff --git a/tests/test_sanity.py b/tests/test_sanity.py index 3d3da523..3ebd49b6 100644 --- a/tests/test_sanity.py +++ b/tests/test_sanity.py @@ -240,7 +240,7 @@ class sanity(RunnerCore): os.chmod(path_from_root('tests', 'fake', 'bin', 'llc'), stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC) os.chmod(path_from_root('tests', 'fake', 'bin', 'clang++'), stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC) try_delete(SANITY_FILE) - output = self.check_working(EMCC, 'did not see a source tree above LLVM_DIR, could not verify version numbers match') + output = self.check_working(EMCC, 'did not see a source tree above the LLVM root directory') VERSION_WARNING = 'Emscripten, llvm and clang versions do not match, this is dangerous' |