Exemple #1
0
                def do_asm2wasm_test():
                    actual = support.run_command(cmd)

                    # verify output
                    if not os.path.exists(wasm):
                        shared.fail_with_error(
                            'output .wast file %s does not exist' % wasm)
                    shared.fail_if_not_identical_to_file(actual, wasm)

                    shared.binary_format_check(wasm, verify_final_result=False)
Exemple #2
0
        def do_asm2wasm_test():
          actual = run_command(cmd)

          # verify output
          if not os.path.exists(wasm):
            fail_with_error('output .wast file %s does not exist' % wasm)
          expected = open(wasm, 'rb').read()
          if actual != expected:
            fail(actual, expected)

          binary_format_check(wasm, verify_final_result=False)
Exemple #3
0
def run_spec_tests():
    print('\n[ checking wasm-shell spec testcases... ]\n')

    for wast in shared.options.spec_tests:
        base = os.path.basename(wast)
        print('..', base)
        # windows has some failures that need to be investigated
        if base == 'names.wast' and shared.skip_if_on_windows('spec: ' + base):
            continue
        # FIXME Reenable this after updating interpreter for EH
        if base == 'exception-handling.wast':
            continue

        def run_spec_test(wast):
            cmd = shared.WASM_SHELL + [wast]
            output = support.run_command(cmd, stderr=subprocess.PIPE)
            # filter out binaryen interpreter logging that the spec suite
            # doesn't expect
            filtered = [
                line for line in output.splitlines()
                if not line.startswith('[trap')
            ]
            return '\n'.join(filtered) + '\n'

        def run_opt_test(wast):
            # check optimization validation
            cmd = shared.WASM_OPT + [wast, '-O', '-all']
            support.run_command(cmd)

        def check_expected(actual, expected):
            if expected and os.path.exists(expected):
                expected = open(expected).read()
                print('       (using expected output)')
                actual = actual.strip()
                expected = expected.strip()
                if actual != expected:
                    shared.fail(actual, expected)

        expected = os.path.join(shared.get_test_dir('spec'), 'expected-output',
                                base + '.log')

        # some spec tests should fail (actual process failure, not just assert_invalid)
        try:
            actual = run_spec_test(wast)
        except Exception as e:
            if ('wasm-validator error' in str(e)
                    or 'parse exception' in str(e)) and '.fail.' in base:
                print('<< test failed as expected >>')
                continue  # don't try all the binary format stuff TODO
            else:
                shared.fail_with_error(str(e))

        check_expected(actual, expected)

        # skip binary checks for tests that reuse previous modules by name, as that's a wast-only feature
        if 'exports.wast' in base:  # FIXME
            continue

        # check binary format. here we can verify execution of the final
        # result, no need for an output verification
        # some wast files cannot be split:
        #     * comments.wast: contains characters that are not valid utf-8,
        #       so our string splitting code fails there

        # FIXME Remove reference type tests from this list after nullref is
        # implemented in V8
        if base not in [
                'comments.wast', 'ref_null.wast', 'ref_is_null.wast',
                'ref_func.wast', 'old_select.wast'
        ]:
            split_num = 0
            actual = ''
            for module, asserts in support.split_wast(wast):
                print('        testing split module', split_num)
                split_num += 1
                support.write_wast('split.wast', module, asserts)
                run_spec_test(
                    'split.wast'
                )  # before binary stuff - just check it's still ok split out
                run_opt_test('split.wast'
                             )  # also that our optimizer doesn't break on it
                result_wast = shared.binary_format_check(
                    'split.wast',
                    verify_final_result=False,
                    original_wast=wast)
                # add the asserts, and verify that the test still passes
                open(result_wast, 'a').write('\n' + '\n'.join(asserts))
                actual += run_spec_test(result_wast)
            # compare all the outputs to the expected output
            check_expected(
                actual,
                os.path.join(shared.get_test_dir('spec'), 'expected-output',
                             base + '.log'))
        else:
            # handle unsplittable wast files
            run_spec_test(wast)
