Generate import-export unittest certs in parallel
[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 import testutils
34
35
36 class ResettableMock(object):
37   def __init__(self, *args, **kwargs):
38     self.Reset()
39
40   def Reset(self):
41     pass
42
43
44 class MockLogger(ResettableMock):
45   def Reset(self):
46     self.debug_count = 0
47     self.warn_count = 0
48     self.error_count = 0
49
50   def debug(string):
51     self.debug_count += 1
52
53   def warning(string):
54     self.warn_count += 1
55
56   def error(string):
57     self.error_count += 1
58
59 class MockConfdAsyncUDPClient(ResettableMock):
60   def Reset(self):
61     self.send_count = 0
62     self.last_address = ''
63     self.last_port = -1
64     self.last_sent = ''
65
66   def enqueue_send(self, address, port, payload):
67     self.send_count += 1
68     self.last_payload = payload
69     self.last_port = port
70     self.last_address = address
71
72 class MockCallback(ResettableMock):
73   def Reset(self):
74     self.call_count = 0
75     self.last_up = None
76
77   def __call__(self, up):
78     """Callback
79
80     @type up: L{ConfdUpcallPayload}
81     @param up: upper callback
82
83     """
84     self.call_count += 1
85     self.last_up = up
86
87
88 class MockTime(ResettableMock):
89   def Reset(self):
90     self.mytime  = 1254213006.5175071
91
92   def time(self):
93     return self.mytime
94
95   def increase(self, delta):
96     self.mytime += delta
97
98
99 class TestClient(unittest.TestCase):
100   """Client tests"""
101
102   def setUp(self):
103     self.mock_time = MockTime()
104     confd.client.time = self.mock_time
105     confd.client.ConfdAsyncUDPClient = MockConfdAsyncUDPClient
106     self.logger = MockLogger()
107     hmac_key = "mykeydata"
108     self.mc_list = ['10.0.0.1',
109                     '10.0.0.2',
110                     '10.0.0.3',
111                     '10.0.0.4',
112                     '10.0.0.5',
113                     '10.0.0.6',
114                     '10.0.0.7',
115                     '10.0.0.8',
116                     '10.0.0.9',
117                    ]
118     self.callback = MockCallback()
119     self.client = confd.client.ConfdClient(hmac_key, self.mc_list,
120                                            self.callback, logger=self.logger)
121
122   def testRequest(self):
123     req1 = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
124     req2 = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
125     self.assertNotEqual(req1.rsalt, req2.rsalt)
126     self.assertEqual(req1.protocol, constants.CONFD_PROTOCOL_VERSION)
127     self.assertEqual(req2.protocol, constants.CONFD_PROTOCOL_VERSION)
128     self.assertRaises(errors.ConfdClientError, confd.client.ConfdClientRequest,
129                       type=-33)
130
131   def testClientSend(self):
132     req = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
133     self.client.SendRequest(req)
134     # Cannot send the same request twice
135     self.assertRaises(errors.ConfdClientError, self.client.SendRequest, req)
136     req2 = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
137     # Coverage is too big
138     self.assertRaises(errors.ConfdClientError, self.client.SendRequest,
139                       req2, coverage=15)
140     self.assertEquals(self.client._socket.send_count,
141                       constants.CONFD_DEFAULT_REQ_COVERAGE)
142     # Send with max coverage
143     self.client.SendRequest(req2, coverage=-1)
144     self.assertEquals(self.client._socket.send_count,
145                       constants.CONFD_DEFAULT_REQ_COVERAGE + len(self.mc_list))
146     self.assert_(self.client._socket.last_address in self.mc_list)
147
148
149   def testClientExpire(self):
150     req = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
151     self.client.SendRequest(req)
152     # Make a couple of seconds pass ;)
153     self.mock_time.increase(2)
154     # Now sending the second request
155     req2 = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
156     self.client.SendRequest(req2)
157     self.mock_time.increase(constants.CONFD_CLIENT_EXPIRE_TIMEOUT - 1)
158     # First request should be expired, second one should not
159     self.client.ExpireRequests()
160     self.assertEquals(self.callback.call_count, 1)
161     self.assertEquals(self.callback.last_up.type, confd.client.UPCALL_EXPIRE)
162     self.assertEquals(self.callback.last_up.salt, req.rsalt)
163     self.assertEquals(self.callback.last_up.orig_request, req)
164     self.mock_time.increase(3)
165     self.assertEquals(self.callback.call_count, 1)
166     self.client.ExpireRequests()
167     self.assertEquals(self.callback.call_count, 2)
168     self.assertEquals(self.callback.last_up.type, confd.client.UPCALL_EXPIRE)
169     self.assertEquals(self.callback.last_up.salt, req2.rsalt)
170     self.assertEquals(self.callback.last_up.orig_request, req2)
171
172   def testClientCascadeExpire(self):
173     req = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
174     self.client.SendRequest(req)
175     self.mock_time.increase(constants.CONFD_CLIENT_EXPIRE_TIMEOUT +1)
176     req2 = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
177     self.client.SendRequest(req2)
178     self.assertEquals(self.callback.call_count, 1)
179
180   def testUpdatePeerList(self):
181     new_peers = ['1.2.3.4', '1.2.3.5']
182     self.client.UpdatePeerList(new_peers)
183     self.assertEquals(self.client._peers, new_peers)
184     req = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
185     self.client.SendRequest(req)
186     self.assertEquals(self.client._socket.send_count, len(new_peers))
187     self.assert_(self.client._socket.last_address in new_peers)
188
189
190 if __name__ == '__main__':
191   testutils.GanetiTestProgram()