~justin-fathomdb/nova/justinsb-openstack-api-volumes

« back to all changes in this revision

Viewing changes to vendor/Twisted-10.0.0/twisted/test/test_defer.py

  • Committer: Jesse Andrews
  • Date: 2010-05-28 06:05:26 UTC
  • Revision ID: git-v1:bf6e6e718cdc7488e2da87b21e258ccc065fe499
initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
# Copyright (c) 2001-2007 Twisted Matrix Laboratories.
 
3
# See LICENSE for details.
 
4
 
 
5
 
 
6
"""
 
7
Test cases for defer module.
 
8
"""
 
9
 
 
10
import gc
 
11
 
 
12
from twisted.trial import unittest, util
 
13
from twisted.internet import reactor, defer
 
14
from twisted.python import failure, log
 
15
 
 
16
from twisted.internet.task import Clock
 
17
 
 
18
class GenericError(Exception):
 
19
    pass
 
20
 
 
21
 
 
22
_setTimeoutSuppression = util.suppress(
 
23
    message="Deferred.setTimeout is deprecated.  Look for timeout "
 
24
            "support specific to the API you are using instead.",
 
25
    category=DeprecationWarning)
 
26
 
 
27
 
 
28
class DeferredTestCase(unittest.TestCase):
 
29
 
 
30
    def setUp(self):
 
31
        self.callback_results = None
 
32
        self.errback_results = None
 
33
        self.callback2_results = None
 
34
 
 
35
    def _callback(self, *args, **kw):
 
36
        self.callback_results = args, kw
 
37
        return args[0]
 
38
 
 
39
    def _callback2(self, *args, **kw):
 
40
        self.callback2_results = args, kw
 
41
 
 
42
    def _errback(self, *args, **kw):
 
43
        self.errback_results = args, kw
 
44
 
 
45
    def testCallbackWithoutArgs(self):
 
46
        deferred = defer.Deferred()
 
47
        deferred.addCallback(self._callback)
 
48
        deferred.callback("hello")
 
49
        self.failUnlessEqual(self.errback_results, None)
 
50
        self.failUnlessEqual(self.callback_results, (('hello',), {}))
 
51
 
 
52
    def testCallbackWithArgs(self):
 
53
        deferred = defer.Deferred()
 
54
        deferred.addCallback(self._callback, "world")
 
55
        deferred.callback("hello")
 
56
        self.failUnlessEqual(self.errback_results, None)
 
57
        self.failUnlessEqual(self.callback_results, (('hello', 'world'), {}))
 
58
 
 
59
    def testCallbackWithKwArgs(self):
 
60
        deferred = defer.Deferred()
 
61
        deferred.addCallback(self._callback, world="world")
 
62
        deferred.callback("hello")
 
63
        self.failUnlessEqual(self.errback_results, None)
 
64
        self.failUnlessEqual(self.callback_results,
 
65
                             (('hello',), {'world': 'world'}))
 
66
 
 
67
    def testTwoCallbacks(self):
 
68
        deferred = defer.Deferred()
 
69
        deferred.addCallback(self._callback)
 
70
        deferred.addCallback(self._callback2)
 
71
        deferred.callback("hello")
 
72
        self.failUnlessEqual(self.errback_results, None)
 
73
        self.failUnlessEqual(self.callback_results,
 
74
                             (('hello',), {}))
 
75
        self.failUnlessEqual(self.callback2_results,
 
76
                             (('hello',), {}))
 
77
 
 
78
    def testDeferredList(self):
 
79
        defr1 = defer.Deferred()
 
80
        defr2 = defer.Deferred()
 
81
        defr3 = defer.Deferred()
 
82
        dl = defer.DeferredList([defr1, defr2, defr3])
 
83
        result = []
 
84
        def cb(resultList, result=result):
 
85
            result.extend(resultList)
 
86
        def catch(err):
 
87
            return None
 
88
        dl.addCallbacks(cb, cb)
 
89
        defr1.callback("1")
 
90
        defr2.addErrback(catch)
 
91
        # "catch" is added to eat the GenericError that will be passed on by
 
92
        # the DeferredList's callback on defr2. If left unhandled, the
 
93
        # Failure object would cause a log.err() warning about "Unhandled
 
94
        # error in Deferred". Twisted's pyunit watches for log.err calls and
 
95
        # treats them as failures. So "catch" must eat the error to prevent
 
96
        # it from flunking the test.
 
97
        defr2.errback(GenericError("2"))
 
98
        defr3.callback("3")
 
99
        self.failUnlessEqual([result[0],
 
100
                    #result[1][1] is now a Failure instead of an Exception
 
101
                              (result[1][0], str(result[1][1].value)),
 
102
                              result[2]],
 
103
 
 
104
                             [(defer.SUCCESS, "1"),
 
105
                              (defer.FAILURE, "2"),
 
106
                              (defer.SUCCESS, "3")])
 
107
 
 
108
    def testEmptyDeferredList(self):
 