Exemple #4
0
def run_wasm_opt_tests():
    print '\n[ checking wasm-opt -o notation... ]\n'

    for extra_args in [[], ['--no-validation']]:
        wast = os.path.join(options.binaryen_test, 'hello_world.wast')
        delete_from_orbit('a.wast')
        cmd = WASM_OPT + [wast, '-o', 'a.wast', '-S'] + extra_args
        run_command(cmd)
        fail_if_not_identical_to_file(open('a.wast').read(), wast)

    print '\n[ checking wasm-opt binary reading/writing... ]\n'

    shutil.copyfile(os.path.join(options.binaryen_test, 'hello_world.wast'),
                    'a.wast')
    delete_from_orbit('a.wasm')
    delete_from_orbit('b.wast')
    run_command(WASM_OPT + ['a.wast', '-o', 'a.wasm'])
    assert open('a.wasm', 'rb').read()[0] == '\0', 'we emit binary by default'
    run_command(WASM_OPT + ['a.wasm', '-o', 'b.wast', '-S'])
    assert open('b.wast', 'rb').read()[0] != '\0', 'we emit text with -S'

    print '\n[ checking wasm-opt passes... ]\n'

    for t in sorted(os.listdir(os.path.join(options.binaryen_test, 'passes'))):
        if t.endswith(('.wast', '.wasm')):
            print '..', t
            binary = '.wasm' in t
            base = os.path.basename(t).replace('.wast',
                                               '').replace('.wasm', '')
            passname = base
            if passname.isdigit():
                passname = open(
                    os.path.join(options.binaryen_test, 'passes',
                                 passname + '.passes')).read().strip()
            opts = [('--' + p if not p.startswith('O') else '-' + p)
                    for p in passname.split('_')]
            t = os.path.join(options.binaryen_test, 'passes', t)
            actual = ''
            for module, asserts in split_wast(t):
                assert len(asserts) == 0
                with open('split.wast', 'w') as o:
                    o.write(module)
                cmd = WASM_OPT + opts + ['split.wast', '--print']
                curr = run_command(cmd)
                actual += curr
                # also check debug mode output is valid
                debugged = run_command(cmd + ['--debug'],
                                       stderr=subprocess.PIPE)
                fail_if_not_contained(actual, debugged)

                # also check pass-debug mode
                def check():
                    pass_debug = run_command(cmd)
                    fail_if_not_identical(curr, pass_debug)

                with_pass_debug(check)

            expected_file = os.path.join(
                options.binaryen_test, 'passes',
                base + ('.bin' if binary else '') + '.txt')
            fail_if_not_identical_to_file(actual, expected_file)

            if 'emit-js-wrapper' in t:
                with open('a.js') as actual:
                    fail_if_not_identical_to_file(actual.read(), t + '.js')
            if 'emit-spec-wrapper' in t:
                with open('a.wat') as actual:
                    fail_if_not_identical_to_file(actual.read(), t + '.wat')

    print '\n[ checking wasm-opt parsing & printing... ]\n'

    for t in sorted(os.listdir(os.path.join(options.binaryen_test, 'print'))):
        if t.endswith('.wast'):
            print '..', t
            wasm = os.path.basename(t).replace('.wast', '')
            cmd = WASM_OPT + [
                os.path.join(options.binaryen_test, 'print', t), '--print'
            ]
            print '    ', ' '.join(cmd)
            actual, err = subprocess.Popen(
                cmd, stdout=subprocess.PIPE,
                stderr=subprocess.PIPE).communicate()
            expected_file = os.path.join(options.binaryen_test, 'print',
                                         wasm + '.txt')
            fail_if_not_identical_to_file(actual, expected_file)
            cmd = WASM_OPT + [
                os.path.join(options.binaryen_test, 'print', t),
                '--print-minified'
            ]
            print '    ', ' '.join(cmd)
            actual, err = subprocess.Popen(
                cmd, stdout=subprocess.PIPE,
                stderr=subprocess.PIPE).communicate()
            fail_if_not_identical(
                actual.strip(),
                open(
                    os.path.join(options.binaryen_test, 'print',
                                 wasm + '.minified.txt')).read().strip())

    print '\n[ checking wasm-opt testcases... ]\n'

    for t in tests:
        if t.endswith('.wast') and not t.startswith('spec'):
            print '..', t
            t = os.path.join(options.binaryen_test, t)
            f = t + '.from-wast'
            cmd = WASM_OPT + [t, '--print']
            actual = run_command(cmd)
            actual = actual.replace('printing before:\n', '')

            fail_if_not_identical_to_file(actual, f)

            binary_format_check(t, wasm_as_args=['-g'])  # test with debuginfo
            binary_format_check(t,
                                wasm_as_args=[],
                                binary_suffix='.fromBinary.noDebugInfo'
                                )  # test without debuginfo

            minify_check(t)
