blob: 9c9e307dc934159e4db363c5457d66513b383dad [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
17from chromite.lib import cros_build_lib_unittest
18from chromite.lib import cros_import
Chris Sosa90c78502012-10-05 17:07:42 -070019from chromite.lib import cros_test_lib
David Pursellf1c27c12015-03-18 09:51:38 -070020from chromite.lib import partial_mock
21
Chris Sosa90c78502012-10-05 17:07:42 -070022
Don Garrett5bcf1442015-03-13 15:55:02 -070023# pylint:disable=protected-access
24
Chris Sosa90c78502012-10-05 17:07:42 -070025_COMMAND_NAME = 'superAwesomeCommandOfFunness'
26
27
David Pursellf1c27c12015-03-18 09:51:38 -070028@command.CommandDecorator(_COMMAND_NAME)
David Pursellffb90042015-03-23 09:21:41 -070029class TestCommand(command.CliCommand):
Chris Sosa90c78502012-10-05 17:07:42 -070030 """A fake command."""
31 def Run(self):
Mike Frysinger383367e2014-09-16 15:06:17 -040032 print('Just testing')
Chris Sosa90c78502012-10-05 17:07:42 -070033
34
David Pursellf80b8c52015-04-03 12:46:45 -070035class TestCommandTest(cros_test_lib.MockTestCase):
Chris Sosa90c78502012-10-05 17:07:42 -070036 """This test class tests that Commands method."""
37
David Pursellffb90042015-03-23 09:21:41 -070038 def testParserSetsCommandClass(self):
39 """Tests that our parser sets command_class correctly."""
Chris Sosa90c78502012-10-05 17:07:42 -070040 my_parser = argparse.ArgumentParser()
David Pursellffb90042015-03-23 09:21:41 -070041 command.CliCommand.AddParser(my_parser)
Chris Sosa90c78502012-10-05 17:07:42 -070042 ns = my_parser.parse_args([])
David Pursellffb90042015-03-23 09:21:41 -070043 self.assertEqual(ns.command_class, command.CliCommand)
Chris Sosa90c78502012-10-05 17:07:42 -070044
45 def testCommandDecorator(self):
46 """Tests that our decorator correctly adds TestCommand to _commands."""
47 # Note this exposes an implementation detail of _commands.
David Pursellf1c27c12015-03-18 09:51:38 -070048 self.assertEqual(command._commands[_COMMAND_NAME], TestCommand)
Chris Sosa90c78502012-10-05 17:07:42 -070049
50 def testBadUseOfCommandDecorator(self):
51 """Tests that our decorator correctly rejects bad test commands."""
52 try:
Brian Harring984988f2012-10-10 22:53:30 -070053 # pylint: disable=W0612
David Pursellf1c27c12015-03-18 09:51:38 -070054 @command.CommandDecorator('bad')
Chris Sosa90c78502012-10-05 17:07:42 -070055 class BadTestCommand(object):
Brian Harring984988f2012-10-10 22:53:30 -070056 """A command that wasn't implemented correctly."""
Chris Sosa90c78502012-10-05 17:07:42 -070057 pass
58
David Pursellf1c27c12015-03-18 09:51:38 -070059 except command.InvalidCommandError:
Chris Sosa90c78502012-10-05 17:07:42 -070060 pass
61 else:
62 self.fail('Invalid command was accepted by the CommandDecorator')
David Pursellf1c27c12015-03-18 09:51:38 -070063
David Pursellc7ba7842015-07-08 10:48:41 -070064 def testAddDeviceArgument(self):
65 """Tests CliCommand.AddDeviceArgument()."""
David Pursellf80b8c52015-04-03 12:46:45 -070066 parser = argparse.ArgumentParser()
67 command.CliCommand.AddDeviceArgument(parser)
David Pursellc7ba7842015-07-08 10:48:41 -070068 # Device should be a positional argument.
David Pursellf80b8c52015-04-03 12:46:45 -070069 parser.parse_args(['device'])
David Pursellf80b8c52015-04-03 12:46:45 -070070
David Pursellf1c27c12015-03-18 09:51:38 -070071
72class MockCommand(partial_mock.PartialMock):
David Pursellffb90042015-03-23 09:21:41 -070073 """Mock class for a generic CLI command."""
David Pursellf1c27c12015-03-18 09:51:38 -070074 ATTRS = ('Run',)
75 COMMAND = None
76 TARGET_CLASS = None
77
78 def __init__(self, args, base_args=None):
79 partial_mock.PartialMock.__init__(self)
80 self.args = args
81 self.rc_mock = cros_build_lib_unittest.RunCommandMock()
82 self.rc_mock.SetDefaultCmdResult()
83 parser = commandline.ArgumentParser(caching=True)
84 subparsers = parser.add_subparsers()
85 subparser = subparsers.add_parser(self.COMMAND, caching=True)
86 self.TARGET_CLASS.AddParser(subparser)
87
88 args = base_args if base_args else []
89 args += [self.COMMAND] + self.args
90 options = parser.parse_args(args)
David Pursellffb90042015-03-23 09:21:41 -070091 self.inst = options.command_class(options)
David Pursellf1c27c12015-03-18 09:51:38 -070092
93 def Run(self, inst):
94 with self.rc_mock:
95 return self.backup['Run'](inst)
96
97
98class CommandTest(cros_test_lib.MockTestCase):
99 """This test class tests that we can load modules correctly."""
100
101 # pylint: disable=W0212
102
103 def testFindModules(self):
104 """Tests that we can return modules correctly when mocking out glob."""
105 fake_command_file = 'cros_command_test.py'
106 filtered_file = 'cros_command_unittest.py'
107 mydir = 'mydir'
108
109 self.PatchObject(glob, 'glob',
110 return_value=[fake_command_file, filtered_file])
111
David Pursellc7ba7842015-07-08 10:48:41 -0700112 self.assertEqual(command._FindModules(mydir), [fake_command_file])
David Pursellf1c27c12015-03-18 09:51:38 -0700113
114 def testLoadCommands(self):
115 """Tests import commands correctly."""
116 fake_module = 'cros_command_test'
David Pursellc7ba7842015-07-08 10:48:41 -0700117 fake_command_file = os.path.join(constants.CHROMITE_DIR, 'foo', fake_module)
118 module_path = ['chromite', 'foo', fake_module]
David Pursellf1c27c12015-03-18 09:51:38 -0700119
120 self.PatchObject(command, '_FindModules', return_value=[fake_command_file])
121 # The code doesn't use the return value, so stub it out lazy-like.
122 load_mock = self.PatchObject(cros_import, 'ImportModule', return_value=None)
123
David Pursellc7ba7842015-07-08 10:48:41 -0700124 command._ImportCommands()
David Pursellf1c27c12015-03-18 09:51:38 -0700125
126 load_mock.assert_called_with(module_path)
127
David Pursellffb90042015-03-23 09:21:41 -0700128 def testListCrosCommands(self):
129 """Tests we get a sane `cros` list back."""
David Pursellc7ba7842015-07-08 10:48:41 -0700130 cros_commands = command.ListCommands()
David Pursellf1c27c12015-03-18 09:51:38 -0700131 # Pick some commands that are likely to not go away.
132 self.assertIn('chrome-sdk', cros_commands)
133 self.assertIn('flash', cros_commands)