109
        result = []
 
110
        def cb(resultList, result=result):
 
111
            result.append(resultList)
 
112
 
 
113
        dl = defer.DeferredList([])
 
114
        dl.addCallbacks(cb)
 
115
        self.failUnlessEqual(result, [[]])
 
116
 
 
117
        result[:] = []
 
118
        dl = defer.DeferredList([], fireOnOneCallback=1)
 
119
        dl.addCallbacks(cb)
 
120
        self.failUnlessEqual(result, [])
 
121
 
 
122
    def testDeferredListFireOnOneError(self):
 
123
        defr1 = defer.Deferred()
 
124
        defr2 = defer.Deferred()
 
125
        defr3 = defer.Deferred()
 
126
        dl = defer.DeferredList([defr1, defr2, defr3], fireOnOneErrback=1)
 
127
        result = []
 
128
        dl.addErrback(result.append)
 
129
 
 
130
        # consume errors after they pass through the DeferredList (to avoid
 
131
        # 'Unhandled error in Deferred'.
 
132
        def catch(err):
 
133
            return None
 
134
        defr2.addErrback(catch)
 
135
 
 
136
        # fire one Deferred's callback, no result yet
 
137
        defr1.callback("1")
 
138
        self.failUnlessEqual(result, [])
 
139
 
 
140
        # fire one Deferred's errback -- now we have a result
 
141
        defr2.errback(GenericError("from def2"))
 
142
        self.failUnlessEqual(len(result), 1)
 
143
 
 
144
        # extract the result from the list
 
145
        failure = result[0]
 
146
 
 
147
        # the type of the failure is a FirstError
 
148
        self.failUnless(issubclass(failure.type, defer.FirstError),
 
149
            'issubclass(failure.type, defer.FirstError) failed: '
 
150
            'failure.type is %r' % (failure.type,)
 
151
        )
 
152
 
 
153
        firstError = failure.value
 
154
 
 
155
        # check that the GenericError("2") from the deferred at index 1
 
156
        # (defr2) is intact inside failure.value
 
157
        self.failUnlessEqual(firstError.subFailure.type, GenericError)
 
158
        self.failUnlessEqual(firstError.subFailure.value.args, ("from def2",))
 
159
        self.failUnlessEqual(firstError.index, 1)
 
160
 
 
161
 
 
162
    def testDeferredListDontConsumeErrors(self):
 
163
        d1 = defer.Deferred()
 
164
        dl = defer.DeferredList([d1])
 
165
 
 
166
        errorTrap = []
 
167
        d1.addErrback(errorTrap.append)
 
168
 
 
169
        result = []
 
170
        dl.addCallback(result.append)
 
171
 
 
172
        d1.errback(GenericError('Bang'))
 
173
        self.failUnlessEqual('Bang', errorTrap[0].value.args[0])
 
174
        self.failUnlessEqual(1, len(result))
 
175
        self.failUnlessEqual('Bang', result[0][0][1].value.args[0])
 
176
 
 
177
    def testDeferredListConsumeErrors(self):
 
178
        d1 = defer.Deferred()
 
179
        dl = defer.DeferredList([d1], consumeErrors=True)
 
180
 
 
181
        errorTrap = []
 
182
        d1.addErrback(errorTrap.append)
 
183
 
 
184
        result = []
 
185
        dl.addCallback(result.append)
 
186
 
 
187
        d1.errback(GenericError('Bang'))
 
188
        self.failUnlessEqual([], errorTrap)
 
189
        self.failUnlessEqual(1, len(result))
 
190
        self.failUnlessEqual('Bang', result[0][0][1].value.args[0])
 
191
 
 
192
    def testDeferredListFireOnOneErrorWithAlreadyFiredDeferreds(self):
 
193
        # Create some deferreds, and errback one
 
194
        d1 = defer.Deferred()
 
195
        d2 = defer.Deferred()
 
196
        d1.errback(GenericError('Bang'))
 
197
 
 
198
        # *Then* build the DeferredList, with fireOnOneErrback=True
 
199
        dl = defer.DeferredList([d1, d2], fireOnOneErrback=True)
 
200
        result = []
 
201
        dl.addErrback(result.append)
 
202
        self.failUnlessEqual(1, len(result))
 
203
 
 
204
        d1.addErrback(lambda e: None)  # Swallow error
 
205
 
 
206
    def testDeferredListWithAlreadyFiredDeferreds(self):
 
207
        # Create some deferreds, and err one, call the other
 
208
        d1 = defer.Deferred()
 
209
        d2 = defer.Deferred()
 
210
        d1.errback(GenericError('Bang'))
 
211
        d2.callback(2)
 
212
 
 
213
        # *Then* build the DeferredList
 
214
        dl = defer.DeferredList([d1, d2])
 
215
 
 
216
        result = []
 
217
        dl.addCallback(result.append)
 
218
 
 
219
        self.failUnlessEqual(1, len(result))
 
