blob: c8366e6e05be2199f025d258ad25a4d0ee1c89ed [file] [log] [blame]
# 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) -> None:
print("Just testing")
class TestCommandTest(cros_test_lib.MockTestCase):
"""This test class tests that Commands method."""
def testParserSetsCommandClass(self) -> None:
"""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) -> None:
"""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) -> None:
"""Tests that our decorator correctly rejects bad test commands."""
try:
# pylint: disable=unused-variable
@command.command_decorator("bad")
class BadTestCommand:
"""A command that wasn't implemented correctly."""
except command.InvalidCommandError:
pass
else:
self.fail("Invalid command was accepted by @command_decorator")
def testAddDeviceArgument(self) -> None:
"""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) -> None:
"""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) -> 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) -> None:
"""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) -> None:
"""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) -> None:
"""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)