Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.daemon_unittest.py @ 18215385

History | View | Annotate | Download (17.8 kB)

1 1118ec44 Guido Trotter
#!/usr/bin/python
2 1118ec44 Guido Trotter
#
3 1118ec44 Guido Trotter
4 1118ec44 Guido Trotter
# Copyright (C) 2010 Google Inc.
5 1118ec44 Guido Trotter
#
6 1118ec44 Guido Trotter
# This program is free software; you can redistribute it and/or modify
7 1118ec44 Guido Trotter
# it under the terms of the GNU General Public License as published by
8 1118ec44 Guido Trotter
# the Free Software Foundation; either version 2 of the License, or
9 1118ec44 Guido Trotter
# (at your option) any later version.
10 1118ec44 Guido Trotter
#
11 1118ec44 Guido Trotter
# This program is distributed in the hope that it will be useful, but
12 1118ec44 Guido Trotter
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 1118ec44 Guido Trotter
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 1118ec44 Guido Trotter
# General Public License for more details.
15 1118ec44 Guido Trotter
#
16 1118ec44 Guido Trotter
# You should have received a copy of the GNU General Public License
17 1118ec44 Guido Trotter
# along with this program; if not, write to the Free Software
18 1118ec44 Guido Trotter
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 1118ec44 Guido Trotter
# 02110-1301, USA.
20 1118ec44 Guido Trotter
21 1118ec44 Guido Trotter
22 1118ec44 Guido Trotter
"""Script for unittesting the daemon module"""
23 1118ec44 Guido Trotter
24 1118ec44 Guido Trotter
import unittest
25 1118ec44 Guido Trotter
import signal
26 1118ec44 Guido Trotter
import os
27 4db33137 Guido Trotter
import socket
28 19ad29d2 Guido Trotter
import time
29 18215385 Guido Trotter
import tempfile
30 18215385 Guido Trotter
import shutil
31 1118ec44 Guido Trotter
32 1118ec44 Guido Trotter
from ganeti import daemon
33 e3cc4c69 Guido Trotter
from ganeti import errors
34 6e7e58b4 Guido Trotter
from ganeti import utils
35 1118ec44 Guido Trotter
36 1118ec44 Guido Trotter
import testutils
37 1118ec44 Guido Trotter
38 1118ec44 Guido Trotter
39 1118ec44 Guido Trotter
class TestMainloop(testutils.GanetiTestCase):
40 1118ec44 Guido Trotter
  """Test daemon.Mainloop"""
41 1118ec44 Guido Trotter
42 1118ec44 Guido Trotter
  def setUp(self):
43 1118ec44 Guido Trotter
    testutils.GanetiTestCase.setUp(self)
44 1118ec44 Guido Trotter
    self.mainloop = daemon.Mainloop()
45 1118ec44 Guido Trotter
    self.sendsig_events = []
46 1118ec44 Guido Trotter
    self.onsignal_events = []
47 1118ec44 Guido Trotter
48 1118ec44 Guido Trotter
  def _CancelEvent(self, handle):
49 1118ec44 Guido Trotter
    self.mainloop.scheduler.cancel(handle)
50 1118ec44 Guido Trotter
51 1118ec44 Guido Trotter
  def _SendSig(self, sig):
52 1118ec44 Guido Trotter
    self.sendsig_events.append(sig)
53 1118ec44 Guido Trotter
    os.kill(os.getpid(), sig)
54 1118ec44 Guido Trotter
55 1118ec44 Guido Trotter
  def OnSignal(self, signum):
56 1118ec44 Guido Trotter
    self.onsignal_events.append(signum)
57 1118ec44 Guido Trotter
58 1118ec44 Guido Trotter
  def testRunAndTermBySched(self):
59 1118ec44 Guido Trotter
    self.mainloop.scheduler.enter(0.1, 1, self._SendSig, [signal.SIGTERM])
60 1118ec44 Guido Trotter
    self.mainloop.Run() # terminates by _SendSig being scheduled
61 1118ec44 Guido Trotter
    self.assertEquals(self.sendsig_events, [signal.SIGTERM])
62 1118ec44 Guido Trotter
63 f59dce3e Guido Trotter
  def testTerminatingSignals(self):
64 f59dce3e Guido Trotter
    self.mainloop.scheduler.enter(0.1, 1, self._SendSig, [signal.SIGCHLD])
65 f59dce3e Guido Trotter
    self.mainloop.scheduler.enter(0.2, 1, self._SendSig, [signal.SIGINT])
66 f59dce3e Guido Trotter
    self.mainloop.Run()
67 f59dce3e Guido Trotter
    self.assertEquals(self.sendsig_events, [signal.SIGCHLD, signal.SIGINT])
