diff --git a/AUTHORS b/AUTHORS index 30737b25bc532..d6f3c1417f766 100644 --- a/AUTHORS +++ b/AUTHORS @@ -224,3 +224,5 @@ a license to everyone to use it as detailed in LICENSE.) * Josh Peterson <petersonjm1@gmail.com> * eska <eska@eska.me> * Nate Burr <nate.oo@gmail.com> +* Paul "TBBle" Hampson <Paul.Hampson@Pobox.com> +* Andreas Plesch <andreasplesch@gmail.com> diff --git a/emcc.py b/emcc.py index fcc3ab90fe10e..70a82eebe65f2 100755 --- a/emcc.py +++ b/emcc.py @@ -968,6 +968,10 @@ def check(input_file): assert not use_closure_compiler, 'cannot use closure compiler on shared modules' assert not shared.Settings.ALLOW_MEMORY_GROWTH, 'memory growth is not supported with shared modules yet' + if shared.Settings.ALLOW_MEMORY_GROWTH: + logging.warning('not all asm.js optimizations are possible with ALLOW_MEMORY_GROWTH, disabling those') + shared.Settings.ASM_JS = 2 # memory growth does not validate as asm.js http://discourse.wicg.io/t/request-for-comments-switching-resizing-heaps-in-asm-js/641/23 + if shared.Settings.WASM: assert not shared.Settings.ALLOW_MEMORY_GROWTH, 'memory growth is not supported with WASM=1' diff --git a/emscripten-version.txt b/emscripten-version.txt index bec44b5440eb2..9c6893ff4602e 100644 --- a/emscripten-version.txt +++ b/emscripten-version.txt @@ -1,2 +1,2 @@ -"1.35.17" +"1.35.18" diff --git a/site/source/docs/building_from_source/building_emscripten_from_source_using_the_sdk.rst b/site/source/docs/building_from_source/building_emscripten_from_source_using_the_sdk.rst index c7093d3f0dd36..e191230be6d79 100644 --- a/site/source/docs/building_from_source/building_emscripten_from_source_using_the_sdk.rst +++ b/site/source/docs/building_from_source/building_emscripten_from_source_using_the_sdk.rst @@ -139,21 +139,18 @@ After installing the main repositories: :: - # From your emsdk "root" (where emsdk is installed). Navigate to the LLVM clone: - cd clang/fastcomp/src - - # Add a git remote link to your LLVM repository fork, then fetch changes - git remote add myremote https://github.com/mygituseraccount/emscripten-fastcomp.git - git fetch myremote + # From your emsdk "root" (where emsdk is installed). Navigate to the Emscripten clone: + cd emscripten/incoming - # Add a git remote link to your Clang repository fork. - git remote add myclangremote https://github.com/mygituseraccount/emscripten-fastcomp-clang.git + # Add a git remote link to your Emscripten repository fork + git remote add myremote https://github.com/mygituseraccount/emscripten.git + # Fetch the changes in the remote. - git fetch myllvmremote + git fetch myremote # Checkout the code in your LLVM fork to replace the original repository code - git checkout -b myllvmremote --track myremote/incoming + git checkout -b myremote --track myremote/incoming You can switch back and forth between remotes (the original sources and your fork, or the incoming and master branches) using the ``git checkout`` command. You can switch between the SDK and source using the ``./emsdk activate <target>`` command. diff --git a/site/source/docs/getting_started/test-suite.rst b/site/source/docs/getting_started/test-suite.rst index 84fcb159a1f11..d33f1b6a12987 100644 --- a/site/source/docs/getting_started/test-suite.rst +++ b/site/source/docs/getting_started/test-suite.rst @@ -23,8 +23,8 @@ The whole core test suite can be run using the script `tests/runner.py <https:// - This may take several hours. - :term:`Node.js` cannot run all of the tests in the suite; if you need to run them all, you should get a recent trunk version of the `SpiderMonkey <https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Introduction_to_the_JavaScript_shell>`_ shell. On Windows you can install and activate *SpiderMonkey* using the :ref:`emsdk`. -Running a specific test -======================= +Running specific tests +====================== You can also use *runner.py* to run different parts of the test suite, or individual tests. For example, you would run test named ``test_hello_world`` as shown: @@ -34,6 +34,22 @@ You can also use *runner.py* to run different parts of the test suite, or indivi Tests in the "core" test suite (``tests/test_core.py``) can be run as above. Other tests may need a prefix, for example ``browser.test_cubegeom`` for a test in ``tests/test_browser.py``. You can also specify an optional prefix for tests in core, to run them with extra options, for example ``asm2.test_hello_world`` will run ``hello_world`` using ``asm2`` opts (basically ``-O2``). See more examples in :ref:`emscripten-test-suite-list-of-tests`. +It is possible to pass a wildcard to match multiple tests by name. For example, the commands + +.. code-block:: bash + + python tests/runner.py ALL.test_simd_* ALL.test_sse* + +would run all the SIMD related tests in the suite. + +Individual tests can be skipped, so + +.. code-block:: bash + + python tests/runner.py browser.test_pthread_* skip:browser.test_pthread_gcc_atomic_fetch_and_op + +would run all the multithreading tests except the one test ``browser.test_pthread_gcc_atomic_fetch_and_op``. + Running a bunch of random tests =============================== diff --git a/src/compiler.js b/src/compiler.js index 159930f5e72ed..7598caf9a1e4b 100644 --- a/src/compiler.js +++ b/src/compiler.js @@ -123,6 +123,15 @@ if (typeof print === 'undefined') { DEBUG_MEMORY = false; +// Polyfilling + +if (!String.prototype.startsWith) { + String.prototype.startsWith = function(searchString, position) { + position = position || 0; + return this.indexOf(searchString, position) === position; + }; +} + // Basic utilities load('utility.js'); diff --git a/src/jsifier.js b/src/jsifier.js index af688007c10c9..21b2cbc084548 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -102,6 +102,14 @@ function JSify(data, functionsOnly) { // functionStub function functionStubHandler(item) { + // special logic + if (item.ident.startsWith('___cxa_find_matching_catch_')) { + var num = +item.ident.split('_').slice(-1)[0]; + LibraryManager.library[item.ident.substr(1)] = function() { + return ___cxa_find_matching_catch.apply(null, arguments); + }; + } + // note the signature if (item.returnType && item.params) { functionStubSigs[item.ident] = Functions.getSignature(item.returnType.text, item.params.map(function(arg) { return arg.type }), false); diff --git a/src/library.js b/src/library.js index 2762ea51b19a7..94be0443131f3 100644 --- a/src/library.js +++ b/src/library.js @@ -1300,6 +1300,17 @@ LibraryManager.library = { llvm_dbg_declare__inline: function() { throw 'llvm_debug_declare' }, // avoid warning + llvm_bitreverse_i32__asm: true, + llvm_bitreverse_i32__sig: 'ii', + llvm_bitreverse_i32: function(x) { + x = x|0; + x = ((x & 0xaaaaaaaa) >>> 1) | ((x & 0x55555555) << 1); + x = ((x & 0xcccccccc) >>> 2) | ((x & 0x33333333) << 2); + x = ((x & 0xf0f0f0f0) >>> 4) | ((x & 0x0f0f0f0f) << 4); + x = ((x & 0xff00ff00) >>> 8) | ((x & 0x00ff00ff) << 8); + return (x >>> 16) | (x << 16); + }, + // llvm-nacl llvm_nacl_atomic_store_i32__inline: true, @@ -1643,10 +1654,10 @@ LibraryManager.library = { var winterOffset = start.getTimezoneOffset(); var dstOffset = Math.min(winterOffset, summerOffset); // DST is in December in South if (dst < 0) { - {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_isdst, 'Number(winterOffset != guessedOffset)', 'i32') }}}; - } else if ((dst > 0) != (winterOffset != guessedOffset)) { - var summerOffset = new Date(date.getFullYear(), 6, 1).getTimezoneOffset(); - var trueOffset = dst > 0 ? summerOffset : winterOffset; + {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_isdst, 'Number(dstOffset == guessedOffset)', 'i32') }}}; + } else if ((dst > 0) != (dstOffset == guessedOffset)) { + var nonDstOffset = Math.max(winterOffset, summerOffset); + var trueOffset = dst > 0 ? dstOffset : nonDstOffset; // Don't try setMinutes(date.getMinutes() + ...) -- it's messed up. date.setTime(date.getTime() + (trueOffset - guessedOffset)*60000); } @@ -2026,7 +2037,10 @@ LibraryManager.library = { return leadingNulls(date.tm_hour, 2); }, '%I': function(date) { - return leadingNulls(date.tm_hour < 13 ? date.tm_hour : date.tm_hour-12, 2); + var twelveHour = date.tm_hour; + if (twelveHour == 0) twelveHour = 12; + else if (twelveHour > 12) twelveHour -= 12; + return leadingNulls(twelveHour, 2); }, '%j': function(date) { // Day of the year (001-366) @@ -2042,7 +2056,7 @@ LibraryManager.library = { return '\n'; }, '%p': function(date) { - if (date.tm_hour > 0 && date.tm_hour < 13) { + if (date.tm_hour >= 0 && date.tm_hour < 12) { return 'AM'; } else { return 'PM'; @@ -3183,11 +3197,11 @@ LibraryManager.library = { lookup_name: function (name) { // If the name is already a valid ipv4 / ipv6 address, don't generate a fake one. var res = __inet_pton4_raw(name); - if (res) { + if (res !== null) { return name; } res = __inet_pton6_raw(name); - if (res) { + if (res !== null) { return name; } diff --git a/src/library_lz4.js b/src/library_lz4.js index 1c46c4601886d..b304d35a0f62e 100644 --- a/src/library_lz4.js +++ b/src/library_lz4.js @@ -25,7 +25,6 @@ mergeInto(LibraryManager.library, { compressedData.cachedOffset + (i+1)*LZ4.CHUNK_SIZE); assert(compressedData.cachedChunks[i].length === LZ4.CHUNK_SIZE); } - console.log('loading package'); pack['metadata'].files.forEach(function(file) { var dir = PATH.dirname(file.filename); var name = PATH.basename(file.filename); diff --git a/src/library_pthread.js b/src/library_pthread.js index 0a7c2b0483a29..c287bd1214d8d 100644 --- a/src/library_pthread.js +++ b/src/library_pthread.js @@ -1,6 +1,6 @@ var LibraryPThread = { $PThread__postset: 'if (!ENVIRONMENT_IS_PTHREAD) PThread.initMainThreadBlock();', - $PThread__deps: ['$PROCINFO'], + $PThread__deps: ['$PROCINFO', '_register_pthread_ptr'], $PThread: { MAIN_THREAD_ID: 1, // A special constant that identifies the main JS thread ID. mainThreadInfo: { @@ -17,6 +17,8 @@ var LibraryPThread = { initMainThreadBlock: function() { if (ENVIRONMENT_IS_PTHREAD) return undefined; PThread.mainThreadBlock = allocate({{{ C_STRUCTS.pthread.__size__ }}}, "i32*", ALLOC_STATIC); + __register_pthread_ptr(PThread.mainThreadBlock, /*isMainBrowserThread=*/!ENVIRONMENT_IS_WORKER, /*isMainRuntimeThread=*/1); // Pass the thread address inside the asm.js scope to store it for fast access that avoids the need for a FFI out. + for (var i = 0; i < {{{ C_STRUCTS.pthread.__size__ }}}/4; ++i) HEAPU32[PThread.mainThreadBlock/4+i] = 0; // The pthread struct has a field that points to itself - this is used as a magic ID to detect whether the pthread_t @@ -144,6 +146,7 @@ var LibraryPThread = { PThread.runExitHandlers(); _emscripten_futex_wake(tb + {{{ C_STRUCTS.pthread.threadStatus }}}, {{{ cDefine('INT_MAX') }}}); + __register_pthread_ptr(0, 0, 0); // Unregister the thread block also inside the asm.js scope. threadInfoStruct = 0; if (ENVIRONMENT_IS_PTHREAD) { postMessage({ cmd: 'exit' }); @@ -157,6 +160,7 @@ var LibraryPThread = { Atomics.store(HEAPU32, (threadInfoStruct + {{{ C_STRUCTS.pthread.threadStatus }}} ) >> 2, 1); // Mark the thread as no longer running. _emscripten_futex_wake(threadInfoStruct + {{{ C_STRUCTS.pthread.threadStatus }}}, {{{ cDefine('INT_MAX') }}}); // wake all threads threadInfoStruct = selfThreadId = 0; // Not hosting a pthread anymore in this worker, reset the info structures to null. + __register_pthread_ptr(0, 0, 0); // Unregister the thread block also inside the asm.js scope. postMessage({ cmd: 'cancelDone' }); }, @@ -607,18 +611,38 @@ var LibraryPThread = { else PThread.threadExit(status); }, + _pthread_ptr: 0, + _pthread_is_main_runtime_thread: 0, + _pthread_is_main_browser_thread: 0, + + _register_pthread_ptr__asm: true, + _register_pthread_ptr__deps: ['_pthread_ptr', '_pthread_is_main_runtime_thread', '_pthread_is_main_browser_thread'], + _register_pthread_ptr: function(pthreadPtr, isMainBrowserThread, isMainRuntimeThread) { + pthreadPtr = pthreadPtr|0; + isMainBrowserThread = isMainBrowserThread|0; + isMainRuntimeThread = isMainRuntimeThread|0; + __pthread_ptr = pthreadPtr; + __pthread_is_main_browser_thread = isMainBrowserThread; + __pthread_is_main_runtime_thread = isMainRuntimeThread; + }, + // Public pthread_self() function which returns a unique ID for the thread. + pthread_self__asm: true, + pthread_self__deps: ['_pthread_ptr'], pthread_self: function() { - if (ENVIRONMENT_IS_PTHREAD) return threadInfoStruct; - return PThread.mainThreadBlock; // Main JS thread. + return __pthread_ptr|0; }, + emscripten_is_main_runtime_thread__asm: true, + emscripten_is_main_runtime_thread__deps: ['_pthread_is_main_runtime_thread'], emscripten_is_main_runtime_thread: function() { - return !ENVIRONMENT_IS_PTHREAD; + return __pthread_is_main_runtime_thread|0; // Semantically the same as testing "!ENVIRONMENT_IS_PTHREAD" outside the asm.js scope }, + emscripten_is_main_browser_thread__asm: true, + emscripten_is_main_browser_thread__deps: ['_pthread_is_main_browser_thread'], emscripten_is_main_browser_thread: function() { - return !ENVIRONMENT_IS_WORKER; + return __pthread_is_main_browser_thread|0; // Semantically the same as testing "!ENVIRONMENT_IS_WORKER" outside the asm.js scope }, pthread_getschedparam: function(thread, policy, schedparam) { diff --git a/src/library_syscall.js b/src/library_syscall.js index 85ee5d9afa40b..bf11cdb2020c1 100644 --- a/src/library_syscall.js +++ b/src/library_syscall.js @@ -448,7 +448,17 @@ var SyscallsLibrary = { } case 6: { // getsockname var sock = SYSCALLS.getSocketFromFD(), addr = SYSCALLS.get(), addrlen = SYSCALLS.get(); - var res = __write_sockaddr(addr, sock.family, DNS.lookup_name(sock.daddr || '0.0.0.0'), sock.dport); + // TODO: sock.saddr should never be undefined, see TODO in websocket_sock_ops.getname + var res = __write_sockaddr(addr, sock.family, DNS.lookup_name(sock.saddr || '0.0.0.0'), sock.sport); + assert(!res.errno); + return 0; + } + case 7: { // getpeername + var sock = SYSCALLS.getSocketFromFD(), addr = SYSCALLS.get(), addrlen = SYSCALLS.get(); + if (!sock.daddr) { + return -ERRNO_CODES.ENOTCONN; // The socket is not connected. + } + var res = __write_sockaddr(addr, sock.family, DNS.lookup_name(sock.daddr), sock.dport); assert(!res.errno); return 0; } diff --git a/src/pthread-main.js b/src/pthread-main.js index 3cd43c180d3bd..b3a68e1fbc20b 100644 --- a/src/pthread-main.js +++ b/src/pthread-main.js @@ -51,6 +51,7 @@ this.onmessage = function(e) { postMessage({ cmd: 'loaded' }); } else if (e.data.cmd === 'run') { // This worker was idle, and now should start executing its pthread entry point. threadInfoStruct = e.data.threadInfoStruct; + __register_pthread_ptr(threadInfoStruct, /*isMainBrowserThread=*/0, /*isMainRuntimeThread=*/0); // Pass the thread address inside the asm.js scope to store it for fast access that avoids the need for a FFI out. assert(threadInfoStruct); selfThreadId = e.data.selfThreadId; assert(selfThreadId); diff --git a/src/settings.js b/src/settings.js index fc8e417a54a4e..af3a3f2f5801c 100644 --- a/src/settings.js +++ b/src/settings.js @@ -514,6 +514,9 @@ var MODULARIZE = 0; // By default we emit all code in a straightforward way into // // var instance = EXPORT_NAME({ option: value, ... }); // + // Note the parentheses - we are calling EXPORT_NAME in order to instantiate + // the module. (This allows, in particular, for you to create multiple + // instantiations, etc.) var BENCHMARK = 0; // If 1, will just time how long main() takes to execute, and not // print out anything at all whatsoever. This is useful for benchmarking. diff --git a/tests/cases/aliasbitcast2_noasm.ll b/tests/cases/aliasbitcast2_noasm.ll deleted file mode 100644 index 3cf73e9c75994..0000000000000 --- a/tests/cases/aliasbitcast2_noasm.ll +++ /dev/null @@ -1,27 +0,0 @@ -; ModuleID = 'tests/hello_world.bc' -target datalayout = "e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-p:32:32:32-v128:32:128-n32-S128" -target triple = "asmjs-unknown-emscripten" - -@.str = private constant [14 x i8] c"hello, world!\00", align 1 ; [#uses=1] - -@othername = alias bitcast (void ()* @original to void (i32)*) ; [#uses=1] - -; [#uses=2] -define void @original() { -entry: - %0 = call i32 bitcast (i32 (i8*)* @puts to i32 (i32*)*)(i32* bitcast (i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str, i32 0, i32 0) to i32*)) ; [#uses=0] - br label %return - -return: ; preds = %entry - ret void -} - -; [#uses=1] -declare i32 @puts(i8*) - -; [#uses=0] -define i32 @main() { -entry: - call void @othername(i32 5) - ret i32 0 -} diff --git a/tests/cases/aliasbitcast3_noasm.ll b/tests/cases/aliasbitcast3_noasm.ll deleted file mode 100644 index b1d88c3dc600d..0000000000000 --- a/tests/cases/aliasbitcast3_noasm.ll +++ /dev/null @@ -1,29 +0,0 @@ -; ModuleID = 'tests/hello_world.bc' -target datalayout = "e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-p:32:32:32-v128:32:128-n32-S128" -target triple = "asmjs-unknown-emscripten" - -@.str = private constant [14 x i8] c"hello, world!\00", align 1 ; [#uses=1] - -@thriceremoved = alias bitcast (void ()* @twiceremoved to void (i32)*) ; [#uses=1] -@othername = alias bitcast (void ()* @original to void (i32)*) ; [#uses=1] -@twiceremoved = alias bitcast (void (i32)* @othername to void ()*) ; [#uses=1] - -; [#uses=2] -define void @original() { -entry: - %0 = call i32 bitcast (i32 (i8*)* @puts to i32 (i32*)*)(i32* bitcast (i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str, i32 0, i32 0) to i32*)) ; [#uses=0] - br label %return - -return: ; preds = %entry - ret void -} - -; [#uses=1] -declare i32 @puts(i8*) - -; [#uses=0] -define i32 @main() { -entry: - call void @thriceremoved(i32 0) - ret i32 0 -} diff --git a/tests/cases/aliasbitcastdollar_noasm.ll b/tests/cases/aliasbitcastdollar_noasm.ll deleted file mode 100644 index 99ab490ecbd51..0000000000000 --- a/tests/cases/aliasbitcastdollar_noasm.ll +++ /dev/null @@ -1,27 +0,0 @@ -; ModuleID = 'tests/hello_world.bc' -target datalayout = "e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-p:32:32:32-v128:32:128-n32-S128" -target triple = "asmjs-unknown-emscripten" - -@.str = private constant [14 x i8] c"hello, world!\00", align 1 ; [#uses=1] - -@"other$name" = alias bitcast (void ()* @original to void (i32)*) ; [#uses=1] - -; [#uses=2] -define void @original() { -entry: - %0 = call i32 bitcast (i32 (i8*)* @puts to i32 (i32*)*)(i32* bitcast (i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str, i32 0, i32 0) to i32*)) ; [#uses=0] - br label %return - -return: ; preds = %entry - ret void -} - -; [#uses=1] -declare i32 @puts(i8*) - -; [#uses=0] -define i32 @main() { -entry: - call void @"other$name"(i32 5) - ret i32 0 -} diff --git a/tests/cases/llvm_bitreverse.ll b/tests/cases/llvm_bitreverse.ll new file mode 100644 index 0000000000000..28fa51e823ce5 --- /dev/null +++ b/tests/cases/llvm_bitreverse.ll @@ -0,0 +1,26 @@ +; ModuleID = 'tests/hello_world.bc' +target datalayout = "e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-p:32:32:32-v128:32:128-n32-S128" +target triple = "asmjs-unknown-emscripten" + +@.str2 = private constant [6 x i8] c"*%d*\0A\00", align 1 ; [#uses=1] + +declare i32 @printf(i8* noalias, ...) nounwind +declare i32 @llvm.bitreverse.i32(i32) #1 + +define i32 @main() { +entry: + %a = call i32 @llvm.bitreverse.i32(i32 1) + call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str2, i32 0, i32 0), i32 %a) + %b = call i32 @llvm.bitreverse.i32(i32 -2147483648) + call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str2, i32 0, i32 0), i32 %b) + %c = call i32 @llvm.bitreverse.i32(i32 -1) + call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str2, i32 0, i32 0), i32 %c) + %d = call i32 @llvm.bitreverse.i32(i32 0) + call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str2, i32 0, i32 0), i32 %d) + %e = call i32 @llvm.bitreverse.i32(i32 275600565) + call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str2, i32 0, i32 0), i32 %e) + %f = call i32 @llvm.bitreverse.i32(i32 -8) + call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str2, i32 0, i32 0), i32 %f) + + ret i32 0 +} diff --git a/tests/cases/llvm_bitreverse.txt b/tests/cases/llvm_bitreverse.txt new file mode 100644 index 0000000000000..29f95bfb37a5d --- /dev/null +++ b/tests/cases/llvm_bitreverse.txt @@ -0,0 +1,6 @@ +*-2147483648* +*1* +*-1* +*0* +*-1389709816* +*536870911* \ No newline at end of file diff --git a/tests/cases/unannotated__noasm.ll b/tests/cases/unannotated__noasm.ll deleted file mode 100644 index 7acafc6c0a6a3..0000000000000 --- a/tests/cases/unannotated__noasm.ll +++ /dev/null @@ -1,20 +0,0 @@ -; ModuleID = '/tmp/tmpe4Pk1F/a.out.bc' -target datalayout = "e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-p:32:32:32-v128:32:128-n32-S128" -target triple = "asmjs-unknown-emscripten" - -@.str = private unnamed_addr constant [6 x i8] c"test\0A\00" - -declare hidden zeroext i1 @_OptionParser(i8*, i8) ; separate test: check that we can compile this line (zeroext confused us) - -define i32 @main() nounwind { - %1 = alloca i32, align 4 - store i32 0, i32* %1 - %2 = call i32 @llvm.expect.i32(i32 0, i32 1) - %3 = call i32 @puts(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str, i32 0, i32 0)) - ret i32 0 -} - -declare i32 @puts(i8*) - -declare i32 @llvm.expect.i32(i32, i32) - diff --git a/tests/cases/unannotated__noasm.txt b/tests/cases/unannotated__noasm.txt deleted file mode 100644 index 9daeafb9864cf..0000000000000 --- a/tests/cases/unannotated__noasm.txt +++ /dev/null @@ -1 +0,0 @@ -test diff --git a/tests/core/test_strcmp_uni.in b/tests/core/test_strcmp_uni.in index fd16490d72147..8e8c1897fce2b 100644 --- a/tests/core/test_strcmp_uni.in +++ b/tests/core/test_strcmp_uni.in @@ -6,6 +6,8 @@ int main() { char *word = (char*)"WORD"; \ char wordEntry[2] = {-61, -126}; /* "Â"; */ \ int cmp = func(word, wordEntry, 2); \ + if (cmp < 0) cmp = -1; \ + else if (cmp > 0) cmp = 1; \ printf("Compare value " #func " is %d\n", cmp); \ } TEST(strncmp); diff --git a/tests/core/test_strcmp_uni.out b/tests/core/test_strcmp_uni.out index ebfe2c8e1f61f..58e237d768713 100644 --- a/tests/core/test_strcmp_uni.out +++ b/tests/core/test_strcmp_uni.out @@ -1,3 +1,3 @@ -Compare value strncmp is -108 -Compare value strncasecmp is -76 -Compare value memcmp is -108 +Compare value strncmp is -1 +Compare value strncasecmp is -1 +Compare value memcmp is -1 diff --git a/tests/core/test_strftime.in b/tests/core/test_strftime.in index af616dca5989a..020fece3cb39f 100644 --- a/tests/core/test_strftime.in +++ b/tests/core/test_strftime.in @@ -148,4 +148,27 @@ int main() { test((size == 5) && strchr(s, ahead ? '+' : '-'), "strftime zone test #3", s); size = strftime(s, 50, "%Z", &tm); test(strcmp(s, tzname[tm.tm_isdst]) == 0, "strftime zone test #4", s); + + // AM/PM + tm.tm_sec = 0; + tm.tm_min = 0; + + tm.tm_hour = 0; + size = strftime(s, 10, "%I %p", &tm); + test(!cmp(s, "12 AM"), "strftime test #32", s); + + tm.tm_hour = 12; + size = strftime(s, 10, "%I %p", &tm); + test(!cmp(s, "12 PM"), "strftime test #33", s); + + tm.tm_min = 1; + + tm.tm_hour = 0; + size = strftime(s, 10, "%I %M %p", &tm); + test(!cmp(s, "12 01 AM"), "strftime test #34", s); + + tm.tm_hour = 12; + size = strftime(s, 10, "%I %M %p", &tm); + test(!cmp(s, "12 01 PM"), "strftime test #35", s); + } diff --git a/tests/core/test_strftime.out b/tests/core/test_strftime.out index 91aab81d319fb..1ff67172a50c4 100644 --- a/tests/core/test_strftime.out +++ b/tests/core/test_strftime.out @@ -30,4 +30,8 @@ strftime test #29: 1 strftime zone test #1: 1 strftime zone test #2: 1 strftime zone test #3: 1 -strftime zone test #4: 1 \ No newline at end of file +strftime zone test #4: 1 +strftime test #32: 1 +strftime test #33: 1 +strftime test #34: 1 +strftime test #35: 1 diff --git a/tests/runner.py b/tests/runner.py index 5412e049fe8a4..59775f4b32e23 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -9,7 +9,7 @@ from subprocess import Popen, PIPE, STDOUT -import os, unittest, tempfile, shutil, time, inspect, sys, math, glob, re, difflib, webbrowser, hashlib, threading, platform, BaseHTTPServer, SimpleHTTPServer, multiprocessing, functools, stat, string, random, operator +import os, unittest, tempfile, shutil, time, inspect, sys, math, glob, re, difflib, webbrowser, hashlib, threading, platform, BaseHTTPServer, SimpleHTTPServer, multiprocessing, functools, stat, string, random, operator, fnmatch from urllib import unquote # Setup @@ -68,6 +68,21 @@ def path_from_root(*pathelems): python tests/runner.py random50 +An individual test can be skipped by passing the "skip:" prefix. E.g. + + python tests/runner.py other skip:other.test_cmake + +Passing a wildcard allows choosing a subset of tests in a suite, e.g. + + python tests/runner.py browser.test_pthread_* + +will run all the pthreads related tests. Wildcards can also be passed in skip, +so + + python tests/runner.py browser skip:browser.test_pthread_* + +will run the whole browser suite except for all the pthread tests in it. + Debugging: You can run EM_SAVE_DIR=1 python tests/runner.py ALL.test_hello_world @@ -911,6 +926,33 @@ def get_bullet_library(runner_core, use_cmake): new_args += [arg] sys.argv = new_args + # Create a list of all known tests so that we can choose from them based on a wildcard search + all_tests = [] + suites = test_modes + ['other', 'browser', 'sanity', 'sockets', 'interactive'] + for m in modules: + for s in suites: + if hasattr(m, s): + tests = filter(lambda t: t.startswith('test_'), dir(getattr(m, s))) + all_tests += map(lambda t: s + '.' + t, tests) + + # Process wildcards, e.g. "browser.test_pthread_*" should expand to list all pthread tests + new_args = [sys.argv[0]] + for i in range(1, len(sys.argv)): + arg = sys.argv[i] + if '*' in arg: + if arg.startswith('skip:'): + arg = arg[5:] + matching_tests = fnmatch.filter(all_tests, arg) + new_args += map(lambda t: 'skip:' + t, matching_tests) + else: + new_args += fnmatch.filter(all_tests, arg) + else: + new_args += [arg] + if len(new_args) == 1 and len(sys.argv) > 1: + print 'No tests found to run in set ' + str(sys.argv[1:]) + sys.exit(0) + sys.argv = new_args + # Skip requested tests for i in range(len(sys.argv)): arg = sys.argv[i] diff --git a/tests/cases/sillyfuncast2_noasm.ll b/tests/sillyfuncast2_noasm.ll similarity index 100% rename from tests/cases/sillyfuncast2_noasm.ll rename to tests/sillyfuncast2_noasm.ll diff --git a/tests/sockets/test_sockets_echo_client.c b/tests/sockets/test_sockets_echo_client.c index b10cf76febabb..30dbe436a6910 100644 --- a/tests/sockets/test_sockets_echo_client.c +++ b/tests/sockets/test_sockets_echo_client.c @@ -198,10 +198,30 @@ int main() { finish(EXIT_FAILURE); } char buffer[1000]; - sprintf(buffer, "%s:%u\n", inet_ntoa(adr_inet.sin_addr), (unsigned)ntohs(adr_inet.sin_port)); - char *correct = "127.0.0.1:49161\n"; + sprintf(buffer, "%s:%u", inet_ntoa(adr_inet.sin_addr), (unsigned)ntohs(adr_inet.sin_port)); + // TODO: This is not the correct result: We should have a auto-bound address + char *correct = "0.0.0.0:0"; printf("got (expected) socket: %s (%s), size %d (%d)\n", buffer, correct, strlen(buffer), strlen(correct)); - assert(strncmp(buffer, correct, 10) == 0); + assert(strlen(buffer) == strlen(correct)); + assert(strcmp(buffer, correct) == 0); + } + + { + int z; + struct sockaddr_in adr_inet; + socklen_t len_inet = sizeof adr_inet; + z = getpeername(server.fd, (struct sockaddr *)&adr_inet, &len_inet); + if (z != 0) { + perror("getpeername"); + finish(EXIT_FAILURE); + } + char buffer[1000]; + sprintf(buffer, "%s:%u", inet_ntoa(adr_inet.sin_addr), (unsigned)ntohs(adr_inet.sin_port)); + char correct[1000]; + sprintf(correct, "127.0.0.1:%u", SOCKK); + printf("got (expected) socket: %s (%s), size %d (%d)\n", buffer, correct, strlen(buffer), strlen(correct)); + assert(strlen(buffer) == strlen(correct)); + assert(strcmp(buffer, correct) == 0); } #ifdef __EMSCRIPTEN__ diff --git a/tests/test_browser.py b/tests/test_browser.py index bd15a2345bb2b..484e3e5455727 100644 --- a/tests/test_browser.py +++ b/tests/test_browser.py @@ -2755,21 +2755,21 @@ def test_memory_growth_during_startup(self): # pthreads tests # Test that the emscripten_ atomics api functions work. - def test_zzz_aaa_pthread_atomics(self): + def test_pthread_atomics(self): self.btest(path_from_root('tests', 'pthread', 'test_pthread_atomics.cpp'), expected='0', args=['-O3', '-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_POOL_SIZE=8'], timeout=120) # extra time on first test, to be sure to build all libraries # Test 64-bit atomics. - def test_zzz_pthread_64bit_atomics(self): + def test_pthread_64bit_atomics(self): self.btest(path_from_root('tests', 'pthread', 'test_pthread_64bit_atomics.cpp'), expected='0', args=['-O3', '-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_POOL_SIZE=8'], timeout=30) # Test 64-bit C++11 atomics. - def test_zzz_pthread_64bit_cxx11_atomics(self): + def test_pthread_64bit_cxx11_atomics(self): for opt in [['-O0'], ['-O3']]: for pthreads in [[], ['-s', 'USE_PTHREADS=1']]: self.btest(path_from_root('tests', 'pthread', 'test_pthread_64bit_cxx11_atomics.cpp'), expected='0', args=opt + pthreads + ['-std=c++11'], timeout=30) # Test the old GCC atomic __sync_fetch_and_op builtin operations. - def test_zzz_pthread_gcc_atomic_fetch_and_op(self): + def test_pthread_gcc_atomic_fetch_and_op(self): # We need to resort to using regexes to optimize out SharedArrayBuffer when pthreads are not supported, which is brittle! # Therefore perform very extensive testing of different codegen modes to catch any problems. for opt in [[], ['-O1'], ['-O2'], ['-O3'], ['-Os'], ['-Oz']]: @@ -2779,125 +2779,125 @@ def test_zzz_pthread_gcc_atomic_fetch_and_op(self): self.btest(path_from_root('tests', 'pthread', 'test_pthread_gcc_atomic_fetch_and_op.cpp'), expected='0', args=opt+debug+f32+['-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_POOL_SIZE=8'], timeout=60) # 64 bit version of the above test. - def test_zzz_pthread_gcc_64bit_atomic_fetch_and_op(self): + def test_pthread_gcc_64bit_atomic_fetch_and_op(self): self.btest(path_from_root('tests', 'pthread', 'test_pthread_gcc_64bit_atomic_fetch_and_op.cpp'), expected='0', args=['-O3', '-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_POOL_SIZE=8'], timeout=30) # Test the old GCC atomic __sync_op_and_fetch builtin operations. - def test_zzz_pthread_gcc_atomic_op_and_fetch(self): + def test_pthread_gcc_atomic_op_and_fetch(self): self.btest(path_from_root('tests', 'pthread', 'test_pthread_gcc_atomic_op_and_fetch.cpp'), expected='0', args=['-O3', '-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_POOL_SIZE=8'], timeout=30) # 64 bit version of the above test. - def test_zzz_pthread_gcc_64bit_atomic_op_and_fetch(self): + def test_pthread_gcc_64bit_atomic_op_and_fetch(self): self.btest(path_from_root('tests', 'pthread', 'test_pthread_gcc_64bit_atomic_op_and_fetch.cpp'), expected='0', args=['-O3', '-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_POOL_SIZE=8'], timeout=30) # Tests the rest of the remaining GCC atomics after the two above tests. - def test_zzz_pthread_gcc_atomics(self): + def test_pthread_gcc_atomics(self): self.btest(path_from_root('tests', 'pthread', 'test_pthread_gcc_atomics.cpp'), expected='0', args=['-O3', '-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_POOL_SIZE=8'], timeout=30) # Test the __sync_lock_test_and_set and __sync_lock_release primitives. - def test_zzz_pthread_gcc_spinlock(self): + def test_pthread_gcc_spinlock(self): for arg in [[], ['-DUSE_EMSCRIPTEN_INTRINSICS']]: self.btest(path_from_root('tests', 'pthread', 'test_pthread_gcc_spinlock.cpp'), expected='800', args=['-O3', '-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_POOL_SIZE=8'] + arg, timeout=30) # Test that basic thread creation works. - def test_zzz_pthread_create(self): + def test_pthread_create(self): for opt in [['-O0'], ['-O3']]: for pthreads in [['-s', 'USE_PTHREADS=1'], ['-s', 'USE_PTHREADS=2', '--separate-asm']]: print str(opt) + ' ' + str(pthreads) self.btest(path_from_root('tests', 'pthread', 'test_pthread_create.cpp'), expected='0', args=opt + pthreads + ['-s', 'PTHREAD_POOL_SIZE=8'], timeout=30) # Test that a pthread can spawn another pthread of its own. - def test_zzz_pthread_create_pthread(self): + def test_pthread_create_pthread(self): self.btest(path_from_root('tests', 'pthread', 'test_pthread_create_pthread.cpp'), expected='1', args=['-O3', '-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_POOL_SIZE=2', '-s', 'NO_EXIT_RUNTIME=1'], timeout=30) # Test another case of pthreads spawning pthreads, but this time the callers immediately join on the threads they created. - def test_zzz_pthread_nested_spawns(self): + def test_pthread_nested_spawns(self): self.btest(path_from_root('tests', 'pthread', 'test_pthread_nested_spawns.cpp'), expected='1', args=['-O3', '-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_POOL_SIZE=2'], timeout=30) # Test that main thread can wait for a pthread to finish via pthread_join(). - def test_zzz_pthread_join(self): + def test_pthread_join(self): self.btest(path_from_root('tests', 'pthread', 'test_pthread_join.cpp'), expected='6765', args=['-O3', '-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_POOL_SIZE=8'], timeout=30) # Test pthread_cancel() operation - def test_zzz_pthread_cancel(self): + def test_pthread_cancel(self): self.btest(path_from_root('tests', 'pthread', 'test_pthread_cancel.cpp'), expected='1', args=['-O3', '-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_POOL_SIZE=8'], timeout=30) # Test pthread_kill() operation - def test_zzz_pthread_kill(self): + def test_pthread_kill(self): self.btest(path_from_root('tests', 'pthread', 'test_pthread_kill.cpp'), expected='0', args=['-O3', '-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_POOL_SIZE=8'], timeout=30) # Test that pthread cleanup stack (pthread_cleanup_push/_pop) works. - def test_zzz_pthread_cleanup(self): + def test_pthread_cleanup(self): self.btest(path_from_root('tests', 'pthread', 'test_pthread_cleanup.cpp'), expected='907640832', args=['-O3', '-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_POOL_SIZE=8'], timeout=30) # Tests the pthread mutex api. - def test_zzz_pthread_mutex(self): + def test_pthread_mutex(self): for arg in [[], ['-DSPINLOCK_TEST']]: self.btest(path_from_root('tests', 'pthread', 'test_pthread_mutex.cpp'), expected='50', args=['-O3', '-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_POOL_SIZE=8'] + arg, timeout=20) # Test that memory allocation is thread-safe. - def test_zzz_pthread_malloc(self): + def test_pthread_malloc(self): self.btest(path_from_root('tests', 'pthread', 'test_pthread_malloc.cpp'), expected='0', args=['-O3', '-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_POOL_SIZE=8'], timeout=30) # Stress test pthreads allocating memory that will call to sbrk(), and main thread has to free up the data. - def test_zzz_pthread_malloc_free(self): + def test_pthread_malloc_free(self): self.btest(path_from_root('tests', 'pthread', 'test_pthread_malloc_free.cpp'), expected='0', args=['-O3', '-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_POOL_SIZE=8', '-s', 'TOTAL_MEMORY=268435456'], timeout=30) # Test that the pthread_barrier API works ok. - def test_zzz_pthread_barrier(self): + def test_pthread_barrier(self): self.btest(path_from_root('tests', 'pthread', 'test_pthread_barrier.cpp'), expected='0', args=['-O3', '-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_POOL_SIZE=8'], timeout=30) # Test the pthread_once() function. - def test_zzz_pthread_once(self): + def test_pthread_once(self): self.btest(path_from_root('tests', 'pthread', 'test_pthread_once.cpp'), expected='0', args=['-O3', '-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_POOL_SIZE=8'], timeout=30) # Test against a certain thread exit time handling bug by spawning tons of threads. - def test_zzz_pthread_spawns(self): + def test_pthread_spawns(self): self.btest(path_from_root('tests', 'pthread', 'test_pthread_spawns.cpp'), expected='0', args=['-O3', '-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_POOL_SIZE=8'], timeout=30) # It is common for code to flip volatile global vars for thread control. This is a bit lax, but nevertheless, test whether that # kind of scheme will work with Emscripten as well. - def test_zzz_pthread_volatile(self): + def test_pthread_volatile(self): for arg in [[], ['-DUSE_C_VOLATILE']]: self.btest(path_from_root('tests', 'pthread', 'test_pthread_volatile.cpp'), expected='1', args=['-O3', '-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_POOL_SIZE=8'] + arg, timeout=30) # Test thread-specific data (TLS). - def test_zzz_pthread_thread_local_storage(self): + def test_pthread_thread_local_storage(self): self.btest(path_from_root('tests', 'pthread', 'test_pthread_thread_local_storage.cpp'), expected='0', args=['-O3', '-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_POOL_SIZE=8'], timeout=30) # Test the pthread condition variable creation and waiting. - def test_zzz_pthread_condition_variable(self): + def test_pthread_condition_variable(self): self.btest(path_from_root('tests', 'pthread', 'test_pthread_condition_variable.cpp'), expected='0', args=['-O3', '-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_POOL_SIZE=8'], timeout=30) # Test that pthreads are able to do printf. - def test_zzz_pthread_printf(self): + def test_pthread_printf(self): self.btest(path_from_root('tests', 'pthread', 'test_pthread_printf.cpp'), expected='0', args=['-O3', '-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_POOL_SIZE=1'], timeout=30) # Test that pthreads are able to do cout. Failed due to https://bugzilla.mozilla.org/show_bug.cgi?id=1154858. - def test_zzz_pthread_iostream(self): + def test_pthread_iostream(self): self.btest(path_from_root('tests', 'pthread', 'test_pthread_iostream.cpp'), expected='0', args=['-O3', '-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_POOL_SIZE=1'], timeout=30) # Test that the main thread is able to use pthread_set/getspecific. - def test_zzz_pthread_setspecific_mainthread(self): + def test_pthread_setspecific_mainthread(self): self.btest(path_from_root('tests', 'pthread', 'test_pthread_setspecific_mainthread.cpp'), expected='0', args=['-O3', '-s', 'USE_PTHREADS=2', '--separate-asm'], timeout=30) # Test the -s PTHREAD_HINT_NUM_CORES=x command line variable. - def test_zzz_pthread_num_logical_cores(self): + def test_pthread_num_logical_cores(self): self.btest(path_from_root('tests', 'pthread', 'test_pthread_num_logical_cores.cpp'), expected='0', args=['-O3', '-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_HINT_NUM_CORES=2'], timeout=30) # Test that pthreads have access to filesystem. - def test_zzz_pthread_file_io(self): + def test_pthread_file_io(self): self.btest(path_from_root('tests', 'pthread', 'test_pthread_file_io.cpp'), expected='0', args=['-O3', '-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_POOL_SIZE=1'], timeout=30) # Test that the pthread_create() function operates benignly in the case that threading is not supported. - def test_zzz_pthread_supported(self): + def test_pthread_supported(self): for args in [[], ['-s', 'USE_PTHREADS=2', '--separate-asm', '-s', 'PTHREAD_POOL_SIZE=8']]: self.btest(path_from_root('tests', 'pthread', 'test_pthread_supported.cpp'), expected='0', args=['-O3'] + args, timeout=30) - def test_zzz_separate_asm_pthreads(self): + def test_pthread_separate_asm_pthreads(self): self.btest(path_from_root('tests', 'pthread', 'test_pthread_atomics.cpp'), expected='0', args=['-O3', '-s', 'USE_PTHREADS=1', '-s', 'PTHREAD_POOL_SIZE=8', '--separate-asm', '--profiling'], timeout=30) - def test_zzz_pthread_custom_pthread_main_url(self): + def test_pthread_custom_pthread_main_url(self): self.clear() os.makedirs(os.path.join(self.get_dir(), 'cdn')); open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write(self.with_report_result(r''' diff --git a/tests/test_core.py b/tests/test_core.py index 9b5466b986226..a9e7c5dad287a 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -7216,7 +7216,7 @@ def do_test_in_mode(mode): // test purposes: remove printErr output, whose order is unpredictable when compared to print Module.printErr = Module['printErr'] = function(){}; ''') - self.emcc_args += ['--post-js', 'glue.js', '--post-js', 'export.js'] + self.emcc_args += ['-s', 'EXPORTED_FUNCTIONS=["_malloc"]', '--post-js', 'glue.js', '--post-js', 'export.js'] shutil.copyfile(path_from_root('tests', 'webidl', 'test.h'), self.in_dir('test.h')) shutil.copyfile(path_from_root('tests', 'webidl', 'test.cpp'), self.in_dir('test.cpp')) src = open('test.cpp').read() diff --git a/tests/test_other.py b/tests/test_other.py index 46c9bbcdc11f6..0841b30b0443e 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -2783,7 +2783,7 @@ def test_incorrect_static_call(self): for asserts in [0, 1]: extra = [] if opts != 1-asserts: extra = ['-s', 'ASSERTIONS=' + str(asserts)] - cmd = [PYTHON, EMCC, path_from_root('tests', 'cases', 'sillyfuncast2_noasm.ll'), '-O' + str(opts)] + extra + cmd = [PYTHON, EMCC, path_from_root('tests', 'sillyfuncast2_noasm.ll'), '-O' + str(opts)] + extra print cmd stdout, stderr = Popen(cmd, stderr=PIPE).communicate() assert ('''unexpected number of arguments 3 in call to 'doit', should be 2''' in stderr) == asserts, stderr @@ -5929,3 +5929,8 @@ def test_link_response_file_does_not_force_absolute_paths(self): # We want only the relative path to be in the linker args, it should not be converted to an absolute path. self.assertItemsEqual(link_args, [main_object_file_name]) + def test_memory_growth_noasm(self): + check_execute([PYTHON, EMCC, path_from_root('tests', 'hello_world.c'), '-O2', '-s', 'ALLOW_MEMORY_GROWTH=1']) + src = open('a.out.js').read() + assert 'use asm' not in src + diff --git a/tests/test_sockets.py b/tests/test_sockets.py index 5c66623a12810..bc8ed7cadb341 100644 --- a/tests/test_sockets.py +++ b/tests/test_sockets.py @@ -257,14 +257,14 @@ def test_inet4(self): ok. ''') - def test_getsockname_null(self): + def test_getsockname_unconnected_socket(self): self.do_run(r''' #include <sys/socket.h> #include <stdio.h> #include <assert.h> #include <sys/socket.h> #include <netinet/in.h> - #include <arpa/inet.h> + #include <arpa/inet.h> #include <string.h> int main() { int fd; @@ -278,13 +278,39 @@ def test_getsockname_null(self): return 1; } char buffer[1000]; - sprintf(buffer, "%s:%u\n", inet_ntoa(adr_inet.sin_addr), (unsigned)ntohs(adr_inet.sin_port)); - const char *correct = "0.0.0.0:0\n"; + sprintf(buffer, "%s:%u", inet_ntoa(adr_inet.sin_addr), (unsigned)ntohs(adr_inet.sin_port)); + const char *correct = "0.0.0.0:0"; printf("got (expected) socket: %s (%s), size %d (%d)\n", buffer, correct, strlen(buffer), strlen(correct)); + assert(strlen(buffer) == strlen(correct)); + assert(strcmp(buffer, correct) == 0); puts("success."); } ''', 'success.') + def test_getpeername_unconnected_socket(self): + self.do_run(r''' + #include <sys/socket.h> + #include <stdio.h> + #include <assert.h> + #include <sys/socket.h> + #include <netinet/in.h> + #include <arpa/inet.h> + #include <string.h> + int main() { + int fd; + int z; + fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + struct sockaddr_in adr_inet; + socklen_t len_inet = sizeof adr_inet; + z = getpeername(fd, (struct sockaddr *)&adr_inet, &len_inet); + if (z != 0) { + perror("getpeername error"); + return 1; + } + puts("unexpected success."); + } + ''', 'getpeername error: Socket not connected') + def test_getaddrinfo(self): self.emcc_args=[] self.do_run(open(path_from_root('tests', 'sockets', 'test_getaddrinfo.c')).read(), 'success') diff --git a/tests/time/src.c b/tests/time/src.c index 238a43f91c316..ce0771f62520b 100644 --- a/tests/time/src.c +++ b/tests/time/src.c @@ -74,7 +74,7 @@ int main() { // ones to watch, but we don't where they are since the zoneinfo could be US or // European) int mktimeOk = 1; - for (int i = 0; i < 2*24*266; ++i) { + for (int i = 0; i < 2*24*366; ++i) { struct tm tmp; time_t test = xmas2002 + 30*60*i; if (localtime_r(&test, &tmp) != &tmp) printf("localtime_r failed\n");