# SPDX-License-Identifier: GPL-2.0+
# Copyright 2022 Google LLC
# Written by Simon Glass <sjg@chromium.org>
#

"""Tests for the Bintool class"""

import collections
import os
import shutil
import tempfile
import unittest
import unittest.mock
import urllib.error

from binman import bintool
from binman.bintool import Bintool

from patman import command
from patman import terminal
from patman import test_util
from patman import tools

# pylint: disable=R0904
class TestBintool(unittest.TestCase):
    """Tests for the Bintool class"""
    def setUp(self):
        # Create a temporary directory for test files
        self._indir = tempfile.mkdtemp(prefix='bintool.')
        self.seq = None
        self.count = None
        self.fname = None
        self.btools = None

    def tearDown(self):
        """Remove the temporary input directory and its contents"""
        if self._indir:
            shutil.rmtree(self._indir)
        self._indir = None

    def test_missing_btype(self):
        """Test that unknown bintool types are detected"""
        with self.assertRaises(ValueError) as exc:
            Bintool.create('missing')
        self.assertIn("No module named 'binman.btool.missing'",
                      str(exc.exception))

    def test_fresh_bintool(self):
        """Check that the _testing bintool is not cached"""
        btest = Bintool.create('_testing')
        btest.present = True
        btest2 = Bintool.create('_testing')
        self.assertFalse(btest2.present)

    def test_version(self):
        """Check handling of a tool being present or absent"""
        btest = Bintool.create('_testing')
        with test_util.capture_sys_output() as (stdout, _):
            btest.show()
        self.assertFalse(btest.is_present())
        self.assertIn('-', stdout.getvalue())
        btest.present = True
        self.assertTrue(btest.is_present())
        self.assertEqual('123', btest.version())
        with test_util.capture_sys_output() as (stdout, _):
            btest.show()
        self.assertIn('123', stdout.getvalue())

    def test_fetch_present(self):
        """Test fetching of a tool"""
        btest = Bintool.create('_testing')
        btest.present = True
        col = terminal.Color()
        self.assertEqual(bintool.PRESENT,
                         btest.fetch_tool(bintool.FETCH_ANY, col, True))

    @classmethod
    def check_fetch_url(cls, fake_download, method):
        """Check the output from fetching a tool

        Args:
            fake_download (function): Function to call instead of
                tools.download()
            method (bintool.FETCH_...: Fetch method to use

        Returns:
            str: Contents of stdout
        """
        btest = Bintool.create('_testing')
        col = terminal.Color()
        with unittest.mock.patch.object(tools, 'download',
                                        side_effect=fake_download):
            with test_util.capture_sys_output() as (stdout, _):
                btest.fetch_tool(method, col, False)
        return stdout.getvalue()

    def test_fetch_url_err(self):
        """Test an error while fetching a tool from a URL"""
        def fail_download(url):
            """Take the tools.download() function by raising an exception"""
            raise urllib.error.URLError('my error')

        stdout = self.check_fetch_url(fail_download, bintool.FETCH_ANY)
        self.assertIn('my error', stdout)

    def test_fetch_url_exception(self):
        """Test an exception while fetching a tool from a URL"""
        def cause_exc(url):
            raise ValueError('exc error')

        stdout = self.check_fetch_url(cause_exc, bintool.FETCH_ANY)
        self.assertIn('exc error', stdout)

    def test_fetch_method(self):
        """Test fetching using a particular method"""
        def fail_download(url):
            """Take the tools.download() function by raising an exception"""
            raise urllib.error.URLError('my error')

        stdout = self.check_fetch_url(fail_download, bintool.FETCH_BIN)
        self.assertIn('my error', stdout)

    def test_fetch_pass_fail(self):
        """Test fetching multiple tools with some passing and some failing"""
        def handle_download(_):
            """Take the tools.download() function by writing a file"""
            if self.seq:
                raise urllib.error.URLError('not found')
            self.seq += 1
            tools.write_file(fname, expected)
            return fname, dirname

        expected = b'this is a test'
        dirname = os.path.join(self._indir, 'download_dir')
        os.mkdir(dirname)
        fname = os.path.join(dirname, 'downloaded')
        destdir = os.path.join(self._indir, 'dest_dir')
        os.mkdir(destdir)
        dest_fname = os.path.join(destdir, '_testing')
        self.seq = 0

        with unittest.mock.patch.object(bintool, 'DOWNLOAD_DESTDIR', destdir):
            with unittest.mock.patch.object(tools, 'download',
                                            side_effect=handle_download):
                with test_util.capture_sys_output() as (stdout, _):
                    Bintool.fetch_tools(bintool.FETCH_ANY, ['_testing'] * 2)
        self.assertTrue(os.path.exists(dest_fname))
        data = tools.read_file(dest_fname)
        self.assertEqual(expected, data)

        lines = stdout.getvalue().splitlines()
        self.assertTrue(len(lines) > 2)
        self.assertEqual('Tools fetched:    1: _testing', lines[-2])
        self.assertEqual('Failures:         1: _testing', lines[-1])

    def test_tool_list(self):
        """Test listing available tools"""
        self.assertGreater(len(Bintool.get_tool_list()), 3)

    def check_fetch_all(self, method):
        """Helper to check the operation of fetching all tools"""

        # pylint: disable=W0613
        def fake_fetch(method, col, skip_present):
            """Fakes the Binutils.fetch() function

            Returns FETCHED and FAIL on alternate calls
            """
            self.seq += 1
            result = bintool.FETCHED if self.seq & 1 else bintool.FAIL
            self.count[result] += 1
            return result

        self.seq = 0
        self.count = collections.defaultdict(int)
        with unittest.mock.patch.object(bintool.Bintool, 'fetch_tool',
                                        side_effect=fake_fetch):
            with test_util.capture_sys_output() as (stdout, _):
                Bintool.fetch_tools(method, ['all'])
        lines = stdout.getvalue().splitlines()
        self.assertIn(f'{self.count[bintool.FETCHED]}: ', lines[-2])
        self.assertIn(f'{self.count[bintool.FAIL]}: ', lines[-1])

    def test_fetch_all(self):
        """Test fetching all tools"""
        self.check_fetch_all(bintool.FETCH_ANY)

    def test_fetch_all_specific(self):
        """Test fetching all tools with a specific method"""
        self.check_fetch_all(bintool.FETCH_BIN)

    def test_fetch_missing(self):
        """Test fetching missing tools"""
        # pylint: disable=W0613
        def fake_fetch2(method, col, skip_present):
            """Fakes the Binutils.fetch() function

            Returns PRESENT only for the '_testing' bintool
            """
            btool = list(self.btools.values())[self.seq]
            self.seq += 1
            print('fetch', btool.name)
            if btool.name == '_testing':
                return bintool.PRESENT
            return bintool.FETCHED

        # Preload a list of tools to return when get_tool_list() and create()
        # are called
        all_tools = Bintool.get_tool_list(True)
        self.btools = collections.OrderedDict()
        for name in all_tools:
            self.btools[name] = Bintool.create(name)
        self.seq = 0
        with unittest.mock.patch.object(bintool.Bintool, 'fetch_tool',
                                        side_effect=fake_fetch2):
            with unittest.mock.patch.object(bintool.Bintool,
                                            'get_tool_list',
                                            side_effect=[all_tools]):
                with unittest.mock.patch.object(bintool.Bintool, 'create',
                                                side_effect=self.btools.values()):
                    with test_util.capture_sys_output() as (stdout, _):
                        Bintool.fetch_tools(bintool.FETCH_ANY, ['missing'])
        lines = stdout.getvalue().splitlines()
        num_tools = len(self.btools)
        fetched = [line for line in lines if 'Tools fetched:' in line].pop()
        present = [line for line in lines if 'Already present:' in line].pop()
        self.assertIn(f'{num_tools - 1}: ', fetched)
        self.assertIn('1: ', present)

    def check_build_method(self, write_file):
        """Check the output from fetching using the BUILD method

        Args:
            write_file (bool): True to write the output file when 'make' is
                called

        Returns:
            tuple:
                str: Filename of written file (or missing 'make' output)
                str: Contents of stdout
        """
        def fake_run(*cmd):
            if cmd[0] == 'make':
                # See Bintool.build_from_git()
                tmpdir = cmd[2]
                self.fname = os.path.join(tmpdir, 'pathname')
                if write_file:
                    tools.write_file(self.fname, b'hello')

        btest = Bintool.create('_testing')
        col = terminal.Color()
        self.fname = None
        with unittest.mock.patch.object(bintool, 'DOWNLOAD_DESTDIR',
                                        self._indir):
            with unittest.mock.patch.object(tools, 'run', side_effect=fake_run):
                with test_util.capture_sys_output() as (stdout, _):
                    btest.fetch_tool(bintool.FETCH_BUILD, col, False)
        fname = os.path.join(self._indir, '_testing')
        return fname if write_file else self.fname, stdout.getvalue()

    def test_build_method(self):
        """Test fetching using the build method"""
        fname, stdout = self.check_build_method(write_file=True)
        self.assertTrue(os.path.exists(fname))
        self.assertIn(f"writing to '{fname}", stdout)

    def test_build_method_fail(self):
        """Test fetching using the build method when no file is produced"""
        fname, stdout = self.check_build_method(write_file=False)
        self.assertFalse(os.path.exists(fname))
        self.assertIn(f"File '{fname}' was not produced", stdout)

    def test_install(self):
        """Test fetching using the install method"""
        btest = Bintool.create('_testing')
        btest.install = True
        col = terminal.Color()
        with unittest.mock.patch.object(tools, 'run', return_value=None):
            with test_util.capture_sys_output() as _:
                result = btest.fetch_tool(bintool.FETCH_BIN, col, False)
        self.assertEqual(bintool.FETCHED, result)

    def test_no_fetch(self):
        """Test fetching when there is no method"""
        btest = Bintool.create('_testing')
        btest.disable = True
        col = terminal.Color()
        with test_util.capture_sys_output() as _:
            result = btest.fetch_tool(bintool.FETCH_BIN, col, False)
        self.assertEqual(bintool.FAIL, result)

    def test_all_bintools(self):
        """Test that all bintools can handle all available fetch types"""
        def handle_download(_):
            """Take the tools.download() function by writing a file"""
            tools.write_file(fname, expected)
            return fname, dirname

        def fake_run(*cmd):
            if cmd[0] == 'make':
                # See Bintool.build_from_git()
                tmpdir = cmd[2]
                self.fname = os.path.join(tmpdir, 'pathname')
                tools.write_file(self.fname, b'hello')

        expected = b'this is a test'
        dirname = os.path.join(self._indir, 'download_dir')
        os.mkdir(dirname)
        fname = os.path.join(dirname, 'downloaded')

        with unittest.mock.patch.object(tools, 'run', side_effect=fake_run):
            with unittest.mock.patch.object(tools, 'download',
                                            side_effect=handle_download):
                with test_util.capture_sys_output() as _:
                    for name in Bintool.get_tool_list():
                        btool = Bintool.create(name)
                        for method in range(bintool.FETCH_COUNT):
                            result = btool.fetch(method)
                            self.assertTrue(result is not False)
                            if result is not True and result is not None:
                                result_fname, _ = result
                                self.assertTrue(os.path.exists(result_fname))
                                data = tools.read_file(result_fname)
                                self.assertEqual(expected, data)
                                os.remove(result_fname)

    def test_all_bintool_versions(self):
        """Test handling of bintool version when it cannot be run"""
        all_tools = Bintool.get_tool_list()
        for name in all_tools:
            btool = Bintool.create(name)
            with unittest.mock.patch.object(
                btool, 'run_cmd_result', return_value=command.CommandResult()):
                self.assertEqual('unknown', btool.version())

    def test_force_missing(self):
        btool = Bintool.create('_testing')
        btool.present = True
        self.assertTrue(btool.is_present())

        btool.present = None
        Bintool.set_missing_list(['_testing'])
        self.assertFalse(btool.is_present())

    def test_failed_command(self):
        """Check that running a command that does not exist returns None"""
        btool = Bintool.create('_testing')
        result = btool.run_cmd_result('fred')
        self.assertIsNone(result)


if __name__ == "__main__":
    unittest.main()