68 f59dce3e Guido Trotter
    self.mainloop.scheduler.enter(0.1, 1, self._SendSig, [signal.SIGTERM])
69 f59dce3e Guido Trotter
    self.mainloop.Run()
70 f59dce3e Guido Trotter
    self.assertEquals(self.sendsig_events, [signal.SIGCHLD, signal.SIGINT,
71 f59dce3e Guido Trotter
                                            signal.SIGTERM])
72 f59dce3e Guido Trotter
73 1118ec44 Guido Trotter
  def testSchedulerCancel(self):
74 1118ec44 Guido Trotter
    handle = self.mainloop.scheduler.enter(0.1, 1, self._SendSig,
75 1118ec44 Guido Trotter
                                           [signal.SIGTERM])
76 1118ec44 Guido Trotter
    self.mainloop.scheduler.cancel(handle)
77 1118ec44 Guido Trotter
    self.mainloop.scheduler.enter(0.2, 1, self._SendSig, [signal.SIGCHLD])
78 1118ec44 Guido Trotter
    self.mainloop.scheduler.enter(0.3, 1, self._SendSig, [signal.SIGTERM])
79 1118ec44 Guido Trotter
    self.mainloop.Run()
80 1118ec44 Guido Trotter
    self.assertEquals(self.sendsig_events, [signal.SIGCHLD, signal.SIGTERM])
81 1118ec44 Guido Trotter
82 1118ec44 Guido Trotter
  def testRegisterSignal(self):
83 1118ec44 Guido Trotter
    self.mainloop.RegisterSignal(self)
84 1118ec44 Guido Trotter
    self.mainloop.scheduler.enter(0.1, 1, self._SendSig, [signal.SIGCHLD])
85 1118ec44 Guido Trotter
    handle = self.mainloop.scheduler.enter(0.1, 1, self._SendSig,
86 1118ec44 Guido Trotter
                                           [signal.SIGTERM])
87 1118ec44 Guido Trotter
    self.mainloop.scheduler.cancel(handle)
88 1118ec44 Guido Trotter
    self.mainloop.scheduler.enter(0.2, 1, self._SendSig, [signal.SIGCHLD])
89 1118ec44 Guido Trotter
    self.mainloop.scheduler.enter(0.3, 1, self._SendSig, [signal.SIGTERM])
90 1118ec44 Guido Trotter
    # ...not delievered because they are scheduled after TERM
91 1118ec44 Guido Trotter
    self.mainloop.scheduler.enter(0.4, 1, self._SendSig, [signal.SIGCHLD])
92 1118ec44 Guido Trotter
    self.mainloop.scheduler.enter(0.5, 1, self._SendSig, [signal.SIGCHLD])
93 1118ec44 Guido Trotter
    self.mainloop.Run()
94 1118ec44 Guido Trotter
    self.assertEquals(self.sendsig_events,
95 1118ec44 Guido Trotter
                      [signal.SIGCHLD, signal.SIGCHLD, signal.SIGTERM])
96 1118ec44 Guido Trotter
    self.assertEquals(self.onsignal_events, self.sendsig_events)
97 1118ec44 Guido Trotter
98 1118ec44 Guido Trotter
  def testDeferredCancel(self):
99 1118ec44 Guido Trotter
    self.mainloop.RegisterSignal(self)
100 19ad29d2 Guido Trotter
    now = time.time()
101 19ad29d2 Guido Trotter
    self.mainloop.scheduler.enterabs(now + 0.1, 1, self._SendSig,
102 19ad29d2 Guido Trotter
                                     [signal.SIGCHLD])
103 19ad29d2 Guido Trotter
    handle1 = self.mainloop.scheduler.enterabs(now + 0.3, 2, self._SendSig,
104 19ad29d2 Guido Trotter
                                               [signal.SIGCHLD])
105 19ad29d2 Guido Trotter
    handle2 = self.mainloop.scheduler.enterabs(now + 0.4, 2, self._SendSig,
106 19ad29d2 Guido Trotter
                                               [signal.SIGCHLD])
107 19ad29d2 Guido Trotter
    self.mainloop.scheduler.enterabs(now + 0.2, 1, self._CancelEvent,
108 19ad29d2 Guido Trotter
                                     [handle1])
109 19ad29d2 Guido Trotter
    self.mainloop.scheduler.enterabs(now + 0.2, 1, self._CancelEvent,
110 19ad29d2 Guido Trotter
                                     [handle2])
111 1118ec44 Guido Trotter
    self.mainloop.scheduler.enter(0.5, 1, self._SendSig, [signal.SIGTERM])
112 1118ec44 Guido Trotter
    self.mainloop.Run()
113 1118ec44 Guido Trotter
    self.assertEquals(self.sendsig_events, [signal.SIGCHLD, signal.SIGTERM])
