summaryrefslogtreecommitdiff
path: root/cli/command_unittest.py
diff options
context:
space:
mode:
Diffstat (limited to 'cli/command_unittest.py')
-rw-r--r--cli/command_unittest.py179
1 files changed, 179 insertions, 0 deletions
diff --git a/cli/command_unittest.py b/cli/command_unittest.py
new file mode 100644
index 000000000..33c072567
--- /dev/null
+++ b/cli/command_unittest.py
@@ -0,0 +1,179 @@
+# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+# 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."""
+
+from __future__ import print_function
+
+import argparse
+import glob
+import os
+
+from chromite.cbuildbot import constants
+from chromite.cli import command
+from chromite.lib import commandline
+from chromite.lib import cros_build_lib_unittest
+from chromite.lib import cros_import
+from chromite.lib import cros_logging as logging
+from chromite.lib import cros_test_lib
+from chromite.lib import partial_mock
+from chromite.lib import workspace_lib
+
+
+# pylint:disable=protected-access
+
+_COMMAND_NAME = 'superAwesomeCommandOfFunness'
+
+
+@command.CommandDecorator(_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=W0612
+ @command.CommandDecorator('bad')
+ class BadTestCommand(object):
+ """A command that wasn't implemented correctly."""
+ pass
+
+ except command.InvalidCommandError:
+ pass
+ else:
+ self.fail('Invalid command was accepted by the CommandDecorator')
+
+ def testAddDeviceArgument(self):
+ """Tests CliCommand.AddDeviceArgument()."""
+ parser = argparse.ArgumentParser()
+ command.CliCommand.AddDeviceArgument(parser)
+ # Device should be a positional argument.
+ parser.parse_args(['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_build_lib_unittest.RunCommandMock()
+ self.rc_mock.SetDefaultCmdResult()
+ parser = commandline.ArgumentParser(caching=True)
+ subparsers = parser.add_subparsers()
+ subparser = subparsers.add_parser(self.COMMAND, caching=True)
+ 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."""
+
+ # pylint: disable=W0212
+
+ 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'
+ mydir = 'mydir'
+
+ self.PatchObject(glob, 'glob',
+ return_value=[fake_command_file, filtered_file])
+
+ self.assertEqual(command._FindModules(mydir), [fake_command_file])
+
+ def testLoadCommands(self):
+ """Tests import commands correctly."""
+ fake_module = 'cros_command_test'
+ fake_command_file = os.path.join(constants.CHROMITE_DIR, 'foo', fake_module)
+ module_path = ['chromite', 'foo', fake_module]
+
+ self.PatchObject(command, '_FindModules', return_value=[fake_command_file])
+ # The code doesn't use the return value, so stub it out lazy-like.
+ load_mock = self.PatchObject(cros_import, 'ImportModule', return_value=None)
+
+ command._ImportCommands()
+
+ load_mock.assert_called_with(module_path)
+
+ def testListCrosCommands(self):
+ """Tests we get a sane `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)
+
+
+class FileLoggerSetupTest(cros_test_lib.WorkspaceTestCase):
+ """Test that logging to file works correctly."""
+
+ def setUp(self):
+ self.CreateWorkspace()
+
+ def testSetupFileLoggerFilename(self):
+ """Test that the filename and path are correct."""
+ patch_handler = self.PatchObject(logging, 'FileHandler',
+ return_value=logging.StreamHandler())
+ command.SetupFileLogger(filename='foo.log')
+
+ # Test that the filename is correct.
+ patch_handler.assert_called_with(
+ os.path.join(self.workspace_path, workspace_lib.WORKSPACE_LOGS_DIR,
+ 'foo.log'), mode='w')
+
+ def testSetupFileLoggerNoFilename(self):
+ """Test that the filename and path are correct with no arguments."""
+ patch_handler = self.PatchObject(logging, 'FileHandler',
+ return_value=logging.StreamHandler())
+ command.SetupFileLogger()
+
+ # Test that the filename is correct.
+ patch_handler.assert_called_with(
+ os.path.join(self.workspace_path, workspace_lib.WORKSPACE_LOGS_DIR,
+ 'brillo.log'), mode='w')
+
+ def testSetupFileLoggerLogLevels(self):
+ """Test that the logger operates at the right level."""
+ command.SetupFileLogger('foo.log', log_level=logging.INFO)
+ logging.getLogger().setLevel(logging.DEBUG)
+ logging.debug('debug')
+ logging.info('info')
+ logging.notice('notice')
+
+ # Test that the logs are correct.
+ logs = open(
+ os.path.join(self.workspace_path, workspace_lib.WORKSPACE_LOGS_DIR,
+ 'foo.log'), 'r').read()
+ self.assertNotIn('debug', logs)
+ self.assertIn('info', logs)
+ self.assertIn('notice', logs)