1 #define BOOST_TEST_DYN_LINK
2 #define BOOST_TEST_NO_MAIN
7 #include <boost/test/unit_test.hpp>
8 #include "dnswriter.hh"
9 #include "dnsrecords.hh"
10 #include "dns_random.hh"
12 #include "recpacketcache.hh"
16 BOOST_AUTO_TEST_SUITE(recpacketcache_cc
)
18 BOOST_AUTO_TEST_CASE(test_recPacketCacheSimple
) {
19 RecursorPacketCache rpc
;
25 BOOST_CHECK_EQUAL(rpc
.size(), 0);
27 DNSName
qname("www.powerdns.com");
28 vector
<uint8_t> packet
;
29 DNSPacketWriter
pw(packet
, qname
, QType::A
);
30 pw
.getHeader()->rd
=true;
31 pw
.getHeader()->qr
=false;
32 pw
.getHeader()->id
=random();
33 string
qpacket((const char*)&packet
[0], packet
.size());
34 pw
.startRecord(qname
, QType::A
, ttd
);
36 BOOST_CHECK_EQUAL(rpc
.getResponsePacket(tag
, qpacket
, time(nullptr), &fpacket
, &age
, &qhash
), false);
37 BOOST_CHECK_EQUAL(rpc
.getResponsePacket(tag
, qpacket
, qname
, QType::A
, QClass::IN
, time(nullptr), &fpacket
, &age
, &qhash
), false);
39 ARecordContent
ar("127.0.0.1");
42 string
rpacket((const char*)&packet
[0], packet
.size());
44 rpc
.insertResponsePacket(tag
, qhash
, qname
, QType::A
, QClass::IN
, rpacket
, time(0), ttd
);
45 BOOST_CHECK_EQUAL(rpc
.size(), 1);
47 BOOST_CHECK_EQUAL(rpc
.size(), 0);
48 rpc
.insertResponsePacket(tag
, qhash
, qname
, QType::A
, QClass::IN
, rpacket
, time(0), ttd
);
49 BOOST_CHECK_EQUAL(rpc
.size(), 1);
50 rpc
.doWipePacketCache(qname
);
51 BOOST_CHECK_EQUAL(rpc
.size(), 0);
53 rpc
.insertResponsePacket(tag
, qhash
, qname
, QType::A
, QClass::IN
, rpacket
, time(0), ttd
);
55 bool found
= rpc
.getResponsePacket(tag
, qpacket
, time(nullptr), &fpacket
, &age
, &qhash2
);
56 BOOST_CHECK_EQUAL(found
, true);
57 BOOST_CHECK_EQUAL(qhash
, qhash2
);
58 BOOST_CHECK_EQUAL(fpacket
, rpacket
);
59 found
= rpc
.getResponsePacket(tag
, qpacket
, qname
, QType::A
, QClass::IN
, time(nullptr), &fpacket
, &age
, &qhash2
);
60 BOOST_CHECK_EQUAL(found
, true);
61 BOOST_CHECK_EQUAL(qhash
, qhash2
);
62 BOOST_CHECK_EQUAL(fpacket
, rpacket
);
65 qname
+=DNSName("co.uk");
66 DNSPacketWriter
pw2(packet
, qname
, QType::A
);
68 pw2
.getHeader()->rd
=true;
69 pw2
.getHeader()->qr
=false;
70 pw2
.getHeader()->id
=random();
71 qpacket
.assign((const char*)&packet
[0], packet
.size());
73 found
= rpc
.getResponsePacket(tag
, qpacket
, time(nullptr), &fpacket
, &age
, &qhash
);
74 BOOST_CHECK_EQUAL(found
, false);
75 found
= rpc
.getResponsePacket(tag
, qpacket
, qname
, QType::A
, QClass::IN
, time(nullptr), &fpacket
, &age
, &qhash
);
76 BOOST_CHECK_EQUAL(found
, false);
78 rpc
.doWipePacketCache(DNSName("com"), 0xffff, true);
79 BOOST_CHECK_EQUAL(rpc
.size(), 0);
82 BOOST_AUTO_TEST_CASE(test_recPacketCache_Tags
) {
83 /* Insert a response with tag1, the exact same query with a different tag
84 should lead to a miss. Inserting a different response with the second tag
85 should not override the first one, and we should get a hit for the
86 query with either tags, with the response matching the tag.
88 RecursorPacketCache rpc
;
90 const unsigned int tag1
=0;
91 const unsigned int tag2
=42;
96 BOOST_CHECK_EQUAL(rpc
.size(), 0);
98 DNSName
qname("www.powerdns.com");
99 vector
<uint8_t> packet
;
100 DNSPacketWriter
pw(packet
, qname
, QType::A
);
101 pw
.getHeader()->rd
=true;
102 pw
.getHeader()->qr
=false;
103 pw
.getHeader()->id
=random();
104 string
qpacket(reinterpret_cast<const char*>(&packet
[0]), packet
.size());
105 pw
.startRecord(qname
, QType::A
, ttd
);
107 /* Both interfaces (with and without the qname/qtype/qclass) should get the same hash */
108 BOOST_CHECK_EQUAL(rpc
.getResponsePacket(tag1
, qpacket
, time(nullptr), &fpacket
, &age
, &qhash
), false);
109 BOOST_CHECK_EQUAL(rpc
.getResponsePacket(tag1
, qpacket
, qname
, QType::A
, QClass::IN
, time(nullptr), &fpacket
, &age
, &temphash
), false);
110 BOOST_CHECK_EQUAL(qhash
, temphash
);
112 /* Different tag, should still get get the same hash, for both interfaces */
113 BOOST_CHECK_EQUAL(rpc
.getResponsePacket(tag2
, qpacket
, time(nullptr), &fpacket
, &age
, &temphash
), false);
114 BOOST_CHECK_EQUAL(qhash
, temphash
);
115 BOOST_CHECK_EQUAL(rpc
.getResponsePacket(tag2
, qpacket
, qname
, QType::A
, QClass::IN
, time(nullptr), &fpacket
, &age
, &temphash
), false);
116 BOOST_CHECK_EQUAL(qhash
, temphash
);
119 ARecordContent
ar("127.0.0.1");
123 string
r1packet(reinterpret_cast<const char*>(&packet
[0]), packet
.size());
126 ARecordContent
ar("127.0.0.2");
130 string
r2packet(reinterpret_cast<const char*>(&packet
[0]), packet
.size());
132 BOOST_CHECK(r1packet
!= r2packet
);
134 /* inserting a response for tag1 */
135 rpc
.insertResponsePacket(tag1
, qhash
, qname
, QType::A
, QClass::IN
, r1packet
, time(0), ttd
);
136 BOOST_CHECK_EQUAL(rpc
.size(), 1);
138 /* inserting a different response for tag2, should not override the first one */
139 rpc
.insertResponsePacket(tag2
, qhash
, qname
, QType::A
, QClass::IN
, r2packet
, time(0), ttd
);
140 BOOST_CHECK_EQUAL(rpc
.size(), 2);
142 /* remove all responses from the cache */
144 BOOST_CHECK_EQUAL(rpc
.size(), 0);
147 rpc
.insertResponsePacket(tag1
, qhash
, qname
, QType::A
, QClass::IN
, r1packet
, time(0), ttd
);
148 BOOST_CHECK_EQUAL(rpc
.size(), 1);
150 rpc
.insertResponsePacket(tag2
, qhash
, qname
, QType::A
, QClass::IN
, r2packet
, time(0), ttd
);
151 BOOST_CHECK_EQUAL(rpc
.size(), 2);
153 /* remove the responses by qname, should remove both */
154 rpc
.doWipePacketCache(qname
);
155 BOOST_CHECK_EQUAL(rpc
.size(), 0);
157 /* insert the response for tag1 */
158 rpc
.insertResponsePacket(tag1
, qhash
, qname
, QType::A
, QClass::IN
, r1packet
, time(0), ttd
);
159 BOOST_CHECK_EQUAL(rpc
.size(), 1);
161 /* we can retrieve it */
162 BOOST_CHECK_EQUAL(rpc
.getResponsePacket(tag1
, qpacket
, qname
, QType::A
, QClass::IN
, time(nullptr), &fpacket
, &age
, &temphash
), true);
163 BOOST_CHECK_EQUAL(qhash
, temphash
);
164 BOOST_CHECK_EQUAL(fpacket
, r1packet
);
166 /* with both interfaces */
167 BOOST_CHECK_EQUAL(rpc
.getResponsePacket(tag1
, qpacket
, time(nullptr), &fpacket
, &age
, &temphash
), true);
168 BOOST_CHECK_EQUAL(qhash
, temphash
);
169 BOOST_CHECK_EQUAL(fpacket
, r1packet
);
171 /* but not with the second tag */
172 BOOST_CHECK_EQUAL(rpc
.getResponsePacket(tag2
, qpacket
, qname
, QType::A
, QClass::IN
, time(nullptr), &fpacket
, &age
, &temphash
), false);
173 /* we should still get the same hash */
174 BOOST_CHECK_EQUAL(temphash
, qhash
);
176 /* adding a response for the second tag */
177 rpc
.insertResponsePacket(tag2
, qhash
, qname
, QType::A
, QClass::IN
, r2packet
, time(0), ttd
);
178 BOOST_CHECK_EQUAL(rpc
.size(), 2);
180 /* We still get the correct response for the first tag */
181 BOOST_CHECK_EQUAL(rpc
.getResponsePacket(tag1
, qpacket
, time(nullptr), &fpacket
, &age
, &temphash
), true);
182 BOOST_CHECK_EQUAL(qhash
, temphash
);
183 BOOST_CHECK_EQUAL(fpacket
, r1packet
);
185 BOOST_CHECK_EQUAL(rpc
.getResponsePacket(tag1
, qpacket
, qname
, QType::A
, QClass::IN
, time(nullptr), &fpacket
, &age
, &temphash
), true);
186 BOOST_CHECK_EQUAL(qhash
, temphash
);
187 BOOST_CHECK_EQUAL(fpacket
, r1packet
);
189 /* and the correct response for the second tag */
190 BOOST_CHECK_EQUAL(rpc
.getResponsePacket(tag2
, qpacket
, time(nullptr), &fpacket
, &age
, &temphash
), true);
191 BOOST_CHECK_EQUAL(qhash
, temphash
);
192 BOOST_CHECK_EQUAL(fpacket
, r2packet
);
194 BOOST_CHECK_EQUAL(rpc
.getResponsePacket(tag2
, qpacket
, qname
, QType::A
, QClass::IN
, time(nullptr), &fpacket
, &age
, &temphash
), true);
195 BOOST_CHECK_EQUAL(qhash
, temphash
);
196 BOOST_CHECK_EQUAL(fpacket
, r2packet
);
199 BOOST_AUTO_TEST_SUITE_END()