def __enter__(self): # compile the server # NOTE empty filename support is a hack to support # the current test_enet if self.filename: proc = run_process([CLANG_CC, path_from_root('tests', self.filename), '-o', 'server', '-DSOCKK=%d' % self.target_port] + clang_native.get_clang_native_args() + self.args, clang_native.get_clang_native_env(), stdout=PIPE, stderr=PIPE) print('Socket server build: out:', proc.stdout or '', '/ err:', proc.stderr or '') process = Popen([os.path.abspath('server')]) self.processes.append(process) # start the websocket proxy print('running websockify on %d, forward to tcp %d' % (self.listen_port, self.target_port), file=sys.stderr) wsp = websockify.WebSocketProxy(verbose=True, listen_port=self.listen_port, target_host="127.0.0.1", target_port=self.target_port, run_once=True) self.websockify = multiprocessing.Process(target=wsp.start_server) self.websockify.start() self.processes.append(self.websockify) # Make sure both the actual server and the websocket proxy are running for i in range(10): try: if self.do_server_check: server_sock = socket.create_connection(('localhost', self.target_port), timeout=1) server_sock.close() proxy_sock = socket.create_connection(('localhost', self.listen_port), timeout=1) proxy_sock.close() break except IOError: time.sleep(1) else: clean_processes(self.processes) raise Exception('[Websockify failed to start up in a timely manner]') print('[Websockify on process %s]' % str(self.processes[-2:]))
def test_sdl_audio(self): shutil.copyfile( path_from_root('tests', 'sounds', 'alarmvictory_1.ogg'), os.path.join(self.get_dir(), 'sound.ogg')) shutil.copyfile( path_from_root('tests', 'sounds', 'alarmcreatemiltaryfoot_1.wav'), os.path.join(self.get_dir(), 'sound2.wav')) shutil.copyfile(path_from_root('tests', 'sounds', 'noise.ogg'), os.path.join(self.get_dir(), 'noise.ogg')) shutil.copyfile( path_from_root('tests', 'sounds', 'the_entertainer.ogg'), os.path.join(self.get_dir(), 'the_entertainer.ogg')) open(os.path.join(self.get_dir(), 'bad.ogg'), 'w').write('I claim to be audio, but am lying') open(os.path.join(self.get_dir(), 'sdl_audio.c'), 'w').write( self.with_report_result( open(path_from_root('tests', 'sdl_audio.c')).read())) # use closure to check for a possible bug with closure minifying away newer Audio() attributes Popen([ EMCC, '-O2', '--closure', '1', '--minify', '0', os.path.join(self.get_dir(), 'sdl_audio.c'), '--preload-file', 'sound.ogg', '--preload-file', 'sound2.wav', '--embed-file', 'the_entertainer.ogg', '--preload-file', 'noise.ogg', '--preload-file', 'bad.ogg', '-o', 'page.html', '-s', 'EXPORTED_FUNCTIONS=["_main", "_play", "_play2"]' ]).communicate() self.run_browser('page.html', '', '/report_result?1')
def test_sdl_audio_panning(self): shutil.copyfile(path_from_root('tests', 'sounds', 'the_entertainer.wav'), os.path.join(self.get_dir(), 'the_entertainer.wav')) open(os.path.join(self.get_dir(), 'sdl_audio_panning.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_audio_panning.c')).read())) # use closure to check for a possible bug with closure minifying away newer Audio() attributes Popen([PYTHON, EMCC, '-O2', '--closure', '1', '--minify', '0', os.path.join(self.get_dir(), 'sdl_audio_panning.c'), '--preload-file', 'the_entertainer.wav', '-o', 'page.html', '-s', 'EXPORTED_FUNCTIONS=["_main", "_play"]']).communicate() self.run_browser('page.html', '', '/report_result?1')
def test_openal_playback(self): shutil.copyfile(path_from_root('tests', 'sounds', 'audio.wav'), os.path.join(self.get_dir(), 'audio.wav')) open(os.path.join(self.get_dir(), 'openal_playback.cpp'), 'w').write(self.with_report_result(open(path_from_root('tests', 'openal_playback.cpp')).read())) for args in [[], ['-s', 'USE_PTHREADS=1', '-s', 'PROXY_TO_PTHREAD=1']]: Popen([PYTHON, EMCC, '-O2', os.path.join(self.get_dir(), 'openal_playback.cpp'), '--preload-file', 'audio.wav', '-o', 'page.html'] + args).communicate() self.run_browser('page.html', '', '/report_result?1')
def __enter__(self): # assuming this is only used for WebSocket tests at the moment, validate that # the ws module is installed child = run_process(NODE_JS + ['-e', 'require("ws");'], check=False) global node_ws_module_installed # Attempt to automatically install ws module for Node.js. if child.returncode != 0 and not node_ws_module_installed: node_ws_module_installed = True run_process( [NPM, 'install', path_from_root('tests', 'sockets', 'ws')], cwd=os.path.dirname(EMCC)) # Did installation succeed? child = run_process(NODE_JS + ['-e', 'require("ws");'], check=False) assert child.returncode == 0, 'ws module for Node.js not installed, and automatic installation failed! Please run \'npm install\' from %s' % shared.__rootpath__ # compile the server proc = run_process([ PYTHON, EMCC, path_from_root('tests', self.filename), '-o', 'server.js', '-DSOCKK=%d' % self.listen_port ] + self.args) print('Socket server build: out:', proc.stdout or '', '/ err:', proc.stderr or '') process = Popen(NODE_JS + ['server.js']) self.processes.append(process)
def test_sdl_audio_mix(self): shutil.copyfile(path_from_root('tests', 'sounds', 'pluck.ogg'), os.path.join(self.get_dir(), 'sound.ogg')) shutil.copyfile(path_from_root('tests', 'sounds', 'the_entertainer.ogg'), os.path.join(self.get_dir(), 'music.ogg')) shutil.copyfile(path_from_root('tests', 'sounds', 'noise.ogg'), os.path.join(self.get_dir(), 'noise.ogg')) open(os.path.join(self.get_dir(), 'sdl_audio_mix.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_audio_mix.c')).read())) Popen([PYTHON, EMCC, '-O2', '--minify', '0', os.path.join(self.get_dir(), 'sdl_audio_mix.c'), '--preload-file', 'sound.ogg', '--preload-file', 'music.ogg', '--preload-file', 'noise.ogg', '-o', 'page.html']).communicate() self.run_browser('page.html', '', '/report_result?1')
def test_sdl_audio_beeps(self): open(os.path.join(self.get_dir(), 'sdl_audio_beep.cpp'), 'w').write( self.with_report_result( open(path_from_root('tests', 'sdl_audio_beep.cpp')).read())) # use closure to check for a possible bug with closure minifying away newer Audio() attributes Popen([ PYTHON, EMCC, '-O2', '--closure', '1', '--minify', '0', os.path.join(self.get_dir(), 'sdl_audio_beep.cpp'), '-s', 'DISABLE_EXCEPTION_CATCHING=0', '-o', 'page.html' ]).communicate() self.run_browser('page.html', '', '/report_result?1')
def test_sdl2_mixer(self): shutil.copyfile( path_from_root('tests', 'sounds', 'alarmvictory_1.ogg'), os.path.join(self.get_dir(), 'sound.ogg')) open(os.path.join(self.get_dir(), 'sdl2_mixer.c'), 'w').write( self.with_report_result( open(path_from_root('tests', 'sdl2_mixer.c')).read())) Popen([ PYTHON, EMCC, '-O2', '--minify', '0', os.path.join(self.get_dir(), 'sdl2_mixer.c'), '-s', 'USE_SDL=2', '-s', 'USE_SDL_MIXER=2', '-s', 'TOTAL_MEMORY=33554432', '--preload-file', 'sound.ogg', '-o', 'page.html' ]).communicate() self.run_browser('page.html', '', '/report_result?1')
def __enter__(self): # assuming this is only used for WebSocket tests at the moment, validate that # the ws module is installed global npm_checked if not npm_checked: child = run_process(NODE_JS + ['-e', 'require("ws");'], check=False) assert child.returncode == 0, '"ws" node module not found. you may need to run npm install' npm_checked = True # compile the server proc = run_process([EMCC, path_from_root('tests', self.filename), '-o', 'server.js', '-DSOCKK=%d' % self.listen_port] + self.args) print('Socket server build: out:', proc.stdout or '', '/ err:', proc.stderr or '') process = Popen(NODE_JS + ['server.js']) self.processes.append(process)
def test_sdl2_mixer_wav(self): shutil.copyfile( path_from_root('tests', 'sounds', 'the_entertainer.wav'), os.path.join(self.get_dir(), 'sound.wav')) open(os.path.join(self.get_dir(), 'sdl2_mixer_wav.c'), 'w').write( self.with_report_result( open(path_from_root('tests', 'sdl2_mixer_wav.c')).read())) Popen([ EMCC, '-O2', '--minify', '0', os.path.join(self.get_dir(), 'sdl2_mixer_wav.c'), '-s', 'USE_SDL=2', '-s', 'USE_SDL_MIXER=2', '-s', 'INITIAL_MEMORY=33554432', '--preload-file', 'sound.wav', '-o', 'page.html' ]).communicate() self.run_browser('page.html', '', '/report_result?1')
def path_from_root(*pathelems): return os.path.join(__rootpath__, *pathelems) sys.path += [path_from_root('')] from tools import shared, building from tools.shared import PYTHON, WINDOWS, CLANG_CXX, EMCC, PIPE, V8_ENGINE from tools.shared import Popen temp_dir = tempfile.mkdtemp() # System info system_info = Popen([PYTHON, path_from_root('emrun'), '--system_info'], stdout=PIPE, stderr=PIPE).communicate() # Native info native_info = Popen(['clang', '-v'], stdout=PIPE, stderr=PIPE).communicate() # Emscripten info emscripten_info = Popen([EMCC, '-v'], stdout=PIPE, stderr=PIPE).communicate() def run_benchmark(benchmark_file, results_file, build_args): # Run native build out_file = os.path.join(temp_dir, 'benchmark_sse_native') if WINDOWS: out_file += '.exe' cmd = [CLANG_CXX] + building.get_native_building_args() + [ benchmark_file, '-O3', '-o', out_file
def test_freealut(self): Popen([EMCC, '-O2'] + self.get_freealut_library() + ['-o', 'page.html']).communicate() self.run_browser('page.html', 'You should hear "Hello World!"')
def path_from_root(*pathelems): return os.path.join(__rootpath__, *pathelems) sys.path += [path_from_root('')] from tools import shared from tools.shared import PYTHON, WINDOWS, CLANG_CXX, EMCC, PIPE, V8_ENGINE from tools.shared import Popen temp_dir = tempfile.mkdtemp() # System info system_info = Popen([PYTHON, path_from_root('emrun'), '--system_info'], stdout=PIPE, stderr=PIPE).communicate() # Native info native_info = Popen(['clang', '-v'], stdout=PIPE, stderr=PIPE).communicate() # Emscripten info emscripten_info = Popen([EMCC, '-v'], stdout=PIPE, stderr=PIPE).communicate() # Run native build out_file = os.path.join(temp_dir, 'benchmark_sse1_native') if WINDOWS: out_file += '.exe' cmd = [CLANG_CXX] + shared.Building.get_native_building_args() + [ path_from_root('tests', 'sse', 'benchmark_sse1.cpp'), '-O3', '-o', out_file ] print 'Building native version of the benchmark:'
def run_benchmark(benchmark_file, results_file, build_args): # Run native build out_file = os.path.join(temp_dir, 'benchmark_sse_native') if WINDOWS: out_file += '.exe' cmd = [CLANG_CXX] + building.get_native_building_args() + [ benchmark_file, '-O3', '-o', out_file ] print 'Building native version of the benchmark:' print ' '.join(cmd) build = Popen(cmd, env=building.get_building_env(native=True)) out = build.communicate() if build.returncode != 0: sys.exit(1) native_results = Popen([out_file], stdout=PIPE, stderr=PIPE).communicate() print native_results[0] # Run emscripten build out_file = os.path.join(temp_dir, 'benchmark_sse_html.js') cmd = [ EMCC, benchmark_file, '-O3', '-s', 'TOTAL_MEMORY=536870912', '-o', out_file ] + build_args print 'Building Emscripten version of the benchmark:' print ' '.join(cmd) build = Popen(cmd) out = build.communicate() if build.returncode != 0: sys.exit(1) cmd = V8_ENGINE + ['--experimental-wasm-simd', os.path.basename(out_file)] print ' '.join(cmd) old_dir = os.getcwd() os.chdir(os.path.dirname(out_file)) wasm_results = Popen(cmd, stdout=PIPE, stderr=PIPE).communicate() os.chdir(old_dir) if not wasm_results: raise Exception('Unable to run benchmark in V8!') if not wasm_results[0].strip(): print wasm_results[1] sys.exit(1) print wasm_results[0] def strip_comments(text): return re.sub('//.*?\n|/\*.*?\*/', '', text, re.S) benchmark_results = strip_comments(wasm_results[0]) # Strip out unwanted print output. benchmark_results = benchmark_results[benchmark_results.find('{'):].strip() if '*************************' in benchmark_results: benchmark_results = benchmark_results[:benchmark_results.find( '*************************')].strip() print benchmark_results shutil.rmtree(temp_dir) native_results = json.loads(native_results[0]) benchmark_results = benchmark_results[ benchmark_results.index('{'):benchmark_results.rindex('}') + 1] wasm_results = json.loads(benchmark_results) native_workload = native_results['workload'] html_workload = wasm_results['workload'] html = '''<html><head></head><body><h1>SSE JavaScript Benchmark</h1> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script> <script src="https://code.highcharts.com/highcharts.js"></script> <script src="https://code.highcharts.com/modules/exporting.js"></script><b>System Info:</b><br/> ''' + system_info[0].replace('\n', '<br/>') + ''' <b>Native Clang Compiler:</b><br/> ''' + native_info[1].replace('\n', '<br/>') + ''' <b>Emscripten Compiler:</b><br/> ''' + emscripten_info[0].replace('\n', '<br/>') charts_native = {} charts_html = {} for result in native_results['results']: ch = result['chart'] if ch not in charts_native: charts_native[ch] = [] charts_native[ch] += [result] for result in wasm_results['results']: ch = result['chart'] if ch not in charts_html: charts_html[ch] = [] charts_html[ch] += [result] def find_result_in_category(results, category): for result in results: if result['category'] == category: return result return None def format_comparison(a, b): if a < b and a != 0: return "<span style='color:green;font-weight:bold;'> {:10.2f}".format( b / a) + 'x FASTER</span>' elif b != 0: return "<span style='color:red;font-weight:bold;'> {:10.2f}".format( a / b) + 'x SLOWER</span>' else: return "<span style='color:red;font-weight:bold;'> NaN </span>" chartNumber = 0 total_time_native_scalar = 0 total_time_native_simd = 0 total_time_html_scalar = 0 total_time_html_simd = 0 for chart_name in charts_native.keys(): # Extract data for each chart. categories = [] nativeScalarResults = [] nativeSimdResults = [] htmlScalarResults = [] htmlSimdResults = [] native_results = charts_native[chart_name] wasm_results = charts_html[chart_name] textual_results_native = '<p>' textual_results_html = '<p>' textual_results_html2 = '<p>' textual_results_html3 = '<p>' for result in native_results: categories += ["'" + result['category'] + "'"] nsc = result['scalar'] nsi = result['simd'] nativeScalarResults += [str(nsc)] nativeSimdResults += [str(nsi)] html_result = find_result_in_category(wasm_results, result['category']) textual_results_native += 'Native ' + result[ 'category'] + ': ' + "{:10.4f}".format( nsc) + 'ns -> ' + "{:10.4f}".format(nsi) + 'ns. ' textual_results_native += 'Native SSE is ' + format_comparison( nsi, nsc ) + ' than native scalar. <br />' if html_result is not None: hsc = html_result['scalar'] htmlScalarResults += [str(hsc)] hsi = html_result['simd'] htmlSimdResults += [str(hsi)] textual_results_html += 'JS ' + result[ 'category'] + ': ' + "{:10.4f}".format( hsc) + 'ns -> ' + "{:10.4f}".format(hsi) + 'ns. ' textual_results_html += 'JS SSE is ' + format_comparison( hsi, hsc ) + ' than JS scalar. <br />' textual_results_html2 += 'JS ' + result[ 'category'] + ': JS scalar is ' + format_comparison( hsc, nsc ) + ' than native scalar. <br />' textual_results_html3 += 'JS ' + result[ 'category'] + ': JS SSE is ' + format_comparison( hsi, nsi ) + ' than native SSE. <br />' total_time_native_scalar += nsc total_time_native_simd += nsi total_time_html_scalar += hsc total_time_html_simd += hsi else: htmlScalarResults += [str(-1)] htmlSimdResults += [str(-1)] chartNumber += 1 html += '<div id="chart' + str( chartNumber ) + '" style="width:100%; height:400px; margin-top: 100px;"></div>' html += '''<script>$(function () { $('#chart''' + str(chartNumber) + '''').highcharts({ chart: { type: 'column' }, title: { text: "''' + chart_name + '''" }, subtitle: { text: 'Time per operation in nanoseconds' }, xAxis: { categories: [''' + ','.join(categories) + ''' ] }, yAxis: { min: 0, title: { text: 'Time (nanoseconds)' } }, tooltip: { headerFormat: '<span style="font-size:10px">{point.key}</span><table>', pointFormat: '<tr><td style="color:{series.color};padding:0">{series.name}: </td>' + '<td style="padding:0"><b>{point.y:.3f} ns</b></td></tr>', footerFormat: '</table>', shared: true, useHTML: true }, plotOptions: { column: { pointPadding: 0.2, borderWidth: 0 } }, series: [{ name: 'Native scalar', data: [''' + ','.join(nativeScalarResults) + '''] }, { name: 'Native SSE', data: [''' + ','.join(nativeSimdResults) + '''] }, { name: 'JS scalar', data: [''' + ','.join(htmlScalarResults) + '''] }, { name: 'JS SSE', data: [''' + ','.join(htmlSimdResults) + '''] }] }); });</script>''' + '<table><tr><td>' + textual_results_native + '</td><td>' + textual_results_html + '</td></tr><tr><td>' + textual_results_html2 + '</td><td>' + textual_results_html3 + '</td></tr></table>' # Final overall score html += '<div id="overallscore" style="width:100%; height:400px; margin-top: 100px;"></div>' html += '''<script>$(function () { $('#overallscore').highcharts({ chart: { type: 'column' }, title: { text: "Overall Execution Time" }, xAxis: { categories: ['Total time normalized to native'] }, yAxis: { min: 0, title: { text: 'Relative time' } }, tooltip: { headerFormat: '<span style="font-size:10px">{point.key}</span><table>', pointFormat: '<tr><td style="color:{series.color};padding:0">{series.name}: </td>' + '<td style="padding:0"><b>{point.y:.3f}x</b></td></tr>', footerFormat: '</table>', shared: true, useHTML: true }, plotOptions: { column: { pointPadding: 0.2, borderWidth: 0 } }, series: [{ name: 'Native scalar', data: [''' + str(1.0) + '''] }, { name: 'Native SSE', data: [''' + (str(total_time_native_simd / total_time_native_scalar) if total_time_native_scalar != 0 else 'N/A') + '''] }, { name: 'JS scalar', data: [''' + (str(total_time_html_scalar / total_time_native_scalar) if total_time_native_scalar != 0 else 'N/A') + '''] }, { name: 'JS SSE', data: [''' + (str(total_time_html_simd / total_time_native_scalar) if total_time_native_scalar != 0 else 'N/A') + '''] }] }); });</script>''' html += '</body></html>' open(results_file, 'w').write(html) print 'Wrote ' + str(len(html)) + ' bytes to file ' + results_file + '.'
def test_webrtc(self): # XXX see src/settings.js, this is disabled pending investigation self.skipTest('WebRTC support is not up to date.') host_src = 'webrtc_host.c' peer_src = 'webrtc_peer.c' host_outfile = 'host.html' peer_outfile = 'peer.html' host_filepath = path_from_root('tests', 'sockets', host_src) temp_host_filepath = os.path.join(self.get_dir(), os.path.basename(host_src)) with open(host_filepath) as f: host_src = f.read() with open(temp_host_filepath, 'w') as f: f.write(self.with_report_result(host_src)) peer_filepath = path_from_root('tests', 'sockets', peer_src) temp_peer_filepath = os.path.join(self.get_dir(), os.path.basename(peer_src)) with open(peer_filepath) as f: peer_src = f.read() with open(temp_peer_filepath, 'w') as f: f.write(self.with_report_result(peer_src)) open(os.path.join(self.get_dir(), 'host_pre.js'), 'w').write(''' var Module = { webrtc: { broker: 'http://localhost:8182', session: undefined, onpeer: function(peer, route) { window.open('http://localhost:8888/peer.html?' + route); // iframe = document.createElement("IFRAME"); // iframe.setAttribute("src", "http://localhost:8888/peer.html?" + route); // iframe.style.display = "none"; // document.body.appendChild(iframe); peer.listen(); }, onconnect: function(peer) { }, ondisconnect: function(peer) { }, onerror: function(error) { console.error(error); } }, setStatus: function(text) { console.log('status: ' + text); } }; ''') open(os.path.join(self.get_dir(), 'peer_pre.js'), 'w').write(''' var Module = { webrtc: { broker: 'http://localhost:8182', session: window.location.toString().split('?')[1], onpeer: function(peer, route) { peer.connect(Module['webrtc']['session']); }, onconnect: function(peer) { }, ondisconnect: function(peer) { // Calling window.close() from this handler hangs my browser, so run it in the next turn setTimeout(window.close, 0); }, onerror: function(error) { console.error(error); }, }, setStatus: function(text) { console.log('status: ' + text); } }; ''') run_process([EMCC, temp_host_filepath, '-o', host_outfile] + ['-s', 'GL_TESTING=1', '--pre-js', 'host_pre.js', '-s', 'SOCKET_WEBRTC=1', '-s', 'SOCKET_DEBUG=1']) run_process([EMCC, temp_peer_filepath, '-o', peer_outfile] + ['-s', 'GL_TESTING=1', '--pre-js', 'peer_pre.js', '-s', 'SOCKET_WEBRTC=1', '-s', 'SOCKET_DEBUG=1']) # note: you may need to run this manually yourself, if npm is not in the path, or if you need a version that is not in the path run_process([NPM, 'install', path_from_root('tests', 'sockets', 'p2p')]) broker = Popen(NODE_JS + [path_from_root('tests', 'sockets', 'p2p', 'broker', 'p2p-broker.js')]) expected = '1' self.run_browser(host_outfile, '.', ['/report_result?' + e for e in expected]) broker.kill()
def __enter__(self): print('Running background server: ' + str(self.args)) process = Popen(self.args) self.processes.append(process)
__rootpath__ = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) def path_from_root(*pathelems): return os.path.join(__rootpath__, *pathelems) sys.path += [path_from_root('')] from tools.shared import PYTHON, WINDOWS, CLANG_CPP, EMCC, PIPE from tools.shared import Popen, get_clang_native_args, get_clang_native_env temp_dir = tempfile.mkdtemp() # System info system_info = Popen([PYTHON, path_from_root('emrun'), '--system_info'], stdout=PIPE, stderr=PIPE).communicate() # Native info native_info = Popen(['clang', '-v'], stdout=PIPE, stderr=PIPE).communicate() # Emscripten info emscripten_info = Popen([PYTHON, EMCC, '-v'], stdout=PIPE, stderr=PIPE).communicate() # Run native build out_file = os.path.join(temp_dir, 'benchmark_sse1_native') if WINDOWS: out_file += '.exe' cmd = [CLANG_CPP] + get_clang_native_args() + [ path_from_root('tests', 'benchmark_sse1.cpp'), '-O3', '-o', out_file ]