Home | History | Annotate | Download | only in hosts
      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 
      5 import mock
      6 import unittest
      7 
      8 import common
      9 from autotest_lib.frontend.afe.json_rpc import proxy as rpc_proxy
     10 from autotest_lib.server import frontend
     11 from autotest_lib.server.hosts import afe_store
     12 from autotest_lib.server.hosts import host_info
     13 
     14 class 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_commit_adds_attributes(self):
     90         """Tests that new attributes are added correctly on commit."""
     91         self.mock_afe.get_hosts.return_value = [
     92                 self._create_mock_host([], {})]
     93         info = host_info.HostInfo([], {'attrib1': 'val1'})
     94         self.store._commit_impl(info)
     95         self.assertEqual(self.mock_afe.set_host_attribute.call_count, 1)
     96         self.mock_afe.set_host_attribute.assert_called_once_with(
     97                 'attrib1', 'val1', hostname=self.hostname)
     98 
     99 
    100     def test_commit_updates_attributes(self):
    101         """Tests that existing attributes are updated correctly on commit."""
    102         self.mock_afe.get_hosts.return_value = [
    103                 self._create_mock_host([], {'attrib1': 'val1'})]
    104         info = host_info.HostInfo([], {'attrib1': 'val1_updated'})
    105         self.store._commit_impl(info)
    106         self.assertEqual(self.mock_afe.set_host_attribute.call_count, 1)
    107         self.mock_afe.set_host_attribute.assert_called_once_with(
    108                 'attrib1', 'val1_updated', hostname=self.hostname)
    109 
    110 
    111     def test_commit_deletes_attributes(self):
    112         """Tests that deleted attributes are updated correctly on commit."""
    113         self.mock_afe.get_hosts.return_value = [
    114                 self._create_mock_host([], {'attrib1': 'val1'})]
    115         info = host_info.HostInfo([], {})
    116         self.store._commit_impl(info)
    117         self.assertEqual(self.mock_afe.set_host_attribute.call_count, 1)
    118         self.mock_afe.set_host_attribute.assert_called_once_with(
    119                 'attrib1', None, hostname=self.hostname)
    120 
    121 
    122     def test_str(self):
    123         """Sanity tests the __str__ implementaiton"""
    124         self.assertEqual(str(self.store), 'AfeStore[some-host]')
    125 
    126 
    127 class DictDiffTest(unittest.TestCase):
    128     """Tests the afe_store._dict_diff private method."""
    129 
    130     def _assert_dict_diff(self, got_tuple, expectation_tuple):
    131         """Verifies the result from _dict_diff
    132 
    133         @param got_tuple: The tuple returned by afe_store._dict_diff
    134         @param expectatin_tuple: tuple (left_only, right_only, differing)
    135                 containing iterable of keys to verify against got_tuple.
    136         """
    137         for got, expect in zip(got_tuple, expectation_tuple):
    138             self.assertEqual(got, set(expect))
    139 
    140 
    141     def test_both_empty(self):
    142         """Tests the case when both dicts are empty."""
    143         self._assert_dict_diff(afe_store._dict_diff({}, {}),
    144                                ((), (), ()))
    145 
    146 
    147     def test_right_dict_only(self):
    148         """Tests the case when left dict is empty."""
    149         self._assert_dict_diff(afe_store._dict_diff({}, {1: 1}),
    150                                ((), (1,), ()))
    151 
    152 
    153     def test_left_dict_only(self):
    154         """Tests the case when right dict is empty."""
    155         self._assert_dict_diff(afe_store._dict_diff({1: 1}, {}),
    156                                ((1,), (), ()))
    157 
    158 
    159     def test_left_dict_extra(self):
    160         """Tests the case when left dict has extra keys."""
    161         self._assert_dict_diff(afe_store._dict_diff({1: 1, 2: 2}, {1: 1}),
    162                                ((2,), (), ()))
    163 
    164 
    165     def test_right_dict_extra(self):
    166         """Tests the case when right dict has extra keys."""
    167         self._assert_dict_diff(afe_store._dict_diff({1: 1}, {1: 1, 2: 2}),
    168                                ((), (2,), ()))
    169 
    170 
    171     def test_identical_keys_with_different_values(self):
    172         """Tests the case when the set of keys is same, but values differ."""
    173         self._assert_dict_diff(afe_store._dict_diff({1: 1, 2: 3}, {1: 1, 2: 2}),
    174                                ((), (), (2,)))
    175 
    176 
    177 if __name__ == '__main__':
    178     unittest.main()
    179