|
| 1 | +# Copyright 2020 The Emscripten Authors. All rights reserved. |
| 2 | +# Emscripten is available under two separate licenses, the MIT license and the |
| 3 | +# University of Illinois/NCSA Open Source License. Both these licenses can be |
| 4 | +# found in the LICENSE file. |
| 5 | + |
| 6 | +"""Runs the pthreads test from the upstream posixtest suite in: |
| 7 | + ./tests/third_party/posixtestsuite |
| 8 | +See |
| 9 | + https://github.com/juj/posixtestsuite |
| 10 | +""" |
| 11 | + |
| 12 | +import glob |
| 13 | +import os |
| 14 | + |
| 15 | +from runner import RunnerCore, path_from_root |
| 16 | +from tools import config |
| 17 | +from tools.shared import EMCC |
| 18 | +import test_posixtest_browser |
| 19 | + |
| 20 | +testsuite_root = path_from_root('tests', 'third_party', 'posixtestsuite') |
| 21 | + |
| 22 | + |
| 23 | +class posixtest(RunnerCore): |
| 24 | + """Run the suite under node (and in parallel) |
| 25 | +
|
| 26 | + This class get populated dynamically below. |
| 27 | + """ |
| 28 | + pass |
| 29 | + |
| 30 | + |
| 31 | +def filter_tests(all_tests): |
| 32 | + pthread_tests = [t for t in all_tests if t.startswith('pthread_')] |
| 33 | + # filter out some tests we don't support |
| 34 | + pthread_tests = [t for t in pthread_tests if not t.startswith('pthread_atfork')] |
| 35 | + pthread_tests = [t for t in pthread_tests if not t.startswith('pthread_sigmask')] |
| 36 | + return pthread_tests |
| 37 | + |
| 38 | + |
| 39 | +def get_pthread_tests(): |
| 40 | + # For now, we don't require the submodule to exist. In this case we just report |
| 41 | + # no tests |
| 42 | + pthread_test_root = os.path.join(testsuite_root, 'conformance', 'interfaces') |
| 43 | + if not os.path.exists(pthread_test_root): |
| 44 | + print('posixtestsuite not found (run git submodule update --init?)') |
| 45 | + return [] |
| 46 | + pthread_tests = filter_tests(os.listdir(pthread_test_root)) |
| 47 | + pthread_tests = [os.path.join(pthread_test_root, t) for t in pthread_tests] |
| 48 | + return pthread_tests |
| 49 | + |
| 50 | + |
| 51 | +engine = config.NODE_JS + ['--experimental-wasm-threads', '--experimental-wasm-bulk-memory'] |
| 52 | + |
| 53 | +# Mark certain tests as not passing |
| 54 | +disabled = { |
| 55 | + 'test_pthread_create_11_1': 'never returns', |
| 56 | + 'test_pthread_barrier_wait_2_1': 'never returns', |
| 57 | + 'test_pthread_cond_timedwait_2_6': 'never returns', |
| 58 | + 'test_pthread_cond_timedwait_4_3': 'never returns', |
| 59 | + 'test_pthread_attr_setscope_5_1': 'internally skipped (PTS_UNTESTED)', |
| 60 | + 'test_pthread_cond_wait_2_3': 'never returns', |
| 61 | + 'test_pthread_create_5_1': 'never returns', |
| 62 | + 'test_pthread_exit_1_2': 'never returns', |
| 63 | + 'test_pthread_exit_2_2': 'never returns', |
| 64 | + 'test_pthread_exit_3_2': 'never returns', |
| 65 | + 'test_pthread_exit_4_1': 'never returns', |
| 66 | + 'test_pthread_getcpuclockid_1_1': 'never returns', |
| 67 | + 'test_pthread_key_create_1_2': 'never returns', |
| 68 | + 'test_pthread_rwlock_rdlock_1_1': 'fails with "main: Unexpected thread state"', |
| 69 | + 'test_pthread_rwlock_timedrdlock_1_1': 'fails with "main: Unexpected thread state"', |
| 70 | + 'test_pthread_rwlock_timedrdlock_3_1': 'fails with "main: Unexpected thread state"', |
| 71 | + 'test_pthread_rwlock_timedrdlock_5_1': 'fails with "main: Unexpected thread state"', |
| 72 | + 'test_pthread_rwlock_timedwrlock_1_1': 'fails with "main: Unexpected thread state"', |
| 73 | + 'test_pthread_rwlock_timedwrlock_3_1': 'fails with "main: Unexpected thread state"', |
| 74 | + 'test_pthread_rwlock_timedwrlock_5_1': 'fails with "main: Unexpected thread state"', |
| 75 | + 'test_pthread_rwlock_wrlock_1_1': 'fails with "main: Unexpected thread state"', |
| 76 | + 'test_pthread_rwlock_trywrlock_1_1': 'fails with "main: Unexpected thread state"', |
| 77 | + 'test_pthread_spin_destroy_3_1': 'never returns', |
| 78 | + 'test_pthread_spin_init_4_1': 'never returns', |
| 79 | +} |
| 80 | + |
| 81 | + |
| 82 | +def make_test(name, testfile, browser): |
| 83 | + |
| 84 | + def f(self): |
| 85 | + if name in disabled: |
| 86 | + self.skipTest(disabled[name]) |
| 87 | + args = ['-I' + os.path.join(testsuite_root, 'include'), |
| 88 | + '-Werror', |
| 89 | + '-Wno-format-security', |
| 90 | + '-Wno-int-conversion', |
| 91 | + '-sUSE_PTHREADS', |
| 92 | + '-sEXIT_RUNTIME', |
| 93 | + '-sTOTAL_MEMORY=268435456', |
| 94 | + '-sPTHREAD_POOL_SIZE=40'] |
| 95 | + if browser: |
| 96 | + # Only are only needed for browser tests of the was btest |
| 97 | + # injects headers using `-include` flag. |
| 98 | + args += ['-Wno-macro-redefined', '-D_GNU_SOURCE'] |
| 99 | + self.btest(testfile, args=args, expected='exit:0') |
| 100 | + else: |
| 101 | + self.run_process([EMCC, testfile, '-o', 'test.js'] + args) |
| 102 | + self.run_js('test.js', engine=engine) |
| 103 | + |
| 104 | + return f |
| 105 | + |
| 106 | + |
| 107 | +for testdir in get_pthread_tests(): |
| 108 | + basename = os.path.basename(testdir) |
| 109 | + for test_file in glob.glob(os.path.join(testdir, '*.c')): |
| 110 | + if not os.path.basename(test_file)[0].isdigit(): |
| 111 | + continue |
| 112 | + test_suffix = os.path.splitext(os.path.basename(test_file))[0] |
| 113 | + test_suffix = test_suffix.replace('-', '_') |
| 114 | + test_name = 'test_' + basename + '_' + test_suffix |
| 115 | + setattr(posixtest, test_name, make_test(test_name, test_file, browser=False)) |
| 116 | + setattr(test_posixtest_browser.posixtest_browser, test_name, make_test(test_name, test_file, browser=True)) |
0 commit comments