~ahasenack/landscape-client/landscape-client-1.5.5-0ubuntu0.9.04.0

« back to all changes in this revision

Viewing changes to landscape/tests/test_reactor.py

  • Committer: Bazaar Package Importer
  • Author(s): Rick Clark
  • Date: 2008-09-08 16:35:57 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20080908163557-l3ixzj5dxz37wnw2
Tags: 1.0.18-0ubuntu1
New upstream release 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
import thread
 
2
import types
 
3
import time
 
4
 
 
5
from landscape.reactor import Reactor, FakeReactor, TwistedReactor
 
6
 
 
7
from landscape.tests.helpers import LandscapeTest
 
8
 
 
9
 
 
10
class ReactorTest(LandscapeTest):
 
11
 
 
12
    def get_reactor(self):
 
13
        return Reactor()
 
14
 
 
15
    def test_call_later(self):
 
16
        reactor = self.get_reactor()
 
17
        called = []
 
18
        def dummy():
 
19
            called.append("Hello!")
 
20
            reactor.stop()
 
21
        reactor.call_later(0, dummy)
 
22
        reactor.run()
 
23
        self.assertEquals(called, ["Hello!"])
 
24
 
 
25
    def test_call_later_with_args(self):
 
26
        reactor = self.get_reactor()
 
27
        called = []
 
28
        def dummy(a, b=3):
 
29
            called.append((a, b))
 
30
            reactor.stop()
 
31
        reactor.call_later(0, dummy, "a", b="b")
 
32
        reactor.run()
 
33
        self.assertEquals(called, [("a", "b")])
 
34
 
 
35
    def test_call_later_only_calls_once(self):
 
36
        reactor = self.get_reactor()
 
37
        called = []
 
38
        def append():
 
39
            called.append("Hey!")
 
40
            return True
 
41
        reactor.call_later(0, append)
 
42
        reactor.call_later(0.3, reactor.stop)
 
43
        reactor.run()
 
44
        self.assertEquals(len(called), 1)
 
45
 
 
46
    def test_cancel_call(self):
 
47
        reactor = self.get_reactor()
 
48
        called = []
 
49
        id = reactor.call_later(0, called.append, "hi")
 
50
        reactor.cancel_call(id)
 
51
        reactor.call_later(0.3, reactor.stop)
 
52
        reactor.run()
 
53
        self.assertEquals(len(called), 0)
 
54
 
 
55
    def test_call_every(self):
 
56
        reactor = self.get_reactor()
 
57
        called = []
 
58
        reactor.call_every(0.01, called.append, "hi")
 
59
        reactor.call_later(0.5, reactor.stop)
 
60
        reactor.run()
 
61
        self.failUnless(5 < len(called) < 100, len(called))
 
62
 
 
63
    def test_cancel_call_every(self):
 
64
        reactor = self.get_reactor()
 
65
        called = []
 
66
        id = reactor.call_every(0, called.append, "hi")
 
67
        reactor.cancel_call(id)
 
68
        reactor.call_later(0.3, reactor.stop)
 
69
        reactor.run()
 
70
        self.assertEquals(len(called), 0)
 
71
 
 
72
    def test_cancel_call_every_after_first_call(self):
 
73
        reactor = self.get_reactor()
 
74
        called = []
 
75
        def cancel_call():
 
76
            reactor.cancel_call(id)
 
77
            called.append("hi")
 
78
        id = reactor.call_every(0, cancel_call)
 
79
        reactor.call_later(0.1, reactor.stop)
 
80
        reactor.run()
 
81
        self.assertEquals(len(called), 1)
 
82
 
 
83
    def test_cancel_later_called(self):
 
84
        reactor = self.get_reactor()
 
85
        id = reactor.call_later(0, lambda: None)
 
86
        reactor.call_later(0.3, reactor.stop)
 
87
        reactor.run()
 
88
        reactor.cancel_call(id)
 
89
 
 
90
    def test_cancel_call_twice(self):
 
91
        """
 
92
        Multiple cancellations of a call will not raise any exceptions.
 
93
        """
 
