| Index: third_party/twisted_8_1/twisted/test/test_internet.py
|
| diff --git a/third_party/twisted_8_1/twisted/test/test_internet.py b/third_party/twisted_8_1/twisted/test/test_internet.py
|
| deleted file mode 100644
|
| index b87766964c2ef4ce39c913ffa0dae02e705d24b5..0000000000000000000000000000000000000000
|
| --- a/third_party/twisted_8_1/twisted/test/test_internet.py
|
| +++ /dev/null
|
| @@ -1,1653 +0,0 @@
|
| -# Copyright (c) 2001-2007 Twisted Matrix Laboratories.
|
| -# See LICENSE for details.
|
| -
|
| -
|
| -from twisted.trial import unittest
|
| -from twisted.internet import reactor, protocol, error, abstract, defer
|
| -from twisted.internet import interfaces, base, task
|
| -from twisted.internet.tcp import Connection
|
| -
|
| -from twisted.test.time_helpers import Clock
|
| -
|
| -try:
|
| - from twisted.internet import ssl
|
| -except ImportError:
|
| - ssl = None
|
| -if ssl and not ssl.supported:
|
| - ssl = None
|
| -
|
| -from twisted.internet.defer import Deferred, maybeDeferred
|
| -from twisted.python import util, runtime
|
| -
|
| -import os
|
| -import sys
|
| -import time
|
| -import socket
|
| -
|
| -
|
| -
|
| -class ThreePhaseEventTests(unittest.TestCase):
|
| - """
|
| - Tests for the private implementation helpers for system event triggers.
|
| - """
|
| - def setUp(self):
|
| - """
|
| - Create a trigger, an argument, and an event to be used by tests.
|
| - """
|
| - self.trigger = lambda x: None
|
| - self.arg = object()
|
| - self.event = base._ThreePhaseEvent()
|
| -
|
| -
|
| - def test_addInvalidPhase(self):
|
| - """
|
| - L{_ThreePhaseEvent.addTrigger} should raise L{KeyError} when called
|
| - with an invalid phase.
|
| - """
|
| - self.assertRaises(
|
| - KeyError,
|
| - self.event.addTrigger, 'xxx', self.trigger, self.arg)
|
| -
|
| -
|
| - def test_addBeforeTrigger(self):
|
| - """
|
| - L{_ThreePhaseEvent.addTrigger} should accept C{'before'} as a phase, a
|
| - callable, and some arguments and add the callable with the arguments to
|
| - the before list.
|
| - """
|
| - self.event.addTrigger('before', self.trigger, self.arg)
|
| - self.assertEqual(
|
| - self.event.before,
|
| - [(self.trigger, (self.arg,), {})])
|
| -
|
| -
|
| - def test_addDuringTrigger(self):
|
| - """
|
| - L{_ThreePhaseEvent.addTrigger} should accept C{'during'} as a phase, a
|
| - callable, and some arguments and add the callable with the arguments to
|
| - the during list.
|
| - """
|
| - self.event.addTrigger('during', self.trigger, self.arg)
|
| - self.assertEqual(
|
| - self.event.during,
|
| - [(self.trigger, (self.arg,), {})])
|
| -
|
| -
|
| - def test_addAfterTrigger(self):
|
| - """
|
| - L{_ThreePhaseEvent.addTrigger} should accept C{'after'} as a phase, a
|
| - callable, and some arguments and add the callable with the arguments to
|
| - the after list.
|
| - """
|
| - self.event.addTrigger('after', self.trigger, self.arg)
|
| - self.assertEqual(
|
| - self.event.after,
|
| - [(self.trigger, (self.arg,), {})])
|
| -
|
| -
|
| - def test_removeTrigger(self):
|
| - """
|
| - L{_ThreePhaseEvent.removeTrigger} should accept an opaque object
|
| - previously returned by L{_ThreePhaseEvent.addTrigger} and remove the
|
| - associated trigger.
|
| - """
|
| - handle = self.event.addTrigger('before', self.trigger, self.arg)
|
| - self.event.removeTrigger(handle)
|
| - self.assertEqual(self.event.before, [])
|
| -
|
| -
|
| - def test_removeNonexistentTrigger(self):
|
| - """
|
| - L{_ThreePhaseEvent.removeTrigger} should raise L{ValueError} when given
|
| - an object not previously returned by L{_ThreePhaseEvent.addTrigger}.
|
| - """
|
| - self.assertRaises(ValueError, self.event.removeTrigger, object())
|
| -
|
| -
|
| - def test_removeRemovedTrigger(self):
|
| - """
|
| - L{_ThreePhaseEvent.removeTrigger} should raise L{ValueError} the second
|
| - time it is called with an object returned by
|
| - L{_ThreePhaseEvent.addTrigger}.
|
| - """
|
| - handle = self.event.addTrigger('before', self.trigger, self.arg)
|
| - self.event.removeTrigger(handle)
|
| - self.assertRaises(ValueError, self.event.removeTrigger, handle)
|
| -
|
| -
|
| - def test_removeAlmostValidTrigger(self):
|
| - """
|
| - L{_ThreePhaseEvent.removeTrigger} should raise L{ValueError} if it is
|
| - given a trigger handle which resembles a valid trigger handle aside
|
| - from its phase being incorrect.
|
| - """
|
| - self.assertRaises(
|
| - KeyError,
|
| - self.event.removeTrigger, ('xxx', self.trigger, (self.arg,), {}))
|
| -
|
| -
|
| - def test_fireEvent(self):
|
| - """
|
| - L{_ThreePhaseEvent.fireEvent} should call I{before}, I{during}, and
|
| - I{after} phase triggers in that order.
|
| - """
|
| - events = []
|
| - self.event.addTrigger('after', events.append, ('first', 'after'))
|
| - self.event.addTrigger('during', events.append, ('first', 'during'))
|
| - self.event.addTrigger('before', events.append, ('first', 'before'))
|
| - self.event.addTrigger('before', events.append, ('second', 'before'))
|
| - self.event.addTrigger('during', events.append, ('second', 'during'))
|
| - self.event.addTrigger('after', events.append, ('second', 'after'))
|
| -
|
| - self.assertEqual(events, [])
|
| - self.event.fireEvent()
|
| - self.assertEqual(events,
|
| - [('first', 'before'), ('second', 'before'),
|
| - ('first', 'during'), ('second', 'during'),
|
| - ('first', 'after'), ('second', 'after')])
|
| -
|
| -
|
| - def test_asynchronousBefore(self):
|
| - """
|
| - L{_ThreePhaseEvent.fireEvent} should wait for any L{Deferred} returned
|
| - by a I{before} phase trigger before proceeding to I{during} events.
|
| - """
|
| - events = []
|
| - beforeResult = Deferred()
|
| - self.event.addTrigger('before', lambda: beforeResult)
|
| - self.event.addTrigger('during', events.append, 'during')
|
| - self.event.addTrigger('after', events.append, 'after')
|
| -
|
| - self.assertEqual(events, [])
|
| - self.event.fireEvent()
|
| - self.assertEqual(events, [])
|
| - beforeResult.callback(None)
|
| - self.assertEqual(events, ['during', 'after'])
|
| -
|
| -
|
| - def test_beforeTriggerException(self):
|
| - """
|
| - If a before-phase trigger raises a synchronous exception, it should be
|
| - logged and the remaining triggers should be run.
|
| - """
|
| - events = []
|
| -
|
| - class DummyException(Exception):
|
| - pass
|
| -
|
| - def raisingTrigger():
|
| - raise DummyException()
|
| -
|
| - self.event.addTrigger('before', raisingTrigger)
|
| - self.event.addTrigger('before', events.append, 'before')
|
| - self.event.addTrigger('during', events.append, 'during')
|
| - self.event.fireEvent()
|
| - self.assertEqual(events, ['before', 'during'])
|
| - errors = self.flushLoggedErrors(DummyException)
|
| - self.assertEqual(len(errors), 1)
|
| -
|
| -
|
| - def test_duringTriggerException(self):
|
| - """
|
| - If a during-phase trigger raises a synchronous exception, it should be
|
| - logged and the remaining triggers should be run.
|
| - """
|
| - events = []
|
| -
|
| - class DummyException(Exception):
|
| - pass
|
| -
|
| - def raisingTrigger():
|
| - raise DummyException()
|
| -
|
| - self.event.addTrigger('during', raisingTrigger)
|
| - self.event.addTrigger('during', events.append, 'during')
|
| - self.event.addTrigger('after', events.append, 'after')
|
| - self.event.fireEvent()
|
| - self.assertEqual(events, ['during', 'after'])
|
| - errors = self.flushLoggedErrors(DummyException)
|
| - self.assertEqual(len(errors), 1)
|
| -
|
| -
|
| - def test_synchronousRemoveAlreadyExecutedBefore(self):
|
| - """
|
| - If a before-phase trigger tries to remove another before-phase trigger
|
| - which has already run, a warning should be emitted.
|
| - """
|
| - events = []
|
| -
|
| - def removeTrigger():
|
| - self.event.removeTrigger(beforeHandle)
|
| -
|
| - beforeHandle = self.event.addTrigger('before', events.append, ('first', 'before'))
|
| - self.event.addTrigger('before', removeTrigger)
|
| - self.event.addTrigger('before', events.append, ('second', 'before'))
|
| - self.assertWarns(
|
| - DeprecationWarning,
|
| - "Removing already-fired system event triggers will raise an "
|
| - "exception in a future version of Twisted.",
|
| - __file__,
|
| - self.event.fireEvent)
|
| - self.assertEqual(events, [('first', 'before'), ('second', 'before')])
|
| -
|
| -
|
| - def test_synchronousRemovePendingBefore(self):
|
| - """
|
| - If a before-phase trigger removes another before-phase trigger which
|
| - has not yet run, the removed trigger should not be run.
|
| - """
|
| - events = []
|
| - self.event.addTrigger(
|
| - 'before', lambda: self.event.removeTrigger(beforeHandle))
|
| - beforeHandle = self.event.addTrigger(
|
| - 'before', events.append, ('first', 'before'))
|
| - self.event.addTrigger('before', events.append, ('second', 'before'))
|
| - self.event.fireEvent()
|
| - self.assertEqual(events, [('second', 'before')])
|
| -
|
| -
|
| - def test_synchronousBeforeRemovesDuring(self):
|
| - """
|
| - If a before-phase trigger removes a during-phase trigger, the
|
| - during-phase trigger should not be run.
|
| - """
|
| - events = []
|
| - self.event.addTrigger(
|
| - 'before', lambda: self.event.removeTrigger(duringHandle))
|
| - duringHandle = self.event.addTrigger('during', events.append, 'during')
|
| - self.event.addTrigger('after', events.append, 'after')
|
| - self.event.fireEvent()
|
| - self.assertEqual(events, ['after'])
|
| -
|
| -
|
| - def test_asynchronousBeforeRemovesDuring(self):
|
| - """
|
| - If a before-phase trigger returns a L{Deferred} and later removes a
|
| - during-phase trigger before the L{Deferred} fires, the during-phase
|
| - trigger should not be run.
|
| - """
|
| - events = []
|
| - beforeResult = Deferred()
|
| - self.event.addTrigger('before', lambda: beforeResult)
|
| - duringHandle = self.event.addTrigger('during', events.append, 'during')
|
| - self.event.addTrigger('after', events.append, 'after')
|
| - self.event.fireEvent()
|
| - self.event.removeTrigger(duringHandle)
|
| - beforeResult.callback(None)
|
| - self.assertEqual(events, ['after'])
|
| -
|
| -
|
| - def test_synchronousBeforeRemovesConspicuouslySimilarDuring(self):
|
| - """
|
| - If a before-phase trigger removes a during-phase trigger which is
|
| - identical to an already-executed before-phase trigger aside from their
|
| - phases, no warning should be emitted and the during-phase trigger
|
| - should not be run.
|
| - """
|
| - events = []
|
| - def trigger():
|
| - events.append('trigger')
|
| - self.event.addTrigger('before', trigger)
|
| - self.event.addTrigger(
|
| - 'before', lambda: self.event.removeTrigger(duringTrigger))
|
| - duringTrigger = self.event.addTrigger('during', trigger)
|
| - self.event.fireEvent()
|
| - self.assertEqual(events, ['trigger'])
|
| -
|
| -
|
| - def test_synchronousRemovePendingDuring(self):
|
| - """
|
| - If a during-phase trigger removes another during-phase trigger which
|
| - has not yet run, the removed trigger should not be run.
|
| - """
|
| - events = []
|
| - self.event.addTrigger(
|
| - 'during', lambda: self.event.removeTrigger(duringHandle))
|
| - duringHandle = self.event.addTrigger(
|
| - 'during', events.append, ('first', 'during'))
|
| - self.event.addTrigger(
|
| - 'during', events.append, ('second', 'during'))
|
| - self.event.fireEvent()
|
| - self.assertEqual(events, [('second', 'during')])
|
| -
|
| -
|
| - def test_triggersRunOnce(self):
|
| - """
|
| - A trigger should only be called on the first call to
|
| - L{_ThreePhaseEvent.fireEvent}.
|
| - """
|
| - events = []
|
| - self.event.addTrigger('before', events.append, 'before')
|
| - self.event.addTrigger('during', events.append, 'during')
|
| - self.event.addTrigger('after', events.append, 'after')
|
| - self.event.fireEvent()
|
| - self.event.fireEvent()
|
| - self.assertEqual(events, ['before', 'during', 'after'])
|
| -
|
| -
|
| - def test_finishedBeforeTriggersCleared(self):
|
| - """
|
| - The temporary list L{_ThreePhaseEvent.finishedBefore} should be emptied
|
| - and the state reset to C{'BASE'} before the first during-phase trigger
|
| - executes.
|
| - """
|
| - events = []
|
| - def duringTrigger():
|
| - events.append('during')
|
| - self.assertEqual(self.event.finishedBefore, [])
|
| - self.assertEqual(self.event.state, 'BASE')
|
| - self.event.addTrigger('before', events.append, 'before')
|
| - self.event.addTrigger('during', duringTrigger)
|
| - self.event.fireEvent()
|
| - self.assertEqual(events, ['before', 'during'])
|
| -
|
| -
|
| -
|
| -class SystemEventTestCase(unittest.TestCase):
|
| - """
|
| - Tests for the reactor's implementation of the C{fireSystemEvent},
|
| - C{addSystemEventTrigger}, and C{removeSystemEventTrigger} methods of the
|
| - L{IReactorCore} interface.
|
| -
|
| - @ivar triggers: A list of the handles to triggers which have been added to
|
| - the reactor.
|
| - """
|
| - def setUp(self):
|
| - """
|
| - Create an empty list in which to store trigger handles.
|
| - """
|
| - self.triggers = []
|
| -
|
| -
|
| - def tearDown(self):
|
| - """
|
| - Remove all remaining triggers from the reactor.
|
| - """
|
| - while self.triggers:
|
| - trigger = self.triggers.pop()
|
| - try:
|
| - reactor.removeSystemEventTrigger(trigger)
|
| - except (ValueError, KeyError):
|
| - pass
|
| -
|
| -
|
| - def addTrigger(self, event, phase, func):
|
| - """
|
| - Add a trigger to the reactor and remember it in C{self.triggers}.
|
| - """
|
| - t = reactor.addSystemEventTrigger(event, phase, func)
|
| - self.triggers.append(t)
|
| - return t
|
| -
|
| -
|
| - def removeTrigger(self, trigger):
|
| - """
|
| - Remove a trigger by its handle from the reactor and from
|
| - C{self.triggers}.
|
| - """
|
| - reactor.removeSystemEventTrigger(trigger)
|
| - self.triggers.remove(trigger)
|
| -
|
| -
|
| - def _addSystemEventTriggerTest(self, phase):
|
| - eventType = 'test'
|
| - events = []
|
| - def trigger():
|
| - events.append(None)
|
| - self.addTrigger(phase, eventType, trigger)
|
| - self.assertEqual(events, [])
|
| - reactor.fireSystemEvent(eventType)
|
| - self.assertEqual(events, [None])
|
| -
|
| -
|
| - def test_beforePhase(self):
|
| - """
|
| - L{IReactorCore.addSystemEventTrigger} should accept the C{'before'}
|
| - phase and not call the given object until the right event is fired.
|
| - """
|
| - self._addSystemEventTriggerTest('before')
|
| -
|
| -
|
| - def test_duringPhase(self):
|
| - """
|
| - L{IReactorCore.addSystemEventTrigger} should accept the C{'during'}
|
| - phase and not call the given object until the right event is fired.
|
| - """
|
| - self._addSystemEventTriggerTest('during')
|
| -
|
| -
|
| - def test_afterPhase(self):
|
| - """
|
| - L{IReactorCore.addSystemEventTrigger} should accept the C{'after'}
|
| - phase and not call the given object until the right event is fired.
|
| - """
|
| - self._addSystemEventTriggerTest('after')
|
| -
|
| -
|
| - def test_unknownPhase(self):
|
| - """
|
| - L{IReactorCore.addSystemEventTrigger} should reject phases other than
|
| - C{'before'}, C{'during'}, or C{'after'}.
|
| - """
|
| - eventType = 'test'
|
| - self.assertRaises(
|
| - KeyError, self.addTrigger, 'xxx', eventType, lambda: None)
|
| -
|
| -
|
| - def test_beforePreceedsDuring(self):
|
| - """
|
| - L{IReactorCore.addSystemEventTrigger} should call triggers added to the
|
| - C{'before'} phase before it calls triggers added to the C{'during'}
|
| - phase.
|
| - """
|
| - eventType = 'test'
|
| - events = []
|
| - def beforeTrigger():
|
| - events.append('before')
|
| - def duringTrigger():
|
| - events.append('during')
|
| - self.addTrigger('before', eventType, beforeTrigger)
|
| - self.addTrigger('during', eventType, duringTrigger)
|
| - self.assertEqual(events, [])
|
| - reactor.fireSystemEvent(eventType)
|
| - self.assertEqual(events, ['before', 'during'])
|
| -
|
| -
|
| - def test_duringPreceedsAfter(self):
|
| - """
|
| - L{IReactorCore.addSystemEventTrigger} should call triggers added to the
|
| - C{'during'} phase before it calls triggers added to the C{'after'}
|
| - phase.
|
| - """
|
| - eventType = 'test'
|
| - events = []
|
| - def duringTrigger():
|
| - events.append('during')
|
| - def afterTrigger():
|
| - events.append('after')
|
| - self.addTrigger('during', eventType, duringTrigger)
|
| - self.addTrigger('after', eventType, afterTrigger)
|
| - self.assertEqual(events, [])
|
| - reactor.fireSystemEvent(eventType)
|
| - self.assertEqual(events, ['during', 'after'])
|
| -
|
| -
|
| - def test_beforeReturnsDeferred(self):
|
| - """
|
| - If a trigger added to the C{'before'} phase of an event returns a
|
| - L{Deferred}, the C{'during'} phase should be delayed until it is called
|
| - back.
|
| - """
|
| - triggerDeferred = Deferred()
|
| - eventType = 'test'
|
| - events = []
|
| - def beforeTrigger():
|
| - return triggerDeferred
|
| - def duringTrigger():
|
| - events.append('during')
|
| - self.addTrigger('before', eventType, beforeTrigger)
|
| - self.addTrigger('during', eventType, duringTrigger)
|
| - self.assertEqual(events, [])
|
| - reactor.fireSystemEvent(eventType)
|
| - self.assertEqual(events, [])
|
| - triggerDeferred.callback(None)
|
| - self.assertEqual(events, ['during'])
|
| -
|
| -
|
| - def test_multipleBeforeReturnDeferred(self):
|
| - """
|
| - If more than one trigger added to the C{'before'} phase of an event
|
| - return L{Deferred}s, the C{'during'} phase should be delayed until they
|
| - are all called back.
|
| - """
|
| - firstDeferred = Deferred()
|
| - secondDeferred = Deferred()
|
| - eventType = 'test'
|
| - events = []
|
| - def firstBeforeTrigger():
|
| - return firstDeferred
|
| - def secondBeforeTrigger():
|
| - return secondDeferred
|
| - def duringTrigger():
|
| - events.append('during')
|
| - self.addTrigger('before', eventType, firstBeforeTrigger)
|
| - self.addTrigger('before', eventType, secondBeforeTrigger)
|
| - self.addTrigger('during', eventType, duringTrigger)
|
| - self.assertEqual(events, [])
|
| - reactor.fireSystemEvent(eventType)
|
| - self.assertEqual(events, [])
|
| - firstDeferred.callback(None)
|
| - self.assertEqual(events, [])
|
| - secondDeferred.callback(None)
|
| - self.assertEqual(events, ['during'])
|
| -
|
| -
|
| - def test_subsequentBeforeTriggerFiresPriorBeforeDeferred(self):
|
| - """
|
| - If a trigger added to the C{'before'} phase of an event calls back a
|
| - L{Deferred} returned by an earlier trigger in the C{'before'} phase of
|
| - the same event, the remaining C{'before'} triggers for that event
|
| - should be run and any further L{Deferred}s waited on before proceeding
|
| - to the C{'during'} events.
|
| - """
|
| - eventType = 'test'
|
| - events = []
|
| - firstDeferred = Deferred()
|
| - secondDeferred = Deferred()
|
| - def firstBeforeTrigger():
|
| - return firstDeferred
|
| - def secondBeforeTrigger():
|
| - firstDeferred.callback(None)
|
| - def thirdBeforeTrigger():
|
| - events.append('before')
|
| - return secondDeferred
|
| - def duringTrigger():
|
| - events.append('during')
|
| - self.addTrigger('before', eventType, firstBeforeTrigger)
|
| - self.addTrigger('before', eventType, secondBeforeTrigger)
|
| - self.addTrigger('before', eventType, thirdBeforeTrigger)
|
| - self.addTrigger('during', eventType, duringTrigger)
|
| - self.assertEqual(events, [])
|
| - reactor.fireSystemEvent(eventType)
|
| - self.assertEqual(events, ['before'])
|
| - secondDeferred.callback(None)
|
| - self.assertEqual(events, ['before', 'during'])
|
| -
|
| -
|
| - def test_removeSystemEventTrigger(self):
|
| - """
|
| - A trigger removed with L{IReactorCore.removeSystemEventTrigger} should
|
| - not be called when the event fires.
|
| - """
|
| - eventType = 'test'
|
| - events = []
|
| - def firstBeforeTrigger():
|
| - events.append('first')
|
| - def secondBeforeTrigger():
|
| - events.append('second')
|
| - self.addTrigger('before', eventType, firstBeforeTrigger)
|
| - self.removeTrigger(
|
| - self.addTrigger('before', eventType, secondBeforeTrigger))
|
| - self.assertEqual(events, [])
|
| - reactor.fireSystemEvent(eventType)
|
| - self.assertEqual(events, ['first'])
|
| -
|
| -
|
| - def test_removeNonExistentSystemEventTrigger(self):
|
| - """
|
| - Passing an object to L{IReactorCore.removeSystemEventTrigger} which was
|
| - not returned by a previous call to
|
| - L{IReactorCore.addSystemEventTrigger} or which has already been passed
|
| - to C{removeSystemEventTrigger} should result in L{TypeError},
|
| - L{KeyError}, or L{ValueError} being raised.
|
| - """
|
| - b = self.addTrigger('during', 'test', lambda: None)
|
| - self.removeTrigger(b)
|
| - self.assertRaises(
|
| - TypeError, reactor.removeSystemEventTrigger, None)
|
| - self.assertRaises(
|
| - ValueError, reactor.removeSystemEventTrigger, b)
|
| - self.assertRaises(
|
| - KeyError,
|
| - reactor.removeSystemEventTrigger,
|
| - (b[0], ('xxx',) + b[1][1:]))
|
| -
|
| -
|
| - def test_interactionBetweenDifferentEvents(self):
|
| - """
|
| - L{IReactorCore.fireSystemEvent} should behave the same way for a
|
| - particular system event regardless of whether Deferreds are being
|
| - waited on for a different system event.
|
| - """
|
| - events = []
|
| -
|
| - firstEvent = 'first-event'
|
| - firstDeferred = Deferred()
|
| - def beforeFirstEvent():
|
| - events.append(('before', 'first'))
|
| - return firstDeferred
|
| - def afterFirstEvent():
|
| - events.append(('after', 'first'))
|
| -
|
| - secondEvent = 'second-event'
|
| - secondDeferred = Deferred()
|
| - def beforeSecondEvent():
|
| - events.append(('before', 'second'))
|
| - return secondDeferred
|
| - def afterSecondEvent():
|
| - events.append(('after', 'second'))
|
| -
|
| - self.addTrigger('before', firstEvent, beforeFirstEvent)
|
| - self.addTrigger('after', firstEvent, afterFirstEvent)
|
| - self.addTrigger('before', secondEvent, beforeSecondEvent)
|
| - self.addTrigger('after', secondEvent, afterSecondEvent)
|
| -
|
| - self.assertEqual(events, [])
|
| -
|
| - # After this, firstEvent should be stuck before 'during' waiting for
|
| - # firstDeferred.
|
| - reactor.fireSystemEvent(firstEvent)
|
| - self.assertEqual(events, [('before', 'first')])
|
| -
|
| - # After this, secondEvent should be stuck before 'during' waiting for
|
| - # secondDeferred.
|
| - reactor.fireSystemEvent(secondEvent)
|
| - self.assertEqual(events, [('before', 'first'), ('before', 'second')])
|
| -
|
| - # After this, firstEvent should have finished completely, but
|
| - # secondEvent should be at the same place.
|
| - firstDeferred.callback(None)
|
| - self.assertEqual(events, [('before', 'first'), ('before', 'second'),
|
| - ('after', 'first')])
|
| -
|
| - # After this, secondEvent should have finished completely.
|
| - secondDeferred.callback(None)
|
| - self.assertEqual(events, [('before', 'first'), ('before', 'second'),
|
| - ('after', 'first'), ('after', 'second')])
|
| -
|
| -
|
| -
|
| -class TimeTestCase(unittest.TestCase):
|
| - """
|
| - Tests for the IReactorTime part of the reactor.
|
| - """
|
| -
|
| -
|
| - def test_seconds(self):
|
| - """
|
| - L{twisted.internet.reactor.seconds} should return something
|
| - like a number.
|
| -
|
| - 1. This test specifically does not assert any relation to the
|
| - "system time" as returned by L{time.time} or
|
| - L{twisted.python.runtime.seconds}, because at some point we
|
| - may find a better option for scheduling calls than
|
| - wallclock-time.
|
| - 2. This test *also* does not assert anything about the type of
|
| - the result, because operations may not return ints or
|
| - floats: For example, datetime-datetime == timedelta(0).
|
| - """
|
| - now = reactor.seconds()
|
| - self.assertEquals(now-now+now, now)
|
| -
|
| -
|
| - def test_callLaterUsesReactorSecondsInDelayedCall(self):
|
| - """
|
| - L{reactor.callLater} should use the reactor's seconds factory
|
| - to produce the time at which the DelayedCall will be called.
|
| - """
|
| - oseconds = reactor.seconds
|
| - reactor.seconds = lambda: 100
|
| - try:
|
| - call = reactor.callLater(5, lambda: None)
|
| - self.assertEquals(call.getTime(), 105)
|
| - finally:
|
| - reactor.seconds = oseconds
|
| -
|
| -
|
| - def test_callLaterUsesReactorSecondsAsDelayedCallSecondsFactory(self):
|
| - """
|
| - L{reactor.callLater} should propagate its own seconds factory
|
| - to the DelayedCall to use as its own seconds factory.
|
| - """
|
| - oseconds = reactor.seconds
|
| - reactor.seconds = lambda: 100
|
| - try:
|
| - call = reactor.callLater(5, lambda: None)
|
| - self.assertEquals(call.seconds(), 100)
|
| - finally:
|
| - reactor.seconds = oseconds
|
| -
|
| -
|
| - def test_callLater(self):
|
| - """
|
| - Test that a DelayedCall really calls the function it is
|
| - supposed to call.
|
| - """
|
| - d = Deferred()
|
| - reactor.callLater(0, d.callback, None)
|
| - d.addCallback(self.assertEqual, None)
|
| - return d
|
| -
|
| -
|
| - def test_cancelDelayedCall(self):
|
| - """
|
| - Test that when a DelayedCall is cancelled it does not run.
|
| - """
|
| - called = []
|
| - def function():
|
| - called.append(None)
|
| - call = reactor.callLater(0, function)
|
| - call.cancel()
|
| -
|
| - # Schedule a call in two "iterations" to check to make sure that the
|
| - # above call never ran.
|
| - d = Deferred()
|
| - def check():
|
| - try:
|
| - self.assertEqual(called, [])
|
| - except:
|
| - d.errback()
|
| - else:
|
| - d.callback(None)
|
| - reactor.callLater(0, reactor.callLater, 0, check)
|
| - return d
|
| -
|
| -
|
| - def test_cancelCancelledDelayedCall(self):
|
| - """
|
| - Test that cancelling a DelayedCall which has already been cancelled
|
| - raises the appropriate exception.
|
| - """
|
| - call = reactor.callLater(0, lambda: None)
|
| - call.cancel()
|
| - self.assertRaises(error.AlreadyCancelled, call.cancel)
|
| -
|
| -
|
| - def test_cancelCalledDelayedCallSynchronous(self):
|
| - """
|
| - Test that cancelling a DelayedCall in the DelayedCall's function as
|
| - that function is being invoked by the DelayedCall raises the
|
| - appropriate exception.
|
| - """
|
| - d = Deferred()
|
| - def later():
|
| - try:
|
| - self.assertRaises(error.AlreadyCalled, call.cancel)
|
| - except:
|
| - d.errback()
|
| - else:
|
| - d.callback(None)
|
| - call = reactor.callLater(0, later)
|
| - return d
|
| -
|
| -
|
| - def test_cancelCalledDelayedCallAsynchronous(self):
|
| - """
|
| - Test that cancelling a DelayedCall after it has run its function
|
| - raises the appropriate exception.
|
| - """
|
| - d = Deferred()
|
| - def check():
|
| - try:
|
| - self.assertRaises(error.AlreadyCalled, call.cancel)
|
| - except:
|
| - d.errback()
|
| - else:
|
| - d.callback(None)
|
| - def later():
|
| - reactor.callLater(0, check)
|
| - call = reactor.callLater(0, later)
|
| - return d
|
| -
|
| -
|
| - def testCallLaterDelayAndReset(self):
|
| - """
|
| - Test that the reactor handles DelayedCalls which have been
|
| - reset or delayed.
|
| - """
|
| - clock = Clock()
|
| - clock.install()
|
| - try:
|
| - callbackTimes = [None, None]
|
| -
|
| - def resetCallback():
|
| - callbackTimes[0] = clock()
|
| -
|
| - def delayCallback():
|
| - callbackTimes[1] = clock()
|
| -
|
| - ireset = reactor.callLater(2, resetCallback)
|
| - idelay = reactor.callLater(3, delayCallback)
|
| -
|
| - clock.pump(reactor, [0, 1])
|
| -
|
| - self.assertIdentical(callbackTimes[0], None)
|
| - self.assertIdentical(callbackTimes[1], None)
|
| -
|
| - ireset.reset(2) # (now)1 + 2 = 3
|
| - idelay.delay(3) # (orig)3 + 3 = 6
|
| -
|
| - clock.pump(reactor, [0, 1])
|
| -
|
| - self.assertIdentical(callbackTimes[0], None)
|
| - self.assertIdentical(callbackTimes[1], None)
|
| -
|
| - clock.pump(reactor, [0, 1])
|
| -
|
| - self.assertEquals(callbackTimes[0], 3)
|
| - self.assertEquals(callbackTimes[1], None)
|
| -
|
| - clock.pump(reactor, [0, 3])
|
| - self.assertEquals(callbackTimes[1], 6)
|
| - finally:
|
| - clock.uninstall()
|
| -
|
| -
|
| - def testCallLaterTime(self):
|
| - d = reactor.callLater(10, lambda: None)
|
| - try:
|
| - self.failUnless(d.getTime() - (time.time() + 10) < 1)
|
| - finally:
|
| - d.cancel()
|
| -
|
| - def testCallInNextIteration(self):
|
| - calls = []
|
| - def f1():
|
| - calls.append('f1')
|
| - reactor.callLater(0.0, f2)
|
| - def f2():
|
| - calls.append('f2')
|
| - reactor.callLater(0.0, f3)
|
| - def f3():
|
| - calls.append('f3')
|
| -
|
| - reactor.callLater(0, f1)
|
| - self.assertEquals(calls, [])
|
| - reactor.iterate()
|
| - self.assertEquals(calls, ['f1'])
|
| - reactor.iterate()
|
| - self.assertEquals(calls, ['f1', 'f2'])
|
| - reactor.iterate()
|
| - self.assertEquals(calls, ['f1', 'f2', 'f3'])
|
| -
|
| - def testCallLaterOrder(self):
|
| - l = []
|
| - l2 = []
|
| - def f(x):
|
| - l.append(x)
|
| - def f2(x):
|
| - l2.append(x)
|
| - def done():
|
| - self.assertEquals(l, range(20))
|
| - def done2():
|
| - self.assertEquals(l2, range(10))
|
| -
|
| - for n in range(10):
|
| - reactor.callLater(0, f, n)
|
| - for n in range(10):
|
| - reactor.callLater(0, f, n+10)
|
| - reactor.callLater(0.1, f2, n)
|
| -
|
| - reactor.callLater(0, done)
|
| - reactor.callLater(0.1, done2)
|
| - d = Deferred()
|
| - reactor.callLater(0.2, d.callback, None)
|
| - return d
|
| -
|
| - testCallLaterOrder.todo = "See bug 1396"
|
| - testCallLaterOrder.skip = "Trial bug, todo doesn't work! See bug 1397"
|
| - def testCallLaterOrder2(self):
|
| - # This time destroy the clock resolution so that it fails reliably
|
| - # even on systems that don't have a crappy clock resolution.
|
| -
|
| - def seconds():
|
| - return int(time.time())
|
| -
|
| - base_original = base.seconds
|
| - runtime_original = runtime.seconds
|
| - base.seconds = seconds
|
| - runtime.seconds = seconds
|
| -
|
| - def cleanup(x):
|
| - runtime.seconds = runtime_original
|
| - base.seconds = base_original
|
| - return x
|
| - return maybeDeferred(self.testCallLaterOrder).addBoth(cleanup)
|
| -
|
| - testCallLaterOrder2.todo = "See bug 1396"
|
| - testCallLaterOrder2.skip = "Trial bug, todo doesn't work! See bug 1397"
|
| -
|
| - def testDelayedCallStringification(self):
|
| - # Mostly just make sure str() isn't going to raise anything for
|
| - # DelayedCalls within reason.
|
| - dc = reactor.callLater(0, lambda x, y: None, 'x', y=10)
|
| - str(dc)
|
| - dc.reset(5)
|
| - str(dc)
|
| - dc.cancel()
|
| - str(dc)
|
| -
|
| - dc = reactor.callLater(0, lambda: None, x=[({'hello': u'world'}, 10j), reactor], *range(10))
|
| - str(dc)
|
| - dc.cancel()
|
| - str(dc)
|
| -
|
| - def calledBack(ignored):
|
| - str(dc)
|
| - d = Deferred().addCallback(calledBack)
|
| - dc = reactor.callLater(0, d.callback, None)
|
| - str(dc)
|
| - return d
|
| -
|
| -
|
| - def testDelayedCallSecondsOverride(self):
|
| - """
|
| - Test that the C{seconds} argument to DelayedCall gets used instead of
|
| - the default timing function, if it is not None.
|
| - """
|
| - def seconds():
|
| - return 10
|
| - dc = base.DelayedCall(5, lambda: None, (), {}, lambda dc: None,
|
| - lambda dc: None, seconds)
|
| - self.assertEquals(dc.getTime(), 5)
|
| - dc.reset(3)
|
| - self.assertEquals(dc.getTime(), 13)
|
| -
|
| -
|
| -class CallFromThreadTests(unittest.TestCase):
|
| - def testWakeUp(self):
|
| - # Make sure other threads can wake up the reactor
|
| - d = Deferred()
|
| - def wake():
|
| - time.sleep(0.1)
|
| - # callFromThread will call wakeUp for us
|
| - reactor.callFromThread(d.callback, None)
|
| - reactor.callInThread(wake)
|
| - return d
|
| -
|
| - if interfaces.IReactorThreads(reactor, None) is None:
|
| - testWakeUp.skip = "Nothing to wake up for without thread support"
|
| -
|
| - def _stopCallFromThreadCallback(self):
|
| - self.stopped = True
|
| -
|
| - def _callFromThreadCallback(self, d):
|
| - reactor.callFromThread(self._callFromThreadCallback2, d)
|
| - reactor.callLater(0, self._stopCallFromThreadCallback)
|
| -
|
| - def _callFromThreadCallback2(self, d):
|
| - try:
|
| - self.assert_(self.stopped)
|
| - except:
|
| - # Send the error to the deferred
|
| - d.errback()
|
| - else:
|
| - d.callback(None)
|
| -
|
| - def testCallFromThreadStops(self):
|
| - """
|
| - Ensure that callFromThread from inside a callFromThread
|
| - callback doesn't sit in an infinite loop and lets other
|
| - things happen too.
|
| - """
|
| - self.stopped = False
|
| - d = defer.Deferred()
|
| - reactor.callFromThread(self._callFromThreadCallback, d)
|
| - return d
|
| -
|
| -
|
| -
|
| -class DummyReactor(base.ReactorBase):
|
| - """
|
| - A reactor faking the methods needed to make it starts.
|
| - """
|
| -
|
| - def __init__(self, clock):
|
| - """
|
| - @param clock: the clock used to fake time.
|
| - @type clock: C{task.Clock}.
|
| - """
|
| - base.ReactorBase.__init__(self)
|
| - self.clock = clock
|
| -
|
| -
|
| - def installWaker(self):
|
| - """
|
| - Called by C{self._initThreads}: no waker is needed for the tests.
|
| - """
|
| -
|
| -
|
| - def callLater(self, _seconds, _f, *args, **kw):
|
| - """
|
| - Override callLater using the internal clock.
|
| - """
|
| - return self.clock.callLater( _seconds, _f, *args, **kw)
|
| -
|
| -
|
| - def removeAll(self):
|
| - """
|
| - Needed during stop.
|
| - """
|
| - return []
|
| -
|
| -
|
| -
|
| -class ReactorBaseTestCase(unittest.TestCase):
|
| - """
|
| - Tests for L{base.ReactorBase} object.
|
| - """
|
| -
|
| - def setUp(self):
|
| - """
|
| - Create a clock and a L{DummyReactor}.
|
| - """
|
| - self.clock = task.Clock()
|
| - self.reactor = DummyReactor(self.clock)
|
| -
|
| -
|
| - def test_stopWhenNotStarted(self):
|
| - """
|
| - Test that the reactor stop raises an error when the reactor is not
|
| - started.
|
| - """
|
| - self.assertRaises(RuntimeError, self.reactor.stop)
|
| -
|
| -
|
| - def test_stopWhenAlreadyStopped(self):
|
| - """
|
| - Test that the reactor stop raises an error when the reactor is already
|
| - stopped.
|
| - """
|
| - self.reactor.startRunning()
|
| - self.reactor.stop()
|
| - self.assertRaises(RuntimeError, self.reactor.stop)
|
| -
|
| -
|
| - def test_stopShutDownEvents(self):
|
| - """
|
| - Verify that reactor.stop fires shutdown events.
|
| - """
|
| - events = []
|
| - self.reactor.addSystemEventTrigger(
|
| - "before", "shutdown",
|
| - lambda: events.append(("before", "shutdown")))
|
| - self.reactor.addSystemEventTrigger(
|
| - "during", "shutdown",
|
| - lambda: events.append(("during", "shutdown")))
|
| - self.reactor.startRunning()
|
| - self.reactor.stop()
|
| -
|
| - # Simulate the mainloop spinning a little bit. Do this to allow
|
| - # reactor.stop() to schedule the shutdown event to be fired as opposed
|
| - # to assuming reactor.stop() will fire the shutdown event before
|
| - # returning.
|
| -
|
| - # Generally, randomly scheduling things to happen instead of doing them
|
| - # synchronously is wrong. However, this is finicky functionality which
|
| - # was always poorly specified and was implemented such that most times
|
| - # the shutdown event was fired asynchronously. If you're implementing
|
| - # a new API, don't look at this advance(0) and think it's great and
|
| - # copy it.
|
| -
|
| - # See #3168, #3146, and #3198.
|
| - self.reactor.clock.advance(0)
|
| -
|
| - self.assertEquals(events, [("before", "shutdown"),
|
| - ("during", "shutdown")])
|
| -
|
| -
|
| - def test_multipleRun(self):
|
| - """
|
| - Verify that the reactor.startRunning raises an error when called
|
| - multiple times.
|
| - """
|
| - self.reactor.startRunning()
|
| - self.assertWarns(DeprecationWarning,
|
| - "Reactor already running! This behavior is deprecated since "
|
| - "Twisted 8.0",
|
| - __file__,
|
| - self.reactor.startRunning)
|
| -
|
| -
|
| - def test_crash(self):
|
| - """
|
| - reactor.crash should NOT fire shutdown triggers.
|
| - """
|
| - events = []
|
| - self.reactor.addSystemEventTrigger(
|
| - "before", "shutdown",
|
| - lambda: events.append(("before", "shutdown")))
|
| -
|
| - self.reactor.callWhenRunning(
|
| - self.reactor.callLater, 0, self.reactor.crash)
|
| - self.reactor.startRunning()
|
| - self.clock.advance(0.1)
|
| - self.failIf(events, "reactor.crash invoked shutdown triggers, but it "
|
| - "isn't supposed to.")
|
| -
|
| -
|
| -
|
| -class ReactorCoreTestCase(unittest.TestCase):
|
| - """
|
| - Test core functionalities of the reactor.
|
| - """
|
| -
|
| - def test_run(self):
|
| - """
|
| - Test that reactor.crash terminates reactor.run
|
| - """
|
| - for i in xrange(3):
|
| - reactor.callLater(0.01, reactor.crash)
|
| - reactor.run()
|
| -
|
| -
|
| - def test_iterate(self):
|
| - """
|
| - Test that reactor.iterate(0) doesn't block
|
| - """
|
| - start = time.time()
|
| - # twisted timers are distinct from the underlying event loop's
|
| - # timers, so this fail-safe probably won't keep a failure from
|
| - # hanging the test
|
| - t = reactor.callLater(10, reactor.crash)
|
| - reactor.iterate(0) # shouldn't block
|
| - stop = time.time()
|
| - elapsed = stop - start
|
| - self.failUnless(elapsed < 8)
|
| - t.cancel()
|
| -
|
| -
|
| -
|
| -class ReactorFDTestCase(unittest.TestCase):
|
| - """
|
| - Tests for L{interfaces.IReactorFDSet}.
|
| - """
|
| -
|
| - def test_getReaders(self):
|
| - """
|
| - Check that L{interfaces.IReactorFDSet.getReaders} reflects the actions
|
| - made with L{interfaces.IReactorFDSet.addReader} and
|
| - L{interfaces.IReactorFDSet.removeReader}.
|
| - """
|
| - s = socket.socket()
|
| - self.addCleanup(s.close)
|
| -
|
| - c = Connection(s, protocol.Protocol())
|
| - self.assertNotIn(c, reactor.getReaders())
|
| -
|
| - reactor.addReader(c)
|
| - self.assertIn(c, reactor.getReaders())
|
| -
|
| - reactor.removeReader(c)
|
| - self.assertNotIn(c, reactor.getReaders())
|
| -
|
| -
|
| - def test_getWriters(self):
|
| - """
|
| - Check that L{interfaces.IReactorFDSet.getWriters} reflects the actions
|
| - made with L{interfaces.IReactorFDSet.addWriter} and
|
| - L{interfaces.IReactorFDSet.removeWriter}.
|
| - """
|
| - s = socket.socket()
|
| - self.addCleanup(s.close)
|
| -
|
| - c = Connection(s, protocol.Protocol())
|
| - self.assertNotIn(c, reactor.getWriters())
|
| -
|
| - reactor.addWriter(c)
|
| - self.assertIn(c, reactor.getWriters())
|
| -
|
| - reactor.removeWriter(c)
|
| - self.assertNotIn(c, reactor.getWriters())
|
| -
|
| -if not interfaces.IReactorFDSet.providedBy(reactor):
|
| - ReactorFDTestCase.skip = "Reactor not providing IReactorFDSet"
|
| -
|
| -
|
| -
|
| -class DelayedTestCase(unittest.TestCase):
|
| - def setUp(self):
|
| - self.finished = 0
|
| - self.counter = 0
|
| - self.timers = {}
|
| - self.deferred = defer.Deferred()
|
| - # ick. Sometimes there are magic timers already running:
|
| - # popsicle.Freezer.tick . Kill off all such timers now so they won't
|
| - # interfere with the test. Of course, this kind of requires that
|
| - # getDelayedCalls already works, so certain failure modes won't be
|
| - # noticed.
|
| - if not hasattr(reactor, "getDelayedCalls"):
|
| - return
|
| - for t in reactor.getDelayedCalls():
|
| - t.cancel()
|
| - reactor.iterate() # flush timers
|
| -
|
| - def tearDown(self):
|
| - for t in self.timers.values():
|
| - t.cancel()
|
| -
|
| - def checkTimers(self):
|
| - l1 = self.timers.values()
|
| - l2 = list(reactor.getDelayedCalls())
|
| -
|
| - # There should be at least the calls we put in. There may be other
|
| - # calls that are none of our business and that we should ignore,
|
| - # though.
|
| -
|
| - missing = []
|
| - for dc in l1:
|
| - if dc not in l2:
|
| - missing.append(dc)
|
| - if missing:
|
| - self.finished = 1
|
| - self.failIf(missing, "Should have been missing no calls, instead was missing " + repr(missing))
|
| -
|
| - def callback(self, tag):
|
| - del self.timers[tag]
|
| - self.checkTimers()
|
| -
|
| - def addCallback(self, tag):
|
| - self.callback(tag)
|
| - self.addTimer(15, self.callback)
|
| -
|
| - def done(self, tag):
|
| - self.finished = 1
|
| - self.callback(tag)
|
| - self.deferred.callback(None)
|
| -
|
| - def addTimer(self, when, callback):
|
| - self.timers[self.counter] = reactor.callLater(when * 0.01, callback,
|
| - self.counter)
|
| - self.counter += 1
|
| - self.checkTimers()
|
| -
|
| - def testGetDelayedCalls(self):
|
| - if not hasattr(reactor, "getDelayedCalls"):
|
| - return
|
| - # This is not a race because we don't do anything which might call
|
| - # the reactor until we have all the timers set up. If we did, this
|
| - # test might fail on slow systems.
|
| - self.checkTimers()
|
| - self.addTimer(35, self.done)
|
| - self.addTimer(20, self.callback)
|
| - self.addTimer(30, self.callback)
|
| - which = self.counter
|
| - self.addTimer(29, self.callback)
|
| - self.addTimer(25, self.addCallback)
|
| - self.addTimer(26, self.callback)
|
| -
|
| - self.timers[which].cancel()
|
| - del self.timers[which]
|
| - self.checkTimers()
|
| -
|
| - self.deferred.addCallback(lambda x : self.checkTimers())
|
| - return self.deferred
|
| -
|
| - def testActive(self):
|
| - dcall = reactor.callLater(0, lambda: None)
|
| - self.assertEquals(dcall.active(), 1)
|
| - reactor.iterate()
|
| - self.assertEquals(dcall.active(), 0)
|
| -
|
| -resolve_helper = """
|
| -import %(reactor)s
|
| -%(reactor)s.install()
|
| -from twisted.internet import reactor
|
| -
|
| -class Foo:
|
| - def __init__(self):
|
| - reactor.callWhenRunning(self.start)
|
| - self.timer = reactor.callLater(3, self.failed)
|
| - def start(self):
|
| - reactor.resolve('localhost').addBoth(self.done)
|
| - def done(self, res):
|
| - print 'done', res
|
| - reactor.stop()
|
| - def failed(self):
|
| - print 'failed'
|
| - self.timer = None
|
| - reactor.stop()
|
| -f = Foo()
|
| -reactor.run()
|
| -"""
|
| -
|
| -class ChildResolveProtocol(protocol.ProcessProtocol):
|
| - def __init__(self, onCompletion):
|
| - self.onCompletion = onCompletion
|
| -
|
| - def connectionMade(self):
|
| - self.output = []
|
| - self.error = []
|
| -
|
| - def outReceived(self, out):
|
| - self.output.append(out)
|
| -
|
| - def errReceived(self, err):
|
| - self.error.append(err)
|
| -
|
| - def processEnded(self, reason):
|
| - self.onCompletion.callback((reason, self.output, self.error))
|
| - self.onCompletion = None
|
| -
|
| -
|
| -class Resolve(unittest.TestCase):
|
| - def testChildResolve(self):
|
| - # I've seen problems with reactor.run under gtk2reactor. Spawn a
|
| - # child which just does reactor.resolve after the reactor has
|
| - # started, fail if it does not complete in a timely fashion.
|
| - helperPath = os.path.abspath(self.mktemp())
|
| - helperFile = open(helperPath, 'w')
|
| -
|
| - # Eeueuuggg
|
| - reactorName = reactor.__module__
|
| -
|
| - helperFile.write(resolve_helper % {'reactor': reactorName})
|
| - helperFile.close()
|
| -
|
| - env = os.environ.copy()
|
| - env['PYTHONPATH'] = os.pathsep.join(sys.path)
|
| -
|
| - helperDeferred = Deferred()
|
| - helperProto = ChildResolveProtocol(helperDeferred)
|
| -
|
| - reactor.spawnProcess(helperProto, sys.executable, ("python", "-u", helperPath), env)
|
| -
|
| - def cbFinished((reason, output, error)):
|
| - # If the output is "done 127.0.0.1\n" we don't really care what
|
| - # else happened.
|
| - output = ''.join(output)
|
| - if output != 'done 127.0.0.1\n':
|
| - self.fail((
|
| - "The child process failed to produce the desired results:\n"
|
| - " Reason for termination was: %r\n"
|
| - " Output stream was: %r\n"
|
| - " Error stream was: %r\n") % (reason.getErrorMessage(), output, ''.join(error)))
|
| -
|
| - helperDeferred.addCallback(cbFinished)
|
| - return helperDeferred
|
| -
|
| -if not interfaces.IReactorProcess(reactor, None):
|
| - Resolve.skip = "cannot run test: reactor doesn't support IReactorProcess"
|
| -
|
| -class Counter:
|
| - index = 0
|
| -
|
| - def add(self):
|
| - self.index = self.index + 1
|
| -
|
| -
|
| -class Order:
|
| -
|
| - stage = 0
|
| -
|
| - def a(self):
|
| - if self.stage != 0: raise RuntimeError
|
| - self.stage = 1
|
| -
|
| - def b(self):
|
| - if self.stage != 1: raise RuntimeError
|
| - self.stage = 2
|
| -
|
| - def c(self):
|
| - if self.stage != 2: raise RuntimeError
|
| - self.stage = 3
|
| -
|
| -
|
| -class CallFromThreadTestCase(unittest.TestCase):
|
| - """Task scheduling from threads tests."""
|
| -
|
| - if interfaces.IReactorThreads(reactor, None) is None:
|
| - skip = "Nothing to test without thread support"
|
| -
|
| - def schedule(self, *args, **kwargs):
|
| - """Override in subclasses."""
|
| - reactor.callFromThread(*args, **kwargs)
|
| -
|
| - def testScheduling(self):
|
| - c = Counter()
|
| - for i in range(100):
|
| - self.schedule(c.add)
|
| - for i in range(100):
|
| - reactor.iterate()
|
| - self.assertEquals(c.index, 100)
|
| -
|
| - def testCorrectOrder(self):
|
| - o = Order()
|
| - self.schedule(o.a)
|
| - self.schedule(o.b)
|
| - self.schedule(o.c)
|
| - reactor.iterate()
|
| - reactor.iterate()
|
| - reactor.iterate()
|
| - self.assertEquals(o.stage, 3)
|
| -
|
| - def testNotRunAtOnce(self):
|
| - c = Counter()
|
| - self.schedule(c.add)
|
| - # scheduled tasks should not be run at once:
|
| - self.assertEquals(c.index, 0)
|
| - reactor.iterate()
|
| - self.assertEquals(c.index, 1)
|
| -
|
| -
|
| -class MyProtocol(protocol.Protocol):
|
| - """Sample protocol."""
|
| -
|
| -class MyFactory(protocol.Factory):
|
| - """Sample factory."""
|
| -
|
| - protocol = MyProtocol
|
| -
|
| -
|
| -class ProtocolTestCase(unittest.TestCase):
|
| -
|
| - def testFactory(self):
|
| - factory = MyFactory()
|
| - protocol = factory.buildProtocol(None)
|
| - self.assertEquals(protocol.factory, factory)
|
| - self.assert_( isinstance(protocol, factory.protocol) )
|
| -
|
| -
|
| -class DummyProducer(object):
|
| - """
|
| - Very uninteresting producer implementation used by tests to ensure the
|
| - right methods are called by the consumer with which it is registered.
|
| -
|
| - @type events: C{list} of C{str}
|
| - @ivar events: The producer/consumer related events which have happened to
|
| - this producer. Strings in this list may be C{'resume'}, C{'stop'}, or
|
| - C{'pause'}. Elements are added as they occur.
|
| - """
|
| -
|
| - def __init__(self):
|
| - self.events = []
|
| -
|
| -
|
| - def resumeProducing(self):
|
| - self.events.append('resume')
|
| -
|
| -
|
| - def stopProducing(self):
|
| - self.events.append('stop')
|
| -
|
| -
|
| - def pauseProducing(self):
|
| - self.events.append('pause')
|
| -
|
| -
|
| -
|
| -class SillyDescriptor(abstract.FileDescriptor):
|
| - """
|
| - A descriptor whose data buffer gets filled very fast.
|
| -
|
| - Useful for testing FileDescriptor's IConsumer interface, since
|
| - the data buffer fills as soon as at least four characters are
|
| - written to it, and gets emptied in a single doWrite() cycle.
|
| - """
|
| - bufferSize = 3
|
| - connected = True
|
| -
|
| - def writeSomeData(self, data):
|
| - """
|
| - Always write all data.
|
| - """
|
| - return len(data)
|
| -
|
| -
|
| - def startWriting(self):
|
| - """
|
| - Do nothing: bypass the reactor.
|
| - """
|
| - stopWriting = startWriting
|
| -
|
| -
|
| -
|
| -class ReentrantProducer(DummyProducer):
|
| - """
|
| - Similar to L{DummyProducer}, but with a resumeProducing method which calls
|
| - back into an L{IConsumer} method of the consumer against which it is
|
| - registered.
|
| -
|
| - @ivar consumer: The consumer with which this producer has been or will
|
| - be registered.
|
| -
|
| - @ivar methodName: The name of the method to call on the consumer inside
|
| - C{resumeProducing}.
|
| -
|
| - @ivar methodArgs: The arguments to pass to the consumer method invoked in
|
| - C{resumeProducing}.
|
| - """
|
| - def __init__(self, consumer, methodName, *methodArgs):
|
| - super(ReentrantProducer, self).__init__()
|
| - self.consumer = consumer
|
| - self.methodName = methodName
|
| - self.methodArgs = methodArgs
|
| -
|
| -
|
| - def resumeProducing(self):
|
| - super(ReentrantProducer, self).resumeProducing()
|
| - getattr(self.consumer, self.methodName)(*self.methodArgs)
|
| -
|
| -
|
| -
|
| -class TestProducer(unittest.TestCase):
|
| - """
|
| - Test abstract.FileDescriptor's consumer interface.
|
| - """
|
| - def test_doubleProducer(self):
|
| - """
|
| - Verify that registering a non-streaming producer invokes its
|
| - resumeProducing() method and that you can only register one producer
|
| - at a time.
|
| - """
|
| - fd = abstract.FileDescriptor()
|
| - fd.connected = 1
|
| - dp = DummyProducer()
|
| - fd.registerProducer(dp, 0)
|
| - self.assertEquals(dp.events, ['resume'])
|
| - self.assertRaises(RuntimeError, fd.registerProducer, DummyProducer(), 0)
|
| -
|
| -
|
| - def test_unconnectedFileDescriptor(self):
|
| - """
|
| - Verify that registering a producer when the connection has already
|
| - been closed invokes its stopProducing() method.
|
| - """
|
| - fd = abstract.FileDescriptor()
|
| - fd.disconnected = 1
|
| - dp = DummyProducer()
|
| - fd.registerProducer(dp, 0)
|
| - self.assertEquals(dp.events, ['stop'])
|
| -
|
| -
|
| - def _dontPausePullConsumerTest(self, methodName):
|
| - descriptor = SillyDescriptor()
|
| - producer = DummyProducer()
|
| - descriptor.registerProducer(producer, streaming=False)
|
| - self.assertEqual(producer.events, ['resume'])
|
| - del producer.events[:]
|
| -
|
| - # Fill up the descriptor's write buffer so we can observe whether or
|
| - # not it pauses its producer in that case.
|
| - getattr(descriptor, methodName)('1234')
|
| -
|
| - self.assertEqual(producer.events, [])
|
| -
|
| -
|
| - def test_dontPausePullConsumerOnWrite(self):
|
| - """
|
| - Verify that FileDescriptor does not call producer.pauseProducing() on a
|
| - non-streaming pull producer in response to a L{IConsumer.write} call
|
| - which results in a full write buffer. Issue #2286.
|
| - """
|
| - return self._dontPausePullConsumerTest('write')
|
| -
|
| -
|
| - def test_dontPausePullConsumerOnWriteSequence(self):
|
| - """
|
| - Like L{test_dontPausePullConsumerOnWrite}, but for a call to
|
| - C{writeSequence} rather than L{IConsumer.write}.
|
| -
|
| - C{writeSequence} is not part of L{IConsumer}, but
|
| - L{abstract.FileDescriptor} has supported consumery behavior in response
|
| - to calls to L{writeSequence} forever.
|
| - """
|
| - return self._dontPausePullConsumerTest('writeSequence')
|
| -
|
| -
|
| - def _reentrantStreamingProducerTest(self, methodName):
|
| - descriptor = SillyDescriptor()
|
| - producer = ReentrantProducer(descriptor, methodName, 'spam')
|
| - descriptor.registerProducer(producer, streaming=True)
|
| -
|
| - # Start things off by filling up the descriptor's buffer so it will
|
| - # pause its producer.
|
| - getattr(descriptor, methodName)('spam')
|
| -
|
| - # Sanity check - make sure that worked.
|
| - self.assertEqual(producer.events, ['pause'])
|
| - del producer.events[:]
|
| -
|
| - # After one call to doWrite, the buffer has been emptied so the
|
| - # FileDescriptor should resume its producer. That will result in an
|
| - # immediate call to FileDescriptor.write which will again fill the
|
| - # buffer and result in the producer being paused.
|
| - descriptor.doWrite()
|
| - self.assertEqual(producer.events, ['resume', 'pause'])
|
| - del producer.events[:]
|
| -
|
| - # After a second call to doWrite, the exact same thing should have
|
| - # happened. Prior to the bugfix for which this test was written,
|
| - # FileDescriptor would have incorrectly believed its producer was
|
| - # already resumed (it was paused) and so not resume it again.
|
| - descriptor.doWrite()
|
| - self.assertEqual(producer.events, ['resume', 'pause'])
|
| -
|
| -
|
| - def test_reentrantStreamingProducerUsingWrite(self):
|
| - """
|
| - Verify that FileDescriptor tracks producer's paused state correctly.
|
| - Issue #811, fixed in revision r12857.
|
| - """
|
| - return self._reentrantStreamingProducerTest('write')
|
| -
|
| -
|
| - def test_reentrantStreamingProducerUsingWriteSequence(self):
|
| - """
|
| - Like L{test_reentrantStreamingProducerUsingWrite}, but for calls to
|
| - C{writeSequence}.
|
| -
|
| - C{writeSequence} is B{not} part of L{IConsumer}, however
|
| - C{abstract.FileDescriptor} has supported consumery behavior in response
|
| - to calls to C{writeSequence} forever.
|
| - """
|
| - return self._reentrantStreamingProducerTest('writeSequence')
|
| -
|
| -
|
| -
|
| -class PortStringification(unittest.TestCase):
|
| - if interfaces.IReactorTCP(reactor, None) is not None:
|
| - def testTCP(self):
|
| - p = reactor.listenTCP(0, protocol.ServerFactory())
|
| - portNo = p.getHost().port
|
| - self.assertNotEqual(str(p).find(str(portNo)), -1,
|
| - "%d not found in %s" % (portNo, p))
|
| - return p.stopListening()
|
| -
|
| - if interfaces.IReactorUDP(reactor, None) is not None:
|
| - def testUDP(self):
|
| - p = reactor.listenUDP(0, protocol.DatagramProtocol())
|
| - portNo = p.getHost().port
|
| - self.assertNotEqual(str(p).find(str(portNo)), -1,
|
| - "%d not found in %s" % (portNo, p))
|
| - return p.stopListening()
|
| -
|
| - if interfaces.IReactorSSL(reactor, None) is not None and ssl:
|
| - def testSSL(self, ssl=ssl):
|
| - pem = util.sibpath(__file__, 'server.pem')
|
| - p = reactor.listenSSL(0, protocol.ServerFactory(), ssl.DefaultOpenSSLContextFactory(pem, pem))
|
| - portNo = p.getHost().port
|
| - self.assertNotEqual(str(p).find(str(portNo)), -1,
|
| - "%d not found in %s" % (portNo, p))
|
| - return p.stopListening()
|
|
|