# SPDX-License-Identifier: Apache-2.0
# Copyright 2021 The Meson development team
# Copyright © 2024 Intel Corporation

from __future__ import annotations
import json
import os
import pickle
import subprocess
import tempfile
import subprocess
import textwrap
import shutil
from unittest import skipIf, SkipTest
from pathlib import Path

from .baseplatformtests import BasePlatformTests
from .helpers import is_ci
from mesonbuild.mesonlib import EnvironmentVariables, ExecutableSerialisation, MesonException, is_linux, python_command, windows_proof_rmtree
from mesonbuild.mformat import Formatter, match_path
from mesonbuild.optinterpreter import OptionInterpreter, OptionException
from mesonbuild.options import OptionStore
from run_tests import Backend

@skipIf(is_ci() and not is_linux(), "Run only on fast platforms")
class PlatformAgnosticTests(BasePlatformTests):
    '''
    Tests that does not need to run on all platforms during CI
    '''

    def test_relative_find_program(self):
        '''
        Tests that find_program() with a relative path does not find the program
        in current workdir.
        '''
        testdir = os.path.join(self.unit_test_dir, '101 relative find program')
        self.init(testdir, workdir=testdir)

    def test_invalid_option_names(self):
        store = OptionStore(False)
        interp = OptionInterpreter(store, '')

        def write_file(code: str):
            with tempfile.NamedTemporaryFile('w', dir=self.builddir, encoding='utf-8', delete=False) as f:
                f.write(code)
                return f.name

        fname = write_file("option('default_library', type: 'string')")
        self.assertRaisesRegex(OptionException, 'Option name default_library is reserved.',
                               interp.process, fname)

        fname = write_file("option('c_anything', type: 'string')")
        self.assertRaisesRegex(OptionException, 'Option name c_anything is reserved.',
                               interp.process, fname)

        fname = write_file("option('b_anything', type: 'string')")
        self.assertRaisesRegex(OptionException, 'Option name b_anything is reserved.',
                               interp.process, fname)

        fname = write_file("option('backend_anything', type: 'string')")
        self.assertRaisesRegex(OptionException, 'Option name backend_anything is reserved.',
                               interp.process, fname)

        fname = write_file("option('foo.bar', type: 'string')")
        self.assertRaisesRegex(OptionException, 'Option names can only contain letters, numbers or dashes.',
                               interp.process, fname)

        # platlib is allowed, only python.platlib is reserved.
        fname = write_file("option('platlib', type: 'string')")
        interp.process(fname)

    def test_option_validation(self):
        """Test cases that are not catch by the optinterpreter itself."""
        store = OptionStore(False)
        interp = OptionInterpreter(store, '')

        def write_file(code: str):
            with tempfile.NamedTemporaryFile('w', dir=self.builddir, encoding='utf-8', delete=False) as f:
                f.write(code)
                return f.name

        fname = write_file("option('intminmax', type: 'integer', value: 10, min: 0, max: 5)")
        self.assertRaisesRegex(MesonException, 'Value 10 for option "intminmax" is more than maximum value 5.',
                               interp.process, fname)

        fname = write_file("option('array', type: 'array', choices : ['one', 'two', 'three'], value : ['one', 'four'])")
        self.assertRaisesRegex(MesonException, 'Value "four" for option "array" is not in allowed choices: "one, two, three"',
                               interp.process, fname)

        fname = write_file("option('array', type: 'array', choices : ['one', 'two', 'three'], value : ['four', 'five', 'six'])")
        self.assertRaisesRegex(MesonException, 'Values "four, five, six" for option "array" are not in allowed choices: "one, two, three"',
                               interp.process, fname)

    def test_python_dependency_without_pkgconfig(self):
        testdir = os.path.join(self.unit_test_dir, '103 python without pkgconfig')
        self.init(testdir, override_envvars={'PKG_CONFIG': 'notfound'})

    def test_debug_function_outputs_to_meson_log(self):
        testdir = os.path.join(self.unit_test_dir, '105 debug function')
        log_msg = 'This is an example debug output, should only end up in debug log'
        output = self.init(testdir)

        # Check if message is not printed to stdout while configuring
        self.assertNotIn(log_msg, output)

        # Check if message is written to the meson log
        mesonlog = self.get_meson_log_raw()
        self.assertIn(log_msg, mesonlog)

    def test_new_subproject_reconfigure(self):
        testdir = os.path.join(self.unit_test_dir, '109 new subproject on reconfigure')
        self.init(testdir)
        self.build()

        # Enable the subproject "foo" and reconfigure, this is used to fail
        # because per-subproject builtin options were not initialized:
        # https://github.com/mesonbuild/meson/issues/10225.
        self.setconf('-Dfoo=enabled')
        self.build('reconfigure')

    def check_connectivity(self):
        import urllib
        try:
            with urllib.request.urlopen('https://wrapdb.mesonbuild.com') as p:
                pass
        except urllib.error.URLError as e:
            self.skipTest('No internet connectivity: ' + str(e))

    def test_update_wrapdb(self):
        self.check_connectivity()
        # Write the project into a temporary directory because it will add files
        # into subprojects/ and we don't want to pollute meson source tree.
        with tempfile.TemporaryDirectory() as testdir:
            with Path(testdir, 'meson.build').open('w', encoding='utf-8') as f:
                f.write(textwrap.dedent(
                    '''
                    project('wrap update-db',
                      default_options: ['wrap_mode=forcefallback'])

                    zlib_dep = dependency('zlib')
                    assert(zlib_dep.type_name() == 'internal')
                    '''))
            subprocess.check_call(self.wrap_command + ['update-db'], cwd=testdir)
            self.init(testdir, workdir=testdir)

    def test_none_backend(self):
        testdir = os.path.join(self.python_test_dir, '7 install path')

        self.init(testdir, extra_args=['--backend=none'], override_envvars={'NINJA': 'absolutely false command'})
        self.assertPathDoesNotExist(os.path.join(self.builddir, 'build.ninja'))

        self.run_tests(inprocess=True, override_envvars={})

        out = self._run(self.meson_command + ['install', f'--destdir={self.installdir}'], workdir=self.builddir)
        self.assertNotIn('Only ninja backend is supported to rebuild the project before installation.', out)

        with open(os.path.join(testdir, 'test.json'), 'rb') as f:
            dat = json.load(f)
        for i in dat['installed']:
            self.assertPathExists(os.path.join(self.installdir, i['file']))

    def test_change_backend(self):
        if self.backend != Backend.ninja:
            raise SkipTest('Only useful to test if backend is ninja.')

        testdir = os.path.join(self.python_test_dir, '7 install path')
        self.init(testdir)

        # no-op change works
        self.setconf(f'--backend=ninja')
        self.init(testdir, extra_args=['--reconfigure', '--backend=ninja'])

        # Change backend option is not allowed
        with self.assertRaises(subprocess.CalledProcessError) as cm:
            self.setconf('-Dbackend=none')
        self.assertIn("ERROR: Tried to modify read only option 'backend'", cm.exception.stdout)

        # Check that the new value was not written in the store.
        self.assertEqual(self.getconf('backend'), 'ninja')

        # Wipe with a different backend is allowed
        self.init(testdir, extra_args=['--wipe', '--backend=none'])

        self.assertEqual(self.getconf('backend'), 'none')

    def test_validate_dirs(self):
        testdir = os.path.join(self.common_test_dir, '1 trivial')

        # Using parent as builddir should fail
        self.builddir = os.path.dirname(self.builddir)
        with self.assertRaises(subprocess.CalledProcessError) as cm:
            self.init(testdir)
        self.assertIn('cannot be a parent of source directory', cm.exception.stdout)

        # Reconfigure of empty builddir should work
        self.new_builddir()
        self.init(testdir, extra_args=['--reconfigure'])

        # Reconfigure of not empty builddir should work
        self.new_builddir()
        Path(self.builddir, 'dummy').touch()
        self.init(testdir, extra_args=['--reconfigure'])

        # Setup a valid builddir should update options but not reconfigure
        self.assertEqual(self.getconf('buildtype'), 'debug')
        o = self.init(testdir, extra_args=['-Dbuildtype=release'])
        self.assertIn('Directory already configured', o)
        self.assertNotIn('The Meson build system', o)
        self.assertEqual(self.getconf('buildtype'), 'release')

        # Wipe of empty builddir should work
        self.new_builddir()
        self.init(testdir, extra_args=['--wipe'])

        # Wipe of partial builddir should work
        self.new_builddir()
        Path(self.builddir, 'meson-private').mkdir()
        Path(self.builddir, 'dummy').touch()
        self.init(testdir, extra_args=['--wipe'])

        # Wipe of not empty builddir should fail
        self.new_builddir()
        Path(self.builddir, 'dummy').touch()
        with self.assertRaises(subprocess.CalledProcessError) as cm:
            self.init(testdir, extra_args=['--wipe'])
        self.assertIn('Directory is not empty', cm.exception.stdout)

    def test_scripts_loaded_modules(self):
        '''
        Simulate a wrapped command, as done for custom_target() that capture
        output. The script will print all python modules loaded and we verify
        that it contains only an acceptable subset. Loading too many modules
        slows down the build when many custom targets get wrapped.

        This list must not be edited without a clear rationale for why it is
        acceptable to do so!
        '''
        es = ExecutableSerialisation(python_command + ['-c', 'exit(0)'], env=EnvironmentVariables())
        p = Path(self.builddir, 'exe.dat')
        with p.open('wb') as f:
            pickle.dump(es, f)
        cmd = self.meson_command + ['--internal', 'test_loaded_modules', '--unpickle', str(p)]
        p = subprocess.run(cmd, stdout=subprocess.PIPE)
        all_modules = json.loads(p.stdout.splitlines()[0])
        meson_modules = [m for m in all_modules if m.startswith('mesonbuild')]
        expected_meson_modules = [
            'mesonbuild',
            'mesonbuild._pathlib',
            'mesonbuild.utils',
            'mesonbuild.utils.core',
            'mesonbuild.mesonmain',
            'mesonbuild.mlog',
            'mesonbuild.scripts',
            'mesonbuild.scripts.meson_exe',
            'mesonbuild.scripts.test_loaded_modules'
        ]
        self.assertEqual(sorted(expected_meson_modules), sorted(meson_modules))

    def test_setup_loaded_modules(self):
        '''
        Execute a very basic meson.build and capture a list of all python
        modules loaded. We verify that it contains only an acceptable subset.
        Loading too many modules slows down `meson setup` startup time and
        gives a perception that meson is slow.

        Adding more modules to the default startup flow is not an unreasonable
        thing to do as new features are added, but keeping track of them is
        good.
        '''
        testdir = os.path.join(self.unit_test_dir, '117 empty project')

        self.init(testdir)
        self._run(self.meson_command + ['--internal', 'regenerate', '--profile-self', testdir, self.builddir])
        with open(os.path.join(self.builddir, 'meson-logs', 'profile-startup-modules.json'), encoding='utf-8') as f:
                data = json.load(f)['meson']

        with open(os.path.join(testdir, 'expected_mods.json'), encoding='utf-8') as f:
            expected = json.load(f)['meson']['modules']

        self.assertEqual(data['modules'], expected)
        self.assertEqual(data['count'], 70)

    def test_meson_package_cache_dir(self):
        # Copy testdir into temporary directory to not pollute meson source tree.
        testdir = os.path.join(self.unit_test_dir, '119 meson package cache dir')
        srcdir = os.path.join(self.builddir, 'srctree')
        shutil.copytree(testdir, srcdir)
        builddir = os.path.join(srcdir, '_build')
        self.change_builddir(builddir)
        self.init(srcdir, override_envvars={'MESON_PACKAGE_CACHE_DIR': os.path.join(srcdir, 'cache_dir')})

    def test_cmake_openssl_not_found_bug(self):
        """Issue #12098"""
        testdir = os.path.join(self.unit_test_dir, '120 openssl cmake bug')
        self.meson_native_files.append(os.path.join(testdir, 'nativefile.ini'))
        out = self.init(testdir, allow_fail=True)
        self.assertNotIn('Unhandled python exception', out)

    def test_editorconfig_match_path(self):
        '''match_path function used to parse editorconfig in meson format'''
        cases = [
            ('a.txt', '*.txt', True),
            ('a.txt', '?.txt', True),
            ('a.txt', 'a.t?t', True),
            ('a.txt', '*.build', False),

            ('/a.txt', '*.txt', True),
            ('/a.txt', '/*.txt', True),
            ('a.txt', '/*.txt', False),

            ('a/b/c.txt', 'a/b/*.txt', True),
            ('a/b/c.txt', 'a/*/*.txt', True),
            ('a/b/c.txt', '*/*.txt', True),
            ('a/b/c.txt', 'b/*.txt', True),
            ('a/b/c.txt', 'a/*.txt', False),

            ('a/b/c/d.txt', 'a/**/*.txt', True),
            ('a/b/c/d.txt', 'a/*', False),
            ('a/b/c/d.txt', 'a/**', True),

            ('a.txt', '[abc].txt', True),
            ('a.txt', '[!xyz].txt', True),
            ('a.txt', '[xyz].txt', False),
            ('a.txt', '[!abc].txt', False),

            ('a.txt', '{a,b,c}.txt', True),
            ('a.txt', '*.{txt,tex,cpp}', True),
            ('a.hpp', '*.{txt,tex,cpp}', False),

            ('a1.txt', 'a{0..9}.txt', True),
            ('a001.txt', 'a{0..9}.txt', True),
            ('a-1.txt', 'a{-10..10}.txt', True),
            ('a99.txt', 'a{0..9}.txt', False),
            ('a099.txt', 'a{0..9}.txt', False),
            ('a-1.txt', 'a{0..10}.txt', False),
        ]

        for filename, pattern, expected in cases:
            self.assertTrue(match_path(filename, pattern) is expected, f'{filename} -> {pattern}')

    def test_format_invalid_config_key(self) -> None:
        fd, fname = tempfile.mkstemp(suffix='.ini', text=True)
        self.addCleanup(os.unlink, fname)

        with os.fdopen(fd, 'w', encoding='utf-8') as handle:
            handle.write('not_an_option = 42\n')

        with self.assertRaises(MesonException):
            Formatter(Path(fname), use_editor_config=False, fetch_subdirs=False)

    def test_format_invalid_config_value(self) -> None:
        fd, fname = tempfile.mkstemp(suffix='.ini', text=True)
        self.addCleanup(os.unlink, fname)

        with os.fdopen(fd, 'w', encoding='utf-8') as handle:
            handle.write('max_line_length = string\n')

        with self.assertRaises(MesonException):
            Formatter(Path(fname), use_editor_config=False, fetch_subdirs=False)

    def test_format_invalid_editorconfig_value(self) -> None:
        dirpath = tempfile.mkdtemp()
        self.addCleanup(windows_proof_rmtree, dirpath)

        editorconfig = Path(dirpath, '.editorconfig')
        with open(editorconfig, 'w', encoding='utf-8') as handle:
            handle.write('[*]\n')
            handle.write('indent_size = string\n')

        formatter = Formatter(None, use_editor_config=True, fetch_subdirs=False)
        with self.assertRaises(MesonException):
            formatter.load_editor_config(editorconfig)

    def test_format_empty_file(self) -> None:
        formatter = Formatter(None, use_editor_config=False, fetch_subdirs=False)
        for code in ('', '\n'):
            formatted = formatter.format(code, Path())
            self.assertEqual('\n', formatted)

    def test_format_indent_comment_in_brackets(self) -> None:
        """Ensure comments in arrays and dicts are correctly indented"""
        formatter = Formatter(None, use_editor_config=False, fetch_subdirs=False)
        code = 'a = [\n    # comment\n]\n'
        formatted = formatter.format(code, Path())
        self.assertEqual(code, formatted)

        code = 'a = [\n    # comment\n    1,\n]\n'
        formatted = formatter.format(code, Path())
        self.assertEqual(code, formatted)

        code = 'a = {\n    # comment\n}\n'
        formatted = formatter.format(code, Path())
        self.assertEqual(code, formatted)

    def test_error_configuring_subdir(self):
        testdir = os.path.join(self.common_test_dir, '152 index customtarget')
        out = self.init(os.path.join(testdir, 'subdir'), allow_fail=True)

        self.assertIn('first statement must be a call to project()', out)
        # provide guidance diagnostics by finding a file whose first AST statement is project()
        self.assertIn(f'Did you mean to run meson from the directory: "{testdir}"?', out)

    def test_reconfigure_base_options(self):
        testdir = os.path.join(self.unit_test_dir, '123 reconfigure base options')
        out = self.init(testdir, extra_args=['-Db_ndebug=true'])
        self.assertIn('\nMessage: b_ndebug: true\n', out)
        self.assertIn('\nMessage: c_std: c89\n', out)

        out = self.init(testdir, extra_args=['--reconfigure', '-Db_ndebug=if-release', '-Dsub:b_ndebug=false', '-Dc_std=c99', '-Dsub:c_std=c11'])
        self.assertIn('\n    b_ndebug    : if-release\n', out)
        self.assertIn('\n    c_std       : c99\n', out)
        self.assertIn('\n    sub:b_ndebug: false\n', out)
        self.assertIn('\n    sub:c_std   : c11\n', out)

    def test_setup_with_unknown_option(self):
        testdir = os.path.join(self.common_test_dir, '1 trivial')

        out = self.init(testdir, extra_args=['--wipe', f'-Dnot_an_option=1'], allow_fail=True)
        self.assertIn('ERROR: Unknown options: "not_an_option"', out)

        out = self.init(testdir, extra_args=['--wipe', f'-Db_not_an_option=1'])
        self.assertIn('WARNING: The following command line option(s) were not used: b_not_an_option', out)


    def test_configure_new_option(self) -> None:
        """Adding a new option without reconfiguring should work."""
        testdir = self.copy_srcdir(os.path.join(self.common_test_dir, '40 options'))
        self.init(testdir)
        with open(os.path.join(testdir, 'meson_options.txt'), 'a', encoding='utf-8') as f:
            f.write("option('new_option', type : 'boolean', value : false)")
        self.setconf('-Dnew_option=true')
        self.assertEqual(self.getconf('new_option'), True)

    def test_configure_removed_option(self) -> None:
        """Removing an options without reconfiguring should still give an error."""
        testdir = self.copy_srcdir(os.path.join(self.common_test_dir, '40 options'))
        self.init(testdir)
        with open(os.path.join(testdir, 'meson_options.txt'), 'r', encoding='utf-8') as f:
            opts = f.readlines()
        with open(os.path.join(testdir, 'meson_options.txt'), 'w', encoding='utf-8') as f:
            for line in opts:
                if line.startswith("option('neg'"):
                    continue
                f.write(line)
        with self.assertRaises(subprocess.CalledProcessError) as e:
            self.setconf('-Dneg_int_opt=0')
        self.assertIn('Unknown options: "neg_int_opt"', e.exception.stdout)

    def test_configure_option_changed_constraints(self) -> None:
        """Changing the constraints of an option without reconfiguring should work."""
        testdir = self.copy_srcdir(os.path.join(self.common_test_dir, '40 options'))
        self.init(testdir)
        with open(os.path.join(testdir, 'meson_options.txt'), 'r', encoding='utf-8') as f:
            opts = f.readlines()
        with open(os.path.join(testdir, 'meson_options.txt'), 'w', encoding='utf-8') as f:
            for line in opts:
                if line.startswith("option('neg'"):
                    f.write("option('neg_int_opt', type : 'integer', min : -10, max : 10, value : -3)\n")
                else:
                    f.write(line)
        self.setconf('-Dneg_int_opt=-10')
        self.assertEqual(self.getconf('neg_int_opt'), -10)

    def test_configure_meson_options_txt_to_meson_options(self) -> None:
        """Changing from a meson_options.txt to meson.options should still be detected."""
        testdir = self.copy_srcdir(os.path.join(self.common_test_dir, '40 options'))
        self.init(testdir)
        with open(os.path.join(testdir, 'meson_options.txt'), 'r', encoding='utf-8') as f:
            opts = f.readlines()
        with open(os.path.join(testdir, 'meson_options.txt'), 'w', encoding='utf-8') as f:
            for line in opts:
                if line.startswith("option('neg'"):
                    f.write("option('neg_int_opt', type : 'integer', min : -10, max : 10, value : -3)\n")
                else:
                    f.write(line)
        shutil.move(os.path.join(testdir, 'meson_options.txt'), os.path.join(testdir, 'meson.options'))
        self.setconf('-Dneg_int_opt=-10')
        self.assertEqual(self.getconf('neg_int_opt'), -10)

    def test_configure_options_file_deleted(self) -> None:
        """Deleting all option files should make seting a project option an error."""
        testdir = self.copy_srcdir(os.path.join(self.common_test_dir, '40 options'))
        self.init(testdir)
        os.unlink(os.path.join(testdir, 'meson_options.txt'))
        with self.assertRaises(subprocess.CalledProcessError) as e:
            self.setconf('-Dneg_int_opt=0')
        self.assertIn('Unknown options: "neg_int_opt"', e.exception.stdout)

    def test_configure_options_file_added(self) -> None:
        """A new project option file should be detected."""
        testdir = self.copy_srcdir(os.path.join(self.common_test_dir, '1 trivial'))
        self.init(testdir)
        with open(os.path.join(testdir, 'meson.options'), 'w', encoding='utf-8') as f:
            f.write("option('new_option', type : 'string', value : 'foo')")
        self.setconf('-Dnew_option=bar')
        self.assertEqual(self.getconf('new_option'), 'bar')

    def test_configure_options_file_added_old(self) -> None:
        """A new project option file should be detected."""
        testdir = self.copy_srcdir(os.path.join(self.common_test_dir, '1 trivial'))
        self.init(testdir)
        with open(os.path.join(testdir, 'meson_options.txt'), 'w', encoding='utf-8') as f:
            f.write("option('new_option', type : 'string', value : 'foo')")
        self.setconf('-Dnew_option=bar')
        self.assertEqual(self.getconf('new_option'), 'bar')

    def test_configure_new_option_subproject(self) -> None:
        """Adding a new option to a subproject without reconfiguring should work."""
        testdir = self.copy_srcdir(os.path.join(self.common_test_dir, '43 subproject options'))
        self.init(testdir)
        with open(os.path.join(testdir, 'subprojects/subproject/meson_options.txt'), 'a', encoding='utf-8') as f:
            f.write("option('new_option', type : 'boolean', value : false)")
        self.setconf('-Dsubproject:new_option=true')
        self.assertEqual(self.getconf('subproject:new_option'), True)

    def test_mtest_rebuild_deps(self):
        testdir = os.path.join(self.unit_test_dir, '107 underspecified mtest')
        self.init(testdir)

        with self.assertRaises(subprocess.CalledProcessError):
            self._run(self.mtest_command)
        self.clean()

        with self.assertRaises(subprocess.CalledProcessError):
            self._run(self.mtest_command + ['runner-without-dep'])
        self.clean()

        self._run(self.mtest_command + ['runner-with-exedep'])