94
        reactor = self.get_reactor()
 
95
        id = reactor.call_later(3, lambda: None)
 
96
        reactor.cancel_call(id)
 
97
        reactor.cancel_call(id)
 
98
 
 
99
    def test_reactor_doesnt_leak(self):
 
100
        reactor = self.get_reactor()
 
101
        called = []
 
102
        reactor.call_later(0, called.append, "hi")
 
103
        reactor = self.get_reactor()
 
104
        reactor.call_later(0.01, reactor.stop)
 
105
        reactor.run()
 
106
        self.assertEquals(called, [])
 
107
 
 
108
    def test_event(self):
 
109
        reactor = self.get_reactor()
 
110
        called = []
 
111
        def handle_foobar():
 
112
            called.append(True)
 
113
        reactor.call_on("foobar", handle_foobar)
 
114
        reactor.fire("foobar")
 
115
        self.assertEquals(called, [True])
 
116
 
 
117
    def test_event_with_args(self):
 
118
        reactor = self.get_reactor()
 
119
        called = []
 
120
        def handle_foobar(a, b=3):
 
121
            called.append((a, b))
 
122
 
 
123
        reactor.call_on("foobar", handle_foobar)
 
124
        reactor.fire("foobar", "a", b=6)
 
125
        self.assertEquals(called, [("a", 6)])
 
126
 
 
127
    def test_events(self):
 
128
        reactor = self.get_reactor()
 
129
        called = []
 
130
 
 
131
        reactor.call_on("foobar", called.append)
 
132
        reactor.call_on("foobar", called.append)
 
133
 
 
134
        reactor.fire("foobar", "a")
 
135
        self.assertEquals(called, ["a", "a"])
 
136
 
 
137
    def test_events_result(self):
 
138
        reactor = self.get_reactor()
 
139
 
 
140
        generator = iter([1, 2, 3]).next
 
141
 
 
142
        reactor.call_on("foobar", generator)
 
143
        reactor.call_on("foobar", generator)
 
144
        reactor.call_on("foobar", generator)
 
145
 
 
146
        self.assertEquals(reactor.fire("foobar"), [1, 2, 3])
 
147
 
 
148
    def test_event_priority(self):
 
149
        """
 
150
        Event callbacks should be able to be scheduled with a priority
 
151
        which specifies the order they are run in.
 
152
        """
 
153
        reactor = self.get_reactor()
 
154
        called = []
 
155
        reactor.call_on("foobar", lambda: called.append(5), priority=5)
 
156
        reactor.call_on("foobar", lambda: called.append(3), priority=3)
 
157
        reactor.call_on("foobar", lambda: called.append(4), priority=4)
 
158
        reactor.fire("foobar")
 
159
        self.assertEquals(called, [3, 4, 5])
 
160
 
 
161
    def test_default_priority(self):
 
162
        """
 
163
        The default priority of an event callback should be 0.
 
164
        """
 
165
        reactor = self.get_reactor()
 
166
        called = []
 
167
        reactor.call_on("foobar", lambda: called.append(1), 1)
 
168
        reactor.call_on("foobar", lambda: called.append(0))
 
169
        reactor.call_on("foobar", lambda: called.append(-1), -1)
 
170
        reactor.fire("foobar")
 
171
        self.assertEquals(called, [-1, 0, 1])
 
172
 
 
173
    def test_exploding_event_handler(self):
 
174
        self.log_helper.ignore_errors(ZeroDivisionError)
 
175
        reactor = self.get_reactor()
 
176
        called = []
 
177
        def handle_one(): called.append(1)
 
178
        def handle_two():
 
179
            1/0
 
180
        def handle_three(): called.append(3)
 
181
 
 
182
        reactor.call_on("foobar", handle_one)
 
183
        reactor.call_on("foobar", handle_two)
 
184
        reactor.call_on("foobar", handle_three)
 
185
 
 
186
        reactor.fire("foobar")
 
187
        self.assertTrue(1 in called)
 
188
        self.assertTrue(3 in called)
 