220
 
 
221
        d1.addErrback(lambda e: None)  # Swallow error
 
222
 
 
223
    def testTimeOut(self):
 
224
        """
 
225
        Test that a Deferred which has setTimeout called on it and never has
 
226
        C{callback} or C{errback} called on it eventually fails with a
 
227
        L{error.TimeoutError}.
 
228
        """
 
229
        L = []
 
230
        d = defer.Deferred()
 
231
        d.setTimeout(0.01)
 
232
        self.assertFailure(d, defer.TimeoutError)
 
233
        d.addCallback(L.append)
 
234
        self.failIf(L, "Deferred failed too soon.")
 
235
        return d
 
236
    testTimeOut.suppress = [_setTimeoutSuppression]
 
237
 
 
238
 
 
239
    def testImmediateSuccess(self):
 
240
        l = []
 
241
        d = defer.succeed("success")
 
242
        d.addCallback(l.append)
 
243
        self.assertEquals(l, ["success"])
 
244
 
 
245
 
 
246
    def test_immediateSuccessBeforeTimeout(self):
 
247
        """
 
248
        Test that a synchronously successful Deferred is not affected by a
 
249
        C{setTimeout} call.
 
250
        """
 
251
        l = []
 
252
        d = defer.succeed("success")
 
253
        d.setTimeout(1.0)
 
254
        d.addCallback(l.append)
 
255
        self.assertEquals(l, ["success"])
 
256
    test_immediateSuccessBeforeTimeout.suppress = [_setTimeoutSuppression]
 
257
 
 
258
 
 
259
    def testImmediateFailure(self):
 
260
        l = []
 
261
        d = defer.fail(GenericError("fail"))
 
262
        d.addErrback(l.append)
 
263
        self.assertEquals(str(l[0].value), "fail")
 
264
 
 
265
    def testPausedFailure(self):
 
266
        l = []
 
267
        d = defer.fail(GenericError("fail"))
 
268
        d.pause()
 
269
        d.addErrback(l.append)
 
270
        self.assertEquals(l, [])
 
271
        d.unpause()
 
272
        self.assertEquals(str(l[0].value), "fail")
 
273
 
 
274
    def testCallbackErrors(self):
 
275
        l = []
 
276
        d = defer.Deferred().addCallback(lambda _: 1/0).addErrback(l.append)
 
277
        d.callback(1)
 
278
        self.assert_(isinstance(l[0].value, ZeroDivisionError))
 
279
        l = []
 
280
        d = defer.Deferred().addCallback(
 
281
            lambda _: failure.Failure(ZeroDivisionError())).addErrback(l.append)
 
282
        d.callback(1)
 
283
        self.assert_(isinstance(l[0].value, ZeroDivisionError))
 
284
 
 
285
    def testUnpauseBeforeCallback(self):
 
286
        d = defer.Deferred()
 
287
        d.pause()
 
288
        d.addCallback(self._callback)
 
289
        d.unpause()
 
290
 
 
291
    def testReturnDeferred(self):
 
292
        d = defer.Deferred()
 
293
        d2 = defer.Deferred()
 
294
        d2.pause()
 
295
        d.addCallback(lambda r, d2=d2: d2)
 
296
        d.addCallback(self._callback)
 
297
        d.callback(1)
 
298
        assert self.callback_results is None, "Should not have been called yet."
 
299
        d2.callback(2)
 
300
        assert self.callback_results is None, "Still should not have been called yet."
 
301
        d2.unpause()
 
302
        assert self.callback_results[0][0] == 2, "Result should have been from second deferred:%s"% (self.callback_results,)
 
303
 
 
304
    def testGatherResults(self):
 
305
        # test successful list of deferreds
 
306
        l = []
 
307
        defer.gatherResults([defer.succeed(1), defer.succeed(2)]).addCallback(l.append)
 
308
        self.assertEquals(l, [[1, 2]])
 
309
        # test failing list of deferreds
 
310
        l = []
 
311
        dl = [defer.succeed(1), defer.fail(ValueError)]
 
312
        defer.gatherResults(dl).addErrback(l.append)
 
313
        self.assertEquals(len(l), 1)
 
314
        self.assert_(isinstance(l[0], failure.Failure))
 
315
        # get rid of error
 
316
        dl[1].addErrback(lambda e: 1)
 
317
 
 
318
 
 
319
    def test_maybeDeferredSync(self):
 
320
        """
 
321
        L{defer.maybeDeferred} should retrieve the result of a synchronous
 
322
        function and pass it to its resulting L{defer.Deferred}.
 
323
        """
 
324
        S, E = [], []
 
325
        d = defer.maybeDeferred((lambda x: x + 5), 10)
 
326
        d.addCallbacks(S.append, E.append)
 
327
        self.assertEquals(E, [])
 
328
        self.assertEquals(S, [15])
 
329
        return d
 
330
 
 
331
 
 
332
    def test_maybeDeferredSyncError(self):
 
