1# Copyright 2017 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 5import mock 6import unittest 7 8import common 9from autotest_lib.frontend.afe.json_rpc import proxy as rpc_proxy 10from autotest_lib.server import frontend 11from autotest_lib.server.hosts import afe_store 12from autotest_lib.server.hosts import host_info 13 14class AfeStoreTest(unittest.TestCase): 15 """Test refresh/commit success cases for AfeStore.""" 16 17 def setUp(self): 18 self.hostname = 'some-host' 19 self.mock_afe = mock.create_autospec(frontend.AFE, instance=True) 20 self.store = afe_store.AfeStore(self.hostname, afe=self.mock_afe) 21 22 23 def _create_mock_host(self, labels, attributes): 24 """Create a mock frontend.Host with the given labels and attributes. 25 26 @param labels: The labels to set on the host. 27 @param attributes: The attributes to set on the host. 28 @returns: A mock object for frontend.Host. 29 """ 30 mock_host = mock.create_autospec(frontend.Host, instance=True) 31 mock_host.labels = labels 32 mock_host.attributes = attributes 33 return mock_host 34 35 36 def test_refresh(self): 37 """Test that refresh correctly translates host information.""" 38 self.mock_afe.get_hosts.return_value = [ 39 self._create_mock_host(['label1'], {'attrib1': 'val1'})] 40 info = self.store._refresh_impl() 41 self.assertListEqual(info.labels, ['label1']) 42 self.assertDictEqual(info.attributes, {'attrib1': 'val1'}) 43 44 45 def test_refresh_no_host_raises(self): 46 """Test that refresh complains if no host is found.""" 47 self.mock_afe.get_hosts.return_value = [] 48 with self.assertRaises(host_info.StoreError): 49 self.store._refresh_impl() 50 51 52 def test_refresh_multiple_hosts_picks_first(self): 53 """Test that refresh returns the first host if multiple match.""" 54 self.mock_afe.get_hosts.return_value = [ 55 self._create_mock_host(['label1'], {'attrib1': 'val1'}), 56 self._create_mock_host(['label2'], {'attrib2': 'val2'})] 57 info = self.store._refresh_impl() 58 self.assertListEqual(info.labels, ['label1']) 59 self.assertDictEqual(info.attributes, {'attrib1': 'val1'}) 60 61 62 def test_commit_labels(self): 63 """Tests that labels are updated correctly on commit.""" 64 self.mock_afe.get_hosts.return_value = [ 65 self._create_mock_host(['label1'], {})] 66 info = host_info.HostInfo(['label2'], {}) 67 self.store._commit_impl(info) 68 self.assertEqual(self.mock_afe.run.call_count, 2) 69 expected_run_calls = [ 70 mock.call('host_remove_labels', id='some-host', 71 labels={'label1'}), 72 mock.call('host_add_labels', id='some-host', 73 labels={'label2'}), 74 ] 75 self.mock_afe.run.assert_has_calls(expected_run_calls, 76 any_order=True) 77 78 79 def test_commit_labels_raises(self): 80 """Test that exception while committing is translated properly.""" 81 self.mock_afe.get_hosts.return_value = [ 82 self._create_mock_host(['label1'], {})] 83 self.mock_afe.run.side_effect = rpc_proxy.JSONRPCException('some error') 84 info = host_info.HostInfo(['label2'], {}) 85 with self.assertRaises(host_info.StoreError): 86 self.store._commit_impl(info) 87 88 89 def test_committing_attributes_warns(self): 90 """Test that a warning is issued if attribute changes are committed.""" 91 self.mock_afe.get_hosts.return_value = [ 92 self._create_mock_host([], {})] 93 info = host_info.HostInfo([], {'attrib': 'val'}) 94 with mock.patch('logging.warning', autospec=True) as mock_warning: 95 self.store._commit_impl(info) 96 self.assertEqual(mock_warning.call_count, 1) 97 self.assertRegexpMatches( 98 mock_warning.call_args[0][0], 99 '.*Updating attributes is currently not supported.*') 100 101 102 @unittest.expectedFailure 103 def test_commit_adds_attributes(self): 104 """Tests that new attributes are added correctly on commit.""" 105 self.mock_afe.get_hosts.return_value = [ 106 self._create_mock_host([], {})] 107 info = host_info.HostInfo([], {'attrib1': 'val1'}) 108 self.store._commit_impl(info) 109 self.assertEqual(self.mock_afe.set_host_attribute.call_count, 1) 110 self.mock_afe.assert_called_once_with('attrib1', 'val1', 111 hostname=self.hostname) 112 113 114 @unittest.expectedFailure 115 def test_commit_updates_attributes(self): 116 """Tests that existing attributes are updated correctly on commit.""" 117 self.mock_afe.get_hosts.return_value = [ 118 self._create_mock_host([], {'attrib1': 'val1'})] 119 info = host_info.HostInfo([], {'attrib1': 'val1_updated'}) 120 self.store._commit_impl(info) 121 self.assertEqual(self.mock_afe.set_host_attribute.call_count, 1) 122 self.mock_afe.assert_called_once_with('attrib1', 'val1_updated', 123 hostname=self.hostname) 124 125 126 @unittest.expectedFailure 127 def test_commit_deletes_attributes(self): 128 """Tests that deleted attributes are updated correctly on commit.""" 129 self.mock_afe.get_hosts.return_value = [ 130 self._create_mock_host([], {'attrib1': 'val1'})] 131 info = host_info.HostInfo([], {}) 132 self.store._commit_impl(info) 133 self.assertEqual(self.mock_afe.set_host_attribute.call_count, 1) 134 self.mock_afe.assert_called_once_with('attrib1', None, 135 hostname=self.hostname) 136 137 138if __name__ == '__main__': 139 unittest.main() 140