4 # Copyright (C) 2009 Google Inc.
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 # General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 """Script for unittesting the confd client module"""
27 from ganeti import confd
28 from ganeti import constants
29 from ganeti import errors
31 import ganeti.confd.client
34 class ResettableMock(object):
35 def __init__(self, *args, **kwargs):
42 class MockLogger(ResettableMock):
57 class MockConfdAsyncUDPClient(ResettableMock):
60 self.last_address = ''
64 def enqueue_send(self, address, port, payload):
66 self.last_payload = payload
68 self.last_address = address
70 class MockCallback(ResettableMock):
75 def __call__(self, up):
78 @type up: L{ConfdUpcallPayload}
79 @param up: upper callback
86 class MockTime(ResettableMock):
88 self.mytime = 1254213006.5175071
93 def increase(self, delta):
97 class TestClient(unittest.TestCase):
101 self.mock_time = MockTime()
102 confd.client.time = self.mock_time
103 confd.client.ConfdAsyncUDPClient = MockConfdAsyncUDPClient
104 self.logger = MockLogger()
105 hmac_key = "mykeydata"
106 self.mc_list = ['10.0.0.1',
116 self.callback = MockCallback()
117 self.client = confd.client.ConfdClient(hmac_key, self.mc_list,
118 self.callback, logger=self.logger)
120 def testRequest(self):
121 req1 = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
122 req2 = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
123 self.assertNotEqual(req1.rsalt, req2.rsalt)
124 self.assertEqual(req1.protocol, constants.CONFD_PROTOCOL_VERSION)
125 self.assertEqual(req2.protocol, constants.CONFD_PROTOCOL_VERSION)
126 self.assertRaises(errors.ConfdClientError, confd.client.ConfdClientRequest,
129 def testClientSend(self):
130 req = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
131 self.client.SendRequest(req)
132 # Cannot send the same request twice
133 self.assertRaises(errors.ConfdClientError, self.client.SendRequest, req)
134 req2 = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
135 # Coverage is too big
136 self.assertRaises(errors.ConfdClientError, self.client.SendRequest,
138 self.assertEquals(self.client._socket.send_count,
139 constants.CONFD_DEFAULT_REQ_COVERAGE)
140 self.assert_(self.client._socket.last_address in self.mc_list)
143 def testClientExpire(self):
144 req = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
145 self.client.SendRequest(req)
146 # Make a couple of seconds pass ;)
147 self.mock_time.increase(2)
148 # Now sending the second request
149 req2 = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
150 self.client.SendRequest(req2)
151 self.mock_time.increase(constants.CONFD_CLIENT_EXPIRE_TIMEOUT - 1)
152 # First request should be expired, second one should not
153 self.client.ExpireRequests()
154 self.assertEquals(self.callback.call_count, 1)
155 self.assertEquals(self.callback.last_up.type, confd.client.UPCALL_EXPIRE)
156 self.assertEquals(self.callback.last_up.salt, req.rsalt)
157 self.assertEquals(self.callback.last_up.orig_request, req)
158 self.mock_time.increase(3)
159 self.assertEquals(self.callback.call_count, 1)
160 self.client.ExpireRequests()
161 self.assertEquals(self.callback.call_count, 2)
162 self.assertEquals(self.callback.last_up.type, confd.client.UPCALL_EXPIRE)
163 self.assertEquals(self.callback.last_up.salt, req2.rsalt)
164 self.assertEquals(self.callback.last_up.orig_request, req2)
166 def testClientCascadeExpire(self):
167 req = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
168 self.client.SendRequest(req)
169 self.mock_time.increase(constants.CONFD_CLIENT_EXPIRE_TIMEOUT +1)
170 req2 = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
171 self.client.SendRequest(req2)
172 self.assertEquals(self.callback.call_count, 1)
174 def testUpdatePeerList(self):
175 new_peers = ['1.2.3.4', '1.2.3.5']
176 self.client.UpdatePeerList(new_peers)
177 self.assertEquals(self.client._peers, new_peers)
178 req = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
179 self.client.SendRequest(req)
180 self.assertEquals(self.client._socket.send_count, len(new_peers))
181 self.assert_(self.client._socket.last_address in new_peers)
184 if __name__ == '__main__':