diff options
-rw-r--r-- | ChangeLog | 38 | ||||
-rw-r--r-- | cmake/Modules/FindOpenAL.cmake | 26 | ||||
-rw-r--r-- | cmake/Platform/Emscripten.cmake | 7 | ||||
-rwxr-xr-x | emcc | 15 | ||||
-rw-r--r-- | src/intertyper.js | 3 | ||||
-rw-r--r-- | src/library.js | 55 | ||||
-rw-r--r-- | src/library_browser.js | 4 | ||||
-rw-r--r-- | src/library_sdl.js | 2 | ||||
-rw-r--r-- | src/preamble.js | 2 | ||||
-rw-r--r-- | src/runtime.js | 12 | ||||
-rw-r--r-- | system/include/emscripten/emscripten.h | 31 | ||||
-rw-r--r-- | tests/freealut/CMakeLists.txt | 55 | ||||
-rwxr-xr-x | tests/runner.py | 24 | ||||
-rw-r--r-- | tests/sockets/test_sockets_echo_server.c | 9 | ||||
-rw-r--r-- | tests/test_browser.py | 115 | ||||
-rw-r--r-- | tests/test_core.py | 12 | ||||
-rw-r--r-- | tests/test_sanity.py | 2 | ||||
-rw-r--r-- | tests/test_sockets.py | 4 | ||||
-rw-r--r-- | third_party/lzma.js/doit.bat | 4 | ||||
-rw-r--r-- | tools/settings_template_readonly.py | 2 | ||||
-rw-r--r-- | tools/split.py | 34 |
21 files changed, 331 insertions, 125 deletions
@@ -7,6 +7,44 @@ To browse or download snapshots of old tagged versions, visit https://github.com Not all changes are documented here. In particular, new features, user-oriented fixes, options, command-line parameters, usage changes, deprecations, significant internal modifications and optimizations etc. generally deserve a mention. To examine the full set of changes between versions, visit the link to full changeset diff at the end of each section. +Current trunk code +------------------ + - To see a list of commits that in the active development branch 'incoming', which have not yet been packaged in a release, see + https://github.com/kripken/emscripten/compare/1.7.5...incoming + +v1.7.5: 11/13/2013 +------------------ + - Fix issues with the built-in C++ function name demangler. + - Full list of changes: https://github.com/kripken/emscripten/compare/1.7.4...1.7.5 + +v1.7.4: 11/12/2013 +------------------ + - Fixed issues with BSD sockets code and SDL joystick implementation. + - Full list of changes: https://github.com/kripken/emscripten/compare/1.7.3...1.7.4 + +v1.7.3: 11/12/2013 +------------------ + - Added support for generating single-precision floating point instructions. + - For more information, read https://blog.mozilla.org/javascript/2013/11/07/efficient-float32-arithmetic-in-javascript/ + - Made GLES2 support library more spec-conformant by throwing fewer exceptions on errors. Be sure to build with -s GL_ASSERTIONS=1, remember to use glGetError() and check the browser console to best detect WebGL rendering errors. + - Converted return value of emscripten_get_now() from float to double, to not lose precision in the function call. + - Added support for joysticks in SDL via the Gamepad API + - Full list of changes: https://github.com/kripken/emscripten/compare/1.7.2...1.7.3 + +v1.7.2: 11/9/2013 +------------------ + - The compiler now always generates a .js file that contains the generated source code even when compiling to a .html file. + - Read https://groups.google.com/forum/#!topic/emscripten-discuss/EuHMwqdSsEs + - Implemented depth+stencil buffer choosing behavior in GLUT, SDL and GLFW. + - Fixed memory leaks generated by glGetString and eglGetString. + - Greatly optimized startup times when virtual filesystems with a large amount of files in them. + - Added some support for SIMD generated by LLVM. + - Fixed some mappings with SDL keyboard codes. + - Added a new command line parameter --no-heap-copy to compiler and file packager that can be used to optimize VFS memory usage at startup. + - Updated libcxx to revision 194185, 2013-11-07. + - Improvements to various library support. + - Full list of changes: https://github.com/kripken/emscripten/compare/1.7.1...1.7.2 + v1.7.1: 10/24/2013 ------------------ - Remove old call to Runtime.warn in file packager code diff --git a/cmake/Modules/FindOpenAL.cmake b/cmake/Modules/FindOpenAL.cmake new file mode 100644 index 00000000..3170966d --- /dev/null +++ b/cmake/Modules/FindOpenAL.cmake @@ -0,0 +1,26 @@ +# Locate OpenAL +# This module defines +# OPENAL_LIBRARY +# OPENAL_FOUND, if false, do not try to link to OpenAL +# OPENAL_INCLUDE_DIR, where to find the headers + +# The implementation is based on the standard FindOpenAL.cmake provided with CMake, +# but customized for targeting Emscripten only. + +if (NOT OPENAL_FOUND) + SET(OPENAL_FOUND TRUE) + + # For Emscripten-compiled apps in the test suite (test_alut), this is expected... + SET(OPENAL_INCLUDE_DIR "${EMSCRIPTEN_ROOT_PATH}/system/include") + # ... but the stock FindOpenAL.cmake would have returned this. + #SET(OPENAL_INCLUDE_DIR "${EMSCRIPTEN_ROOT_PATH}/system/include/AL") + + # No library to link against for OpenAL, this is picked up automatically by library_openal.js, + # but need to report something, or CMake thinks we failed in the search. + SET(OPENAL_LIBRARY "nul") + SET(OPENAL_LIB "") + + set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${EMSCRIPTEN_ROOT_PATH}/system/include" "${EMSCRIPTEN_ROOT_PATH}/system/include/AL") + + MARK_AS_ADVANCED(OPENAL_LIBRARY OPENAL_INCLUDE_DIR) +endif() diff --git a/cmake/Platform/Emscripten.cmake b/cmake/Platform/Emscripten.cmake index e1e54ccf..c30632ca 100644 --- a/cmake/Platform/Emscripten.cmake +++ b/cmake/Platform/Emscripten.cmake @@ -44,9 +44,10 @@ endif() # Normalize, convert Windows backslashes to forward slashes or CMake will crash. get_filename_component(EMSCRIPTEN_ROOT_PATH "${EMSCRIPTEN_ROOT_PATH}" ABSOLUTE) -if ("${CMAKE_MODULE_PATH}" STREQUAL "") - set(CMAKE_MODULE_PATH "${EMSCRIPTEN_ROOT_PATH}/cmake") +if (NOT CMAKE_MODULE_PATH) + set(CMAKE_MODULE_PATH "") endif() +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${EMSCRIPTEN_ROOT_PATH}/cmake/Modules") set(CMAKE_FIND_ROOT_PATH "${EMSCRIPTEN_ROOT_PATH}/cmake") @@ -82,6 +83,8 @@ set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) +set(CMAKE_SYSTEM_INCLUDE_PATH "${EMSCRIPTEN_ROOT_PATH}/system/include") + # We would prefer to specify a standard set of Clang+Emscripten-friendly common convention for suffix files, especially for CMake executable files, # but if these are adjusted, ${CMAKE_ROOT}/Modules/CheckIncludeFile.cmake will fail, since it depends on being able to compile output files with predefined names. #SET(CMAKE_LINK_LIBRARY_SUFFIX "") @@ -50,7 +50,7 @@ emcc can be influenced by a few environment variables: import os, sys, shutil, tempfile, subprocess, shlex, time, re, logging from subprocess import PIPE, STDOUT from tools import shared, jsrun -from tools.shared import Compression, execute, suffix, unsuffixed, unsuffixed_basename +from tools.shared import Compression, execute, suffix, unsuffixed, unsuffixed_basename, WINDOWS from tools.response_file import read_response_file CXX_SUFFIXES = ('.cpp', '.cxx', '.cc') @@ -887,8 +887,17 @@ try: check_bad_eq(newargs[i]) parts = newargs[i+1].split(',') assert len(parts) == 3, '--compression requires specifying native_encoder,js_decoder,js_name - see emcc --help. got: %s' % newargs[i+1] - Compression.encoder = parts[0] - Compression.decoder = parts[1] + def locate(tool): + if WINDOWS: + if os.path.exists(tool+'.exe'): + return tool+'.exe' + if os.path.exists(tool+'.bat'): + return tool+'.bat' + if os.path.exists(tool+'.cmd'): + return tool+'.cmd' + return tool + Compression.encoder = locate(parts[0]) + Compression.decoder = locate(parts[1]) Compression.js_name = parts[2] assert os.path.exists(Compression.encoder), 'native encoder %s does not exist' % Compression.encoder assert os.path.exists(Compression.decoder), 'js decoder %s does not exist' % Compression.decoder diff --git a/src/intertyper.js b/src/intertyper.js index f92a04db..940c677f 100644 --- a/src/intertyper.js +++ b/src/intertyper.js @@ -660,9 +660,10 @@ function intertyper(lines, sidePass, baseLineNums) { var tokensLeft = item.tokens.slice(2); item.ident = eatLLVMIdent(tokensLeft); if (item.ident == 'asm') { + warnOnce('inline JavaScript using asm() has some oddities due to how gcc asm() syntax works. use EM_ASM where possible (see emscripten.h)'); if (ASM_JS) { Types.hasInlineJS = true; - warnOnce('inline JavaScript (asm, EM_ASM) will cause the code to no longer fall in the asm.js subset of JavaScript, which can reduce performance - consider using emscripten_run_script'); + warnOnce('inline JavaScript using asm() will cause the code to no longer fall in the asm.js subset of JavaScript, which can reduce performance - consider using emscripten_run_script'); } assert(TARGET_LE32, 'inline js is only supported in le32'); // Inline assembly is just JavaScript that we paste into the code diff --git a/src/library.js b/src/library.js index 6d821bfc..a5380c3a 100644 --- a/src/library.js +++ b/src/library.js @@ -3193,7 +3193,7 @@ LibraryManager.library = { } } if (!finalBase) finalBase = 10; - start = str; + var start = str; // Get digits. var chr; @@ -6122,7 +6122,7 @@ LibraryManager.library = { clock_gettime: function(clk_id, tp) { // int clock_gettime(clockid_t clk_id, struct timespec *tp); var now; - if (clk_id === {{{ cDefine('CLOCK_REALTIME') }}}) { + if (clk_id === {{{ cDefine('CLOCK_REALTIME') }}}) { now = Date.now(); } else { now = _emscripten_get_now(); @@ -6136,10 +6136,17 @@ LibraryManager.library = { // Nothing. return 0; }, + clock_getres__deps: ['emscripten_get_now_res'], clock_getres: function(clk_id, res) { // int clock_getres(clockid_t clk_id, struct timespec *res); + var nsec; + if (clk_id === {{{ cDefine('CLOCK_REALTIME') }}}) { + nsec = 1000 * 1000; + } else { + nsec = _emscripten_get_now_res(); + } {{{ makeSetValue('res', C_STRUCTS.timespec.tv_sec, '1', 'i32') }}} - {{{ makeSetValue('res', C_STRUCTS.timespec.tv_nsec, '1000 * 1000', 'i32') }}} // resolution is milliseconds + {{{ makeSetValue('res', C_STRUCTS.timespec.tv_nsec, 'nsec', 'i32') }}} // resolution is milliseconds return 0; }, @@ -8230,7 +8237,7 @@ LibraryManager.library = { }, accept__deps: ['$FS', '$SOCKFS', '$DNS', '$ERRNO_CODES', '__setErrNo', '_write_sockaddr'], - accept: function(fd, addrp, addrlen) { + accept: function(fd, addr, addrlen) { var sock = SOCKFS.getSocket(fd); if (!sock) { ___setErrNo(ERRNO_CODES.EBADF); @@ -8238,7 +8245,7 @@ LibraryManager.library = { } try { var newsock = sock.sock_ops.accept(sock); - if (addrp) { + if (addr) { var res = __write_sockaddr(addr, newsock.family, DNS.lookup_name(newsock.daddr), newsock.dport); assert(!res.errno); } @@ -8669,21 +8676,28 @@ LibraryManager.library = { }, emscripten_asm_const: function(code) { - // code is a constant string on the heap, so we can cache these - if (!Runtime.asmConstCache) Runtime.asmConstCache = {}; - var func = Runtime.asmConstCache[code]; - if (func) return func(); - func = Runtime.asmConstCache[code] = eval('(function(){ ' + Pointer_stringify(code) + ' })'); // new Function does not allow upvars in node - return func(); + Runtime.getAsmConst(code, 0)(); + }, + + emscripten_asm_const_int__jsargs: true, + emscripten_asm_const_int: function(code) { + var args = Array.prototype.slice.call(arguments, 1); + return Runtime.getAsmConst(code, args.length).apply(null, args) | 0; + }, + + emscripten_asm_const_double__jsargs: true, + emscripten_asm_const_double: function(code) { + var args = Array.prototype.slice.call(arguments, 1); + return +Runtime.getAsmConst(code, args.length).apply(null, args); }, emscripten_get_now: function() { if (!_emscripten_get_now.actual) { if (ENVIRONMENT_IS_NODE) { - _emscripten_get_now.actual = function _emscripten_get_now_actual() { - var t = process['hrtime'](); - return t[0] * 1e3 + t[1] / 1e6; - } + _emscripten_get_now.actual = function _emscripten_get_now_actual() { + var t = process['hrtime'](); + return t[0] * 1e3 + t[1] / 1e6; + } } else if (typeof dateNow !== 'undefined') { _emscripten_get_now.actual = dateNow; } else if (ENVIRONMENT_IS_WEB && window['performance'] && window['performance']['now']) { @@ -8695,6 +8709,17 @@ LibraryManager.library = { return _emscripten_get_now.actual(); }, + emscripten_get_now_res: function() { // return resolution of get_now, in nanoseconds + if (ENVIRONMENT_IS_NODE) { + return 1; // nanoseconds + } else if (typeof dateNow !== 'undefined' || + (ENVIRONMENT_IS_WEB && window['performance'] && window['performance']['now'])) { + return 1000; // microseconds (1/1000 of a millisecond) + } else { + return 1000*1000; // milliseconds + } + }, + //============================ // emscripten vector ops //============================ diff --git a/src/library_browser.js b/src/library_browser.js index 1883c3be..8444fb73 100644 --- a/src/library_browser.js +++ b/src/library_browser.js @@ -250,7 +250,9 @@ mergeInto(LibraryManager.library, { contextAttributes.preserveDrawingBuffer = true; #endif - ctx = canvas.getContext('experimental-webgl', contextAttributes); + ['experimental-webgl', 'webgl'].some(function(webglId) { + return ctx = canvas.getContext(webglId, contextAttributes); + }); } else { ctx = canvas.getContext('2d'); } diff --git a/src/library_sdl.js b/src/library_sdl.js index f780e15a..eb8eea97 100644 --- a/src/library_sdl.js +++ b/src/library_sdl.js @@ -2675,7 +2675,7 @@ var LibrarySDL = { SDL_WaitThread: function() { throw 'SDL_WaitThread' }, SDL_GetThreadID: function() { throw 'SDL_GetThreadID' }, - SDL_ThreadID: function() { throw 'SDL_ThreadID' }, + SDL_ThreadID: function() { return 0; }, SDL_AllocRW: function() { throw 'SDL_AllocRW: TODO' }, SDL_CondBroadcast: function() { throw 'SDL_CondBroadcast: TODO' }, SDL_CondWaitTimeout: function() { throw 'SDL_CondWaitTimeout: TODO' }, diff --git a/src/preamble.js b/src/preamble.js index 27016c14..ff9200fc 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -246,7 +246,7 @@ var EXITSTATUS = 0; var undef = 0; // tempInt is used for 32-bit signed values or smaller. tempBigInt is used // for 32-bit unsigned values or more than 32 bits. TODO: audit all uses of tempInt -var tempValue, tempInt, tempBigInt, tempInt2, tempBigInt2, tempPair, tempBigIntI, tempBigIntR, tempBigIntS, tempBigIntP, tempBigIntD; +var tempValue, tempInt, tempBigInt, tempInt2, tempBigInt2, tempPair, tempBigIntI, tempBigIntR, tempBigIntS, tempBigIntP, tempBigIntD, tempDouble, tempFloat; #if USE_TYPED_ARRAYS == 2 var tempI64, tempI64b; var tempRet0, tempRet1, tempRet2, tempRet3, tempRet4, tempRet5, tempRet6, tempRet7, tempRet8, tempRet9; diff --git a/src/runtime.js b/src/runtime.js index 786ae021..dedaf5ea 100644 --- a/src/runtime.js +++ b/src/runtime.js @@ -381,6 +381,18 @@ var Runtime = { #endif }, + getAsmConst: function(code, numArgs) { + // code is a constant string on the heap, so we can cache these + if (!Runtime.asmConstCache) Runtime.asmConstCache = {}; + var func = Runtime.asmConstCache[code]; + if (func) return func; + var args = []; + for (var i = 0; i < numArgs; i++) { + args.push(String.fromCharCode(36) + i); // $0, $1 etc + } + return Runtime.asmConstCache[code] = eval('(function(' + args.join(',') + '){ ' + Pointer_stringify(code) + ' })'); // new Function does not allow upvars in node + }, + warnOnce: function(text) { if (!Runtime.warnOnce.shown) Runtime.warnOnce.shown = {}; if (!Runtime.warnOnce.shown[text]) { diff --git a/system/include/emscripten/emscripten.h b/system/include/emscripten/emscripten.h index ac880981..ddcbc43a 100644 --- a/system/include/emscripten/emscripten.h +++ b/system/include/emscripten/emscripten.h @@ -24,17 +24,38 @@ extern "C" { * EM_ASM(window.alert('hai')); * * This also works with asm.js, as it outlines the code (it - * does a function call to reach it). + * does a function call to reach it). It supports newlines, * - * Notes: double-quotes (") are not supported, but you can use + * EM_ASM( + * window.alert('hai')); + * window.alert('bai')); + * ) + * + * Notes: Double-quotes (") are not supported, but you can use * single-quotes (') in js anyhow. * - * you can't access C variables with EM_ASM, use gcc - * inline asm for that, asm("code" : .. etc.) + * You can't access C variables with EM_ASM, nor receive + * a value back. use EM_ASM_INT or EM_ASM_DOUBLE for that */ #define EM_ASM(...) emscripten_asm_const(#__VA_ARGS__) /* + * Input-output versions of EM_ASM. EM_ASM_INT receives arguments of + * either int or double type and returns an int; EM_ASM_DOUBLE + * receives similar arguments (int or double) but returns a double. + * Arguments arrive as $0, $1 etc; output value should be returned: + * + * int x = EM_ASM_INT({ + * console.log('I received: ' + [$0, $1]); + * return $0 + $1; + * }, calc(), otherCalc()); + * + * Note the {,} + */ +#define EM_ASM_INT(code, ...) emscripten_asm_const_int(#code, __VA_ARGS__) +#define EM_ASM_DOUBLE(code, ...) emscripten_asm_const_double(#code, __VA_ARGS__) + +/* * Forces LLVM to not dead-code-eliminate a function. Note that * you still need to use EXPORTED_FUNCTIONS so it stays alive * in JS, e.g. @@ -423,6 +444,8 @@ void emscripten_jcache_printf_(...); /* internal use */ /* Helper API for EM_ASM - do not call this yourself */ void emscripten_asm_const(const char *code); +int emscripten_asm_const_int(const char *code, ...); +double emscripten_asm_const_double(const char *code, ...); #ifdef __cplusplus } diff --git a/tests/freealut/CMakeLists.txt b/tests/freealut/CMakeLists.txt index 640f35bf..c11680cd 100644 --- a/tests/freealut/CMakeLists.txt +++ b/tests/freealut/CMakeLists.txt @@ -72,20 +72,39 @@ ADD_DEFINE("__NO_CTYPE 1") ADD_DEFINITIONS(-DHAVE_CONFIG_H) ADD_DEFINITIONS(-DNDEBUG) -FIND_LIBRARY(OPENAL_LIB NAMES openal openal32 PATHS /usr/lib /usr/local/lib ${OPENAL_LIB_DIR}) -IF(OPENAL_LIB MATCHES "NOTFOUND") - MESSAGE(FATAL_ERROR "OpenAL not installed, cannot build alut - aborting.") -ENDIF(OPENAL_LIB MATCHES "NOTFOUND") - -IF(UNIX) - SET(ADD_LIBS ${ADD_LIBS} m) -ENDIF(UNIX) +if (EMSCRIPTEN) + # Emscripten cannot use FIND_LIBRARY, since that seaches for linkable library files, but Emscripten supports + # OpenAL in core and there are no library files to link against. Instead, use a custom OpenAL package finder + # provided by Emscripten. + FIND_PACKAGE(OpenAL) + + # All the include file checks bloew are no-ops for Emscripten, so for that platform, just define the flags we support. + SET(HAVE_STDINT_H 1) + SET(HAVE_STAT 1) + SET(HAVE_NANOSLEEP 1) + SET(HAVE_TIME_H 1) + ADD_DEFINITIONS(-DHAVE_STDINT_H=1 -DHAVE_STAT=1 -DHAVE_NANOSLEEP=1 -DHAVE_TIME_H=1) + SET(CMAKE_EXECUTABLE_SUFFIX ".bc") +else() + FIND_LIBRARY(OPENAL_LIB NAMES openal openal32 PATHS /usr/lib /usr/local/lib ${OPENAL_LIB_DIR}) + + IF(OPENAL_LIB MATCHES "NOTFOUND") + MESSAGE(FATAL_ERROR "OpenAL not installed, cannot build alut - aborting.") + ENDIF(OPENAL_LIB MATCHES "NOTFOUND") + + IF(UNIX) + SET(ADD_LIBS ${ADD_LIBS} m) + ENDIF(UNIX) +endif() SET(CMAKE_REQUIRED_INCLUDES ${OPENAL_INCLUDE_DIR}) -CHECK_INCLUDE_FILES("AL/alc.h;AL/al.h" AL_HEADERS) -IF(NOT AL_HEADERS) - MESSAGE(FATAL_ERROR "OpenAL header files not found - aborting.") -ENDIF(NOT AL_HEADERS) + +if (NOT EMSCRIPTEN) # Emscripten is a cross-compiler and cannot verify paths of include files with CHECK_INCLUDE_FILES, since that requires building native executables. + CHECK_INCLUDE_FILES("AL/alc.h;AL/al.h" AL_HEADERS) + IF(NOT AL_HEADERS) + MESSAGE(FATAL_ERROR "OpenAL header files not found - aborting.") + ENDIF(NOT AL_HEADERS) +endif() IF(DEFINED OPENAL_INCLUDE_DIR) INCLUDE_DIRECTORIES(${OPENAL_INCLUDE_DIR}) @@ -178,10 +197,18 @@ INSTALL_FILES(/lib/pkgconfig FILES admin/pkgconfig/freealut.pc) IF(BUILD_TESTS) # examples ADD_EXECUTABLE(hello_world examples/hello_world.c) - TARGET_LINK_LIBRARIES(hello_world ${OPENAL_LIB} ${ADD_LIBS} alut) + if (EMSCRIPTEN) + TARGET_LINK_LIBRARIES(hello_world ${OPENAL_LIB} ${ADD_LIBS} alut_static) + else() + TARGET_LINK_LIBRARIES(hello_world ${OPENAL_LIB} ${ADD_LIBS} alut) + endif() ADD_EXECUTABLE(playfile examples/playfile.c) - TARGET_LINK_LIBRARIES(playfile ${OPENAL_LIB} ${ADD_LIBS} alut) + if (EMSCRIPTEN) + TARGET_LINK_LIBRARIES(playfile ${OPENAL_LIB} ${ADD_LIBS} alut_static) + else() + TARGET_LINK_LIBRARIES(playfile ${OPENAL_LIB} ${ADD_LIBS} alut) + endif() SET(TESTS errorstuff diff --git a/tests/runner.py b/tests/runner.py index 7f513635..34435383 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -16,7 +16,7 @@ so you may prefer to use fewer cores here. ''' from subprocess import Popen, PIPE, STDOUT -import os, unittest, tempfile, shutil, time, inspect, sys, math, glob, re, difflib, webbrowser, hashlib, threading, platform, BaseHTTPServer, multiprocessing, functools, stat, string +import os, unittest, tempfile, shutil, time, inspect, sys, math, glob, re, difflib, webbrowser, hashlib, threading, platform, BaseHTTPServer, SimpleHTTPServer, multiprocessing, functools, stat, string # Setup @@ -491,22 +491,14 @@ def harness_server_func(q): httpd.serve_forever() # test runner will kill us def server_func(dir, q): - class TestServerHandler(BaseHTTPServer.BaseHTTPRequestHandler): - def do_GET(s): - if 'report_' in s.path: - q.put(s.path) + class TestServerHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): + def do_GET(self): + if 'report_' in self.path: + q.put(self.path) else: - filename = s.path.split('?')[0][1:] - if os.path.exists(filename): - s.send_response(200) - s.send_header("Content-type", "text/html") - s.end_headers() - s.wfile.write(open(filename).read()) - s.wfile.close() - else: - s.send_response(500) - s.send_header("Content-type", "text/html") - s.end_headers() + # Use SimpleHTTPServer default file serving operation for GET. + SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self) + def log_request(code=0, size=0): # don't log; too noisy pass diff --git a/tests/sockets/test_sockets_echo_server.c b/tests/sockets/test_sockets_echo_server.c index dbc912a6..55ace660 100644 --- a/tests/sockets/test_sockets_echo_server.c +++ b/tests/sockets/test_sockets_echo_server.c @@ -72,7 +72,16 @@ void main_loop(void *arg) { #if !USE_UDP // for TCP sockets, we may need to accept a connection if (FD_ISSET(server.fd, &fdr)) { +#if TEST_ACCEPT_ADDR + // Do an accept with non-NULL addr and addlen parameters. This tests a fix to a bug in the implementation of + // accept which had a parameter "addrp" but used "addr" internally if addrp was set - giving a ReferenceError. + struct sockaddr_in addr = {0}; + addr.sin_family = AF_INET; + socklen_t addrlen = sizeof(addr); + client.fd = accept(server.fd, (struct sockaddr *) &addr, &addrlen); +#else client.fd = accept(server.fd, NULL, NULL); +#endif assert(client.fd != -1); } #endif diff --git a/tests/test_browser.py b/tests/test_browser.py index 65bccb38..128820b3 100644 --- a/tests/test_browser.py +++ b/tests/test_browser.py @@ -1,12 +1,54 @@ -import BaseHTTPServer, multiprocessing, os, shutil, subprocess, unittest +import BaseHTTPServer, multiprocessing, os, shutil, subprocess, unittest, zlib, webbrowser, time, shlex from runner import BrowserCore, path_from_root from tools.shared import * -''' Enable this code to run in another browser than webbrowser detects as default -def run_in_other_browser(url): - execute(['yourbrowser', url]) -webbrowser.open_new = run_in_other_browser -''' +# User can specify an environment variable EMSCRIPTEN_BROWSER to force the browser test suite to +# run using another browser command line than the default system browser. +emscripten_browser = os.environ.get('EMSCRIPTEN_BROWSER') +if emscripten_browser: + cmd = shlex.split(emscripten_browser) + def run_in_other_browser(url): + Popen(cmd + [url]) + webbrowser.open_new = run_in_other_browser + +def test_chunked_synchronous_xhr_server(support_byte_ranges, chunkSize, data, checksum): + class ChunkedServerHandler(BaseHTTPServer.BaseHTTPRequestHandler): + def sendheaders(s, extra=[], length=len(data)): + s.send_response(200) + s.send_header("Content-Length", str(length)) + s.send_header("Access-Control-Allow-Origin", "http://localhost:8888") + s.send_header("Access-Control-Expose-Headers", "Content-Length, Accept-Ranges") + s.send_header("Content-type", "application/octet-stream") + if support_byte_ranges: + s.send_header("Accept-Ranges", "bytes") + for i in extra: + s.send_header(i[0], i[1]) + s.end_headers() + + def do_HEAD(s): + s.sendheaders() + + def do_OPTIONS(s): + s.sendheaders([("Access-Control-Allow-Headers", "Range")], 0) + + def do_GET(s): + if not support_byte_ranges: + s.sendheaders() + s.wfile.write(data) + else: + (start, end) = s.headers.get("range").split("=")[1].split("-") + start = int(start) + end = int(end) + end = min(len(data)-1, end) + length = end-start+1 + s.sendheaders([],length) + s.wfile.write(data[start:end+1]) + s.wfile.close() + + expectedConns = 11 + httpd = BaseHTTPServer.HTTPServer(('localhost', 11111), ChunkedServerHandler) + for i in range(expectedConns+1): + httpd.handle_request() class browser(BrowserCore): @staticmethod @@ -69,7 +111,6 @@ class browser(BrowserCore): cwd=self.get_dir()).communicate() assert os.path.exists(html_file) assert os.path.exists(html_file + '.map') - import webbrowser, time webbrowser.open_new('file://' + html_file) time.sleep(1) print ''' @@ -85,7 +126,10 @@ If manually bisecting: cwd = os.getcwd() try: os.chdir(path_from_root('third_party', 'lzma.js')) - Popen(['sh', './doit.sh']).communicate() + if WINDOWS and Building.which('mingw32-make'): # On Windows prefer using MinGW make if it exists, otherwise fall back to hoping we have cygwin make. + Popen(['doit.bat']).communicate() + else: + Popen(['sh', './doit.sh']).communicate() finally: os.chdir(cwd) @@ -185,7 +229,7 @@ If manually bisecting: self.reftest(path_from_root('tests', 'htmltest.png')) output = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world_sdl.cpp'), '-o', 'something.js', '-g', '--split', '100', '--pre-js', 'reftest.js']).communicate() assert os.path.exists(os.path.join(self.get_dir(), 'something.js')), 'must be main js file' - assert os.path.exists(self.get_dir() + '/something/' + path_from_root('tests', 'hello_world_sdl.cpp.js')), 'must be functions js file' + assert os.path.exists(os.path.join(self.get_dir(), 'something', 'hello_world_sdl.cpp.js')), 'must be functions js file' assert os.path.exists(os.path.join(self.get_dir(), 'something.include.html')), 'must be js include file' open(os.path.join(self.get_dir(), 'something.html'), 'w').write(''' @@ -1159,8 +1203,14 @@ keydown(100);keyup(100); // trigger the end Popen([PYTHON, EMCC, '-O2', os.path.join(self.get_dir(), 'test_egl_width_height.c'), '-o', 'page.html']).communicate() self.run_browser('page.html', 'Should print "(300, 150)" -- the size of the canvas in pixels', '/report_result?1') + def get_freealut_library(self): + if WINDOWS and Building.which('cmake'): + return self.get_library('freealut', os.path.join('hello_world.bc'), configure=['cmake', '.'], configure_args=['-DBUILD_TESTS=ON']) + else: + return self.get_library('freealut', os.path.join('examples', '.libs', 'hello_world.bc'), make_args=['EXEEXT=.bc']) + def test_freealut(self): - programs = self.get_library('freealut', os.path.join('examples', '.libs', 'hello_world.bc'), make_args=['EXEEXT=.bc']) + programs = self.get_freealut_library() for program in programs: assert os.path.exists(program) Popen([PYTHON, EMCC, '-O2', program, '-o', 'page.html']).communicate() @@ -1256,51 +1306,16 @@ keydown(100);keyup(100); // trigger the end chunkSize = 1024 data = os.urandom(10*chunkSize+1) # 10 full chunks and one 1 byte chunk - expectedConns = 11 - import zlib checksum = zlib.adler32(data) - def chunked_server(support_byte_ranges): - class ChunkedServerHandler(BaseHTTPServer.BaseHTTPRequestHandler): - def sendheaders(s, extra=[], length=len(data)): - s.send_response(200) - s.send_header("Content-Length", str(length)) - s.send_header("Access-Control-Allow-Origin", "http://localhost:8888") - s.send_header("Access-Control-Expose-Headers", "Content-Length, Accept-Ranges") - s.send_header("Content-type", "application/octet-stream") - if support_byte_ranges: - s.send_header("Accept-Ranges", "bytes") - for i in extra: - s.send_header(i[0], i[1]) - s.end_headers() - - def do_HEAD(s): - s.sendheaders() - - def do_OPTIONS(s): - s.sendheaders([("Access-Control-Allow-Headers", "Range")], 0) - - def do_GET(s): - if not support_byte_ranges: - s.sendheaders() - s.wfile.write(data) - else: - (start, end) = s.headers.get("range").split("=")[1].split("-") - start = int(start) - end = int(end) - end = min(len(data)-1, end) - length = end-start+1 - s.sendheaders([],length) - s.wfile.write(data[start:end+1]) - s.wfile.close() - httpd = BaseHTTPServer.HTTPServer(('localhost', 11111), ChunkedServerHandler) - for i in range(expectedConns+1): - httpd.handle_request() - - server = multiprocessing.Process(target=chunked_server, args=(True,)) + server = multiprocessing.Process(target=test_chunked_synchronous_xhr_server, args=(True,chunkSize,data,checksum,)) server.start() self.run_browser(main, 'Chunked binary synchronous XHR in Web Workers!', '/report_result?' + str(checksum)) server.terminate() + # Avoid race condition on cleanup, wait a bit so that processes have released file locks so that test tearDown won't + # attempt to rmdir() files in use. + if WINDOWS: + time.sleep(2) def test_glgears(self): self.btest('hello_world_gles.c', reference='gears.png', reference_slack=1, diff --git a/tests/test_core.py b/tests/test_core.py index d7b6cf53..67e316e4 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -3970,7 +3970,7 @@ def process(filename): #include <stdio.h> #include <emscripten.h> - int main() { + int main(int argc, char **argv) { EM_ASM(Module.print('hello dere1')); EM_ASM( Module.print('hello dere2'); @@ -3981,11 +3981,19 @@ def process(filename): Module.print('hello dere' + 4); ); } + int sum = 0; + for (int i = 0; i < argc*3; i++) { + sum += EM_ASM_INT({ + Module.print('i: ' + [$0, ($1).toFixed(2)]); + return $0*2; + }, i, double(i)/12); + } + printf("sum: %d\n", sum); return 0; } ''' - self.do_run(src, 'hello dere1\nhello dere2\nhello dere3\nhello dere4\nhello dere3\nhello dere4\nhello dere3\nhello dere4\n') + self.do_run(src, 'hello dere1\nhello dere2\nhello dere3\nhello dere4\nhello dere3\nhello dere4\nhello dere3\nhello dere4\ni: 0,0.00\ni: 1,0.08\ni: 2,0.17\nsum: 6\n') def test_memorygrowth(self): if Settings.USE_TYPED_ARRAYS == 0: return self.skip('memory growth is only supported with typed arrays') |