root / test / ganeti.confd.client_unittest.py @ 12eff9b9
History | View | Annotate | Download (6.1 kB)
1 | 74554d66 | Guido Trotter | #!/usr/bin/python
|
---|---|---|---|
2 | 74554d66 | Guido Trotter | #
|
3 | 74554d66 | Guido Trotter | |
4 | 74554d66 | Guido Trotter | # Copyright (C) 2009 Google Inc.
|
5 | 74554d66 | Guido Trotter | #
|
6 | 74554d66 | Guido Trotter | # This program is free software; you can redistribute it and/or modify
|
7 | 74554d66 | Guido Trotter | # it under the terms of the GNU General Public License as published by
|
8 | 74554d66 | Guido Trotter | # the Free Software Foundation; either version 2 of the License, or
|
9 | 74554d66 | Guido Trotter | # (at your option) any later version.
|
10 | 74554d66 | Guido Trotter | #
|
11 | 74554d66 | Guido Trotter | # This program is distributed in the hope that it will be useful, but
|
12 | 74554d66 | Guido Trotter | # WITHOUT ANY WARRANTY; without even the implied warranty of
|
13 | 74554d66 | Guido Trotter | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14 | 74554d66 | Guido Trotter | # General Public License for more details.
|
15 | 74554d66 | Guido Trotter | #
|
16 | 74554d66 | Guido Trotter | # You should have received a copy of the GNU General Public License
|
17 | 74554d66 | Guido Trotter | # along with this program; if not, write to the Free Software
|
18 | 74554d66 | Guido Trotter | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
19 | 74554d66 | Guido Trotter | # 0.0510-1301, USA.
|
20 | 74554d66 | Guido Trotter | |
21 | 74554d66 | Guido Trotter | |
22 | 74554d66 | Guido Trotter | """Script for unittesting the confd client module"""
|
23 | 74554d66 | Guido Trotter | |
24 | 74554d66 | Guido Trotter | |
25 | 74554d66 | Guido Trotter | import unittest |
26 | 74554d66 | Guido Trotter | |
27 | 74554d66 | Guido Trotter | from ganeti import confd |
28 | 74554d66 | Guido Trotter | from ganeti import constants |
29 | 74554d66 | Guido Trotter | from ganeti import errors |
30 | 74554d66 | Guido Trotter | |
31 | 74554d66 | Guido Trotter | import ganeti.confd.client |
32 | 74554d66 | Guido Trotter | |
33 | 25231ec5 | Michael Hanselmann | import testutils |
34 | 25231ec5 | Michael Hanselmann | |
35 | 74554d66 | Guido Trotter | |
36 | 74554d66 | Guido Trotter | class ResettableMock(object): |
37 | 74554d66 | Guido Trotter | def __init__(self, *args, **kwargs): |
38 | 74554d66 | Guido Trotter | self.Reset()
|
39 | 74554d66 | Guido Trotter | |
40 | 74554d66 | Guido Trotter | def Reset(self): |
41 | 74554d66 | Guido Trotter | pass
|
42 | 74554d66 | Guido Trotter | |
43 | 74554d66 | Guido Trotter | |
44 | 74554d66 | Guido Trotter | class MockLogger(ResettableMock): |
45 | 74554d66 | Guido Trotter | def Reset(self): |
46 | 74554d66 | Guido Trotter | self.debug_count = 0 |
47 | 74554d66 | Guido Trotter | self.warn_count = 0 |
48 | 74554d66 | Guido Trotter | self.error_count = 0 |
49 | 74554d66 | Guido Trotter | |
50 | 74554d66 | Guido Trotter | def debug(string): |
51 | 74554d66 | Guido Trotter | self.debug_count += 1 |
52 | 74554d66 | Guido Trotter | |
53 | 74554d66 | Guido Trotter | def warning(string): |
54 | 74554d66 | Guido Trotter | self.warn_count += 1 |
55 | 74554d66 | Guido Trotter | |
56 | 74554d66 | Guido Trotter | def error(string): |
57 | 74554d66 | Guido Trotter | self.error_count += 1 |
58 | 74554d66 | Guido Trotter | |
59 | 74554d66 | Guido Trotter | class MockConfdAsyncUDPClient(ResettableMock): |
60 | 74554d66 | Guido Trotter | def Reset(self): |
61 | 74554d66 | Guido Trotter | self.send_count = 0 |
62 | 74554d66 | Guido Trotter | self.last_address = '' |
63 | 74554d66 | Guido Trotter | self.last_port = -1 |
64 | 74554d66 | Guido Trotter | self.last_sent = '' |
65 | 74554d66 | Guido Trotter | |
66 | 74554d66 | Guido Trotter | def enqueue_send(self, address, port, payload): |
67 | 74554d66 | Guido Trotter | self.send_count += 1 |
68 | 74554d66 | Guido Trotter | self.last_payload = payload
|
69 | 74554d66 | Guido Trotter | self.last_port = port
|
70 | 74554d66 | Guido Trotter | self.last_address = address
|
71 | 74554d66 | Guido Trotter | |
72 | 74554d66 | Guido Trotter | class MockCallback(ResettableMock): |
73 | 74554d66 | Guido Trotter | def Reset(self): |
74 | 74554d66 | Guido Trotter | self.call_count = 0 |
75 | 74554d66 | Guido Trotter | self.last_up = None |
76 | 74554d66 | Guido Trotter | |
77 | 74554d66 | Guido Trotter | def __call__(self, up): |
78 | 74554d66 | Guido Trotter | """Callback
|
79 | 74554d66 | Guido Trotter |
|
80 | 74554d66 | Guido Trotter | @type up: L{ConfdUpcallPayload}
|
81 | 74554d66 | Guido Trotter | @param up: upper callback
|
82 | 74554d66 | Guido Trotter |
|
83 | 74554d66 | Guido Trotter | """
|
84 | 74554d66 | Guido Trotter | self.call_count += 1 |
85 | 74554d66 | Guido Trotter | self.last_up = up
|
86 | 74554d66 | Guido Trotter | |
87 | 74554d66 | Guido Trotter | |
88 | 74554d66 | Guido Trotter | class MockTime(ResettableMock): |
89 | 74554d66 | Guido Trotter | def Reset(self): |
90 | 74554d66 | Guido Trotter | self.mytime = 1254213006.5175071 |
91 | 74554d66 | Guido Trotter | |
92 | 74554d66 | Guido Trotter | def time(self): |
93 | 74554d66 | Guido Trotter | return self.mytime |
94 | 74554d66 | Guido Trotter | |
95 | 74554d66 | Guido Trotter | def increase(self, delta): |
96 | 74554d66 | Guido Trotter | self.mytime += delta
|
97 | 74554d66 | Guido Trotter | |
98 | 74554d66 | Guido Trotter | |
99 | 74554d66 | Guido Trotter | class TestClient(unittest.TestCase): |
100 | 74554d66 | Guido Trotter | """Client tests"""
|
101 | 74554d66 | Guido Trotter | |
102 | 74554d66 | Guido Trotter | def setUp(self): |
103 | 74554d66 | Guido Trotter | self.mock_time = MockTime()
|
104 | 74554d66 | Guido Trotter | confd.client.time = self.mock_time
|
105 | 74554d66 | Guido Trotter | confd.client.ConfdAsyncUDPClient = MockConfdAsyncUDPClient |
106 | 74554d66 | Guido Trotter | self.logger = MockLogger()
|
107 | 74554d66 | Guido Trotter | hmac_key = "mykeydata"
|
108 | 74554d66 | Guido Trotter | self.mc_list = ['10.0.0.1', |
109 | 74554d66 | Guido Trotter | '10.0.0.2',
|
110 | 74554d66 | Guido Trotter | '10.0.0.3',
|
111 | 74554d66 | Guido Trotter | '10.0.0.4',
|
112 | 74554d66 | Guido Trotter | '10.0.0.5',
|
113 | 74554d66 | Guido Trotter | '10.0.0.6',
|
114 | 74554d66 | Guido Trotter | '10.0.0.7',
|
115 | 74554d66 | Guido Trotter | '10.0.0.8',
|
116 | 74554d66 | Guido Trotter | '10.0.0.9',
|
117 | 74554d66 | Guido Trotter | ] |
118 | 74554d66 | Guido Trotter | self.callback = MockCallback()
|
119 | 74554d66 | Guido Trotter | self.client = confd.client.ConfdClient(hmac_key, self.mc_list, |
120 | 74554d66 | Guido Trotter | self.callback, logger=self.logger) |
121 | 74554d66 | Guido Trotter | |
122 | 74554d66 | Guido Trotter | def testRequest(self): |
123 | 74554d66 | Guido Trotter | req1 = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING) |
124 | 74554d66 | Guido Trotter | req2 = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING) |
125 | 74554d66 | Guido Trotter | self.assertNotEqual(req1.rsalt, req2.rsalt)
|
126 | 74554d66 | Guido Trotter | self.assertEqual(req1.protocol, constants.CONFD_PROTOCOL_VERSION)
|
127 | 74554d66 | Guido Trotter | self.assertEqual(req2.protocol, constants.CONFD_PROTOCOL_VERSION)
|
128 | 74554d66 | Guido Trotter | self.assertRaises(errors.ConfdClientError, confd.client.ConfdClientRequest,
|
129 | 74554d66 | Guido Trotter | type=-33)
|
130 | 74554d66 | Guido Trotter | |
131 | 74554d66 | Guido Trotter | def testClientSend(self): |
132 | 74554d66 | Guido Trotter | req = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING) |
133 | 74554d66 | Guido Trotter | self.client.SendRequest(req)
|
134 | 74554d66 | Guido Trotter | # Cannot send the same request twice
|
135 | 74554d66 | Guido Trotter | self.assertRaises(errors.ConfdClientError, self.client.SendRequest, req) |
136 | 74554d66 | Guido Trotter | req2 = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING) |
137 | 74554d66 | Guido Trotter | # Coverage is too big
|
138 | 74554d66 | Guido Trotter | self.assertRaises(errors.ConfdClientError, self.client.SendRequest, |
139 | 74554d66 | Guido Trotter | req2, coverage=15)
|
140 | 74554d66 | Guido Trotter | self.assertEquals(self.client._socket.send_count, |
141 | 74554d66 | Guido Trotter | constants.CONFD_DEFAULT_REQ_COVERAGE) |
142 | cc6484c4 | Iustin Pop | # Send with max coverage
|
143 | cc6484c4 | Iustin Pop | self.client.SendRequest(req2, coverage=-1) |
144 | cc6484c4 | Iustin Pop | self.assertEquals(self.client._socket.send_count, |
145 | cc6484c4 | Iustin Pop | constants.CONFD_DEFAULT_REQ_COVERAGE + len(self.mc_list)) |
146 | 74554d66 | Guido Trotter | self.assert_(self.client._socket.last_address in self.mc_list) |
147 | 74554d66 | Guido Trotter | |
148 | 74554d66 | Guido Trotter | |
149 | 74554d66 | Guido Trotter | def testClientExpire(self): |
150 | 74554d66 | Guido Trotter | req = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING) |
151 | 74554d66 | Guido Trotter | self.client.SendRequest(req)
|
152 | 74554d66 | Guido Trotter | # Make a couple of seconds pass ;)
|
153 | 74554d66 | Guido Trotter | self.mock_time.increase(2) |
154 | 74554d66 | Guido Trotter | # Now sending the second request
|
155 | 74554d66 | Guido Trotter | req2 = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING) |
156 | 74554d66 | Guido Trotter | self.client.SendRequest(req2)
|
157 | 74554d66 | Guido Trotter | self.mock_time.increase(constants.CONFD_CLIENT_EXPIRE_TIMEOUT - 1) |
158 | 74554d66 | Guido Trotter | # First request should be expired, second one should not
|
159 | 74554d66 | Guido Trotter | self.client.ExpireRequests()
|
160 | 74554d66 | Guido Trotter | self.assertEquals(self.callback.call_count, 1) |
161 | 74554d66 | Guido Trotter | self.assertEquals(self.callback.last_up.type, confd.client.UPCALL_EXPIRE) |
162 | 74554d66 | Guido Trotter | self.assertEquals(self.callback.last_up.salt, req.rsalt) |
163 | 74554d66 | Guido Trotter | self.assertEquals(self.callback.last_up.orig_request, req) |
164 | 74554d66 | Guido Trotter | self.mock_time.increase(3) |
165 | 74554d66 | Guido Trotter | self.assertEquals(self.callback.call_count, 1) |
166 | 74554d66 | Guido Trotter | self.client.ExpireRequests()
|
167 | 74554d66 | Guido Trotter | self.assertEquals(self.callback.call_count, 2) |
168 | 74554d66 | Guido Trotter | self.assertEquals(self.callback.last_up.type, confd.client.UPCALL_EXPIRE) |
169 | 74554d66 | Guido Trotter | self.assertEquals(self.callback.last_up.salt, req2.rsalt) |
170 | 74554d66 | Guido Trotter | self.assertEquals(self.callback.last_up.orig_request, req2) |
171 | 74554d66 | Guido Trotter | |
172 | 74554d66 | Guido Trotter | def testClientCascadeExpire(self): |
173 | 74554d66 | Guido Trotter | req = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING) |
174 | 74554d66 | Guido Trotter | self.client.SendRequest(req)
|
175 | 74554d66 | Guido Trotter | self.mock_time.increase(constants.CONFD_CLIENT_EXPIRE_TIMEOUT +1) |
176 | 74554d66 | Guido Trotter | req2 = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING) |
177 | 74554d66 | Guido Trotter | self.client.SendRequest(req2)
|
178 | 74554d66 | Guido Trotter | self.assertEquals(self.callback.call_count, 1) |
179 | 74554d66 | Guido Trotter | |
180 | 74554d66 | Guido Trotter | def testUpdatePeerList(self): |
181 | 74554d66 | Guido Trotter | new_peers = ['1.2.3.4', '1.2.3.5'] |
182 | 74554d66 | Guido Trotter | self.client.UpdatePeerList(new_peers)
|
183 | 74554d66 | Guido Trotter | self.assertEquals(self.client._peers, new_peers) |
184 | 74554d66 | Guido Trotter | req = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING) |
185 | 74554d66 | Guido Trotter | self.client.SendRequest(req)
|
186 | 74554d66 | Guido Trotter | self.assertEquals(self.client._socket.send_count, len(new_peers)) |
187 | 74554d66 | Guido Trotter | self.assert_(self.client._socket.last_address in new_peers) |
188 | 74554d66 | Guido Trotter | |
189 | 74554d66 | Guido Trotter | |
190 | 74554d66 | Guido Trotter | if __name__ == '__main__': |
191 | 25231ec5 | Michael Hanselmann | testutils.GanetiTestProgram() |