Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (7.1 kB)

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
# 02110-1301, USA.
20

    
21

    
22
"""Script for unittesting the confd client module"""
23

    
24

    
25
import socket
26
import unittest
27

    
28
from ganeti import confd
29
from ganeti import constants
30
from ganeti import errors
31

    
32
import ganeti.confd.client
33

    
34
import testutils
35

    
36

    
37
class ResettableMock(object):
38
  def __init__(self, *args, **kwargs):
39
    self.Reset()
40

    
41
  def Reset(self):
42
    pass
43

    
44

    
45
class MockLogger(ResettableMock):
46
  def Reset(self):
47
    self.debug_count = 0
48
    self.warn_count = 0
49
    self.error_count = 0
50

    
51
  def debug(string):
52
    self.debug_count += 1
53

    
54
  def warning(string):
55
    self.warn_count += 1
56

    
57
  def error(string):
58
    self.error_count += 1
59

    
60
class MockConfdAsyncUDPClient(ResettableMock):
61
  def Reset(self):
62
    self.send_count = 0
63
    self.last_address = ''
64
    self.last_port = -1
65
    self.last_sent = ''
66

    
67
  def enqueue_send(self, address, port, payload):
68
    self.send_count += 1
69
    self.last_payload = payload
70
    self.last_port = port
71
    self.last_address = address
72

    
73
class MockCallback(ResettableMock):
74
  def Reset(self):
75
    self.call_count = 0
76
    self.last_up = None
77

    
78
  def __call__(self, up):
79
    """Callback
80

81
    @type up: L{ConfdUpcallPayload}
82
    @param up: upper callback
83

84
    """
85
    self.call_count += 1
86
    self.last_up = up
87

    
88

    
89
class MockTime(ResettableMock):
90
  def Reset(self):
91
    self.mytime  = 1254213006.5175071
92

    
93
  def time(self):
94
    return self.mytime
95

    
96
  def increase(self, delta):
97
    self.mytime += delta
98

    
99

    
100
class _BaseClientTest:
101
  """Base class for client tests"""
102
  mc_list = None
103
  new_peers = None
104
  family = None
105

    
106
  def setUp(self):
107
    self.mock_time = MockTime()
108
    confd.client.time = self.mock_time
109
    confd.client.ConfdAsyncUDPClient = MockConfdAsyncUDPClient
110
    self.logger = MockLogger()
111
    hmac_key = "mykeydata"
112
    self.callback = MockCallback()
113
    self.client = confd.client.ConfdClient(hmac_key, self.mc_list,
114
                                           self.callback, logger=self.logger)
115

    
116
  def testRequest(self):
117
    req1 = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
118
    req2 = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
119
    self.assertNotEqual(req1.rsalt, req2.rsalt)
120
    self.assertEqual(req1.protocol, constants.CONFD_PROTOCOL_VERSION)
121
    self.assertEqual(req2.protocol, constants.CONFD_PROTOCOL_VERSION)
122
    self.assertRaises(errors.ConfdClientError, confd.client.ConfdClientRequest,
123
                      type=-33)
124

    
125
  def testClientSend(self):
126
    req = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
127
    self.client.SendRequest(req)
128
    # Cannot send the same request twice
129
    self.assertRaises(errors.ConfdClientError, self.client.SendRequest, req)
130
    req2 = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
131
    # Coverage is too big
132
    self.assertRaises(errors.ConfdClientError, self.client.SendRequest,
133
                      req2, coverage=15)
134
    self.assertEquals(self.client._socket.send_count,
135
                      constants.CONFD_DEFAULT_REQ_COVERAGE)
136
    # Send with max coverage
137
    self.client.SendRequest(req2, coverage=-1)
138
    self.assertEquals(self.client._socket.send_count,
139
                      constants.CONFD_DEFAULT_REQ_COVERAGE + len(self.mc_list))
140
    self.assert_(self.client._socket.last_address in self.mc_list)
