cfgupgrade: Remove Ganeti 1.2 support
[ganeti-local] / test / ganeti.confd_client_unittest.py
1 #!/usr/bin/python
2 #
3
4 # Copyright (C) 2009 Google Inc.
5 #
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.
10 #
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.
15 #
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
19 # 0.0510-1301, USA.
20
21
22 """Script for unittesting the confd client module"""
23
24
25 import unittest
26
27 from ganeti import confd
28 from ganeti import constants
29 from ganeti import errors
30
31 import ganeti.confd.client
32
33
34 class ResettableMock(object):
35   def __init__(self, *args, **kwargs):
36     self.Reset()
37
38   def Reset(self):
39     pass
40
41
42 class MockLogger(ResettableMock):
43   def Reset(self):
44     self.debug_count = 0
45     self.warn_count = 0
46     self.error_count = 0
47
48   def debug(string):
49     self.debug_count += 1
50
51   def warning(string):
52     self.warn_count += 1
53
54   def error(string):
55     self.error_count += 1
56
57 class MockConfdAsyncUDPClient(ResettableMock):
58   def Reset(self):
59     self.send_count = 0
60     self.last_address = ''
61     self.last_port = -1
62     self.last_sent = ''
63
64   def enqueue_send(self, address, port, payload):
65     self.send_count += 1
66     self.last_payload = payload
67     self.last_port = port
68     self.last_address = address
69
70 class MockCallback(ResettableMock):
71   def Reset(self):
72     self.call_count = 0
73     self.last_up = None
74
75   def __call__(self, up):
76     """Callback
77
78     @type up: L{ConfdUpcallPayload}
79     @param up: upper callback
80
81     """
82     self.call_count += 1
83     self.last_up = up
84
85
86 class MockTime(ResettableMock):
87   def Reset(self):
88     self.mytime  = 1254213006.5175071
89
90   def time(self):
91     return self.mytime
92
93   def increase(self, delta):
94     self.mytime += delta
95
96
97 class TestClient(unittest.TestCase):
98   """Client tests"""
99
100   def setUp(self):
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',
107                     '10.0.0.2',
108                     '10.0.0.3',
109                     '10.0.0.4',
110                     '10.0.0.5',
111                     '10.0.0.6',
112                     '10.0.0.7',
113                     '10.0.0.8',
114                     '10.0.0.9',
115                    ]
116     self.callback = MockCallback()
117     self.client = confd.client.ConfdClient(hmac_key, self.mc_list,
118                                            self.callback, logger=self.logger)
119
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,
127                       type=-33)
128
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,
137                       req2, coverage=15)
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)
141
142
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)
165
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)
173
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)
182
183
184 if __name__ == '__main__':
185   unittest.main()