333
        """
 
334
        L{defer.maybeDeferred} should catch exception raised by a synchronous
 
335
        function and errback its resulting L{defer.Deferred} with it.
 
336
        """
 
337
        S, E = [], []
 
338
        try:
 
339
            '10' + 5
 
340
        except TypeError, e:
 
341
            expected = str(e)
 
342
        d = defer.maybeDeferred((lambda x: x + 5), '10')
 
343
        d.addCallbacks(S.append, E.append)
 
344
        self.assertEquals(S, [])
 
345
        self.assertEquals(len(E), 1)
 
346
        self.assertEquals(str(E[0].value), expected)
 
347
        return d
 
348
 
 
349
 
 
350
    def test_maybeDeferredAsync(self):
 
351
        """
 
352
        L{defer.maybeDeferred} should let L{defer.Deferred} instance pass by
 
353
        so that original result is the same.
 
354
        """
 
355
        d = defer.Deferred()
 
356
        d2 = defer.maybeDeferred(lambda: d)
 
357
        d.callback('Success')
 
358
        return d2.addCallback(self.assertEquals, 'Success')
 
359
 
 
360
 
 
361
    def test_maybeDeferredAsyncError(self):
 
362
        """
 
363
        L{defer.maybeDeferred} should let L{defer.Deferred} instance pass by
 
364
        so that L{failure.Failure} returned by the original instance is the
 
365
        same.
 
366
        """
 
367
        d = defer.Deferred()
 
368
        d2 = defer.maybeDeferred(lambda: d)
 
369
        d.errback(failure.Failure(RuntimeError()))
 
370
        return self.assertFailure(d2, RuntimeError)
 
371
 
 
372
 
 
373
    def test_reentrantRunCallbacks(self):
 
374
        """
 
375
        A callback added to a L{Deferred} by a callback on that L{Deferred}
 
376
        should be added to the end of the callback chain.
 
377
        """
 
378
        deferred = defer.Deferred()
 
379
        called = []
 
380
        def callback3(result):
 
381
            called.append(3)
 
382
        def callback2(result):
 
383
            called.append(2)
 
384
        def callback1(result):
 
385
            called.append(1)
 
386
            deferred.addCallback(callback3)
 
387
        deferred.addCallback(callback1)
 
388
        deferred.addCallback(callback2)
 
389
        deferred.callback(None)
 
390
        self.assertEqual(called, [1, 2, 3])
 
391
 
 
392
 
 
393
    def test_nonReentrantCallbacks(self):
 
394
        """
 
395
        A callback added to a L{Deferred} by a callback on that L{Deferred}
 
396
        should not be executed until the running callback returns.
 
397
        """
 
398
        deferred = defer.Deferred()
 
399
        called = []
 
400
        def callback2(result):
 
401
            called.append(2)
 
402
        def callback1(result):
 
403
            called.append(1)
 
404
            deferred.addCallback(callback2)
 
405
            self.assertEquals(called, [1])
 
406
        deferred.addCallback(callback1)
 
407
        deferred.callback(None)
 
408
        self.assertEqual(called, [1, 2])
 
409
 
 
410
 
 
411
    def test_reentrantRunCallbacksWithFailure(self):
 
412
        """
 
413
        After an exception is raised by a callback which was added to a
 
414
        L{Deferred} by a callback on that L{Deferred}, the L{Deferred} should
 
415
        call the first errback with a L{Failure} wrapping that exception.
 
416
        """
 
417
        exceptionMessage = "callback raised exception"
 
418
        deferred = defer.Deferred()
 
419
        def callback2(result):
 
420
            raise Exception(exceptionMessage)
 
421
        def callback1(result):
 
422
            deferred.addCallback(callback2)
 
423
        deferred.addCallback(callback1)
 
424
        deferred.callback(None)
 
425
        self.assertFailure(deferred, Exception)
 
426
        def cbFailed(exception):
 
427
            self.assertEqual(exception.args, (exceptionMessage,))
 
428
        deferred.addCallback(cbFailed)
 
429
        return deferred
 
430
 
 
431
 
 
432
 
 
433
class FirstErrorTests(unittest.TestCase):
 
434
    """
 
435
    Tests for L{FirstError}.
 
436
    """
 
437
    def test_repr(self):
 
438
        """
 
439
        The repr of a L{FirstError} instance includes the repr of the value of
 
440
        the sub-failure and the index which corresponds to the L{FirstError}.
 
441
        """
 
442
        exc = ValueError("some text")
 
443
        try:
 
444
            raise exc
 
445
        except:
 
446
            f = failure.Failure()
 
447
 
 
448
        error = defer.FirstError(f, 3)
 
449
        self.assertEqual(
 
450
            repr(error),
 
451
            "FirstError[#3, %s]" % (repr(exc),))
 
452
 
 
453
 
 
454
    def test_str(self):
 
455
        """
 
456
        The str of a L{FirstError} instance includes the str of the
 
457
        sub-failure and the index which corresponds to the L{FirstError}.
 
458
        """
 
