~certify-web-dev/twisted/certify-staging

« back to all changes in this revision

Viewing changes to twisted/test/test_task.py

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2010-01-02 19:38:17 UTC
  • mfrom: (2.2.4 sid)
  • Revision ID: james.westby@ubuntu.com-20100102193817-jphp464ppwh7dulg
Tags: 9.0.0-1
* python-twisted: Depend on the python-twisted-* 9.0 packages.
* python-twisted: Depend on python-zope.interface only. Closes: #557781.

Show diffs side-by-side

added added

removed removed

Lines of Context:
199
199
        call = task.LoopingCall(aCallback)
200
200
        call.clock = clock
201
201
 
 
202
        # Start a LoopingCall with a 0.5 second increment, and immediately call
 
203
        # the callable.
202
204
        callDuration = 2
203
205
        call.start(0.5)
 
206
 
 
207
        # Verify that the callable was called, and since it was immediate, with
 
208
        # no skips.
204
209
        self.assertEqual(times, [0])
205
 
        self.assertEqual(clock.seconds(), 2)
 
210
 
 
211
        # The callback should have advanced the clock by the callDuration.
 
212
        self.assertEqual(clock.seconds(), callDuration)
206
213
 
207
214
        # An iteration should have occurred at 2, but since 2 is the present
208
215
        # and not the future, it is skipped.
 
216
 
209
217
        clock.advance(0)
210
218
        self.assertEqual(times, [0])
211
219
 
239
247
        def aCallback():
240
248
            times.append(clock.seconds())
241
249
 
 
250
        # Start a LoopingCall that tracks the time passed, with a 0.5 second
 
251
        # increment.
242
252
        call = task.LoopingCall(aCallback)
243
253
        call.clock = clock
244
 
 
245
254
        call.start(0.5)
 
255
 
 
256
        # Initially, no time should have passed!
246
257
        self.assertEqual(times, [0])
247
258
 
 
259
        # Advance the clock by 2 seconds (2 seconds should have passed)
248
260
        clock.advance(2)
249
261
        self.assertEqual(times, [0, 2])
250
262
 
 
263
        # Advance the clock by 1 second (3 total should have passed)
251
264
        clock.advance(1)
252
265
        self.assertEqual(times, [0, 2, 3])
253
266
 
 
267
        # Advance the clock by 0 seconds (this should have no effect!)
254
268
        clock.advance(0)
255
269
        self.assertEqual(times, [0, 2, 3])
256
270
 
257
271
 
 
272
    def test_reactorTimeCountSkips(self):
 
273
        """
 
274
        When L{LoopingCall} schedules itself to run again, if more than the
 
275
        specified interval has passed, it should schedule the next call for the
 
276
        next interval which is still in the future. If it was created
 
277
        using L{LoopingCall.withCount}, a positional argument will be
 
278
        inserted at the beginning of the argument list, indicating the number
 
279
        of calls that should have been made. 
 
280
        """
 
281
        times = []
 
282
        clock = task.Clock()
 
283
        def aCallback(numCalls):
 
284
            times.append((clock.seconds(), numCalls))
 
285
 
 
286
        # Start a LoopingCall that tracks the time passed, and the number of
 
287
        # skips, with a 0.5 second increment.
 
288
        call = task.LoopingCall.withCount(aCallback)
 
289
        call.clock = clock
 
290
        INTERVAL = 0.5
 
291
        REALISTIC_DELAY = 0.01
 
292
        call.start(INTERVAL)
 
293
 
 
294
        # Initially, no seconds should have passed, and one calls should have
 
295
        # been made.
 
296
        self.assertEqual(times, [(0, 1)])
 
297
 
 
298
        # After the interval (plus a small delay, to account for the time that
 
299
        # the reactor takes to wake up and process the LoopingCall), we should
 
300
        # still have only made one call.
 
301
        clock.advance(INTERVAL + REALISTIC_DELAY)
 
302
        self.assertEqual(times, [(0, 1), (INTERVAL + REALISTIC_DELAY, 1)])
 
303
 
 
304
        # After advancing the clock by three intervals (plus a small delay to
 
305
        # account for the reactor), we should have skipped two calls; one less
 
306
        # than the number of intervals which have completely elapsed. Along
 
307
        # with the call we did actually make, the final number of calls is 3.
 
308
        clock.advance((3 * INTERVAL) + REALISTIC_DELAY)
 
309
        self.assertEqual(times,
 
310
                         [(0, 1), (INTERVAL + REALISTIC_DELAY, 1),
 
311
                          ((4 * INTERVAL) + (2 * REALISTIC_DELAY), 3)])
 
312
 
 
313
        # Advancing the clock by 0 seconds should not cause any changes!
 
314
        clock.advance(0)
 