114 1118ec44 Guido Trotter
    self.assertEquals(self.onsignal_events, self.sendsig_events)
115 1118ec44 Guido Trotter
116 c6987b16 Guido Trotter
  def testReRun(self):
117 c6987b16 Guido Trotter
    self.mainloop.RegisterSignal(self)
118 c6987b16 Guido Trotter
    self.mainloop.scheduler.enter(0.1, 1, self._SendSig, [signal.SIGCHLD])
119 c6987b16 Guido Trotter
    self.mainloop.scheduler.enter(0.2, 1, self._SendSig, [signal.SIGCHLD])
120 c6987b16 Guido Trotter
    self.mainloop.scheduler.enter(0.3, 1, self._SendSig, [signal.SIGTERM])
121 c6987b16 Guido Trotter
    self.mainloop.scheduler.enter(0.4, 1, self._SendSig, [signal.SIGCHLD])
122 c6987b16 Guido Trotter
    self.mainloop.scheduler.enter(0.5, 1, self._SendSig, [signal.SIGCHLD])
123 c6987b16 Guido Trotter
    self.mainloop.Run()
124 c6987b16 Guido Trotter
    self.assertEquals(self.sendsig_events,
125 c6987b16 Guido Trotter
                      [signal.SIGCHLD, signal.SIGCHLD, signal.SIGTERM])
126 c6987b16 Guido Trotter
    self.assertEquals(self.onsignal_events, self.sendsig_events)
127 c6987b16 Guido Trotter
    self.mainloop.scheduler.enter(0.3, 1, self._SendSig, [signal.SIGTERM])
128 c6987b16 Guido Trotter
    self.mainloop.Run()
129 c6987b16 Guido Trotter
    self.assertEquals(self.sendsig_events,
130 c6987b16 Guido Trotter
                      [signal.SIGCHLD, signal.SIGCHLD, signal.SIGTERM,
131 c6987b16 Guido Trotter
                       signal.SIGCHLD, signal.SIGCHLD, signal.SIGTERM])
132 c6987b16 Guido Trotter
    self.assertEquals(self.onsignal_events, self.sendsig_events)
133 c6987b16 Guido Trotter
134 85dbfd78 Guido Trotter
  def testPriority(self):
135 85dbfd78 Guido Trotter
    # for events at the same time, the highest priority one executes first
136 85dbfd78 Guido Trotter
    now = time.time()
137 85dbfd78 Guido Trotter
    self.mainloop.scheduler.enterabs(now + 0.1, 2, self._SendSig,
138 85dbfd78 Guido Trotter
                                     [signal.SIGCHLD])
139 85dbfd78 Guido Trotter
    self.mainloop.scheduler.enterabs(now + 0.1, 1, self._SendSig,
140 85dbfd78 Guido Trotter
                                     [signal.SIGTERM])
141 85dbfd78 Guido Trotter
    self.mainloop.Run()
142 85dbfd78 Guido Trotter
    self.assertEquals(self.sendsig_events, [signal.SIGTERM])
143 85dbfd78 Guido Trotter
    self.mainloop.scheduler.enter(0.2, 1, self._SendSig, [signal.SIGTERM])
144 85dbfd78 Guido Trotter
    self.mainloop.Run()
145 85dbfd78 Guido Trotter
    self.assertEquals(self.sendsig_events,
146 85dbfd78 Guido Trotter
                      [signal.SIGTERM, signal.SIGCHLD, signal.SIGTERM])
147 85dbfd78 Guido Trotter
148 1118ec44 Guido Trotter
149 4db33137 Guido Trotter
class _MyAsyncUDPSocket(daemon.AsyncUDPSocket):
150 4db33137 Guido Trotter
151 4db33137 Guido Trotter
  def __init__(self):
152 4db33137 Guido Trotter
    daemon.AsyncUDPSocket.__init__(self)
153 4db33137 Guido Trotter
    self.received = []
154 4db33137 Guido Trotter
    self.error_count = 0
155 4db33137 Guido Trotter
156 4db33137 Guido Trotter
  def handle_datagram(self, payload, ip, port):
157 4db33137 Guido Trotter
    self.received.append((payload))
158 4db33137 Guido Trotter
    if payload == "terminate":
159 4db33137 Guido Trotter
      os.kill(os.getpid(), signal.SIGTERM)
160 4db33137 Guido Trotter
    elif payload == "error":
161 4db33137 Guido Trotter
      raise errors.GenericError("error")
162 4db33137 Guido Trotter
163 4db33137 Guido Trotter
  def handle_error(self):
164 4db33137 Guido Trotter
    self.error_count += 1
165 e3cc4c69 Guido Trotter
    raise
