@@ -955,22 +955,22 @@ def test_cmake_explicit_generator(self):
955955 # Tests that it's possible to pass C++11 or GNU++11 build modes to CMake by building code that
956956 # needs C++11 (embind)
957957 @requires_ninja
958- def test_cmake_with_embind_cpp11_mode(self):
959- for args in [[], ['-DNO_GNU_EXTENSIONS=1']]:
960- self.clear()
961- # Use ninja generator here since we assume its always installed on our build/test machines.
962- configure = [EMCMAKE, 'cmake', '-GNinja', test_file('cmake/cmake_with_emval')] + args
963- print(str(configure))
964- self.run_process(configure)
965- build = ['cmake', '--build', '.']
966- print(str( build))
967- self.run_process(build)
968-
969- out = self.run_js('cmake_with_emval.js')
970- if '-DNO_GNU_EXTENSIONS=1' in args:
971- self.assertContained('Hello! __STRICT_ANSI__: 1, __cplusplus: 201103', out)
972- else:
973- self.assertContained('Hello! __STRICT_ANSI__: 0, __cplusplus: 201103', out)
958+ @parameterized({
959+ '': [[]],
960+ '_no_gnu': [['-DNO_GNU_EXTENSIONS=1']],
961+ })
962+ def test_cmake_with_embind_cpp11_mode(self, args):
963+ # Use ninja generator here since we assume its always installed on our build/test machines.
964+ configure = [EMCMAKE, 'cmake', '-GNinja', test_file('cmake/cmake_with_emval')] + args
965+ self.run_process(configure)
966+ build = ['cmake', '-- build', '.']
967+ self.run_process(build)
968+
969+ out = self.run_js('cmake_with_emval.js')
970+ if '-DNO_GNU_EXTENSIONS=1' in args:
971+ self.assertContained('Hello! __STRICT_ANSI__: 1, __cplusplus: 201103', out)
972+ else:
973+ self.assertContained('Hello! __STRICT_ANSI__: 0, __cplusplus: 201103', out)
974974
975975 # Tests that the Emscripten CMake toolchain option
976976 def test_cmake_bitcode_static_libraries(self):
@@ -2584,11 +2584,16 @@ def test_undefined_exported_js_function(self, outfile):
25842584 self.run_process(cmd)
25852585
25862586 @parameterized({
2587- 'warn ': ('WARN',) ,
2588- 'error ': ('ERROR',) ,
2589- 'ignore ': (None,)
2587+ '': [[]] ,
2588+ 'O1 ': [['-O1']] ,
2589+ 'GL2 ': [['-sMAX_WEBGL_VERSION=2']],
25902590 })
2591- def test_undefined_symbols(self, action):
2591+ @parameterized({
2592+ 'warn': ['WARN'],
2593+ 'error': ['ERROR'],
2594+ 'ignore': [None]
2595+ })
2596+ def test_undefined_symbols(self, action, args):
25922597 create_file('main.c', r'''
25932598 #include <stdio.h>
25942599 #include <SDL.h>
@@ -2606,36 +2611,35 @@ def test_undefined_symbols(self, action):
26062611 }
26072612 ''')
26082613
2609- for args in ([], ['-O1'], ['-sMAX_WEBGL_VERSION=2']):
2610- for value in ([0, 1]):
2611- delete_file('a.out.js')
2612- print('checking "%s" %s' % (args, value))
2613- extra = ['-s', action + '_ON_UNDEFINED_SYMBOLS=%d' % value] if action else []
2614- proc = self.run_process([EMCC, '-sUSE_SDL', '-sGL_ENABLE_GET_PROC_ADDRESS', 'main.c'] + extra + args, stderr=PIPE, check=False)
2615- if common.EMTEST_VERBOSE:
2616- print(proc.stderr)
2617- if value or action is None:
2618- # The default is that we error in undefined symbols
2619- self.assertContained('undefined symbol: something', proc.stderr)
2620- self.assertContained('undefined symbol: elsey', proc.stderr)
2621- check_success = False
2622- elif action == 'ERROR' and not value:
2623- # Error disables, should only warn
2624- self.assertContained('warning: undefined symbol: something', proc.stderr)
2625- self.assertContained('warning: undefined symbol: elsey', proc.stderr)
2626- self.assertNotContained('undefined symbol: emscripten_', proc.stderr)
2627- check_success = True
2628- elif action == 'WARN' and not value:
2629- # Disabled warning should imply disabling errors
2630- self.assertNotContained('undefined symbol', proc.stderr)
2631- check_success = True
2632-
2633- if check_success:
2634- self.assertEqual(proc.returncode, 0)
2635- self.assertTrue(os.path.exists('a.out.js'))
2636- else:
2637- self.assertNotEqual(proc.returncode, 0)
2638- self.assertFalse(os.path.exists('a.out.js'))
2614+ for value in ([0, 1]):
2615+ delete_file('a.out.js')
2616+ print('checking %s' % value)
2617+ extra = ['-s', action + '_ON_UNDEFINED_SYMBOLS=%d' % value] if action else []
2618+ proc = self.run_process([EMCC, '-sUSE_SDL', '-sGL_ENABLE_GET_PROC_ADDRESS', 'main.c'] + extra + args, stderr=PIPE, check=False)
2619+ if common.EMTEST_VERBOSE:
2620+ print(proc.stderr)
2621+ if value or action is None:
2622+ # The default is that we error in undefined symbols
2623+ self.assertContained('undefined symbol: something', proc.stderr)
2624+ self.assertContained('undefined symbol: elsey', proc.stderr)
2625+ check_success = False
2626+ elif action == 'ERROR' and not value:
2627+ # Error disables, should only warn
2628+ self.assertContained('warning: undefined symbol: something', proc.stderr)
2629+ self.assertContained('warning: undefined symbol: elsey', proc.stderr)
2630+ self.assertNotContained('undefined symbol: emscripten_', proc.stderr)
2631+ check_success = True
2632+ elif action == 'WARN' and not value:
2633+ # Disabled warning should imply disabling errors
2634+ self.assertNotContained('undefined symbol', proc.stderr)
2635+ check_success = True
2636+
2637+ if check_success:
2638+ self.assertEqual(proc.returncode, 0)
2639+ self.assertTrue(os.path.exists('a.out.js'))
2640+ else:
2641+ self.assertNotEqual(proc.returncode, 0)
2642+ self.assertFalse(os.path.exists('a.out.js'))
26392643
26402644 def test_undefined_data_symbols(self):
26412645 create_file('main.c', r'''
@@ -4658,7 +4662,13 @@ def add_on_abort_and_verify(extra=''):
46584662 os.remove('a.out.wasm') # trigger onAbort by intentionally causing startup to fail
46594663 add_on_abort_and_verify()
46604664
4661- def test_no_exit_runtime(self):
4665+ @parameterized({
4666+ '': ([],),
4667+ '01': (['-O1', '-g2'],),
4668+ 'O2': (['-O2', '-g2', '-flto'],),
4669+ })
4670+ @also_with_wasm2js
4671+ def test_no_exit_runtime(self, opts):
46624672 create_file('code.cpp', r'''
46634673#include <stdio.h>
46644674
@@ -4683,29 +4693,27 @@ def test_no_exit_runtime(self):
46834693}
46844694 ''')
46854695
4686- for wasm in [0, 1]:
4687- for no_exit in [1, 0]:
4688- for opts in [[], ['-O1'], ['-O2', '-g2'], ['-O2', '-g2', '-flto']]:
4689- print(wasm, no_exit, opts)
4690- cmd = [EMXX] + opts + ['code.cpp', '-sEXIT_RUNTIME=' + str(1 - no_exit), '-sWASM=' + str(wasm)]
4691- if wasm:
4692- cmd += ['--profiling-funcs'] # for function names
4693- self.run_process(cmd)
4694- output = self.run_js('a.out.js')
4695- src = read_file('a.out.js')
4696- if wasm:
4697- src += '\n' + self.get_wasm_text('a.out.wasm')
4698- exit = 1 - no_exit
4699- print(' exit:', exit, 'opts:', opts)
4700- self.assertContained('coming around', output)
4701- self.assertContainedIf('going away', output, exit)
4702- # The wasm backend uses atexit to register destructors when
4703- # constructors are called There is currently no way to exclude
4704- # these destructors from the wasm binary.
4705- # TODO(sbc): Re-enabled these assertions once the wasm backend
4706- # is able to eliminate these.
4707- # assert ('atexit(' in src) == exit, 'atexit should not appear in src when EXIT_RUNTIME=0'
4708- # assert ('_ZN5WasteILi2EED' in src) == exit, 'destructors should not appear if no exit:\n' + src
4696+ for no_exit in [1, 0]:
4697+ print(no_exit)
4698+ cmd = [EMXX] + opts + ['code.cpp', '-sEXIT_RUNTIME=' + str(1 - no_exit)] + self.get_emcc_args()
4699+ if self.is_wasm():
4700+ cmd += ['--profiling-funcs'] # for function names
4701+ self.run_process(cmd)
4702+ output = self.run_js('a.out.js')
4703+ src = read_file('a.out.js')
4704+ if self.is_wasm():
4705+ src += '\n' + self.get_wasm_text('a.out.wasm')
4706+ exit = 1 - no_exit
4707+ print(' exit:', exit)
4708+ self.assertContained('coming around', output)
4709+ self.assertContainedIf('going away', output, exit)
4710+ # The wasm backend uses atexit to register destructors when
4711+ # constructors are called There is currently no way to exclude
4712+ # these destructors from the wasm binary.
4713+ # TODO(sbc): Re-enabled these assertions once the wasm backend
4714+ # is able to eliminate these.
4715+ # assert ('atexit(' in src) == exit, 'atexit should not appear in src when EXIT_RUNTIME=0'
4716+ # assert ('_ZN5WasteILi2EED' in src) == exit, 'destructors should not appear if no exit:\n' + src
47094717
47104718 def test_no_exit_runtime_warnings_flush(self):
47114719 # check we warn if there is unflushed info
@@ -4771,19 +4779,22 @@ def test(cxx, no_exit, assertions, flush=0, keepalive=0, filesystem=1):
47714779 for flush in [0, 1]:
47724780 test(cxx, no_exit, assertions, flush)
47734781
4774- def test_fs_after_main(self):
4775- for args in [[], ['-O1']]:
4776- print(args)
4777- self.run_process([EMXX, test_file('fs_after_main.cpp')])
4778- self.assertContained('Test passed.', self.run_js('a.out.js'))
4779-
4780- def test_opt_levels(self):
4781- for opt in ['-O1', '-O2', '-Os', '-Oz', '-O3', '-Og', '-Ofast']:
4782+ def test_extra_opt_levels(self):
4783+ # Opt levels that we don't tend to test elsewhere
4784+ for opt in ['-Og', '-Ofast']:
47824785 print(opt)
47834786 proc = self.run_process([EMCC, '-v', test_file('hello_world.c'), opt], stderr=PIPE)
47844787 self.assertContained(opt, proc.stderr)
47854788 self.assertContained('hello, world!', self.run_js('a.out.js'))
47864789
4790+ @parameterized({
4791+ '': [[]],
4792+ 'O1': [['-O1']],
4793+ })
4794+ def test_fs_after_main(self, args):
4795+ self.run_process([EMXX, test_file('fs_after_main.cpp')])
4796+ self.assertContained('Test passed.', self.run_js('a.out.js'))
4797+
47874798 def test_oz_size(self):
47884799 sizes = {}
47894800 for name, args in [
@@ -6615,17 +6626,18 @@ def test_massive_alloc(self, wasm):
66156626 if not wasm:
66166627 self.assertContained('Warning: Enlarging memory arrays, this is not fast! 16777216,1468137472\n', output)
66176628
6618- def test_failing_alloc(self):
6629+ @parameterized({
6630+ '': (False,),
6631+ 'growth': (True,),
6632+ })
6633+ @also_with_wasm2js
6634+ def test_failing_alloc(self, growth):
66196635 for pre_fail, post_fail, opts in [
66206636 ('', '', []),
66216637 ('EM_ASM( Module.temp = _sbrk() );', 'EM_ASM( assert(Module.temp === _sbrk(), "must not adjust brk when an alloc fails!") );', []),
6622- # also test non-wasm in normal mode
6623- ('', '', ['-sWASM=0']),
6624- ('EM_ASM( Module.temp = _sbrk() );', 'EM_ASM( assert(Module.temp === _sbrk(), "must not adjust brk when an alloc fails!") );', ['-sWASM=0']),
66256638 ]:
6626- for growth in [0, 1]:
6627- for aborting_args in [[], ['-sABORTING_MALLOC=0']]:
6628- create_file('main.cpp', r'''
6639+ for aborting_args in [[], ['-sABORTING_MALLOC=0']]:
6640+ create_file('main.cpp', r'''
66296641#include <stdio.h>
66306642#include <stdlib.h>
66316643#include <vector>
@@ -6665,38 +6677,38 @@ def test_failing_alloc(self):
66656677 printf("managed another malloc!\n");
66666678}
66676679''' % (pre_fail, post_fail))
6668- args = [EMXX, 'main.cpp', '-sEXPORTED_FUNCTIONS=_main,_sbrk', '-sINITIAL_MEMORY=16MB'] + opts + aborting_args
6669- args += ['-sTEST_MEMORY_GROWTH_FAILS'] # In this test, force memory growing to fail
6680+ args = [EMXX, 'main.cpp', '-sEXPORTED_FUNCTIONS=_main,_sbrk', '-sINITIAL_MEMORY=16MB'] + opts + aborting_args
6681+ args += ['-sTEST_MEMORY_GROWTH_FAILS'] # In this test, force memory growing to fail
6682+ if growth:
6683+ args += ['-sALLOW_MEMORY_GROWTH']
6684+ # growth disables aborting by default, but it can be overridden
6685+ aborting = not aborting_args and not growth
6686+ print('test_failing_alloc', args, pre_fail)
6687+ self.run_process(args)
6688+ # growth also disables aborting
6689+ can_manage_another = not aborting
6690+ split = '-DSPLIT' in args
6691+ print('can manage another:', can_manage_another, 'split:', split, 'aborting:', aborting)
6692+ output = self.run_js('a.out.js', assert_returncode=0 if can_manage_another else NON_ZERO)
6693+ if can_manage_another:
6694+ self.assertContained('an allocation failed!\n', output)
6695+ if not split:
6696+ # split memory allocation may fail due to GC objects no longer being allocatable,
6697+ # and we can't expect to recover from that deterministically. So just check we
6698+ # get to the fail.
6699+ # otherwise, we should fail eventually, then free, then succeed
6700+ self.assertContained('managed another malloc!\n', output)
6701+ else:
6702+ # we should see an abort
6703+ self.assertContained('Aborted(Cannot enlarge memory arrays', output)
66706704 if growth:
6671- args += ['-sALLOW_MEMORY_GROWTH']
6672- # growth disables aborting by default, but it can be overridden
6673- aborting = not aborting_args and not growth
6674- print('test_failing_alloc', args, pre_fail)
6675- self.run_process(args)
6676- # growth also disables aborting
6677- can_manage_another = not aborting
6678- split = '-DSPLIT' in args
6679- print('can manage another:', can_manage_another, 'split:', split, 'aborting:', aborting)
6680- output = self.run_js('a.out.js', assert_returncode=0 if can_manage_another else NON_ZERO)
6681- if can_manage_another:
6682- self.assertContained('an allocation failed!\n', output)
6683- if not split:
6684- # split memory allocation may fail due to GC objects no longer being allocatable,
6685- # and we can't expect to recover from that deterministically. So just check we
6686- # get to the fail.
6687- # otherwise, we should fail eventually, then free, then succeed
6688- self.assertContained('managed another malloc!\n', output)
6705+ # when growth is enabled, the default is to not abort, so just explain that
6706+ self.assertContained('If you want malloc to return NULL (0) instead of this abort, do not link with -sABORTING_MALLOC', output)
66896707 else:
6690- # we should see an abort
6691- self.assertContained('Aborted(Cannot enlarge memory arrays', output)
6692- if growth:
6693- # when growth is enabled, the default is to not abort, so just explain that
6694- self.assertContained('If you want malloc to return NULL (0) instead of this abort, do not link with -sABORTING_MALLOC', output)
6695- else:
6696- # when growth is not enabled, suggest 3 possible solutions (start with more memory, allow growth, or don't abort)
6697- self.assertContained(('higher than the current value 16777216,', 'higher than the current value 33554432,'), output)
6698- self.assertContained('compile with -sALLOW_MEMORY_GROWTH', output)
6699- self.assertContained('compile with -sABORTING_MALLOC=0', output)
6708+ # when growth is not enabled, suggest 3 possible solutions (start with more memory, allow growth, or don't abort)
6709+ self.assertContained(('higher than the current value 16777216,', 'higher than the current value 33554432,'), output)
6710+ self.assertContained('compile with -sALLOW_MEMORY_GROWTH', output)
6711+ self.assertContained('compile with -sABORTING_MALLOC=0', output)
67006712
67016713 def test_failing_growth_2gb(self):
67026714 create_file('test.c', r'''
@@ -8779,37 +8791,42 @@ def test_side_module_folder_deps(self):
87798791 self.run_process([EMCC, test_file('hello_world.c'), '-sMAIN_MODULE', '-o', 'main.js', '-L', 'subdir', '-lside2'])
87808792
87818793 @is_slow_test
8782- def test_lto(self):
8794+ @parameterized({
8795+ '': ([],),
8796+ '01': (['-O1'],),
8797+ 'O2': (['-O2'],),
8798+ 'O3': (['-O3'],),
8799+ 'Os': (['-Os'],),
8800+ 'Oz': (['-Oz'],),
8801+ })
8802+ def test_lto(self, args):
87838803 # test building of non-wasm-object-files libraries, building with them, and running them
87848804
8785- src = test_file('hello_libcxx.cpp')
87868805 # test codegen in lto mode, and compare to normal (wasm object) mode
8787- for args in [[], ['-O1'], ['-O2'], ['-O3'], ['-Os'], ['-Oz']]:
8788- print(args)
8789-
8790- print('wasm in object')
8791- self.run_process([EMXX, src] + args + ['-c', '-o', 'hello_obj.o'])
8792- self.assertTrue(building.is_wasm('hello_obj.o'))
8793- self.assertFalse(is_bitcode('hello_obj.o'))
8794-
8795- print('bitcode in object')
8796- self.run_process([EMXX, src] + args + ['-c', '-o', 'hello_bitcode.o', '-flto'])
8797- self.assertFalse(building.is_wasm('hello_bitcode.o'))
8798- self.assertTrue(is_bitcode('hello_bitcode.o'))
8799-
8800- print('use bitcode object (LTO)')
8801- self.run_process([EMXX, 'hello_bitcode.o'] + args + ['-flto'])
8802- self.assertContained('hello, world!', self.run_js('a.out.js'))
8803- print('use bitcode object (non-LTO)')
8804- self.run_process([EMXX, 'hello_bitcode.o'] + args)
8805- self.assertContained('hello, world!', self.run_js('a.out.js'))
8806+ src = test_file('hello_libcxx.cpp')
8807+ # wasm in object
8808+ self.run_process([EMXX, src] + args + ['-c', '-o', 'hello_obj.o'])
8809+ self.assertTrue(building.is_wasm('hello_obj.o'))
8810+ self.assertFalse(is_bitcode('hello_obj.o'))
8811+
8812+ # bitcode in object
8813+ self.run_process([EMXX, src] + args + ['-c', '-o', 'hello_bitcode.o', '-flto'])
8814+ self.assertFalse(building.is_wasm('hello_bitcode.o'))
8815+ self.assertTrue(is_bitcode('hello_bitcode.o'))
8816+
8817+ # use bitcode object (LTO)
8818+ self.run_process([EMXX, 'hello_bitcode.o'] + args + ['-flto'])
8819+ self.assertContained('hello, world!', self.run_js('a.out.js'))
8820+ # use bitcode object (non-LTO)
8821+ self.run_process([EMXX, 'hello_bitcode.o'] + args)
8822+ self.assertContained('hello, world!', self.run_js('a.out.js'))
88068823
8807- print(' use native object (LTO)' )
8808- self.run_process([EMXX, 'hello_obj.o'] + args + ['-flto'])
8809- self.assertContained('hello, world!', self.run_js('a.out.js'))
8810- print(' use native object (non-LTO)' )
8811- self.run_process([EMXX, 'hello_obj.o'] + args)
8812- self.assertContained('hello, world!', self.run_js('a.out.js'))
8824+ # use native object (LTO)
8825+ self.run_process([EMXX, 'hello_obj.o'] + args + ['-flto'])
8826+ self.assertContained('hello, world!', self.run_js('a.out.js'))
8827+ # use native object (non-LTO)
8828+ self.run_process([EMXX, 'hello_obj.o'] + args)
8829+ self.assertContained('hello, world!', self.run_js('a.out.js'))
88138830
88148831 @parameterized({
88158832 'noexcept': [],
0 commit comments