test_time.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. # Copyright (c) Twisted Matrix Laboratories.
  2. # See LICENSE for details.
  3. """
  4. Tests for implementations of L{IReactorTime}.
  5. """
  6. __metaclass__ = type
  7. from twisted.python.log import msg
  8. from twisted.python.runtime import platform
  9. from twisted.trial.unittest import SkipTest
  10. from twisted.internet.test.reactormixins import ReactorBuilder
  11. from twisted.internet.interfaces import IReactorTime, IReactorThreads
  12. class TimeTestsBuilder(ReactorBuilder):
  13. """
  14. Builder for defining tests relating to L{IReactorTime}.
  15. """
  16. requiredInterfaces = (IReactorTime,)
  17. def test_delayedCallStopsReactor(self):
  18. """
  19. The reactor can be stopped by a delayed call.
  20. """
  21. reactor = self.buildReactor()
  22. reactor.callLater(0, reactor.stop)
  23. reactor.run()
  24. def test_distantDelayedCall(self):
  25. """
  26. Scheduling a delayed call at a point in the extreme future does not
  27. prevent normal reactor operation.
  28. """
  29. reactor = self.buildReactor()
  30. if IReactorThreads.providedBy(reactor):
  31. def eventSource(reactor, event):
  32. msg(format="Thread-based event-source scheduling %(event)r",
  33. event=event)
  34. reactor.callFromThread(event)
  35. else:
  36. raise SkipTest("Do not know how to synthesize non-time event to "
  37. "stop the test")
  38. # Pick a pretty big delay.
  39. delayedCall = reactor.callLater(2 ** 128 + 1, lambda: None)
  40. def stop():
  41. msg("Stopping the reactor")
  42. reactor.stop()
  43. # Use repeated invocation of the event source to set up the call to stop
  44. # the reactor. This makes it more likely at least one normal iteration
  45. # will take place with the delayed call in place before the slightly
  46. # different reactor shutdown logic alters things.
  47. eventSource(reactor, lambda: eventSource(reactor, stop))
  48. # Run the reactor directly, without a timeout. A timeout would
  49. # interfere with the purpose of this test, which is to have the timeout
  50. # passed to the reactor's doIterate implementation (potentially) be
  51. # very, very large. Hopefully the event source defined above will work
  52. # and cause the reactor to stop.
  53. reactor.run()
  54. # The reactor almost surely stopped before the delayed call
  55. # fired... right?
  56. self.assertTrue(delayedCall.active())
  57. self.assertIn(delayedCall, reactor.getDelayedCalls())
  58. class GlibTimeTestsBuilder(ReactorBuilder):
  59. """
  60. Builder for defining tests relating to L{IReactorTime} for reactors based
  61. off glib.
  62. """
  63. requiredInterfaces = (IReactorTime,)
  64. if platform.isWindows():
  65. _reactors = ["twisted.internet.gtk2reactor.PortableGtkReactor"]
  66. else:
  67. _reactors = ["twisted.internet.glib2reactor.Glib2Reactor",
  68. "twisted.internet.gtk2reactor.Gtk2Reactor"]
  69. def test_timeout_add(self):
  70. """
  71. A
  72. L{reactor.callLater<twisted.internet.interfaces.IReactorTime.callLater>}
  73. call scheduled from a C{gobject.timeout_add}
  74. call is run on time.
  75. """
  76. import gobject
  77. reactor = self.buildReactor()
  78. result = []
  79. def gschedule():
  80. reactor.callLater(0, callback)
  81. return 0
  82. def callback():
  83. result.append(True)
  84. reactor.stop()
  85. reactor.callWhenRunning(gobject.timeout_add, 10, gschedule)
  86. self.runReactor(reactor, 5)
  87. self.assertEqual(result, [True])
  88. globals().update(TimeTestsBuilder.makeTestCaseClasses())
  89. globals().update(GlibTimeTestsBuilder.makeTestCaseClasses())