166 4db33137 Guido Trotter
167 4db33137 Guido Trotter
168 4db33137 Guido Trotter
class TestAsyncUDPSocket(testutils.GanetiTestCase):
169 4db33137 Guido Trotter
  """Test daemon.AsyncUDPSocket"""
170 4db33137 Guido Trotter
171 4db33137 Guido Trotter
  def setUp(self):
172 4db33137 Guido Trotter
    testutils.GanetiTestCase.setUp(self)
173 4db33137 Guido Trotter
    self.mainloop = daemon.Mainloop()
174 4db33137 Guido Trotter
    self.server = _MyAsyncUDPSocket()
175 4db33137 Guido Trotter
    self.client = _MyAsyncUDPSocket()
176 4db33137 Guido Trotter
    self.server.bind(("127.0.0.1", 0))
177 4db33137 Guido Trotter
    self.port = self.server.getsockname()[1]
178 6e7e58b4 Guido Trotter
    # Save utils.IgnoreSignals so we can do evil things to it...
179 6e7e58b4 Guido Trotter
    self.saved_utils_ignoresignals = utils.IgnoreSignals
180 4db33137 Guido Trotter
181 4db33137 Guido Trotter
  def tearDown(self):
182 4db33137 Guido Trotter
    self.server.close()
183 4db33137 Guido Trotter
    self.client.close()
184 6e7e58b4 Guido Trotter
    # ...and restore it as well
185 6e7e58b4 Guido Trotter
    utils.IgnoreSignals = self.saved_utils_ignoresignals
186 4db33137 Guido Trotter
    testutils.GanetiTestCase.tearDown(self)
187 4db33137 Guido Trotter
188 4db33137 Guido Trotter
  def testNoDoubleBind(self):
189 4db33137 Guido Trotter
    self.assertRaises(socket.error, self.client.bind, ("127.0.0.1", self.port))
190 4db33137 Guido Trotter
191 4db33137 Guido Trotter
  def _ThreadedClient(self, payload):
192 4db33137 Guido Trotter
    self.client.enqueue_send("127.0.0.1", self.port, payload)
193 4db33137 Guido Trotter
    print "sending %s" % payload
194 4db33137 Guido Trotter
    while self.client.writable():
195 4db33137 Guido Trotter
      self.client.handle_write()
196 4db33137 Guido Trotter
197 4db33137 Guido Trotter
  def testAsyncClientServer(self):
198 4db33137 Guido Trotter
    self.client.enqueue_send("127.0.0.1", self.port, "p1")
199 4db33137 Guido Trotter
    self.client.enqueue_send("127.0.0.1", self.port, "p2")
200 4db33137 Guido Trotter
    self.client.enqueue_send("127.0.0.1", self.port, "terminate")
201 4db33137 Guido Trotter
    self.mainloop.Run()
202 4db33137 Guido Trotter
    self.assertEquals(self.server.received, ["p1", "p2", "terminate"])
203 4db33137 Guido Trotter
204 4db33137 Guido Trotter
  def testSyncClientServer(self):
205 4db33137 Guido Trotter
    self.client.enqueue_send("127.0.0.1", self.port, "p1")
206 4db33137 Guido Trotter
    self.client.enqueue_send("127.0.0.1", self.port, "p2")
207 4db33137 Guido Trotter
    while self.client.writable():
208 4db33137 Guido Trotter
      self.client.handle_write()
209 4db33137 Guido Trotter
    self.server.process_next_packet()
210 4db33137 Guido Trotter
    self.assertEquals(self.server.received, ["p1"])
211 4db33137 Guido Trotter
    self.server.process_next_packet()
212 4db33137 Guido Trotter
    self.assertEquals(self.server.received, ["p1", "p2"])
213 4db33137 Guido Trotter
    self.client.enqueue_send("127.0.0.1", self.port, "p3")
214 4db33137 Guido Trotter
    while self.client.writable():
215 4db33137 Guido Trotter
      self.client.handle_write()
216 4db33137 Guido Trotter
    self.server.process_next_packet()
217 4db33137 Guido Trotter
    self.assertEquals(self.server.received, ["p1", "p2", "p3"])
218 4db33137 Guido Trotter
219 4db33137 Guido Trotter
  def testErrorHandling(self):
220 4db33137 Guido Trotter
    self.client.enqueue_send("127.0.0.1", self.port, "p1")
221 4db33137 Guido Trotter
    self.client.enqueue_send("127.0.0.1", self.port, "p2")
222 4db33137 Guido Trotter
    self.client.enqueue_send("127.0.0.1", self.port, "error")
223 4db33137 Guido Trotter
    self.client.enqueue_send("127.0.0.1", self.port, "p3")
224 4db33137 Guido Trotter
    self.client.enqueue_send("127.0.0.1", self.port, "error")