Exemple #5
0
def run_spec_tests():
    print '\n[ checking wasm-shell spec testcases... ]\n'

    if len(requested) == 0:
        BLACKLIST = [
            'memory.wast', 'binary.wast'
        ]  # FIXME we support old and new memory formats, for now, until 0xc, and so can't pass this old-style test.
        # FIXME to update the spec to 0xd, we need to implement (register "name") for import.wast
        spec_tests = [
            os.path.join('spec', t) for t in sorted(
                os.listdir(os.path.join(options.binaryen_test, 'spec')))
            if t not in BLACKLIST
        ]
    else:
        spec_tests = requested[:]

    for t in spec_tests:
        if t.startswith('spec') and t.endswith('.wast'):
            print '..', t
            wast = os.path.join(options.binaryen_test, t)

            # skip checks for some tests
            if os.path.basename(wast) in [
                    'linking.wast', 'nop.wast', 'stack.wast', 'typecheck.wast',
                    'unwind.wast'
            ]:  # FIXME
                continue

            def run_spec_test(wast):
                cmd = WASM_SHELL + [wast]
                # we must skip the stack machine portions of spec tests or apply other extra args
                extra = {}
                cmd = cmd + (extra.get(os.path.basename(wast)) or [])
                return run_command(cmd, stderr=subprocess.PIPE)

            def run_opt_test(wast):
                # check optimization validation
                cmd = WASM_OPT + [wast, '-O']
                run_command(cmd)

            def check_expected(actual, expected):
                if expected and os.path.exists(expected):
                    expected = open(expected).read()

                    # fix it up, our pretty (i32.const 83) must become compared to a homely 83 : i32
                    def fix(x):
                        x = x.strip()
                        if not x: return x
                        v, t = x.split(' : ')
                        if v.endswith('.'): v = v[:-1]  # remove trailing '.'
                        return '(' + t + '.const ' + v + ')'

                    expected = '\n'.join(map(fix, expected.split('\n')))
                    print '       (using expected output)'
                    actual = actual.strip()
                    expected = expected.strip()
                    if actual != expected:
                        fail(actual, expected)

            expected = os.path.join(options.binaryen_test, 'spec',
                                    'expected-output',
                                    os.path.basename(wast) + '.log')

            # some spec tests should fail (actual process failure, not just assert_invalid)
            try:
                actual = run_spec_test(wast)
            except Exception, e:
                if ('wasm-validator error' in str(e)
                        or 'parse exception' in str(e)) and '.fail.' in t:
                    print '<< test failed as expected >>'
                    continue  # don't try all the binary format stuff TODO
                else:
                    fail_with_error(str(e))

            check_expected(actual, expected)

            # skip binary checks for tests that reuse previous modules by name, as that's a wast-only feature
            if os.path.basename(wast) in ['exports.wast']:  # FIXME
                continue

            # we must ignore some binary format splits
            splits_to_skip = {'func.wast': [2], 'return.wast': [2]}

            # check binary format. here we can verify execution of the final result, no need for an output verification
            split_num = 0
            if os.path.basename(
                    wast
            ) not in []:  # avoid some tests with things still being sorted out in the spec
                actual = ''
                for module, asserts in split_wast(wast):
                    skip = splits_to_skip.get(os.path.basename(wast)) or []
                    if split_num in skip:
                        print '    skipping split module', split_num - 1
                        split_num += 1
                        continue
                    print '    testing split module', split_num
                    split_num += 1
                    with open('split.wast', 'w') as o:
                        o.write(module + '\n' + '\n'.join(asserts))
                    run_spec_test(
                        'split.wast'
                    )  # before binary stuff - just check it's still ok split out
                    run_opt_test(
                        'split.wast'
                    )  # also that our optimizer doesn't break on it
                    result_wast = binary_format_check(
                        'split.wast', verify_final_result=False)
                    # add the asserts, and verify that the test still passes
                    open(result_wast, 'a').write('\n' + '\n'.join(asserts))
                    actual += run_spec_test(result_wast)
                # compare all the outputs to the expected output
                check_expected(
                    actual,
                    os.path.join(options.binaryen_test, 'spec',
                                 'expected-output',
                                 os.path.basename(wast) + '.log'))
