#!/usr/bin/env python3
# SPDX-License-Identifier: Apache-2.0
# Copyright 2016-2021 The Meson development team

# Work around some pathlib bugs...
from mesonbuild import _pathlib
import sys
sys.modules['pathlib'] = _pathlib

import time
import subprocess
import os
import unittest
import importlib
import typing as T

import mesonbuild.coredata
from mesonbuild.mesonlib import python_command, setup_vsenv


def convert_args(argv):
    # If we got passed a list of tests, pass it on
    pytest_args = ['-v'] if '-v' in argv else []
    test_list = []
    for arg in argv:
        if arg.startswith('-'):
            if arg in ('-f', '--failfast'):
                arg = '--exitfirst'
            pytest_args.append(arg)
            continue
        # ClassName.test_name => 'ClassName and test_name'
        if '.' in arg:
            arg = ' and '.join(arg.split('.'))
        test_list.append(arg)
    if test_list:
        pytest_args += ['-k', ' or '.join(test_list)]
    return pytest_args

def running_single_tests(argv, cases):
    '''
    Check whether we only got arguments for running individual tests, not
    entire testcases, and not all testcases (no test args).
    '''
    got_test_arg = False
    for arg in argv:
        if arg.startswith('-'):
            continue
        for case in cases:
            if not arg.startswith(case):
                continue
            if '.' not in arg:
                # Got a testcase, done
                return False
            got_test_arg = True
    return got_test_arg

def setup_backend():
    filtered = []
    be = 'ninja'
    for a in sys.argv:
        if a.startswith('--backend'):
            be = a.split('=')[1]
        else:
            filtered.append(a)
    # Since we invoke the tests via unittest or xtest test runner
    # we need to pass the backend to use to the spawned process via
    # this side channel. Yes it sucks, but at least is is fully
    # internal to this file.
    os.environ['MESON_UNIT_TEST_BACKEND'] = be
    sys.argv = filtered

def import_test_cases(suite: unittest.TestSuite) -> T.Set[str]:
    '''
    Imports all test classes into the current module and returns their names
    '''
    classes = set()
    for test in suite:
        if isinstance(test, unittest.TestSuite):
            classes.update(import_test_cases(test))
        elif isinstance(test, unittest.TestCase):
            mod = importlib.import_module(test.__module__)
            class_name = test.__class__.__name__
            test_class = getattr(mod, class_name)
            classes.add(class_name)
            setattr(sys.modules[__name__], class_name, test_class)
    return classes

def discover_test_cases() -> T.Set[str]:
    current_dir = os.path.dirname(os.path.realpath(__file__))
    loader = unittest.TestLoader()
    suite = loader.discover(os.path.join(current_dir, 'unittests'), '*tests.py', current_dir)
    if loader.errors:
        raise SystemExit(loader.errors)
    return import_test_cases(suite)

def main():
    cases = sorted(discover_test_cases())
    setup_backend()

    try:
        import pytest # noqa: F401
        pytest_args = []
        try:
            # Need pytest-xdist for `-n` arg
            import xdist # noqa: F401
            # Don't use pytest-xdist when running single unit tests since it wastes
            # time spawning a lot of processes to distribute tests to in that case.
            if not running_single_tests(sys.argv, cases):
                pytest_args += ['-n', 'auto']
        except ImportError:
            print('pytest-xdist not found, tests will not be distributed across CPU cores')
        # Let there be colors!
        if 'CI' in os.environ:
            pytest_args += ['--color=yes']
        pytest_args += ['unittests']
        pytest_args += convert_args(sys.argv[1:])
        # Always disable pytest-cov because we use a custom setup
        try:
            import pytest_cov # noqa: F401
            print('Disabling pytest-cov')
            pytest_args += ['-p' 'no:cov']
        except ImportError:
            pass
        return subprocess.run(python_command + ['-m', 'pytest'] + pytest_args).returncode
    except ImportError:
        print('pytest not found, using unittest instead')
    # Fallback to plain unittest.
    return unittest.main(defaultTest=cases, buffer=True)

if __name__ == '__main__':
    setup_vsenv()
    print('Meson build system', mesonbuild.coredata.version, 'Unit Tests')
    start = time.monotonic()
    try:
        raise SystemExit(main())
    finally:
        print('Total time: {:.3f} seconds'.format(time.monotonic() - start))
