1 #define BOOST_TEST_DYN_LINK
2 #define BOOST_TEST_NO_MAIN
7 #include <boost/test/unit_test.hpp>
8 #include "arguments.hh"
9 #include "dnswriter.hh"
10 #include "dnsrecords.hh"
11 #include "dns_random.hh"
13 #include "recpacketcache.hh"
17 BOOST_AUTO_TEST_SUITE(test_recpacketcache_cc
)
19 BOOST_AUTO_TEST_CASE(test_recPacketCacheSimple
) {
20 RecursorPacketCache rpc
;
26 BOOST_CHECK_EQUAL(rpc
.size(), 0);
28 ::arg().set("rng")="auto";
29 ::arg().set("entropy-source")="/dev/urandom";
31 DNSName
qname("www.powerdns.com");
32 vector
<uint8_t> packet
;
33 DNSPacketWriter
pw(packet
, qname
, QType::A
);
34 pw
.getHeader()->rd
=true;
35 pw
.getHeader()->qr
=false;
36 pw
.getHeader()->id
=dns_random(UINT16_MAX
);
37 string
qpacket((const char*)&packet
[0], packet
.size());
38 pw
.startRecord(qname
, QType::A
, ttd
);
40 BOOST_CHECK_EQUAL(rpc
.getResponsePacket(tag
, qpacket
, time(nullptr), &fpacket
, &age
, &qhash
), false);
41 BOOST_CHECK_EQUAL(rpc
.getResponsePacket(tag
, qpacket
, qname
, QType::A
, QClass::IN
, time(nullptr), &fpacket
, &age
, &qhash
), false);
43 ARecordContent
ar("127.0.0.1");
46 string
rpacket((const char*)&packet
[0], packet
.size());
48 rpc
.insertResponsePacket(tag
, qhash
, string(qpacket
), qname
, QType::A
, QClass::IN
, string(rpacket
), time(0), ttd
, Indeterminate
, 0, 0, boost::none
);
49 BOOST_CHECK_EQUAL(rpc
.size(), 1);
51 BOOST_CHECK_EQUAL(rpc
.size(), 0);
52 rpc
.insertResponsePacket(tag
, qhash
, string(qpacket
), qname
, QType::A
, QClass::IN
, string(rpacket
), time(0), ttd
, Indeterminate
, 0, 0, boost::none
);
53 BOOST_CHECK_EQUAL(rpc
.size(), 1);
54 rpc
.doWipePacketCache(qname
);
55 BOOST_CHECK_EQUAL(rpc
.size(), 0);
57 rpc
.insertResponsePacket(tag
, qhash
, string(qpacket
), qname
, QType::A
, QClass::IN
, string(rpacket
), time(0), ttd
, Indeterminate
, 0, 0, boost::none
);
58 BOOST_CHECK_EQUAL(rpc
.size(), 1);
60 bool found
= rpc
.getResponsePacket(tag
, qpacket
, time(nullptr), &fpacket
, &age
, &qhash2
);
61 BOOST_CHECK_EQUAL(found
, true);
62 BOOST_CHECK_EQUAL(qhash
, qhash2
);
63 BOOST_CHECK_EQUAL(fpacket
, rpacket
);
64 found
= rpc
.getResponsePacket(tag
, qpacket
, qname
, QType::A
, QClass::IN
, time(nullptr), &fpacket
, &age
, &qhash2
);
65 BOOST_CHECK_EQUAL(found
, true);
66 BOOST_CHECK_EQUAL(qhash
, qhash2
);
67 BOOST_CHECK_EQUAL(fpacket
, rpacket
);
70 qname
+=DNSName("co.uk");
71 DNSPacketWriter
pw2(packet
, qname
, QType::A
);
73 pw2
.getHeader()->rd
=true;
74 pw2
.getHeader()->qr
=false;
75 pw2
.getHeader()->id
=dns_random(UINT16_MAX
);
76 qpacket
.assign((const char*)&packet
[0], packet
.size());
78 found
= rpc
.getResponsePacket(tag
, qpacket
, time(nullptr), &fpacket
, &age
, &qhash
);
79 BOOST_CHECK_EQUAL(found
, false);
80 found
= rpc
.getResponsePacket(tag
, qpacket
, qname
, QType::A
, QClass::IN
, time(nullptr), &fpacket
, &age
, &qhash
);
81 BOOST_CHECK_EQUAL(found
, false);
83 rpc
.doWipePacketCache(DNSName("com"), 0xffff, true);
84 BOOST_CHECK_EQUAL(rpc
.size(), 0);
87 BOOST_AUTO_TEST_CASE(test_recPacketCache_Tags
) {
88 /* Insert a response with tag1, the exact same query with a different tag
89 should lead to a miss. Inserting a different response with the second tag
90 should not override the first one, and we should get a hit for the
91 query with either tags, with the response matching the tag.
93 RecursorPacketCache rpc
;
95 const unsigned int tag1
=0;
96 const unsigned int tag2
=42;
101 BOOST_CHECK_EQUAL(rpc
.size(), 0);
103 ::arg().set("rng")="auto";
104 ::arg().set("entropy-source")="/dev/urandom";
106 DNSName
qname("www.powerdns.com");
107 vector
<uint8_t> packet
;
108 DNSPacketWriter
pw(packet
, qname
, QType::A
);
109 pw
.getHeader()->rd
=true;
110 pw
.getHeader()->qr
=false;
111 pw
.getHeader()->id
=dns_random(UINT16_MAX
);
112 string
qpacket(reinterpret_cast<const char*>(&packet
[0]), packet
.size());
113 pw
.startRecord(qname
, QType::A
, ttd
);
115 /* Both interfaces (with and without the qname/qtype/qclass) should get the same hash */
116 BOOST_CHECK_EQUAL(rpc
.getResponsePacket(tag1
, qpacket
, time(nullptr), &fpacket
, &age
, &qhash
), false);
117 BOOST_CHECK_EQUAL(rpc
.getResponsePacket(tag1
, qpacket
, qname
, QType::A
, QClass::IN
, time(nullptr), &fpacket
, &age
, &temphash
), false);
118 BOOST_CHECK_EQUAL(qhash
, temphash
);
120 /* Different tag, should still get get the same hash, for both interfaces */
121 BOOST_CHECK_EQUAL(rpc
.getResponsePacket(tag2
, qpacket
, time(nullptr), &fpacket
, &age
, &temphash
), false);
122 BOOST_CHECK_EQUAL(qhash
, temphash
);
123 BOOST_CHECK_EQUAL(rpc
.getResponsePacket(tag2
, qpacket
, qname
, QType::A
, QClass::IN
, time(nullptr), &fpacket
, &age
, &temphash
), false);
124 BOOST_CHECK_EQUAL(qhash
, temphash
);
127 ARecordContent
ar("127.0.0.1");
131 string
r1packet(reinterpret_cast<const char*>(&packet
[0]), packet
.size());
134 ARecordContent
ar("127.0.0.2");
138 string
r2packet(reinterpret_cast<const char*>(&packet
[0]), packet
.size());
140 BOOST_CHECK(r1packet
!= r2packet
);
142 /* inserting a response for tag1 */
143 rpc
.insertResponsePacket(tag1
, qhash
, string(qpacket
), qname
, QType::A
, QClass::IN
, string(r1packet
), time(0), ttd
, Indeterminate
, 0, 0, boost::none
);
144 BOOST_CHECK_EQUAL(rpc
.size(), 1);
146 /* inserting a different response for tag2, should not override the first one */
147 rpc
.insertResponsePacket(tag2
, qhash
, string(qpacket
), qname
, QType::A
, QClass::IN
, string(r2packet
), time(0), ttd
, Indeterminate
, 0, 0, boost::none
);
148 BOOST_CHECK_EQUAL(rpc
.size(), 2);
150 /* remove all responses from the cache */
152 BOOST_CHECK_EQUAL(rpc
.size(), 0);
155 rpc
.insertResponsePacket(tag1
, qhash
, string(qpacket
), qname
, QType::A
, QClass::IN
, string(r1packet
), time(0), ttd
, Indeterminate
, 0, 0, boost::none
);
156 BOOST_CHECK_EQUAL(rpc
.size(), 1);
158 rpc
.insertResponsePacket(tag2
, qhash
, string(qpacket
), qname
, QType::A
, QClass::IN
, string(r2packet
), time(0), ttd
, Indeterminate
, 0, 0, boost::none
);
159 BOOST_CHECK_EQUAL(rpc
.size(), 2);
161 /* remove the responses by qname, should remove both */
162 rpc
.doWipePacketCache(qname
);
163 BOOST_CHECK_EQUAL(rpc
.size(), 0);
165 /* insert the response for tag1 */
166 rpc
.insertResponsePacket(tag1
, qhash
, string(qpacket
), qname
, QType::A
, QClass::IN
, string(r1packet
), time(0), ttd
, Indeterminate
, 0, 0, boost::none
);
167 BOOST_CHECK_EQUAL(rpc
.size(), 1);
169 /* we can retrieve it */
170 BOOST_CHECK_EQUAL(rpc
.getResponsePacket(tag1
, qpacket
, qname
, QType::A
, QClass::IN
, time(nullptr), &fpacket
, &age
, &temphash
), true);
171 BOOST_CHECK_EQUAL(qhash
, temphash
);
172 BOOST_CHECK_EQUAL(fpacket
, r1packet
);
174 /* with both interfaces */
175 BOOST_CHECK_EQUAL(rpc
.getResponsePacket(tag1
, qpacket
, time(nullptr), &fpacket
, &age
, &temphash
), true);
176 BOOST_CHECK_EQUAL(qhash
, temphash
);
177 BOOST_CHECK_EQUAL(fpacket
, r1packet
);
179 /* but not with the second tag */
180 BOOST_CHECK_EQUAL(rpc
.getResponsePacket(tag2
, qpacket
, qname
, QType::A
, QClass::IN
, time(nullptr), &fpacket
, &age
, &temphash
), false);
181 /* we should still get the same hash */
182 BOOST_CHECK_EQUAL(temphash
, qhash
);
184 /* adding a response for the second tag */
185 rpc
.insertResponsePacket(tag2
, qhash
, string(qpacket
), qname
, QType::A
, QClass::IN
, string(r2packet
), time(0), ttd
, Indeterminate
, 0, 0, boost::none
);
186 BOOST_CHECK_EQUAL(rpc
.size(), 2);
188 /* We still get the correct response for the first tag */
189 BOOST_CHECK_EQUAL(rpc
.getResponsePacket(tag1
, qpacket
, time(nullptr), &fpacket
, &age
, &temphash
), true);
190 BOOST_CHECK_EQUAL(qhash
, temphash
);
191 BOOST_CHECK_EQUAL(fpacket
, r1packet
);
193 BOOST_CHECK_EQUAL(rpc
.getResponsePacket(tag1
, qpacket
, qname
, QType::A
, QClass::IN
, time(nullptr), &fpacket
, &age
, &temphash
), true);
194 BOOST_CHECK_EQUAL(qhash
, temphash
);
195 BOOST_CHECK_EQUAL(fpacket
, r1packet
);
197 /* and the correct response for the second tag */
198 BOOST_CHECK_EQUAL(rpc
.getResponsePacket(tag2
, qpacket
, time(nullptr), &fpacket
, &age
, &temphash
), true);
199 BOOST_CHECK_EQUAL(qhash
, temphash
);
200 BOOST_CHECK_EQUAL(fpacket
, r2packet
);
202 BOOST_CHECK_EQUAL(rpc
.getResponsePacket(tag2
, qpacket
, qname
, QType::A
, QClass::IN
, time(nullptr), &fpacket
, &age
, &temphash
), true);
203 BOOST_CHECK_EQUAL(qhash
, temphash
);
204 BOOST_CHECK_EQUAL(fpacket
, r2packet
);
207 BOOST_AUTO_TEST_SUITE_END()