Exemple #6
0
def run_wasm_opt_tests():
    print('\n[ checking wasm-opt -o notation... ]\n')

    for extra_args in [[], ['--no-validation']]:
        wast = os.path.join(shared.options.binaryen_test, 'hello_world.wat')
        shared.delete_from_orbit('a.wat')
        out = 'a.wat'
        cmd = shared.WASM_OPT + [wast, '-o', out, '-S'] + extra_args
        support.run_command(cmd)
        shared.fail_if_not_identical_to_file(open(out).read(), wast)

    print('\n[ checking wasm-opt binary reading/writing... ]\n')

    shutil.copyfile(
        os.path.join(shared.options.binaryen_test, 'hello_world.wat'), 'a.wat')
    shared.delete_from_orbit('a.wasm')
    shared.delete_from_orbit('b.wast')
    support.run_command(shared.WASM_OPT + ['a.wat', '-o', 'a.wasm'])
    assert open('a.wasm', 'rb').read()[0] == 0, 'we emit binary by default'
    support.run_command(shared.WASM_OPT + ['a.wasm', '-o', 'b.wast', '-S'])
    assert open('b.wast', 'rb').read()[0] != 0, 'we emit text with -S'

    print('\n[ checking wasm-opt passes... ]\n')

    for t in shared.get_tests(shared.get_test_dir('passes'),
                              ['.wast', '.wasm']):
        print('..', os.path.basename(t))
        binary = '.wasm' in t
        base = os.path.basename(t).replace('.wast', '').replace('.wasm', '')
        passname = base
        passes_file = os.path.join(shared.get_test_dir('passes'),
                                   passname + '.passes')
        if os.path.exists(passes_file):
            passname = open(passes_file).read().strip()
        opts = [('--' + p if not p.startswith('O') and p != 'g' else '-' + p)
                for p in passname.split('_')]
        actual = ''
        for module, asserts in support.split_wast(t):
            assert len(asserts) == 0
            support.write_wast('split.wast', module)
            cmd = shared.WASM_OPT + opts + ['split.wast', '--print']
            curr = support.run_command(cmd)
            actual += curr
            # also check debug mode output is valid
            debugged = support.run_command(cmd + ['--debug'],
                                           stderr=subprocess.PIPE)
            shared.fail_if_not_contained(actual, debugged)

            # also check pass-debug mode
            def check():
                pass_debug = support.run_command(cmd)
                shared.fail_if_not_identical(curr, pass_debug)

            shared.with_pass_debug(check)

        expected_file = os.path.join(
            shared.get_test_dir('passes'),
            base + ('.bin' if binary else '') + '.txt')
        shared.fail_if_not_identical_to_file(actual, expected_file)

        if 'emit-js-wrapper' in t:
            with open('a.js') as actual:
                shared.fail_if_not_identical_to_file(actual.read(), t + '.js')
        if 'emit-spec-wrapper' in t:
            with open('a.wat') as actual:
                shared.fail_if_not_identical_to_file(actual.read(), t + '.wat')

    print('\n[ checking wasm-opt parsing & printing... ]\n')

    for t in shared.get_tests(shared.get_test_dir('print'), ['.wast']):
        print('..', os.path.basename(t))
        wasm = os.path.basename(t).replace('.wast', '')
        cmd = shared.WASM_OPT + [t, '--print', '-all']
        print('    ', ' '.join(cmd))
        actual, err = subprocess.Popen(cmd,
                                       stdout=subprocess.PIPE,
                                       stderr=subprocess.PIPE,
                                       universal_newlines=True).communicate()
        expected_file = os.path.join(shared.get_test_dir('print'),
                                     wasm + '.txt')
        shared.fail_if_not_identical_to_file(actual, expected_file)
        cmd = shared.WASM_OPT + [
            os.path.join(shared.get_test_dir('print'), t), '--print-minified',
            '-all'
        ]
        print('    ', ' '.join(cmd))
        actual, err = subprocess.Popen(cmd,
                                       stdout=subprocess.PIPE,
                                       stderr=subprocess.PIPE,
                                       universal_newlines=True).communicate()
        shared.fail_if_not_identical(
            actual.strip(),
            open(
                os.path.join(shared.get_test_dir('print'),
                             wasm + '.minified.txt')).read().strip())

    print('\n[ checking wasm-opt testcases... ]\n')

    for t in shared.get_tests(shared.options.binaryen_test, ['.wast']):
        print('..', os.path.basename(t))
        f = t + '.from-wast'
        cmd = shared.WASM_OPT + [t, '--print', '-all']
        actual = support.run_command(cmd)
        actual = actual.replace('printing before:\n', '')

        shared.fail_if_not_identical_to_file(actual, f)

        # FIXME Remove this condition after nullref is implemented in V8
        if 'reference-types.wast' not in t:
            shared.binary_format_check(t,
                                       wasm_as_args=['-g'
                                                     ])  # test with debuginfo
            shared.binary_format_check(t,
                                       wasm_as_args=[],
                                       binary_suffix='.fromBinary.noDebugInfo'
                                       )  # test without debuginfo

        shared.minify_check(t)

    print('\n[ checking wasm-opt debugInfo read-write... ]\n')

    for t in shared.get_tests(shared.options.binaryen_test, ['.fromasm']):
        if 'debugInfo' not in t:
            continue
        print('..', os.path.basename(t))
        f = t + '.read-written'
        support.run_command(shared.WASM_AS +
                            [t, '--source-map=a.map', '-o', 'a.wasm', '-g'])
        support.run_command(shared.WASM_OPT + [
            'a.wasm', '--input-source-map=a.map', '-o', 'b.wasm',
            '--output-source-map=b.map', '-g'
        ])
        actual = support.run_command(shared.WASM_DIS +
                                     ['b.wasm', '--source-map=b.map'])
        shared.fail_if_not_identical_to_file(actual, f)
