test_cache.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. # Copyright (c) Twisted Matrix Laboratories.
  2. # See LICENSE for details.
  3. """
  4. Tests for L{twisted.names.cache}.
  5. """
  6. from __future__ import division, absolute_import
  7. import time
  8. from zope.interface.verify import verifyClass
  9. from twisted.trial import unittest
  10. from twisted.names import dns, cache
  11. from twisted.internet import task, interfaces
  12. class CachingTests(unittest.TestCase):
  13. """
  14. Tests for L{cache.CacheResolver}.
  15. """
  16. def test_interface(self):
  17. """
  18. L{cache.CacheResolver} implements L{interfaces.IResolver}
  19. """
  20. verifyClass(interfaces.IResolver, cache.CacheResolver)
  21. def test_lookup(self):
  22. c = cache.CacheResolver({
  23. dns.Query(name=b'example.com', type=dns.MX, cls=dns.IN):
  24. (time.time(), ([], [], []))})
  25. return c.lookupMailExchange(b'example.com').addCallback(
  26. self.assertEqual, ([], [], []))
  27. def test_constructorExpires(self):
  28. """
  29. Cache entries passed into L{cache.CacheResolver.__init__} get
  30. cancelled just like entries added with cacheResult
  31. """
  32. r = ([dns.RRHeader(b"example.com", dns.A, dns.IN, 60,
  33. dns.Record_A("127.0.0.1", 60))],
  34. [dns.RRHeader(b"example.com", dns.A, dns.IN, 50,
  35. dns.Record_A("127.0.0.1", 50))],
  36. [dns.RRHeader(b"example.com", dns.A, dns.IN, 40,
  37. dns.Record_A("127.0.0.1", 40))])
  38. clock = task.Clock()
  39. query = dns.Query(name=b"example.com", type=dns.A, cls=dns.IN)
  40. c = cache.CacheResolver({ query : (clock.seconds(), r)}, reactor=clock)
  41. # 40 seconds is enough to expire the entry because expiration is based
  42. # on the minimum TTL.
  43. clock.advance(40)
  44. self.assertNotIn(query, c.cache)
  45. return self.assertFailure(
  46. c.lookupAddress(b"example.com"), dns.DomainError)
  47. def test_normalLookup(self):
  48. """
  49. When a cache lookup finds a cached entry from 1 second ago, it is
  50. returned with a TTL of original TTL minus the elapsed 1 second.
  51. """
  52. r = ([dns.RRHeader(b"example.com", dns.A, dns.IN, 60,
  53. dns.Record_A("127.0.0.1", 60))],
  54. [dns.RRHeader(b"example.com", dns.A, dns.IN, 50,
  55. dns.Record_A("127.0.0.1", 50))],
  56. [dns.RRHeader(b"example.com", dns.A, dns.IN, 40,
  57. dns.Record_A("127.0.0.1", 40))])
  58. clock = task.Clock()
  59. c = cache.CacheResolver(reactor=clock)
  60. c.cacheResult(dns.Query(name=b"example.com", type=dns.A, cls=dns.IN), r)
  61. clock.advance(1)
  62. def cbLookup(result):
  63. self.assertEqual(result[0][0].ttl, 59)
  64. self.assertEqual(result[1][0].ttl, 49)
  65. self.assertEqual(result[2][0].ttl, 39)
  66. self.assertEqual(result[0][0].name, b"example.com")
  67. return c.lookupAddress(b"example.com").addCallback(cbLookup)
  68. def test_cachedResultExpires(self):
  69. """
  70. Once the TTL has been exceeded, the result is removed from the cache.
  71. """
  72. r = ([dns.RRHeader(b"example.com", dns.A, dns.IN, 60,
  73. dns.Record_A("127.0.0.1", 60))],
  74. [dns.RRHeader(b"example.com", dns.A, dns.IN, 50,
  75. dns.Record_A("127.0.0.1", 50))],
  76. [dns.RRHeader(b"example.com", dns.A, dns.IN, 40,
  77. dns.Record_A("127.0.0.1", 40))])
  78. clock = task.Clock()
  79. c = cache.CacheResolver(reactor=clock)
  80. query = dns.Query(name=b"example.com", type=dns.A, cls=dns.IN)
  81. c.cacheResult(query, r)
  82. clock.advance(40)
  83. self.assertNotIn(query, c.cache)
  84. return self.assertFailure(
  85. c.lookupAddress(b"example.com"), dns.DomainError)
  86. def test_expiredTTLLookup(self):
  87. """
  88. When the cache is queried exactly as the cached entry should expire but
  89. before it has actually been cleared, the cache does not return the
  90. expired entry.
  91. """
  92. r = ([dns.RRHeader(b"example.com", dns.A, dns.IN, 60,
  93. dns.Record_A("127.0.0.1", 60))],
  94. [dns.RRHeader(b"example.com", dns.A, dns.IN, 50,
  95. dns.Record_A("127.0.0.1", 50))],
  96. [dns.RRHeader(b"example.com", dns.A, dns.IN, 40,
  97. dns.Record_A("127.0.0.1", 40))])
  98. clock = task.Clock()
  99. # Make sure timeouts never happen, so entries won't get cleared:
  100. clock.callLater = lambda *args, **kwargs: None
  101. c = cache.CacheResolver({
  102. dns.Query(name=b"example.com", type=dns.A, cls=dns.IN) :
  103. (clock.seconds(), r)}, reactor=clock)
  104. clock.advance(60.1)
  105. return self.assertFailure(
  106. c.lookupAddress(b"example.com"), dns.DomainError)