Statistics
| Branch: | Tag: | Revision:

root / test / py / ganeti.confd.client_unittest.py @ 7352d33b

History | View | Annotate | Download (7.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 fd7b69c0 Michael Hanselmann
# 02110-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 d8bcfe21 Manuel Franceschini
import socket
26 74554d66 Guido Trotter
import unittest
27 74554d66 Guido Trotter
28 74554d66 Guido Trotter
from ganeti import confd
29 74554d66 Guido Trotter
from ganeti import constants
30 74554d66 Guido Trotter
from ganeti import errors
31 74554d66 Guido Trotter
32 74554d66 Guido Trotter
import ganeti.confd.client
33 74554d66 Guido Trotter
34 25231ec5 Michael Hanselmann
import testutils
35 25231ec5 Michael Hanselmann
36 74554d66 Guido Trotter
37 74554d66 Guido Trotter
class ResettableMock(object):
38 74554d66 Guido Trotter
  def __init__(self, *args, **kwargs):
39 74554d66 Guido Trotter
    self.Reset()
40 74554d66 Guido Trotter
41 74554d66 Guido Trotter
  def Reset(self):
42 74554d66 Guido Trotter
    pass
43 74554d66 Guido Trotter
44 74554d66 Guido Trotter
45 74554d66 Guido Trotter
class MockLogger(ResettableMock):
46 74554d66 Guido Trotter
  def Reset(self):
47 74554d66 Guido Trotter
    self.debug_count = 0
48 74554d66 Guido Trotter
    self.warn_count = 0
49 74554d66 Guido Trotter
    self.error_count = 0
50 74554d66 Guido Trotter
51 74554d66 Guido Trotter
  def debug(string):
52 74554d66 Guido Trotter
    self.debug_count += 1
53 74554d66 Guido Trotter
54 74554d66 Guido Trotter
  def warning(string):
55 74554d66 Guido Trotter
    self.warn_count += 1
56 74554d66 Guido Trotter
57 74554d66 Guido Trotter
  def error(string):
58 74554d66 Guido Trotter
    self.error_count += 1
59 74554d66 Guido Trotter
60 74554d66 Guido Trotter
class MockConfdAsyncUDPClient(ResettableMock):
61 74554d66 Guido Trotter
  def Reset(self):
62 74554d66 Guido Trotter
    self.send_count = 0
63 74554d66 Guido Trotter
    self.last_address = ''
64 74554d66 Guido Trotter
    self.last_port = -1
65 74554d66 Guido Trotter
    self.last_sent = ''
66 74554d66 Guido Trotter
67 74554d66 Guido Trotter
  def enqueue_send(self, address, port, payload):
68 74554d66 Guido Trotter
    self.send_count += 1
69 74554d66 Guido Trotter
    self.last_payload = payload
70 74554d66 Guido Trotter
    self.last_port = port
71 74554d66 Guido Trotter
    self.last_address = address
72 74554d66 Guido Trotter
73 74554d66 Guido Trotter
class MockCallback(ResettableMock):
74 74554d66 Guido Trotter
  def Reset(self):
75 74554d66 Guido Trotter
    self.call_count = 0
76 74554d66 Guido Trotter
    self.last_up = None
77 74554d66 Guido Trotter
78 74554d66 Guido Trotter
  def __call__(self, up):
79 74554d66 Guido Trotter
    """Callback
80 74554d66 Guido Trotter

81 74554d66 Guido Trotter
    @type up: L{ConfdUpcallPayload}
82 74554d66 Guido Trotter
    @param up: upper callback
83 74554d66 Guido Trotter

84 74554d66 Guido Trotter
    """
85 74554d66 Guido Trotter
    self.call_count += 1
86 74554d66 Guido Trotter
    self.last_up = up
87 74554d66 Guido Trotter
88 74554d66 Guido Trotter
89 74554d66 Guido Trotter
class MockTime(ResettableMock):
90 74554d66 Guido Trotter
  def Reset(self):
91 74554d66 Guido Trotter
    self.mytime  = 1254213006.5175071
92 74554d66 Guido Trotter
93 74554d66 Guido Trotter
  def time(self):
94 74554d66 Guido Trotter
    return self.mytime
95 74554d66 Guido Trotter
96 74554d66 Guido Trotter
  def increase(self, delta):
97 74554d66 Guido Trotter
    self.mytime += delta
98 74554d66 Guido Trotter
99 74554d66 Guido Trotter
100 d8bcfe21 Manuel Franceschini
class _BaseClientTest:
101 d8bcfe21 Manuel Franceschini
  """Base class for client tests"""
102 d8bcfe21 Manuel Franceschini
  mc_list = None
103 d8bcfe21 Manuel Franceschini
  new_peers = None
104 d8bcfe21 Manuel Franceschini
  family = None
105 74554d66 Guido Trotter
106 74554d66 Guido Trotter
  def setUp(self):
107 74554d66 Guido Trotter
    self.mock_time = MockTime()
108 74554d66 Guido Trotter
    confd.client.time = self.mock_time
109 74554d66 Guido Trotter
    confd.client.ConfdAsyncUDPClient = MockConfdAsyncUDPClient
110 74554d66 Guido Trotter
    self.logger = MockLogger()
111 74554d66 Guido Trotter
    hmac_key = "mykeydata"
112 74554d66 Guido Trotter
    self.callback = MockCallback()
113 74554d66 Guido Trotter
    self.client = confd.client.ConfdClient(hmac_key, self.mc_list,
114 74554d66 Guido Trotter
                                           self.callback, logger=self.logger)
115 74554d66 Guido Trotter
116 74554d66 Guido Trotter
  def testRequest(self):
117 74554d66 Guido Trotter
    req1 = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
118 74554d66 Guido Trotter
    req2 = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
119 74554d66 Guido Trotter
    self.assertNotEqual(req1.rsalt, req2.rsalt)
120 74554d66 Guido Trotter
    self.assertEqual(req1.protocol, constants.CONFD_PROTOCOL_VERSION)
121 74554d66 Guido Trotter
    self.assertEqual(req2.protocol, constants.CONFD_PROTOCOL_VERSION)
122 74554d66 Guido Trotter
    self.assertRaises(errors.ConfdClientError, confd.client.ConfdClientRequest,
123 74554d66 Guido Trotter
                      type=-33)
124 74554d66 Guido Trotter
125 74554d66 Guido Trotter
  def testClientSend(self):
126 74554d66 Guido Trotter
    req = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
127 74554d66 Guido Trotter
    self.client.SendRequest(req)
128 74554d66 Guido Trotter
    # Cannot send the same request twice
129 74554d66 Guido Trotter
    self.assertRaises(errors.ConfdClientError, self.client.SendRequest, req)
130 74554d66 Guido Trotter
    req2 = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
131 74554d66 Guido Trotter
    # Coverage is too big
132 74554d66 Guido Trotter
    self.assertRaises(errors.ConfdClientError, self.client.SendRequest,
133 74554d66 Guido Trotter
                      req2, coverage=15)
134 74554d66 Guido Trotter
    self.assertEquals(self.client._socket.send_count,
135 74554d66 Guido Trotter
                      constants.CONFD_DEFAULT_REQ_COVERAGE)
136 cc6484c4 Iustin Pop
    # Send with max coverage
137 cc6484c4 Iustin Pop
    self.client.SendRequest(req2, coverage=-1)
138 cc6484c4 Iustin Pop
    self.assertEquals(self.client._socket.send_count,
139 cc6484c4 Iustin Pop
                      constants.CONFD_DEFAULT_REQ_COVERAGE + len(self.mc_list))
140 74554d66 Guido Trotter
    self.assert_(self.client._socket.last_address in self.mc_list)
141 74554d66 Guido Trotter
142 74554d66 Guido Trotter
143 74554d66 Guido Trotter
  def testClientExpire(self):
144 74554d66 Guido Trotter
    req = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
145 74554d66 Guido Trotter
    self.client.SendRequest(req)
146 74554d66 Guido Trotter
    # Make a couple of seconds pass ;)
147 74554d66 Guido Trotter
    self.mock_time.increase(2)
148 74554d66 Guido Trotter
    # Now sending the second request
149 74554d66 Guido Trotter
    req2 = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
150 74554d66 Guido Trotter
    self.client.SendRequest(req2)
151 74554d66 Guido Trotter
    self.mock_time.increase(constants.CONFD_CLIENT_EXPIRE_TIMEOUT - 1)
152 74554d66 Guido Trotter
    # First request should be expired, second one should not
153 74554d66 Guido Trotter
    self.client.ExpireRequests()
154 74554d66 Guido Trotter
    self.assertEquals(self.callback.call_count, 1)
155 74554d66 Guido Trotter
    self.assertEquals(self.callback.last_up.type, confd.client.UPCALL_EXPIRE)
156 74554d66 Guido Trotter
    self.assertEquals(self.callback.last_up.salt, req.rsalt)
157 74554d66 Guido Trotter
    self.assertEquals(self.callback.last_up.orig_request, req)
158 74554d66 Guido Trotter
    self.mock_time.increase(3)
159 74554d66 Guido Trotter
    self.assertEquals(self.callback.call_count, 1)
160 74554d66 Guido Trotter
    self.client.ExpireRequests()
161 74554d66 Guido Trotter
    self.assertEquals(self.callback.call_count, 2)
162 74554d66 Guido Trotter
    self.assertEquals(self.callback.last_up.type, confd.client.UPCALL_EXPIRE)
163 74554d66 Guido Trotter
    self.assertEquals(self.callback.last_up.salt, req2.rsalt)
164 74554d66 Guido Trotter
    self.assertEquals(self.callback.last_up.orig_request, req2)
165 74554d66 Guido Trotter
166 74554d66 Guido Trotter
  def testClientCascadeExpire(self):
167 74554d66 Guido Trotter
    req = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
168 74554d66 Guido Trotter
    self.client.SendRequest(req)
169 74554d66 Guido Trotter
    self.mock_time.increase(constants.CONFD_CLIENT_EXPIRE_TIMEOUT +1)
170 74554d66 Guido Trotter
    req2 = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
171 74554d66 Guido Trotter
    self.client.SendRequest(req2)
172 74554d66 Guido Trotter
    self.assertEquals(self.callback.call_count, 1)
173 74554d66 Guido Trotter
174 74554d66 Guido Trotter
  def testUpdatePeerList(self):
175 d8bcfe21 Manuel Franceschini
    self.client.UpdatePeerList(self.new_peers)
176 d8bcfe21 Manuel Franceschini
    self.assertEquals(self.client._peers, self.new_peers)
177 74554d66 Guido Trotter
    req = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
178 74554d66 Guido Trotter
    self.client.SendRequest(req)
179 d8bcfe21 Manuel Franceschini
    self.assertEquals(self.client._socket.send_count, len(self.new_peers))
180 d8bcfe21 Manuel Franceschini
    self.assert_(self.client._socket.last_address in self.new_peers)
181 d8bcfe21 Manuel Franceschini
182 d8bcfe21 Manuel Franceschini
  def testSetPeersFamily(self):
183 d8bcfe21 Manuel Franceschini
    self.client._SetPeersAddressFamily()
184 d8bcfe21 Manuel Franceschini
    self.assertEquals(self.client._family, self.family)
185 926feaf1 Manuel Franceschini
    mixed_peers = ["192.0.2.99", "2001:db8:beef::13"]
186 d8bcfe21 Manuel Franceschini
    self.client.UpdatePeerList(mixed_peers)
187 d8bcfe21 Manuel Franceschini
    self.assertRaises(errors.ConfdClientError,
188 d8bcfe21 Manuel Franceschini
                      self.client._SetPeersAddressFamily)
189 d8bcfe21 Manuel Franceschini
190 d8bcfe21 Manuel Franceschini
191 d8bcfe21 Manuel Franceschini
class TestIP4Client(unittest.TestCase, _BaseClientTest):
192 d8bcfe21 Manuel Franceschini
  """Client tests"""
193 926feaf1 Manuel Franceschini
  mc_list = ["192.0.2.1",
194 926feaf1 Manuel Franceschini
             "192.0.2.2",
195 926feaf1 Manuel Franceschini
             "192.0.2.3",
196 926feaf1 Manuel Franceschini
             "192.0.2.4",
197 926feaf1 Manuel Franceschini
             "192.0.2.5",
198 926feaf1 Manuel Franceschini
             "192.0.2.6",
199 926feaf1 Manuel Franceschini
             "192.0.2.7",
200 926feaf1 Manuel Franceschini
             "192.0.2.8",
201 926feaf1 Manuel Franceschini
             "192.0.2.9",
202 d8bcfe21 Manuel Franceschini
            ]
203 926feaf1 Manuel Franceschini
  new_peers = ["198.51.100.1", "198.51.100.2"]
204 d8bcfe21 Manuel Franceschini
  family = socket.AF_INET
205 d8bcfe21 Manuel Franceschini
206 d8bcfe21 Manuel Franceschini
  def setUp(self):
207 d8bcfe21 Manuel Franceschini
    unittest.TestCase.setUp(self)
208 d8bcfe21 Manuel Franceschini
    _BaseClientTest.setUp(self)
209 d8bcfe21 Manuel Franceschini
210 d8bcfe21 Manuel Franceschini
211 d8bcfe21 Manuel Franceschini
class TestIP6Client(unittest.TestCase, _BaseClientTest):
212 d8bcfe21 Manuel Franceschini
  """Client tests"""
213 d8bcfe21 Manuel Franceschini
  mc_list = ["2001:db8::1",
214 d8bcfe21 Manuel Franceschini
             "2001:db8::2",
215 d8bcfe21 Manuel Franceschini
             "2001:db8::3",
216 d8bcfe21 Manuel Franceschini
             "2001:db8::4",
217 d8bcfe21 Manuel Franceschini
             "2001:db8::5",
218 d8bcfe21 Manuel Franceschini
             "2001:db8::6",
219 d8bcfe21 Manuel Franceschini
             "2001:db8::7",
220 d8bcfe21 Manuel Franceschini
             "2001:db8::8",
221 d8bcfe21 Manuel Franceschini
             "2001:db8::9",
222 d8bcfe21 Manuel Franceschini
            ]
223 d8bcfe21 Manuel Franceschini
  new_peers = ["2001:db8:beef::11", "2001:db8:beef::12"]
224 d8bcfe21 Manuel Franceschini
  family = socket.AF_INET6
225 d8bcfe21 Manuel Franceschini
226 d8bcfe21 Manuel Franceschini
  def setUp(self):
227 d8bcfe21 Manuel Franceschini
    unittest.TestCase.setUp(self)
228 d8bcfe21 Manuel Franceschini
    _BaseClientTest.setUp(self)
229 74554d66 Guido Trotter
230 74554d66 Guido Trotter
231 2f96c43c Michael Hanselmann
if __name__ == "__main__":
232 25231ec5 Michael Hanselmann
  testutils.GanetiTestProgram()