@@ -37,6 +37,38 @@ def test_order(self):
3737 cached_record = cache .get (entry )
3838 assert cached_record == record2
3939
40+ def test_adding_same_record_to_cache_different_ttls (self ):
41+ """We should always get back the last entry we added if there are different TTLs.
42+
43+ This ensures we only have one source of truth for TTLs as a record cannot
44+ be both expired and not expired.
45+ """
46+ record1 = r .DNSAddress ('a' , const ._TYPE_A , const ._CLASS_IN , 1 , b'a' )
47+ record2 = r .DNSAddress ('a' , const ._TYPE_A , const ._CLASS_IN , 10 , b'a' )
48+ cache = r .DNSCache ()
49+ cache .add (record1 )
50+ cache .add (record2 )
51+ entry = r .DNSEntry (record2 )
52+ cached_record = cache .get (entry )
53+ assert cached_record == record2
54+
55+ @unittest .skip ('This bug in the implementation needs to be fixed.' )
56+ def test_adding_same_record_to_cache_different_ttls (self ):
57+ """Verify we only get one record back.
58+
59+ The last record added should replace the previous since two
60+ records with different ttls are __eq__. This ensures we
61+ only have one source of truth for TTLs as a record cannot
62+ be both expired and not expired.
63+ """
64+ record1 = r .DNSAddress ('a' , const ._TYPE_A , const ._CLASS_IN , 1 , b'a' )
65+ record2 = r .DNSAddress ('a' , const ._TYPE_A , const ._CLASS_IN , 10 , b'a' )
66+ cache = r .DNSCache ()
67+ cache .add (record1 )
68+ cache .add (record2 )
69+ cached_records = cache .get_all_by_details ('a' , const ._TYPE_A , const ._CLASS_IN )
70+ assert cached_records == [record2 ]
71+
4072 def test_cache_empty_does_not_leak_memory_by_leaving_empty_list (self ):
4173 record1 = r .DNSAddress ('a' , const ._TYPE_SOA , const ._CLASS_IN , 1 , b'a' )
4274 record2 = r .DNSAddress ('a' , const ._TYPE_SOA , const ._CLASS_IN , 1 , b'b' )
@@ -61,3 +93,73 @@ def test_cache_empty_multiple_calls_does_not_throw(self):
6193 cache .remove (record1 )
6294 cache .remove (record2 )
6395 assert 'a' not in cache .cache
96+
97+
98+ # These functions have been seen in other projects so
99+ # we try to maintain a stable API for all the threadsafe getters
100+ class TestDNSCacheAPI (unittest .TestCase ):
101+ def test_get (self ):
102+ record1 = r .DNSAddress ('a' , const ._TYPE_A , const ._CLASS_IN , 1 , b'a' )
103+ record2 = r .DNSAddress ('a' , const ._TYPE_A , const ._CLASS_IN , 1 , b'b' )
104+ cache = r .DNSCache ()
105+ cache .add_records ([record1 , record2 ])
106+ assert cache .get (record1 ) == record1
107+ assert cache .get (record2 ) == record2
108+
109+ def test_get_by_details (self ):
110+ record1 = r .DNSAddress ('a' , const ._TYPE_A , const ._CLASS_IN , 1 , b'a' )
111+ record2 = r .DNSAddress ('a' , const ._TYPE_A , const ._CLASS_IN , 1 , b'b' )
112+ cache = r .DNSCache ()
113+ cache .add_records ([record1 , record2 ])
114+ assert cache .get_by_details ('a' , const ._TYPE_A , const ._CLASS_IN ) == record2
115+
116+ def test_get_all_by_details (self ):
117+ record1 = r .DNSAddress ('a' , const ._TYPE_A , const ._CLASS_IN , 1 , b'a' )
118+ record2 = r .DNSAddress ('a' , const ._TYPE_A , const ._CLASS_IN , 1 , b'b' )
119+ cache = r .DNSCache ()
120+ cache .add_records ([record1 , record2 ])
121+ assert set (cache .get_all_by_details ('a' , const ._TYPE_A , const ._CLASS_IN )) == set ([record1 , record2 ])
122+
123+ def test_entries_with_server (self ):
124+ record1 = r .DNSService (
125+ 'irrelevant' , const ._TYPE_SRV , const ._CLASS_IN , const ._DNS_HOST_TTL , 0 , 0 , 85 , 'ab'
126+ )
127+ record2 = r .DNSService (
128+ 'irrelevant' , const ._TYPE_SRV , const ._CLASS_IN , const ._DNS_HOST_TTL , 0 , 0 , 80 , 'ab'
129+ )
130+ cache = r .DNSCache ()
131+ cache .add_records ([record1 , record2 ])
132+ assert set (cache .entries_with_server ('ab' )) == set ([record1 , record2 ])
133+
134+ def test_entries_with_name (self ):
135+ record1 = r .DNSService (
136+ 'irrelevant' , const ._TYPE_SRV , const ._CLASS_IN , const ._DNS_HOST_TTL , 0 , 0 , 85 , 'ab'
137+ )
138+ record2 = r .DNSService (
139+ 'irrelevant' , const ._TYPE_SRV , const ._CLASS_IN , const ._DNS_HOST_TTL , 0 , 0 , 80 , 'ab'
140+ )
141+ cache = r .DNSCache ()
142+ cache .add_records ([record1 , record2 ])
143+ assert set (cache .entries_with_name ('irrelevant' )) == set ([record1 , record2 ])
144+
145+ def test_current_entry_with_name_and_alias (self ):
146+ record1 = r .DNSPointer (
147+ 'irrelevant' , const ._TYPE_PTR , const ._CLASS_IN , const ._DNS_OTHER_TTL , 'x.irrelevant'
148+ )
149+ record2 = r .DNSPointer (
150+ 'irrelevant' , const ._TYPE_PTR , const ._CLASS_IN , const ._DNS_OTHER_TTL , 'y.irrelevant'
151+ )
152+ cache = r .DNSCache ()
153+ cache .add_records ([record1 , record2 ])
154+ assert cache .current_entry_with_name_and_alias ('irrelevant' , 'x.irrelevant' ) == record1
155+
156+ def test_entries_with_name (self ):
157+ record1 = r .DNSService (
158+ 'irrelevant' , const ._TYPE_SRV , const ._CLASS_IN , const ._DNS_HOST_TTL , 0 , 0 , 85 , 'ab'
159+ )
160+ record2 = r .DNSService (
161+ 'irrelevant' , const ._TYPE_SRV , const ._CLASS_IN , const ._DNS_HOST_TTL , 0 , 0 , 80 , 'ab'
162+ )
163+ cache = r .DNSCache ()
164+ cache .add_records ([record1 , record2 ])
165+ assert cache .names () == ['irrelevant' ]
0 commit comments