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(test_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
, string(qpacket
), qname
, QType::A
, QClass::IN
, string(rpacket
), time(0), ttd
, Indeterminate
, 0, 0, boost::none
);
45 BOOST_CHECK_EQUAL(rpc
.size(), 1);
47 BOOST_CHECK_EQUAL(rpc
.size(), 0);
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);
50 rpc
.doWipePacketCache(qname
);
51 BOOST_CHECK_EQUAL(rpc
.size(), 0);
53 rpc
.insertResponsePacket(tag
, qhash
, string(qpacket
), qname
, QType::A
, QClass::IN
, string(rpacket
), time(0), ttd
, Indeterminate
, 0, 0, boost::none
);
54 BOOST_CHECK_EQUAL(rpc
.size(), 1);
56 bool found
= rpc
.getResponsePacket(tag
, qpacket
, time(nullptr), &fpacket
, &age
, &qhash2
);
57 BOOST_CHECK_EQUAL(found
, true);
58 BOOST_CHECK_EQUAL(qhash
, qhash2
);
59 BOOST_CHECK_EQUAL(fpacket
, rpacket
);
60 found
= rpc
.getResponsePacket(tag
, qpacket
, qname
, QType::A
, QClass::IN
, time(nullptr), &fpacket
, &age
, &qhash2
);
61 BOOST_CHECK_EQUAL(found
, true);
62 BOOST_CHECK_EQUAL(qhash
, qhash2
);
63 BOOST_CHECK_EQUAL(fpacket
, rpacket
);
66 qname
+=DNSName("co.uk");
67 DNSPacketWriter
pw2(packet
, qname
, QType::A
);
69 pw2
.getHeader()->rd
=true;
70 pw2
.getHeader()->qr
=false;
71 pw2
.getHeader()->id
=random();
72 qpacket
.assign((const char*)&packet
[0], packet
.size());
74 found
= rpc
.getResponsePacket(tag
, qpacket
, time(nullptr), &fpacket
, &age
, &qhash
);
75 BOOST_CHECK_EQUAL(found
, false);
76 found
= rpc
.getResponsePacket(tag
, qpacket
, qname
, QType::A
, QClass::IN
, time(nullptr), &fpacket
, &age
, &qhash
);
77 BOOST_CHECK_EQUAL(found
, false);
79 rpc
.doWipePacketCache(DNSName("com"), 0xffff, true);
80 BOOST_CHECK_EQUAL(rpc
.size(), 0);
83 BOOST_AUTO_TEST_CASE(test_recPacketCache_Tags
) {
84 /* Insert a response with tag1, the exact same query with a different tag
85 should lead to a miss. Inserting a different response with the second tag
86 should not override the first one, and we should get a hit for the
87 query with either tags, with the response matching the tag.
89 RecursorPacketCache rpc
;
91 const unsigned int tag1
=0;
92 const unsigned int tag2
=42;
97 BOOST_CHECK_EQUAL(rpc
.size(), 0);
99 DNSName
qname("www.powerdns.com");
100 vector
<uint8_t> packet
;
101 DNSPacketWriter
pw(packet
, qname
, QType::A
);
102 pw
.getHeader()->rd
=true;
103 pw
.getHeader()->qr
=false;
104 pw
.getHeader()->id
=random();
105 string
qpacket(reinterpret_cast<const char*>(&packet
[0]), packet
.size());
106 pw
.startRecord(qname
, QType::A
, ttd
);
108 /* Both interfaces (with and without the qname/qtype/qclass) should get the same hash */
109 BOOST_CHECK_EQUAL(rpc
.getResponsePacket(tag1
, qpacket
, time(nullptr), &fpacket
, &age
, &qhash
), false);
110 BOOST_CHECK_EQUAL(rpc
.getResponsePacket(tag1
, qpacket
, qname
, QType::A
, QClass::IN
, time(nullptr), &fpacket
, &age
, &temphash
), false);
111 BOOST_CHECK_EQUAL(qhash
, temphash
);
113 /* Different tag, should still get get the same hash, for both interfaces */
114 BOOST_CHECK_EQUAL(rpc
.getResponsePacket(tag2
, qpacket
, time(nullptr), &fpacket
, &age
, &temphash
), false);
115 BOOST_CHECK_EQUAL(qhash
, temphash
);
116 BOOST_CHECK_EQUAL(rpc
.getResponsePacket(tag2
, qpacket
, qname
, QType::A
, QClass::IN
, time(nullptr), &fpacket
, &age
, &temphash
), false);
117 BOOST_CHECK_EQUAL(qhash
, temphash
);
120 ARecordContent
ar("127.0.0.1");
124 string
r1packet(reinterpret_cast<const char*>(&packet
[0]), packet
.size());
127 ARecordContent
ar("127.0.0.2");
131 string
r2packet(reinterpret_cast<const char*>(&packet
[0]), packet
.size());
133 BOOST_CHECK(r1packet
!= r2packet
);
135 /* inserting a response for tag1 */
136 rpc
.insertResponsePacket(tag1
, qhash
, string(qpacket
), qname
, QType::A
, QClass::IN
, string(r1packet
), time(0), ttd
, Indeterminate
, 0, 0, boost::none
);
137 BOOST_CHECK_EQUAL(rpc
.size(), 1);
139 /* inserting a different response for tag2, should not override the first one */
140 rpc
.insertResponsePacket(tag2
, qhash
, string(qpacket
), qname
, QType::A
, QClass::IN
, string(r2packet
), time(0), ttd
, Indeterminate
, 0, 0, boost::none
);
141 BOOST_CHECK_EQUAL(rpc
.size(), 2);
143 /* remove all responses from the cache */
145 BOOST_CHECK_EQUAL(rpc
.size(), 0);
148 rpc
.insertResponsePacket(tag1
, qhash
, string(qpacket
), qname
, QType::A
, QClass::IN
, string(r1packet
), time(0), ttd
, Indeterminate
, 0, 0, boost::none
);
149 BOOST_CHECK_EQUAL(rpc
.size(), 1);
151 rpc
.insertResponsePacket(tag2
, qhash
, string(qpacket
), qname
, QType::A
, QClass::IN
, string(r2packet
), time(0), ttd
, Indeterminate
, 0, 0, boost::none
);
152 BOOST_CHECK_EQUAL(rpc
.size(), 2);
154 /* remove the responses by qname, should remove both */
155 rpc
.doWipePacketCache(qname
);
156 BOOST_CHECK_EQUAL(rpc
.size(), 0);
158 /* insert the response for tag1 */
159 rpc
.insertResponsePacket(tag1
, qhash
, string(qpacket
), qname
, QType::A
, QClass::IN
, string(r1packet
), time(0), ttd
, Indeterminate
, 0, 0, boost::none
);
160 BOOST_CHECK_EQUAL(rpc
.size(), 1);
162 /* we can retrieve it */
163 BOOST_CHECK_EQUAL(rpc
.getResponsePacket(tag1
, qpacket
, qname
, QType::A
, QClass::IN
, time(nullptr), &fpacket
, &age
, &temphash
), true);
164 BOOST_CHECK_EQUAL(qhash
, temphash
);
165 BOOST_CHECK_EQUAL(fpacket
, r1packet
);
167 /* with both interfaces */
168 BOOST_CHECK_EQUAL(rpc
.getResponsePacket(tag1
, qpacket
, time(nullptr), &fpacket
, &age
, &temphash
), true);
169 BOOST_CHECK_EQUAL(qhash
, temphash
);
170 BOOST_CHECK_EQUAL(fpacket
, r1packet
);
172 /* but not with the second tag */
173 BOOST_CHECK_EQUAL(rpc
.getResponsePacket(tag2
, qpacket
, qname
, QType::A
, QClass::IN
, time(nullptr), &fpacket
, &age
, &temphash
), false);
174 /* we should still get the same hash */
175 BOOST_CHECK_EQUAL(temphash
, qhash
);
177 /* adding a response for the second tag */
178 rpc
.insertResponsePacket(tag2
, qhash
, string(qpacket
), qname
, QType::A
, QClass::IN
, string(r2packet
), time(0), ttd
, Indeterminate
, 0, 0, boost::none
);
179 BOOST_CHECK_EQUAL(rpc
.size(), 2);
181 /* We still get the correct response for the first tag */
182 BOOST_CHECK_EQUAL(rpc
.getResponsePacket(tag1
, qpacket
, time(nullptr), &fpacket
, &age
, &temphash
), true);
183 BOOST_CHECK_EQUAL(qhash
, temphash
);
184 BOOST_CHECK_EQUAL(fpacket
, r1packet
);
186 BOOST_CHECK_EQUAL(rpc
.getResponsePacket(tag1
, qpacket
, qname
, QType::A
, QClass::IN
, time(nullptr), &fpacket
, &age
, &temphash
), true);
187 BOOST_CHECK_EQUAL(qhash
, temphash
);
188 BOOST_CHECK_EQUAL(fpacket
, r1packet
);
190 /* and the correct response for the second tag */
191 BOOST_CHECK_EQUAL(rpc
.getResponsePacket(tag2
, qpacket
, time(nullptr), &fpacket
, &age
, &temphash
), true);
192 BOOST_CHECK_EQUAL(qhash
, temphash
);
193 BOOST_CHECK_EQUAL(fpacket
, r2packet
);
195 BOOST_CHECK_EQUAL(rpc
.getResponsePacket(tag2
, qpacket
, qname
, QType::A
, QClass::IN
, time(nullptr), &fpacket
, &age
, &temphash
), true);
196 BOOST_CHECK_EQUAL(qhash
, temphash
);
197 BOOST_CHECK_EQUAL(fpacket
, r2packet
);
200 BOOST_AUTO_TEST_SUITE_END()