225 4db33137 Guido Trotter
    self.client.enqueue_send("127.0.0.1", self.port, "terminate")
226 e3cc4c69 Guido Trotter
    self.assertRaises(errors.GenericError, self.mainloop.Run)
227 e3cc4c69 Guido Trotter
    self.assertEquals(self.server.received,
228 e3cc4c69 Guido Trotter
                      ["p1", "p2", "error"])
229 e3cc4c69 Guido Trotter
    self.assertEquals(self.server.error_count, 1)
230 e3cc4c69 Guido Trotter
    self.assertRaises(errors.GenericError, self.mainloop.Run)
231 e3cc4c69 Guido Trotter
    self.assertEquals(self.server.received,
232 e3cc4c69 Guido Trotter
                      ["p1", "p2", "error", "p3", "error"])
233 e3cc4c69 Guido Trotter
    self.assertEquals(self.server.error_count, 2)
234 4db33137 Guido Trotter
    self.mainloop.Run()
235 4db33137 Guido Trotter
    self.assertEquals(self.server.received,
236 4db33137 Guido Trotter
                      ["p1", "p2", "error", "p3", "error", "terminate"])
237 4db33137 Guido Trotter
    self.assertEquals(self.server.error_count, 2)
238 4db33137 Guido Trotter
239 6e7e58b4 Guido Trotter
  def testSignaledWhileReceiving(self):
240 6e7e58b4 Guido Trotter
    utils.IgnoreSignals = lambda fn, *args, **kwargs: None
241 6e7e58b4 Guido Trotter
    self.client.enqueue_send("127.0.0.1", self.port, "p1")
242 6e7e58b4 Guido Trotter
    self.client.enqueue_send("127.0.0.1", self.port, "p2")
243 6e7e58b4 Guido Trotter
    self.server.handle_read()
244 6e7e58b4 Guido Trotter
    self.assertEquals(self.server.received, [])
245 6e7e58b4 Guido Trotter
    self.client.enqueue_send("127.0.0.1", self.port, "terminate")
246 6e7e58b4 Guido Trotter
    utils.IgnoreSignals = self.saved_utils_ignoresignals
247 6e7e58b4 Guido Trotter
    self.mainloop.Run()
248 6e7e58b4 Guido Trotter
    self.assertEquals(self.server.received, ["p1", "p2", "terminate"])
249 6e7e58b4 Guido Trotter
250 4db33137 Guido Trotter
251 18215385 Guido Trotter
class _MyAsyncStreamServer(daemon.AsyncStreamServer):
252 18215385 Guido Trotter
253 18215385 Guido Trotter
  def __init__(self, family, address, handle_connection_fn):
254 18215385 Guido Trotter
    daemon.AsyncStreamServer.__init__(self, family, address)
255 18215385 Guido Trotter
    self.handle_connection_fn = handle_connection_fn
256 18215385 Guido Trotter
    self.error_count = 0
257 18215385 Guido Trotter
    self.expt_count = 0
258 18215385 Guido Trotter
259 18215385 Guido Trotter
  def handle_connection(self, connected_socket, client_address):
260 18215385 Guido Trotter
    self.handle_connection_fn(connected_socket, client_address)
261 18215385 Guido Trotter
262 18215385 Guido Trotter
  def handle_error(self):
263 18215385 Guido Trotter
    self.error_count += 1
264 18215385 Guido Trotter
    self.close()
265 18215385 Guido Trotter
    raise
266 18215385 Guido Trotter
267 18215385 Guido Trotter
  def handle_expt(self):
268 18215385 Guido Trotter
    self.expt_count += 1
269 18215385 Guido Trotter
    self.close()
270 18215385 Guido Trotter
271 18215385 Guido Trotter
272 18215385 Guido Trotter
class _MyMessageStreamHandler(daemon.AsyncTerminatedMessageStream):
273 18215385 Guido Trotter
274 18215385 Guido Trotter
  def __init__(self, connected_socket, client_address, terminator, family,
275 18215385 Guido Trotter
               message_fn, client_id):
276 18215385 Guido Trotter
    daemon.AsyncTerminatedMessageStream.__init__(self, connected_socket,
277 18215385 Guido Trotter
                                                 client_address,
278 18215385 Guido Trotter
                                                 terminator, family)
279 18215385 Guido Trotter
    self.message_fn = message_fn
280 18215385 Guido Trotter
    self.client_id = client_id
281 18215385 Guido Trotter
    self.error_count = 0
282 18215385 Guido Trotter
283 18215385 Guido Trotter
  def handle_message(self, message, message_id):
284 18215385 Guido Trotter
    self.message_fn(self, message, message_id)
285 18215385 Guido Trotter
286 18215385 Guido Trotter
  def handle_error(self):
