Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.confd_client_unittest.py @ d357f531

History | View | Annotate | Download (5.8 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 74554d66 Guido Trotter
34 74554d66 Guido Trotter
class ResettableMock(object):
35 74554d66 Guido Trotter
  def __init__(self, *args, **kwargs):
36 74554d66 Guido Trotter
    self.Reset()
37 74554d66 Guido Trotter
38 74554d66 Guido Trotter
  def Reset(self):
39 74554d66 Guido Trotter
    pass
40 74554d66 Guido Trotter
41 74554d66 Guido Trotter
42 74554d66 Guido Trotter
class MockLogger(ResettableMock):
43 74554d66 Guido Trotter
  def Reset(self):
44 74554d66 Guido Trotter
    self.debug_count = 0
45 74554d66 Guido Trotter
    self.warn_count = 0
46 74554d66 Guido Trotter
    self.error_count = 0
47 74554d66 Guido Trotter
48 74554d66 Guido Trotter
  def debug(string):
49 74554d66 Guido Trotter
    self.debug_count += 1
50 74554d66 Guido Trotter
51 74554d66 Guido Trotter
  def warning(string):
52 74554d66 Guido Trotter
    self.warn_count += 1
53 74554d66 Guido Trotter
54 74554d66 Guido Trotter
  def error(string):
55 74554d66 Guido Trotter
    self.error_count += 1
56 74554d66 Guido Trotter
57 74554d66 Guido Trotter
class MockConfdAsyncUDPClient(ResettableMock):
58 74554d66 Guido Trotter
  def Reset(self):
59 74554d66 Guido Trotter
    self.send_count = 0
60 74554d66 Guido Trotter
    self.last_address = ''
61 74554d66 Guido Trotter
    self.last_port = -1
62 74554d66 Guido Trotter
    self.last_sent = ''
63 74554d66 Guido Trotter
64 74554d66 Guido Trotter
  def enqueue_send(self, address, port, payload):
65 74554d66 Guido Trotter
    self.send_count += 1
66 74554d66 Guido Trotter
    self.last_payload = payload
67 74554d66 Guido Trotter
    self.last_port = port
68 74554d66 Guido Trotter
    self.last_address = address
69 74554d66 Guido Trotter
70 74554d66 Guido Trotter
class MockCallback(ResettableMock):
71 74554d66 Guido Trotter
  def Reset(self):
72 74554d66 Guido Trotter
    self.call_count = 0
73 74554d66 Guido Trotter
    self.last_up = None
74 74554d66 Guido Trotter
75 74554d66 Guido Trotter
  def __call__(self, up):
76 74554d66 Guido Trotter
    """Callback
77 74554d66 Guido Trotter

78 74554d66 Guido Trotter
    @type up: L{ConfdUpcallPayload}
79 74554d66 Guido Trotter
    @param up: upper callback
80 74554d66 Guido Trotter

81 74554d66 Guido Trotter
    """
82 74554d66 Guido Trotter
    self.call_count += 1
83 74554d66 Guido Trotter
    self.last_up = up
84 74554d66 Guido Trotter
85 74554d66 Guido Trotter
86 74554d66 Guido Trotter
class MockTime(ResettableMock):
87 74554d66 Guido Trotter
  def Reset(self):
88 74554d66 Guido Trotter
    self.mytime  = 1254213006.5175071
89 74554d66 Guido Trotter
90 74554d66 Guido Trotter
  def time(self):
91 74554d66 Guido Trotter
    return self.mytime
92 74554d66 Guido Trotter
93 74554d66 Guido Trotter
  def increase(self, delta):
94 74554d66 Guido Trotter
    self.mytime += delta
95 74554d66 Guido Trotter
96 74554d66 Guido Trotter
97 74554d66 Guido Trotter
class TestClient(unittest.TestCase):
98 74554d66 Guido Trotter
  """Client tests"""
99 74554d66 Guido Trotter
100 74554d66 Guido Trotter
  def setUp(self):
101 74554d66 Guido Trotter
    self.mock_time = MockTime()
102 74554d66 Guido Trotter
    confd.client.time = self.mock_time
103 74554d66 Guido Trotter
    confd.client.ConfdAsyncUDPClient = MockConfdAsyncUDPClient
104 74554d66 Guido Trotter
    self.logger = MockLogger()
105 74554d66 Guido Trotter
    hmac_key = "mykeydata"
106 74554d66 Guido Trotter
    self.mc_list = ['10.0.0.1',
107 74554d66 Guido Trotter
                    '10.0.0.2',
108 74554d66 Guido Trotter
                    '10.0.0.3',
109 74554d66 Guido Trotter
                    '10.0.0.4',
110 74554d66 Guido Trotter
                    '10.0.0.5',
111 74554d66 Guido Trotter
                    '10.0.0.6',
112 74554d66 Guido Trotter
                    '10.0.0.7',
113 74554d66 Guido Trotter
                    '10.0.0.8',
114 74554d66 Guido Trotter
                    '10.0.0.9',
115 74554d66 Guido Trotter
                   ]
116 74554d66 Guido Trotter
    self.callback = MockCallback()
117 74554d66 Guido Trotter
    self.client = confd.client.ConfdClient(hmac_key, self.mc_list,
118 74554d66 Guido Trotter
                                           self.callback, logger=self.logger)
119 74554d66 Guido Trotter
120 74554d66 Guido Trotter
  def testRequest(self):
121 74554d66 Guido Trotter
    req1 = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
122 74554d66 Guido Trotter
    req2 = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
123 74554d66 Guido Trotter
    self.assertNotEqual(req1.rsalt, req2.rsalt)
124 74554d66 Guido Trotter
    self.assertEqual(req1.protocol, constants.CONFD_PROTOCOL_VERSION)
125 74554d66 Guido Trotter
    self.assertEqual(req2.protocol, constants.CONFD_PROTOCOL_VERSION)
126 74554d66 Guido Trotter
    self.assertRaises(errors.ConfdClientError, confd.client.ConfdClientRequest,
127 74554d66 Guido Trotter
                      type=-33)
128 74554d66 Guido Trotter
129 74554d66 Guido Trotter
  def testClientSend(self):
130 74554d66 Guido Trotter
    req = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
131 74554d66 Guido Trotter
    self.client.SendRequest(req)
132 74554d66 Guido Trotter
    # Cannot send the same request twice
133 74554d66 Guido Trotter
    self.assertRaises(errors.ConfdClientError, self.client.SendRequest, req)
134 74554d66 Guido Trotter
    req2 = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
135 74554d66 Guido Trotter
    # Coverage is too big
136 74554d66 Guido Trotter
    self.assertRaises(errors.ConfdClientError, self.client.SendRequest,
137 74554d66 Guido Trotter
                      req2, coverage=15)
138 74554d66 Guido Trotter
    self.assertEquals(self.client._socket.send_count,
139 74554d66 Guido Trotter
                      constants.CONFD_DEFAULT_REQ_COVERAGE)
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 74554d66 Guido Trotter
    new_peers = ['1.2.3.4', '1.2.3.5']
176 74554d66 Guido Trotter
    self.client.UpdatePeerList(new_peers)
177 74554d66 Guido Trotter
    self.assertEquals(self.client._peers, new_peers)
178 74554d66 Guido Trotter
    req = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
179 74554d66 Guido Trotter
    self.client.SendRequest(req)
180 74554d66 Guido Trotter
    self.assertEquals(self.client._socket.send_count, len(new_peers))
181 74554d66 Guido Trotter
    self.assert_(self.client._socket.last_address in new_peers)
182 74554d66 Guido Trotter
183 74554d66 Guido Trotter
184 74554d66 Guido Trotter
if __name__ == '__main__':
185 74554d66 Guido Trotter
  unittest.main()