Exemple #7
0
                        cmd += ['--mem-base=1024']
                if 'i64' in asm or 'wasm-only' in asm or 'noffi' in asm:
                    cmd += ['--wasm-only']
                wasm = os.path.join(options.binaryen_test, wasm)
                print '..', asm, wasm
                actual = run_command(cmd)

                # verify output
                if not os.path.exists(wasm):
                    fail_with_error('output .wast file %s does not exist' %
                                    wasm)
                expected = open(wasm, 'rb').read()
                if actual != expected:
                    fail(actual, expected)

                binary_format_check(wasm, verify_final_result=False)

                # verify in wasm
                if options.interpreter:
                    # remove imports, spec interpreter doesn't know what to do with them
                    subprocess.check_call(WASM_OPT +
                                          ['--remove-imports', wasm],
                                          stdout=open('ztemp.wast', 'w'),
                                          stderr=subprocess.PIPE)
                    proc = subprocess.Popen(
                        [options.interpreter, 'ztemp.wast'],
                        stderr=subprocess.PIPE)
                    out, err = proc.communicate()
                    if proc.returncode != 0:
                        try:  # to parse the error
                            reported = err.split(':')[1]
Exemple #8
0
def run_spec_tests():
    print('\n[ checking wasm-shell spec testcases... ]\n')

    if not shared.options.spec_tests:
        # FIXME we support old and new memory formats, for now, until 0xc, and so can't pass this old-style test.
        BLACKLIST = ['binary.wast']
        # FIXME to update the spec to 0xd, we need to implement (register "name") for import.wast
        spec_tests = shared.get_tests(shared.get_test_dir('spec'), ['.wast'])
        spec_tests = [
            t for t in spec_tests if os.path.basename(t) not in BLACKLIST
        ]
    else:
        spec_tests = shared.options.spec_tests[:]

    for wast in spec_tests:
        print('..', os.path.basename(wast))

        # skip checks for some tests
        if os.path.basename(wast) in [
                'linking.wast', 'nop.wast', 'stack.wast', 'typecheck.wast',
                'unwind.wast'
        ]:  # FIXME
            continue

        def run_spec_test(wast):
            cmd = shared.WASM_SHELL + [wast]
            # we must skip the stack machine portions of spec tests or apply other extra args
            extra = {}
            cmd = cmd + (extra.get(os.path.basename(wast)) or [])
            return support.run_command(cmd, stderr=subprocess.PIPE)

        def run_opt_test(wast):
            # check optimization validation
            cmd = shared.WASM_OPT + [wast, '-O', '-all']
            support.run_command(cmd)

        def check_expected(actual, expected):
            if expected and os.path.exists(expected):
                expected = open(expected).read()

                # fix it up, our pretty (i32.const 83) must become compared to a homely 83 : i32
                def fix_expected(x):
                    x = x.strip()
                    if not x:
                        return x
                    v, t = x.split(' : ')
                    if v.endswith('.'):
                        v = v[:-1]  # remove trailing '.'
                    return '(' + t + '.const ' + v + ')'

                def fix_actual(x):
                    if '[trap ' in x:
                        return ''
                    return x

                expected = '\n'.join(map(fix_expected, expected.split('\n')))
                actual = '\n'.join(map(fix_actual, actual.split('\n')))
                print('       (using expected output)')
                actual = actual.strip()
                expected = expected.strip()
                if actual != expected:
                    shared.fail(actual, expected)

        expected = os.path.join(shared.get_test_dir('spec'), 'expected-output',
                                os.path.basename(wast) + '.log')

        # some spec tests should fail (actual process failure, not just assert_invalid)
        try:
            actual = run_spec_test(wast)
        except Exception as e:
            if ('wasm-validator error' in str(e) or 'parse exception'
                    in str(e)) and '.fail.' in os.path.basename(wast):
                print('<< test failed as expected >>')
                continue  # don't try all the binary format stuff TODO
            else:
                shared.fail_with_error(str(e))

        check_expected(actual, expected)

        # skip binary checks for tests that reuse previous modules by name, as that's a wast-only feature
        if os.path.basename(wast) in ['exports.wast']:  # FIXME
            continue

        # we must ignore some binary format splits
        splits_to_skip = {'func.wast': [2], 'return.wast': [2]}

        # check binary format. here we can verify execution of the final
        # result, no need for an output verification
        # some wast files cannot be split:
        #     * comments.wast: contains characters that are not valid utf-8,
        #       so our string splitting code fails there
        if os.path.basename(wast) not in ['comments.wast']:
            split_num = 0
            actual = ''
            for module, asserts in support.split_wast(wast):
                skip = splits_to_skip.get(os.path.basename(wast)) or []
                if split_num in skip:
                    print('        skipping split module', split_num - 1)
                    split_num += 1
                    continue
                print('        testing split module', split_num)
                split_num += 1
                support.write_wast('split.wast', module, asserts)
                run_spec_test(
                    'split.wast'
                )  # before binary stuff - just check it's still ok split out
                run_opt_test('split.wast'
                             )  # also that our optimizer doesn't break on it
                result_wast = shared.binary_format_check(
                    'split.wast',
                    verify_final_result=False,
                    original_wast=wast)
                # add the asserts, and verify that the test still passes
                open(result_wast, 'a').write('\n' + '\n'.join(asserts))
                actual += run_spec_test(result_wast)
            # compare all the outputs to the expected output
            check_expected(
                actual,
                os.path.join(shared.get_test_dir('spec'), 'expected-output',
                             os.path.basename(wast) + '.log'))
        else:
            # handle unsplittable wast files
            run_spec_test(wast)
