aboutsummaryrefslogtreecommitdiff
path: root/tests/test_sanity.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_sanity.py')
-rw-r--r--tests/test_sanity.py522
1 files changed, 522 insertions, 0 deletions
diff --git a/tests/test_sanity.py b/tests/test_sanity.py
new file mode 100644
index 00000000..931645e2
--- /dev/null
+++ b/tests/test_sanity.py
@@ -0,0 +1,522 @@
+import os, shutil, stat, subprocess
+from runner import RunnerCore, path_from_root
+from tools.shared import *
+
+SANITY_FILE = CONFIG_FILE + '_sanity'
+commands = [[EMCC], [PYTHON, path_from_root('tests', 'runner.py'), 'blahblah']]
+
+def restore():
+ shutil.copyfile(CONFIG_FILE + '_backup', CONFIG_FILE)
+
+def wipe():
+ try_delete(CONFIG_FILE)
+ try_delete(SANITY_FILE)
+
+def mtime(filename):
+ return os.stat(filename).st_mtime
+
+class sanity(RunnerCore):
+ @classmethod
+ def setUpClass(self):
+ super(RunnerCore, self).setUpClass()
+ shutil.copyfile(CONFIG_FILE, CONFIG_FILE + '_backup')
+
+ print
+ print 'Running sanity checks.'
+ print 'WARNING: This will modify %s, and in theory can break it although it should be restored properly. A backup will be saved in %s_backup' % (EM_CONFIG, EM_CONFIG)
+ print
+
+ assert os.path.exists(CONFIG_FILE), 'To run these tests, we need a (working!) %s file to already exist' % EM_CONFIG
+ assert not os.environ.get('EMCC_DEBUG'), 'do not run sanity checks in debug mode!'
+
+ @classmethod
+ def tearDownClass(self):
+ super(RunnerCore, self).tearDownClass()
+
+ def setUp(self):
+ wipe()
+
+ def tearDown(self):
+ restore()
+
+ def do(self, command):
+ if type(command) is not list:
+ command = [command]
+ if command[0] == EMCC:
+ command = [PYTHON] + command
+
+ return Popen(command, stdout=PIPE, stderr=STDOUT).communicate()[0]
+
+ def check_working(self, command, expected=None):
+ if type(command) is not list:
+ command = [command]
+ if expected is None:
+ if command[0] == EMCC:
+ expected = 'no input files'
+ else:
+ expected = "No tests found for ['blahblah']"
+
+ output = self.do(command)
+ self.assertContained(expected, output)
+ return output
+
+ def test_aaa_normal(self): # this should be the very first thing that runs. if this fails, everything else is irrelevant!
+ for command in commands:
+ # Your existing EM_CONFIG should work!
+ restore()
+ self.check_working(command)
+
+ def test_firstrun(self):
+ for command in commands:
+ wipe()
+
+ def make_executable(name):
+ with open(os.path.join(temp_bin, name), 'w') as f:
+ os.fchmod(f.fileno(), stat.S_IRWXU)
+
+ try:
+ temp_bin = tempfile.mkdtemp()
+ old_environ_path = os.environ['PATH']
+ os.environ['PATH'] = temp_bin + os.pathsep + old_environ_path
+ make_executable('llvm-dis')
+ make_executable('node')
+ make_executable('python2')
+ output = self.do(command)
+ finally:
+ os.environ['PATH'] = old_environ_path
+ shutil.rmtree(temp_bin)
+
+ self.assertContained('Welcome to Emscripten!', output)
+ self.assertContained('This is the first time any of the Emscripten tools has been run.', output)
+ self.assertContained('A settings file has been copied to %s, at absolute path: %s' % (EM_CONFIG, CONFIG_FILE), output)
+ self.assertContained('It contains our best guesses for the important paths, which are:', output)
+ self.assertContained('LLVM_ROOT', output)
+ self.assertContained('NODE_JS', output)
+ self.assertContained('PYTHON', output)
+ if platform.system() is not 'Windows':
+ # os.chmod can't make files executable on Windows
+ self.assertIdentical(temp_bin, re.search("^ *LLVM_ROOT *= (.*)$", output, re.M).group(1))
+ self.assertIdentical(os.path.join(temp_bin, 'node'), re.search("^ *NODE_JS *= (.*)$", output, re.M).group(1))
+ self.assertIdentical(os.path.join(temp_bin, 'python2'), re.search("^ *PYTHON *= (.*)$", output, re.M).group(1))
+ self.assertContained('Please edit the file if any of those are incorrect', output)
+ self.assertContained('This command will now exit. When you are done editing those paths, re-run it.', output)
+ assert output.split()[-1].endswith('===='), 'We should have stopped: ' + output
+ config_file = open(CONFIG_FILE).read()
+ template_file = open(path_from_root('tools', 'settings_template_readonly.py')).read()
+ self.assertNotContained('~/.emscripten', config_file)
+ self.assertContained('~/.emscripten', template_file)
+ self.assertNotContained('{{{', config_file)
+ self.assertNotContained('}}}', config_file)
+ self.assertContained('{{{', template_file)
+ self.assertContained('}}}', template_file)
+ for content in ['EMSCRIPTEN_ROOT', 'LLVM_ROOT', 'NODE_JS', 'TEMP_DIR', 'COMPILER_ENGINE', 'JS_ENGINES']:
+ self.assertContained(content, config_file)
+
+ # The guessed config should be ok XXX This depends on your local system! it is possible `which` guesses wrong
+ #try_delete('a.out.js')
+ #output = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world.c')], stdout=PIPE, stderr=PIPE).communicate()
+ #self.assertContained('hello, world!', run_js('a.out.js'), output)
+
+ # Second run, with bad EM_CONFIG
+ for settings in ['blah', 'LLVM_ROOT="blarg"; JS_ENGINES=[]; COMPILER_ENGINE=NODE_JS=SPIDERMONKEY_ENGINE=[]']:
+ f = open(CONFIG_FILE, 'w')
+ f.write(settings)
+ f.close()
+ output = self.do(command)
+
+ if 'LLVM_ROOT' not in settings:
+ self.assertContained('Error in evaluating %s' % EM_CONFIG, output)
+ elif 'runner.py' not in ' '.join(command):
+ self.assertContained('CRITICAL', output) # sanity check should fail
+
+ def test_closure_compiler(self):
+ CLOSURE_FATAL = 'fatal: Closure compiler'
+ CLOSURE_WARNING = 'does not exist'
+
+ # Sanity check should find closure
+ restore()
+ output = self.check_working(EMCC)
+ self.assertNotContained(CLOSURE_FATAL, output)
+ self.assertNotContained(CLOSURE_WARNING, output)
+
+ # Append a bad path for closure, will warn
+ f = open(CONFIG_FILE, 'a')
+ f.write('CLOSURE_COMPILER = "/tmp/nowhere/nothingtoseehere/kjadsfkjwelkjsdfkqgas/nonexistent.txt"\n')
+ f.close()
+ output = self.check_working(EMCC, CLOSURE_WARNING)
+
+ # And if you actually try to use the bad path, will be fatal
+ f = open(CONFIG_FILE, 'a')
+ f.write('CLOSURE_COMPILER = "/tmp/nowhere/nothingtoseehere/kjadsfkjwelkjsdfkqgas/nonexistent.txt"\n')
+ f.close()
+ output = self.check_working([EMCC, '-O2', '-s', 'ASM_JS=0', '--closure', '1', 'tests/hello_world.cpp'], CLOSURE_FATAL)
+
+ # With a working path, all is well
+ restore()
+ try_delete('a.out.js')
+ output = self.check_working([EMCC, '-O2', '-s', 'ASM_JS=0', '--closure', '1', 'tests/hello_world.cpp'], '')
+ assert os.path.exists('a.out.js'), output
+
+ def test_llvm(self):
+ LLVM_WARNING = 'LLVM version appears incorrect'
+
+ restore()
+
+ # Clang should report the version number we expect, and emcc should not warn
+ assert check_clang_version()
+ output = self.check_working(EMCC)
+ assert LLVM_WARNING not in output, output
+
+ # Fake a different llvm version
+ restore()
+ f = open(CONFIG_FILE, 'a')
+ f.write('LLVM_ROOT = "' + path_from_root('tests', 'fake') + '"')
+ f.close()
+
+ if not os.path.exists(path_from_root('tests', 'fake')):
+ os.makedirs(path_from_root('tests', 'fake'))
+
+ try:
+ os.environ['EM_IGNORE_SANITY'] = '1'
+ for x in range(-2, 3):
+ for y in range(-2, 3):
+ f = open(path_from_root('tests', 'fake', 'clang'), 'w')
+ f.write('#!/bin/sh\n')
+ f.write('echo "clang version %d.%d" 1>&2\n' % (EXPECTED_LLVM_VERSION[0] + x, EXPECTED_LLVM_VERSION[1] + y))
+ f.close()
+ shutil.copyfile(path_from_root('tests', 'fake', 'clang'), path_from_root('tests', 'fake', 'clang++'))
+ os.chmod(path_from_root('tests', 'fake', 'clang'), stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC)
+ os.chmod(path_from_root('tests', 'fake', 'clang++'), stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC)
+ if x != 0 or y != 0:
+ output = self.check_working(EMCC, LLVM_WARNING)
+ else:
+ output = self.check_working(EMCC)
+ assert LLVM_WARNING not in output, output
+ finally:
+ del os.environ['EM_IGNORE_SANITY']
+
+ def test_node(self):
+ NODE_WARNING = 'node version appears too old'
+ NODE_WARNING_2 = 'cannot check node version'
+
+ restore()
+
+ # Clang should report the version number we expect, and emcc should not warn
+ assert check_node_version()
+ output = self.check_working(EMCC)
+ assert NODE_WARNING not in output, output
+
+ # Fake a different node version
+ restore()
+ f = open(CONFIG_FILE, 'a')
+ f.write('NODE_JS = "' + path_from_root('tests', 'fake', 'nodejs') + '"')
+ f.close()
+
+ if not os.path.exists(path_from_root('tests', 'fake')):
+ os.makedirs(path_from_root('tests', 'fake'))
+
+ try:
+ os.environ['EM_IGNORE_SANITY'] = '1'
+ for version, succeed in [('v0.7.9', False), ('v0.8.0', True), ('v0.8.1', True), ('cheez', False)]:
+ f = open(path_from_root('tests', 'fake', 'nodejs'), 'w')
+ f.write('#!/bin/sh\n')
+ f.write('''if [ $1 = "--version" ]; then
+echo "%s"
+else
+%s $@
+fi
+''' % (version, NODE_JS))
+ f.close()
+ os.chmod(path_from_root('tests', 'fake', 'nodejs'), stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC)
+ if not succeed:
+ if version[0] == 'v':
+ self.check_working(EMCC, NODE_WARNING)
+ else:
+ self.check_working(EMCC, NODE_WARNING_2)
+ else:
+ output = self.check_working(EMCC)
+ assert NODE_WARNING not in output, output
+ finally:
+ del os.environ['EM_IGNORE_SANITY']
+
+ def test_emcc(self):
+ SANITY_MESSAGE = 'Emscripten: Running sanity checks'
+ SANITY_FAIL_MESSAGE = 'sanity check failed to run'
+
+ # emcc should check sanity if no ${EM_CONFIG}_sanity
+ restore()
+ time.sleep(0.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)
+ assert os.path.exists(SANITY_FILE) # EMCC should have checked sanity successfully
+ assert mtime(SANITY_FILE) >= mtime(CONFIG_FILE)
+ assert generate_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)
+
+ # correct sanity contents mean we need not check
+ open(SANITY_FILE, 'w').write(generate_sanity())
+ output = self.check_working(EMCC)
+ self.assertNotContained(SANITY_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)
+
+ # but with EMCC_DEBUG=1 we should check
+ try:
+ os.environ['EMCC_DEBUG'] = '1'
+ output = self.check_working(EMCC)
+ finally:
+ del os.environ['EMCC_DEBUG']
+ self.assertContained(SANITY_MESSAGE, output)
+ output = self.check_working(EMCC)
+ self.assertNotContained(SANITY_MESSAGE, output)
+
+ # 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
+ time.sleep(0.1)
+ restore()
+ assert mtime(SANITY_FILE) < mtime(CONFIG_FILE)
+ output = self.check_working(EMCC)
+ self.assertContained(SANITY_MESSAGE, output)
+ assert mtime(SANITY_FILE) >= mtime(CONFIG_FILE)
+ self.assertNotContained(SANITY_FAIL_MESSAGE, output)
+
+ # emcc should be configurable directly from EM_CONFIG without any config file
+ restore()
+ config = open(CONFIG_FILE, 'r').read()
+ os.environ['EM_CONFIG'] = config
+ wipe()
+ dirname = tempfile.mkdtemp(prefix='emscripten_test_' + self.__class__.__name__ + '_', dir=TEMP_DIR)
+ open(os.path.join(dirname, 'main.cpp'), 'w').write('''
+ #include <stdio.h>
+ int main() {
+ printf("hello from emcc with no config file\\n");
+ return 0;
+ }
+ ''')
+ Popen([PYTHON, EMCC, os.path.join(dirname, 'main.cpp'), '-o', os.path.join(dirname, 'a.out.js')]).communicate()
+ del os.environ['EM_CONFIG']
+ old_dir = os.getcwd()
+ try:
+ os.chdir(dirname)
+ self.assertContained('hello from emcc with no config file', run_js('a.out.js'))
+ finally:
+ os.chdir(old_dir)
+ shutil.rmtree(dirname)
+
+ try_delete(CANONICAL_TEMP_DIR)
+
+ def test_emcc_caching(self):
+ INCLUDING_MESSAGE = 'including X'
+ BUILDING_MESSAGE = 'building X for cache'
+ ERASING_MESSAGE = 'clearing cache'
+
+ EMCC_CACHE = Cache.dirname
+
+ for compiler in [EMCC, EMXX]:
+ print compiler
+
+ restore()
+
+ Cache.erase()
+ assert not os.path.exists(EMCC_CACHE)
+
+ try:
+ os.environ['EMCC_DEBUG'] ='1'
+ self.working_dir = os.path.join(TEMP_DIR, 'emscripten_temp')
+
+ # Building a file that doesn't need cached stuff should not trigger cache generation
+ output = self.do([compiler, path_from_root('tests', 'hello_world.cpp')])
+ assert INCLUDING_MESSAGE.replace('X', 'libc') not in output
+ assert BUILDING_MESSAGE.replace('X', 'libc') not in output
+ self.assertContained('hello, world!', run_js('a.out.js'))
+ assert not os.path.exists(EMCC_CACHE)
+ try_delete('a.out.js')
+
+ basebc_name = os.path.join(TEMP_DIR, 'emscripten_temp', 'emcc-0-basebc.bc')
+ dcebc_name = os.path.join(TEMP_DIR, 'emscripten_temp', 'emcc-1-linktime.bc')
+ ll_names = [os.path.join(TEMP_DIR, 'emscripten_temp', 'emcc-X-ll.ll').replace('X', str(x)) for x in range(2,5)]
+
+ # Building a file that *does* need dlmalloc *should* trigger cache generation, but only the first time
+ for filename, libname in [('hello_malloc.cpp', 'libc'), ('hello_libcxx.cpp', 'libcxx')]:
+ for i in range(3):
+ print filename, libname, i
+ self.clear()
+ try_delete(basebc_name) # we might need to check this file later
+ try_delete(dcebc_name) # we might need to check this file later
+ for ll_name in ll_names: try_delete(ll_name)
+ output = self.do([compiler, '-O' + str(i), '-s', 'RELOOP=0', '--llvm-lto', '0', path_from_root('tests', filename)])
+ #print output
+ assert INCLUDING_MESSAGE.replace('X', libname) in output
+ if libname == 'libc':
+ assert INCLUDING_MESSAGE.replace('X', 'libcxx') not in output # we don't need libcxx in this code
+ else:
+ assert INCLUDING_MESSAGE.replace('X', 'libc') in output # libcxx always forces inclusion of libc
+ 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'))
+ assert os.path.exists(EMCC_CACHE)
+ assert os.path.exists(os.path.join(EMCC_CACHE, libname + '.bc'))
+ if libname == 'libcxx':
+ print os.stat(os.path.join(EMCC_CACHE, libname + '.bc')).st_size, os.stat(basebc_name).st_size, os.stat(dcebc_name).st_size
+ assert os.stat(os.path.join(EMCC_CACHE, libname + '.bc')).st_size > 1000000, 'libc++ is big'
+ assert os.stat(basebc_name).st_size > 1000000, 'libc++ is indeed big'
+ assert os.stat(dcebc_name).st_size < os.stat(basebc_name).st_size/2, 'Dead code elimination must remove most of libc++'
+ # should only have metadata in -O0, not 1 and 2
+ if i > 0:
+ for ll_name in ll_names:
+ ll = None
+ try:
+ ll = open(ll_name).read()
+ break
+ except:
+ pass
+ assert ll
+ assert ll.count('\n!') < 10 # a few lines are left even in -O1 and -O2
+ finally:
+ del os.environ['EMCC_DEBUG']
+
+ restore()
+
+ def ensure_cache():
+ self.do([EMCC, '-O2', path_from_root('tests', 'hello_world.c')])
+
+ # Manual cache clearing
+ ensure_cache()
+ assert os.path.exists(EMCC_CACHE)
+ output = self.do([EMCC, '--clear-cache'])
+ assert ERASING_MESSAGE in output
+ assert not os.path.exists(EMCC_CACHE)
+
+ # Changing LLVM_ROOT, even without altering .emscripten, clears the cache
+ ensure_cache()
+ old = os.environ.get('LLVM')
+ try:
+ os.environ['LLVM'] = 'waka'
+ assert os.path.exists(EMCC_CACHE)
+ output = self.do([EMCC])
+ assert ERASING_MESSAGE in output
+ assert not os.path.exists(EMCC_CACHE)
+ finally:
+ if old: os.environ['LLVM'] = old
+ else: del os.environ['LLVM']
+
+ 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 == 2), 'only bootstrap on first O2: ' + output
+ assert os.path.exists(RELOOPER) == (i >= 2), '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 ($' in main or '}while($' in main) == (i >= 2), 'reloop code on O2: ' + main
+ assert ('switch' not in main) == (i >= 2), '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()
+
+ 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, ('3 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
+
+ finally:
+ del os.environ['EMCC_DEBUG']
+ del os.environ['EMCC_JSOPT_MIN_CHUNK_SIZE'] \ No newline at end of file