189
        self.assertTrue("handle_two" in self.logfile.getvalue())
 
190
        self.assertTrue("ZeroDivisionError" in self.logfile.getvalue(),
 
191
                        self.logfile.getvalue())
 
192
 
 
193
    def test_weird_event_type(self):
 
194
        #This can be useful for "namespaced" event types
 
195
        reactor = self.get_reactor()
 
196
        called = []
 
197
        reactor.call_on(("message", "foobar"), called.append)
 
198
        reactor.fire(("message", "foobar"), "namespaced!")
 
199
        self.assertEquals(called, ["namespaced!"])
 
200
 
 
201
    def test_nonexistent_event_type(self):
 
202
        reactor = self.get_reactor()
 
203
        reactor.fire("Blat!")
 
204
 
 
205
    def test_cancel_event(self):
 
206
        reactor = self.get_reactor()
 
207
        called = []
 
208
        id = reactor.call_on("foobar", called.append)
 
209
        reactor.cancel_call(id)
 
210
        reactor.fire("foobar")
 
211
        self.assertEquals(called, [])
 
212
 
 
213
    def test_run_stop_events(self):
 
214
        reactor = self.get_reactor()
 
215
 
 
216
        called = []
 
217
        called_copy = []
 
218
 
 
219
        reactor.call_on("run", lambda: called.append("run"))
 
220
        reactor.call_on("stop", lambda: called.append("stop"))
 
221
        reactor.call_later(0.0, lambda: called_copy.extend(called))
 
222
        reactor.call_later(0.5, reactor.stop)
 
223
 
 
224
        reactor.run()
 
225
 
 
226
        self.assertEquals(called, ["run", "stop"])
 
227
        self.assertEquals(called_copy, ["run"])
 
228
 
 
229
    def test_call_in_thread(self):
 
230
        reactor = self.get_reactor()
 
231
 
 
232
        called = []
 
233
 
 
234
        def f(a, b, c):
 
235
            called.append((a, b, c))
 
236
            called.append(thread.get_ident())
 
237
 
 
238
        reactor.call_in_thread(None, None, f, 1, 2, c=3)
 
239
 
 
240
        while not called:
 
241
            pass
 
242
 
 
243
        reactor.call_later(0.7, reactor.stop)
 
244
        reactor.run()
 
245
 
 
246
        self.assertEquals(len(called), 2)
 
247
        self.assertEquals(called[0], (1, 2, 3))
 
248
 
 
249
        if not isinstance(reactor, FakeReactor):
 
250
            self.assertNotEquals(called[1], thread.get_ident())
 
251
 
 
252
    def test_call_in_thread_with_callback(self):
 
253
        reactor = self.get_reactor()
 
254
 
 
255
        called = []
 
256
 
 
257
        def f():
 
258
            called.append("f")
 
259
            return 32
 
260
 
 
261
        def callback(result):
 
262
            called.append("callback")
 
263
            called.append(result)
 
264
 
 
265
        def errback(type, value, traceback):
 
266
            called.append("errback")
 
267
            called.append((type, value, traceback))
 
268
 
 
269
        reactor.call_in_thread(callback, errback, f)
 
270
 
 
271
        while not called:
 
272
            pass
 
273
 
 
274
        reactor.call_later(0.7, reactor.stop)
 
275
        reactor.run()
 
276
 
 
277
        self.assertEquals(called, ["f", "callback", 32])
 
278
 
 
279
    def test_call_in_thread_with_errback(self):
 
280
        reactor = self.get_reactor()
 
281
 
 
282
        called = []
 
283
 
 
284
        def f():
 
285
            called.append("f")
 
286
            1/0
 
287
 
 
288
        def callback(result):
 
289
            called.append("callback")
 
290
            called.append(result)
 
291
 
 
292
        def errback(*args):
 
293
            called.append("errback")
 
294
            called.append(args)
 
295
 
 
296
        reactor.call_in_thread(callback, errback, f)
 
297
 
 
298
        while not called:
 
299
            pass
 
300
 
 
301
        reactor.call_later(0.7, reactor.stop)
 
