]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/test-dnsdistpacketcache_cc.cc
Merge pull request #6096 from alexjfisher/docs_database_slaves
[thirdparty/pdns.git] / pdns / test-dnsdistpacketcache_cc.cc
CommitLineData
886e2cf2
RG
1#define BOOST_TEST_DYN_LINK
2#define BOOST_TEST_NO_MAIN
3
4#include <boost/test/unit_test.hpp>
5
1ea747c0 6#include "dnsdist.hh"
886e2cf2 7#include "iputils.hh"
886e2cf2 8#include "dnswriter.hh"
1ea747c0 9#include "dnsdist-cache.hh"
886e2cf2
RG
10
11BOOST_AUTO_TEST_SUITE(dnsdistpacketcache_cc)
12
13BOOST_AUTO_TEST_CASE(test_PacketCacheSimple) {
14 const size_t maxEntries = 150000;
15 DNSDistPacketCache PC(maxEntries, 86400, 1);
16 BOOST_CHECK_EQUAL(PC.getSize(), 0);
17
18 size_t counter=0;
19 size_t skipped=0;
1ea747c0 20 ComboAddress remote;
886e2cf2
RG
21 try {
22 for(counter = 0; counter < 100000; ++counter) {
490dc586 23 DNSName a=DNSName(std::to_string(counter))+DNSName(" hello");
886e2cf2
RG
24 BOOST_CHECK_EQUAL(DNSName(a.toString()), a);
25
26 vector<uint8_t> query;
27 DNSPacketWriter pwQ(query, a, QType::A, QClass::IN, 0);
28 pwQ.getHeader()->rd = 1;
29
30 vector<uint8_t> response;
31 DNSPacketWriter pwR(response, a, QType::A, QClass::IN, 0);
32 pwR.getHeader()->rd = 1;
33 pwR.getHeader()->ra = 1;
34 pwR.getHeader()->qr = 1;
35 pwR.getHeader()->id = pwQ.getHeader()->id;
36 pwR.startRecord(a, QType::A, 100, QClass::IN, DNSResourceRecord::ANSWER);
37 pwR.xfr32BitInt(0x01020304);
38 pwR.commit();
39 uint16_t responseLen = response.size();
40
41 char responseBuf[4096];
42 uint16_t responseBufSize = sizeof(responseBuf);
43 uint32_t key = 0;
1ea747c0
RG
44 DNSQuestion dq(&a, QType::A, QClass::IN, &remote, &remote, (struct dnsheader*) query.data(), query.size(), query.size(), false);
45 bool found = PC.get(dq, a.wirelength(), 0, responseBuf, &responseBufSize, &key);
886e2cf2
RG
46 BOOST_CHECK_EQUAL(found, false);
47
2714396e 48 PC.insert(key, a, QType::A, QClass::IN, (const char*) response.data(), responseLen, false, 0);
886e2cf2 49
1ea747c0 50 found = PC.get(dq, a.wirelength(), pwR.getHeader()->id, responseBuf, &responseBufSize, &key, 0, true);
886e2cf2
RG
51 if (found == true) {
52 BOOST_CHECK_EQUAL(responseBufSize, responseLen);
53 int match = memcmp(responseBuf, response.data(), responseLen);
54 BOOST_CHECK_EQUAL(match, 0);
55 }
56 else {
57 skipped++;
58 }
59 }
60
61 BOOST_CHECK_EQUAL(skipped, PC.getInsertCollisions());
62 BOOST_CHECK_EQUAL(PC.getSize(), counter - skipped);
63
64 size_t deleted=0;
65 size_t delcounter=0;
66 for(delcounter=0; delcounter < counter/1000; ++delcounter) {
490dc586 67 DNSName a=DNSName(std::to_string(delcounter))+DNSName(" hello");
886e2cf2
RG
68 vector<uint8_t> query;
69 DNSPacketWriter pwQ(query, a, QType::A, QClass::IN, 0);
70 pwQ.getHeader()->rd = 1;
71 char responseBuf[4096];
72 uint16_t responseBufSize = sizeof(responseBuf);
73 uint32_t key = 0;
1ea747c0
RG
74 DNSQuestion dq(&a, QType::A, QClass::IN, &remote, &remote, (struct dnsheader*) query.data(), query.size(), query.size(), false);
75 bool found = PC.get(dq, a.wirelength(), 0, responseBuf, &responseBufSize, &key);
886e2cf2 76 if (found == true) {
4275aaba 77 PC.expungeByName(a);
886e2cf2
RG
78 deleted++;
79 }
80 }
81 BOOST_CHECK_EQUAL(PC.getSize(), counter - skipped - deleted);
82
490dc586 83
886e2cf2
RG
84 size_t matches=0;
85 vector<DNSResourceRecord> entry;
86 size_t expected=counter-skipped-deleted;
87 for(; delcounter < counter; ++delcounter) {
490dc586 88 DNSName a(DNSName(std::to_string(delcounter))+DNSName(" hello"));
886e2cf2
RG
89 vector<uint8_t> query;
90 DNSPacketWriter pwQ(query, a, QType::A, QClass::IN, 0);
91 pwQ.getHeader()->rd = 1;
92 uint16_t len = query.size();
93 uint32_t key = 0;
94 char response[4096];
95 uint16_t responseSize = sizeof(response);
1ea747c0
RG
96 DNSQuestion dq(&a, QType::A, QClass::IN, &remote, &remote, (struct dnsheader*) query.data(), len, query.size(), false);
97 if(PC.get(dq, a.wirelength(), pwQ.getHeader()->id, response, &responseSize, &key)) {
490dc586 98 matches++;
886e2cf2
RG
99 }
100 }
101 BOOST_CHECK_EQUAL(matches, expected);
490dc586
RG
102
103 PC.expungeByName(DNSName(" hello"), QType::ANY, true);
104 BOOST_CHECK_EQUAL(PC.getSize(), 0);
886e2cf2
RG
105 }
106 catch(PDNSException& e) {
107 cerr<<"Had error: "<<e.reason<<endl;
108 throw;
109 }
110}
111
112static DNSDistPacketCache PC(500000);
113
af619119 114static void *threadMangler(void* off)
886e2cf2
RG
115{
116 try {
1ea747c0 117 ComboAddress remote;
af619119 118 unsigned int offset=(unsigned int)(unsigned long)off;
886e2cf2
RG
119 for(unsigned int counter=0; counter < 100000; ++counter) {
120 DNSName a=DNSName("hello ")+DNSName(std::to_string(counter+offset));
121 vector<uint8_t> query;
122 DNSPacketWriter pwQ(query, a, QType::A, QClass::IN, 0);
123 pwQ.getHeader()->rd = 1;
124
125 vector<uint8_t> response;
126 DNSPacketWriter pwR(response, a, QType::A, QClass::IN, 0);
127 pwR.getHeader()->rd = 1;
128 pwR.getHeader()->ra = 1;
129 pwR.getHeader()->qr = 1;
130 pwR.getHeader()->id = pwQ.getHeader()->id;
131 pwR.startRecord(a, QType::A, 3600, QClass::IN, DNSResourceRecord::ANSWER);
132 pwR.xfr32BitInt(0x01020304);
133 pwR.commit();
134 uint16_t responseLen = response.size();
135
136 char responseBuf[4096];
137 uint16_t responseBufSize = sizeof(responseBuf);
138 uint32_t key = 0;
1ea747c0
RG
139 DNSQuestion dq(&a, QType::A, QClass::IN, &remote, &remote, (struct dnsheader*) query.data(), query.size(), query.size(), false);
140 PC.get(dq, a.wirelength(), 0, responseBuf, &responseBufSize, &key);
886e2cf2 141
2714396e 142 PC.insert(key, a, QType::A, QClass::IN, (const char*) response.data(), responseLen, false, 0);
886e2cf2
RG
143 }
144 }
145 catch(PDNSException& e) {
146 cerr<<"Had error: "<<e.reason<<endl;
147 throw;
148 }
149 return 0;
150}
151
152AtomicCounter g_missing;
153
af619119 154static void *threadReader(void* off)
886e2cf2
RG
155{
156 try
157 {
af619119 158 unsigned int offset=(unsigned int)(unsigned long)off;
886e2cf2 159 vector<DNSResourceRecord> entry;
1ea747c0 160 ComboAddress remote;
886e2cf2
RG
161 for(unsigned int counter=0; counter < 100000; ++counter) {
162 DNSName a=DNSName("hello ")+DNSName(std::to_string(counter+offset));
163 vector<uint8_t> query;
164 DNSPacketWriter pwQ(query, a, QType::A, QClass::IN, 0);
165 pwQ.getHeader()->rd = 1;
166
167 char responseBuf[4096];
168 uint16_t responseBufSize = sizeof(responseBuf);
169 uint32_t key = 0;
1ea747c0
RG
170 DNSQuestion dq(&a, QType::A, QClass::IN, &remote, &remote, (struct dnsheader*) query.data(), query.size(), query.size(), false);
171 bool found = PC.get(dq, a.wirelength(), 0, responseBuf, &responseBufSize, &key);
886e2cf2
RG
172 if (!found) {
173 g_missing++;
174 }
175 }
176 }
177 catch(PDNSException& e) {
178 cerr<<"Had error in threadReader: "<<e.reason<<endl;
179 throw;
180 }
181 return 0;
182}
183
184BOOST_AUTO_TEST_CASE(test_PacketCacheThreaded) {
185 try {
186 pthread_t tid[4];
187 for(int i=0; i < 4; ++i)
188 pthread_create(&tid[i], 0, threadMangler, (void*)(i*1000000UL));
189 void* res;
190 for(int i=0; i < 4 ; ++i)
191 pthread_join(tid[i], &res);
192
193 BOOST_CHECK_EQUAL(PC.getSize() + PC.getDeferredInserts() + PC.getInsertCollisions(), 400000);
194 BOOST_CHECK_SMALL(1.0*PC.getInsertCollisions(), 10000.0);
195
196 for(int i=0; i < 4; ++i)
197 pthread_create(&tid[i], 0, threadReader, (void*)(i*1000000UL));
198 for(int i=0; i < 4 ; ++i)
199 pthread_join(tid[i], &res);
200
201 BOOST_CHECK((PC.getDeferredInserts() + PC.getDeferredLookups() + PC.getInsertCollisions()) >= g_missing);
202 }
203 catch(PDNSException& e) {
204 cerr<<"Had error: "<<e.reason<<endl;
205 throw;
206 }
207
208}
209
210BOOST_AUTO_TEST_SUITE_END()