diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/cases/phiptrtoint.ll | 138 | ||||
-rw-r--r-- | tests/cases/phiptrtoint.txt | 0 | ||||
-rw-r--r-- | tests/cases/sub_11_0.ll | 16 | ||||
-rw-r--r-- | tests/gles2_uniform_arrays.cpp | 121 | ||||
-rw-r--r-- | tests/glut_wheelevents.c | 68 | ||||
-rw-r--r-- | tests/sdl_rotozoom.c | 2 | ||||
-rw-r--r-- | tests/sdl_rotozoom.png | bin | 431168 -> 711242 bytes | |||
-rw-r--r-- | tests/stdio/test_rename.c | 10 | ||||
-rw-r--r-- | tests/test_browser.py | 9 | ||||
-rw-r--r-- | tests/test_core.py | 50 | ||||
-rw-r--r-- | tests/test_other.py | 70 | ||||
-rw-r--r-- | tests/test_sanity.py | 8 |
12 files changed, 469 insertions, 23 deletions
diff --git a/tests/cases/phiptrtoint.ll b/tests/cases/phiptrtoint.ll new file mode 100644 index 00000000..d682dc06 --- /dev/null +++ b/tests/cases/phiptrtoint.ll @@ -0,0 +1,138 @@ +; ModuleID = '/tmp/tmpJctwj0/bug.bc' +; just an asm validation check, no output +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:32" +target triple = "le32-unknown-nacl" + +%"class.test::Processor" = type { i32, %"class.test::StateMachine" } +%"class.test::StateMachine" = type { { i32, i32 } } + +@_ZN4test9ProcessorC1Ev = alias internal void (%"class.test::Processor"*)* @_ZN4test9ProcessorC2Ev +@_ZN4test9ProcessorD1Ev = alias internal void (%"class.test::Processor"*)* @_ZN4test9ProcessorD2Ev + +define internal void @_ZN4test9ProcessorC2Ev(%"class.test::Processor"* nocapture %this) unnamed_addr nounwind align 2 { + %1 = getelementptr inbounds %"class.test::Processor"* %this, i32 0, i32 0 + store i32 0, i32* %1, align 4 + %2 = getelementptr inbounds %"class.test::Processor"* %this, i32 0, i32 1, i32 0 + store { i32, i32 } zeroinitializer, { i32, i32 }* %2, align 4 + ret void +} + +define internal void @_ZN4test9ProcessorD2Ev(%"class.test::Processor"* nocapture %this) unnamed_addr nounwind readnone align 2 { + ret void +} + +define internal zeroext i1 @_ZN4test9Processor16handleFirstStateEv(%"class.test::Processor"* nocapture %this) align 2 { + %1 = tail call i32 @rand() + %2 = getelementptr inbounds %"class.test::Processor"* %this, i32 0, i32 0 + %3 = load i32* %2, align 4 + %4 = add nsw i32 %3, %1 + store i32 %4, i32* %2, align 4 + %5 = and i32 %4, 1 + %6 = icmp eq i32 %5, 0 + ret i1 %6 +} + +declare i32 @rand() + +define internal zeroext i1 @_ZN4test9Processor15handleLastStateEv(%"class.test::Processor"* nocapture %this) align 2 { + %1 = tail call i32 @rand() + %2 = getelementptr inbounds %"class.test::Processor"* %this, i32 0, i32 0 + %3 = load i32* %2, align 4 + %4 = add nsw i32 %3, %1 + store i32 %4, i32* %2, align 4 + ret i1 true +} + +define internal zeroext i1 @_ZN4test9Processor3runEv(%"class.test::Processor"* %this) align 2 { + %1 = getelementptr inbounds %"class.test::Processor"* %this, i32 0, i32 1, i32 0 + store { i32, i32 } { i32 ptrtoint (i1 (%"class.test::Processor"*)* @_ZN4test9Processor16handleFirstStateEv to i32), i32 0 }, { i32, i32 }* %1, align 4 + %2 = bitcast %"class.test::Processor"* %this to i8* + br label %.backedge + +.backedge: ; preds = %25, %..backedge_crit_edge, %0 + %3 = phi { i32, i32 } [ { i32 ptrtoint (i1 (%"class.test::Processor"*)* @_ZN4test9Processor16handleFirstStateEv to i32), i32 0 }, %0 ], [ %.pre.pre, %..backedge_crit_edge ], [ { i32 ptrtoint (i1 (%"class.test::Processor"*)* @_ZN4test9Processor15handleLastStateEv to i32), i32 0 }, %25 ] + %.fca.0.extract = extractvalue { i32, i32 } %3, 0 + %.fca.1.extract = extractvalue { i32, i32 } %3, 1 + %4 = icmp ne i32 %.fca.0.extract, ptrtoint (i1 (%"class.test::Processor"*)* @_ZN4test9Processor15handleLastStateEv to i32) + %5 = icmp ne i32 %.fca.0.extract, 0 + %6 = icmp ne i32 %.fca.1.extract, 0 + %7 = and i1 %5, %6 + %8 = or i1 %4, %7 + %9 = getelementptr inbounds i8* %2, i32 %.fca.1.extract + %10 = bitcast i8* %9 to %"class.test::Processor"* + %11 = and i32 %.fca.0.extract, 1 + %12 = icmp eq i32 %11, 0 + br i1 %12, label %20, label %13 + +; <label>:13 ; preds = %.backedge + %14 = bitcast i8* %9 to i8** + %15 = load i8** %14, align 4 + %16 = add i32 %.fca.0.extract, -1 + %17 = getelementptr i8* %15, i32 %16 + %18 = bitcast i8* %17 to i1 (%"class.test::Processor"*)** + %19 = load i1 (%"class.test::Processor"*)** %18, align 4 + br label %_ZN4test12StateMachineINS_9ProcessorEE11handleStateEPS1_.exit + +; <label>:20 ; preds = %.backedge + %21 = inttoptr i32 %.fca.0.extract to i1 (%"class.test::Processor"*)* + br label %_ZN4test12StateMachineINS_9ProcessorEE11handleStateEPS1_.exit + +_ZN4test12StateMachineINS_9ProcessorEE11handleStateEPS1_.exit: ; preds = %20, %13 + %22 = phi i1 (%"class.test::Processor"*)* [ %19, %13 ], [ %21, %20 ] + %23 = tail call zeroext i1 %22(%"class.test::Processor"* %10) + br i1 %8, label %24, label %26 + +; <label>:24 ; preds = %_ZN4test12StateMachineINS_9ProcessorEE11handleStateEPS1_.exit + br i1 %23, label %25, label %..backedge_crit_edge + +..backedge_crit_edge: ; preds = %24 + %.pre.pre = load { i32, i32 }* %1, align 4 + br label %.backedge + +; <label>:25 ; preds = %24 + store { i32, i32 } { i32 ptrtoint (i1 (%"class.test::Processor"*)* @_ZN4test9Processor15handleLastStateEv to i32), i32 0 }, { i32, i32 }* %1, align 4 + br label %.backedge + +; <label>:26 ; preds = %_ZN4test12StateMachineINS_9ProcessorEE11handleStateEPS1_.exit + ret i1 %23 +} + +define internal i32 @_ZNK4test9Processor6resultEv(%"class.test::Processor"* nocapture %this) nounwind readonly align 2 { + %1 = getelementptr inbounds %"class.test::Processor"* %this, i32 0, i32 0 + %2 = load i32* %1, align 4 + ret i32 %2 +} + +define i32 @runProcess() { + %processor = alloca %"class.test::Processor", align 4 + call void @_ZN4test9ProcessorC1Ev(%"class.test::Processor"* %processor) + %1 = invoke zeroext i1 @_ZN4test9Processor3runEv(%"class.test::Processor"* %processor) + to label %2 unwind label %5 + +; <label>:2 ; preds = %0 + %3 = invoke i32 @_ZNK4test9Processor6resultEv(%"class.test::Processor"* %processor) + to label %4 unwind label %5 + +; <label>:4 ; preds = %2 + call void @_ZN4test9ProcessorD1Ev(%"class.test::Processor"* %processor) + ret i32 %3 + +; <label>:5 ; preds = %2, %0 + %6 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + cleanup + invoke void @_ZN4test9ProcessorD1Ev(%"class.test::Processor"* %processor) + to label %7 unwind label %8 + +; <label>:7 ; preds = %5 + resume { i8*, i32 } %6 + +; <label>:8 ; preds = %5 + %9 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + catch i8* null + call void @_ZSt9terminatev() noreturn nounwind + unreachable +} + +declare i32 @__gxx_personality_v0(...) + +declare void @_ZSt9terminatev() diff --git a/tests/cases/phiptrtoint.txt b/tests/cases/phiptrtoint.txt new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/tests/cases/phiptrtoint.txt diff --git a/tests/cases/sub_11_0.ll b/tests/cases/sub_11_0.ll new file mode 100644 index 00000000..7f0bb285 --- /dev/null +++ b/tests/cases/sub_11_0.ll @@ -0,0 +1,16 @@ +; ModuleID = 'tests/hello_world.bc' + +@.str = private unnamed_addr constant [15 x i8] c"hello, world!\0A\00", align 1 ; [#uses=1 type=[15 x i8]*] + +; [#uses=0] +define i32 @main() { +entry: + %retval = alloca i32, align 4 ; [#uses=1 type=i32*] + %0 = sub nsw i32 1, 1 + store i32 %0, i32* %retval + %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0)) ; [#uses=0 type=i32] + ret i32 1 +} + +; [#uses=1] +declare i32 @printf(i8*, ...) diff --git a/tests/gles2_uniform_arrays.cpp b/tests/gles2_uniform_arrays.cpp new file mode 100644 index 00000000..84e394dc --- /dev/null +++ b/tests/gles2_uniform_arrays.cpp @@ -0,0 +1,121 @@ +#include "SDL/SDL_opengl.h" +#include "SDL/SDL.h" + +#include <stdio.h> +#include <string.h> +#include <assert.h> + +void RunTest(int testVariant) +{ + GLuint vs = 0; + + const char *vsCode = "#version 100\n" + "attribute vec4 pos; void main() { gl_Position = pos; }"; + + vs = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(vs, 1, &vsCode, NULL); + glCompileShader(vs); + + GLuint ps = 0; + + const char *psCode = "#version 100\n" + "precision lowp float;\n" + "uniform vec3 color;\n" + "uniform vec3 colors[3];\n" + "void main() { gl_FragColor = vec4(color,1) + vec4(colors[0].r, colors[1].g, colors[2].b, 1); }"; + + ps = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(ps, 1, &psCode, NULL); + glCompileShader(ps); + + GLuint program = 0; + program = glCreateProgram(); + glAttachShader(program, vs); + glAttachShader(program, ps); + glBindAttribLocation(program, 0, "pos"); + glLinkProgram(program); + + int color_loc = glGetUniformLocation(program, "color"); + assert(color_loc != -1); + + glUseProgram(program); + float col[3] = { 0.2f, 0.2f, 0.2f }; + glUniform3fv(color_loc, 1, col); + + int loc = glGetUniformLocation(program, "colors"); + assert(loc != -1); + // In previous Emscripten GL layer code, calling glGetUniformLocation would do extra caching operations that interacts how glUniform** after that will work, + // so to exhibit extra issues in old code (and to keep new code from regressing), must test both with and without excess glGetUniformLocation calls. + if ((testVariant&1) != 0) + { + // Deliberately check in odd order to make sure any kind of lazy operations won't affect the indices we get. + assert(glGetUniformLocation(program, "colors[2]") == loc+2); + assert(glGetUniformLocation(program, "colors[0]") == loc); + assert(glGetUniformLocation(program, "colors[3]") == -1); + assert(glGetUniformLocation(program, "colors[1]") == loc+1); + assert(glGetUniformLocation(program, "colors[]") == loc); + assert(glGetUniformLocation(program, "colors[-100]") == -1); + assert(glGetUniformLocation(program, "colors[bleh]") == -1); + } + + float colors[4*3] = { 1,0,0, 0,0.5,0, 0,0,0.2, 1,1,1 }; + + if ((testVariant&2)!=0) + { + glUniform3fv(loc+1, 3, colors+3); // Pass the actual colors (testing a nonzero location offset), but do a mistake by setting one index too many. Spec says this should be gracefully handled, and that excess elements are ignored. + assert(glGetError() == GL_NO_ERROR); + glUniform3fv(loc, 1, colors); // Set the first index as well. + assert(glGetError() == GL_NO_ERROR); + } + else + { + glUniform3fv(loc, 4, colors); // Just directly set the full array. + assert(glGetError() == GL_NO_ERROR); + } + + assert(glGetError() == GL_NO_ERROR); + + GLuint vbo = 0; + const GLfloat v[] = { -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1 }; + glGenBuffers(1, &vbo); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(v), v, GL_STATIC_DRAW); + + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2*sizeof(GLfloat), 0); + glEnableVertexAttribArray(0); + + glDrawArrays(GL_TRIANGLES, 0, 6); + + unsigned char pixel[4]; + glReadPixels(1,1,1,1,GL_RGBA,GL_UNSIGNED_BYTE, pixel); + //printf("%d,%d,%d,%d\n", pixel[0], pixel[1], pixel[2], pixel[3]); + assert(pixel[0] == 255); + assert(pixel[1] == 178); + assert(pixel[2] == 102); + assert(pixel[3] == 255); + + printf("OK: Case %d passed.\n", testVariant); + // Lazy, don't clean up afterwards. +} + +int main(int argc, char *argv[]) +{ + SDL_Surface *screen; + + // Slightly different SDL initialization + if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) { + printf("Unable to initialize SDL: %s\n", SDL_GetError()); + return 1; + } + + screen = SDL_SetVideoMode( 640, 480, 16, SDL_OPENGL ); // *changed* + if ( !screen ) { + printf("Unable to set video mode: %s\n", SDL_GetError()); + return 1; + } + + for(int i = 0; i < 4; ++i) + RunTest(i); + + return 0; +} diff --git a/tests/glut_wheelevents.c b/tests/glut_wheelevents.c new file mode 100644 index 00000000..7be01636 --- /dev/null +++ b/tests/glut_wheelevents.c @@ -0,0 +1,68 @@ +#include <stdio.h> +#include <stdlib.h> +#include <GL/glut.h> +#include <EGL/egl.h> +#include <emscripten.h> + +#define MULTILINE(...) #__VA_ARGS__ + +int wheel_up = 0; +int wheel_down = 0; + +int result = 0; + +void mouseCB(int button, int state, int x, int y) +{ + if(button == 3) + { + wheel_up = 1; + } + else if (button == 4) + { + wheel_down = 1; + } +} + +int main(int argc, char *argv[]) +{ + emscripten_run_script(MULTILINE( + Module.injectWheelEvent = function(x, y, delta) { + var isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1; + var event = document.createEvent("MouseEvents"); + if (!isFirefox) { + // mouse wheel event for IE9, Chrome, Safari, Opera + event.initMouseEvent('mousewheel', true, true, window, + 0, Module['canvas'].offsetLeft + x, Module['canvas'].offsetTop + y, Module['canvas'].offsetLeft + x, Module['canvas'].offsetTop + y, + 0, 0, 0, 0, 0, null); + event.wheelDelta = delta; + } else { + // mouse wheel event for Firefox, the delta sign is inversed for that browser and is stored in the detail property of the mouse event + event.initMouseEvent('DOMMouseScroll', true, true, window, + -delta, Module['canvas'].offsetLeft + x, Module['canvas'].offsetTop + y, Module['canvas'].offsetLeft + x, Module['canvas'].offsetTop + y, + 0, 0, 0, 0, 0, null); + } + Module['canvas'].dispatchEvent(event); + } + )); + + + glutInit(&argc, argv); + + glutMouseFunc(&mouseCB); + + // inject wheel up event (delta > 0) + emscripten_run_script("Module.injectWheelEvent(100, 100, 1)"); + if (wheel_up) { + printf("%s\n", "mouse wheel up event received"); + } + // inject wheel down event (delta < 0) + emscripten_run_script("Module.injectWheelEvent(100, 100, -1)"); + if (wheel_down) { + printf("%s\n", "mouse wheel down event received"); + } + + result = wheel_up && wheel_down; + + REPORT_RESULT(); + return 0; +} diff --git a/tests/sdl_rotozoom.c b/tests/sdl_rotozoom.c index cdbdcc6f..2c0d35df 100644 --- a/tests/sdl_rotozoom.c +++ b/tests/sdl_rotozoom.c @@ -38,7 +38,7 @@ int main(int argc, char **argv) { sprite[2] = zoomSurface(sprite[0], 0.5, 0.5, SMOOTHING_ON); sprite[3] = zoomSurface(sprite[1], 0.5, 0.5, SMOOTHING_ON); sprite[4] = rotozoomSurface(sprite[0], -20, 0.3, SMOOTHING_ON); - sprite[5] = rotozoomSurface(sprite[1], 45, 0.5, SMOOTHING_ON); + sprite[5] = rotozoomSurface(sprite[1], 20, 1, SMOOTHING_ON); sprite[6] = zoomSurface(sprite[0], -0.5, 0.5, SMOOTHING_ON); sprite[7] = zoomSurface(sprite[0], -0.5, -0.5, SMOOTHING_ON); sprite[8] = rotozoomSurface(sprite[1], 0, 0.5, SMOOTHING_ON); diff --git a/tests/sdl_rotozoom.png b/tests/sdl_rotozoom.png Binary files differindex 5933754f..ebde79f2 100644 --- a/tests/sdl_rotozoom.png +++ b/tests/sdl_rotozoom.png diff --git a/tests/stdio/test_rename.c b/tests/stdio/test_rename.c index f15c8140..1a5017c1 100644 --- a/tests/stdio/test_rename.c +++ b/tests/stdio/test_rename.c @@ -25,6 +25,8 @@ void setup() { mkdir("dir/subdir", 0777); mkdir("dir-readonly", 0555); mkdir("dir-nonempty", 0777); + mkdir("dir/subdir3", 0777); + mkdir("dir/subdir3/subdir3_1", 0777); create_file("dir-nonempty/file", "abcdef", 0777); } @@ -38,6 +40,9 @@ void cleanup() { rmdir("dir/subdir"); rmdir("dir/subdir1"); rmdir("dir/subdir2"); + rmdir("dir/subdir3/subdir3_1/subdir1 renamed"); + rmdir("dir/subdir3/subdir3_1"); + rmdir("dir/subdir3"); rmdir("dir"); rmdir("dir-readonly"); unlink("dir-nonempty/file"); @@ -96,6 +101,11 @@ void test() { err = access("dir/subdir2", F_OK); assert(!err); + err = rename("dir/subdir2", "dir/subdir3/subdir3_1/subdir1 renamed"); + assert(!err); + err = access("dir/subdir3/subdir3_1/subdir1 renamed", F_OK); + assert(!err); + puts("success"); } diff --git a/tests/test_browser.py b/tests/test_browser.py index 799759a1..ecd331fd 100644 --- a/tests/test_browser.py +++ b/tests/test_browser.py @@ -866,6 +866,9 @@ keydown(100);keyup(100); // trigger the end def test_glut_touchevents(self): self.btest('glut_touchevents.c', '1') + def test_glut_wheelevents(self): + self.btest('glut_wheelevents.c', '1') + def test_emscripten_get_now(self): self.btest('emscripten_get_now.cpp', '1') @@ -1308,6 +1311,10 @@ keydown(100);keyup(100); // trigger the end def test_gl_vertex_buffer(self): self.btest('gl_vertex_buffer.c', reference='gl_vertex_buffer.png', args=['-s', 'GL_UNSAFE_OPTS=0', '-s', 'LEGACY_GL_EMULATION=1'], reference_slack=1) + # Does not pass due to https://bugzilla.mozilla.org/show_bug.cgi?id=924264 so disabled for now. + # def test_gles2_uniform_arrays(self): + # self.btest('gles2_uniform_arrays.cpp', args=['-s', 'GL_ASSERTIONS=1'], expected=['1']) + def test_matrix_identity(self): self.btest('gl_matrix_identity.c', expected=['-1882984448', '460451840'], args=['-s', 'LEGACY_GL_EMULATION=1']) @@ -1385,7 +1392,7 @@ keydown(100);keyup(100); // trigger the end def test_sdl_rotozoom(self): shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) - self.btest('sdl_rotozoom.c', reference='sdl_rotozoom.png', args=['--preload-file', 'screenshot.png'], reference_slack=5) + self.btest('sdl_rotozoom.c', reference='sdl_rotozoom.png', args=['--preload-file', 'screenshot.png']) def test_sdl_gfx_primitives(self): self.btest('sdl_gfx_primitives.c', reference='sdl_gfx_primitives.png', reference_slack=1) diff --git a/tests/test_core.py b/tests/test_core.py index c1bfce6f..87925082 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -1073,7 +1073,6 @@ Succeeded! self.do_run(open(path_from_root('tests', 'cube2md5.cpp')).read(), open(path_from_root('tests', 'cube2md5.ok')).read()) def test_cube2hash(self): - try: old_chunk_size = os.environ.get('EMSCRIPT_MAX_CHUNK_SIZE') or '' os.environ['EMSCRIPT_MAX_CHUNK_SIZE'] = '1' # test splitting out each function to a chunk in emscripten.py (21 functions here) @@ -1091,6 +1090,17 @@ Succeeded! finally: os.environ['EMSCRIPT_MAX_CHUNK_SIZE'] = old_chunk_size + assert 'asm1' in test_modes + if self.run_name == 'asm1': + assert Settings.RELOOP + generated = open('src.cpp.o.js').read() + main = generated[generated.find('function _main'):] + main = main[:main.find('\n}')] + num_vars = 0 + for v in re.findall('var [^;]+;', main): + num_vars += v.count(',') + 1 + assert num_vars == 10, 'no variable elimination should have been run, but seeing %d' % num_vars + def test_unaligned(self): if Settings.QUANTUM_SIZE == 1: return self.skip('No meaning to unaligned addresses in q1') @@ -8608,9 +8618,10 @@ void*:16 assert 'asm1' in test_modes if self.run_name == 'asm1': - assert not Settings.RELOOP - Settings.RELOOP = 1 # check for mixing of relooping with asm1 - self.do_run(path_from_root('tests', 'cubescript'), '*\nTemp is 33\n9\n5\nhello, everyone\n*', main_file='command.cpp') + generated = open('src.cpp.o.js').read() + main = generated[generated.find('function runPostSets'):] + main = main[:main.find('\n}')] + assert main.count('\n') == 7, 'must not emit too many postSets: %d' % main.count('\n') def test_gcc_unmangler(self): Settings.NAMED_GLOBALS = 1 # test coverage for this @@ -8649,7 +8660,10 @@ void*:16 def test_freetype(self): if self.emcc_args is None: return self.skip('requires emcc') if Settings.QUANTUM_SIZE == 1: return self.skip('TODO: Figure out and try to fix') - if Settings.ASM_JS and '-O2' not in self.emcc_args: return self.skip('mozilla bug 863867') + + assert 'asm2g' in test_modes + if self.run_name == 'asm2g': + Settings.ALIASING_FUNCTION_POINTERS = 1 - Settings.ALIASING_FUNCTION_POINTERS # flip for some more coverage here if Settings.CORRECT_SIGNS == 0: Settings.CORRECT_SIGNS = 1 # Not sure why, but needed @@ -9462,6 +9476,32 @@ def process(filename): Settings.ALIASING_FUNCTION_POINTERS = 1 - Settings.ALIASING_FUNCTION_POINTERS # flip the test self.do_run(src, '''Hello 7 from JS!''') + def test_demangle_stacks(self): + if Settings.ASM_JS: return self.skip('spidermonkey has stack trace issues') + + src = r''' + #include<stdio.h> + #include<stdlib.h> + + namespace NameSpace { + class Class { + public: + int Aborter(double x, char y, int *z) { + int addr = x+y+(int)z; + void *p = (void*)addr; + for (int i = 0; i < 100; i++) free(p); // will abort, should show proper stack trace + } + }; + } + + int main(int argc, char **argv) { + NameSpace::Class c; + c.Aborter(1.234, 'a', NULL); + return 0; + } + ''' + self.do_run(src, 'NameSpace::Class::Aborter(double, char, int*)'); + def test_embind(self): if self.emcc_args is None: return self.skip('requires emcc') Building.COMPILER_TEST_OPTS += ['--bind'] diff --git a/tests/test_other.py b/tests/test_other.py index afad1927..185b4853 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -125,8 +125,6 @@ Options that are modified or new in %s include: (['-o', 'something.js', '-O0'], 0, None, 0, 0), (['-o', 'something.js', '-O1'], 1, None, 0, 0), (['-o', 'something.js', '-O1', '-g'], 1, None, 0, 0), # no closure since debug - (['-o', 'something.js', '-O1', '--closure', '1'], 1, None, 1, 0), - (['-o', 'something.js', '-O1', '--closure', '1', '-s', 'ASM_JS=0'], 1, None, 1, 0), (['-o', 'something.js', '-O2'], 2, None, 0, 1), (['-o', 'something.js', '-O2', '-g'], 2, None, 0, 0), (['-o', 'something.js', '-Os'], 2, None, 0, 1), @@ -169,9 +167,9 @@ Options that are modified or new in %s include: # closure has not been run, we can do some additional checks. TODO: figure out how to do these even with closure assert '._main = ' not in generated, 'closure compiler should not have been run' if keep_debug: - assert ('(label)' in generated or '(label | 0)' in generated) == (opt_level <= 1), 'relooping should be in opt >= 2' + assert ('(label)' in generated or '(label | 0)' in generated) == (opt_level <= 0), 'relooping should be in opt >= 1' assert ('assert(STACKTOP < STACK_MAX' in generated) == (opt_level == 0), 'assertions should be in opt == 0' - assert 'var $i;' in generated or 'var $i_0' in generated or 'var $storemerge3;' in generated or 'var $storemerge4;' in generated or 'var $i_04;' in generated or 'var $original = 0' in generated, 'micro opts should always be on' + assert 'var $i;' in generated or 'var $i_0' in generated or 'var $storemerge3;' in generated or 'var $storemerge4;' in generated or '$i_04' in generated or '$i_05' in generated or 'var $original = 0' in generated, 'micro opts should always be on' if opt_level >= 2 and '-g' in params: assert re.search('HEAP8\[\$?\w+ ?\+ ?\(+\$?\w+ ?', generated) or re.search('HEAP8\[HEAP32\[', generated), 'eliminator should create compound expressions, and fewer one-time vars' # also in -O1, but easier to test in -O2 assert ('_puts(' in generated) == (opt_level >= 1), 'with opt >= 1, llvm opts are run and they should optimize printf to puts' @@ -1647,6 +1645,8 @@ f.close() ['asm', 'outline']), (path_from_root('tools', 'test-js-optimizer-asm-outline3.js'), open(path_from_root('tools', 'test-js-optimizer-asm-outline3-output.js')).read(), ['asm', 'outline']), + (path_from_root('tools', 'test-js-optimizer-asm-minlast.js'), open(path_from_root('tools', 'test-js-optimizer-asm-minlast-output.js')).read(), + ['asm', 'minifyWhitespace', 'last']), ]: print input output = Popen(listify(NODE_JS) + [path_from_root('tools', 'js-optimizer.js'), input] + passes, stdin=PIPE, stdout=PIPE).communicate()[0] @@ -1666,20 +1666,16 @@ f.close() try: os.environ['EMCC_DEBUG'] = '1' os.environ['EMCC_CORES'] = '2' # standardize over machines - for asm, linkable, chunks, js_chunks in [ - (0, 0, 2, 2), (0, 1, 2, 4), - (1, 0, 2, 2), (1, 1, 2, 4) + for asm, linkable, chunks in [ + (0, 0, 2), (0, 1, 2), + (1, 0, 2), (1, 1, 2) ]: - print asm, linkable, chunks, js_chunks + print asm, linkable, chunks output, err = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_libcxx.cpp'), '-O1', '-s', 'LINKABLE=%d' % linkable, '-s', 'ASM_JS=%d' % asm] + (['-O2'] if asm else []), stdout=PIPE, stderr=PIPE).communicate() ok = False for c in range(chunks, chunks+2): ok = ok or ('phase 2 working on %d chunks' % c in err) assert ok, err - ok = False - for c in range(js_chunks, js_chunks+2): - ok = ok or ('splitting up js optimization into %d chunks' % c in err) - assert ok, err finally: del os.environ['EMCC_DEBUG'] del os.environ['EMCC_CORES'] @@ -1910,3 +1906,53 @@ done. assert '''tests/hello_world.c"''' in out assert '''printf("hello, world!''' in out + def test_demangle(self): + open('src.cpp', 'w').write(''' + #include <stdio.h> + #include <emscripten.h> + void two(char c) { + EM_ASM(Module.print(stackTrace())); + } + void one(int x) { + two(x % 17); + } + int main() { + EM_ASM(Module.print(demangle('__Znwj'))); // check for no aborts + EM_ASM(Module.print(demangle('_main'))); + EM_ASM(Module.print(demangle('__Z2f2v'))); + EM_ASM(Module.print(demangle('__Z12abcdabcdabcdi'))); + EM_ASM(Module.print(demangle('__Z4testcsifdPvPiPc'))); + EM_ASM(Module.print(demangle('__ZN4test5moarrEcslfdPvPiPc'))); + EM_ASM(Module.print(demangle('__ZN4Waka1f12a234123412345pointEv'))); + EM_ASM(Module.print(demangle('__Z3FooIiEvv'))); + EM_ASM(Module.print(demangle('__Z3FooIidEvi'))); + EM_ASM(Module.print(demangle('__ZN3Foo3BarILi5EEEvv'))); + EM_ASM(Module.print(demangle('__ZNK10__cxxabiv120__si_class_type_info16search_below_dstEPNS_19__dynamic_cast_infoEPKvib'))); + EM_ASM(Module.print(demangle('__Z9parsewordRPKciRi'))); + EM_ASM(Module.print(demangle('__Z5multiwahtjmxyz'))); + EM_ASM(Module.print(demangle('__Z1aA32_iPA5_c'))); + one(17); + return 0; + } + ''') + + Popen([PYTHON, EMCC, 'src.cpp', '-s', 'LINKABLE=1']).communicate() + output = run_js('a.out.js') + self.assertContained('''main +f2() +abcdabcdabcd(int) +test(char, short, int, float, double, void*, int*, char*) +test::moarr(char, short, long, float, double, void*, int*, char*) +Waka::f::a23412341234::point() +void Foo<int>() +void Foo<int, double>(int) +void Foo::Bar<5>() +__cxxabiv1::__si_class_type_info::search_below_dst(__cxxabiv1::__dynamic_cast_info*, void*, int, bool) +parseword(char*&, int, int&) +multi(wchar_t, signed char, unsigned char, unsigned short, unsigned int, unsigned long, long long, unsigned long long, ...) +a(int [32], char [5]*) +''', output) + # test for multiple functions in one stack trace + assert 'one(int)' in output + assert 'two(char)' in output + diff --git a/tests/test_sanity.py b/tests/test_sanity.py index aa3f1242..a0fff252 100644 --- a/tests/test_sanity.py +++ b/tests/test_sanity.py @@ -429,12 +429,12 @@ fi stdout=PIPE, stderr=PIPE).communicate() self.assertContained('hello, world!', run_js('a.out.js')) output = '\n'.join(output) - assert ('bootstrapping relooper succeeded' in output) == (i == 2), 'only bootstrap on first O2: ' + output - assert os.path.exists(RELOOPER) == (i >= 2), 'have relooper on O2: ' + output + assert ('bootstrapping relooper succeeded' in output) == (i == 1), 'only bootstrap on first O2: ' + output + assert os.path.exists(RELOOPER) == (i >= 1), 'have relooper on O2: ' + output src = open('a.out.js').read() main = src.split('function _main()')[1].split('\n}\n')[0] - assert ('while (1) {' in main or 'while(1){' in main or '} while ($' in main or '}while($' in main) == (i >= 2), 'reloop code on O2: ' + main - assert ('switch' not in main) == (i >= 2), 'reloop code on O2: ' + main + assert ('while (1) {' in main or 'while(1){' in main or 'while(1) {' in main or '} while ($' in main or '}while($' in main) == (i >= 1), 'reloop code on O2: ' + main + assert ('switch' not in main) == (i >= 1), 'reloop code on O2: ' + main def test_jcache(self): PRE_LOAD_MSG = 'loading pre from jcache' |