# Copyright 2016 WebAssembly Community Group participants
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import os
import subprocess

from . import shared, support

basic_tests = shared.get_tests(os.path.join(shared.options.binaryen_test, 'lit', 'basic'))
# memory64 is not supported in wasm2js yet (but may be with BigInt eventually).
basic_tests = [t for t in basic_tests if '64.wast' not in t]
spec_tests = shared.options.spec_tests
spec_tests = [t for t in spec_tests if '.fail' not in t]
spec_tests = [t for t in spec_tests if '64.wast' not in t]
wasm2js_tests = shared.get_tests(shared.get_test_dir('wasm2js'), ['.wast'])
assert_tests = ['wasm2js.wast.asserts']
# These tests exercise functionality not supported by wasm2js
wasm2js_skipped_tests = [
    'empty_imported_table.wast',
    'br.wast',  # depends on multivalue
    'fac.wast',  # depends on mutlivalue
    'br_table.wast',  # needs support for externref in assert_return
]


def check_for_stale_files():
    if shared.options.test_name_filter:
        return

    # TODO(sbc): Generalize and apply other test suites
    all_tests = basic_tests + spec_tests + wasm2js_tests
    all_tests = [os.path.basename(os.path.splitext(t)[0]) for t in all_tests]

    all_files = os.listdir(shared.get_test_dir('wasm2js'))
    for f in all_files:
        prefix = f.split('.')[0]
        if prefix in [t.split('.')[0] for t in assert_tests]:
            continue
        if prefix not in all_tests:
            shared.fail_with_error(f'orphan test output: {f}')


def test_wasm2js_output():
    for opt in (0, 1):
        for t in basic_tests + spec_tests + wasm2js_tests:
            basename = os.path.basename(t)
            if basename in wasm2js_skipped_tests:
                continue

            asm = basename.replace('.wast', '.2asm.js')
            expected_file = os.path.join(shared.get_test_dir('wasm2js'), asm)
            if opt:
                expected_file += '.opt'

            if not os.path.exists(expected_file):
                # It is ok to skip tests from other test suites that we also
                # test on wasm2js (the basic and spec tests). When such files
                # pass in wasm2js, we add expected files for them, so lacking
                # such a file just means we should ignore it. But lacking an
                # expected file for an explicit wasm2js test is an error.
                if t in basic_tests or t in spec_tests:
                    continue
                else:
                    raise Exception(f'missing expected file {expected_file}')

            print('..', os.path.basename(t))

            all_js = []
            all_out = ''

            for module, asserts in support.split_wast(t):
                support.write_wast('split.wast', module, asserts)

                # wasm2js does not yet support EH, and enabling it can reduce
                # optimization opportunities
                cmd = shared.WASM2JS + ['split.wast', '-all',
                                        '--disable-exception-handling']
                if opt:
                    cmd += ['-O']
                if 'emscripten' in basename:
                    cmd += ['--emscripten']
                if 'deterministic' in basename:
                    cmd += ['--deterministic']
                js = support.run_command(cmd)
                all_js.append(js)

                if not shared.NODEJS and not shared.MOZJS:
                    print('No JS interpreters. Skipping spec tests.')
                    continue

                open('a.2asm.mjs', 'w').write(js)

                cmd += ['--allow-asserts']
                js = support.run_command(cmd)
                # also verify it passes pass-debug verifications
                with shared.with_pass_debug():
                    support.run_command(cmd, stderr=subprocess.PIPE)

                open('a.2asm.asserts.mjs', 'w').write(js)

                # verify asm.js is valid js, note that we're using --experimental-modules
                # to enable ESM syntax and we're also passing a custom loader to handle the
                # `spectest` and `env` modules in our tests.
                if shared.NODEJS:
                    loader = os.path.join(shared.options.binaryen_root, 'scripts', 'test', 'node-esm-loader.mjs')
                    node = [shared.NODEJS, '--experimental-modules', '--no-warnings', '--loader', loader]
                    cmd = node[:]
                    cmd.append('a.2asm.mjs')
                    out = support.run_command(cmd)
                    shared.fail_if_not_identical(out, '')
                    cmd = node[:]
                    cmd.append('a.2asm.asserts.mjs')
                    out = support.run_command(cmd, expected_err='', err_ignore='ExperimentalWarning')
                    all_out += out

            shared.fail_if_not_identical_to_file(''.join(all_js), expected_file)
            expected_out = os.path.join(shared.get_test_dir('spec'), 'expected-output', os.path.basename(t) + '.log')
            if os.path.exists(expected_out):
                expected_out = open(expected_out).read()
            else:
                expected_out = ''
            shared.fail_if_not_identical(all_out, expected_out)