315
        self.assertEqual(times,
 
316
                         [(0, 1), (INTERVAL + REALISTIC_DELAY, 1),
 
317
                          ((4 * INTERVAL) + (2 * REALISTIC_DELAY), 3)])
 
318
 
 
319
 
 
320
    def test_countLengthyIntervalCounts(self):
 
321
        """
 
322
        L{LoopingCall.withCount} counts only calls that were expected to be
 
323
        made.  So, if more than one, but less than two intervals pass between
 
324
        invocations, it won't increase the count above 1.  For example, a
 
325
        L{LoopingCall} with interval T expects to be invoked at T, 2T, 3T, etc.
 
326
        However, the reactor takes some time to get around to calling it, so in
 
327
        practice it will be called at T+something, 2T+something, 3T+something;
 
328
        and due to other things going on in the reactor, "something" is
 
329
        variable.  It won't increase the count unless "something" is greater
 
330
        than T.  So if the L{LoopingCall} is invoked at T, 2.75T, and 3T,
 
331
        the count has not increased, even though the distance between
 
332
        invocation 1 and invocation 2 is 1.75T.
 
333
        """
 
334
        times = []
 
335
        clock = task.Clock()
 
336
        def aCallback(count):
 
337
            times.append((clock.seconds(), count))
 
338
 
 
339
        # Start a LoopingCall that tracks the time passed, and the number of
 
340
        # calls, with a 0.5 second increment.
 
341
        call = task.LoopingCall.withCount(aCallback)
 
342
        call.clock = clock
 
343
        INTERVAL = 0.5
 
344
        REALISTIC_DELAY = 0.01
 
345
        call.start(INTERVAL)
 
346
        self.assertEqual(times.pop(), (0, 1))
 
347
 
 
348
        # About one interval... So far, so good
 
349
        clock.advance(INTERVAL + REALISTIC_DELAY)
 
350
        self.assertEqual(times.pop(), (INTERVAL + REALISTIC_DELAY, 1))
 
351
 
 
352
        # Oh no, something delayed us for a while.
 
353
        clock.advance(INTERVAL * 1.75)
 
354
        self.assertEqual(times.pop(), ((2.75 * INTERVAL) + REALISTIC_DELAY, 1))
 
355
 
 
356
        # Back on track!  We got invoked when we expected this time.
 
357
        clock.advance(INTERVAL * 0.25)
 
358
        self.assertEqual(times.pop(), ((3.0 * INTERVAL) + REALISTIC_DELAY, 1))
 
359
 
 
360
 
258
361
    def testBasicFunction(self):
259
362
        # Arrange to have time advanced enough so that our function is
260
363
        # called a few times.
439
542
        return d
440
543
 
441
544
 
 
545
    def test_deferredWithCount(self):
 
546
        """
 
547
        In the case that the function passed to L{LoopingCall.withCount}
 
548
        returns a deferred, which does not fire before the next interval
 
549
        elapses, the function should not be run again. And if a function call
 
550
        is skipped in this fashion, the appropriate count should be
 
551
        provided.
 
552
        """
 
553
        testClock = task.Clock()
 
554
        d = defer.Deferred()
 
555
        deferredCounts = []
 
556
 
 
557
        def countTracker(possibleCount):
 
558
            # Keep a list of call counts
 
559
            deferredCounts.append(possibleCount)
 
560
            # Return a deferred, but only on the first request
 
561
            if len(deferredCounts) == 1:
 
562
                return d
 
563
            else:
 
564
                return None
 
565
 
 
566
        # Start a looping call for our countTracker function
 
567
        # Set the increment to 0.2, and do not call the function on startup.
 
568
        lc = task.LoopingCall.withCount(countTracker)
 
569
        lc.clock = testClock
 
570
        d = lc.start(0.2, now=False)
 
571
 
 
572
        # Confirm that nothing has happened yet.
 
573
        self.assertEquals(deferredCounts, [])
 
574
 
 
575
        # Advance the clock by 0.2 and then 0.4;
 
576
        testClock.pump([0.2, 0.4])
 
577
        # We should now have exactly one count (of 1 call)
 
578
        self.assertEquals(len(deferredCounts), 1)
 
579
 
 
580
        # Fire the deferred, and advance the clock by another 0.2
 
581
        d.callback(None)
 
582
        testClock.pump([0.2])
 
583
        # We should now have exactly 2 counts...
 
584
        self.assertEquals(len(deferredCounts), 2)
 
585
        # The first count should be 1 (one call)
 
586
        # The second count should be 3 (calls were missed at about 0.6 and 0.8)
 
587
        self.assertEquals(deferredCounts, [1, 3])
 
588
 
 
589
 
442
590
 
443
591
class DeferLaterTests(unittest.TestCase):
444
592
    """