Exemple #9
0
def run_emscripten_tests():
    if MOZJS and 0:

        print '\n[ checking native wasm support ]\n'

        command = [
            EMCC, '-o', 'a.wasm.js', '-s', 'BINARYEN=1',
            os.path.join(options.binaryen_test, 'hello_world.c'), '-s',
            'BINARYEN_METHOD="native-wasm"', '-s',
            'BINARYEN_SCRIPTS="spidermonkify.py"'
        ]
        print ' '.join(command)
        subprocess.check_call(command)

        cmd = [MOZJS, 'a.wasm.js']
        out = run_command(cmd)
        assert 'hello, world!' in out, out

        proc = subprocess.Popen([NODEJS, 'a.wasm.js'],
                                stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE)
        out, err = proc.communicate()
        assert proc.returncode != 0, 'should fail on no wasm support'
        assert 'no native wasm support detected' in err, err

    print '\n[ checking wasm.js methods... ]\n'

    for method_init in [
            'interpret-asm2wasm', 'interpret-s-expr', 'asmjs',
            'interpret-binary', 'asmjs,interpret-binary',
            'interpret-binary,asmjs'
    ]:
        # check success and failure for simple modes, only success for combined/fallback ones
        for success in [1, 0] if ',' not in method_init else [1]:
            method = method_init
            command = [
                EMCC, '-o', 'a.wasm.js', '-s', 'BINARYEN=1',
                os.path.join(options.binaryen_test, 'hello_world.c')
            ]
            command += ['-s', 'BINARYEN_METHOD="' + method + '"']
            print method, ' : ', ' '.join(command), ' => ', success
            subprocess.check_call(command)

            see_polyfill = 'var WasmJS = ' in open('a.wasm.js').read()

            if method and 'interpret' not in method:
                assert not see_polyfill, 'verify polyfill was not added - we specified a method, and it does not need it'
            else:
                assert see_polyfill, 'we need the polyfill'

            def break_cashew():
                asm = open('a.wasm.asm.js').read()
                asm = asm.replace(
                    '"almost asm"',
                    '"use asm"; var not_in_asm = [].length + (true || { x: 5 }.x);'
                )
                asm = asm.replace(
                    "'almost asm'",
                    '"use asm"; var not_in_asm = [].length + (true || { x: 5 }.x);'
                )
                with open('a.wasm.asm.js', 'w') as o:
                    o.write(asm)

            if method.startswith('interpret-asm2wasm'):
                delete_from_orbit(
                    'a.wasm.wast')  # we should not need the .wast
                if not success:
                    break_cashew()  # we need cashew
            elif method.startswith('interpret-s-expr'):
                delete_from_orbit(
                    'a.wasm.asm.js')  # we should not need the .asm.js
                if not success:
                    delete_from_orbit('a.wasm.wast')
            elif method.startswith('asmjs'):
                delete_from_orbit(
                    'a.wasm.wast')  # we should not need the .wast
                break_cashew()  # we don't use cashew, so ok to break it
                if not success:
                    delete_from_orbit('a.wasm.js')
            elif method.startswith('interpret-binary'):
                delete_from_orbit(
                    'a.wasm.wast')  # we should not need the .wast
                delete_from_orbit(
                    'a.wasm.asm.js')  # we should not need the .asm.js
                if not success:
                    delete_from_orbit('a.wasm.wasm')
            else:
                1 / 0
            if NODEJS:
                proc = subprocess.Popen([NODEJS, 'a.wasm.js'],
                                        stdout=subprocess.PIPE,
                                        stderr=subprocess.PIPE)
                out, err = proc.communicate()
                if success:
                    assert proc.returncode == 0, err
                    assert 'hello, world!' in out, out
                else:
                    assert proc.returncode != 0, err
                    assert 'hello, world!' not in out, out

    print '\n[ checking wasm.js testcases... ]\n'

    for c in tests:
        if c.endswith(('.c', '.cpp')):
            print '..', c
            base = c.replace('.cpp', '').replace('.c', '')
            post = base + '.post.js'
            try:
                post = open(os.path.join(options.binaryen_test, post)).read()
            except:
                post = None
            expected = open(os.path.join(options.binaryen_test,
                                         base + '.txt')).read()
            emcc = os.path.join(options.binaryen_test, base + '.emcc')
            extra = []
            if os.path.exists(emcc):
                extra = json.loads(open(emcc).read())
            if os.path.exists('a.normal.js'): os.unlink('a.normal.js')
            for opts in [[], ['-O1'], ['-O2'], ['-O3'], ['-Oz']]:
                for method in [
                        'interpret-asm2wasm', 'interpret-s-expr',
                        'interpret-binary'
                ]:
                    command = [
                        EMCC, '-o', 'a.wasm.js', '-s', 'BINARYEN=1',
                        os.path.join(options.binaryen_test, c)
                    ] + opts + extra
                    command += ['-s', 'BINARYEN_METHOD="' + method + '"']
                    command += ['-s', 'BINARYEN_TRAP_MODE="js"']
                    print '....' + ' '.join(command)
                    subprocess.check_call(command,
                                          stdout=subprocess.PIPE,
                                          stderr=subprocess.PIPE)
                    if post:
                        open('a.wasm.js', 'a').write(post)
                    else:
                        print '     (no post)'
                    for which in ['wasm']:
                        print '......', which
                        try:
                            args = json.loads(
                                open(
                                    os.path.join(options.binaryen_test,
                                                 base + '.args')).read())
                        except:
                            args = []
                            print '     (no args)'

                        def execute():
                            if NODEJS:
                                cmd = [NODEJS, 'a.' + which + '.js'] + args
                                out = run_command(cmd)
                                if out.strip() != expected.strip():
                                    fail(out, expected)

                        execute()

                        if method in ['interpret-s-expr']:
                            # binary and back
                            shutil.copyfile('a.wasm.wast',
                                            'a.wasm.original.wast')
                            recreated = binary_format_check(
                                'a.wasm.wast', verify_final_result=False)
                            shutil.copyfile(recreated, 'a.wasm.wast')
                            execute()
