def test_emconfig(self): restore_and_set_up() fd, custom_config_filename = tempfile.mkstemp( prefix='.emscripten_config_') orig_config = open(CONFIG_FILE, 'r').read() # Move the ~/.emscripten to a custom location. with os.fdopen(fd, "w") as f: f.write(orig_config) # Make a syntax error in the original config file so that attempting to access it would fail. open(CONFIG_FILE, 'w').write('asdfasdfasdfasdf\n\'\'\'' + orig_config) temp_dir = tempfile.mkdtemp(prefix='emscripten_temp_') with chdir(temp_dir): run_process([EMCC, '--em-config', custom_config_filename] + MINIMAL_HELLO_WORLD + ['-O2']) result = run_js('a.out.js') self.assertContained('hello, world!', result) # Clean up created temp files. os.remove(custom_config_filename) if Settings.WASM_BACKEND: os.remove(custom_config_filename + "_sanity_wasm") else: os.remove(custom_config_filename + "_sanity") shutil.rmtree(temp_dir)
def test_js_engine_path(self): # Test that running JS commands works for node, d8, and jsc and is not path dependent restore_and_set_up() sample_script = path_from_root('tests', 'print_args.js') # Fake some JS engines # Note that the path contains 'd8'. test_path = self.in_dir('fake', 'abcd8765') ensure_dir(test_path) with env_modify({'EM_IGNORE_SANITY': '1'}): jsengines = [('d8', V8_ENGINE), ('d8_g', V8_ENGINE), ('js', SPIDERMONKEY_ENGINE), ('node', NODE_JS), ('nodejs', NODE_JS)] for filename, engine in jsengines: if type(engine) is list: engine = engine[0] if not engine: print('WARNING: Not testing engine %s, not configured.' % (filename)) continue print(filename, engine) test_engine_path = os.path.join(test_path, filename) with open(test_engine_path, 'w') as f: f.write('#!/bin/sh\n') f.write('exec %s $@\n' % (engine)) os.chmod(test_engine_path, stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC) out = run_js(sample_script, engine=test_engine_path, args=['--foo']) self.assertEqual('0: --foo', out.strip())
def test_d8_path(self): """ Test that running JS commands works for node, d8, and jsc and is not path dependent """ # Fake some JS engines restore_and_set_up() sample_script = path_from_root('tests', 'print_args.js') # Note that the path contains 'd8'. test_path = self.in_dir('fake', 'abcd8765') ensure_dir(test_path) with env_modify({'EM_IGNORE_SANITY': '1'}): jsengines = [('d8', V8_ENGINE), ('d8_g', V8_ENGINE), ('js', SPIDERMONKEY_ENGINE), ('node', NODE_JS), ('nodejs', NODE_JS)] for filename, engine in jsengines: if type(engine) is list: engine = engine[0] if not engine: print('WARNING: Not testing engine %s, not configured.' % (filename)) continue print(filename, engine) test_engine_path = os.path.join(test_path, filename) f = open(test_engine_path, 'w') f.write('#!/bin/sh\n') f.write('%s $@\n' % (engine)) f.close() os.chmod(test_engine_path, stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC) try: out = run_js(sample_script, engine=test_engine_path, args=['--foo'], full_output=True, assert_returncode=0, skip_check=True) except Exception as e: if 'd8' in filename: assert False, 'Your d8 version does not correctly parse command-line arguments, please upgrade or delete from ~/.emscripten config file: %s' % ( e) else: assert False, 'Error running script command: %s' % (e) self.assertEqual('0: --foo', out.strip())
def test_emcc_caching(self): BUILDING_MESSAGE = 'generating system library: X' ERASING_MESSAGE = 'clearing cache' restore_and_set_up() self.erase_cache() # Building a file that *does* need something *should* trigger cache # generation, but only the first time libname = 'libc++' for i in range(3): print(i) self.clear() output = self.do([ EMCC, '-O' + str(i), '-s', '--llvm-lto', '0', path_from_root('tests', 'hello_libcxx.cpp'), '--save-bc', 'a.bc', '-s', 'DISABLE_EXCEPTION_CATCHING=0' ]) print('\n\n\n', output) assert (BUILDING_MESSAGE.replace('X', libname) in output) == (i == 0), 'Must only build the first time' self.assertContained('hello, world!', run_js('a.out.js')) self.assertExists(Cache.dirname) full_libname = libname + '.bc' if libname != 'libc++' else libname + '.a' self.assertExists(os.path.join(Cache.dirname, full_libname)) restore_and_set_up() # Manual cache clearing self.ensure_cache() self.assertTrue(os.path.exists(Cache.dirname)) self.assertTrue(os.path.exists(Cache.root_dirname)) output = self.do([EMCC, '--clear-cache']) self.assertIn(ERASING_MESSAGE, output) self.assertIn(SANITY_MESSAGE, output) self.assertCacheEmpty() # Changing LLVM_ROOT, even without altering .emscripten, clears the cache self.ensure_cache() make_fake_clang(self.in_dir('fake', 'bin', 'clang'), expected_llvm_version()) make_fake_llc(self.in_dir('fake', 'bin', 'llc'), 'js - JavaScript (asm.js, emscripten)') with env_modify({'EM_LLVM_ROOT': self.in_dir('fake', 'bin')}): self.assertTrue(os.path.exists(Cache.dirname)) output = self.do([EMCC]) self.assertIn(ERASING_MESSAGE, output) self.assertCacheEmpty()
def test_em_config_env_var(self): # emcc should be configurable directly from EM_CONFIG without any config file restore_and_set_up() create_test_file('main.cpp', ''' #include <stdio.h> int main() { printf("hello from emcc with no config file\\n"); return 0; } ''') wipe() with env_modify({'EM_CONFIG': get_basic_config()}): run_process([EMCC, 'main.cpp', '-o', 'a.out.js']) self.assertContained('hello from emcc with no config file', run_js('a.out.js'))
def try_js(args): shared.run_process([shared.EMCC] + EMCC_ARGS + CSMITH_CFLAGS + args + [filename, '-o', js_filename]) js = jsrun.run_js(js_filename, engine=shared.NODE_JS, stderr=PIPE) assert correct == js
def run(self, args): return jsrun.run_js(self.filename, engine=self.engine, args=args, stderr=PIPE)
use_data += ''' var files = metadata.files; for (var i = 0; i < files.length; ++i) { DataRequest.prototype.requests[files[i].filename].onload(); } ''' use_data += " Module['removeRunDependency']('datafile_%s');\n" % escape_for_js_string( data_target) else: # LZ4FS usage temp = data_target + '.orig' shutil.move(data_target, temp) meta = run_js( shared.path_from_root('tools', 'lz4-compress.js'), shared.NODE_JS, [shared.path_from_root('src', 'mini-lz4.js'), temp, data_target], stdout=PIPE) os.unlink(temp) use_data = ''' var compressedData = %s; compressedData.data = byteArray; assert(typeof LZ4 === 'object', 'LZ4 not present - was your app build with -s LZ4=1 ?'); LZ4.loadPackage({ 'metadata': metadata, 'compressedData': compressedData }); Module['removeRunDependency']('datafile_%s'); ''' % (meta, escape_for_js_string(data_target)) package_uuid = uuid.uuid4() package_name = data_target statinfo = os.stat(package_name) remote_package_size = statinfo.st_size
def test_nodejs_sockets_echo(self): # This test checks that sockets work when the client code is run in Node.js # Run with ./runner.py sockets.test_nodejs_sockets_echo if NODE_JS not in JS_ENGINES: self.skipTest('node is not present') sockets_include = '-I' + path_from_root('tests', 'sockets') harnesses = [ (CompiledServerHarness(os.path.join('sockets', 'test_sockets_echo_server.c'), [sockets_include, '-DTEST_DGRAM=0'], 59162), 0), (CompiledServerHarness(os.path.join('sockets', 'test_sockets_echo_server.c'), [sockets_include, '-DTEST_DGRAM=1'], 59164), 1) ] if not WINDOWS: # TODO: Python pickling bug causes WebsockifyServerHarness to not work on Windows. harnesses += [(WebsockifyServerHarness(os.path.join('sockets', 'test_sockets_echo_server.c'), [sockets_include], 59160), 0)] # Basic test of node client against both a Websockified and compiled echo server. for harness, datagram in harnesses: with harness: run_process([EMCC, path_from_root('tests', 'sockets', 'test_sockets_echo_client.c'), '-o', 'client.js', '-DSOCKK=%d' % harness.listen_port, '-DTEST_DGRAM=%d' % datagram], stdout=PIPE, stderr=PIPE) out = run_js('client.js', full_output=True) self.assertContained('do_msg_read: read 14 bytes', out) if not WINDOWS: # TODO: Python pickling bug causes WebsockifyServerHarness to not work on Windows. # Test against a Websockified server with compile time configured WebSocket subprotocol. We use a Websockified # server because as long as the subprotocol list contains binary it will configure itself to accept binary # This test also checks that the connect url contains the correct subprotocols. print("\nTesting compile time WebSocket configuration.\n") for harness in [ WebsockifyServerHarness(os.path.join('sockets', 'test_sockets_echo_server.c'), [sockets_include], 59166) ]: with harness: run_process([EMCC, path_from_root('tests', 'sockets', 'test_sockets_echo_client.c'), '-o', 'client.js', '-s', 'SOCKET_DEBUG=1', '-s', 'WEBSOCKET_SUBPROTOCOL="base64, binary"', '-DSOCKK=59166'], stdout=PIPE, stderr=PIPE) out = run_js('client.js', full_output=True) self.assertContained('do_msg_read: read 14 bytes', out) self.assertContained(['connect: ws://127.0.0.1:59166, base64,binary', 'connect: ws://127.0.0.1:59166/, base64,binary'], out) # Test against a Websockified server with runtime WebSocket configuration. We specify both url and subprotocol. # In this test we have *deliberately* used the wrong port '-DSOCKK=12345' to configure the echo_client.c, so # the connection would fail without us specifying a valid WebSocket URL in the configuration. print("\nTesting runtime WebSocket configuration.\n") for harness in [ WebsockifyServerHarness(os.path.join('sockets', 'test_sockets_echo_server.c'), [sockets_include], 59168) ]: with harness: open(os.path.join(self.get_dir(), 'websocket_pre.js'), 'w').write(''' var Module = { websocket: { url: 'ws://localhost:59168/testA/testB', subprotocol: 'text, base64, binary', } }; ''') run_process([EMCC, path_from_root('tests', 'sockets', 'test_sockets_echo_client.c'), '-o', 'client.js', '--pre-js', 'websocket_pre.js', '-s', 'SOCKET_DEBUG=1', '-DSOCKK=12345'], stdout=PIPE, stderr=PIPE) out = run_js('client.js', full_output=True) self.assertContained('do_msg_read: read 14 bytes', out) self.assertContained('connect: ws://localhost:59168/testA/testB, text,base64,binary', out)
def test(): self.assertContained('hello, world!', run_js('a.out.js'))
def test_emcc(self): SANITY_FAIL_MESSAGE = 'sanity check failed to run' # emcc should check sanity if no ${EM_CONFIG}_sanity restore_and_set_up() time.sleep(1) assert not os.path.exists( SANITY_FILE) # restore is just the settings, not the sanity output = self.check_working(EMCC) self.assertContained(SANITY_MESSAGE, output) # EMCC should have checked sanity successfully old_sanity = open(SANITY_FILE).read() self.assertNotContained(SANITY_FAIL_MESSAGE, output) # emcc run again should not sanity check, because the sanity file is newer output = self.check_working(EMCC) self.assertNotContained(SANITY_MESSAGE, output) self.assertNotContained(SANITY_FAIL_MESSAGE, output) # incorrect sanity contents mean we *must* check open(SANITY_FILE, 'w').write('wakawaka') output = self.check_working(EMCC) self.assertContained(SANITY_MESSAGE, output) # correct sanity contents mean we need not check open(SANITY_FILE, 'w').write(old_sanity) output = self.check_working(EMCC) self.assertNotContained(SANITY_MESSAGE, output) # but with EMCC_DEBUG=1 we should check with env_modify({'EMCC_DEBUG': '1'}): output = self.check_working(EMCC) try_delete(CANONICAL_TEMP_DIR) self.assertContained(SANITY_MESSAGE, output) output = self.check_working(EMCC) self.assertNotContained(SANITY_MESSAGE, output) # also with -v, with or without inputs output = self.check_working([EMCC, '-v'], SANITY_MESSAGE) output = self.check_working([EMCC, '-v'] + MINIMAL_HELLO_WORLD + [], SANITY_MESSAGE) # Make sure the test runner didn't do anything to the setup output = self.check_working(EMCC) self.assertNotContained(SANITY_MESSAGE, output) self.assertNotContained(SANITY_FAIL_MESSAGE, output) # emcc should also check sanity if the file is outdated open(CONFIG_FILE, 'a').write('# extra stuff\n') output = self.check_working(EMCC) self.assertContained(SANITY_MESSAGE, output) self.assertNotContained(SANITY_FAIL_MESSAGE, output) # emcc should be configurable directly from EM_CONFIG without any config file restore_and_set_up() config = open(CONFIG_FILE, 'r').read() open('main.cpp', 'w').write(''' #include <stdio.h> int main() { printf("hello from emcc with no config file\\n"); return 0; } ''') wipe() with env_modify({'EM_CONFIG': config}): run_process([EMCC, 'main.cpp', '-o', 'a.out.js']) self.assertContained('hello from emcc with no config file', run_js('a.out.js'))
// Reuse the bytearray from the XHR as the source for file reads. DataRequest.prototype.byteArray = byteArray; ''' use_data += ''' var files = metadata.files; for (i = 0; i < files.length; ++i) { DataRequest.prototype.requests[files[i].filename].onload(); } ''' use_data += " Module['removeRunDependency']('datafile_%s');\n" % data_target else: # LZ4FS usage temp = data_target + '.orig' shutil.move(data_target, temp) meta = run_js(shared.path_from_root('tools', 'lz4-compress.js'), shared.NODE_JS, [shared.path_from_root('src', 'mini-lz4.js'), temp, data_target], stdout=PIPE) os.unlink(temp) use_data = ''' var compressedData = %s; compressedData.data = byteArray; assert(typeof LZ4 === 'object', 'LZ4 not present - was your app build with -s LZ4=1 ?'); LZ4.loadPackage({ 'metadata': metadata, 'compressedData': compressedData }); Module['removeRunDependency']('datafile_%s'); ''' % (meta, data_target) package_uuid = uuid.uuid4(); package_name = data_target statinfo = os.stat(package_name) remote_package_size = statinfo.st_size remote_package_name = os.path.basename(package_name) ret += r'''