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