aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/browser_main.cpp42
-rw-r--r--tests/browser_module.cpp15
-rw-r--r--tests/cmake/target_html/CMakeLists.txt8
-rw-r--r--tests/cmake/target_js/CMakeLists.txt24
-rw-r--r--tests/dlmalloc_proxy.c85
-rw-r--r--tests/filesystem/src.js22
-rw-r--r--tests/gl_vertex_buffer.c195
-rw-r--r--tests/gl_vertex_buffer.pngbin0 -> 47668 bytes
-rw-r--r--tests/gl_vertex_buffer_pre.c177
-rw-r--r--tests/gl_vertex_buffer_pre.pngbin0 -> 83534 bytes
-rwxr-xr-xtests/runner.py8
-rw-r--r--tests/sdl_canvas_proxy.c34
-rw-r--r--tests/sdl_canvas_proxy.pngbin0 -> 4488 bytes
-rw-r--r--tests/sdl_key_proxy.c63
-rw-r--r--tests/test_browser.py79
-rw-r--r--tests/test_core.py619
-rw-r--r--tests/test_other.py104
-rw-r--r--tests/unistd/access.c8
-rw-r--r--tests/unistd/access.js4
-rw-r--r--tests/unistd/access.out4
-rw-r--r--tests/unistd/curdir.c11
-rw-r--r--tests/unistd/curdir.js7
-rw-r--r--tests/unistd/io.c50
-rw-r--r--tests/unistd/io.js52
-rw-r--r--tests/unistd/links.c7
-rw-r--r--tests/unistd/links.js3
-rw-r--r--tests/unistd/truncate.c7
-rw-r--r--tests/unistd/truncate.js2
28 files changed, 1355 insertions, 275 deletions
diff --git a/tests/browser_main.cpp b/tests/browser_main.cpp
new file mode 100644
index 00000000..efdce1be
--- /dev/null
+++ b/tests/browser_main.cpp
@@ -0,0 +1,42 @@
+#include <assert.h>
+#include <stdio.h>
+#include <dlfcn.h>
+#include <emscripten.h>
+
+typedef void (*voidfunc)();
+typedef int (*intfunc)();
+
+void *lib_handle;
+voidfunc onefunc;
+intfunc twofunc;
+
+void next(const char *x) {
+ lib_handle = dlopen("themodule.js", RTLD_NOW);
+ assert(lib_handle != NULL);
+
+ onefunc = (voidfunc)dlsym(lib_handle, "one");
+ twofunc = (intfunc)dlsym(lib_handle, "two");
+ assert(onefunc && twofunc);
+
+ assert(twofunc() == 0);
+ onefunc();
+ assert(twofunc() == 1);
+ onefunc();
+ onefunc();
+ assert(twofunc() == 3);
+ onefunc();
+ onefunc();
+ onefunc();
+ onefunc();
+ assert(twofunc() == 7);
+ onefunc();
+ int result = twofunc();
+ REPORT_RESULT();
+}
+
+int main() {
+ emscripten_async_wget("module.js", "themodule.js", next, NULL);
+
+ return 0;
+}
+
diff --git a/tests/browser_module.cpp b/tests/browser_module.cpp
new file mode 100644
index 00000000..85d724b5
--- /dev/null
+++ b/tests/browser_module.cpp
@@ -0,0 +1,15 @@
+
+int state = 0;
+
+extern "C" {
+
+void one() {
+ state++;
+}
+
+int two() {
+ return state;
+}
+
+}
+
diff --git a/tests/cmake/target_html/CMakeLists.txt b/tests/cmake/target_html/CMakeLists.txt
index 9f891e71..8b0528eb 100644
--- a/tests/cmake/target_html/CMakeLists.txt
+++ b/tests/cmake/target_html/CMakeLists.txt
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 2.8)
-project(hello_world_gles.html)
+project(hello_world_gles)
file(GLOB sourceFiles ../../hello_world_gles.c)
@@ -10,5 +10,7 @@ else() # Either MinSizeRel, RelWithDebInfo or Release, all which run with optimi
SET(linkFlags "-O2")
endif()
-add_executable(hello_world_gles.html ${sourceFiles})
-set_target_properties(hello_world_gles.html PROPERTIES LINK_FLAGS "${linkFlags}")
+SET(CMAKE_EXECUTABLE_SUFFIX ".html")
+
+add_executable(hello_world_gles ${sourceFiles})
+set_target_properties(hello_world_gles PROPERTIES LINK_FLAGS "${linkFlags}")
diff --git a/tests/cmake/target_js/CMakeLists.txt b/tests/cmake/target_js/CMakeLists.txt
index 860b70a9..cee5fc42 100644
--- a/tests/cmake/target_js/CMakeLists.txt
+++ b/tests/cmake/target_js/CMakeLists.txt
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 2.8)
-project(hello_world.js)
+project(hello_world)
file(GLOB sourceFiles ../../hello_world.cpp)
@@ -10,5 +10,23 @@ else() # Either MinSizeRel, RelWithDebInfo or Release, all which run with optimi
SET(linkFlags "-O2")
endif()
-add_executable(hello_world.js ${sourceFiles})
-set_target_properties(hello_world.js PROPERTIES LINK_FLAGS "${linkFlags}")
+SET(CMAKE_EXECUTABLE_SUFFIX ".js")
+
+if (WIN32)
+ message(FATAL_ERROR "WIN32 should not be defined when cross-compiling!")
+endif()
+
+if (APPLE)
+ message(FATAL_ERROR "APPLE should not be defined when cross-compiling!")
+endif()
+
+if (NOT EMSCRIPTEN)
+ message(FATAL_ERROR "EMSCRIPTEN should be defined when cross-compiling!")
+endif()
+
+if (NOT CMAKE_C_SIZEOF_DATA_PTR)
+ message(FATAL_ERROR "CMAKE_C_SIZEOF_DATA_PTR was not defined!")
+endif()
+
+add_executable(hello_world ${sourceFiles})
+set_target_properties(hello_world PROPERTIES LINK_FLAGS "${linkFlags}")
diff --git a/tests/dlmalloc_proxy.c b/tests/dlmalloc_proxy.c
new file mode 100644
index 00000000..06137c42
--- /dev/null
+++ b/tests/dlmalloc_proxy.c
@@ -0,0 +1,85 @@
+// Emscripten tests
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <dlfcn.h>
+
+typedef void *(*mallocer)(int n);
+typedef void (*freeer)(void *p);
+
+void *lib_handle;
+int handles = 0;
+mallocer mallocproxy = NULL;
+freeer freeproxy = NULL;
+
+void get_lib() {
+ //printf("get lib\n");
+ lib_handle = dlopen("liblib.so", RTLD_NOW);
+ assert(lib_handle != NULL);
+ handles++;
+
+ mallocproxy = (mallocer)dlsym(lib_handle, "mallocproxy");
+ assert(mallocproxy!= NULL);
+ freeproxy = (freeer)dlsym(lib_handle, "freeproxy");
+ assert(freeproxy!= NULL);
+}
+
+void unget_lib() {
+ //printf("unget lib\n");
+ assert(lib_handle);
+ dlclose(lib_handle);
+ handles--;
+ if (handles == 0) lib_handle = NULL;
+}
+
+int main() {
+ int n = 0, total = 0, l = 0;
+ void *allocs[50];
+ allocs[10] = malloc(10); // pull in real malloc
+ for (int i = 0; i < 1000; i++) {
+ //printf("%d: total ever %d MB, current MB %d, total libs %d\n", i, total, n, l);
+ if (i % 5 == 0) {
+ if (handles < 10) {
+ get_lib();
+ l++;
+ }
+ }
+ if (i % 7 == 0) {
+ if (handles > 0) unget_lib();
+ }
+ if (i % 3 == 0) {
+ if (handles > 0) {
+ if (n < 10) {
+ if (i % 2 == 0) {
+ //printf("alloc\n");
+ allocs[n++] = mallocproxy(1024*1024);
+ } else {
+ //printf("real alloc\n");
+ allocs[n++] = malloc(1024*1024);
+ }
+ total++;
+ } else {
+ //printf("real free\n");
+ free(allocs[--n]); // real free
+ }
+ }
+ }
+ if (i % 4 == 0) {
+ if (handles > 0 && n > 0) {
+ //printf("free\n");
+ if (i % 2 == 0) {
+ //printf("free\n");
+ freeproxy(allocs[--n]);
+ } else {
+ //printf("real free\n");
+ free(allocs[--n]);
+ }
+ }
+ }
+ }
+ while (n > 0) free(allocs[--n]); // real free
+ while (handles > 0) unget_lib();
+ printf("*%d,%d*\n", total, l);
+}
+
diff --git a/tests/filesystem/src.js b/tests/filesystem/src.js
index dbdd4bed..91337f5b 100644
--- a/tests/filesystem/src.js
+++ b/tests/filesystem/src.js
@@ -1,16 +1,18 @@
var dummy_device = FS.makedev(64, 0);
FS.registerDevice(dummy_device, {});
-FS.createFolder('/', 'forbidden', false, false);
-FS.createFolder('/forbidden', 'test', true, true);
-FS.createPath('/', 'abc/123', true, true);
-FS.createPath('/', 'abc/456', true, true);
-FS.createPath('/', 'def/789', true, true);
-FS.mkdev('/abc/deviceA', 0666, dummy_device);
-FS.mkdev('/def/deviceB', 0666, dummy_device);
-FS.createLink('/abc', 'localLink', '123', true, true);
-FS.createLink('/abc', 'rootLink', '/', true, true);
-FS.createLink('/abc', 'relativeLink', '../def', true, true);
+FS.mkdir('/forbidden', 0000);
+FS.mkdir('/forbidden/test');
+FS.mkdir('/abc');
+FS.mkdir('/abc/123');
+FS.mkdir('/abc/456');
+FS.mkdir('/def');
+FS.mkdir('/def/789');
+FS.mkdev('/abc/deviceA', dummy_device);
+FS.mkdev('/def/deviceB', dummy_device);
+FS.symlink('123', '/abc/localLink');
+FS.symlink('/', '/abc/rootLink');
+FS.symlink('../def', '/abc/relativeLink');
FS.ignorePermissions = false;
function explore(path) {
diff --git a/tests/gl_vertex_buffer.c b/tests/gl_vertex_buffer.c
new file mode 100644
index 00000000..6b695462
--- /dev/null
+++ b/tests/gl_vertex_buffer.c
@@ -0,0 +1,195 @@
+/*******************************************************************
+ * *
+ * Using SDL With OpenGL *
+ * *
+ * Tutorial by Kyle Foley (sdw) *
+ * *
+ * http://gpwiki.org/index.php/SDL:Tutorials:Using_SDL_with_OpenGL *
+ * *
+ *******************************************************************/
+
+/*
+ THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION
+ AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN.
+
+ THE ORIGINAL AUTHOR IS KYLE FOLEY.
+
+ THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
+ OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
+ MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
+ ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
+ RESULTING FROM THE USE, MODIFICATION, OR
+ REDISTRIBUTION OF THIS SOFTWARE.
+ */
+
+#if !EMSCRIPTEN
+#define USE_GLEW 0
+#endif
+
+#if USE_GLEW
+#include "GL/glew.h"
+#endif
+
+#include <SDL/SDL.h>
+
+#if !USE_GLEW
+#include "SDL/SDL_opengl.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+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;
+ }
+
+ SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // *new*
+
+ screen = SDL_SetVideoMode( 640, 480, 16, SDL_OPENGL ); // *changed*
+ if ( !screen ) {
+ printf("Unable to set video mode: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ // Set the OpenGL state after creating the context with SDL_SetVideoMode
+
+ glClearColor( 0, 0, 0, 0 );
+
+#if !EMSCRIPTEN
+ glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL
+#endif
+
+ glViewport( 0, 0, 640, 480 );
+
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+
+ // Clear the screen before drawing
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ typedef struct Color {
+ GLubyte r;
+ GLubyte g;
+ GLubyte b;
+ GLubyte a;
+ } Color;
+
+ typedef struct Vertex {
+ GLfloat x;
+ GLfloat y;
+ Color color;
+ } Vertex;
+
+ Vertex vertices[18] = {
+ {-1.00, 0.0, {0xFF, 0x00, 0xFF, 0xFF}},
+ {-1.00, 1.0, {0xFF, 0xFF, 0x00, 0xFF}},
+ {-0.75, 0.0, {0xFF, 0x00, 0x00, 0xFF}},
+ {-0.75, 1.0, {0xFF, 0xFF, 0xFF, 0xFF}},
+ {-0.50, 0.0, {0xFF, 0x00, 0x00, 0xFF}},
+ {-0.50, 1.0, {0xFF, 0xFF, 0x00, 0xFF}},
+ {-0.25, 0.0, {0xFF, 0x00, 0xFF, 0xFF}},
+ {-0.25, 1.0, {0xFF, 0xFF, 0x00, 0xFF}},
+ {-0.00, 0.0, {0xFF, 0x00, 0x00, 0xFF}},
+ {-0.00, 1.0, {0xFF, 0xFF, 0xFF, 0xFF}},
+ { 0.25, 0.0, {0xFF, 0x00, 0x00, 0xFF}},
+ { 0.25, 1.0, {0xFF, 0xFF, 0x00, 0xFF}},
+ { 0.50, 0.0, {0xFF, 0x00, 0xFF, 0xFF}},
+ { 0.50, 1.0, {0xFF, 0xFF, 0x00, 0xFF}},
+ { 0.75, 0.0, {0xFF, 0x00, 0x00, 0xFF}},
+ { 0.75, 1.0, {0xFF, 0xFF, 0xFF, 0xFF}},
+ { 1.00, 0.0, {0xFF, 0x00, 0x00, 0xFF}},
+ { 1.00, 1.0, {0xFF, 0xFF, 0x00, 0xFF}}
+ };
+
+ Vertex vertices2[18] = {
+ {-1.00, -1.0, {0xFF, 0x00, 0xFF, 0xFF}},
+ {-1.00, 0.0, {0xFF, 0xFF, 0x00, 0xFF}},
+ {-0.75, -1.0, {0xFF, 0x00, 0x00, 0xFF}},
+ {-0.75, 0.0, {0xFF, 0xFF, 0xFF, 0xFF}},
+ {-0.50, -1.0, {0xFF, 0x00, 0x00, 0xFF}},
+ {-0.50, 0.0, {0xFF, 0xFF, 0x00, 0xFF}},
+ {-0.25, -1.0, {0xFF, 0x00, 0xFF, 0xFF}},
+ {-0.25, 0.0, {0xFF, 0xFF, 0x00, 0xFF}},
+ {-0.00, -1.0, {0xFF, 0x00, 0x00, 0xFF}},
+ {-0.00, 0.0, {0xFF, 0xFF, 0xFF, 0xFF}},
+ { 0.25, -1.0, {0xFF, 0x00, 0x00, 0xFF}},
+ { 0.25, 0.0, {0xFF, 0xFF, 0x00, 0xFF}},
+ { 0.50, -1.0, {0xFF, 0x00, 0xFF, 0xFF}},
+ { 0.50, 0.0, {0xFF, 0xFF, 0x00, 0xFF}},
+ { 0.75, -1.0, {0xFF, 0x00, 0x00, 0xFF}},
+ { 0.75, 0.0, {0xFF, 0xFF, 0xFF, 0xFF}},
+ { 1.00, -1.0, {0xFF, 0x00, 0x00, 0xFF}},
+ { 1.00, 0.0, {0xFF, 0xFF, 0x00, 0xFF}}
+ };
+
+ // make a vertex buffer for the second set of vertices
+ GLuint vbo = 0;
+ glGenBuffers(1, &vbo);
+
+
+ // bind to it
+ glBindBuffer(GL_ARRAY_BUFFER, vbo);
+ // send it to gl
+ glBufferData(GL_ARRAY_BUFFER, sizeof(vertices2), vertices2, GL_STATIC_READ); // GL_STATIC_READ is not in WebGL!
+
+ // unbind from it
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+
+ // DRAW
+
+ // Clear the screen before drawing
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ // This test ensures that we can use two separate arrays in memory for different
+ // attributes, and that they each can have different stride.
+ // The first test shows implicit striding (the zero indicates tightly packed)
+ // The second test shows explicit striding where the stride is passed in
+ // even though it also is tightly packed
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
+
+ // TEST 1 - clientside data
+
+ glVertexPointer(2, GL_FLOAT, sizeof(Vertex), vertices);
+ glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), &vertices[0].color);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 6);
+ glDrawArrays(GL_TRIANGLE_STRIP, 10, 3);
+
+
+
+ // TEST 2 - bind to array buffer, gl*Pointer calls are offsets into the buffer, which was previously uploaded to
+
+ glBindBuffer(GL_ARRAY_BUFFER, vbo);
+
+ glVertexPointer(2, GL_FLOAT, sizeof(Vertex), 0);
+ glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), (GLvoid*)((GLvoid*)&vertices2[0].color - (GLvoid*)&vertices2[0]));
+
+// gldrawarrays first with a low number of vertices, then with a high number
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 6);
+ glDrawArrays(GL_TRIANGLE_STRIP, 10, 3);
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ glDisableClientState(GL_COLOR_ARRAY);
+ glDisableClientState(GL_VERTEX_ARRAY);
+
+ SDL_GL_SwapBuffers();
+
+#if !EMSCRIPTEN
+ // Wait for 3 seconds to give us a chance to see the image
+ SDL_Delay(3000);
+#endif
+
+ SDL_Quit();
+
+ return 0;
+}
diff --git a/tests/gl_vertex_buffer.png b/tests/gl_vertex_buffer.png
new file mode 100644
index 00000000..3e1f2230
--- /dev/null
+++ b/tests/gl_vertex_buffer.png
Binary files differ
diff --git a/tests/gl_vertex_buffer_pre.c b/tests/gl_vertex_buffer_pre.c
new file mode 100644
index 00000000..84b76569
--- /dev/null
+++ b/tests/gl_vertex_buffer_pre.c
@@ -0,0 +1,177 @@
+/*******************************************************************
+ * *
+ * Using SDL With OpenGL *
+ * *
+ * Tutorial by Kyle Foley (sdw) *
+ * *
+ * http://gpwiki.org/index.php/SDL:Tutorials:Using_SDL_with_OpenGL *
+ * *
+ *******************************************************************/
+
+/*
+ THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION
+ AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN.
+
+ THE ORIGINAL AUTHOR IS KYLE FOLEY.
+
+ THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
+ OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
+ MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
+ ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
+ RESULTING FROM THE USE, MODIFICATION, OR
+ REDISTRIBUTION OF THIS SOFTWARE.
+ */
+
+#if !EMSCRIPTEN
+#define USE_GLEW 0
+#endif
+
+#if USE_GLEW
+#include "GL/glew.h"
+#endif
+
+#include <SDL/SDL.h>
+
+#if !USE_GLEW
+#include "SDL/SDL_opengl.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+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;
+ }
+
+ SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // *new*
+
+ screen = SDL_SetVideoMode( 640, 480, 16, SDL_OPENGL ); // *changed*
+ if ( !screen ) {
+ printf("Unable to set video mode: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ // Set the OpenGL state after creating the context with SDL_SetVideoMode
+
+ glClearColor( 0, 0, 0, 0 );
+
+#if !EMSCRIPTEN
+ glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL
+#endif
+
+ glViewport( 0, 0, 640, 480 );
+
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+
+ // Clear the screen before drawing
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ typedef struct Color {
+ GLubyte r;
+ GLubyte g;
+ GLubyte b;
+ GLubyte a;
+ } Color;
+
+ typedef struct Vertex {
+ GLfloat x;
+ GLfloat y;
+ Color color;
+ } Vertex;
+
+ Vertex vertices[18] = {
+ {-1.00, 0.0, {0xFF, 0x00, 0xFF, 0xFF}},
+ {-1.00, 1.0, {0xFF, 0xFF, 0x00, 0xFF}},
+ {-0.75, 0.0, {0xFF, 0x00, 0x00, 0xFF}},
+ {-0.75, 1.0, {0xFF, 0xFF, 0xFF, 0xFF}},
+ {-0.50, 0.0, {0xFF, 0x00, 0x00, 0xFF}},
+ {-0.50, 1.0, {0xFF, 0xFF, 0x00, 0xFF}},
+ {-0.25, 0.0, {0xFF, 0x00, 0xFF, 0xFF}},
+ {-0.25, 1.0, {0xFF, 0xFF, 0x00, 0xFF}},
+ {-0.00, 0.0, {0xFF, 0x00, 0x00, 0xFF}},
+ {-0.00, 1.0, {0xFF, 0xFF, 0xFF, 0xFF}},
+ { 0.25, 0.0, {0xFF, 0x00, 0x00, 0xFF}},
+ { 0.25, 1.0, {0xFF, 0xFF, 0x00, 0xFF}},
+ { 0.50, 0.0, {0xFF, 0x00, 0xFF, 0xFF}},
+ { 0.50, 1.0, {0xFF, 0xFF, 0x00, 0xFF}},
+ { 0.75, 0.0, {0xFF, 0x00, 0x00, 0xFF}},
+ { 0.75, 1.0, {0xFF, 0xFF, 0xFF, 0xFF}},
+ { 1.00, 0.0, {0xFF, 0x00, 0x00, 0xFF}},
+ { 1.00, 1.0, {0xFF, 0xFF, 0x00, 0xFF}}
+ };
+
+ Vertex vertices2[18] = {
+ {-1.00, -1.0, {0xFF, 0x00, 0xFF, 0xFF}},
+ {-1.00, 0.0, {0xFF, 0xFF, 0x00, 0xFF}},
+ {-0.75, -1.0, {0xFF, 0x00, 0x00, 0xFF}},
+ {-0.75, 0.0, {0xFF, 0xFF, 0xFF, 0xFF}},
+ {-0.50, -1.0, {0xFF, 0x00, 0x00, 0xFF}},
+ {-0.50, 0.0, {0xFF, 0xFF, 0x00, 0xFF}},
+ {-0.25, -1.0, {0xFF, 0x00, 0xFF, 0xFF}},
+ {-0.25, 0.0, {0xFF, 0xFF, 0x00, 0xFF}},
+ {-0.00, -1.0, {0xFF, 0x00, 0x00, 0xFF}},
+ {-0.00, 0.0, {0xFF, 0xFF, 0xFF, 0xFF}},
+ { 0.25, -1.0, {0xFF, 0x00, 0x00, 0xFF}},
+ { 0.25, 0.0, {0xFF, 0xFF, 0x00, 0xFF}},
+ { 0.50, -1.0, {0xFF, 0x00, 0xFF, 0xFF}},
+ { 0.50, 0.0, {0xFF, 0xFF, 0x00, 0xFF}},
+ { 0.75, -1.0, {0xFF, 0x00, 0x00, 0xFF}},
+ { 0.75, 0.0, {0xFF, 0xFF, 0xFF, 0xFF}},
+ { 1.00, -1.0, {0xFF, 0x00, 0x00, 0xFF}},
+ { 1.00, 0.0, {0xFF, 0xFF, 0x00, 0xFF}}
+ };
+
+ // make a vertex buffer for the second set of vertices
+ GLuint vbo = 0;
+ glGenBuffers(1, &vbo);
+
+
+ // bind to it
+ glBindBuffer(GL_ARRAY_BUFFER, vbo);
+ // send it to gl
+ glBufferData(GL_ARRAY_BUFFER, sizeof(vertices2), vertices2, GL_STATIC_DRAW);
+
+ // unbind from it
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+
+ // DRAW
+
+ // Clear the screen before drawing
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ // This test ensures that we can use two separate arrays in memory for different
+ // attributes, and that they each can have different stride.
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
+
+ glVertexPointer(2, GL_FLOAT, sizeof(Vertex), vertices);
+ glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), &vertices[0].color);
+ glDrawArrays(GL_TRIANGLE_STRIP, 10, 3);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 6);
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ glDisableClientState(GL_COLOR_ARRAY);
+ glDisableClientState(GL_VERTEX_ARRAY);
+
+ SDL_GL_SwapBuffers();
+
+#if !EMSCRIPTEN
+ // Wait for 3 seconds to give us a chance to see the image
+ SDL_Delay(3000);
+#endif
+
+ SDL_Quit();
+
+ return 0;
+}
diff --git a/tests/gl_vertex_buffer_pre.png b/tests/gl_vertex_buffer_pre.png
new file mode 100644
index 00000000..5677a868
--- /dev/null
+++ b/tests/gl_vertex_buffer_pre.png
Binary files differ
diff --git a/tests/runner.py b/tests/runner.py
index f0e61c4e..ddc97ea4 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -254,7 +254,7 @@ process(sys.argv[1])
os.chdir(cwd)
out = open(stdout, 'r').read()
err = open(stderr, 'r').read()
- if engine == SPIDERMONKEY_ENGINE and Settings.ASM_JS:
+ if engine == SPIDERMONKEY_ENGINE and Settings.ASM_JS == 1:
err = self.validate_asmjs(err)
if output_nicerizer:
ret = output_nicerizer(out, err)
@@ -646,7 +646,7 @@ class BrowserCore(RunnerCore):
});
''' % basename)
- def btest(self, filename, expected=None, reference=None, force_c=False, reference_slack=0,
+ def btest(self, filename, expected=None, reference=None, force_c=False, reference_slack=0, manual_reference=False, post_build=None,
args=[], outfile='test.html', message='.'): # TODO: use in all other tests
# if we are provided the source and not a path, use that
filename_is_src = '\n' in filename
@@ -663,9 +663,11 @@ class BrowserCore(RunnerCore):
expected = [str(i) for i in range(0, reference_slack+1)]
shutil.copyfile(filepath, temp_filepath)
self.reftest(path_from_root('tests', reference))
- args = args + ['--pre-js', 'reftest.js', '-s', 'GL_TESTING=1']
+ if not manual_reference:
+ args = args + ['--pre-js', 'reftest.js', '-s', 'GL_TESTING=1']
Popen([PYTHON, EMCC, temp_filepath, '-o', outfile] + args).communicate()
assert os.path.exists(outfile)
+ if post_build: post_build()
if type(expected) is str: expected = [expected]
self.run_browser(outfile, message, ['/report_result?' + e for e in expected])
diff --git a/tests/sdl_canvas_proxy.c b/tests/sdl_canvas_proxy.c
new file mode 100644
index 00000000..27ef3bb4
--- /dev/null
+++ b/tests/sdl_canvas_proxy.c
@@ -0,0 +1,34 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <SDL/SDL.h>
+#include <assert.h>
+#include <emscripten.h>
+
+int main(int argc, char **argv) {
+ FILE *f = fopen("data.txt", "rb");
+ assert(f);
+ assert(fgetc(f) == 'd');
+ assert(fgetc(f) == 'a');
+ assert(fgetc(f) == 't');
+ assert(fgetc(f) == 'u');
+ assert(fgetc(f) == 'm');
+ fclose(f);
+
+ SDL_Init(SDL_INIT_VIDEO);
+ SDL_Surface *screen = SDL_SetVideoMode(600, 450, 32, SDL_HWSURFACE);
+
+ SDL_LockSurface(screen);
+ unsigned int *pixels = (unsigned int *)screen->pixels;
+ for (int x = 0; x < screen->w; x++) {
+ for (int y = 0; y < screen->h; y++) {
+ pixels[x + y*screen->h] = x < 300 ? (y < 200 ? 0x3377AA88 : 0xAA3377CC) : (y < 200 ? 0x0066AA77 : 0xAA006699);
+ }
+ }
+ SDL_UnlockSurface(screen);
+
+ SDL_Quit();
+
+ EM_ASM(window.close());
+ return 0;
+}
+
diff --git a/tests/sdl_canvas_proxy.png b/tests/sdl_canvas_proxy.png
new file mode 100644
index 00000000..cc96acfd
--- /dev/null
+++ b/tests/sdl_canvas_proxy.png
Binary files differ
diff --git a/tests/sdl_key_proxy.c b/tests/sdl_key_proxy.c
new file mode 100644
index 00000000..bc233f29
--- /dev/null
+++ b/tests/sdl_key_proxy.c
@@ -0,0 +1,63 @@
+#include <stdio.h>
+#include <SDL/SDL.h>
+#include <SDL/SDL_ttf.h>
+#include <emscripten.h>
+
+int result = 1;
+
+void one() {
+ SDL_Event event;
+ while (SDL_PollEvent(&event)) {
+ printf("got event %d\n", event.type);
+ switch(event.type) {
+ case SDL_KEYDOWN:
+ break;
+ case SDL_KEYUP:
+ // don't handle the modifier key events
+ if (event.key.keysym.sym == SDLK_LCTRL ||
+ event.key.keysym.sym == SDLK_LSHIFT ||
+ event.key.keysym.sym == SDLK_LALT) {
+ return;
+ }
+ if ((event.key.keysym.mod & KMOD_LCTRL) || (event.key.keysym.mod & KMOD_RCTRL)) {
+ result *= 2;
+ }
+ if ((event.key.keysym.mod & KMOD_LSHIFT) || (event.key.keysym.mod & KMOD_RSHIFT)) {
+ result *= 3;
+ }
+ if ((event.key.keysym.mod & KMOD_LALT) || (event.key.keysym.mod & KMOD_RALT)) {
+ result *= 5;
+ }
+ switch (event.key.keysym.sym) {
+ case SDLK_RIGHT: printf("right\n"); result *= 7; break;
+ case SDLK_LEFT: printf("left\n"); result *= 11; break;
+ case SDLK_DOWN: printf("down\n"); result *= 13; break;
+ case SDLK_UP: printf("up\n"); result *= 17; break;
+ case SDLK_a: printf("a\n"); result *= 19; break;
+ default: {
+ if (event.key.keysym.scancode == SDL_SCANCODE_B) {
+ printf("b scancode\n"); result *= 23; break;
+ }
+ printf("unknown key: sym %d scancode %d\n", event.key.keysym.sym, event.key.keysym.scancode);
+ REPORT_RESULT();
+ emscripten_run_script("throw 'done'"); // comment this out to leave event handling active. Use the following to log DOM keys:
+ // addEventListener('keyup', function(event) { console.log(event.keyCode) }, true)
+ }
+ }
+ break;
+ default: /* Report an unhandled event */
+ printf("I don't know what this event is!\n");
+ }
+ }
+}
+
+int main(int argc, char **argv) {
+ printf("main\n");
+ SDL_Init(SDL_INIT_VIDEO);
+ SDL_Surface *screen = SDL_SetVideoMode(600, 450, 32, SDL_HWSURFACE);
+
+ if (argc == 1337) one(); // keep it alive
+
+ return 0;
+}
+
diff --git a/tests/test_browser.py b/tests/test_browser.py
index a0c4dceb..e6fd6544 100644
--- a/tests/test_browser.py
+++ b/tests/test_browser.py
@@ -627,6 +627,28 @@ If manually bisecting:
Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'sdl_canvas.c'), '-o', 'page.html', '-s', 'LEGACY_GL_EMULATION=1']).communicate()
self.run_browser('page.html', '', '/report_result?1')
+ def test_sdl_canvas_proxy(self):
+ def post():
+ html = open('test.html').read()
+ html = html.replace('</body>', '''
+<script>
+function assert(x, y) { if (!x) throw 'assertion failed ' + y }
+
+%s
+
+var windowClose = window.close;
+window.close = function() {
+ doReftest();
+ setTimeout(windowClose, 1000);
+};
+</script>
+</body>''' % open('reftest.js').read())
+ open('test.html', 'w').write(html)
+
+ open('data.txt', 'w').write('datum')
+
+ self.btest('sdl_canvas_proxy.c', reference='sdl_canvas_proxy.png', args=['--proxy-to-worker', '--preload-file', 'data.txt'], manual_reference=True, post_build=post)
+
def test_sdl_key(self):
open(os.path.join(self.get_dir(), 'pre.js'), 'w').write('''
Module.postRun = function() {
@@ -658,6 +680,52 @@ If manually bisecting:
Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'sdl_key.c'), '-o', 'page.html', '--pre-js', 'pre.js', '-s', '''EXPORTED_FUNCTIONS=['_main', '_one']''']).communicate()
self.run_browser('page.html', '', '/report_result?223092870')
+ def test_sdl_key_proxy(self):
+ open(os.path.join(self.get_dir(), 'pre.js'), 'w').write('''
+ var Module = {};
+ Module.postRun = function() {
+ function doOne() {
+ Module._one();
+ setTimeout(doOne, 1000/60);
+ }
+ setTimeout(doOne, 1000/60);
+ }
+ ''')
+
+ def post():
+ html = open('test.html').read()
+ html = html.replace('</body>', '''
+<script>
+function keydown(c) {
+ var event = document.createEvent("KeyboardEvent");
+ event.initKeyEvent("keydown", true, true, window,
+ 0, 0, 0, 0,
+ c, c);
+ document.dispatchEvent(event);
+}
+
+function keyup(c) {
+ var event = document.createEvent("KeyboardEvent");
+ event.initKeyEvent("keyup", true, true, window,
+ 0, 0, 0, 0,
+ c, c);
+ document.dispatchEvent(event);
+}
+
+keydown(1250);keydown(38);keyup(38);keyup(1250); // alt, up
+keydown(1248);keydown(1249);keydown(40);keyup(40);keyup(1249);keyup(1248); // ctrl, shift, down
+keydown(37);keyup(37); // left
+keydown(39);keyup(39); // right
+keydown(65);keyup(65); // a
+keydown(66);keyup(66); // b
+keydown(100);keyup(100); // trigger the end
+
+</script>
+</body>''')
+ open('test.html', 'w').write(html)
+
+ self.btest('sdl_key_proxy.c', '223092870', args=['--proxy-to-worker', '--pre-js', 'pre.js', '-s', '''EXPORTED_FUNCTIONS=['_main', '_one']'''], manual_reference=True, post_build=post)
+
def test_sdl_text(self):
open(os.path.join(self.get_dir(), 'pre.js'), 'w').write('''
Module.postRun = function() {
@@ -1207,6 +1275,12 @@ If manually bisecting:
def test_gl_stride(self):
self.btest('gl_stride.c', reference='gl_stride.png', args=['-s', 'GL_UNSAFE_OPTS=0', '-s', 'LEGACY_GL_EMULATION=1'])
+ def test_gl_vertex_buffer_pre(self):
+ self.btest('gl_vertex_buffer_pre.c', reference='gl_vertex_buffer_pre.png', args=['-s', 'GL_UNSAFE_OPTS=0', '-s', 'LEGACY_GL_EMULATION=1'])
+
+ 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)
+
def test_matrix_identity(self):
self.btest('gl_matrix_identity.c', expected=['-1882984448', '460451840'], args=['-s', 'LEGACY_GL_EMULATION=1'])
@@ -1404,3 +1478,8 @@ If manually bisecting:
def test_emscripten_async_wget2(self):
self.btest('http.cpp', expected='0', args=['-I' + path_from_root('tests')])
+
+ def test_module(self):
+ Popen([PYTHON, EMCC, path_from_root('tests', 'browser_module.cpp'), '-o', 'module.js', '-O2', '-s', 'SIDE_MODULE=1', '-s', 'DLOPEN_SUPPORT=1', '-s', 'EXPORTED_FUNCTIONS=["_one", "_two"]']).communicate()
+ self.btest('browser_main.cpp', args=['-O2', '-s', 'MAIN_MODULE=1', '-s', 'DLOPEN_SUPPORT=1'], expected='8')
+
diff --git a/tests/test_core.py b/tests/test_core.py
index 16bf9a00..5d4f35e8 100644
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -3742,7 +3742,8 @@ def process(filename):
self.do_run(open(path_from_root('tests', 'emscripten_get_now.cpp')).read(), 'Timer resolution is good.')
def test_inlinejs(self):
- if Settings.ASM_JS: return self.skip('asm does not support random code, TODO: something that works in asm')
+ if Settings.ASM_JS: Settings.ASM_JS = 2 # skip validation, asm does not support random code
+ if not self.is_le32(): return self.skip('le32 needed for inline js')
src = r'''
#include <stdio.h>
@@ -3762,7 +3763,8 @@ def process(filename):
self.do_run(src, 'Inline JS is very cool\n3.64\n')
def test_inlinejs2(self):
- if Settings.ASM_JS: return self.skip('asm does not support random code, TODO: something that works in asm')
+ if Settings.ASM_JS: Settings.ASM_JS = 2 # skip validation, asm does not support random code
+ if not self.is_le32(): return self.skip('le32 needed for inline js')
src = r'''
#include <stdio.h>
@@ -3773,8 +3775,8 @@ def process(filename):
}
void mult() {
- asm("var $_$1 = Math.abs(-100); $_$1 *= 2;"); // multiline
- asm __volatile__("Module.print($_$1); Module.print('\n')");
+ asm("var $_$1 = Math.abs(-100); $_$1 *= 2; Module.print($_$1)"); // multiline
+ asm __volatile__("Module.print('done')");
}
int main(int argc, char **argv) {
@@ -3784,7 +3786,7 @@ def process(filename):
}
'''
- self.do_run(src, '4\n200\n')
+ self.do_run(src, '4\n200\ndone\n')
def test_inlinejs3(self):
if Settings.ASM_JS: return self.skip('asm does not support random code, TODO: something that works in asm')
@@ -5580,11 +5582,53 @@ The current type of b is: 9
Settings.RUNTIME_LINKED_LIBS = ['liblib.so'];
self.do_run(main, 'supp: 54,2\nmain: 56\nsupp see: 543\nmain see: 76\nok.')
- def test_dlfcn_basic(self):
- if Settings.ASM_JS: return self.skip('TODO: dlopen in asm')
+ def can_dlfcn(self):
+ if self.emcc_args and '--memory-init-file' in self.emcc_args:
+ for i in range(len(self.emcc_args)):
+ if self.emcc_args[i] == '--memory-init-file':
+ self.emcc_args = self.emcc_args[:i] + self.emcc_args[i+2:]
+ break
- Settings.NAMED_GLOBALS = 1
+ if Settings.ASM_JS:
+ Settings.DLOPEN_SUPPORT = 1
+ else:
+ Settings.NAMED_GLOBALS = 1
+
+ if not self.is_le32():
+ self.skip('need le32 for dlfcn support')
+ return False
+ else:
+ return True
+
+ def prep_dlfcn_lib(self):
+ if Settings.ASM_JS:
+ Settings.MAIN_MODULE = 0
+ Settings.SIDE_MODULE = 1
+ else:
+ Settings.BUILD_AS_SHARED_LIB = 1
+ Settings.INCLUDE_FULL_LIBRARY = 0
+
+ def prep_dlfcn_main(self):
+ if Settings.ASM_JS:
+ Settings.MAIN_MODULE = 1
+ Settings.SIDE_MODULE = 0
+ else:
+ Settings.BUILD_AS_SHARED_LIB = 0
+ Settings.INCLUDE_FULL_LIBRARY = 1
+
+ dlfcn_post_build = '''
+def process(filename):
+ src = open(filename, 'r').read().replace(
+ '// {{PRE_RUN_ADDITIONS}}',
+ "FS.createLazyFile('/', 'liblib.so', 'liblib.so', true, false);"
+ )
+ open(filename, 'w').write(src)
+'''
+
+ def test_dlfcn_basic(self):
+ if not self.can_dlfcn(): return
+ self.prep_dlfcn_lib()
lib_src = '''
#include <cstdio>
@@ -5599,10 +5643,10 @@ The current type of b is: 9
'''
dirname = self.get_dir()
filename = os.path.join(dirname, 'liblib.cpp')
- Settings.BUILD_AS_SHARED_LIB = 1
self.build(lib_src, dirname, filename)
shutil.move(filename + '.o.js', os.path.join(dirname, 'liblib.so'))
+ self.prep_dlfcn_main()
src = '''
#include <cstdio>
#include <dlfcn.h>
@@ -5621,28 +5665,17 @@ The current type of b is: 9
return 0;
}
'''
- Settings.BUILD_AS_SHARED_LIB = 0
- add_pre_run_and_checks = '''
-def process(filename):
- src = open(filename, 'r').read().replace(
- '// {{PRE_RUN_ADDITIONS}}',
- "FS.createLazyFile('/', 'liblib.so', 'liblib.so', true, false);"
- )
- open(filename, 'w').write(src)
-'''
self.do_run(src, 'Constructing main object.\nConstructing lib object.\n',
- post_build=add_pre_run_and_checks)
+ post_build=self.dlfcn_post_build)
def test_dlfcn_qsort(self):
- if self.emcc_args is None: return self.skip('requires emcc')
- if Settings.ASM_JS: return self.skip('TODO: dlopen in asm')
-
- Settings.LINKABLE = 1
- Settings.NAMED_GLOBALS = 1
+ if not self.can_dlfcn(): return
if Settings.USE_TYPED_ARRAYS == 2:
Settings.CORRECT_SIGNS = 1 # Needed for unsafe optimizations
+ self.prep_dlfcn_lib()
+ Settings.EXPORTED_FUNCTIONS = ['_get_cmp']
lib_src = '''
int lib_cmp(const void* left, const void* right) {
const int* a = (const int*) left;
@@ -5660,11 +5693,11 @@ def process(filename):
'''
dirname = self.get_dir()
filename = os.path.join(dirname, 'liblib.cpp')
- Settings.BUILD_AS_SHARED_LIB = 1
- Settings.EXPORTED_FUNCTIONS = ['_get_cmp']
self.build(lib_src, dirname, filename)
shutil.move(filename + '.o.js', os.path.join(dirname, 'liblib.so'))
+ self.prep_dlfcn_main()
+ Settings.EXPORTED_FUNCTIONS = ['_main', '_malloc']
src = '''
#include <stdio.h>
#include <stdlib.h>
@@ -5686,6 +5719,13 @@ def process(filename):
CMP_TYPE lib_cmp_ptr;
int arr[5] = {4, 2, 5, 1, 3};
+ qsort((void*)arr, 5, sizeof(int), main_cmp);
+ printf("Sort with main comparison: ");
+ for (int i = 0; i < 5; i++) {
+ printf("%d ", arr[i]);
+ }
+ printf("\\n");
+
lib_handle = dlopen("liblib.so", RTLD_NOW);
if (lib_handle == NULL) {
printf("Could not load lib.\\n");
@@ -5697,14 +5737,6 @@ def process(filename):
return 1;
}
lib_cmp_ptr = getter_ptr();
-
- qsort((void*)arr, 5, sizeof(int), main_cmp);
- printf("Sort with main comparison: ");
- for (int i = 0; i < 5; i++) {
- printf("%d ", arr[i]);
- }
- printf("\\n");
-
qsort((void*)arr, 5, sizeof(int), lib_cmp_ptr);
printf("Sort with lib comparison: ");
for (int i = 0; i < 5; i++) {
@@ -5715,27 +5747,22 @@ def process(filename):
return 0;
}
'''
- Settings.BUILD_AS_SHARED_LIB = 0
- Settings.EXPORTED_FUNCTIONS = ['_main']
- add_pre_run_and_checks = '''
-def process(filename):
- src = open(filename, 'r').read().replace(
- '// {{PRE_RUN_ADDITIONS}}',
- "FS.createLazyFile('/', 'liblib.so', 'liblib.so', true, false);"
- )
- open(filename, 'w').write(src)
-'''
self.do_run(src, 'Sort with main comparison: 5 4 3 2 1 *Sort with lib comparison: 1 2 3 4 5 *',
output_nicerizer=lambda x, err: x.replace('\n', '*'),
- post_build=add_pre_run_and_checks)
+ post_build=self.dlfcn_post_build)
+
+ if Settings.ASM_JS and os.path.exists(SPIDERMONKEY_ENGINE[0]):
+ out = run_js('liblib.so', engine=SPIDERMONKEY_ENGINE, full_output=True, stderr=STDOUT)
+ if 'asm' in out:
+ self.validate_asmjs(out)
def test_dlfcn_data_and_fptr(self):
- if Settings.ASM_JS: return self.skip('TODO: dlopen in asm')
- if Building.LLVM_OPTS: return self.skip('LLVM opts will optimize out parent_func')
+ if Settings.ASM_JS: return self.skip('this is not a valid case - libraries should not be able to access their parents globals willy nilly')
+ if not self.can_dlfcn(): return
- Settings.LINKABLE = 1
- Settings.NAMED_GLOBALS = 1
+ if Building.LLVM_OPTS: return self.skip('LLVM opts will optimize out parent_func')
+ self.prep_dlfcn_lib()
lib_src = '''
#include <stdio.h>
@@ -5760,21 +5787,23 @@ def process(filename):
'''
dirname = self.get_dir()
filename = os.path.join(dirname, 'liblib.cpp')
- Settings.BUILD_AS_SHARED_LIB = 1
Settings.EXPORTED_FUNCTIONS = ['_func']
Settings.EXPORTED_GLOBALS = ['_global']
self.build(lib_src, dirname, filename)
shutil.move(filename + '.o.js', os.path.join(dirname, 'liblib.so'))
+ self.prep_dlfcn_main()
+ Settings.LINKABLE = 1
src = '''
#include <stdio.h>
#include <dlfcn.h>
+ #include <emscripten.h>
typedef void (*FUNCTYPE(int, void(*)()))();
FUNCTYPE func;
- void parent_func() {
+ void EMSCRIPTEN_KEEPALIVE parent_func() {
printf("parent_func called from child\\n");
}
@@ -5818,23 +5847,14 @@ def process(filename):
return 0;
}
'''
- Settings.BUILD_AS_SHARED_LIB = 0
Settings.EXPORTED_FUNCTIONS = ['_main']
Settings.EXPORTED_GLOBALS = []
- add_pre_run_and_checks = '''
-def process(filename):
- src = open(filename, 'r').read().replace(
- '// {{PRE_RUN_ADDITIONS}}',
- "FS.createLazyFile('/', 'liblib.so', 'liblib.so', true, false);"
- )
- open(filename, 'w').write(src)
-'''
self.do_run(src, 'In func: 13*First calling main_fptr from lib.*Second calling lib_fptr from main.*parent_func called from child*parent_func called from child*Var: 42*',
output_nicerizer=lambda x, err: x.replace('\n', '*'),
- post_build=add_pre_run_and_checks)
+ post_build=self.dlfcn_post_build)
def test_dlfcn_alias(self):
- if Settings.ASM_JS: return self.skip('TODO: dlopen in asm')
+ if Settings.ASM_JS: return self.skip('this is not a valid case - libraries should not be able to access their parents globals willy nilly')
Settings.LINKABLE = 1
Settings.NAMED_GLOBALS = 1
@@ -5876,29 +5896,23 @@ def process(filename):
Settings.BUILD_AS_SHARED_LIB = 0
Settings.INCLUDE_FULL_LIBRARY = 1
Settings.EXPORTED_FUNCTIONS = ['_main']
- add_pre_run_and_checks = '''
-def process(filename):
- src = open(filename, 'r').read().replace(
- '// {{PRE_RUN_ADDITIONS}}',
- "FS.createLazyFile('/', 'liblib.so', 'liblib.so', true, false);"
- )
- open(filename, 'w').write(src)
-'''
self.do_run(src, 'Parent global: 123.*Parent global: 456.*',
output_nicerizer=lambda x, err: x.replace('\n', '*'),
- post_build=add_pre_run_and_checks,
+ post_build=self.dlfcn_post_build,
extra_emscripten_args=['-H', 'libc/fcntl.h,libc/sys/unistd.h,poll.h,libc/math.h,libc/time.h,libc/langinfo.h'])
Settings.INCLUDE_FULL_LIBRARY = 0
def test_dlfcn_varargs(self):
- if Settings.ASM_JS: return self.skip('TODO: dlopen in asm')
+ if Settings.ASM_JS: return self.skip('this is not a valid case - libraries should not be able to access their parents globals willy nilly')
+
+ if not self.can_dlfcn(): return
Settings.LINKABLE = 1
- Settings.NAMED_GLOBALS = 1
if Building.LLVM_OPTS == 2: return self.skip('LLVM LTO will optimize things that prevent shared objects from working')
if Settings.QUANTUM_SIZE == 1: return self.skip('FIXME: Add support for this')
+ self.prep_dlfcn_lib()
lib_src = r'''
void print_ints(int n, ...);
extern "C" void func() {
@@ -5907,15 +5921,16 @@ def process(filename):
'''
dirname = self.get_dir()
filename = os.path.join(dirname, 'liblib.cpp')
- Settings.BUILD_AS_SHARED_LIB = 1
Settings.EXPORTED_FUNCTIONS = ['_func']
self.build(lib_src, dirname, filename)
shutil.move(filename + '.o.js', os.path.join(dirname, 'liblib.so'))
+ self.prep_dlfcn_main()
src = r'''
#include <stdarg.h>
#include <stdio.h>
#include <dlfcn.h>
+ #include <assert.h>
void print_ints(int n, ...) {
va_list args;
@@ -5933,24 +5948,16 @@ def process(filename):
print_ints(2, 100, 200);
lib_handle = dlopen("liblib.so", RTLD_NOW);
+ assert(lib_handle);
fptr = (void (*)())dlsym(lib_handle, "func");
fptr();
return 0;
}
'''
- Settings.BUILD_AS_SHARED_LIB = 0
Settings.EXPORTED_FUNCTIONS = ['_main']
- add_pre_run_and_checks = '''
-def process(filename):
- src = open(filename, 'r').read().replace(
- '// {{PRE_RUN_ADDITIONS}}',
- "FS.createLazyFile('/', 'liblib.so', 'liblib.so', true, false);"
- )
- open(filename, 'w').write(src)
-'''
self.do_run(src, '100\n200\n13\n42\n',
- post_build=add_pre_run_and_checks)
+ post_build=self.dlfcn_post_build)
def test_dlfcn_self(self):
if Settings.USE_TYPED_ARRAYS == 1: return self.skip('Does not work with USE_TYPED_ARRAYS=1')
@@ -5959,14 +5966,15 @@ def process(filename):
src = r'''
#include <stdio.h>
#include <dlfcn.h>
+#include <emscripten.h>
-int global = 123;
+int EMSCRIPTEN_KEEPALIVE global = 123;
-extern "C" __attribute__((noinline)) void foo(int x) {
+extern "C" EMSCRIPTEN_KEEPALIVE void foo(int x) {
printf("%d\n", x);
}
-extern "C" __attribute__((noinline)) void repeatable() {
+extern "C" EMSCRIPTEN_KEEPALIVE void repeatable() {
void* self = dlopen(NULL, RTLD_LAZY);
int* global_ptr = (int*)dlsym(self, "global");
void (*foo_ptr)(int) = (void (*)(int))dlsym(self, "foo");
@@ -5987,15 +5995,372 @@ return 0;
break
else:
raise Exception('Could not find symbol table!')
- import json
- table = json.loads(table[table.find('{'):table.rfind('}')+1])
- actual = list(sorted(table.keys()))
+ table = table[table.find('{'):table.rfind('}')+1]
# ensure there aren't too many globals; we don't want unnamed_addr
- assert actual == ['_foo', '_global', '_main', '_repeatable'], \
- "Symbol table does not match: %s" % actual
-
+ assert table.count(',') <= 4
self.do_run(src, '123\n123', post_build=(None, post))
+
+ def test_dlfcn_unique_sig(self):
+ if not self.can_dlfcn(): return
+
+ self.prep_dlfcn_lib()
+ lib_src = '''
+ #include <stdio.h>
+
+ int myfunc(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, int m) {
+ return 13;
+ }
+ '''
+ Settings.EXPORTED_FUNCTIONS = ['_myfunc']
+ dirname = self.get_dir()
+ filename = os.path.join(dirname, 'liblib.c')
+ self.build(lib_src, dirname, filename)
+ shutil.move(filename + '.o.js', os.path.join(dirname, 'liblib.so'))
+
+ self.prep_dlfcn_main()
+ src = '''
+ #include <assert.h>
+ #include <stdio.h>
+ #include <dlfcn.h>
+
+ typedef int (*FUNCTYPE)(int, int, int, int, int, int, int, int, int, int, int, int, int);
+
+ int main() {
+ void *lib_handle;
+ FUNCTYPE func_ptr;
+
+ lib_handle = dlopen("liblib.so", RTLD_NOW);
+ assert(lib_handle != NULL);
+
+ func_ptr = (FUNCTYPE)dlsym(lib_handle, "myfunc");
+ assert(func_ptr != NULL);
+ assert(func_ptr(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) == 13);
+
+ puts("success");
+
+ return 0;
+ }
+ '''
+ Settings.EXPORTED_FUNCTIONS = ['_main', '_malloc']
+ self.do_run(src, 'success', force_c=True, post_build=self.dlfcn_post_build)
+
+ def test_dlfcn_stacks(self):
+ if not self.can_dlfcn(): return
+
+ self.prep_dlfcn_lib()
+ lib_src = '''
+ #include <assert.h>
+ #include <stdio.h>
+ #include <string.h>
+
+ int myfunc(const char *input) {
+ char bigstack[1024] = { 0 };
+
+ // make sure we didn't just trample the stack!
+ assert(!strcmp(input, "foobar"));
+
+ snprintf(bigstack, sizeof(bigstack), input);
+ return strlen(bigstack);
+ }
+ '''
+ Settings.EXPORTED_FUNCTIONS = ['_myfunc']
+ dirname = self.get_dir()
+ filename = os.path.join(dirname, 'liblib.c')
+ self.build(lib_src, dirname, filename)
+ shutil.move(filename + '.o.js', os.path.join(dirname, 'liblib.so'))
+
+ self.prep_dlfcn_main()
+ src = '''
+ #include <assert.h>
+ #include <stdio.h>
+ #include <dlfcn.h>
+
+ typedef int (*FUNCTYPE)(const char *);
+
+ int main() {
+ void *lib_handle;
+ FUNCTYPE func_ptr;
+ char str[128];
+
+ snprintf(str, sizeof(str), "foobar");
+
+ lib_handle = dlopen("liblib.so", RTLD_NOW);
+ assert(lib_handle != NULL);
+
+ func_ptr = (FUNCTYPE)dlsym(lib_handle, "myfunc");
+ assert(func_ptr != NULL);
+ assert(func_ptr(str) == 6);
+
+ puts("success");
+
+ return 0;
+ }
+ '''
+ Settings.EXPORTED_FUNCTIONS = ['_main', '_malloc']
+ self.do_run(src, 'success', force_c=True, post_build=self.dlfcn_post_build)
+
+ def test_dlfcn_funcs(self):
+ if not self.can_dlfcn(): return
+
+ self.prep_dlfcn_lib()
+ lib_src = r'''
+ #include <assert.h>
+ #include <stdio.h>
+ #include <string.h>
+
+ typedef void (*voidfunc)();
+ typedef void (*intfunc)(int);
+
+ void callvoid(voidfunc f) { f(); }
+ void callint(voidfunc f, int x) { f(x); }
+
+ void void_0() { printf("void 0\n"); }
+ void void_1() { printf("void 1\n"); }
+ voidfunc getvoid(int i) {
+ switch(i) {
+ case 0: return void_0;
+ case 1: return void_1;
+ default: return NULL;
+ }
+ }
+
+ void int_0(int x) { printf("int 0 %d\n", x); }
+ void int_1(int x) { printf("int 1 %d\n", x); }
+ intfunc getint(int i) {
+ switch(i) {
+ case 0: return int_0;
+ case 1: return int_1;
+ default: return NULL;
+ }
+ }
+ '''
+ Settings.EXPORTED_FUNCTIONS = ['_callvoid', '_callint', '_getvoid', '_getint']
+ dirname = self.get_dir()
+ filename = os.path.join(dirname, 'liblib.c')
+ self.build(lib_src, dirname, filename)
+ shutil.move(filename + '.o.js', os.path.join(dirname, 'liblib.so'))
+
+ self.prep_dlfcn_main()
+ src = r'''
+ #include <assert.h>
+ #include <stdio.h>
+ #include <dlfcn.h>
+
+ typedef void (*voidfunc)();
+ typedef void (*intfunc)(int);
+
+ typedef void (*voidcaller)(voidfunc);
+ typedef void (*intcaller)(intfunc, int);
+
+ typedef voidfunc (*voidgetter)(int);
+ typedef intfunc (*intgetter)(int);
+
+ void void_main() { printf("main.\n"); }
+ void int_main(int x) { printf("main %d\n", x); }
+
+ int main() {
+ printf("go\n");
+ void *lib_handle;
+ lib_handle = dlopen("liblib.so", RTLD_NOW);
+ assert(lib_handle != NULL);
+
+ voidcaller callvoid = (voidcaller)dlsym(lib_handle, "callvoid");
+ assert(callvoid != NULL);
+ callvoid(void_main);
+
+ intcaller callint = (intcaller)dlsym(lib_handle, "callint");
+ assert(callint != NULL);
+ callint(int_main, 201);
+
+ voidgetter getvoid = (voidgetter)dlsym(lib_handle, "getvoid");
+ assert(getvoid != NULL);
+ callvoid(getvoid(0));
+ callvoid(getvoid(1));
+
+ intgetter getint = (intgetter)dlsym(lib_handle, "getint");
+ assert(getint != NULL);
+ callint(getint(0), 54);
+ callint(getint(1), 9000);
+
+ assert(getint(1000) == NULL);
+
+ puts("ok");
+ return 0;
+ }
+ '''
+ Settings.EXPORTED_FUNCTIONS = ['_main', '_malloc']
+ self.do_run(src, '''go
+main.
+main 201
+void 0
+void 1
+int 0 54
+int 1 9000
+ok
+''', force_c=True, post_build=self.dlfcn_post_build)
+
+ def test_dlfcn_mallocs(self):
+ if not Settings.ASM_JS: return self.skip('needs asm')
+
+ if not self.can_dlfcn(): return
+
+ Settings.TOTAL_MEMORY = 64*1024*1024 # will be exhausted without functional malloc/free
+
+ self.prep_dlfcn_lib()
+ lib_src = r'''
+ #include <assert.h>
+ #include <stdio.h>
+ #include <string.h>
+ #include <stdlib.h>
+
+ void *mallocproxy(int n) { return malloc(n); }
+ void freeproxy(void *p) { free(p); }
+ '''
+ Settings.EXPORTED_FUNCTIONS = ['_mallocproxy', '_freeproxy']
+ dirname = self.get_dir()
+ filename = os.path.join(dirname, 'liblib.c')
+ self.build(lib_src, dirname, filename)
+ shutil.move(filename + '.o.js', os.path.join(dirname, 'liblib.so'))
+
+ self.prep_dlfcn_main()
+ src = open(path_from_root('tests', 'dlmalloc_proxy.c')).read()
+ Settings.EXPORTED_FUNCTIONS = ['_main', '_malloc', '_free']
+ self.do_run(src, '''*294,153*''', force_c=True, post_build=self.dlfcn_post_build)
+
+ def test_dlfcn_longjmp(self):
+ if not self.can_dlfcn(): return
+
+ self.prep_dlfcn_lib()
+ lib_src = r'''
+ #include <setjmp.h>
+
+ void jumpy(jmp_buf buf) {
+ static int i = 0;
+ i++;
+ if (i == 10) longjmp(buf, i);
+ printf("pre %d\n", i);
+ }
+ '''
+ Settings.EXPORTED_FUNCTIONS = ['_jumpy']
+ dirname = self.get_dir()
+ filename = os.path.join(dirname, 'liblib.c')
+ self.build(lib_src, dirname, filename)
+ shutil.move(filename + '.o.js', os.path.join(dirname, 'liblib.so'))
+
+ self.prep_dlfcn_main()
+ src = r'''
+ #include <assert.h>
+ #include <stdio.h>
+ #include <dlfcn.h>
+ #include <setjmp.h>
+
+ typedef void (*jumpfunc)(jmp_buf);
+
+ int main() {
+ printf("go!\n");
+
+ void *lib_handle;
+ lib_handle = dlopen("liblib.so", RTLD_NOW);
+ assert(lib_handle != NULL);
+
+ jumpfunc jumpy = (jumpfunc)dlsym(lib_handle, "jumpy");
+ assert(jumpy);
+
+ jmp_buf buf;
+ int jmpval = setjmp(buf);
+ if (jmpval == 0) {
+ while (1) jumpy(buf);
+ } else {
+ printf("out!\n");
+ }
+
+ return 0;
+ }
+ '''
+ Settings.EXPORTED_FUNCTIONS = ['_main', '_malloc', '_free']
+ self.do_run(src, '''go!
+pre 1
+pre 2
+pre 3
+pre 4
+pre 5
+pre 6
+pre 7
+pre 8
+pre 9
+out!
+''', post_build=self.dlfcn_post_build, force_c=True)
+
+ def zzztest_dlfcn_exceptions(self): # TODO: make this work. need to forward tempRet0 across modules
+ if not self.can_dlfcn(): return
+
+ Settings.DISABLE_EXCEPTION_CATCHING = 0
+
+ self.prep_dlfcn_lib()
+ lib_src = r'''
+ extern "C" {
+ int ok() {
+ return 65;
+ }
+ int fail() {
+ throw 123;
+ }
+ }
+ '''
+ Settings.EXPORTED_FUNCTIONS = ['_ok', '_fail']
+ dirname = self.get_dir()
+ filename = os.path.join(dirname, 'liblib.cpp')
+ self.build(lib_src, dirname, filename)
+ shutil.move(filename + '.o.js', os.path.join(dirname, 'liblib.so'))
+
+ self.prep_dlfcn_main()
+ src = r'''
+ #include <assert.h>
+ #include <stdio.h>
+ #include <dlfcn.h>
+
+ typedef int (*intfunc)();
+
+ int main() {
+ printf("go!\n");
+
+ void *lib_handle;
+ lib_handle = dlopen("liblib.so", RTLD_NOW);
+ assert(lib_handle != NULL);
+
+ intfunc okk = (intfunc)dlsym(lib_handle, "ok");
+ intfunc faill = (intfunc)dlsym(lib_handle, "fail");
+ assert(okk && faill);
+
+ try {
+ printf("ok: %d\n", okk());
+ } catch(...) {
+ printf("wha\n");
+ }
+
+ try {
+ printf("fail: %d\n", faill());
+ } catch(int x) {
+ printf("int %d\n", x);
+ }
+
+ try {
+ printf("fail: %d\n", faill());
+ } catch(double x) {
+ printf("caught %f\n", x);
+ }
+
+ return 0;
+ }
+ '''
+ Settings.EXPORTED_FUNCTIONS = ['_main', '_malloc', '_free']
+ self.do_run(src, '''go!
+ok: 65
+int 123
+ok
+''', post_build=self.dlfcn_post_build)
+
def test_rand(self):
return self.skip('rand() is now random') # FIXME
@@ -6992,7 +7357,7 @@ def process(filename):
FS.registerDevice(dummy_device, {});
FS.createDataFile('/', 'file', 'abcdef', true, true);
- FS.mkdev('/device', 0666, dummy_device);
+ FS.mkdev('/device', dummy_device);
\'\'\'
)
open(filename, 'w').write(src)
@@ -7250,32 +7615,18 @@ def process(filename):
Settings.INCLUDE_FULL_LIBRARY = 0
def test_unistd_access(self):
- add_pre_run = '''
-def process(filename):
- import tools.shared as shared
- src = open(filename, 'r').read().replace(
- '// {{PRE_RUN_ADDITIONS}}',
- open(shared.path_from_root('tests', 'unistd', 'access.js'), 'r').read()
- )
- open(filename, 'w').write(src)
-'''
+ if Settings.ASM_JS: Settings.ASM_JS = 2 # skip validation, asm does not support random code
+ if not self.is_le32(): return self.skip('le32 needed for inline js')
src = open(path_from_root('tests', 'unistd', 'access.c'), 'r').read()
expected = open(path_from_root('tests', 'unistd', 'access.out'), 'r').read()
- self.do_run(src, expected, post_build=add_pre_run)
+ self.do_run(src, expected)
def test_unistd_curdir(self):
- add_pre_run = '''
-def process(filename):
- import tools.shared as shared
- src = open(filename, 'r').read().replace(
- '// {{PRE_RUN_ADDITIONS}}',
- open(shared.path_from_root('tests', 'unistd', 'curdir.js'), 'r').read()
- )
- open(filename, 'w').write(src)
-'''
+ if Settings.ASM_JS: Settings.ASM_JS = 2 # skip validation, asm does not support random code
+ if not self.is_le32(): return self.skip('le32 needed for inline js')
src = open(path_from_root('tests', 'unistd', 'curdir.c'), 'r').read()
expected = open(path_from_root('tests', 'unistd', 'curdir.out'), 'r').read()
- self.do_run(src, expected, post_build=add_pre_run)
+ self.do_run(src, expected)
def test_unistd_close(self):
src = open(path_from_root('tests', 'unistd', 'close.c'), 'r').read()
@@ -7302,18 +7653,11 @@ def process(filename):
self.do_run(src, expected)
def test_unistd_truncate(self):
- add_pre_run = '''
-def process(filename):
- import tools.shared as shared
- src = open(filename, 'r').read().replace(
- '// {{PRE_RUN_ADDITIONS}}',
- open(shared.path_from_root('tests', 'unistd', 'truncate.js'), 'r').read()
- )
- open(filename, 'w').write(src)
-'''
+ if Settings.ASM_JS: Settings.ASM_JS = 2 # skip validation, asm does not support random code
+ if not self.is_le32(): return self.skip('le32 needed for inline js')
src = open(path_from_root('tests', 'unistd', 'truncate.c'), 'r').read()
expected = open(path_from_root('tests', 'unistd', 'truncate.out'), 'r').read()
- self.do_run(src, expected, post_build=add_pre_run)
+ self.do_run(src, expected)
def test_unistd_swab(self):
src = open(path_from_root('tests', 'unistd', 'swab.c'), 'r').read()
@@ -7339,18 +7683,11 @@ def process(filename):
self.do_run(src, 'success', force_c=True)
def test_unistd_links(self):
- add_pre_run = '''
-def process(filename):
- import tools.shared as shared
- src = open(filename, 'r').read().replace(
- '// {{PRE_RUN_ADDITIONS}}',
- open(shared.path_from_root('tests', 'unistd', 'links.js'), 'r').read()
- )
- open(filename, 'w').write(src)
-'''
+ if Settings.ASM_JS: Settings.ASM_JS = 2 # skip validation, asm does not support random code
+ if not self.is_le32(): return self.skip('le32 needed for inline js')
src = open(path_from_root('tests', 'unistd', 'links.c'), 'r').read()
expected = open(path_from_root('tests', 'unistd', 'links.out'), 'r').read()
- self.do_run(src, expected, post_build=add_pre_run)
+ self.do_run(src, expected)
def test_unistd_sleep(self):
src = open(path_from_root('tests', 'unistd', 'sleep.c'), 'r').read()
@@ -7358,18 +7695,12 @@ def process(filename):
self.do_run(src, expected)
def test_unistd_io(self):
- add_pre_run = '''
-def process(filename):
- import tools.shared as shared
- src = open(filename, 'r').read().replace(
- '// {{PRE_RUN_ADDITIONS}}',
- open(shared.path_from_root('tests', 'unistd', 'io.js'), 'r').read()
- )
- open(filename, 'w').write(src)
-'''
+ if Settings.ASM_JS: Settings.ASM_JS = 2 # skip validation, asm does not support random code
+ if not self.is_le32(): return self.skip('le32 needed for inline js')
+ if self.run_name == 'o2': return self.skip('non-asm optimized builds can fail with inline js')
src = open(path_from_root('tests', 'unistd', 'io.c'), 'r').read()
expected = open(path_from_root('tests', 'unistd', 'io.out'), 'r').read()
- self.do_run(src, expected, post_build=add_pre_run)
+ self.do_run(src, expected)
def test_unistd_misc(self):
src = open(path_from_root('tests', 'unistd', 'misc.c'), 'r').read()
diff --git a/tests/test_other.py b/tests/test_other.py
index fd1a6245..627995e9 100644
--- a/tests/test_other.py
+++ b/tests/test_other.py
@@ -281,54 +281,65 @@ f.close()
if os.name == 'nt':
make_command = 'mingw32-make'
- emscriptencmaketoolchain = path_from_root('cmake', 'Platform', 'Emscripten.cmake')
+ generator = 'MinGW Makefiles'
+ emconfigure = path_from_root('emconfigure.bat')
else:
make_command = 'make'
- emscriptencmaketoolchain = path_from_root('cmake', 'Platform', 'Emscripten_unix.cmake')
+ generator = 'Unix Makefiles'
+ emconfigure = path_from_root('emconfigure')
cmake_cases = ['target_js', 'target_html']
cmake_outputs = ['hello_world.js', 'hello_world_gles.html']
- for i in range(0, 2):
+ for i in range(0, 2): # Test both JS and HTML build outputs from CMake.
for configuration in ['Debug', 'Release']:
-
- # Create a temp workspace folder
- cmakelistsdir = path_from_root('tests', 'cmake', cmake_cases[i])
- tempdirname = tempfile.mkdtemp(prefix='emscripten_test_' + self.__class__.__name__ + '_', dir=TEMP_DIR)
- try:
- os.chdir(tempdirname)
-
- # Run Cmake
- cmd = ['cmake', '-DCMAKE_TOOLCHAIN_FILE='+emscriptencmaketoolchain,
- '-DCMAKE_BUILD_TYPE=' + configuration,
- '-DCMAKE_MODULE_PATH=' + path_from_root('cmake').replace('\\', '/'),
- '-G' 'Unix Makefiles', cmakelistsdir]
- ret = Popen(cmd, stdout=PIPE, stderr=PIPE).communicate()
- if ret[1] != None and len(ret[1].strip()) > 0:
- print >> sys.stderr, ret[1] # If there were any errors, print them directly to console for diagnostics.
- if 'error' in ret[1].lower():
- print >> sys.stderr, 'Failed command: ' + ' '.join(cmd)
- print >> sys.stderr, 'Result:\n' + ret[1]
- raise Exception('cmake call failed!')
- assert os.path.exists(tempdirname + '/Makefile'), 'CMake call did not produce a Makefile!'
-
- # Build
- cmd = [make_command]
- ret = Popen(cmd, stdout=PIPE).communicate()
- if ret[1] != None and len(ret[1].strip()) > 0:
- print >> sys.stderr, ret[1] # If there were any errors, print them directly to console for diagnostics.
- if 'error' in ret[0].lower() and not '0 error(s)' in ret[0].lower():
- print >> sys.stderr, 'Failed command: ' + ' '.join(cmd)
- print >> sys.stderr, 'Result:\n' + ret[0]
- raise Exception('make failed!')
- assert os.path.exists(tempdirname + '/' + cmake_outputs[i]), 'Building a cmake-generated Makefile failed to produce an output file %s!' % tempdirname + '/' + cmake_outputs[i]
-
- # Run through node, if CMake produced a .js file.
- if cmake_outputs[i].endswith('.js'):
- ret = Popen(listify(NODE_JS) + [tempdirname + '/' + cmake_outputs[i]], stdout=PIPE).communicate()[0]
- assert 'hello, world!' in ret, 'Running cmake-based .js application failed!'
- finally:
- os.chdir(path_from_root('tests')) # Move away from the directory we are about to remove.
- shutil.rmtree(tempdirname)
+ # CMake can be invoked in two ways, using 'emconfigure cmake', or by directly running 'cmake'.
+ # Test both methods.
+ for invoke_method in ['cmake', 'emconfigure']:
+
+ # Create a temp workspace folder
+ cmakelistsdir = path_from_root('tests', 'cmake', cmake_cases[i])
+ tempdirname = tempfile.mkdtemp(prefix='emscripten_test_' + self.__class__.__name__ + '_', dir=TEMP_DIR)
+ try:
+ os.chdir(tempdirname)
+
+ verbose_level = int(os.getenv('EM_BUILD_VERBOSE')) if os.getenv('EM_BUILD_VERBOSE') != None else 0
+
+ # Run Cmake
+ if invoke_method == 'cmake':
+ # Test invoking cmake directly.
+ cmd = ['cmake', '-DCMAKE_TOOLCHAIN_FILE='+path_from_root('cmake', 'Platform', 'Emscripten.cmake'),
+ '-DCMAKE_BUILD_TYPE=' + configuration, '-G', generator, cmakelistsdir]
+ else:
+ # Test invoking via 'emconfigure cmake'
+ cmd = [emconfigure, 'cmake', '-DCMAKE_BUILD_TYPE=' + configuration, '-G', generator, cmakelistsdir]
+
+ ret = Popen(cmd, stdout=None if verbose_level >= 2 else PIPE, stderr=None if verbose_level >= 1 else PIPE).communicate()
+ if len(ret) > 1 and ret[1] != None and len(ret[1].strip()) > 0:
+ logging.error(ret[1]) # If there were any errors, print them directly to console for diagnostics.
+ if len(ret) > 1 and ret[1] != None and 'error' in ret[1].lower():
+ logging.error('Failed command: ' + ' '.join(cmd))
+ logging.error('Result:\n' + ret[1])
+ raise Exception('cmake call failed!')
+ assert os.path.exists(tempdirname + '/Makefile'), 'CMake call did not produce a Makefile!'
+
+ # Build
+ cmd = [make_command] + (['VERBOSE=1'] if verbose_level >= 3 else [])
+ ret = Popen(cmd, stdout=None if verbose_level >= 2 else PIPE).communicate()
+ if len(ret) > 1 and ret[1] != None and len(ret[1].strip()) > 0:
+ logging.error(ret[1]) # If there were any errors, print them directly to console for diagnostics.
+ if len(ret) > 0 and ret[0] != None and 'error' in ret[0].lower() and not '0 error(s)' in ret[0].lower():
+ logging.error('Failed command: ' + ' '.join(cmd))
+ logging.error('Result:\n' + ret[0])
+ raise Exception('make failed!')
+ assert os.path.exists(tempdirname + '/' + cmake_outputs[i]), 'Building a cmake-generated Makefile failed to produce an output file %s!' % tempdirname + '/' + cmake_outputs[i]
+
+ # Run through node, if CMake produced a .js file.
+ if cmake_outputs[i].endswith('.js'):
+ ret = Popen(listify(NODE_JS) + [tempdirname + '/' + cmake_outputs[i]], stdout=PIPE).communicate()[0]
+ assert 'hello, world!' in ret, 'Running cmake-based .js application failed!'
+ finally:
+ os.chdir(path_from_root('tests')) # Move away from the directory we are about to remove.
+ shutil.rmtree(tempdirname)
def test_failure_error_code(self):
for compiler in [EMCC, EMXX]:
@@ -1884,3 +1895,12 @@ you should see two lines of text in different colors and a blue rectangle
SDL_Quit called (and ignored)
done.
''' in output, output
+
+ def test_preprocess(self):
+ self.clear()
+
+ out, err = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world.c'), '-E'], stdout=PIPE).communicate()
+ assert not os.path.exists('a.out.js')
+ assert '''tests/hello_world.c"''' in out
+ assert '''printf("hello, world!''' in out
+
diff --git a/tests/unistd/access.c b/tests/unistd/access.c
index 89428610..4d5ba08e 100644
--- a/tests/unistd/access.c
+++ b/tests/unistd/access.c
@@ -1,8 +1,16 @@
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
+#include <emscripten.h>
int main() {
+ EM_ASM(
+ FS.writeFile('/forbidden', ''); FS.chmod('/forbidden', 0000);
+ FS.writeFile('/readable', ''); FS.chmod('/readable', 0444);
+ FS.writeFile('/writeable', ''); FS.chmod('/writeable', 0222);
+ FS.writeFile('/allaccess', ''); FS.chmod('/allaccess', 0777);
+ );
+
char* files[] = {"/readable", "/writeable",
"/allaccess", "/forbidden", "/nonexistent"};
for (int i = 0; i < sizeof files / sizeof files[0]; i++) {
diff --git a/tests/unistd/access.js b/tests/unistd/access.js
deleted file mode 100644
index ea9e6359..00000000
--- a/tests/unistd/access.js
+++ /dev/null
@@ -1,4 +0,0 @@
-FS.createDataFile('/', 'forbidden', '', false, false);
-FS.createDataFile('/', 'readable', '', true, false);
-FS.createDataFile('/', 'writeable', '', false, true);
-FS.createDataFile('/', 'allaccess', '', true, true);
diff --git a/tests/unistd/access.out b/tests/unistd/access.out
index dffe0b9e..d462e5a5 100644
--- a/tests/unistd/access.out
+++ b/tests/unistd/access.out
@@ -2,8 +2,8 @@ F_OK(/readable): 0
errno: 0
R_OK(/readable): 0
errno: 0
-X_OK(/readable): 0
-errno: 0
+X_OK(/readable): -1
+errno: 13
W_OK(/readable): -1
errno: 13
diff --git a/tests/unistd/curdir.c b/tests/unistd/curdir.c
index 63b9c7fe..b9f22dd7 100644
--- a/tests/unistd/curdir.c
+++ b/tests/unistd/curdir.c
@@ -2,8 +2,19 @@
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
+#include <emscripten.h>
int main() {
+ EM_ASM(
+ var dummy_device = FS.makedev(64, 0);
+ FS.registerDevice(dummy_device, {});
+ FS.mkdev('/device', dummy_device);
+
+ FS.mkdir('/folder');
+ FS.symlink('/folder', '/link');
+ FS.writeFile('/file', '', { mode: 0777 });
+ );
+
char buffer[256];
printf("getwd: %s\n", getwd(buffer));
printf("errno: %d\n", errno);
diff --git a/tests/unistd/curdir.js b/tests/unistd/curdir.js
deleted file mode 100644
index 75a1d2ce..00000000
--- a/tests/unistd/curdir.js
+++ /dev/null
@@ -1,7 +0,0 @@
-var dummy_device = FS.makedev(64, 0);
-FS.registerDevice(dummy_device, {});
-
-FS.createDataFile('/', 'file', '', true, true);
-FS.createFolder('/', 'folder', true, true);
-FS.mkdev('/device', 0666, dummy_device);
-FS.createLink('/', 'link', 'folder', true, true);
diff --git a/tests/unistd/io.c b/tests/unistd/io.c
index a96290ef..0ff5f4fb 100644
--- a/tests/unistd/io.c
+++ b/tests/unistd/io.c
@@ -3,8 +3,58 @@
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
+#include <emscripten.h>
int main() {
+ EM_ASM(
+ var major = 80;
+
+ var device = FS.makedev(major++, 0);
+ FS.registerDevice(device, {
+ open: function(stream) {
+ stream.payload = [65, 66, 67, 68];
+ },
+ read: function(stream, buffer, offset, length, pos) {
+ var bytesRead = 0;
+ for (var i = 0; i < length; i++) {
+ if (stream.payload.length) {
+ bytesRead++;
+ buffer[offset+i] = stream.payload.shift();
+ } else {
+ break;
+ }
+ }
+ return bytesRead;
+ },
+ write: function(stream, buffer, offset, length, pos) {
+ for (var i = 0; i < length; i++) {
+ Module.print('TO DEVICE: ' + buffer[offset+i]);
+ }
+ return i;
+ }
+ });
+ FS.mkdev('/device', device);
+
+ var broken_device = FS.makedev(major++, 0);
+ FS.registerDevice(broken_device, {
+ read: function(stream, buffer, offset, length, pos) {
+ throw new FS.ErrnoError(ERRNO_CODES.EIO);
+ },
+ write: function(stream, buffer, offset, length, pos) {
+ throw new FS.ErrnoError(ERRNO_CODES.EIO);
+ }
+ });
+ FS.mkdev('/broken-device', broken_device);
+
+ // NB: These are meant to test FS.createDevice specifically,
+ // and as such do not use registerDevice/mkdev
+ FS.createDevice('/', 'createDevice-read-only', function() {});
+ FS.createDevice('/', 'createDevice-write-only', null, function() {});
+
+ FS.mkdir('/folder', 0777);
+ FS.writeFile('/file', '1234567890');
+ );
+
char readBuffer[256] = {0};
char writeBuffer[] = "writeme";
diff --git a/tests/unistd/io.js b/tests/unistd/io.js
deleted file mode 100644
index 11c0da79..00000000
--- a/tests/unistd/io.js
+++ /dev/null
@@ -1,52 +0,0 @@
-(function() {
- var major = 80;
-
- var device = FS.makedev(major++, 0);
- var device_ops = {
- open: function(stream) {
- stream.payload = [65, 66, 67, 68];
- },
- read: function(stream, buffer, offset, length, pos) {
- var bytesRead = 0;
- for (var i = 0; i < length; i++) {
- if (stream.payload.length) {
- bytesRead++;
- buffer[offset+i] = stream.payload.shift();
- } else {
- break;
- }
- }
- return bytesRead;
- },
- write: function(stream, buffer, offset, length, pos) {
- for (var i = 0; i < length; i++) {
- Module.print("TO DEVICE: " + buffer[offset+i]);
- }
- return i;
- }
- };
- FS.registerDevice(device, device_ops);
-
- FS.mkdev('/device', 0666, device);
-
- var broken_device = FS.makedev(major++, 0);
- var broken_device_ops = {
- read: function(stream, buffer, offset, length, pos) {
- throw new FS.ErrnoError(ERRNO_CODES.EIO);
- },
- write: function(stream, buffer, offset, length, pos) {
- throw new FS.ErrnoError(ERRNO_CODES.EIO);
- }
- };
- FS.registerDevice(broken_device, broken_device_ops);
-
- FS.mkdev('/broken-device', 0666, broken_device);
-
- // NB: These are meant to test FS.createDevice specifically,
- // and as such do not use registerDevice/mkdev
- FS.createDevice('/', 'createDevice-read-only', function() {});
- FS.createDevice('/', 'createDevice-write-only', null, function() {});
-
- FS.createDataFile('/', 'file', '1234567890', true, true);
- FS.createFolder('/', 'folder', true, true);
-})();
diff --git a/tests/unistd/links.c b/tests/unistd/links.c
index c6da83b9..5b403c1f 100644
--- a/tests/unistd/links.c
+++ b/tests/unistd/links.c
@@ -1,8 +1,15 @@
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
+#include <emscripten.h>
int main() {
+ EM_ASM(
+ FS.symlink('../test/../there!', '/link');
+ FS.writeFile('/file', 'test');
+ FS.mkdir('/folder');
+ );
+
char* files[] = {"/link", "/file", "/folder"};
char buffer[256] = {0};
diff --git a/tests/unistd/links.js b/tests/unistd/links.js
deleted file mode 100644
index 5e58a729..00000000
--- a/tests/unistd/links.js
+++ /dev/null
@@ -1,3 +0,0 @@
-FS.createLink('/', 'link', '../test/../there!', true, true);
-FS.createDataFile('/', 'file', 'test', true, true);
-FS.createFolder('/', 'folder', true, true);
diff --git a/tests/unistd/truncate.c b/tests/unistd/truncate.c
index 18920976..b1d9fc96 100644
--- a/tests/unistd/truncate.c
+++ b/tests/unistd/truncate.c
@@ -4,8 +4,15 @@
#include <fcntl.h>
#include <sys/stat.h>
#include <string.h>
+#include <emscripten.h>
int main() {
+ EM_ASM(
+ FS.writeFile('/towrite', 'abcdef');
+ FS.writeFile('/toread', 'abcdef');
+ FS.chmod('/toread', 0444);
+ );
+
struct stat s;
int f = open("/towrite", O_WRONLY);
int f2 = open("/toread", O_RDONLY);
diff --git a/tests/unistd/truncate.js b/tests/unistd/truncate.js
deleted file mode 100644
index 6a4c6868..00000000
--- a/tests/unistd/truncate.js
+++ /dev/null
@@ -1,2 +0,0 @@
-FS.createDataFile('/', 'towrite', 'abcdef', true, true);
-FS.createDataFile('/', 'toread', 'abcdef', true, false);