459
        exc = ValueError("some text")
 
460
        try:
 
461
            raise exc
 
462
        except:
 
463
            f = failure.Failure()
 
464
 
 
465
        error = defer.FirstError(f, 5)
 
466
        self.assertEqual(
 
467
            str(error),
 
468
            "FirstError[#5, %s]" % (str(f),))
 
469
 
 
470
 
 
471
    def test_comparison(self):
 
472
        """
 
473
        L{FirstError} instances compare equal to each other if and only if
 
474
        their failure and index compare equal.  L{FirstError} instances do not
 
475
        compare equal to instances of other types.
 
476
        """
 
477
        try:
 
478
            1 / 0
 
479
        except:
 
480
            firstFailure = failure.Failure()
 
481
 
 
482
        one = defer.FirstError(firstFailure, 13)
 
483
        anotherOne = defer.FirstError(firstFailure, 13)
 
484
 
 
485
        try:
 
486
            raise ValueError("bar")
 
487
        except:
 
488
            secondFailure = failure.Failure()
 
489
 
 
490
        another = defer.FirstError(secondFailure, 9)
 
491
 
 
492
        self.assertTrue(one == anotherOne)
 
493
        self.assertFalse(one == another)
 
494
        self.assertTrue(one != another)
 
495
        self.assertFalse(one != anotherOne)
 
496
 
 
497
        self.assertFalse(one == 10)
 
498
 
 
499
 
 
500
 
 
501
class AlreadyCalledTestCase(unittest.TestCase):
 
502
    def setUp(self):
 
503
        self._deferredWasDebugging = defer.getDebugging()
 
504
        defer.setDebugging(True)
 
505
 
 
506
    def tearDown(self):
 
507
        defer.setDebugging(self._deferredWasDebugging)
 
508
 
 
509
    def _callback(self, *args, **kw):
 
510
        pass
 
511
    def _errback(self, *args, **kw):
 
512
        pass
 
513
 
 
514
    def _call_1(self, d):
 
515
        d.callback("hello")
 
516
    def _call_2(self, d):
 
517
        d.callback("twice")
 
518
    def _err_1(self, d):
 
519
        d.errback(failure.Failure(RuntimeError()))
 
520
    def _err_2(self, d):
 
521
        d.errback(failure.Failure(RuntimeError()))
 
522
 
 
523
    def testAlreadyCalled_CC(self):
 
524
        d = defer.Deferred()
 
525
        d.addCallbacks(self._callback, self._errback)
 
526
        self._call_1(d)
 
527
        self.failUnlessRaises(defer.AlreadyCalledError, self._call_2, d)
 
528
 
 
529
    def testAlreadyCalled_CE(self):
 
530
        d = defer.Deferred()
 
531
        d.addCallbacks(self._callback, self._errback)
 
532
        self._call_1(d)
 
533
        self.failUnlessRaises(defer.AlreadyCalledError, self._err_2, d)
 
534
 
 
535
    def testAlreadyCalled_EE(self):
 
536
        d = defer.Deferred()
 
537
        d.addCallbacks(self._callback, self._errback)
 
538
        self._err_1(d)
 
539
        self.failUnlessRaises(defer.AlreadyCalledError, self._err_2, d)
 
540
 
 
541
    def testAlreadyCalled_EC(self):
 
542
        d = defer.Deferred()
 
543
        d.addCallbacks(self._callback, self._errback)
 
544
        self._err_1(d)
 
545
        self.failUnlessRaises(defer.AlreadyCalledError, self._call_2, d)
 
546
 
 
547
 
 
548
    def _count(self, linetype, func, lines, expected):
 
549
        count = 0
 
550
        for line in lines:
 
551
            if (line.startswith(' %s:' % linetype) and
 
552
                line.endswith(' %s' % func)):
 
553
                count += 1
 
554
        self.failUnless(count == expected)
 
555
 
 
556
    def _check(self, e, caller, invoker1, invoker2):
 
557
        # make sure the debugging information is vaguely correct
 
558
        lines = e.args[0].split("\n")
 
559
        # the creator should list the creator (testAlreadyCalledDebug) but not
 
560
        # _call_1 or _call_2 or other invokers
 
561
        self._count('C', caller, lines, 1)
 
562
        self._count('C', '_call_1', lines, 0)
 
563
        self._count('C', '_call_2', lines, 0)
 
564
        self._count('C', '_err_1', lines, 0)
 
565
        self._count('C', '_err_2', lines, 0)
 
566
        # invoker should list the first invoker but not the second
 
567
        self._count('I', invoker1, lines, 1)
 
568
        self._count('I', invoker2, lines, 0)
 
569
 
 
570
    def testAlreadyCalledDebug_CC(self):
 
571
        d = defer.Deferred()
 
572
        d.addCallbacks(self._callback, self._errback)
 
573
        self._call_1(d)
 