287 18215385 Guido Trotter
    self.error_count += 1
288 18215385 Guido Trotter
    raise
289 18215385 Guido Trotter
290 18215385 Guido Trotter
291 18215385 Guido Trotter
class TestAsyncStreamServerTCP(testutils.GanetiTestCase):
292 18215385 Guido Trotter
  """Test daemon.AsyncStreamServer with a TCP connection"""
293 18215385 Guido Trotter
294 18215385 Guido Trotter
  family = socket.AF_INET
295 18215385 Guido Trotter
296 18215385 Guido Trotter
  def setUp(self):
297 18215385 Guido Trotter
    testutils.GanetiTestCase.setUp(self)
298 18215385 Guido Trotter
    self.mainloop = daemon.Mainloop()
299 18215385 Guido Trotter
    self.address = self.getAddress()
300 18215385 Guido Trotter
    self.server = _MyAsyncStreamServer(self.family, self.address,
301 18215385 Guido Trotter
                                       self.handle_connection)
302 18215385 Guido Trotter
    self.client_handler = _MyMessageStreamHandler
303 18215385 Guido Trotter
    self.terminator = "\3"
304 18215385 Guido Trotter
    self.address = self.server.getsockname()
305 18215385 Guido Trotter
    self.clients = []
306 18215385 Guido Trotter
    self.connections = []
307 18215385 Guido Trotter
    self.messages = {}
308 18215385 Guido Trotter
    self.connect_terminate_count = 0
309 18215385 Guido Trotter
    self.message_terminate_count = 0
310 18215385 Guido Trotter
    self.next_client_id = 0
311 18215385 Guido Trotter
    # Save utils.IgnoreSignals so we can do evil things to it...
312 18215385 Guido Trotter
    self.saved_utils_ignoresignals = utils.IgnoreSignals
313 18215385 Guido Trotter
314 18215385 Guido Trotter
  def tearDown(self):
315 18215385 Guido Trotter
    for c in self.clients:
316 18215385 Guido Trotter
      c.close()
317 18215385 Guido Trotter
    for c in self.connections:
318 18215385 Guido Trotter
      c.close()
319 18215385 Guido Trotter
    self.server.close()
320 18215385 Guido Trotter
    # ...and restore it as well
321 18215385 Guido Trotter
    utils.IgnoreSignals = self.saved_utils_ignoresignals
322 18215385 Guido Trotter
    testutils.GanetiTestCase.tearDown(self)
323 18215385 Guido Trotter
324 18215385 Guido Trotter
  def getAddress(self):
325 18215385 Guido Trotter
    return ("127.0.0.1", 0)
326 18215385 Guido Trotter
327 18215385 Guido Trotter
  def countTerminate(self, name):
328 18215385 Guido Trotter
    value = getattr(self, name)
329 18215385 Guido Trotter
    if value is not None:
330 18215385 Guido Trotter
      value -= 1
331 18215385 Guido Trotter
      setattr(self, name, value)
332 18215385 Guido Trotter
      if value <= 0:
333 18215385 Guido Trotter
        os.kill(os.getpid(), signal.SIGTERM)
334 18215385 Guido Trotter
335 18215385 Guido Trotter
  def handle_connection(self, connected_socket, client_address):
336 18215385 Guido Trotter
    client_id = self.next_client_id
337 18215385 Guido Trotter
    self.next_client_id += 1
338 18215385 Guido Trotter
    client_handler = self.client_handler(connected_socket, client_address,
339 18215385 Guido Trotter
                                         self.terminator, self.family,
340 18215385 Guido Trotter
                                         self.handle_message,
341 18215385 Guido Trotter
                                         client_id)
342 18215385 Guido Trotter
    self.connections.append(client_handler)
343 18215385 Guido Trotter
    self.countTerminate("connect_terminate_count")
344 18215385 Guido Trotter
345 18215385 Guido Trotter
  def handle_message(self, handler, message, message_id):
346 18215385 Guido Trotter
    self.messages.setdefault(handler.client_id, [])
347 18215385 Guido Trotter
    # We should just check that the message_ids are monotonically increasing.
348 18215385 Guido Trotter
    # If in the unit tests we never remove messages from the received queue,
349 18215385 Guido Trotter
    # though, we can just require that the queue length is the same as the
350 18215385 Guido Trotter
    # message id, before pushing the message to it. This forces a more
351 18215385 Guido Trotter
    # restrictive check, but we can live with this for now.
352 18215385 Guido Trotter
    self.assertEquals(len(self.messages[handler.client_id]), message_id)
353 18215385 Guido Trotter
    self.messages[handler.client_id].append(message)
354 18215385 Guido Trotter
    if message == "error":
355 18215385 Guido Trotter
      raise errors.GenericError("error")
