# Copyright 2012 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Tests for the command module."""

import argparse
import importlib
import os

from chromite.cli import command
from chromite.lib import commandline
from chromite.lib import cros_test_lib
from chromite.lib import partial_mock


# pylint:disable=protected-access

_COMMAND_NAME = "superAwesomeCommandOfFunness"


@command.command_decorator(_COMMAND_NAME)
class TestCommand(command.CliCommand):
    """A fake command."""

    def Run(self):
        print("Just testing")


class TestCommandTest(cros_test_lib.MockTestCase):
    """This test class tests that Commands method."""

    def testParserSetsCommandClass(self):
        """Tests that our parser sets command_class correctly."""
        my_parser = argparse.ArgumentParser()
        command.CliCommand.AddParser(my_parser)
        ns = my_parser.parse_args([])
        self.assertEqual(ns.command_class, command.CliCommand)

    def testCommandDecorator(self):
        """Tests that our decorator correctly adds TestCommand to _commands."""
        # Note this exposes an implementation detail of _commands.
        self.assertEqual(command._commands[_COMMAND_NAME], TestCommand)

    def testBadUseOfCommandDecorator(self):
        """Tests that our decorator correctly rejects bad test commands."""
        try:
            # pylint: disable=unused-variable
            @command.command_decorator("bad")
            class BadTestCommand(object):
                """A command that wasn't implemented correctly."""

        except command.InvalidCommandError:
            pass
        else:
            self.fail("Invalid command was accepted by @command_decorator")

    def testAddDeviceArgument(self):
        """Tests CliCommand.AddDeviceArgument()."""
        parser = argparse.ArgumentParser()
        command.CliCommand.AddDeviceArgument(parser, positional=True)
        # Device should be a positional argument.
        parser.parse_args(["device"])

    def testAddNamedDeviceArgument(self):
        """Tests CliCommand.AddDeviceArgument()."""
        parser = argparse.ArgumentParser()
        command.CliCommand.AddDeviceArgument(parser, positional=False)
        # Device should be a named argument.
        parser.parse_args(["--device=device"])
        parser.parse_args(["-d", "device"])


class MockCommand(partial_mock.PartialMock):
    """Mock class for a generic CLI command."""

    ATTRS = ("Run",)
    COMMAND = None
    TARGET_CLASS = None

    def __init__(self, args, base_args=None):
        partial_mock.PartialMock.__init__(self)
        self.args = args
        self.rc_mock = cros_test_lib.RunCommandMock()
        self.rc_mock.SetDefaultCmdResult()
        self.parser = parser = commandline.ArgumentParser(caching=True)
        subparsers = parser.add_subparsers()
        subparser = subparsers.add_parser(
            self.COMMAND,
            caching=self.TARGET_CLASS.use_caching_options,
            dryrun=self.TARGET_CLASS.use_dryrun_options,
        )
        self.TARGET_CLASS.AddParser(subparser)

        args = base_args if base_args else []
        args += [self.COMMAND] + self.args
        options = parser.parse_args(args)
        self.inst = options.command_class(options)

    def Run(self, inst):
        with self.rc_mock:
            return self.backup["Run"](inst)


class CommandTest(cros_test_lib.MockTestCase):
    """This test class tests that we can load modules correctly."""

    def testFindModules(self):
        """Tests that we can return modules correctly when mocking out glob."""
        fake_command_file = "cros_command_test.py"
        filtered_file = "cros_command_unittest.py"

        self.PatchObject(
            os, "listdir", return_value=[fake_command_file, filtered_file]
        )

        self.assertEqual(command.ListCommands(), {"command-test"})

    def testLoadCommands(self):
        """Tests import commands correctly."""
        fake_module = "cros_command_test"
        module_path = "chromite.cli.cros.%s" % fake_module

        # The code doesn't use the return value, so stub it out lazy-like.
        load_mock = self.PatchObject(
            importlib, "import_module", return_value=None
        )

        command._commands["command-test"] = 123
        self.assertEqual(command.ImportCommand("command-test"), 123)
        command._commands.pop("command-test")

        load_mock.assert_called_with(module_path)

    def testListCrosCommands(self):
        """Tests we get a correct `cros` list back."""
        cros_commands = command.ListCommands()
        # Pick some commands that are likely to not go away.
        self.assertIn("chrome-sdk", cros_commands)
        self.assertIn("flash", cros_commands)