Exemple #10
0
def run_spec_tests():
    print('\n[ checking wasm-shell spec testcases... ]\n')

    for wast in shared.options.spec_tests:
        print('..', os.path.basename(wast))

        def run_spec_test(wast):
            cmd = shared.WASM_SHELL + [wast]
            return support.run_command(cmd, stderr=subprocess.PIPE)

        def run_opt_test(wast):
            # check optimization validation
            cmd = shared.WASM_OPT + [wast, '-O', '-all']
            support.run_command(cmd)

        def check_expected(actual, expected):
            if expected and os.path.exists(expected):
                expected = open(expected).read()
                print('       (using expected output)')
                actual = actual.strip()
                expected = expected.strip()
                if actual != expected:
                    shared.fail(actual, expected)

        expected = os.path.join(shared.get_test_dir('spec'), 'expected-output',
                                os.path.basename(wast) + '.log')

        # some spec tests should fail (actual process failure, not just assert_invalid)
        try:
            actual = run_spec_test(wast)
        except Exception as e:
            if ('wasm-validator error' in str(e) or 'parse exception'
                    in str(e)) and '.fail.' in os.path.basename(wast):
                print('<< test failed as expected >>')
                continue  # don't try all the binary format stuff TODO
            else:
                shared.fail_with_error(str(e))

        check_expected(actual, expected)

        # skip binary checks for tests that reuse previous modules by name, as that's a wast-only feature
        if 'exports.wast' in os.path.basename(wast):  # FIXME
            continue

        # check binary format. here we can verify execution of the final
        # result, no need for an output verification
        # some wast files cannot be split:
        #     * comments.wast: contains characters that are not valid utf-8,
        #       so our string splitting code fails there
        if os.path.basename(wast) not in ['comments.wast']:
            split_num = 0
            actual = ''
            for module, asserts in support.split_wast(wast):
                print('        testing split module', split_num)
                split_num += 1
                support.write_wast('split.wast', module, asserts)
                run_spec_test(
                    'split.wast'
                )  # before binary stuff - just check it's still ok split out
                run_opt_test('split.wast'
                             )  # also that our optimizer doesn't break on it
                result_wast = shared.binary_format_check(
                    'split.wast',
                    verify_final_result=False,
                    original_wast=wast)
                # add the asserts, and verify that the test still passes
                open(result_wast, 'a').write('\n' + '\n'.join(asserts))
                actual += run_spec_test(result_wast)
            # compare all the outputs to the expected output
            check_expected(
                actual,
                os.path.join(shared.get_test_dir('spec'), 'expected-output',
                             os.path.basename(wast) + '.log'))
        else:
            # handle unsplittable wast files
            run_spec_test(wast)
Exemple #11
0
          if asm[0] == 'e':
            cmd += ['--mem-base=1024']
        if 'i64' in asm or 'wasm-only' in asm:
          cmd += ['--wasm-only']
        wasm = os.path.join(options.binaryen_test, wasm)
        print '..', asm, wasm
        actual = run_command(cmd)

        # verify output
        if not os.path.exists(wasm):
          fail_with_error('output .wast file %s does not exist' % wasm)
        expected = open(wasm, 'rb').read()
        if actual != expected:
          fail(actual, expected)

        binary_format_check(wasm, verify_final_result=False)

        # verify in wasm
        if options.interpreter:
          # remove imports, spec interpreter doesn't know what to do with them
          subprocess.check_call(WASM_OPT + ['--remove-imports', wasm], stdout=open('ztemp.wast', 'w'), stderr=subprocess.PIPE)
          proc = subprocess.Popen([options.interpreter, 'ztemp.wast'], stderr=subprocess.PIPE)
          out, err = proc.communicate()
          if proc.returncode != 0:
            try: # to parse the error
              reported = err.split(':')[1]
              start, end = reported.split('-')
              start_line, start_col = map(int, start.split('.'))
              lines = open('ztemp.wast').read().split('\n')
              print
              print '='*80