Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.daemon_unittest.py @ e3cc4c69

History | View | Annotate | Download (9.2 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 1118ec44 Guido Trotter
30 1118ec44 Guido Trotter
from ganeti import daemon
31 e3cc4c69 Guido Trotter
from ganeti import errors
32 1118ec44 Guido Trotter
33 1118ec44 Guido Trotter
import testutils
34 1118ec44 Guido Trotter
35 1118ec44 Guido Trotter
36 1118ec44 Guido Trotter
class TestMainloop(testutils.GanetiTestCase):
37 1118ec44 Guido Trotter
  """Test daemon.Mainloop"""
38 1118ec44 Guido Trotter
39 1118ec44 Guido Trotter
  def setUp(self):
40 1118ec44 Guido Trotter
    testutils.GanetiTestCase.setUp(self)
41 1118ec44 Guido Trotter
    self.mainloop = daemon.Mainloop()
42 1118ec44 Guido Trotter
    self.sendsig_events = []
43 1118ec44 Guido Trotter
    self.onsignal_events = []
44 1118ec44 Guido Trotter
45 1118ec44 Guido Trotter
  def _CancelEvent(self, handle):
46 1118ec44 Guido Trotter
    self.mainloop.scheduler.cancel(handle)
47 1118ec44 Guido Trotter
48 1118ec44 Guido Trotter
  def _SendSig(self, sig):
49 1118ec44 Guido Trotter
    self.sendsig_events.append(sig)
50 1118ec44 Guido Trotter
    os.kill(os.getpid(), sig)
51 1118ec44 Guido Trotter
52 1118ec44 Guido Trotter
  def OnSignal(self, signum):
53 1118ec44 Guido Trotter
    self.onsignal_events.append(signum)
54 1118ec44 Guido Trotter
55 1118ec44 Guido Trotter
  def testRunAndTermBySched(self):
56 1118ec44 Guido Trotter
    self.mainloop.scheduler.enter(0.1, 1, self._SendSig, [signal.SIGTERM])
57 1118ec44 Guido Trotter
    self.mainloop.Run() # terminates by _SendSig being scheduled
58 1118ec44 Guido Trotter
    self.assertEquals(self.sendsig_events, [signal.SIGTERM])
59 1118ec44 Guido Trotter
60 f59dce3e Guido Trotter
  def testTerminatingSignals(self):
61 f59dce3e Guido Trotter
    self.mainloop.scheduler.enter(0.1, 1, self._SendSig, [signal.SIGCHLD])
62 f59dce3e Guido Trotter
    self.mainloop.scheduler.enter(0.2, 1, self._SendSig, [signal.SIGINT])
63 f59dce3e Guido Trotter
    self.mainloop.Run()
64 f59dce3e Guido Trotter
    self.assertEquals(self.sendsig_events, [signal.SIGCHLD, signal.SIGINT])
65 f59dce3e Guido Trotter
    self.mainloop.scheduler.enter(0.1, 1, self._SendSig, [signal.SIGTERM])
66 f59dce3e Guido Trotter
    self.mainloop.Run()
67 f59dce3e Guido Trotter
    self.assertEquals(self.sendsig_events, [signal.SIGCHLD, signal.SIGINT,
68 f59dce3e Guido Trotter
                                            signal.SIGTERM])
69 f59dce3e Guido Trotter
70 1118ec44 Guido Trotter
  def testSchedulerCancel(self):
71 1118ec44 Guido Trotter
    handle = self.mainloop.scheduler.enter(0.1, 1, self._SendSig,
72 1118ec44 Guido Trotter
                                           [signal.SIGTERM])
73 1118ec44 Guido Trotter
    self.mainloop.scheduler.cancel(handle)
74 1118ec44 Guido Trotter
    self.mainloop.scheduler.enter(0.2, 1, self._SendSig, [signal.SIGCHLD])
75 1118ec44 Guido Trotter
    self.mainloop.scheduler.enter(0.3, 1, self._SendSig, [signal.SIGTERM])
76 1118ec44 Guido Trotter
    self.mainloop.Run()
77 1118ec44 Guido Trotter
    self.assertEquals(self.sendsig_events, [signal.SIGCHLD, signal.SIGTERM])
78 1118ec44 Guido Trotter
79 1118ec44 Guido Trotter
  def testRegisterSignal(self):
80 1118ec44 Guido Trotter
    self.mainloop.RegisterSignal(self)
81 1118ec44 Guido Trotter
    self.mainloop.scheduler.enter(0.1, 1, self._SendSig, [signal.SIGCHLD])
82 1118ec44 Guido Trotter
    handle = self.mainloop.scheduler.enter(0.1, 1, self._SendSig,
83 1118ec44 Guido Trotter
                                           [signal.SIGTERM])
84 1118ec44 Guido Trotter
    self.mainloop.scheduler.cancel(handle)
85 1118ec44 Guido Trotter
    self.mainloop.scheduler.enter(0.2, 1, self._SendSig, [signal.SIGCHLD])
86 1118ec44 Guido Trotter
    self.mainloop.scheduler.enter(0.3, 1, self._SendSig, [signal.SIGTERM])
87 1118ec44 Guido Trotter
    # ...not delievered because they are scheduled after TERM
88 1118ec44 Guido Trotter
    self.mainloop.scheduler.enter(0.4, 1, self._SendSig, [signal.SIGCHLD])
89 1118ec44 Guido Trotter
    self.mainloop.scheduler.enter(0.5, 1, self._SendSig, [signal.SIGCHLD])
90 1118ec44 Guido Trotter
    self.mainloop.Run()
91 1118ec44 Guido Trotter
    self.assertEquals(self.sendsig_events,
92 1118ec44 Guido Trotter
                      [signal.SIGCHLD, signal.SIGCHLD, signal.SIGTERM])
93 1118ec44 Guido Trotter
    self.assertEquals(self.onsignal_events, self.sendsig_events)
94 1118ec44 Guido Trotter
95 1118ec44 Guido Trotter
  def testDeferredCancel(self):
96 1118ec44 Guido Trotter
    self.mainloop.RegisterSignal(self)
97 19ad29d2 Guido Trotter
    now = time.time()
98 19ad29d2 Guido Trotter
    self.mainloop.scheduler.enterabs(now + 0.1, 1, self._SendSig,
99 19ad29d2 Guido Trotter
                                     [signal.SIGCHLD])
100 19ad29d2 Guido Trotter
    handle1 = self.mainloop.scheduler.enterabs(now + 0.3, 2, self._SendSig,
101 19ad29d2 Guido Trotter
                                               [signal.SIGCHLD])
102 19ad29d2 Guido Trotter
    handle2 = self.mainloop.scheduler.enterabs(now + 0.4, 2, self._SendSig,
103 19ad29d2 Guido Trotter
                                               [signal.SIGCHLD])
104 19ad29d2 Guido Trotter
    self.mainloop.scheduler.enterabs(now + 0.2, 1, self._CancelEvent,
105 19ad29d2 Guido Trotter
                                     [handle1])
106 19ad29d2 Guido Trotter
    self.mainloop.scheduler.enterabs(now + 0.2, 1, self._CancelEvent,
107 19ad29d2 Guido Trotter
                                     [handle2])
108 1118ec44 Guido Trotter
    self.mainloop.scheduler.enter(0.5, 1, self._SendSig, [signal.SIGTERM])
109 1118ec44 Guido Trotter
    self.mainloop.Run()
110 1118ec44 Guido Trotter
    self.assertEquals(self.sendsig_events, [signal.SIGCHLD, signal.SIGTERM])
111 1118ec44 Guido Trotter
    self.assertEquals(self.onsignal_events, self.sendsig_events)
112 1118ec44 Guido Trotter
113 c6987b16 Guido Trotter
  def testReRun(self):
114 c6987b16 Guido Trotter
    self.mainloop.RegisterSignal(self)
115 c6987b16 Guido Trotter
    self.mainloop.scheduler.enter(0.1, 1, self._SendSig, [signal.SIGCHLD])
116 c6987b16 Guido Trotter
    self.mainloop.scheduler.enter(0.2, 1, self._SendSig, [signal.SIGCHLD])
117 c6987b16 Guido Trotter
    self.mainloop.scheduler.enter(0.3, 1, self._SendSig, [signal.SIGTERM])
118 c6987b16 Guido Trotter
    self.mainloop.scheduler.enter(0.4, 1, self._SendSig, [signal.SIGCHLD])
119 c6987b16 Guido Trotter
    self.mainloop.scheduler.enter(0.5, 1, self._SendSig, [signal.SIGCHLD])
120 c6987b16 Guido Trotter
    self.mainloop.Run()
121 c6987b16 Guido Trotter
    self.assertEquals(self.sendsig_events,
122 c6987b16 Guido Trotter
                      [signal.SIGCHLD, signal.SIGCHLD, signal.SIGTERM])
123 c6987b16 Guido Trotter
    self.assertEquals(self.onsignal_events, self.sendsig_events)
124 c6987b16 Guido Trotter
    self.mainloop.scheduler.enter(0.3, 1, self._SendSig, [signal.SIGTERM])
125 c6987b16 Guido Trotter
    self.mainloop.Run()
126 c6987b16 Guido Trotter
    self.assertEquals(self.sendsig_events,
127 c6987b16 Guido Trotter
                      [signal.SIGCHLD, signal.SIGCHLD, signal.SIGTERM,
128 c6987b16 Guido Trotter
                       signal.SIGCHLD, signal.SIGCHLD, signal.SIGTERM])
129 c6987b16 Guido Trotter
    self.assertEquals(self.onsignal_events, self.sendsig_events)
130 c6987b16 Guido Trotter
131 85dbfd78 Guido Trotter
  def testPriority(self):
132 85dbfd78 Guido Trotter
    # for events at the same time, the highest priority one executes first
133 85dbfd78 Guido Trotter
    now = time.time()
134 85dbfd78 Guido Trotter
    self.mainloop.scheduler.enterabs(now + 0.1, 2, self._SendSig,
135 85dbfd78 Guido Trotter
                                     [signal.SIGCHLD])
136 85dbfd78 Guido Trotter
    self.mainloop.scheduler.enterabs(now + 0.1, 1, self._SendSig,
137 85dbfd78 Guido Trotter
                                     [signal.SIGTERM])
138 85dbfd78 Guido Trotter
    self.mainloop.Run()
139 85dbfd78 Guido Trotter
    self.assertEquals(self.sendsig_events, [signal.SIGTERM])
140 85dbfd78 Guido Trotter
    self.mainloop.scheduler.enter(0.2, 1, self._SendSig, [signal.SIGTERM])
141 85dbfd78 Guido Trotter
    self.mainloop.Run()
142 85dbfd78 Guido Trotter
    self.assertEquals(self.sendsig_events,
143 85dbfd78 Guido Trotter
                      [signal.SIGTERM, signal.SIGCHLD, signal.SIGTERM])
144 85dbfd78 Guido Trotter
145 1118ec44 Guido Trotter
146 4db33137 Guido Trotter
class _MyAsyncUDPSocket(daemon.AsyncUDPSocket):
147 4db33137 Guido Trotter
148 4db33137 Guido Trotter
  def __init__(self):
149 4db33137 Guido Trotter
    daemon.AsyncUDPSocket.__init__(self)
150 4db33137 Guido Trotter
    self.received = []
151 4db33137 Guido Trotter
    self.error_count = 0
152 4db33137 Guido Trotter
153 4db33137 Guido Trotter
  def handle_datagram(self, payload, ip, port):
154 4db33137 Guido Trotter
    self.received.append((payload))
155 4db33137 Guido Trotter
    if payload == "terminate":
156 4db33137 Guido Trotter
      os.kill(os.getpid(), signal.SIGTERM)
157 4db33137 Guido Trotter
    elif payload == "error":
158 4db33137 Guido Trotter
      raise errors.GenericError("error")
159 4db33137 Guido Trotter
160 4db33137 Guido Trotter
  def handle_error(self):
161 4db33137 Guido Trotter
    self.error_count += 1
162 e3cc4c69 Guido Trotter
    raise
163 4db33137 Guido Trotter
164 4db33137 Guido Trotter
165 4db33137 Guido Trotter
class TestAsyncUDPSocket(testutils.GanetiTestCase):
166 4db33137 Guido Trotter
  """Test daemon.AsyncUDPSocket"""
167 4db33137 Guido Trotter
168 4db33137 Guido Trotter
  def setUp(self):
169 4db33137 Guido Trotter
    testutils.GanetiTestCase.setUp(self)
170 4db33137 Guido Trotter
    self.mainloop = daemon.Mainloop()
171 4db33137 Guido Trotter
    self.server = _MyAsyncUDPSocket()
172 4db33137 Guido Trotter
    self.client = _MyAsyncUDPSocket()
173 4db33137 Guido Trotter
    self.server.bind(("127.0.0.1", 0))
174 4db33137 Guido Trotter
    self.port = self.server.getsockname()[1]
175 4db33137 Guido Trotter
176 4db33137 Guido Trotter
  def tearDown(self):
177 4db33137 Guido Trotter
    self.server.close()
178 4db33137 Guido Trotter
    self.client.close()
179 4db33137 Guido Trotter
    testutils.GanetiTestCase.tearDown(self)
180 4db33137 Guido Trotter
181 4db33137 Guido Trotter
  def testNoDoubleBind(self):
182 4db33137 Guido Trotter
    self.assertRaises(socket.error, self.client.bind, ("127.0.0.1", self.port))
183 4db33137 Guido Trotter
184 4db33137 Guido Trotter
  def _ThreadedClient(self, payload):
185 4db33137 Guido Trotter
    self.client.enqueue_send("127.0.0.1", self.port, payload)
186 4db33137 Guido Trotter
    print "sending %s" % payload
187 4db33137 Guido Trotter
    while self.client.writable():
188 4db33137 Guido Trotter
      self.client.handle_write()
189 4db33137 Guido Trotter
190 4db33137 Guido Trotter
  def testAsyncClientServer(self):
191 4db33137 Guido Trotter
    self.client.enqueue_send("127.0.0.1", self.port, "p1")
192 4db33137 Guido Trotter
    self.client.enqueue_send("127.0.0.1", self.port, "p2")
193 4db33137 Guido Trotter
    self.client.enqueue_send("127.0.0.1", self.port, "terminate")
194 4db33137 Guido Trotter
    self.mainloop.Run()
195 4db33137 Guido Trotter
    self.assertEquals(self.server.received, ["p1", "p2", "terminate"])
196 4db33137 Guido Trotter
197 4db33137 Guido Trotter
  def testSyncClientServer(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
    while self.client.writable():
201 4db33137 Guido Trotter
      self.client.handle_write()
202 4db33137 Guido Trotter
    self.server.process_next_packet()
203 4db33137 Guido Trotter
    self.assertEquals(self.server.received, ["p1"])
204 4db33137 Guido Trotter
    self.server.process_next_packet()
205 4db33137 Guido Trotter
    self.assertEquals(self.server.received, ["p1", "p2"])
206 4db33137 Guido Trotter
    self.client.enqueue_send("127.0.0.1", self.port, "p3")
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", "p2", "p3"])
211 4db33137 Guido Trotter
212 4db33137 Guido Trotter
  def testErrorHandling(self):
213 4db33137 Guido Trotter
    self.client.enqueue_send("127.0.0.1", self.port, "p1")
214 4db33137 Guido Trotter
    self.client.enqueue_send("127.0.0.1", self.port, "p2")
215 4db33137 Guido Trotter
    self.client.enqueue_send("127.0.0.1", self.port, "error")
216 4db33137 Guido Trotter
    self.client.enqueue_send("127.0.0.1", self.port, "p3")
217 4db33137 Guido Trotter
    self.client.enqueue_send("127.0.0.1", self.port, "error")
218 4db33137 Guido Trotter
    self.client.enqueue_send("127.0.0.1", self.port, "terminate")
219 e3cc4c69 Guido Trotter
    self.assertRaises(errors.GenericError, self.mainloop.Run)
220 e3cc4c69 Guido Trotter
    self.assertEquals(self.server.received,
221 e3cc4c69 Guido Trotter
                      ["p1", "p2", "error"])
222 e3cc4c69 Guido Trotter
    self.assertEquals(self.server.error_count, 1)
223 e3cc4c69 Guido Trotter
    self.assertRaises(errors.GenericError, self.mainloop.Run)
224 e3cc4c69 Guido Trotter
    self.assertEquals(self.server.received,
225 e3cc4c69 Guido Trotter
                      ["p1", "p2", "error", "p3", "error"])
226 e3cc4c69 Guido Trotter
    self.assertEquals(self.server.error_count, 2)
227 4db33137 Guido Trotter
    self.mainloop.Run()
228 4db33137 Guido Trotter
    self.assertEquals(self.server.received,
229 4db33137 Guido Trotter
                      ["p1", "p2", "error", "p3", "error", "terminate"])
230 4db33137 Guido Trotter
    self.assertEquals(self.server.error_count, 2)
231 4db33137 Guido Trotter
232 4db33137 Guido Trotter
233 1118ec44 Guido Trotter
if __name__ == "__main__":
234 1118ec44 Guido Trotter
  testutils.GanetiTestProgram()