Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (6.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
# 0.0510-1301, USA.
20

    
21

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

    
24

    
25
import unittest
26

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

    
31
import ganeti.confd.client
32

    
33
import testutils
34

    
35

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

    
40
  def Reset(self):
41
    pass
42

    
43

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

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

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

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

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

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

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

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

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

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

    
87

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

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

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

    
98

    
99
class TestClient(unittest.TestCase):
100
  """Client tests"""
101

    
102
  def setUp(self):
103
    self.mock_time = MockTime()
104
    confd.client.time = self.mock_time
105
    confd.client.ConfdAsyncUDPClient = MockConfdAsyncUDPClient
106
    self.logger = MockLogger()
107
    hmac_key = "mykeydata"
108
    self.mc_list = ['10.0.0.1',
109
                    '10.0.0.2',
110
                    '10.0.0.3',
111
                    '10.0.0.4',
112
                    '10.0.0.5',
113
                    '10.0.0.6',
114
                    '10.0.0.7',
115
                    '10.0.0.8',
116
                    '10.0.0.9',
117
                   ]
118
    self.callback = MockCallback()
119
    self.client = confd.client.ConfdClient(hmac_key, self.mc_list,
120
                                           self.callback, logger=self.logger)
121

    
122
  def testRequest(self):
123
    req1 = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
124
    req2 = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
125
    self.assertNotEqual(req1.rsalt, req2.rsalt)
126
    self.assertEqual(req1.protocol, constants.CONFD_PROTOCOL_VERSION)
127
    self.assertEqual(req2.protocol, constants.CONFD_PROTOCOL_VERSION)
128
    self.assertRaises(errors.ConfdClientError, confd.client.ConfdClientRequest,
129
                      type=-33)
130

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

    
148

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

    
172
  def testClientCascadeExpire(self):
173
    req = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
174
    self.client.SendRequest(req)
175
    self.mock_time.increase(constants.CONFD_CLIENT_EXPIRE_TIMEOUT +1)
176
    req2 = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
177
    self.client.SendRequest(req2)
178
    self.assertEquals(self.callback.call_count, 1)
179

    
180
  def testUpdatePeerList(self):
181
    new_peers = ['1.2.3.4', '1.2.3.5']
182
    self.client.UpdatePeerList(new_peers)
183
    self.assertEquals(self.client._peers, new_peers)
184
    req = confd.client.ConfdClientRequest(type=constants.CONFD_REQ_PING)
185
    self.client.SendRequest(req)
186
    self.assertEquals(self.client._socket.send_count, len(new_peers))
187
    self.assert_(self.client._socket.last_address in new_peers)
188

    
189

    
190
if __name__ == '__main__':
191
  testutils.GanetiTestProgram()