]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/test-recpacketcache_cc.cc
Merge pull request #5206 from rgacogne/rec-packetcache-tag-unit-tests
[thirdparty/pdns.git] / pdns / test-recpacketcache_cc.cc
1 #define BOOST_TEST_DYN_LINK
2 #define BOOST_TEST_NO_MAIN
3
4 #ifdef HAVE_CONFIG_H
5 #include "config.h"
6 #endif
7 #include <boost/test/unit_test.hpp>
8 #include "dnswriter.hh"
9 #include "dnsrecords.hh"
10 #include "dns_random.hh"
11 #include "iputils.hh"
12 #include "recpacketcache.hh"
13 #include <utility>
14
15
16 BOOST_AUTO_TEST_SUITE(recpacketcache_cc)
17
18 BOOST_AUTO_TEST_CASE(test_recPacketCacheSimple) {
19 RecursorPacketCache rpc;
20 string fpacket;
21 unsigned int tag=0;
22 uint32_t age=0;
23 uint32_t qhash=0;
24 uint32_t ttd=3600;
25 BOOST_CHECK_EQUAL(rpc.size(), 0);
26
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);
35
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);
38
39 ARecordContent ar("127.0.0.1");
40 ar.toPacket(pw);
41 pw.commit();
42 string rpacket((const char*)&packet[0], packet.size());
43
44 rpc.insertResponsePacket(tag, qhash, qname, QType::A, QClass::IN, rpacket, time(0), ttd);
45 BOOST_CHECK_EQUAL(rpc.size(), 1);
46 rpc.doPruneTo(0);
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);
52
53 rpc.insertResponsePacket(tag, qhash, qname, QType::A, QClass::IN, rpacket, time(0), ttd);
54 uint32_t qhash2 = 0;
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);
63
64 packet.clear();
65 qname+=DNSName("co.uk");
66 DNSPacketWriter pw2(packet, qname, QType::A);
67
68 pw2.getHeader()->rd=true;
69 pw2.getHeader()->qr=false;
70 pw2.getHeader()->id=random();
71 qpacket.assign((const char*)&packet[0], packet.size());
72
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);
77
78 rpc.doWipePacketCache(DNSName("com"), 0xffff, true);
79 BOOST_CHECK_EQUAL(rpc.size(), 0);
80 }
81
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.
87 */
88 RecursorPacketCache rpc;
89 string fpacket;
90 const unsigned int tag1=0;
91 const unsigned int tag2=42;
92 uint32_t age=0;
93 uint32_t qhash=0;
94 uint32_t temphash=0;
95 uint32_t ttd=3600;
96 BOOST_CHECK_EQUAL(rpc.size(), 0);
97
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);
106
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);
111
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);
117
118 {
119 ARecordContent ar("127.0.0.1");
120 ar.toPacket(pw);
121 pw.commit();
122 }
123 string r1packet(reinterpret_cast<const char*>(&packet[0]), packet.size());
124
125 {
126 ARecordContent ar("127.0.0.2");
127 ar.toPacket(pw);
128 pw.commit();
129 }
130 string r2packet(reinterpret_cast<const char*>(&packet[0]), packet.size());
131
132 BOOST_CHECK(r1packet != r2packet);
133
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);
137
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);
141
142 /* remove all responses from the cache */
143 rpc.doPruneTo(0);
144 BOOST_CHECK_EQUAL(rpc.size(), 0);
145
146 /* reinsert both */
147 rpc.insertResponsePacket(tag1, qhash, qname, QType::A, QClass::IN, r1packet, time(0), ttd);
148 BOOST_CHECK_EQUAL(rpc.size(), 1);
149
150 rpc.insertResponsePacket(tag2, qhash, qname, QType::A, QClass::IN, r2packet, time(0), ttd);
151 BOOST_CHECK_EQUAL(rpc.size(), 2);
152
153 /* remove the responses by qname, should remove both */
154 rpc.doWipePacketCache(qname);
155 BOOST_CHECK_EQUAL(rpc.size(), 0);
156
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);
160
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);
165
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);
170
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);
175
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);
179
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);
184
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);
188
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);
193
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);
197 }
198
199 BOOST_AUTO_TEST_SUITE_END()