574
        try:
 
575
            self._call_2(d)
 
576
        except defer.AlreadyCalledError, e:
 
577
            self._check(e, "testAlreadyCalledDebug_CC", "_call_1", "_call_2")
 
578
        else:
 
579
            self.fail("second callback failed to raise AlreadyCalledError")
 
580
 
 
581
    def testAlreadyCalledDebug_CE(self):
 
582
        d = defer.Deferred()
 
583
        d.addCallbacks(self._callback, self._errback)
 
584
        self._call_1(d)
 
585
        try:
 
586
            self._err_2(d)
 
587
        except defer.AlreadyCalledError, e:
 
588
            self._check(e, "testAlreadyCalledDebug_CE", "_call_1", "_err_2")
 
589
        else:
 
590
            self.fail("second errback failed to raise AlreadyCalledError")
 
591
 
 
592
    def testAlreadyCalledDebug_EC(self):
 
593
        d = defer.Deferred()
 
594
        d.addCallbacks(self._callback, self._errback)
 
595
        self._err_1(d)
 
596
        try:
 
597
            self._call_2(d)
 
598
        except defer.AlreadyCalledError, e:
 
599
            self._check(e, "testAlreadyCalledDebug_EC", "_err_1", "_call_2")
 
600
        else:
 
601
            self.fail("second callback failed to raise AlreadyCalledError")
 
602
 
 
603
    def testAlreadyCalledDebug_EE(self):
 
604
        d = defer.Deferred()
 
605
        d.addCallbacks(self._callback, self._errback)
 
606
        self._err_1(d)
 
607
        try:
 
608
            self._err_2(d)
 
609
        except defer.AlreadyCalledError, e:
 
610
            self._check(e, "testAlreadyCalledDebug_EE", "_err_1", "_err_2")
 
611
        else:
 
612
            self.fail("second errback failed to raise AlreadyCalledError")
 
613
 
 
614
    def testNoDebugging(self):
 
615
        defer.setDebugging(False)
 
616
        d = defer.Deferred()
 
617
        d.addCallbacks(self._callback, self._errback)
 
618
        self._call_1(d)
 
619
        try:
 
620
            self._call_2(d)
 
621
        except defer.AlreadyCalledError, e:
 
622
            self.failIf(e.args)
 
623
        else:
 
624
            self.fail("second callback failed to raise AlreadyCalledError")
 
625
 
 
626
 
 
627
    def testSwitchDebugging(self):
 
628
        # Make sure Deferreds can deal with debug state flipping
 
629
        # around randomly.  This is covering a particular fixed bug.
 
630
        defer.setDebugging(False)
 
631
        d = defer.Deferred()
 
632
        d.addBoth(lambda ign: None)
 
633
        defer.setDebugging(True)
 
634
        d.callback(None)
 
635
 
 
636
        defer.setDebugging(False)
 
637
        d = defer.Deferred()
 
638
        d.callback(None)
 
639
        defer.setDebugging(True)
 
640
        d.addBoth(lambda ign: None)
 
641
 
 
642
 
 
643
 
 
644
class LogTestCase(unittest.TestCase):
 
645
    """
 
646
    Test logging of unhandled errors.
 
647
    """
 
648
 
 
649
    def setUp(self):
 
650
        """
 
651
        Add a custom observer to observer logging.
 
652
        """
 
653
        self.c = []
 
654
        log.addObserver(self.c.append)
 
655
 
 
656
    def tearDown(self):
 
657
        """
 
658
        Remove the observer.
 
659
        """
 
660
        log.removeObserver(self.c.append)
 
661
 
 
662
    def _check(self):
 
663
        """
 
664
        Check the output of the log observer to see if the error is present.
 
665
        """
 
666
        c2 = [e for e in self.c if e["isError"]]
 
667
        self.assertEquals(len(c2), 2)
 
668
        c2[1]["failure"].trap(ZeroDivisionError)
 
669
        self.flushLoggedErrors(ZeroDivisionError)
 
670
 
 
671
    def test_errorLog(self):
 
672
        """
 
673
        Verify that when a Deferred with no references to it is fired, and its
 
674
        final result (the one not handled by any callback) is an exception,
 
675
        that exception will be logged immediately.
 
676
        """
 
677
        defer.Deferred().addCallback(lambda x: 1/0).callback(1)
 
678
        gc.collect()
 
679
        self._check()
 
680
 
 
681
    def test_errorLogWithInnerFrameRef(self):
 
682
        """
 
683
        Same as L{test_errorLog}, but with an inner frame.
 
684
        """
 
685
        def _subErrorLogWithInnerFrameRef():
 
686
            d = defer.Deferred()
 
687
            d.addCallback(lambda x: 1/0)
 
688
            d.callback(1)
 
689
 
 
690
        _subErrorLogWithInnerFrameRef()
 
691
        gc.collect()
 
692
        self._check()
 
693
 
 
694
    def test_errorLogWithInnerFrameCycle(self):
 
