def test__fire_propagates_error_from_hook(self): error = factory.make_exception() dhooks = DeferredHooks() d = Deferred() d.addCallback(lambda _: Failure(error)) dhooks.add(d) self.assertRaises(type(error), dhooks.fire)
def test__savepoint_saves_and_restores_hooks(self): d = Deferred() dhooks = DeferredHooks() dhooks.add(d) with dhooks.savepoint(): self.expectThat(list(dhooks.hooks), Equals([])) self.expectThat(list(dhooks.hooks), Equals([d]))
def test__fire_always_consumes_all_hooks(self): dhooks = DeferredHooks() d1, d2 = Deferred(), Deferred() d1.addCallback(lambda _: 0 / 0) # d1 will fail. dhooks.add(d1) dhooks.add(d2) self.assertRaises(ZeroDivisionError, dhooks.fire) self.assertThat(dhooks.hooks, HasLength(0)) self.assertThat(d1, IsFiredDeferred()) self.assertThat(d2, IsFiredDeferred())
def test__is_thread_local(self): dhooks = DeferredHooks() queues = [] for _ in range(3): thread = threading.Thread( target=lambda: queues.append(dhooks.hooks)) thread.start() thread.join() self.assertThat(queues, HasLength(3)) # Each queue is distinct (deque is unhashable; use the id() of each). self.assertThat(set(id(q) for q in queues), HasLength(3))
def test__savepoint_restores_hooks_with_new_hooks_on_clean_exit(self): d1 = Deferred() d2 = Deferred() dhooks = DeferredHooks() dhooks.add(d1) with dhooks.savepoint(): dhooks.add(d2) self.expectThat(list(dhooks.hooks), Equals([d2])) self.expectThat(list(dhooks.hooks), Equals([d1, d2]))
def test__fire_calls_hooks(self): dhooks = DeferredHooks() ds = Deferred(), Deferred() for d in ds: dhooks.add(d) dhooks.fire() for d in ds: self.assertIsNone(extract_result(d))
def test__reset_cancels_all_hooks(self): canceller = Mock() dhooks = DeferredHooks() d1, d2 = Deferred(canceller), Deferred(canceller) dhooks.add(d1) dhooks.add(d2) dhooks.reset() self.assertThat(dhooks.hooks, HasLength(0)) self.assertThat(canceller, MockCallsMatch(call(d1), call(d2)))
def test__savepoint_restores_hooks_only_on_dirty_exit(self): d1 = Deferred() d2 = Deferred() dhooks = DeferredHooks() dhooks.add(d1) exception_type = factory.make_exception_type() with ExpectedException(exception_type): with dhooks.savepoint(): dhooks.add(d2) raise exception_type() self.expectThat(list(dhooks.hooks), Equals([d1]))
def test__reset_suppresses_CancelledError(self): logger = self.useFixture(TwistedLoggerFixture()) dhooks = DeferredHooks() d = Deferred() dhooks.add(d) dhooks.reset() self.assertThat(dhooks.hooks, HasLength(0)) self.assertThat(extract_result(d), Is(None)) self.assertEqual("", logger.output)
def test__fire_calls_hooks_in_reactor(self): def validate_in_reactor(_): self.assertTrue(isInIOThread()) dhooks = DeferredHooks() d = Deferred() d.addCallback(validate_in_reactor) dhooks.add(d) dhooks.fire() self.assertThat(d, IsFiredDeferred())
def test__reset_cancels_in_reactor(self): def validate_in_reactor(_): self.assertTrue(isInIOThread()) dhooks = DeferredHooks() d = Deferred() d.addBoth(validate_in_reactor) dhooks.add(d) dhooks.reset() self.assertThat(dhooks.hooks, HasLength(0)) self.assertThat(d, IsFiredDeferred())
def test__logs_failures_from_cancelled_hooks(self): logger = self.useFixture(TwistedLoggerFixture()) error = factory.make_exception() dhooks = DeferredHooks() d = Deferred() d.addBoth(lambda _: Failure(error)) dhooks.add(d) dhooks.reset() self.assertThat(dhooks.hooks, HasLength(0)) self.assertThat(d, IsFiredDeferred()) self.assertDocTestMatches( dedent("""\ Failure when cancelling hook. Traceback (most recent call last): ... maastesting.factory.TestException#... """), logger.output)
def test__logs_failures_from_cancellers_when_hook_already_fired(self): logger = self.useFixture(TwistedLoggerFixture()) def canceller(d): d.callback(None) raise factory.make_exception() dhooks = DeferredHooks() d = Deferred(canceller) dhooks.add(d) dhooks.reset() self.assertThat(dhooks.hooks, HasLength(0)) self.assertThat(d, IsFiredDeferred()) self.assertDocTestMatches( dedent("""\ Failure when cancelling hook. Traceback (most recent call last): ... maastesting.factory.TestException#... """), logger.output)
def test__logs_failures_from_cancellers(self): logger = self.useFixture(TwistedLoggerFixture()) canceller = Mock() canceller.side_effect = factory.make_exception() dhooks = DeferredHooks() d = Deferred(canceller) dhooks.add(d) dhooks.reset() self.assertThat(dhooks.hooks, HasLength(0)) # The hook has not been fired, but because the user-supplied canceller # has failed we're not in a position to know what to do. This reflects # a programming error and not a run-time error that we ought to be # prepared for, so it is left as-is. self.assertThat(d, IsUnfiredDeferred()) self.assertDocTestMatches( dedent("""\ Failure when cancelling hook. Traceback (most recent call last): ... maastesting.factory.TestException#... """), logger.output)
def test__add_cannot_be_called_in_the_reactor(self): dhooks = DeferredHooks() add_in_reactor = wait_for(30)(dhooks.add) # Wait 30 seconds. self.assertRaises(AssertionError, add_in_reactor, Deferred())
def test__add_appends_Deferred_to_queue(self): dhooks = DeferredHooks() self.assertThat(dhooks.hooks, HasLength(0)) dhooks.add(Deferred()) self.assertThat(dhooks.hooks, HasLength(1))