302
        reactor.run()
 
303
 
 
304
        self.assertEquals(called[:2], ["f", "errback"])
 
305
        self.assertEquals(len(called), 3)
 
306
        self.assertEquals(called[2][0], ZeroDivisionError)
 
307
        self.assertTrue(isinstance(called[2][1], ZeroDivisionError))
 
308
        self.assertTrue(isinstance(called[2][2], types.TracebackType))
 
309
 
 
310
    def test_call_in_thread_with_error_but_no_errback(self):
 
311
        self.log_helper.ignore_errors(ZeroDivisionError)
 
312
        reactor = self.get_reactor()
 
313
 
 
314
        called = []
 
315
 
 
316
        def f():
 
317
            called.append("f")
 
318
            1/0
 
319
 
 
320
        def callback(result):
 
321
            called.append("callback")
 
322
            called.append(result)
 
323
 
 
324
        reactor.call_in_thread(callback, None, f)
 
325
 
 
326
        while not called:
 
327
            pass
 
328
 
 
329
        reactor.call_later(0.7, reactor.stop)
 
330
        reactor.run()
 
331
 
 
332
        self.assertEquals(called, ["f"])
 
333
        self.assertTrue("ZeroDivisionError" in self.logfile.getvalue(),
 
334
                        self.logfile.getvalue())
 
335
 
 
336
    def test_call_in_main(self):
 
337
        reactor = self.get_reactor()
 
338
 
 
339
        called = []
 
340
 
 
341
        def f():
 
342
            called.append("f")
 
343
            called.append(thread.get_ident())
 
344
            reactor.call_in_main(g, 1, 2, c=3)
 
345
 
 
346
        def g(a, b, c):
 
347
            called.append("g")
 
348
            called.append(thread.get_ident())
 
349
 
 
350
        reactor.call_in_thread(None, None, f)
 
351
 
 
352
        while not called:
 
353
            pass
 
354
 
 
355
        reactor.call_later(0.7, reactor.stop)
 
356
        reactor.run()
 
357
 
 
358
        self.assertEquals(len(called), 4)
 
359
        self.assertEquals(called[0], "f")
 
360
        if not isinstance(reactor, FakeReactor):
 
361
            self.assertNotEquals(called[1], thread.get_ident())
 
362
        self.assertEquals(called[2], "g")
 
363
        self.assertEquals(called[3], thread.get_ident())
 
364
 
 
365
 
 
366
class FakeReactorTest(ReactorTest):
 
367
 
 
368
    def get_reactor(self):
 
369
        return FakeReactor()
 
370
 
 
371
    def test_incremental_advance(self):
 
372
        reactor = self.get_reactor()
 
373
 
 
374
        called = []
 
375
        def callback():
 
376
            called.append(True)
 
377
 
 
378
        reactor.call_later(2, callback)
 
379
 
 
380
        self.assertFalse(called)
 
381
        reactor.advance(1)
 
382
        self.assertFalse(called)
 
383
        reactor.advance(1)
 
384
        self.assertTrue(called)
 
385
 
 
386
    def test_time(self):
 
387
        """
 
388
        The time method of FakeReactor should return the current
 
389
        simulated time.
 
390
        """
 
391
        reactor = self.get_reactor()
 
392
        self.assertEquals(reactor.time(), 0)
 
393
        reactor.advance(10.5)
 
394
        self.assertEquals(reactor.time(), 10.5)
 
395
        reactor.advance(3)
 
396
        self.assertEquals(reactor.time(), 13.5)
 
397
 
 
398
 
 
399
class TwistedReactorTest(ReactorTest):
 
400
 
 
401
    def get_reactor(self):
 
402
        return TwistedReactor()
 
403
 
 
404
    def test_real_time(self):
 
405
        reactor = self.get_reactor()
 
406
        self.assertTrue(reactor.time() - time.time() < 3)
 
407
 
 
408
 
 
409
# FIXME This is here because the GObject reactor frequently causes the
 
410
# test suite to segfault.  When it becomes stable this can be removed.
 
411
del ReactorTest