695
        """
 
696
        Same as L{test_errorLogWithInnerFrameRef}, plus create a cycle.
 
697
        """
 
698
        def _subErrorLogWithInnerFrameCycle():
 
699
            d = defer.Deferred()
 
700
            d.addCallback(lambda x, d=d: 1/0)
 
701
            d._d = d
 
702
            d.callback(1)
 
703
 
 
704
        _subErrorLogWithInnerFrameCycle()
 
705
        gc.collect()
 
706
        self._check()
 
707
 
 
708
 
 
709
class DeferredTestCaseII(unittest.TestCase):
 
710
    def setUp(self):
 
711
        self.callbackRan = 0
 
712
 
 
713
    def testDeferredListEmpty(self):
 
714
        """Testing empty DeferredList."""
 
715
        dl = defer.DeferredList([])
 
716
        dl.addCallback(self.cb_empty)
 
717
 
 
718
    def cb_empty(self, res):
 
719
        self.callbackRan = 1
 
720
        self.failUnlessEqual([], res)
 
721
 
 
722
    def tearDown(self):
 
723
        self.failUnless(self.callbackRan, "Callback was never run.")
 
724
 
 
725
class OtherPrimitives(unittest.TestCase):
 
726
    def _incr(self, result):
 
727
        self.counter += 1
 
728
 
 
729
    def setUp(self):
 
730
        self.counter = 0
 
731
 
 
732
    def testLock(self):
 
733
        lock = defer.DeferredLock()
 
734
        lock.acquire().addCallback(self._incr)
 
735
        self.failUnless(lock.locked)
 
736
        self.assertEquals(self.counter, 1)
 
737
 
 
738
        lock.acquire().addCallback(self._incr)
 
739
        self.failUnless(lock.locked)
 
740
        self.assertEquals(self.counter, 1)
 
741
 
 
742
        lock.release()
 
743
        self.failUnless(lock.locked)
 
744
        self.assertEquals(self.counter, 2)
 
745
 
 
746
        lock.release()
 
747
        self.failIf(lock.locked)
 
748
        self.assertEquals(self.counter, 2)
 
749
 
 
750
        self.assertRaises(TypeError, lock.run)
 
751
 
 
752
        firstUnique = object()
 
753
        secondUnique = object()
 
754
 
 
755
        controlDeferred = defer.Deferred()
 
756
        def helper(self, b):
 
757
            self.b = b
 
758
            return controlDeferred
 
759
 
 
760
        resultDeferred = lock.run(helper, self=self, b=firstUnique)
 
761
        self.failUnless(lock.locked)
 
762
        self.assertEquals(self.b, firstUnique)
 
763
 
 
764
        resultDeferred.addCallback(lambda x: setattr(self, 'result', x))
 
765
 
 
766
        lock.acquire().addCallback(self._incr)
 
767
        self.failUnless(lock.locked)
 
768
        self.assertEquals(self.counter, 2)
 
769
 
 
770
        controlDeferred.callback(secondUnique)
 
771
        self.assertEquals(self.result, secondUnique)
 
772
        self.failUnless(lock.locked)
 
773
        self.assertEquals(self.counter, 3)
 
774
 
 
775
        lock.release()
 
776
        self.failIf(lock.locked)
 
777
 
 
778
    def testSemaphore(self):
 
779
        N = 13
 
780
        sem = defer.DeferredSemaphore(N)
 
781
 
 
782
        controlDeferred = defer.Deferred()
 
783
        def helper(self, arg):
 
784
            self.arg = arg
 
785
            return controlDeferred
 
786
 
 
787
        results = []
 
788
        uniqueObject = object()
 
789
        resultDeferred = sem.run(helper, self=self, arg=uniqueObject)
 
790
        resultDeferred.addCallback(results.append)
 
791
        resultDeferred.addCallback(self._incr)
 
792
        self.assertEquals(results, [])
 
793
        self.assertEquals(self.arg, uniqueObject)
 
794
        controlDeferred.callback(None)
 
795
        self.assertEquals(results.pop(), None)
 
796
        self.assertEquals(self.counter, 1)
 
797
 
 
798
        self.counter = 0
 
799
        for i in range(1, 1 + N):
 
800
            sem.acquire().addCallback(self._incr)
 
801
            self.assertEquals(self.counter, i)
 
802
 
 
803
        sem.acquire().addCallback(self._incr)
 
804
        self.assertEquals(self.counter, N)
 
805
 
 
806
        sem.release()
 
807
        self.assertEquals(self.counter, N + 1)
 
808
 
 
809
        for i in range(1, 1 + N):
 
810
            sem.release()
 
811
            self.assertEquals(self.counter, N + 1)
 
812
 
 
813
    def testQueue(self):
 
814
        N, M = 2, 2
 
815
        queue = defer.DeferredQueue(N, M)
 
816
 
 
817
        gotten = []
 
818
 
 
819
        for i in range(M):
 