def test_asserts_output():
    for wasm in assert_tests:
        print('..', wasm)

        asserts = os.path.basename(wasm).replace('.wast.asserts', '.asserts.js')
        traps = os.path.basename(wasm).replace('.wast.asserts', '.traps.js')
        asserts_expected_file = os.path.join(shared.options.binaryen_test, 'wasm2js', asserts)
        traps_expected_file = os.path.join(shared.options.binaryen_test, 'wasm2js', traps)

        wasm = os.path.join(shared.get_test_dir('wasm2js'), wasm)
        cmd = shared.WASM2JS + [wasm, '--allow-asserts', '-all',
                                '--disable-exception-handling']
        out = support.run_command(cmd)
        shared.fail_if_not_identical_to_file(out, asserts_expected_file)

        cmd += ['--pedantic']
        out = support.run_command(cmd)
        shared.fail_if_not_identical_to_file(out, traps_expected_file)


def test_wasm2js():
    print('\n[ checking wasm2js testcases... ]\n')
    check_for_stale_files()
    if shared.skip_if_on_windows('wasm2js'):
        return
    test_wasm2js_output()
    test_asserts_output()


def update_wasm2js_tests():
    print('\n[ checking wasm2js ]\n')

    for opt in (0, 1):
        for wasm in basic_tests + spec_tests + wasm2js_tests:
            if not wasm.endswith('.wast'):
                continue

            basename = os.path.basename(wasm)
            if basename in wasm2js_skipped_tests:
                continue

            asm = basename.replace('.wast', '.2asm.js')
            expected_file = os.path.join(shared.get_test_dir('wasm2js'), asm)
            if opt:
                expected_file += '.opt'

            # we run wasm2js on tests and spec tests only if the output
            # exists - only some work so far. the tests in extra are in
            # the test/wasm2js dir and so are specific to wasm2js, and
            # we run all of those.
            if wasm not in wasm2js_tests and not os.path.exists(expected_file):
                continue

            print('..', wasm)

            t = os.path.join(shared.options.binaryen_test, wasm)

            all_out = []

            for module, asserts in support.split_wast(t):
                support.write_wast('split.wast', module, asserts)

                # wasm2js does not yet support EH, and enable it can reduce
                # optimization opportunities
                cmd = shared.WASM2JS + ['split.wast', '-all',
                                        '--disable-exception-handling']
                if opt:
                    cmd += ['-O']
                if 'emscripten' in basename:
                    cmd += ['--emscripten']
                if 'deterministic' in basename:
                    cmd += ['--deterministic']
                out = support.run_command(cmd)
                all_out.append(out)

            with open(expected_file, 'w') as o:
                o.write(''.join(all_out))

    for wasm in assert_tests:
        print('..', wasm)

        asserts = os.path.basename(wasm).replace('.wast.asserts', '.asserts.js')
        traps = os.path.basename(wasm).replace('.wast.asserts', '.traps.js')
        asserts_expected_file = os.path.join(shared.options.binaryen_test, 'wasm2js', asserts)
        traps_expected_file = os.path.join(shared.options.binaryen_test, 'wasm2js', traps)

        cmd = shared.WASM2JS + [os.path.join(shared.get_test_dir('wasm2js'), wasm), '--allow-asserts', '-all', '--disable-exception-handling']
        out = support.run_command(cmd)
        with open(asserts_expected_file, 'w') as o:
            o.write(out)

        cmd += ['--pedantic']
        out = support.run_command(cmd)
        with open(traps_expected_file, 'w') as o:
            o.write(out)
