4 # Copyright (C) 2010 Google Inc.
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.
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.
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
22 """Script for unittesting the daemon module"""
30 from ganeti import daemon
31 from ganeti import errors
36 class TestMainloop(testutils.GanetiTestCase):
37 """Test daemon.Mainloop"""
40 testutils.GanetiTestCase.setUp(self)
41 self.mainloop = daemon.Mainloop()
42 self.sendsig_events = []
43 self.onsignal_events = []
45 def _CancelEvent(self, handle):
46 self.mainloop.scheduler.cancel(handle)
48 def _SendSig(self, sig):
49 self.sendsig_events.append(sig)
50 os.kill(os.getpid(), sig)
52 def OnSignal(self, signum):
53 self.onsignal_events.append(signum)
55 def testRunAndTermBySched(self):
56 self.mainloop.scheduler.enter(0.1, 1, self._SendSig, [signal.SIGTERM])
57 self.mainloop.Run() # terminates by _SendSig being scheduled
58 self.assertEquals(self.sendsig_events, [signal.SIGTERM])
60 def testTerminatingSignals(self):
61 self.mainloop.scheduler.enter(0.1, 1, self._SendSig, [signal.SIGCHLD])
62 self.mainloop.scheduler.enter(0.2, 1, self._SendSig, [signal.SIGINT])
64 self.assertEquals(self.sendsig_events, [signal.SIGCHLD, signal.SIGINT])
65 self.mainloop.scheduler.enter(0.1, 1, self._SendSig, [signal.SIGTERM])
67 self.assertEquals(self.sendsig_events, [signal.SIGCHLD, signal.SIGINT,
70 def testSchedulerCancel(self):
71 handle = self.mainloop.scheduler.enter(0.1, 1, self._SendSig,
73 self.mainloop.scheduler.cancel(handle)
74 self.mainloop.scheduler.enter(0.2, 1, self._SendSig, [signal.SIGCHLD])
75 self.mainloop.scheduler.enter(0.3, 1, self._SendSig, [signal.SIGTERM])
77 self.assertEquals(self.sendsig_events, [signal.SIGCHLD, signal.SIGTERM])
79 def testRegisterSignal(self):
80 self.mainloop.RegisterSignal(self)
81 self.mainloop.scheduler.enter(0.1, 1, self._SendSig, [signal.SIGCHLD])
82 handle = self.mainloop.scheduler.enter(0.1, 1, self._SendSig,
84 self.mainloop.scheduler.cancel(handle)
85 self.mainloop.scheduler.enter(0.2, 1, self._SendSig, [signal.SIGCHLD])
86 self.mainloop.scheduler.enter(0.3, 1, self._SendSig, [signal.SIGTERM])
87 # ...not delievered because they are scheduled after TERM
88 self.mainloop.scheduler.enter(0.4, 1, self._SendSig, [signal.SIGCHLD])
89 self.mainloop.scheduler.enter(0.5, 1, self._SendSig, [signal.SIGCHLD])
91 self.assertEquals(self.sendsig_events,
92 [signal.SIGCHLD, signal.SIGCHLD, signal.SIGTERM])
93 self.assertEquals(self.onsignal_events, self.sendsig_events)
95 def testDeferredCancel(self):
96 self.mainloop.RegisterSignal(self)
98 self.mainloop.scheduler.enterabs(now + 0.1, 1, self._SendSig,
100 handle1 = self.mainloop.scheduler.enterabs(now + 0.3, 2, self._SendSig,
102 handle2 = self.mainloop.scheduler.enterabs(now + 0.4, 2, self._SendSig,
104 self.mainloop.scheduler.enterabs(now + 0.2, 1, self._CancelEvent,
106 self.mainloop.scheduler.enterabs(now + 0.2, 1, self._CancelEvent,
108 self.mainloop.scheduler.enter(0.5, 1, self._SendSig, [signal.SIGTERM])
110 self.assertEquals(self.sendsig_events, [signal.SIGCHLD, signal.SIGTERM])
111 self.assertEquals(self.onsignal_events, self.sendsig_events)
114 self.mainloop.RegisterSignal(self)
115 self.mainloop.scheduler.enter(0.1, 1, self._SendSig, [signal.SIGCHLD])
116 self.mainloop.scheduler.enter(0.2, 1, self._SendSig, [signal.SIGCHLD])
117 self.mainloop.scheduler.enter(0.3, 1, self._SendSig, [signal.SIGTERM])
118 self.mainloop.scheduler.enter(0.4, 1, self._SendSig, [signal.SIGCHLD])
119 self.mainloop.scheduler.enter(0.5, 1, self._SendSig, [signal.SIGCHLD])
121 self.assertEquals(self.sendsig_events,
122 [signal.SIGCHLD, signal.SIGCHLD, signal.SIGTERM])
123 self.assertEquals(self.onsignal_events, self.sendsig_events)
124 self.mainloop.scheduler.enter(0.3, 1, self._SendSig, [signal.SIGTERM])
126 self.assertEquals(self.sendsig_events,
127 [signal.SIGCHLD, signal.SIGCHLD, signal.SIGTERM,
128 signal.SIGCHLD, signal.SIGCHLD, signal.SIGTERM])
129 self.assertEquals(self.onsignal_events, self.sendsig_events)
131 def testPriority(self):
132 # for events at the same time, the highest priority one executes first
134 self.mainloop.scheduler.enterabs(now + 0.1, 2, self._SendSig,
136 self.mainloop.scheduler.enterabs(now + 0.1, 1, self._SendSig,
139 self.assertEquals(self.sendsig_events, [signal.SIGTERM])
140 self.mainloop.scheduler.enter(0.2, 1, self._SendSig, [signal.SIGTERM])
142 self.assertEquals(self.sendsig_events,
143 [signal.SIGTERM, signal.SIGCHLD, signal.SIGTERM])
146 class _MyAsyncUDPSocket(daemon.AsyncUDPSocket):
149 daemon.AsyncUDPSocket.__init__(self)
153 def handle_datagram(self, payload, ip, port):
154 self.received.append((payload))
155 if payload == "terminate":
156 os.kill(os.getpid(), signal.SIGTERM)
157 elif payload == "error":
158 raise errors.GenericError("error")
160 def handle_error(self):
161 self.error_count += 1
165 class TestAsyncUDPSocket(testutils.GanetiTestCase):
166 """Test daemon.AsyncUDPSocket"""
169 testutils.GanetiTestCase.setUp(self)
170 self.mainloop = daemon.Mainloop()
171 self.server = _MyAsyncUDPSocket()
172 self.client = _MyAsyncUDPSocket()
173 self.server.bind(("127.0.0.1", 0))
174 self.port = self.server.getsockname()[1]
179 testutils.GanetiTestCase.tearDown(self)
181 def testNoDoubleBind(self):
182 self.assertRaises(socket.error, self.client.bind, ("127.0.0.1", self.port))
184 def _ThreadedClient(self, payload):
185 self.client.enqueue_send("127.0.0.1", self.port, payload)
186 print "sending %s" % payload
187 while self.client.writable():
188 self.client.handle_write()
190 def testAsyncClientServer(self):
191 self.client.enqueue_send("127.0.0.1", self.port, "p1")
192 self.client.enqueue_send("127.0.0.1", self.port, "p2")
193 self.client.enqueue_send("127.0.0.1", self.port, "terminate")
195 self.assertEquals(self.server.received, ["p1", "p2", "terminate"])
197 def testSyncClientServer(self):
198 self.client.enqueue_send("127.0.0.1", self.port, "p1")
199 self.client.enqueue_send("127.0.0.1", self.port, "p2")
200 while self.client.writable():
201 self.client.handle_write()
202 self.server.process_next_packet()
203 self.assertEquals(self.server.received, ["p1"])
204 self.server.process_next_packet()
205 self.assertEquals(self.server.received, ["p1", "p2"])
206 self.client.enqueue_send("127.0.0.1", self.port, "p3")
207 while self.client.writable():
208 self.client.handle_write()
209 self.server.process_next_packet()
210 self.assertEquals(self.server.received, ["p1", "p2", "p3"])
212 def testErrorHandling(self):
213 self.client.enqueue_send("127.0.0.1", self.port, "p1")
214 self.client.enqueue_send("127.0.0.1", self.port, "p2")
215 self.client.enqueue_send("127.0.0.1", self.port, "error")
216 self.client.enqueue_send("127.0.0.1", self.port, "p3")
217 self.client.enqueue_send("127.0.0.1", self.port, "error")
218 self.client.enqueue_send("127.0.0.1", self.port, "terminate")
219 self.assertRaises(errors.GenericError, self.mainloop.Run)
220 self.assertEquals(self.server.received,
221 ["p1", "p2", "error"])
222 self.assertEquals(self.server.error_count, 1)
223 self.assertRaises(errors.GenericError, self.mainloop.Run)
224 self.assertEquals(self.server.received,
225 ["p1", "p2", "error", "p3", "error"])
226 self.assertEquals(self.server.error_count, 2)
228 self.assertEquals(self.server.received,
229 ["p1", "p2", "error", "p3", "error", "terminate"])
230 self.assertEquals(self.server.error_count, 2)
233 if __name__ == "__main__":
234 testutils.GanetiTestProgram()