blob: 1c1abf1edac1600a97e9350116b6edd539122515 [file] [log] [blame]
Mike Frysingere58c0e22017-10-04 15:43:30 -04001# -*- coding: utf-8 -*-
Chris Sosa90c78502012-10-05 17:07:42 -07002# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
David Pursellf1c27c12015-03-18 09:51:38 -07006"""Tests for the command module."""
Chris Sosa90c78502012-10-05 17:07:42 -07007
Mike Frysinger383367e2014-09-16 15:06:17 -04008from __future__ import print_function
9
Chris Sosa90c78502012-10-05 17:07:42 -070010import argparse
David Pursellf1c27c12015-03-18 09:51:38 -070011import glob
Ralph Nathan74e864d2015-05-11 12:13:53 -070012import os
Chris Sosa90c78502012-10-05 17:07:42 -070013
Aviv Keshetb7519e12016-10-04 00:50:00 -070014from chromite.lib import constants
David Pursellf1c27c12015-03-18 09:51:38 -070015from chromite.cli import command
16from chromite.lib import commandline
David Pursellf1c27c12015-03-18 09:51:38 -070017from chromite.lib import cros_import
Chris Sosa90c78502012-10-05 17:07:42 -070018from chromite.lib import cros_test_lib
David Pursellf1c27c12015-03-18 09:51:38 -070019from chromite.lib import partial_mock
20
Chris Sosa90c78502012-10-05 17:07:42 -070021
Don Garrett5bcf1442015-03-13 15:55:02 -070022# pylint:disable=protected-access
23
Chris Sosa90c78502012-10-05 17:07:42 -070024_COMMAND_NAME = 'superAwesomeCommandOfFunness'
25
26
David Pursellf1c27c12015-03-18 09:51:38 -070027@command.CommandDecorator(_COMMAND_NAME)
David Pursellffb90042015-03-23 09:21:41 -070028class TestCommand(command.CliCommand):
Chris Sosa90c78502012-10-05 17:07:42 -070029 """A fake command."""
30 def Run(self):
Mike Frysinger383367e2014-09-16 15:06:17 -040031 print('Just testing')
Chris Sosa90c78502012-10-05 17:07:42 -070032
33
David Pursellf80b8c52015-04-03 12:46:45 -070034class TestCommandTest(cros_test_lib.MockTestCase):
Chris Sosa90c78502012-10-05 17:07:42 -070035 """This test class tests that Commands method."""
36
David Pursellffb90042015-03-23 09:21:41 -070037 def testParserSetsCommandClass(self):
38 """Tests that our parser sets command_class correctly."""
Chris Sosa90c78502012-10-05 17:07:42 -070039 my_parser = argparse.ArgumentParser()
David Pursellffb90042015-03-23 09:21:41 -070040 command.CliCommand.AddParser(my_parser)
Chris Sosa90c78502012-10-05 17:07:42 -070041 ns = my_parser.parse_args([])
David Pursellffb90042015-03-23 09:21:41 -070042 self.assertEqual(ns.command_class, command.CliCommand)
Chris Sosa90c78502012-10-05 17:07:42 -070043
44 def testCommandDecorator(self):
45 """Tests that our decorator correctly adds TestCommand to _commands."""
46 # Note this exposes an implementation detail of _commands.
David Pursellf1c27c12015-03-18 09:51:38 -070047 self.assertEqual(command._commands[_COMMAND_NAME], TestCommand)
Chris Sosa90c78502012-10-05 17:07:42 -070048
49 def testBadUseOfCommandDecorator(self):
50 """Tests that our decorator correctly rejects bad test commands."""
51 try:
Mike Frysinger27e21b72018-07-12 14:20:21 -040052 # pylint: disable=unused-variable
David Pursellf1c27c12015-03-18 09:51:38 -070053 @command.CommandDecorator('bad')
Chris Sosa90c78502012-10-05 17:07:42 -070054 class BadTestCommand(object):
Brian Harring984988f2012-10-10 22:53:30 -070055 """A command that wasn't implemented correctly."""
Chris Sosa90c78502012-10-05 17:07:42 -070056 pass
57
David Pursellf1c27c12015-03-18 09:51:38 -070058 except command.InvalidCommandError:
Chris Sosa90c78502012-10-05 17:07:42 -070059 pass
60 else:
61 self.fail('Invalid command was accepted by the CommandDecorator')
David Pursellf1c27c12015-03-18 09:51:38 -070062
David Pursellc7ba7842015-07-08 10:48:41 -070063 def testAddDeviceArgument(self):
64 """Tests CliCommand.AddDeviceArgument()."""
David Pursellf80b8c52015-04-03 12:46:45 -070065 parser = argparse.ArgumentParser()
66 command.CliCommand.AddDeviceArgument(parser)
David Pursellc7ba7842015-07-08 10:48:41 -070067 # Device should be a positional argument.
David Pursellf80b8c52015-04-03 12:46:45 -070068 parser.parse_args(['device'])
David Pursellf80b8c52015-04-03 12:46:45 -070069
David Pursellf1c27c12015-03-18 09:51:38 -070070
71class MockCommand(partial_mock.PartialMock):
David Pursellffb90042015-03-23 09:21:41 -070072 """Mock class for a generic CLI command."""
David Pursellf1c27c12015-03-18 09:51:38 -070073 ATTRS = ('Run',)
74 COMMAND = None
75 TARGET_CLASS = None
76
77 def __init__(self, args, base_args=None):
78 partial_mock.PartialMock.__init__(self)
79 self.args = args
Benjamin Gordon121a2aa2018-05-04 16:24:45 -060080 self.rc_mock = cros_test_lib.RunCommandMock()
David Pursellf1c27c12015-03-18 09:51:38 -070081 self.rc_mock.SetDefaultCmdResult()
82 parser = commandline.ArgumentParser(caching=True)
83 subparsers = parser.add_subparsers()
84 subparser = subparsers.add_parser(self.COMMAND, caching=True)
85 self.TARGET_CLASS.AddParser(subparser)
86
87 args = base_args if base_args else []
88 args += [self.COMMAND] + self.args
89 options = parser.parse_args(args)
David Pursellffb90042015-03-23 09:21:41 -070090 self.inst = options.command_class(options)
David Pursellf1c27c12015-03-18 09:51:38 -070091
92 def Run(self, inst):
93 with self.rc_mock:
94 return self.backup['Run'](inst)
95
96
97class CommandTest(cros_test_lib.MockTestCase):
98 """This test class tests that we can load modules correctly."""
99
Mike Frysinger27e21b72018-07-12 14:20:21 -0400100 # pylint: disable=protected-access
David Pursellf1c27c12015-03-18 09:51:38 -0700101
102 def testFindModules(self):
103 """Tests that we can return modules correctly when mocking out glob."""
104 fake_command_file = 'cros_command_test.py'
105 filtered_file = 'cros_command_unittest.py'
106 mydir = 'mydir'
107
108 self.PatchObject(glob, 'glob',
109 return_value=[fake_command_file, filtered_file])
110
David Pursellc7ba7842015-07-08 10:48:41 -0700111 self.assertEqual(command._FindModules(mydir), [fake_command_file])
David Pursellf1c27c12015-03-18 09:51:38 -0700112
113 def testLoadCommands(self):
114 """Tests import commands correctly."""
115 fake_module = 'cros_command_test'
David Pursellc7ba7842015-07-08 10:48:41 -0700116 fake_command_file = os.path.join(constants.CHROMITE_DIR, 'foo', fake_module)
117 module_path = ['chromite', 'foo', fake_module]
David Pursellf1c27c12015-03-18 09:51:38 -0700118
119 self.PatchObject(command, '_FindModules', return_value=[fake_command_file])
120 # The code doesn't use the return value, so stub it out lazy-like.
121 load_mock = self.PatchObject(cros_import, 'ImportModule', return_value=None)
122
David Pursellc7ba7842015-07-08 10:48:41 -0700123 command._ImportCommands()
David Pursellf1c27c12015-03-18 09:51:38 -0700124
125 load_mock.assert_called_with(module_path)
126
David Pursellffb90042015-03-23 09:21:41 -0700127 def testListCrosCommands(self):
128 """Tests we get a sane `cros` list back."""
David Pursellc7ba7842015-07-08 10:48:41 -0700129 cros_commands = command.ListCommands()
David Pursellf1c27c12015-03-18 09:51:38 -0700130 # Pick some commands that are likely to not go away.
131 self.assertIn('chrome-sdk', cros_commands)
132 self.assertIn('flash', cros_commands)