test_util.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. # Copyright (c) Twisted Matrix Laboratories.
  2. # See LICENSE for details.
  3. """
  4. Utilities for Twisted.names tests.
  5. """
  6. from __future__ import division, absolute_import
  7. from random import randrange
  8. from zope.interface import implementer
  9. from zope.interface.verify import verifyClass
  10. from twisted.internet.address import IPv4Address
  11. from twisted.internet.defer import succeed
  12. from twisted.internet.task import Clock
  13. from twisted.internet.interfaces import IReactorUDP, IUDPTransport
  14. @implementer(IUDPTransport)
  15. class MemoryDatagramTransport(object):
  16. """
  17. This L{IUDPTransport} implementation enforces the usual connection rules
  18. and captures sent traffic in a list for later inspection.
  19. @ivar _host: The host address to which this transport is bound.
  20. @ivar _protocol: The protocol connected to this transport.
  21. @ivar _sentPackets: A C{list} of two-tuples of the datagrams passed to
  22. C{write} and the addresses to which they are destined.
  23. @ivar _connectedTo: L{None} if this transport is unconnected, otherwise an
  24. address to which all traffic is supposedly sent.
  25. @ivar _maxPacketSize: An C{int} giving the maximum length of a datagram
  26. which will be successfully handled by C{write}.
  27. """
  28. def __init__(self, host, protocol, maxPacketSize):
  29. self._host = host
  30. self._protocol = protocol
  31. self._sentPackets = []
  32. self._connectedTo = None
  33. self._maxPacketSize = maxPacketSize
  34. def getHost(self):
  35. """
  36. Return the address which this transport is pretending to be bound
  37. to.
  38. """
  39. return IPv4Address('UDP', *self._host)
  40. def connect(self, host, port):
  41. """
  42. Connect this transport to the given address.
  43. """
  44. if self._connectedTo is not None:
  45. raise ValueError("Already connected")
  46. self._connectedTo = (host, port)
  47. def write(self, datagram, addr=None):
  48. """
  49. Send the given datagram.
  50. """
  51. if addr is None:
  52. addr = self._connectedTo
  53. if addr is None:
  54. raise ValueError("Need an address")
  55. if len(datagram) > self._maxPacketSize:
  56. raise ValueError("Packet too big")
  57. self._sentPackets.append((datagram, addr))
  58. def stopListening(self):
  59. """
  60. Shut down this transport.
  61. """
  62. self._protocol.stopProtocol()
  63. return succeed(None)
  64. def setBroadcastAllowed(self, enabled):
  65. """
  66. Dummy implementation to satisfy L{IUDPTransport}.
  67. """
  68. pass
  69. def getBroadcastAllowed(self):
  70. """
  71. Dummy implementation to satisfy L{IUDPTransport}.
  72. """
  73. pass
  74. verifyClass(IUDPTransport, MemoryDatagramTransport)
  75. @implementer(IReactorUDP)
  76. class MemoryReactor(Clock):
  77. """
  78. An L{IReactorTime} and L{IReactorUDP} provider.
  79. Time is controlled deterministically via the base class, L{Clock}. UDP is
  80. handled in-memory by connecting protocols to instances of
  81. L{MemoryDatagramTransport}.
  82. @ivar udpPorts: A C{dict} mapping port numbers to instances of
  83. L{MemoryDatagramTransport}.
  84. """
  85. def __init__(self):
  86. Clock.__init__(self)
  87. self.udpPorts = {}
  88. def listenUDP(self, port, protocol, interface='', maxPacketSize=8192):
  89. """
  90. Pretend to bind a UDP port and connect the given protocol to it.
  91. """
  92. if port == 0:
  93. while True:
  94. port = randrange(1, 2 ** 16)
  95. if port not in self.udpPorts:
  96. break
  97. if port in self.udpPorts:
  98. raise ValueError("Address in use")
  99. transport = MemoryDatagramTransport(
  100. (interface, port), protocol, maxPacketSize)
  101. self.udpPorts[port] = transport
  102. protocol.makeConnection(transport)
  103. return transport
  104. verifyClass(IReactorUDP, MemoryReactor)