141

    
142

    
143
  def testClientExpire(self):
144
    req = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
145
    self.client.SendRequest(req)
146
    # Make a couple of seconds pass ;)
147
    self.mock_time.increase(2)
148
    # Now sending the second request
149
    req2 = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
150
    self.client.SendRequest(req2)
151
    self.mock_time.increase(constants.CONFD_CLIENT_EXPIRE_TIMEOUT - 1)
152
    # First request should be expired, second one should not
153
    self.client.ExpireRequests()
154
    self.assertEquals(self.callback.call_count, 1)
155
    self.assertEquals(self.callback.last_up.type, confd.client.UPCALL_EXPIRE)
156
    self.assertEquals(self.callback.last_up.salt, req.rsalt)
157
    self.assertEquals(self.callback.last_up.orig_request, req)
158
    self.mock_time.increase(3)
159
    self.assertEquals(self.callback.call_count, 1)
160
    self.client.ExpireRequests()
161
    self.assertEquals(self.callback.call_count, 2)
162
    self.assertEquals(self.callback.last_up.type, confd.client.UPCALL_EXPIRE)
163
    self.assertEquals(self.callback.last_up.salt, req2.rsalt)
164
    self.assertEquals(self.callback.last_up.orig_request, req2)
165

    
166
  def testClientCascadeExpire(self):
167
    req = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
168
    self.client.SendRequest(req)
169
    self.mock_time.increase(constants.CONFD_CLIENT_EXPIRE_TIMEOUT +1)
170
    req2 = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
171
    self.client.SendRequest(req2)
172
    self.assertEquals(self.callback.call_count, 1)
173

    
174
  def testUpdatePeerList(self):
175
    self.client.UpdatePeerList(self.new_peers)
176
    self.assertEquals(self.client._peers, self.new_peers)
177
    req = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
178
    self.client.SendRequest(req)
179
    self.assertEquals(self.client._socket.send_count, len(self.new_peers))
180
    self.assert_(self.client._socket.last_address in self.new_peers)
181

    
182
  def testSetPeersFamily(self):
183
    self.client._SetPeersAddressFamily()
184
    self.assertEquals(self.client._family, self.family)
185
    mixed_peers = ["192.0.2.99", "2001:db8:beef::13"]
186
    self.client.UpdatePeerList(mixed_peers)
187
    self.assertRaises(errors.ConfdClientError,
188
                      self.client._SetPeersAddressFamily)
189

    
190

    
191
class TestIP4Client(unittest.TestCase, _BaseClientTest):
192
  """Client tests"""
193
  mc_list = ["192.0.2.1",
194
             "192.0.2.2",
195
             "192.0.2.3",
196
             "192.0.2.4",
197
             "192.0.2.5",
198
             "192.0.2.6",
199
             "192.0.2.7",
200
             "192.0.2.8",
201
             "192.0.2.9",
202
            ]
203
  new_peers = ["198.51.100.1", "198.51.100.2"]
204
  family = socket.AF_INET
205

    
206
  def setUp(self):
207
    unittest.TestCase.setUp(self)
208
    _BaseClientTest.setUp(self)
209

    
210

    
211
class TestIP6Client(unittest.TestCase, _BaseClientTest):
212
  """Client tests"""
213
  mc_list = ["2001:db8::1",
214
             "2001:db8::2",
215
             "2001:db8::3",
216
             "2001:db8::4",
217
             "2001:db8::5",
218
             "2001:db8::6",
219
             "2001:db8::7",
220
             "2001:db8::8",
221
             "2001:db8::9",
222
            ]
223
  new_peers = ["2001:db8:beef::11", "2001:db8:beef::12"]
224
  family = socket.AF_INET6
225

    
226
  def setUp(self):
227
    unittest.TestCase.setUp(self)
228
    _BaseClientTest.setUp(self)
229

    
230

    
231
if __name__ == '__main__':
232
  testutils.GanetiTestProgram()