356 18215385 Guido Trotter
    self.countTerminate("message_terminate_count")
357 18215385 Guido Trotter
358 18215385 Guido Trotter
  def getClient(self):
359 18215385 Guido Trotter
    client = socket.socket(self.family, socket.SOCK_STREAM)
360 18215385 Guido Trotter
    client.connect(self.address)
361 18215385 Guido Trotter
    self.clients.append(client)
362 18215385 Guido Trotter
    return client
363 18215385 Guido Trotter
364 18215385 Guido Trotter
  def tearDown(self):
365 18215385 Guido Trotter
    testutils.GanetiTestCase.tearDown(self)
366 18215385 Guido Trotter
    self.server.close()
367 18215385 Guido Trotter
368 18215385 Guido Trotter
  def testConnect(self):
369 18215385 Guido Trotter
    self.getClient()
370 18215385 Guido Trotter
    self.mainloop.Run()
371 18215385 Guido Trotter
    self.assertEquals(len(self.connections), 1)
372 18215385 Guido Trotter
    self.getClient()
373 18215385 Guido Trotter
    self.mainloop.Run()
374 18215385 Guido Trotter
    self.assertEquals(len(self.connections), 2)
375 18215385 Guido Trotter
    self.connect_terminate_count = 4
376 18215385 Guido Trotter
    self.getClient()
377 18215385 Guido Trotter
    self.getClient()
378 18215385 Guido Trotter
    self.getClient()
379 18215385 Guido Trotter
    self.getClient()
380 18215385 Guido Trotter
    self.mainloop.Run()
381 18215385 Guido Trotter
    self.assertEquals(len(self.connections), 6)
382 18215385 Guido Trotter
383 18215385 Guido Trotter
  def testBasicMessage(self):
384 18215385 Guido Trotter
    self.connect_terminate_count = None
385 18215385 Guido Trotter
    client = self.getClient()
386 18215385 Guido Trotter
    client.send("ciao\3")
387 18215385 Guido Trotter
    self.mainloop.Run()
388 18215385 Guido Trotter
    self.assertEquals(len(self.connections), 1)
389 18215385 Guido Trotter
    self.assertEquals(len(self.messages[0]), 1)
390 18215385 Guido Trotter
    self.assertEquals(self.messages[0][0], "ciao")
391 18215385 Guido Trotter
392 18215385 Guido Trotter
  def testDoubleMessage(self):
393 18215385 Guido Trotter
    self.connect_terminate_count = None
394 18215385 Guido Trotter
    client = self.getClient()
395 18215385 Guido Trotter
    client.send("ciao\3")
396 18215385 Guido Trotter
    self.mainloop.Run()
397 18215385 Guido Trotter
    client.send("foobar\3")
398 18215385 Guido Trotter
    self.mainloop.Run()
399 18215385 Guido Trotter
    self.assertEquals(len(self.connections), 1)
400 18215385 Guido Trotter
    self.assertEquals(len(self.messages[0]), 2)
401 18215385 Guido Trotter
    self.assertEquals(self.messages[0][1], "foobar")
402 18215385 Guido Trotter
403 18215385 Guido Trotter
  def testComposedMessage(self):
404 18215385 Guido Trotter
    self.connect_terminate_count = None
405 18215385 Guido Trotter
    self.message_terminate_count = 3
406 18215385 Guido Trotter
    client = self.getClient()
407 18215385 Guido Trotter
    client.send("one\3composed\3message\3")
408 18215385 Guido Trotter
    self.mainloop.Run()
409 18215385 Guido Trotter
    self.assertEquals(len(self.messages[0]), 3)
410 18215385 Guido Trotter
    self.assertEquals(self.messages[0], ["one", "composed", "message"])
411 18215385 Guido Trotter
412 18215385 Guido Trotter
  def testLongTerminator(self):
413 18215385 Guido Trotter
    self.terminator = "\0\1\2"
414 18215385 Guido Trotter
    self.connect_terminate_count = None
415 18215385 Guido Trotter
    self.message_terminate_count = 3
416 18215385 Guido Trotter
    client = self.getClient()
417 18215385 Guido Trotter
    client.send("one\0\1\2composed\0\1\2message\0\1\2")
418 18215385 Guido Trotter
    self.mainloop.Run()
419 18215385 Guido Trotter
    self.assertEquals(len(self.messages[0]), 3)
420 18215385 Guido Trotter
    self.assertEquals(self.messages[0], ["one", "composed", "message"])
421 18215385 Guido Trotter
422 18215385 Guido Trotter
  def testErrorHandling(self):
423 18215385 Guido Trotter
    self.connect_terminate_count = None
424 18215385 Guido Trotter
    self.message_terminate_count = None
