1# Copyright 2018 The Chromium OS Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5"""Unit tests for the `stable_version` module and CLI.""" 6 7import mock 8import unittest 9 10import common 11from autotest_lib.server import frontend 12from autotest_lib.site_utils.stable_images import stable_version 13 14 15class ParseArgsTestCase(unittest.TestCase): 16 """Unit tests for `_parse_args()`.""" 17 18 def test_default_options(self): 19 """Test for an empty command line.""" 20 arguments = stable_version._parse_args(['command']) 21 self.assertFalse(arguments.dry_run) 22 self.assertIsNone(arguments.type) 23 self.assertIsNone(arguments.web) 24 self.assertFalse(arguments.delete) 25 self.assertIsNone(arguments.key) 26 self.assertIsNone(arguments.version) 27 28 def test_web_option(self): 29 """Test for the `--web` option.""" 30 for option in ['-w', '--web']: 31 argv = ['command', option, 'server'] 32 arguments = stable_version._parse_args(argv) 33 self.assertEqual(arguments.web, argv[2]) 34 35 def test_dry_run_option(self): 36 """Test for the `--dry-run` option.""" 37 for option in ['-n', '--dry-run']: 38 argv = ['command', option] 39 arguments = stable_version._parse_args(argv) 40 self.assertTrue(arguments.dry_run) 41 42 def test_image_type_option(self): 43 """Test for the `--type` option.""" 44 for image_type in stable_version._ALL_IMAGE_TYPES: 45 for option in ['-t', '--type']: 46 argv = ['command', option, image_type] 47 arguments = stable_version._parse_args(argv) 48 49 def test_delete_option(self): 50 """Test for the `--delete` option.""" 51 for option in ['-d', '--delete']: 52 argv = ['command', option] 53 arguments = stable_version._parse_args(argv) 54 self.assertTrue(arguments.delete) 55 56 def test_key_argument(self): 57 """Test for the BOARD_OR_MODEL argument.""" 58 argv = ['command', 'key'] 59 arguments = stable_version._parse_args(argv) 60 self.assertEqual(arguments.key, argv[1]) 61 62 def test_version_argument(self): 63 """Test for the VERSION argument.""" 64 argv = ['command', 'key', 'version'] 65 arguments = stable_version._parse_args(argv) 66 self.assertEqual(arguments.key, argv[1]) 67 self.assertEqual(arguments.version, argv[2]) 68 69 70class ProcessCommandTestCase(unittest.TestCase): 71 """Unit tests for `_dispatch_command()`.""" 72 73 def _dispatch_command_success(self, afe, argv, name_called): 74 arguments = stable_version._parse_args(argv) 75 patches = mock.patch.multiple(stable_version, 76 list_all_mappings=mock.DEFAULT, 77 list_mapping_by_key=mock.DEFAULT, 78 set_mapping=mock.DEFAULT, 79 delete_mapping=mock.DEFAULT) 80 with patches as mocks: 81 stable_version._dispatch_command(afe, arguments) 82 for not_called in set(mocks) - set([name_called]): 83 mocks[not_called].assert_not_called() 84 return mocks[name_called] 85 86 def _assert_command_error(self, argv): 87 afe = object() 88 arguments = stable_version._parse_args(argv) 89 with self.assertRaises(stable_version._CommandError): 90 stable_version._dispatch_command(afe, arguments) 91 92 def test_list_all(self): 93 """Test that `list_all_mappings` is called when required.""" 94 argv = ['command'] 95 afe = object() 96 called_mock = self._dispatch_command_success( 97 afe, argv, 'list_all_mappings') 98 called_mock.assert_called_once_with(afe, None) 99 100 def test_list_all_with_type(self): 101 """Test that `list_all_mappings` is called with a supplied type.""" 102 argv = ['command', '-t', frontend.AFE.CROS_IMAGE_TYPE] 103 afe = object() 104 called_mock = self._dispatch_command_success( 105 afe, argv, 'list_all_mappings') 106 called_mock.assert_called_once_with(afe, argv[2]) 107 108 def test_list_mapping_by_key(self): 109 """Test that `list_mapping_by_key` is called when required.""" 110 argv = ['command', 'board'] 111 afe = object() 112 called_mock = self._dispatch_command_success( 113 afe, argv, 'list_mapping_by_key') 114 called_mock.assert_called_once_with(afe, None, argv[1]) 115 116 def test_list_mapping_by_key_with_type(self): 117 """Test that `list_mapping_by_key` is called with a supplied type.""" 118 argv = ['command', '-t', frontend.AFE.CROS_IMAGE_TYPE, 'board'] 119 afe = object() 120 called_mock = self._dispatch_command_success( 121 afe, argv, 'list_mapping_by_key') 122 called_mock.assert_called_once_with(afe, argv[2], argv[3]) 123 124 def test_set_mapping(self): 125 """Test that `set_mapping` is called when required.""" 126 argv = ['command', '-t', frontend.AFE.CROS_IMAGE_TYPE, 'board', 'V0.0'] 127 afe = object() 128 called_mock = self._dispatch_command_success( 129 afe, argv, 'set_mapping') 130 called_mock.assert_called_once_with(afe, argv[2], argv[3], 131 argv[4], False) 132 133 def test_set_mapping_firmware(self): 134 """Test error when `set_mapping` is called for firmware.""" 135 argv = ['command', '-t', frontend.AFE.FIRMWARE_IMAGE_TYPE, 136 'board', 'V0.0'] 137 self._assert_command_error(argv) 138 139 def test_set_mapping_no_type(self): 140 """Test error when `set_mapping` is called without a type.""" 141 argv = ['command', 'board', 'V0.0'] 142 self._assert_command_error(argv) 143 144 def test_delete_mapping(self): 145 """Test that `delete_mapping` is called when required.""" 146 argv = ['command', '-t', frontend.AFE.CROS_IMAGE_TYPE, '-d', 'board'] 147 afe = object() 148 called_mock = self._dispatch_command_success( 149 afe, argv, 'delete_mapping') 150 called_mock.assert_called_once_with(afe, argv[2], argv[4], False) 151 152 def test_delete_mapping_no_key(self): 153 """Test error when `delete_mapping` is called without a key.""" 154 argv = ['command', '-t', frontend.AFE.CROS_IMAGE_TYPE, '-d'] 155 self._assert_command_error(argv) 156 157 def test_delete_mapping_no_type(self): 158 """Test error when `delete_mapping` is called without a type.""" 159 argv = ['command', '-d', 'board'] 160 self._assert_command_error(argv) 161 162 def test_delete_mapping_with_version(self): 163 """Test error when `delete_mapping` is called with extra arguments.""" 164 argv = ['command', '-t', frontend.AFE.CROS_IMAGE_TYPE, '-d', 165 'board', 'V0.0'] 166 self._assert_command_error(argv) 167 168 169if __name__ == '__main__': 170 unittest.main() 171