Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.confd.client_unittest.py @ edf7d66e

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()