425 18215385 Guido Trotter
    client = self.getClient()
426 18215385 Guido Trotter
    client.send("one\3two\3error\3three\3")
427 18215385 Guido Trotter
    self.assertRaises(errors.GenericError, self.mainloop.Run)
428 18215385 Guido Trotter
    self.assertEquals(self.connections[0].error_count, 1)
429 18215385 Guido Trotter
    self.assertEquals(self.messages[0], ["one", "two", "error"])
430 18215385 Guido Trotter
    client.send("error\3")
431 18215385 Guido Trotter
    self.assertRaises(errors.GenericError, self.mainloop.Run)
432 18215385 Guido Trotter
    self.assertEquals(self.connections[0].error_count, 2)
433 18215385 Guido Trotter
    self.assertEquals(self.messages[0], ["one", "two", "error", "three",
434 18215385 Guido Trotter
                                         "error"])
435 18215385 Guido Trotter
436 18215385 Guido Trotter
  def testDoubleClient(self):
437 18215385 Guido Trotter
    self.connect_terminate_count = None
438 18215385 Guido Trotter
    self.message_terminate_count = 2
439 18215385 Guido Trotter
    client1 = self.getClient()
440 18215385 Guido Trotter
    client2 = self.getClient()
441 18215385 Guido Trotter
    client1.send("c1m1\3")
442 18215385 Guido Trotter
    client2.send("c2m1\3")
443 18215385 Guido Trotter
    self.mainloop.Run()
444 18215385 Guido Trotter
    self.assertEquals(self.messages[0], ["c1m1"])
445 18215385 Guido Trotter
    self.assertEquals(self.messages[1], ["c2m1"])
446 18215385 Guido Trotter
447 18215385 Guido Trotter
  def testUnterminatedMessage(self):
448 18215385 Guido Trotter
    self.connect_terminate_count = None
449 18215385 Guido Trotter
    self.message_terminate_count = 3
450 18215385 Guido Trotter
    client1 = self.getClient()
451 18215385 Guido Trotter
    client2 = self.getClient()
452 18215385 Guido Trotter
    client1.send("message\3unterminated")
453 18215385 Guido Trotter
    client2.send("c2m1\3c2m2\3")
454 18215385 Guido Trotter
    self.mainloop.Run()
455 18215385 Guido Trotter
    self.assertEquals(self.messages[0], ["message"])
456 18215385 Guido Trotter
    self.assertEquals(self.messages[1], ["c2m1", "c2m2"])
457 18215385 Guido Trotter
    client1.send("message\3")
458 18215385 Guido Trotter
    self.mainloop.Run()
459 18215385 Guido Trotter
    self.assertEquals(self.messages[0], ["message", "unterminatedmessage"])
460 18215385 Guido Trotter
461 18215385 Guido Trotter
  def testSignaledWhileAccepting(self):
462 18215385 Guido Trotter
    utils.IgnoreSignals = lambda fn, *args, **kwargs: None
463 18215385 Guido Trotter
    client1 = self.getClient()
464 18215385 Guido Trotter
    self.server.handle_accept()
465 18215385 Guido Trotter
    # When interrupted while accepting we don't have a connection, but we
466 18215385 Guido Trotter
    # didn't crash either.
467 18215385 Guido Trotter
    self.assertEquals(len(self.connections), 0)
468 18215385 Guido Trotter
    utils.IgnoreSignals = self.saved_utils_ignoresignals
469 18215385 Guido Trotter
    self.mainloop.Run()
470 18215385 Guido Trotter
    self.assertEquals(len(self.connections), 1)
471 18215385 Guido Trotter
472 18215385 Guido Trotter
473 18215385 Guido Trotter
class TestAsyncStreamServerUnixPath(TestAsyncStreamServerTCP):
474 18215385 Guido Trotter
  """Test daemon.AsyncStreamServer with a Unix path connection"""
475 18215385 Guido Trotter
476 18215385 Guido Trotter
  family = socket.AF_UNIX
477 18215385 Guido Trotter
478 18215385 Guido Trotter
  def getAddress(self):
479 18215385 Guido Trotter
    self.tmpdir = tempfile.mkdtemp()
480 18215385 Guido Trotter
    return os.path.join(self.tmpdir, "server.sock")
481 18215385 Guido Trotter
482 18215385 Guido Trotter
  def tearDown(self):
483 18215385 Guido Trotter
    shutil.rmtree(self.tmpdir)
484 18215385 Guido Trotter
    TestAsyncStreamServerTCP.tearDown(self)
485 18215385 Guido Trotter
486 18215385 Guido Trotter
487 1118ec44 Guido Trotter
if __name__ == "__main__":
488 1118ec44 Guido Trotter
  testutils.GanetiTestProgram()