summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/core/test_inlinejs3.in1
-rw-r--r--tests/core/test_inlinejs3.out1
-rwxr-xr-xtests/runner.py18
-rw-r--r--tests/test_benchmark.py1
-rw-r--r--tests/test_browser.py377
-rw-r--r--tests/test_core.py148
-rw-r--r--tests/test_other.py677
-rw-r--r--tests/test_sanity.py134
8 files changed, 644 insertions, 713 deletions
diff --git a/tests/core/test_inlinejs3.in b/tests/core/test_inlinejs3.in
index 9ddd5907..12e31007 100644
--- a/tests/core/test_inlinejs3.in
+++ b/tests/core/test_inlinejs3.in
@@ -7,6 +7,7 @@ int main(int argc, char **argv) {
for (int i = 0; i < 3; i++) {
EM_ASM(Module.print('hello dere3'); Module.print('hello dere' + 4););
}
+ EM_ASM_({ Module.print('hello input ' + $0) }, 123);
int sum = 0;
for (int i = 0; i < argc * 3; i++) {
sum += EM_ASM_INT({
diff --git a/tests/core/test_inlinejs3.out b/tests/core/test_inlinejs3.out
index c293e80b..1f64a89a 100644
--- a/tests/core/test_inlinejs3.out
+++ b/tests/core/test_inlinejs3.out
@@ -6,6 +6,7 @@ hello dere3
hello dere4
hello dere3
hello dere4
+hello input 123
i: 0,0.00
i: 1,0.08
i: 2,0.17
diff --git a/tests/runner.py b/tests/runner.py
index 501299c7..32575a1a 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -27,6 +27,19 @@ sys.path += [path_from_root(''), path_from_root('third_party/websockify')]
import tools.shared
from tools.shared import *
+# Utils
+
+def nonfastcomp(test):
+ try:
+ old_fastcomp = os.environ.get('EMCC_FAST_COMPILER')
+ os.environ['EMCC_FAST_COMPILER'] = '0'
+ test()
+ finally:
+ if old_fastcomp is None:
+ del os.environ['EMCC_FAST_COMPILER']
+ else:
+ os.environ['EMCC_FAST_COMPILER'] = old_fastcomp
+
# Sanity check for config
try:
@@ -36,10 +49,7 @@ except:
# Core test runner class, shared between normal tests and benchmarks
checked_sanity = False
-if os.environ.get('EMCC_FAST_COMPILER') == '1':
- test_modes = ['default', 'asm1', 'asm2', 'asm3', 'asm2f', 'asm2g']
-else:
- test_modes = ['default', 'o1', 'o2', 'asm1', 'asm2', 'asm3', 'asm2f', 'asm2g', 'asm2x86', 's_0_0', 's_0_1']
+test_modes = ['default', 'asm1', 'asm2', 'asm3', 'asm2f', 'asm2g', 'slow2', 'slow2asm', 's_0_0', 's_0_1']
test_index = 0
class RunnerCore(unittest.TestCase):
diff --git a/tests/test_benchmark.py b/tests/test_benchmark.py
index 023ac1e2..2bc34c60 100644
--- a/tests/test_benchmark.py
+++ b/tests/test_benchmark.py
@@ -134,7 +134,6 @@ try:
#JSBenchmarker('sm-f32-3.2', SPIDERMONKEY_ENGINE, ['-s', 'PRECISE_F32=2'], env={ 'LLVM': LLVM_3_2 }),
#JSBenchmarker('sm-f32-3.3', SPIDERMONKEY_ENGINE, ['-s', 'PRECISE_F32=2'], env={ 'LLVM': LLVM_3_3 }),
#JSBenchmarker('sm-f32-3.4', SPIDERMONKEY_ENGINE, ['-s', 'PRECISE_F32=2'], env={ 'LLVM': LLVM_3_4 }),
- #JSBenchmarker('sm-fc', SPIDERMONKEY_ENGINE, env={ 'EMCC_FAST_COMPILER': '1' }),
#JSBenchmarker('sm-noasm', SPIDERMONKEY_ENGINE + ['--no-asmjs']),
#JSBenchmarker('sm-noasm-f32', SPIDERMONKEY_ENGINE + ['--no-asmjs'], ['-s', 'PRECISE_F32=2']),
#JSBenchmarker('v8', V8_ENGINE)
diff --git a/tests/test_browser.py b/tests/test_browser.py
index c1d1caab..f2e17ea0 100644
--- a/tests/test_browser.py
+++ b/tests/test_browser.py
@@ -1,5 +1,5 @@
import BaseHTTPServer, multiprocessing, os, shutil, subprocess, unittest, zlib, webbrowser, time, shlex
-from runner import BrowserCore, path_from_root
+from runner import BrowserCore, path_from_root, nonfastcomp
from tools.shared import *
# User can specify an environment variable EMSCRIPTEN_BROWSER to force the browser test suite to
@@ -120,8 +120,6 @@ If manually bisecting:
'''
def test_emscripten_log(self):
- if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('fastcomp uses asm, where call stacks are sometimes less clear')
-
src = os.path.join(self.get_dir(), 'src.cpp')
open(src, 'w').write(self.with_report_result(open(path_from_root('tests', 'emscripten_log', 'emscripten_log.cpp')).read()))
@@ -143,191 +141,193 @@ If manually bisecting:
os.chdir(cwd)
def test_split(self):
- if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('no --split in fastcomp, deprecated')
+ def nfc():
+ # test HTML generation.
+ self.reftest(path_from_root('tests', 'htmltest.png'))
+ output = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world_sdl.cpp'), '-o', 'something.js', '--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(os.path.join(self.get_dir(), 'something_functions.js')), 'must be functions js file'
+ assert os.path.exists(os.path.join(self.get_dir(), 'something.include.html')), 'must be js include file'
- # test HTML generation.
- self.reftest(path_from_root('tests', 'htmltest.png'))
- output = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world_sdl.cpp'), '-o', 'something.js', '--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(os.path.join(self.get_dir(), 'something_functions.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('''
-
- <!doctype html>
- <html lang="en-us">
- <head>
- <meta charset="utf-8">
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
- <title>Emscripten-Generated Code</title>
- <style>
- .emscripten { padding-right: 0; margin-left: auto; margin-right: auto; display: block; }
- canvas.emscripten { border: 1px solid black; }
- textarea.emscripten { font-family: monospace; width: 80%; }
- div.emscripten { text-align: center; }
- </style>
- </head>
- <body>
- <hr/>
- <div class="emscripten" id="status">Downloading...</div>
- <div class="emscripten">
- <progress value="0" max="100" id="progress" hidden=1></progress>
- </div>
- <canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
- <hr/>
- <div class="emscripten"><input type="button" value="fullscreen" onclick="Module.requestFullScreen()"></div>
- <hr/>
- <textarea class="emscripten" id="output" rows="8"></textarea>
- <hr>
- <script type='text/javascript'>
- // connect to canvas
- var Module = {
- preRun: [],
- postRun: [],
- print: (function() {
- var element = document.getElementById('output');
- element.value = ''; // clear browser cache
- return function(text) {
- // These replacements are necessary if you render to raw HTML
- //text = text.replace(/&/g, "&amp;");
- //text = text.replace(/</g, "&lt;");
- //text = text.replace(/>/g, "&gt;");
- //text = text.replace('\\n', '<br>', 'g');
- element.value += text + "\\n";
- element.scrollTop = element.scrollHeight; // focus on bottom
- };
- })(),
- printErr: function(text) {
- if (0) { // XXX disabled for safety typeof dump == 'function') {
- dump(text + '\\n'); // fast, straight to the real console
- } else {
- console.log(text);
- }
- },
- canvas: document.getElementById('canvas'),
- setStatus: function(text) {
- if (Module.setStatus.interval) clearInterval(Module.setStatus.interval);
- var m = text.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/);
- var statusElement = document.getElementById('status');
- var progressElement = document.getElementById('progress');
- if (m) {
- text = m[1];
- progressElement.value = parseInt(m[2])*100;
- progressElement.max = parseInt(m[4])*100;
- progressElement.hidden = false;
- } else {
- progressElement.value = null;
- progressElement.max = null;
- progressElement.hidden = true;
+ open(os.path.join(self.get_dir(), 'something.html'), 'w').write('''
+
+ <!doctype html>
+ <html lang="en-us">
+ <head>
+ <meta charset="utf-8">
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <title>Emscripten-Generated Code</title>
+ <style>
+ .emscripten { padding-right: 0; margin-left: auto; margin-right: auto; display: block; }
+ canvas.emscripten { border: 1px solid black; }
+ textarea.emscripten { font-family: monospace; width: 80%; }
+ div.emscripten { text-align: center; }
+ </style>
+ </head>
+ <body>
+ <hr/>
+ <div class="emscripten" id="status">Downloading...</div>
+ <div class="emscripten">
+ <progress value="0" max="100" id="progress" hidden=1></progress>
+ </div>
+ <canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
+ <hr/>
+ <div class="emscripten"><input type="button" value="fullscreen" onclick="Module.requestFullScreen()"></div>
+ <hr/>
+ <textarea class="emscripten" id="output" rows="8"></textarea>
+ <hr>
+ <script type='text/javascript'>
+ // connect to canvas
+ var Module = {
+ preRun: [],
+ postRun: [],
+ print: (function() {
+ var element = document.getElementById('output');
+ element.value = ''; // clear browser cache
+ return function(text) {
+ // These replacements are necessary if you render to raw HTML
+ //text = text.replace(/&/g, "&amp;");
+ //text = text.replace(/</g, "&lt;");
+ //text = text.replace(/>/g, "&gt;");
+ //text = text.replace('\\n', '<br>', 'g');
+ element.value += text + "\\n";
+ element.scrollTop = element.scrollHeight; // focus on bottom
+ };
+ })(),
+ printErr: function(text) {
+ if (0) { // XXX disabled for safety typeof dump == 'function') {
+ dump(text + '\\n'); // fast, straight to the real console
+ } else {
+ console.log(text);
+ }
+ },
+ canvas: document.getElementById('canvas'),
+ setStatus: function(text) {
+ if (Module.setStatus.interval) clearInterval(Module.setStatus.interval);
+ var m = text.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/);
+ var statusElement = document.getElementById('status');
+ var progressElement = document.getElementById('progress');
+ if (m) {
+ text = m[1];
+ progressElement.value = parseInt(m[2])*100;
+ progressElement.max = parseInt(m[4])*100;
+ progressElement.hidden = false;
+ } else {
+ progressElement.value = null;
+ progressElement.max = null;
+ progressElement.hidden = true;
+ }
+ statusElement.innerHTML = text;
+ },
+ totalDependencies: 0,
+ monitorRunDependencies: function(left) {
+ this.totalDependencies = Math.max(this.totalDependencies, left);
+ Module.setStatus(left ? 'Preparing... (' + (this.totalDependencies-left) + '/' + this.totalDependencies + ')' : 'All downloads complete.');
}
- statusElement.innerHTML = text;
- },
- totalDependencies: 0,
- monitorRunDependencies: function(left) {
- this.totalDependencies = Math.max(this.totalDependencies, left);
- Module.setStatus(left ? 'Preparing... (' + (this.totalDependencies-left) + '/' + this.totalDependencies + ')' : 'All downloads complete.');
- }
- };
- Module.setStatus('Downloading...');
- </script>''' + open(os.path.join(self.get_dir(), 'something.include.html')).read() + '''
- </body>
- </html>
- ''')
+ };
+ Module.setStatus('Downloading...');
+ </script>''' + open(os.path.join(self.get_dir(), 'something.include.html')).read() + '''
+ </body>
+ </html>
+ ''')
- self.run_browser('something.html', 'You should see "hello, world!" and a colored cube.', '/report_result?0')
+ self.run_browser('something.html', 'You should see "hello, world!" and a colored cube.', '/report_result?0')
+
+ nonfastcomp(nfc)
def test_split_in_source_filenames(self):
- if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('no --split in fastcomp, deprecated')
-
- 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(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('''
-
- <!doctype html>
- <html lang="en-us">
- <head>
- <meta charset="utf-8">
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
- <title>Emscripten-Generated Code</title>
- <style>
- .emscripten { padding-right: 0; margin-left: auto; margin-right: auto; display: block; }
- canvas.emscripten { border: 1px solid black; }
- textarea.emscripten { font-family: monospace; width: 80%; }
- div.emscripten { text-align: center; }
- </style>
- </head>
- <body>
- <hr/>
- <div class="emscripten" id="status">Downloading...</div>
- <div class="emscripten">
- <progress value="0" max="100" id="progress" hidden=1></progress>
- </div>
- <canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
- <hr/>
- <div class="emscripten"><input type="button" value="fullscreen" onclick="Module.requestFullScreen()"></div>
- <hr/>
- <textarea class="emscripten" id="output" rows="8"></textarea>
- <hr>
- <script type='text/javascript'>
- // connect to canvas
- var Module = {
- preRun: [],
- postRun: [],
- print: (function() {
- var element = document.getElementById('output');
- element.value = ''; // clear browser cache
- return function(text) {
- // These replacements are necessary if you render to raw HTML
- //text = text.replace(/&/g, "&amp;");
- //text = text.replace(/</g, "&lt;");
- //text = text.replace(/>/g, "&gt;");
- //text = text.replace('\\n', '<br>', 'g');
- element.value += text + "\\n";
- element.scrollTop = element.scrollHeight; // focus on bottom
- };
- })(),
- printErr: function(text) {
- if (0) { // XXX disabled for safety typeof dump == 'function') {
- dump(text + '\\n'); // fast, straight to the real console
- } else {
- console.log(text);
- }
- },
- canvas: document.getElementById('canvas'),
- setStatus: function(text) {
- if (Module.setStatus.interval) clearInterval(Module.setStatus.interval);
- var m = text.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/);
- var statusElement = document.getElementById('status');
- var progressElement = document.getElementById('progress');
- if (m) {
- text = m[1];
- progressElement.value = parseInt(m[2])*100;
- progressElement.max = parseInt(m[4])*100;
- progressElement.hidden = false;
- } else {
- progressElement.value = null;
- progressElement.max = null;
- progressElement.hidden = true;
+ def nfc():
+ 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(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('''
+
+ <!doctype html>
+ <html lang="en-us">
+ <head>
+ <meta charset="utf-8">
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <title>Emscripten-Generated Code</title>
+ <style>
+ .emscripten { padding-right: 0; margin-left: auto; margin-right: auto; display: block; }
+ canvas.emscripten { border: 1px solid black; }
+ textarea.emscripten { font-family: monospace; width: 80%; }
+ div.emscripten { text-align: center; }
+ </style>
+ </head>
+ <body>
+ <hr/>
+ <div class="emscripten" id="status">Downloading...</div>
+ <div class="emscripten">
+ <progress value="0" max="100" id="progress" hidden=1></progress>
+ </div>
+ <canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
+ <hr/>
+ <div class="emscripten"><input type="button" value="fullscreen" onclick="Module.requestFullScreen()"></div>
+ <hr/>
+ <textarea class="emscripten" id="output" rows="8"></textarea>
+ <hr>
+ <script type='text/javascript'>
+ // connect to canvas
+ var Module = {
+ preRun: [],
+ postRun: [],
+ print: (function() {
+ var element = document.getElementById('output');
+ element.value = ''; // clear browser cache
+ return function(text) {
+ // These replacements are necessary if you render to raw HTML
+ //text = text.replace(/&/g, "&amp;");
+ //text = text.replace(/</g, "&lt;");
+ //text = text.replace(/>/g, "&gt;");
+ //text = text.replace('\\n', '<br>', 'g');
+ element.value += text + "\\n";
+ element.scrollTop = element.scrollHeight; // focus on bottom
+ };
+ })(),
+ printErr: function(text) {
+ if (0) { // XXX disabled for safety typeof dump == 'function') {
+ dump(text + '\\n'); // fast, straight to the real console
+ } else {
+ console.log(text);
+ }
+ },
+ canvas: document.getElementById('canvas'),
+ setStatus: function(text) {
+ if (Module.setStatus.interval) clearInterval(Module.setStatus.interval);
+ var m = text.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/);
+ var statusElement = document.getElementById('status');
+ var progressElement = document.getElementById('progress');
+ if (m) {
+ text = m[1];
+ progressElement.value = parseInt(m[2])*100;
+ progressElement.max = parseInt(m[4])*100;
+ progressElement.hidden = false;
+ } else {
+ progressElement.value = null;
+ progressElement.max = null;
+ progressElement.hidden = true;
+ }
+ statusElement.innerHTML = text;
+ },
+ totalDependencies: 0,
+ monitorRunDependencies: function(left) {
+ this.totalDependencies = Math.max(this.totalDependencies, left);
+ Module.setStatus(left ? 'Preparing... (' + (this.totalDependencies-left) + '/' + this.totalDependencies + ')' : 'All downloads complete.');
}
- statusElement.innerHTML = text;
- },
- totalDependencies: 0,
- monitorRunDependencies: function(left) {
- this.totalDependencies = Math.max(this.totalDependencies, left);
- Module.setStatus(left ? 'Preparing... (' + (this.totalDependencies-left) + '/' + this.totalDependencies + ')' : 'All downloads complete.');
- }
- };
- Module.setStatus('Downloading...');
- </script>''' + open(os.path.join(self.get_dir(), 'something.include.html')).read() + '''
- </body>
- </html>
- ''')
+ };
+ Module.setStatus('Downloading...');
+ </script>''' + open(os.path.join(self.get_dir(), 'something.include.html')).read() + '''
+ </body>
+ </html>
+ ''')
- self.run_browser('something.html', 'You should see "hello, world!" and a colored cube.', '/report_result?0')
+ self.run_browser('something.html', 'You should see "hello, world!" and a colored cube.', '/report_result?0')
+
+ nonfastcomp(nfc)
def test_compression(self):
open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write(self.with_report_result(r'''
@@ -1495,11 +1495,6 @@ keydown(100);keyup(100); // trigger the end
def test_sdl_resize(self):
self.btest('sdl_resize.c', '1')
- def test_gc(self):
- if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('flaky in fastcomp and also non-fastcomp -O1, timing issues')
-
- self.btest('browser_gc.cpp', '1')
-
def test_glshaderinfo(self):
self.btest('glshaderinfo.cpp', '1')
@@ -1706,7 +1701,7 @@ void *getBindBuffer() {
self.btest('s3tc_crunch.c', reference='s3tc_crunch.png', reference_slack=11, args=['--pre-js', 'asset_a.js', '--pre-js', 'asset_b.js', '-s', 'LEGACY_GL_EMULATION=1'])
def test_aniso(self):
- if SPIDERMONKEY_ENGINE in JS_ENGINES and os.environ.get('EMCC_FAST_COMPILER') != '1':
+ if SPIDERMONKEY_ENGINE in JS_ENGINES:
# asm.js-ification check
Popen([PYTHON, EMCC, path_from_root('tests', 'aniso.c'), '-O2', '-g2', '-s', 'LEGACY_GL_EMULATION=1']).communicate()
Settings.ASM_JS = 1
@@ -1766,10 +1761,10 @@ void *getBindBuffer() {
self.btest('http.cpp', expected='0', args=['-I' + path_from_root('tests')])
def test_module(self):
- if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp')
-
- Popen([PYTHON, EMCC, path_from_root('tests', 'browser_module.cpp'), '-o', 'module.js', '-O2', '-s', 'SIDE_MODULE=1', '-s', 'DLOPEN_SUPPORT=1', '-s', 'EXPORTED_FUNCTIONS=["_one", "_two"]']).communicate()
- self.btest('browser_main.cpp', args=['-O2', '-s', 'MAIN_MODULE=1', '-s', 'DLOPEN_SUPPORT=1'], expected='8')
+ def nfc():
+ Popen([PYTHON, EMCC, path_from_root('tests', 'browser_module.cpp'), '-o', 'module.js', '-O2', '-s', 'SIDE_MODULE=1', '-s', 'DLOPEN_SUPPORT=1', '-s', 'EXPORTED_FUNCTIONS=["_one", "_two"]']).communicate()
+ self.btest('browser_main.cpp', args=['-O2', '-s', 'MAIN_MODULE=1', '-s', 'DLOPEN_SUPPORT=1'], expected='8')
+ nonfastcomp(nfc)
def test_mmap_file(self):
open(self.in_dir('data.dat'), 'w').write('data from the file ' + ('.' * 9000))
diff --git a/tests/test_core.py b/tests/test_core.py
index c4bfcfa3..19bb9ca1 100644
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -512,33 +512,45 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co
self.do_run(open(path_from_root('tests', 'cube2md5.cpp')).read(), open(path_from_root('tests', 'cube2md5.ok')).read())
def test_cube2hash(self):
- try:
- old_chunk_size = os.environ.get('EMSCRIPT_MAX_CHUNK_SIZE') or ''
- os.environ['EMSCRIPT_MAX_CHUNK_SIZE'] = '1' # test splitting out each function to a chunk in emscripten.py (21 functions here)
-
- # A good test of i64 math
- if Settings.USE_TYPED_ARRAYS != 2: return self.skip('requires ta2 C-style memory aliasing')
- self.do_run('', 'Usage: hashstring <seed>',
- libraries=self.get_library('cube2hash', ['cube2hash.bc'], configure=None),
- includes=[path_from_root('tests', 'cube2hash')])
-
- for text, output in [('fleefl', '892BDB6FD3F62E863D63DA55851700FDE3ACF30204798CE9'),
- ('fleefl2', 'AA2CC5F96FC9D540CA24FDAF1F71E2942753DB83E8A81B61'),
- ('64bitisslow', '64D8470573635EC354FEE7B7F87C566FCAF1EFB491041670')]:
- self.do_run('', 'hash value: ' + output, [text], no_build=True)
- finally:
- os.environ['EMSCRIPT_MAX_CHUNK_SIZE'] = old_chunk_size
-
- assert 'asm1' in test_modes
- if self.run_name == 'asm1' and not os.environ.get('EMCC_FAST_COMPILER'):
- assert Settings.RELOOP
- generated = open('src.cpp.o.js').read()
- main = generated[generated.find('function _main'):]
- main = main[:main.find('\n}')]
- num_vars = 0
- for v in re.findall('var [^;]+;', main):
- num_vars += v.count(',') + 1
- assert num_vars == 10, 'no variable elimination should have been run, but seeing %d' % num_vars
+ # extra testing for various codegen modes
+ for x86 in [0, 1] if self.run_name == 'asm2' else [0]:
+ print 'x86', x86
+ try:
+ old_x86 = os.environ.get('EMCC_LLVM_TARGET') or ''
+ if x86:
+ os.environ['EMCC_LLVM_TARGET'] = "i386-pc-linux-gnu"
+ try:
+ old_fastcomp = os.environ.get('EMCC_FAST_COMPILER') or ''
+ if x86:
+ os.environ['EMCC_FAST_COMPILER'] = "0"
+ try:
+ old_chunk_size = os.environ.get('EMSCRIPT_MAX_CHUNK_SIZE') or ''
+ os.environ['EMSCRIPT_MAX_CHUNK_SIZE'] = '1' # test splitting out each function to a chunk in emscripten.py (21 functions here)
+
+ # A good test of i64 math
+ if Settings.USE_TYPED_ARRAYS != 2: return self.skip('requires ta2 C-style memory aliasing')
+ self.do_run('', 'Usage: hashstring <seed>',
+ libraries=self.get_library('cube2hash', ['cube2hash.bc'], configure=None, cache_name_extra=str(x86)),
+ includes=[path_from_root('tests', 'cube2hash')])
+
+ for text, output in [('fleefl', '892BDB6FD3F62E863D63DA55851700FDE3ACF30204798CE9'),
+ ('fleefl2', 'AA2CC5F96FC9D540CA24FDAF1F71E2942753DB83E8A81B61'),
+ ('64bitisslow', '64D8470573635EC354FEE7B7F87C566FCAF1EFB491041670')]:
+ self.do_run('', 'hash value: ' + output, [text], no_build=True)
+ finally:
+ os.environ['EMSCRIPT_MAX_CHUNK_SIZE'] = old_chunk_size
+ finally:
+ if x86:
+ if old_fastcomp:
+ os.environ['EMCC_FAST_COMPILER'] = old_fastcomp
+ else:
+ del os.environ['EMCC_FAST_COMPILER']
+ finally:
+ if x86:
+ if old_x86:
+ os.environ['EMCC_LLVM_TARGET'] = old_x86
+ else:
+ del os.environ['EMCC_LLVM_TARGET']
def test_unaligned(self):
if Settings.QUANTUM_SIZE == 1: return self.skip('No meaning to unaligned addresses in q1')
@@ -951,7 +963,7 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co
for named in (0, 1):
print named
- if os.environ.get('EMCC_FAST_COMPILER') == '1' and named: continue # no named globals in fastcomp
+ if os.environ.get('EMCC_FAST_COMPILER') != '0' and named: continue # no named globals in fastcomp
Settings.NAMED_GLOBALS = named
self.do_run_from_file(src, output, ['wowie', 'too', '74'])
@@ -1138,7 +1150,7 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co
self.do_run_from_file(src, output)
def test_longjmp_repeat(self):
- if os.environ.get('EMCC_FAST_COMPILER') != '1': Settings.MAX_SETJMPS = 1 # todo: do this more strict thing in fastcomp too
+ if os.environ.get('EMCC_FAST_COMPILER') == '0': Settings.MAX_SETJMPS = 1 # todo: do this more strict thing in fastcomp too
test_path = path_from_root('tests', 'core', 'test_longjmp_repeat')
src, output = (test_path + s for s in ('.in', '.out'))
self.do_run_from_file(src, output)
@@ -1162,7 +1174,7 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co
self.do_run_from_file(src, output)
def test_setjmp_many(self):
- if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp: make MAX_SETJMPS take effect')
+ if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('todo in fastcomp: make MAX_SETJMPS take effect')
src = r'''
#include <stdio.h>
@@ -1930,7 +1942,7 @@ def process(filename):
def test_inlinejs(self):
if not self.is_le32(): return self.skip('le32 needed for inline js')
- if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('fastcomp only supports EM_ASM')
+ if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('fastcomp only supports EM_ASM')
test_path = path_from_root('tests', 'core', 'test_inlinejs')
src, output = (test_path + s for s in ('.in', '.out'))
@@ -1943,7 +1955,7 @@ def process(filename):
def test_inlinejs2(self):
if not self.is_le32(): return self.skip('le32 needed for inline js')
- if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('fastcomp only supports EM_ASM')
+ if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('fastcomp only supports EM_ASM')
test_path = path_from_root('tests', 'core', 'test_inlinejs2')
src, output = (test_path + s for s in ('.in', '.out'))
@@ -2749,7 +2761,7 @@ The current type of b is: 9
self.do_run(main, 'supp: 54,2\nmain: 56\nsupp see: 543\nmain see: 76\nok.')
def can_dlfcn(self):
- if os.environ.get('EMCC_FAST_COMPILER') == '1':
+ if os.environ.get('EMCC_FAST_COMPILER') != '0':
self.skip('todo in fastcomp')
return False
@@ -3171,7 +3183,7 @@ def process(filename):
def test_dlfcn_self(self):
if Settings.USE_TYPED_ARRAYS == 1: return self.skip('Does not work with USE_TYPED_ARRAYS=1')
- if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp')
+ if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('todo in fastcomp')
Settings.DLOPEN_SUPPORT = 1
def post(filename):
@@ -4673,25 +4685,6 @@ return malloc(size);
main = main[:main.find('\n}')]
assert main.count('\n') <= 7, ('must not emit too many postSets: %d' % main.count('\n')) + ' : ' + main
- if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('fastcomp always aliases pointers')
-
- assert 'asm2g' in test_modes
- if self.run_name == 'asm2g':
- results = {}
- original = open('src.cpp.o.js').read()
- results[Settings.ALIASING_FUNCTION_POINTERS] = len(original)
- Settings.ALIASING_FUNCTION_POINTERS = 1 - Settings.ALIASING_FUNCTION_POINTERS
- self.do_run(path_from_root('tests', 'cubescript'), '*\nTemp is 33\n9\n5\nhello, everyone\n*', main_file='command.cpp')
- final = open('src.cpp.o.js').read()
- results[Settings.ALIASING_FUNCTION_POINTERS] = len(final)
- open('original.js', 'w').write(original)
- print results
- assert results[1] < 0.99*results[0]
- assert ' & 3]()' in original, 'small function table exists'
- assert ' & 3]()' not in final, 'small function table does not exist'
- assert ' & 255]()' not in original, 'big function table does not exist'
- assert ' & 255]()' in final, 'big function table exists'
-
def test_simd(self):
if Settings.USE_TYPED_ARRAYS != 2: return self.skip('needs ta2')
if Settings.ASM_JS: Settings.ASM_JS = 2 # does not validate
@@ -4721,7 +4714,7 @@ return malloc(size);
self.do_run_from_file(src, output)
def test_gcc_unmangler(self):
- if os.environ.get('EMCC_FAST_COMPILER') != '1': Settings.NAMED_GLOBALS = 1 # test coverage for this; fastcomp never names globals
+ if os.environ.get('EMCC_FAST_COMPILER') == '0': Settings.NAMED_GLOBALS = 1 # test coverage for this; fastcomp never names globals
Building.COMPILER_TEST_OPTS += ['-I' + path_from_root('third_party'), '-Wno-warn-absolute-paths']
@@ -4892,7 +4885,7 @@ def process(filename):
test()
assert 'asm2g' in test_modes
- if self.run_name == 'asm2g' and not use_cmake and os.environ.get('EMCC_FAST_COMPILER') != '1':
+ if self.run_name == 'asm2g' and not use_cmake and os.environ.get('EMCC_FAST_COMPILER') == '0':
# Test forced alignment
print >> sys.stderr, 'testing FORCE_ALIGNED_MEMORY'
old = open('src.cpp.o.js').read()
@@ -5125,7 +5118,7 @@ def process(filename):
for name in glob.glob(path_from_root('tests', 'cases', '*.ll')):
shortname = name.replace('.ll', '')
if '' not in shortname: continue
- if os.environ.get('EMCC_FAST_COMPILER') == '1' and os.path.basename(shortname) in [
+ if os.environ.get('EMCC_FAST_COMPILER') != '0' and os.path.basename(shortname) in [
'structparam', 'extendedprecision', 'issue_39', 'emptystruct', 'phinonexist', 'quotedlabel', 'oob_ta2', 'phientryimplicit', 'phiself', 'invokebitcast', 'funcptr', # invalid ir
'structphiparam', 'callwithstructural_ta2', 'callwithstructural64_ta2', 'structinparam', # pnacl limitations in ExpandStructRegs
'2xi40', # pnacl limitations in ExpandGetElementPtr
@@ -5141,7 +5134,7 @@ def process(filename):
if '_le32' in shortname and not self.is_le32():
print self.skip('case "%s" not relevant for non-le32 target' % shortname)
continue
- if '_fastcomp' in shortname and not os.environ.get('EMCC_FAST_COMPILER') == '1':
+ if '_fastcomp' in shortname and not os.environ.get('EMCC_FAST_COMPILER') != '0':
print self.skip('case "%s" not relevant for non-fastcomp' % shortname)
continue
self.emcc_args = emcc_args
@@ -5180,7 +5173,7 @@ def process(filename):
for name in glob.glob(path_from_root('tests', 'fuzz', '*.c')) + glob.glob(path_from_root('tests', 'fuzz', '*.cpp')):
#if os.path.basename(name) != '4.c': continue
if 'newfail' in name: continue
- if os.path.basename(name) == '18.cpp' and not os.environ.get('EMCC_FAST_COMPILER') == '1': continue # works only in fastcomp
+ if os.path.basename(name) == '18.cpp' and not os.environ.get('EMCC_FAST_COMPILER') != '0': continue # works only in fastcomp
print name
self.do_run(open(path_from_root('tests', 'fuzz', name)).read(),
@@ -5420,7 +5413,7 @@ def process(filename):
def test_asm_pgo(self):
if not Settings.ASM_JS: return self.skip('this is a test for PGO for asm (NB: not *in* asm)')
- if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp')
+ if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('todo in fastcomp')
src = open(path_from_root('tests', 'hello_libcxx.cpp')).read()
output = 'hello, world!'
@@ -5540,7 +5533,7 @@ def process(filename):
def test_embind(self):
if self.emcc_args is None: return self.skip('requires emcc')
- if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp')
+ if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('todo in fastcomp')
Building.COMPILER_TEST_OPTS += ['--bind']
src = r'''
@@ -5563,7 +5556,7 @@ def process(filename):
def test_embind_2(self):
if self.emcc_args is None: return self.skip('requires emcc')
- if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp')
+ if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('todo in fastcomp')
Building.COMPILER_TEST_OPTS += ['--bind', '--post-js', 'post.js']
open('post.js', 'w').write('''
Module.print('lerp ' + Module.lerp(1, 2, 0.66) + '.');
@@ -5637,8 +5630,6 @@ def process(filename):
# Way 2: use CppHeaderParser
- Settings.RUNTIME_TYPE_INFO = 1
-
header = '''
#include <stdio.h>
@@ -5879,6 +5870,8 @@ def process(filename):
self.do_run(src, '|hello|43|world|41|', post_build=post)
def test_typeinfo(self):
+ if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('fastcomp does not support RUNTIME_TYPE_INFO')
+
if self.emcc_args is not None and self.emcc_args != []: return self.skip('full LLVM opts optimize out all the code that uses the type')
Settings.RUNTIME_TYPE_INFO = 1
@@ -6397,7 +6390,7 @@ def process(filename):
def test_minmax(self):
if self.emcc_args == None: return self.skip('needs emcc')
- if os.environ.get('EMCC_FAST_COMPILER') != '1': return self.skip('this test will not pass in the old compiler')
+ if os.environ.get('EMCC_FAST_COMPILER') == '0': return self.skip('this test will not pass in the old compiler')
self.do_run(open(path_from_root('tests', 'test_minmax.c')).read(), 'NAN != NAN\nSuccess!')
def test_locale(self):
@@ -6460,6 +6453,7 @@ def make_run(fullname, name=-1, compiler=-1, embetter=0, quantum_size=0,
return
# TODO: Move much of these to a init() function in shared.py, and reuse that
+ Settings.ASM_JS = 0
Settings.USE_TYPED_ARRAYS = typed_arrays
Settings.INVOKE_RUN = 1
Settings.RELOOP = 0 # we only do them in the "o2" pass
@@ -6487,27 +6481,19 @@ def make_run(fullname, name=-1, compiler=-1, embetter=0, quantum_size=0,
return TT
-# Make one run with the defaults
-default = make_run("default", compiler=CLANG, emcc_args=[] if os.environ.get('EMCC_FAST_COMPILER') != '1' else ['-s', 'ASM_JS=1'])
-
-# Make one run with -O1, with safe heap
-o1 = make_run("o1", compiler=CLANG, emcc_args=["-O1", "-s", "ASM_JS=0", "-s", "SAFE_HEAP=1"])
-
-# Make one run with -O2, but without closure (we enable closure in specific tests, otherwise on everything it is too slow)
-o2 = make_run("o2", compiler=CLANG, emcc_args=["-O2", "-s", "ASM_JS=0", "-s", "JS_CHUNK_SIZE=1024"])
-
-# asm.js
+# Main test modes
+default = make_run("default", compiler=CLANG, emcc_args=[])
asm1 = make_run("asm1", compiler=CLANG, emcc_args=["-O1"])
asm2 = make_run("asm2", compiler=CLANG, emcc_args=["-O2"])
asm3 = make_run("asm3", compiler=CLANG, emcc_args=["-O3"])
asm2f = make_run("asm2f", compiler=CLANG, emcc_args=["-O2", "-s", "PRECISE_F32=1"])
-if os.environ.get('EMCC_FAST_COMPILER') == '1':
- asm2g = make_run("asm2g", compiler=CLANG, emcc_args=["-O2", "-g", "-s", "ASSERTIONS=1", "--memory-init-file", "1", "-s", "SAFE_HEAP=1"])
-else:
- asm2g = make_run("asm2g", compiler=CLANG, emcc_args=["-O2", "-g", "-s", "ASSERTIONS=1", "--memory-init-file", "1", "-s", "CHECK_HEAP_ALIGN=1"])
-asm2x86 = make_run("asm2x86", compiler=CLANG, emcc_args=["-O2", "-g", "-s", "CHECK_HEAP_ALIGN=1"], env={"EMCC_LLVM_TARGET": "i386-pc-linux-gnu"})
+asm2g = make_run("asm2g", compiler=CLANG, emcc_args=["-O2", "-g", "-s", "ASSERTIONS=1", "--memory-init-file", "1", "-s", "SAFE_HEAP=1"])
+
+# Legacy test modes -
+slow2 = make_run("slow2", compiler=CLANG, emcc_args=["-O2", "-s", "ASM_JS=0"], env={"EMCC_FAST_COMPILER": "0"})
+slow2asm = make_run("slow2asm", compiler=CLANG, emcc_args=["-O2"], env={"EMCC_FAST_COMPILER": "0"})
-# Make custom runs with various options
+# Legacy test modes - very old
for compiler, quantum, embetter, typed_arrays in [
(CLANG, 4, 0, 0),
(CLANG, 4, 1, 1),
@@ -6515,6 +6501,6 @@ for compiler, quantum, embetter, typed_arrays in [
fullname = 's_0_%d%s%s' % (
embetter, '' if quantum == 4 else '_q' + str(quantum), '' if typed_arrays in [0, 1] else '_t' + str(typed_arrays)
)
- locals()[fullname] = make_run(fullname, fullname, compiler, embetter, quantum, typed_arrays)
+ locals()[fullname] = make_run(fullname, fullname, compiler, embetter, quantum, typed_arrays, env={"EMCC_FAST_COMPILER": "0"})
del T # T is just a shape for the specific subclasses, we don't test it itself
diff --git a/tests/test_other.py b/tests/test_other.py
index 80461972..69f8d5c0 100644
--- a/tests/test_other.py
+++ b/tests/test_other.py
@@ -1,7 +1,7 @@
import multiprocessing, os, re, shutil, subprocess, sys
import tools.shared
from tools.shared import *
-from runner import RunnerCore, path_from_root, get_bullet_library
+from runner import RunnerCore, path_from_root, get_bullet_library, nonfastcomp
class other(RunnerCore):
def get_zlib_library(self):
@@ -207,7 +207,7 @@ Options that are modified or new in %s include:
]:
print params, text
self.clear()
- if os.environ.get('EMCC_FAST_COMPILER') == '1' and ['disable typed arrays', 'typed arrays 1 selected']: continue
+ if os.environ.get('EMCC_FAST_COMPILER') != '0' and ['disable typed arrays', 'typed arrays 1 selected']: continue
output = Popen([PYTHON, compiler, path_from_root('tests', 'hello_world_loop.cpp'), '-o', 'a.out.js'] + params, stdout=PIPE, stderr=PIPE).communicate()
assert len(output[0]) == 0, output[0]
assert os.path.exists('a.out.js'), '\n'.join(output)
@@ -277,6 +277,9 @@ f.close()
# TODO: test normal project linking, static and dynamic: get_library should not need to be told what to link!
# TODO: deprecate llvm optimizations, dlmalloc, etc. in emscripten.py.
+ def test_emcc_nonfastcomp(self):
+ nonfastcomp(self.test_emcc)
+
def test_cmake(self):
# Test all supported generators.
if WINDOWS:
@@ -451,48 +454,48 @@ f.close()
self.assertContained('hello, world!', run_js(os.path.join(self.get_dir(), 'a.out.js')))
def test_unaligned_memory(self):
- if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp')
-
- open(os.path.join(self.get_dir(), 'test.cpp'), 'w').write(r'''
- #include <stdio.h>
- #include <stdarg.h>
+ def test():
+ open(os.path.join(self.get_dir(), 'test.cpp'), 'w').write(r'''
+ #include <stdio.h>
+ #include <stdarg.h>
- typedef unsigned char Bit8u;
- typedef unsigned short Bit16u;
- typedef unsigned int Bit32u;
+ typedef unsigned char Bit8u;
+ typedef unsigned short Bit16u;
+ typedef unsigned int Bit32u;
- int main()
- {
- va_list argp;
- va_arg(argp, char *); // check for compilation error, #1705
+ int main()
+ {
+ va_list argp;
+ va_arg(argp, char *); // check for compilation error, #1705
- Bit8u data[4] = {0x01,0x23,0x45,0x67};
+ Bit8u data[4] = {0x01,0x23,0x45,0x67};
- printf("data: %x\n", *(Bit32u*)data);
- printf("data[0,1] 16bit: %x\n", *(Bit16u*)data);
- printf("data[1,2] 16bit: %x\n", *(Bit16u*)(data+1));
- }
- ''')
- Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'test.cpp'), '-s', 'UNALIGNED_MEMORY=1']).communicate()
- self.assertContained('data: 67452301\ndata[0,1] 16bit: 2301\ndata[1,2] 16bit: 4523', run_js(os.path.join(self.get_dir(), 'a.out.js')))
+ printf("data: %x\n", *(Bit32u*)data);
+ printf("data[0,1] 16bit: %x\n", *(Bit16u*)data);
+ printf("data[1,2] 16bit: %x\n", *(Bit16u*)(data+1));
+ }
+ ''')
+ Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'test.cpp'), '-s', 'UNALIGNED_MEMORY=1']).communicate()
+ self.assertContained('data: 67452301\ndata[0,1] 16bit: 2301\ndata[1,2] 16bit: 4523', run_js(os.path.join(self.get_dir(), 'a.out.js')))
+ nonfastcomp(test)
def test_unaligned_memory_2(self):
- if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp')
-
- open(os.path.join(self.get_dir(), 'test.cpp'), 'w').write(r'''
- #include <string>
- #include <stdio.h>
+ def test():
+ open(os.path.join(self.get_dir(), 'test.cpp'), 'w').write(r'''
+ #include <string>
+ #include <stdio.h>
- int main( int argc, char ** argv )
- {
- std::string testString( "Hello, World!" );
+ int main( int argc, char ** argv )
+ {
+ std::string testString( "Hello, World!" );
- printf( "testString = %s\n", testString.c_str() );
- return 0;
- }
- ''')
- Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'test.cpp'), '-s', 'UNALIGNED_MEMORY=1']).communicate()
- self.assertContained('testString = Hello, World!', run_js(os.path.join(self.get_dir(), 'a.out.js')))
+ printf( "testString = %s\n", testString.c_str() );
+ return 0;
+ }
+ ''')
+ Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'test.cpp'), '-s', 'UNALIGNED_MEMORY=1']).communicate()
+ self.assertContained('testString = Hello, World!', run_js(os.path.join(self.get_dir(), 'a.out.js')))
+ nonfastcomp(test)
def test_asm_minify(self):
def test(args):
@@ -542,7 +545,7 @@ f.close()
self.assertContained(expected, run_js(self.in_dir('a.out.js'), stderr=PIPE, full_output=True))
return open(self.in_dir('a.out.js')).read()
- if os.environ.get('EMCC_FAST_COMPILER') != '1':
+ if os.environ.get('EMCC_FAST_COMPILER') == '0':
test([], 'my func') # no asm, so casting func works
test(['-O2'], 'abort', ['Casting potentially incompatible function pointer i32 ()* to void (...)*, for my_func',
'Incompatible function pointer casts are very dangerous with ASM_JS=1, you should investigate and correct these']) # asm, so failure
@@ -590,283 +593,285 @@ This pointer might make sense in another type signature: i: _my_func
assert not os.path.exists('a.out') and not os.path.exists('a.exe'), 'Must not leave unneeded linker stubs'
def test_static_link(self):
- if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp')
-
- def test(name, header, main, side, expected, args=[], suffix='cpp', first=True):
- print name
- #t = main ; main = side ; side = t
- original_main = main
- original_side = side
- if header: open(os.path.join(self.get_dir(), 'header.h'), 'w').write(header)
- if type(main) == str:
- open(os.path.join(self.get_dir(), 'main.' + suffix), 'w').write(main)
- main = ['main.' + suffix]
- if type(side) == str:
- open(os.path.join(self.get_dir(), 'side.' + suffix), 'w').write(side)
- side = ['side.' + suffix]
- Popen([PYTHON, EMCC] + side + ['-o', 'side.js', '-s', 'SIDE_MODULE=1', '-O2'] + args).communicate()
- # TODO: test with and without DISABLE_GL_EMULATION, check that file sizes change
- Popen([PYTHON, EMCC] + main + ['-o', 'main.js', '-s', 'MAIN_MODULE=1', '-O2', '-s', 'DISABLE_GL_EMULATION=1'] + args).communicate()
- Popen([PYTHON, EMLINK, 'main.js', 'side.js', 'together.js'], stdout=PIPE).communicate()
- assert os.path.exists('together.js')
- for engine in JS_ENGINES:
- out = run_js('together.js', engine=engine, stderr=PIPE, full_output=True)
- self.assertContained(expected, out)
- if engine == SPIDERMONKEY_ENGINE: self.validate_asmjs(out)
- if first:
- shutil.copyfile('together.js', 'first.js')
- test(name + ' (reverse)', header, original_side, original_main, expected, args, suffix, False) # test reverse order
-
- # test a simple call from one module to another. only one has a string (and constant memory initialization for it)
- test('basics', '', '''
- #include <stdio.h>
- extern int sidey();
- int main() {
- printf("other says %d.", sidey());
- return 0;
- }
- ''', '''
- int sidey() { return 11; }
- ''', 'other says 11.')
-
- # finalization of float variables should pass asm.js validation
- test('floats', '', '''
- #include <stdio.h>
- extern float sidey();
- int main() {
- printf("other says %.2f.", sidey()+1);
- return 0;
- }
- ''', '''
- float sidey() { return 11.5; }
- ''', 'other says 12.50')
+ def nonfc():
+ if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('todo in fastcomp')
+
+ def test(name, header, main, side, expected, args=[], suffix='cpp', first=True):
+ print name
+ #t = main ; main = side ; side = t
+ original_main = main
+ original_side = side
+ if header: open(os.path.join(self.get_dir(), 'header.h'), 'w').write(header)
+ if type(main) == str:
+ open(os.path.join(self.get_dir(), 'main.' + suffix), 'w').write(main)
+ main = ['main.' + suffix]
+ if type(side) == str:
+ open(os.path.join(self.get_dir(), 'side.' + suffix), 'w').write(side)
+ side = ['side.' + suffix]
+ Popen([PYTHON, EMCC] + side + ['-o', 'side.js', '-s', 'SIDE_MODULE=1', '-O2'] + args).communicate()
+ # TODO: test with and without DISABLE_GL_EMULATION, check that file sizes change
+ Popen([PYTHON, EMCC] + main + ['-o', 'main.js', '-s', 'MAIN_MODULE=1', '-O2', '-s', 'DISABLE_GL_EMULATION=1'] + args).communicate()
+ Popen([PYTHON, EMLINK, 'main.js', 'side.js', 'together.js'], stdout=PIPE).communicate()
+ assert os.path.exists('together.js')
+ for engine in JS_ENGINES:
+ out = run_js('together.js', engine=engine, stderr=PIPE, full_output=True)
+ self.assertContained(expected, out)
+ if engine == SPIDERMONKEY_ENGINE: self.validate_asmjs(out)
+ if first:
+ shutil.copyfile('together.js', 'first.js')
+ test(name + ' (reverse)', header, original_side, original_main, expected, args, suffix, False) # test reverse order
+
+ # test a simple call from one module to another. only one has a string (and constant memory initialization for it)
+ test('basics', '', '''
+ #include <stdio.h>
+ extern int sidey();
+ int main() {
+ printf("other says %d.", sidey());
+ return 0;
+ }
+ ''', '''
+ int sidey() { return 11; }
+ ''', 'other says 11.')
- # memory initialization in both
- test('multiple memory inits', '', r'''
- #include <stdio.h>
- extern void sidey();
- int main() {
- printf("hello from main\n");
- sidey();
- return 0;
- }
- ''', r'''
- #include <stdio.h>
- void sidey() { printf("hello from side\n"); }
- ''', 'hello from main\nhello from side\n')
+ # finalization of float variables should pass asm.js validation
+ test('floats', '', '''
+ #include <stdio.h>
+ extern float sidey();
+ int main() {
+ printf("other says %.2f.", sidey()+1);
+ return 0;
+ }
+ ''', '''
+ float sidey() { return 11.5; }
+ ''', 'other says 12.50')
- # function pointers
- test('fp1', 'typedef void (*voidfunc)();', r'''
- #include <stdio.h>
- #include "header.h"
- voidfunc sidey(voidfunc f);
- void a() { printf("hello from funcptr\n"); }
- int main() {
- sidey(a)();
- return 0;
- }
- ''', '''
- #include "header.h"
- voidfunc sidey(voidfunc f) { return f; }
- ''', 'hello from funcptr\n')
+ # memory initialization in both
+ test('multiple memory inits', '', r'''
+ #include <stdio.h>
+ extern void sidey();
+ int main() {
+ printf("hello from main\n");
+ sidey();
+ return 0;
+ }
+ ''', r'''
+ #include <stdio.h>
+ void sidey() { printf("hello from side\n"); }
+ ''', 'hello from main\nhello from side\n')
- # function pointers with 'return' in the name
- test('fp2', 'typedef void (*voidfunc)();', r'''
- #include <stdio.h>
- #include "header.h"
- int sidey(voidfunc f);
- void areturn0() { printf("hello 0\n"); }
- void areturn1() { printf("hello 1\n"); }
- void areturn2() { printf("hello 2\n"); }
- int main(int argc, char **argv) {
- voidfunc table[3] = { areturn0, areturn1, areturn2 };
- table[sidey(NULL)]();
- return 0;
- }
- ''', '''
- #include "header.h"
- int sidey(voidfunc f) { if (f) f(); return 1; }
- ''', 'hello 1\n')
+ # function pointers
+ test('fp1', 'typedef void (*voidfunc)();', r'''
+ #include <stdio.h>
+ #include "header.h"
+ voidfunc sidey(voidfunc f);
+ void a() { printf("hello from funcptr\n"); }
+ int main() {
+ sidey(a)();
+ return 0;
+ }
+ ''', '''
+ #include "header.h"
+ voidfunc sidey(voidfunc f) { return f; }
+ ''', 'hello from funcptr\n')
- # Global initializer
- test('global init', '', r'''
- #include <stdio.h>
- struct Class {
- Class() { printf("a new Class\n"); }
- };
- static Class c;
- int main() {
- return 0;
- }
- ''', r'''
- void nothing() {}
- ''', 'a new Class\n')
+ # function pointers with 'return' in the name
+ test('fp2', 'typedef void (*voidfunc)();', r'''
+ #include <stdio.h>
+ #include "header.h"
+ int sidey(voidfunc f);
+ void areturn0() { printf("hello 0\n"); }
+ void areturn1() { printf("hello 1\n"); }
+ void areturn2() { printf("hello 2\n"); }
+ int main(int argc, char **argv) {
+ voidfunc table[3] = { areturn0, areturn1, areturn2 };
+ table[sidey(NULL)]();
+ return 0;
+ }
+ ''', '''
+ #include "header.h"
+ int sidey(voidfunc f) { if (f) f(); return 1; }
+ ''', 'hello 1\n')
- # Multiple global initializers (LLVM generates overlapping names for them)
- test('global inits', r'''
- #include <stdio.h>
- struct Class {
- Class(const char *name) { printf("new %s\n", name); }
- };
- ''', r'''
- #include "header.h"
- static Class c("main");
- int main() {
- return 0;
- }
- ''', r'''
- #include "header.h"
- static Class c("side");
- ''', ['new main\nnew side\n', 'new side\nnew main\n'])
+ # Global initializer
+ test('global init', '', r'''
+ #include <stdio.h>
+ struct Class {
+ Class() { printf("a new Class\n"); }
+ };
+ static Class c;
+ int main() {
+ return 0;
+ }
+ ''', r'''
+ void nothing() {}
+ ''', 'a new Class\n')
- # Class code used across modules
- test('codecall', r'''
- #include <stdio.h>
- struct Class {
- Class(const char *name);
- };
- ''', r'''
- #include "header.h"
- int main() {
- Class c("main");
- return 0;
- }
- ''', r'''
- #include "header.h"
- Class::Class(const char *name) { printf("new %s\n", name); }
- ''', ['new main\n'])
-
- # malloc usage in both modules
- test('malloc', r'''
- #include <stdlib.h>
- #include <string.h>
- char *side(const char *data);
- ''', r'''
- #include <stdio.h>
- #include "header.h"
- int main() {
- char *temp = side("hello through side\n");
- char *ret = (char*)malloc(strlen(temp)+1);
- strcpy(ret, temp);
- temp[1] = 'x';
- puts(ret);
- return 0;
- }
- ''', r'''
- #include "header.h"
- char *side(const char *data) {
- char *ret = (char*)malloc(strlen(data)+1);
- strcpy(ret, data);
- return ret;
- }
- ''', ['hello through side\n'])
+ # Multiple global initializers (LLVM generates overlapping names for them)
+ test('global inits', r'''
+ #include <stdio.h>
+ struct Class {
+ Class(const char *name) { printf("new %s\n", name); }
+ };
+ ''', r'''
+ #include "header.h"
+ static Class c("main");
+ int main() {
+ return 0;
+ }
+ ''', r'''
+ #include "header.h"
+ static Class c("side");
+ ''', ['new main\nnew side\n', 'new side\nnew main\n'])
- # js library call
- open('lib.js', 'w').write(r'''
- mergeInto(LibraryManager.library, {
- test_lib_func: function(x) {
- return x + 17.2;
+ # Class code used across modules
+ test('codecall', r'''
+ #include <stdio.h>
+ struct Class {
+ Class(const char *name);
+ };
+ ''', r'''
+ #include "header.h"
+ int main() {
+ Class c("main");
+ return 0;
}
- });
- ''')
- test('js-lib', 'extern "C" { extern double test_lib_func(int input); }', r'''
- #include <stdio.h>
- #include "header.h"
- extern double sidey();
- int main2() { return 11; }
- int main() {
- int input = sidey();
- double temp = test_lib_func(input);
- printf("other says %.2f\n", temp);
- printf("more: %.5f, %d\n", temp, input);
- return 0;
- }
- ''', r'''
- #include <stdio.h>
- #include "header.h"
- extern int main2();
- double sidey() {
- int temp = main2();
- printf("main2 sed: %d\n", temp);
- printf("main2 sed: %u, %c\n", temp, temp/2);
- return test_lib_func(temp);
- }
- ''', 'other says 45.2', ['--js-library', 'lib.js'])
+ ''', r'''
+ #include "header.h"
+ Class::Class(const char *name) { printf("new %s\n", name); }
+ ''', ['new main\n'])
- # libc usage in one modules. must force libc inclusion in the main module if that isn't the one using mallinfo()
- try:
- os.environ['EMCC_FORCE_STDLIBS'] = 'libc'
- test('malloc-1', r'''
+ # malloc usage in both modules
+ test('malloc', r'''
+ #include <stdlib.h>
#include <string.h>
- int side();
+ char *side(const char *data);
''', r'''
#include <stdio.h>
#include "header.h"
int main() {
- printf("|%d|\n", side());
+ char *temp = side("hello through side\n");
+ char *ret = (char*)malloc(strlen(temp)+1);
+ strcpy(ret, temp);
+ temp[1] = 'x';
+ puts(ret);
return 0;
}
''', r'''
- #include <stdlib.h>
- #include <malloc.h>
#include "header.h"
- int side() {
- struct mallinfo m = mallinfo();
- return m.arena > 1;
+ char *side(const char *data) {
+ char *ret = (char*)malloc(strlen(data)+1);
+ strcpy(ret, data);
+ return ret;
}
- ''', ['|1|\n'])
- finally:
- del os.environ['EMCC_FORCE_STDLIBS']
-
- # iostream usage in one and std::string in both
- test('iostream', r'''
- #include <iostream>
- #include <string>
- std::string side();
- ''', r'''
- #include "header.h"
- int main() {
- std::cout << "hello from main " << side() << std::endl;
- return 0;
- }
- ''', r'''
- #include "header.h"
- std::string side() { return "and hello from side"; }
- ''', ['hello from main and hello from side\n'])
-
- # followup to iostream test: a second linking
- print 'second linking of a linking output'
- open('moar.cpp', 'w').write(r'''
- #include <iostream>
- struct Moar {
- Moar() { std::cout << "moar!" << std::endl; }
- };
- Moar m;
- ''')
- Popen([PYTHON, EMCC, 'moar.cpp', '-o', 'moar.js', '-s', 'SIDE_MODULE=1', '-O2']).communicate()
- Popen([PYTHON, EMLINK, 'together.js', 'moar.js', 'triple.js'], stdout=PIPE).communicate()
- assert os.path.exists('triple.js')
- for engine in JS_ENGINES:
- out = run_js('triple.js', engine=engine, stderr=PIPE, full_output=True)
- self.assertContained('moar!\nhello from main and hello from side\n', out)
- if engine == SPIDERMONKEY_ENGINE: self.validate_asmjs(out)
-
- # zlib compression library. tests function pointers in initializers and many other things
- test('zlib', '', open(path_from_root('tests', 'zlib', 'example.c'), 'r').read(),
- self.get_zlib_library(),
- open(path_from_root('tests', 'zlib', 'ref.txt'), 'r').read(),
- args=['-I' + path_from_root('tests', 'zlib')], suffix='c')
-
- use_cmake = WINDOWS
- bullet_library = get_bullet_library(self, use_cmake)
-
- # bullet physics engine. tests all the things
- test('bullet', '', open(path_from_root('tests', 'bullet', 'Demos', 'HelloWorld', 'HelloWorld.cpp'), 'r').read(),
- bullet_library,
- [open(path_from_root('tests', 'bullet', 'output.txt'), 'r').read(), # different roundings
- open(path_from_root('tests', 'bullet', 'output2.txt'), 'r').read(),
- open(path_from_root('tests', 'bullet', 'output3.txt'), 'r').read()],
- args=['-I' + path_from_root('tests', 'bullet', 'src')])
+ ''', ['hello through side\n'])
+
+ # js library call
+ open('lib.js', 'w').write(r'''
+ mergeInto(LibraryManager.library, {
+ test_lib_func: function(x) {
+ return x + 17.2;
+ }
+ });
+ ''')
+ test('js-lib', 'extern "C" { extern double test_lib_func(int input); }', r'''
+ #include <stdio.h>
+ #include "header.h"
+ extern double sidey();
+ int main2() { return 11; }
+ int main() {
+ int input = sidey();
+ double temp = test_lib_func(input);
+ printf("other says %.2f\n", temp);
+ printf("more: %.5f, %d\n", temp, input);
+ return 0;
+ }
+ ''', r'''
+ #include <stdio.h>
+ #include "header.h"
+ extern int main2();
+ double sidey() {
+ int temp = main2();
+ printf("main2 sed: %d\n", temp);
+ printf("main2 sed: %u, %c\n", temp, temp/2);
+ return test_lib_func(temp);
+ }
+ ''', 'other says 45.2', ['--js-library', 'lib.js'])
+
+ # libc usage in one modules. must force libc inclusion in the main module if that isn't the one using mallinfo()
+ try:
+ os.environ['EMCC_FORCE_STDLIBS'] = 'libc'
+ test('malloc-1', r'''
+ #include <string.h>
+ int side();
+ ''', r'''
+ #include <stdio.h>
+ #include "header.h"
+ int main() {
+ printf("|%d|\n", side());
+ return 0;
+ }
+ ''', r'''
+ #include <stdlib.h>
+ #include <malloc.h>
+ #include "header.h"
+ int side() {
+ struct mallinfo m = mallinfo();
+ return m.arena > 1;
+ }
+ ''', ['|1|\n'])
+ finally:
+ del os.environ['EMCC_FORCE_STDLIBS']
+
+ # iostream usage in one and std::string in both
+ test('iostream', r'''
+ #include <iostream>
+ #include <string>
+ std::string side();
+ ''', r'''
+ #include "header.h"
+ int main() {
+ std::cout << "hello from main " << side() << std::endl;
+ return 0;
+ }
+ ''', r'''
+ #include "header.h"
+ std::string side() { return "and hello from side"; }
+ ''', ['hello from main and hello from side\n'])
+
+ # followup to iostream test: a second linking
+ print 'second linking of a linking output'
+ open('moar.cpp', 'w').write(r'''
+ #include <iostream>
+ struct Moar {
+ Moar() { std::cout << "moar!" << std::endl; }
+ };
+ Moar m;
+ ''')
+ Popen([PYTHON, EMCC, 'moar.cpp', '-o', 'moar.js', '-s', 'SIDE_MODULE=1', '-O2']).communicate()
+ Popen([PYTHON, EMLINK, 'together.js', 'moar.js', 'triple.js'], stdout=PIPE).communicate()
+ assert os.path.exists('triple.js')
+ for engine in JS_ENGINES:
+ out = run_js('triple.js', engine=engine, stderr=PIPE, full_output=True)
+ self.assertContained('moar!\nhello from main and hello from side\n', out)
+ if engine == SPIDERMONKEY_ENGINE: self.validate_asmjs(out)
+
+ # zlib compression library. tests function pointers in initializers and many other things
+ test('zlib', '', open(path_from_root('tests', 'zlib', 'example.c'), 'r').read(),
+ self.get_zlib_library(),
+ open(path_from_root('tests', 'zlib', 'ref.txt'), 'r').read(),
+ args=['-I' + path_from_root('tests', 'zlib')], suffix='c')
+
+ use_cmake = WINDOWS
+ bullet_library = get_bullet_library(self, use_cmake)
+
+ # bullet physics engine. tests all the things
+ test('bullet', '', open(path_from_root('tests', 'bullet', 'Demos', 'HelloWorld', 'HelloWorld.cpp'), 'r').read(),
+ bullet_library,
+ [open(path_from_root('tests', 'bullet', 'output.txt'), 'r').read(), # different roundings
+ open(path_from_root('tests', 'bullet', 'output2.txt'), 'r').read(),
+ open(path_from_root('tests', 'bullet', 'output3.txt'), 'r').read()],
+ args=['-I' + path_from_root('tests', 'bullet', 'src')])
+ nonfastcomp(nonfc)
def test_outline(self):
def test(name, src, libs, expected, expected_ranges, args=[], suffix='cpp'):
@@ -918,7 +923,7 @@ This pointer might make sense in another type signature: i: _my_func
500: (250, 500),
1000: (230, 1000),
2000: (380, 2000),
- 5000: (800, 5000),
+ 5000: (500, 5000),
0: (1500, 5000)
}),
(['-O2'], {
@@ -1817,26 +1822,28 @@ This pointer might make sense in another type signature: i: _my_func
assert 'error' not in err, 'Unexpected stderr: ' + err
def test_chunking(self):
- if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('not relevant for fastcomp, only checks js compiler chunking')
- if os.environ.get('EMCC_DEBUG'): return self.skip('cannot run in debug mode')
- if os.environ.get('EMCC_CORES'): return self.skip('cannot run if cores are altered')
- if multiprocessing.cpu_count() < 2: return self.skip('need multiple cores')
- try:
- os.environ['EMCC_DEBUG'] = '1'
- os.environ['EMCC_CORES'] = '2' # standardize over machines
- for asm, linkable, chunks in [
- (0, 0, 2), (0, 1, 2),
- (1, 0, 2), (1, 1, 2)
- ]:
- print asm, linkable, chunks
- output, err = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_libcxx.cpp'), '-O1', '-s', 'LINKABLE=%d' % linkable, '-s', 'ASM_JS=%d' % asm] + (['-O2'] if asm else []), stdout=PIPE, stderr=PIPE).communicate()
- ok = False
- for c in range(chunks, chunks+2):
- ok = ok or ('phase 2 working on %d chunks' % c in err)
- assert ok, err
- finally:
- del os.environ['EMCC_DEBUG']
- del os.environ['EMCC_CORES']
+ def nonfc():
+ if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('not relevant for fastcomp, only checks js compiler chunking')
+ if os.environ.get('EMCC_DEBUG'): return self.skip('cannot run in debug mode')
+ if os.environ.get('EMCC_CORES'): return self.skip('cannot run if cores are altered')
+ if multiprocessing.cpu_count() < 2: return self.skip('need multiple cores')
+ try:
+ os.environ['EMCC_DEBUG'] = '1'
+ os.environ['EMCC_CORES'] = '2' # standardize over machines
+ for asm, linkable, chunks in [
+ (0, 0, 2), (0, 1, 2),
+ (1, 0, 2), (1, 1, 2)
+ ]:
+ print asm, linkable, chunks
+ output, err = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_libcxx.cpp'), '-O1', '-s', 'LINKABLE=%d' % linkable, '-s', 'ASM_JS=%d' % asm] + (['-O2'] if asm else []), stdout=PIPE, stderr=PIPE).communicate()
+ ok = False
+ for c in range(chunks, chunks+2):
+ ok = ok or ('phase 2 working on %d chunks' % c in err)
+ assert ok, err
+ finally:
+ del os.environ['EMCC_DEBUG']
+ del os.environ['EMCC_CORES']
+ nonfastcomp(nonfc)
def test_debuginfo(self):
if os.environ.get('EMCC_DEBUG'): return self.skip('cannot run in debug mode')
@@ -1868,23 +1875,25 @@ This pointer might make sense in another type signature: i: _my_func
assert 'If you see this - the world is all right!' in output
def test_embind(self):
- if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp')
- for args, fail in [
- ([], True), # without --bind, we fail
- (['--bind'], False),
- (['--bind', '-O1'], False),
- (['--bind', '-O2'], False),
- (['--bind', '-O1', '-s', 'ASM_JS=0'], False),
- (['--bind', '-O2', '-s', 'ASM_JS=0'], False)
- ]:
- print args, fail
- self.clear()
- try_delete(self.in_dir('a.out.js'))
- Popen([PYTHON, EMCC, path_from_root('tests', 'embind', 'embind_test.cpp'), '--post-js', path_from_root('tests', 'embind', 'underscore-1.4.2.js'), '--post-js', path_from_root('tests', 'embind', 'imvu_test_adapter.js'), '--post-js', path_from_root('tests', 'embind', 'embind.test.js')] + args, stderr=PIPE if fail else None).communicate()
- assert os.path.exists(self.in_dir('a.out.js')) == (not fail)
- if not fail:
- output = run_js(self.in_dir('a.out.js'), stdout=PIPE, stderr=PIPE, full_output=True)
- assert "FAIL" not in output, output
+ def nonfc():
+ if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('todo in fastcomp')
+ for args, fail in [
+ ([], True), # without --bind, we fail
+ (['--bind'], False),
+ (['--bind', '-O1'], False),
+ (['--bind', '-O2'], False),
+ (['--bind', '-O1', '-s', 'ASM_JS=0'], False),
+ (['--bind', '-O2', '-s', 'ASM_JS=0'], False)
+ ]:
+ print args, fail
+ self.clear()
+ try_delete(self.in_dir('a.out.js'))
+ Popen([PYTHON, EMCC, path_from_root('tests', 'embind', 'embind_test.cpp'), '--post-js', path_from_root('tests', 'embind', 'underscore-1.4.2.js'), '--post-js', path_from_root('tests', 'embind', 'imvu_test_adapter.js'), '--post-js', path_from_root('tests', 'embind', 'embind.test.js')] + args, stderr=PIPE if fail else None).communicate()
+ assert os.path.exists(self.in_dir('a.out.js')) == (not fail)
+ if not fail:
+ output = run_js(self.in_dir('a.out.js'), stdout=PIPE, stderr=PIPE, full_output=True)
+ assert "FAIL" not in output, output
+ nonfastcomp(nonfc)
def test_llvm_nativizer(self):
try:
@@ -2362,7 +2371,7 @@ int main() {
assert '*** PCH/Modules Loaded:\nModule: header.h.gch' not in err[1], err[1]
def test_warn_unaligned(self):
- if os.environ.get('EMCC_FAST_COMPILER') != '1': return self.skip('need fastcomp')
+ if os.environ.get('EMCC_FAST_COMPILER') == '0': return self.skip('need fastcomp')
open('src.cpp', 'w').write(r'''
#include <stdio.h>
static const double grid[4][2] = {{-3 / 3., -1 / 3.},
diff --git a/tests/test_sanity.py b/tests/test_sanity.py
index 894f2192..5713c99c 100644
--- a/tests/test_sanity.py
+++ b/tests/test_sanity.py
@@ -196,9 +196,10 @@ class sanity(RunnerCore):
del os.environ['EM_IGNORE_SANITY']
def test_llvm_fastcomp(self):
- if os.environ.get('EMCC_FAST_COMPILER') != '1': return self.skip('not using fastcomp')
+ assert os.environ.get('EMCC_FAST_COMPILER') != '0', 'must be using fastcomp to test fastcomp'
WARNING = 'fastcomp in use, but LLVM has not been built with the JavaScript backend as a target'
+ WARNING2 = 'you can fall back to the older (pre-fastcomp) compiler core, although that is not recommended, see https://github.com/kripken/emscripten/wiki/LLVM-Backend'
restore()
@@ -206,6 +207,7 @@ class sanity(RunnerCore):
assert check_fastcomp()
output = self.check_working(EMCC)
assert WARNING not in output, output
+ assert WARNING2 not in output, output
# Fake incorrect llc output, no mention of js backend
restore()
@@ -222,6 +224,11 @@ class sanity(RunnerCore):
f.close()
os.chmod(path_from_root('tests', 'fake', 'llc'), stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC)
output = self.check_working(EMCC, WARNING)
+ output = self.check_working(EMCC, WARNING2)
+
+ restore()
+
+ self.check_working([EMCC, 'tests/hello_world.cpp', '-s', 'INIT_HEAP=1'], '''Compiler settings are incompatible with fastcomp. You can fall back to the older compiler core, although that is not recommended, see https://github.com/kripken/emscripten/wiki/LLVM-Backend''')
def test_node(self):
NODE_WARNING = 'node version appears too old'
@@ -446,111 +453,34 @@ fi
try_delete(CANONICAL_TEMP_DIR)
def test_relooper(self):
- RELOOPER = Cache.get_path('relooper.js')
-
- restore()
- for phase in range(2): # 0: we wipe the relooper dir. 1: we have it, so should just update
- if phase == 0: Cache.erase()
- try_delete(RELOOPER)
-
- for i in range(4):
- print >> sys.stderr, phase, i
- opt = min(i, 2)
- try_delete('a.out.js')
- output = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world_loop.cpp'), '-O' + str(opt), '-g'],
- stdout=PIPE, stderr=PIPE).communicate()
- self.assertContained('hello, world!', run_js('a.out.js'))
- output = '\n'.join(output)
- assert ('bootstrapping relooper succeeded' in output) == (i == 1), 'only bootstrap on first O2: ' + output
- assert os.path.exists(RELOOPER) == (i >= 1), 'have relooper on O2: ' + output
- src = open('a.out.js').read()
- main = src.split('function _main()')[1].split('\n}\n')[0]
- assert ('while (1) {' in main or 'while(1){' in main or 'while(1) {' in main or '} while ($' in main or '}while($' in main) == (i >= 1), 'reloop code on O2: ' + main
- assert ('switch' not in main) == (i >= 1), 'reloop code on O2: ' + main
-
- def test_jcache(self):
- PRE_LOAD_MSG = 'loading pre from jcache'
- PRE_SAVE_MSG = 'saving pre to jcache'
- FUNC_CHUNKS_LOAD_MSG = ' funcchunks from jcache'
- FUNC_CHUNKS_SAVE_MSG = ' funcchunks to jcache'
- JSFUNC_CHUNKS_LOAD_MSG = 'jsfuncchunks from jcache'
- JSFUNC_CHUNKS_SAVE_MSG = 'jsfuncchunks to jcache'
-
- restore()
- Cache.erase()
+ assert os.environ.get('EMCC_FAST_COMPILER') is None
try:
- os.environ['EMCC_DEBUG'] = '1'
- os.environ['EMCC_JSOPT_MIN_CHUNK_SIZE'] = str(1024*512)
-
- self.working_dir = os.path.join(TEMP_DIR, 'emscripten_temp')
- if not os.path.exists(self.working_dir): os.makedirs(self.working_dir)
-
- assert not os.path.exists(JCache.get_cachename('emscript_files'))
-
- srcs = {}
- used_jcache = False
-
- for args, input_file, expect_pre_save, expect_pre_load, expect_funcs_save, expect_funcs_load, expect_jsfuncs_save, expect_jsfuncs_load, expected in [
- ([], 'hello_world_loop.cpp', False, False, False, False, False, False, []),
- (['--jcache'], 'hello_world_loop.cpp', True, False, True, False, True, False, []),
- (['--jcache'], 'hello_world_loop.cpp', False, True, False, True, False, True, []),
- ([], 'hello_world_loop.cpp', False, False, False, False, False, False, []),
- # new
- ([], 'hello_world.cpp', False, False, False, False, False, False, []),
- (['--jcache'], 'hello_world.cpp', True, False, True, False, True, False, []),
- (['--jcache'], 'hello_world.cpp', False, True, False, True, False, True, []),
- ([], 'hello_world.cpp', False, False, False, False, False, False, []),
- # go back to old file, experience caching
- (['--jcache'], 'hello_world_loop.cpp', False, True, False, True, False, True, []),
- # new, large file
- ([], 'hello_malloc.cpp', False, False, False, False, False, False, []),
- (['--jcache'], 'hello_malloc.cpp', True, False, True, False, True, False, []),
- (['--jcache'], 'hello_malloc.cpp', False, True, False, True, False, True, []),
- ([], 'hello_malloc.cpp', False, False, False, False, False, False, []),
- # new, huge file
- ([], 'hello_libcxx.cpp', False, False, False, False, False, False, ('4 chunks',)),
- (['--jcache'], 'hello_libcxx.cpp', True, False, True, False, True, False, []),
- (['--jcache'], 'hello_libcxx.cpp', False, True, False, True, False, True, []),
- ([], 'hello_libcxx.cpp', False, False, False, False, False, False, []),
- # finally, build a file close to the previous, to see that some chunks are found in the cache and some not
- (['--jcache'], 'hello_libcxx_mod1.cpp', False, True, True, True, True, True, []), # win on pre, mix on funcs, mix on jsfuncs
- (['--jcache'], 'hello_libcxx_mod1.cpp', False, True, False, True, False, True, []),
- (None, None, None, None, None, None, None, None, None), # clear
- (['--jcache'], 'hello_libcxx_mod2.cpp', True, False, True, False, True, False, []), # load into cache
- (['--jcache'], 'hello_libcxx_mod2a.cpp', False, True, True, True, True, True, []) # add a printf, do not lose everything
- ]:
- self.clear()
- if args is None:
- Cache.erase()
- continue
-
- print >> sys.stderr, args, input_file, expect_pre_save, expect_pre_load, expect_funcs_save, expect_funcs_load, expect_jsfuncs_save, expect_jsfuncs_load, expected
-
- out, err = Popen([PYTHON, EMCC, '-O2', '-g', path_from_root('tests', input_file)] + args, stdout=PIPE, stderr=PIPE).communicate()
- errtail = err.split('emcc invocation')[-1]
- self.assertContained('hello, world!', run_js('a.out.js'), errtail)
- assert (PRE_SAVE_MSG in err) == expect_pre_save, errtail
- assert (PRE_LOAD_MSG in err) == expect_pre_load, errtail
- assert (FUNC_CHUNKS_SAVE_MSG in err) == expect_funcs_save, errtail
- assert (FUNC_CHUNKS_LOAD_MSG in err) == expect_funcs_load, errtail
- assert (JSFUNC_CHUNKS_SAVE_MSG in err) == expect_jsfuncs_save, errtail
- assert (JSFUNC_CHUNKS_LOAD_MSG in err) == expect_jsfuncs_load, errtail
- for expect in expected: assert expect in err, expect + ' ? ' + errtail
- curr = open('a.out.js').read()
- if input_file not in srcs:
- srcs[input_file] = curr
- else:
- #open('/home/alon/Dev/emscripten/a', 'w').write(srcs[input_file])
- #open('/home/alon/Dev/emscripten/b', 'w').write(curr)
- assert abs(len(curr)/float(len(srcs[input_file]))-1)<0.01, 'contents may shift in order, but must remain the same size %d vs %d' % (len(curr), len(srcs[input_file])) + '\n' + errtail
- used_jcache = used_jcache or ('--jcache' in args)
- assert used_jcache == os.path.exists(JCache.get_cachename('emscript_files'))
- #print >> sys.stderr, errtail
+ os.environ['EMCC_FAST_COMPILER'] = '0'
+
+ RELOOPER = Cache.get_path('relooper.js')
+ restore()
+ for phase in range(2): # 0: we wipe the relooper dir. 1: we have it, so should just update
+ if phase == 0: Cache.erase()
+ try_delete(RELOOPER)
+
+ for i in range(4):
+ print >> sys.stderr, phase, i
+ opt = min(i, 2)
+ try_delete('a.out.js')
+ output = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world_loop.cpp'), '-O' + str(opt), '-g'],
+ stdout=PIPE, stderr=PIPE).communicate()
+ self.assertContained('hello, world!', run_js('a.out.js'))
+ output = '\n'.join(output)
+ assert ('bootstrapping relooper succeeded' in output) == (i == 1), 'only bootstrap on first O2: ' + output
+ assert os.path.exists(RELOOPER) == (i >= 1), 'have relooper on O2: ' + output
+ src = open('a.out.js').read()
+ main = src.split('function _main()')[1].split('\n}\n')[0]
+ assert ('while (1) {' in main or 'while(1){' in main or 'while(1) {' in main or '} while ($' in main or '}while($' in main) == (i >= 1), 'reloop code on O2: ' + main
+ assert ('switch' not in main) == (i >= 1), 'reloop code on O2: ' + main
finally:
- del os.environ['EMCC_DEBUG']
- del os.environ['EMCC_JSOPT_MIN_CHUNK_SIZE']
+ del os.environ['EMCC_FAST_COMPILER']
def test_nostdincxx(self):
restore()