820
            queue.get().addCallback(gotten.append)
 
821
        self.assertRaises(defer.QueueUnderflow, queue.get)
 
822
 
 
823
        for i in range(M):
 
824
            queue.put(i)
 
825
            self.assertEquals(gotten, range(i + 1))
 
826
        for i in range(N):
 
827
            queue.put(N + i)
 
828
            self.assertEquals(gotten, range(M))
 
829
        self.assertRaises(defer.QueueOverflow, queue.put, None)
 
830
 
 
831
        gotten = []
 
832
        for i in range(N):
 
833
            queue.get().addCallback(gotten.append)
 
834
            self.assertEquals(gotten, range(N, N + i + 1))
 
835
 
 
836
        queue = defer.DeferredQueue()
 
837
        gotten = []
 
838
        for i in range(N):
 
839
            queue.get().addCallback(gotten.append)
 
840
        for i in range(N):
 
841
            queue.put(i)
 
842
        self.assertEquals(gotten, range(N))
 
843
 
 
844
        queue = defer.DeferredQueue(size=0)
 
845
        self.assertRaises(defer.QueueOverflow, queue.put, None)
 
846
 
 
847
        queue = defer.DeferredQueue(backlog=0)
 
848
        self.assertRaises(defer.QueueUnderflow, queue.get)
 
849
 
 
850
 
 
851
 
 
852
class DeferredFilesystemLockTestCase(unittest.TestCase):
 
853
    """
 
854
    Test the behavior of L{DeferredFilesystemLock}
 
855
    """
 
856
    def setUp(self):
 
857
        self.clock = Clock()
 
858
        self.lock = defer.DeferredFilesystemLock(self.mktemp(),
 
859
                                                 scheduler=self.clock)
 
860
 
 
861
 
 
862
    def test_waitUntilLockedWithNoLock(self):
 
863
        """
 
864
        Test that the lock can be acquired when no lock is held
 
865
        """
 
866
        d = self.lock.deferUntilLocked(timeout=1)
 
867
 
 
868
        return d
 
869
 
 
870
 
 
871
    def test_waitUntilLockedWithTimeoutLocked(self):
 
872
        """
 
873
        Test that the lock can not be acquired when the lock is held
 
874
        for longer than the timeout.
 
875
        """
 
876
        self.failUnless(self.lock.lock())
 
877
 
 
878
        d = self.lock.deferUntilLocked(timeout=5.5)
 
879
        self.assertFailure(d, defer.TimeoutError)
 
880
 
 
881
        self.clock.pump([1]*10)
 
882
 
 
883
        return d
 
884
 
 
885
 
 
886
    def test_waitUntilLockedWithTimeoutUnlocked(self):
 
887
        """
 
888
        Test that a lock can be acquired while a lock is held
 
889
        but the lock is unlocked before our timeout.
 
890
        """
 
891
        def onTimeout(f):
 
892
            f.trap(defer.TimeoutError)
 
893
            self.fail("Should not have timed out")
 
894
 
 
895
        self.failUnless(self.lock.lock())
 
896
 
 
897
        self.clock.callLater(1, self.lock.unlock)
 
898
        d = self.lock.deferUntilLocked(timeout=10)
 
899
        d.addErrback(onTimeout)
 
900
 
 
901
        self.clock.pump([1]*10)
 
902
 
 
903
        return d
 
904
 
 
905
 
 
906
    def test_defaultScheduler(self):
 
907
        """
 
908
        Test that the default scheduler is set up properly.
 
909
        """
 
910
        lock = defer.DeferredFilesystemLock(self.mktemp())
 
911
 
 
912
        self.assertEquals(lock._scheduler, reactor)
 
913
 
 
914
 
 
915
    def test_concurrentUsage(self):
 
916
        """
 
917
        Test that an appropriate exception is raised when attempting
 
918
        to use deferUntilLocked concurrently.
 
919
        """
 
920
        self.lock.lock()
 
921
        self.clock.callLater(1, self.lock.unlock)
 
922
 
 
923
        d = self.lock.deferUntilLocked()
 
924
        d2 = self.lock.deferUntilLocked()
 
925
 
 
926
        self.assertFailure(d2, defer.AlreadyTryingToLockError)
 
927
 
 
928
        self.clock.advance(1)
 
929
 
 
930
        return d
 
931
 
 
932
 
 
933
    def test_multipleUsages(self):
 
934
        """
 
935
        Test that a DeferredFilesystemLock can be used multiple times
 
936
        """
 
937
        def lockAquired(ign):
 
938
            self.lock.unlock()
 
939
            d = self.lock.deferUntilLocked()
 
940
            return d
 
941
 
 
942
        self.lock.lock()
 
943
        self.clock.callLater(1, self.lock.unlock)
 
944
 
 
945
        d = self.lock.deferUntilLocked()
 
946
        d.addCallback(lockAquired)
 
947
 
 
948
        self.clock.advance(1)
 
949
 
 
950
        return d