_awaittests.py.3only 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. # Copyright (c) Twisted Matrix Laboratories.
  2. # See LICENSE for details.
  3. """
  4. Tests for C{await} support in Deferreds.
  5. These tests can only work and be imported on Python 3.5+!
  6. """
  7. import types
  8. from twisted.internet.defer import Deferred, ensureDeferred, fail
  9. from twisted.trial.unittest import TestCase
  10. from twisted.test.proto_helpers import Clock
  11. class AwaitTests(TestCase):
  12. """
  13. Tests for using Deferreds in conjunction with PEP-492.
  14. """
  15. def test_awaitReturnsIterable(self):
  16. """
  17. C{Deferred.__await__} returns an iterable.
  18. """
  19. d = Deferred()
  20. awaitedDeferred = d.__await__()
  21. self.assertEqual(awaitedDeferred, iter(awaitedDeferred))
  22. def test_ensureDeferred(self):
  23. """
  24. L{ensureDeferred} will turn a coroutine into a L{Deferred}.
  25. """
  26. async def run():
  27. d = Deferred()
  28. d.callback("bar")
  29. await d
  30. res = await run2()
  31. return res
  32. async def run2():
  33. d = Deferred()
  34. d.callback("foo")
  35. res = await d
  36. return res
  37. # It's a coroutine...
  38. r = run()
  39. self.assertIsInstance(r, types.CoroutineType)
  40. # Now it's a Deferred.
  41. d = ensureDeferred(r)
  42. self.assertIsInstance(d, Deferred)
  43. # The Deferred has the result we want.
  44. res = self.successResultOf(d)
  45. self.assertEqual(res, "foo")
  46. def test_basic(self):
  47. """
  48. L{ensureDeferred} allows a function to C{await} on a L{Deferred}.
  49. """
  50. async def run():
  51. d = Deferred()
  52. d.callback("foo")
  53. res = await d
  54. return res
  55. d = ensureDeferred(run())
  56. res = self.successResultOf(d)
  57. self.assertEqual(res, "foo")
  58. def test_exception(self):
  59. """
  60. An exception in a coroutine wrapped with L{ensureDeferred} will cause
  61. the returned L{Deferred} to fire with a failure.
  62. """
  63. async def run():
  64. d = Deferred()
  65. d.callback("foo")
  66. await d
  67. raise ValueError("Oh no!")
  68. d = ensureDeferred(run())
  69. res = self.failureResultOf(d)
  70. self.assertEqual(type(res.value), ValueError)
  71. self.assertEqual(res.value.args, ("Oh no!",))
  72. def test_twoDeep(self):
  73. """
  74. A coroutine wrapped with L{ensureDeferred} that awaits a L{Deferred}
  75. suspends its execution until the inner L{Deferred} fires.
  76. """
  77. reactor = Clock()
  78. sections = []
  79. async def runone():
  80. sections.append(2)
  81. d = Deferred()
  82. reactor.callLater(1, d.callback, 2)
  83. await d
  84. sections.append(3)
  85. return "Yay!"
  86. async def run():
  87. sections.append(1)
  88. result = await runone()
  89. sections.append(4)
  90. d = Deferred()
  91. reactor.callLater(1, d.callback, 1)
  92. await d
  93. sections.append(5)
  94. return result
  95. d = ensureDeferred(run())
  96. reactor.advance(0.9)
  97. self.assertEqual(sections, [1, 2])
  98. reactor.advance(0.1)
  99. self.assertEqual(sections, [1, 2, 3, 4])
  100. reactor.advance(0.9)
  101. self.assertEqual(sections, [1, 2, 3, 4])
  102. reactor.advance(0.1)
  103. self.assertEqual(sections, [1, 2, 3, 4, 5])
  104. res = self.successResultOf(d)
  105. self.assertEqual(res, "Yay!")
  106. def test_reraise(self):
  107. """
  108. Awaiting an already failed Deferred will raise the exception.
  109. """
  110. async def test():
  111. try:
  112. await fail(ValueError("Boom"))
  113. except ValueError as e:
  114. self.assertEqual(e.args, ("Boom",))
  115. return 1
  116. return 0
  117. res = self.successResultOf(ensureDeferred(test()))
  118. self.assertEqual(res, 1)
  119. def test_chained(self):
  120. """
  121. Awaiting a paused & chained Deferred will give the result when it has
  122. one.
  123. """
  124. reactor = Clock()
  125. async def test():
  126. d = Deferred()
  127. d2 = Deferred()
  128. d.addCallback(lambda ignored: d2)
  129. d.callback(None)
  130. reactor.callLater(0, d2.callback, "bye")
  131. return await d
  132. d = ensureDeferred(test())
  133. reactor.advance(0.1)
  134. res = self.successResultOf(d)
  135. self.assertEqual(res, "bye")