1 #define BOOST_TEST_DYN_LINK
2 #define BOOST_TEST_NO_MAIN
3 #include <boost/test/unit_test.hpp>
4 #include <boost/assign/std/map.hpp>
9 #include "dnswriter.hh"
10 #include "dnsrecords.hh"
11 #include <unordered_set>
12 using namespace boost
;
15 BOOST_AUTO_TEST_SUITE(test_dnsname_cc
)
17 BOOST_AUTO_TEST_CASE(test_basic
) {
18 DNSName
aroot("a.root-servers.net"), broot("b.root-servers.net");
19 BOOST_CHECK(aroot
< broot
);
20 BOOST_CHECK(!(broot
< aroot
));
21 BOOST_CHECK(aroot
.canonCompare(broot
));
22 BOOST_CHECK(!broot
.canonCompare(aroot
));
25 string
before("www.ds9a.nl.");
27 BOOST_CHECK_EQUAL(b
.getRawLabels().size(), 3);
28 string
after(b
.toString());
29 BOOST_CHECK_EQUAL(before
, after
);
31 DNSName
jpmens("ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc.bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.test.xxx.yyy-yyyy.zzzzzzzzz-test.");
33 BOOST_CHECK_EQUAL(jpmens
.toString(), "ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc.bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.test.xxx.yyy-yyyy.zzzzzzzzz-test.");
35 DNSName
wwwds9anl("www.ds9a.nl.");
36 DNSName
wwwds9anl1("www.ds9a\002nl.");
38 BOOST_CHECK(wwwds9anl
.isPartOf(nl
));
39 BOOST_CHECK(!wwwds9anl1
.isPartOf(nl
));
40 BOOST_CHECK(wwwds9anl
.isPartOf(wwwds9anl
));
42 BOOST_CHECK(!nl
.isPartOf(wwwds9anl
));
44 BOOST_CHECK(wwwds9anl
== wwwds9anl
);
46 BOOST_CHECK(DNSName("wWw.ds9A.Nl.") == DNSName("www.ds9a.nl."));
47 BOOST_CHECK(DNSName("www.ds9a.nl.") == DNSName("www.ds9a.nl."));
49 BOOST_CHECK(DNSName("www.ds9a.nl.").toString() == "www.ds9a.nl.");
52 { // Check root vs empty
53 DNSName
name("."); // root
54 DNSName parent
; // empty
55 BOOST_CHECK(name
!= parent
);
58 { // Check name part of root
61 BOOST_CHECK(name
.isPartOf(parent
));
65 DNSName
name("a\002bb.");
66 DNSName
parent("bb.");
67 BOOST_CHECK(!name
.isPartOf(parent
));
70 { // Multi label parent
71 DNSName
name("a.bb.ccc.dddd.");
72 DNSName
parent("ccc.dddd.");
73 BOOST_CHECK(name
.isPartOf(parent
));
77 DNSName
name("a.bb.ccc.dddd.");
78 DNSName
parent("ccc.dddx.");
79 BOOST_CHECK(!name
.isPartOf(parent
));
82 { // Equal length identical
83 DNSName
name("aaaa.bbb.cc.d.");
84 DNSName
parent("aaaa.bbb.cc.d.");
85 BOOST_CHECK(name
.isPartOf(parent
));
88 { // Equal length first char diff
89 DNSName
name("xaaa.bbb.cc.d.");
90 DNSName
parent("aaaa.bbb.cc.d.");
91 BOOST_CHECK(!name
.isPartOf(parent
));
95 DNSName
name("aaaa.bbb.cc.d.");
96 DNSName
parent("cc.d.");
97 BOOST_CHECK_EQUAL( name
.makeRelative(parent
), DNSName("aaaa.bbb."));
101 DNSName
name("aaaa.bbb.cc.d.");
102 BOOST_CHECK( name
.labelReverse() == DNSName("d.cc.bbb.aaaa."));
107 BOOST_CHECK(name
.empty());
112 BOOST_CHECK(!name
.empty());
114 DNSName
rootnodot("");
115 BOOST_CHECK_EQUAL(name
, rootnodot
);
118 DNSName
rootnodot2(empty
);
119 BOOST_CHECK_EQUAL(rootnodot2
, name
);
122 DNSName
left("ds9a.nl.");
123 left
.prependRawLabel("www");
124 BOOST_CHECK( left
== DNSName("WwW.Ds9A.Nl."));
126 left
.appendRawLabel("com");
128 BOOST_CHECK( left
== DNSName("WwW.Ds9A.Nl.com."));
132 unset
.appendRawLabel("www");
133 unset
.appendRawLabel("powerdns.com");
134 unset
.appendRawLabel("com");
136 BOOST_CHECK_EQUAL(unset
.toString(), "www.powerdns\\.com.com.");
138 DNSName
rfc4343_2_1("~!.example.");
139 DNSName
rfc4343_2_2(R
"(Donald\032E\.\032Eastlake\0323rd.example.)");
140 DNSName
example("example.");
141 BOOST_CHECK(rfc4343_2_1
.isPartOf(example
));
142 BOOST_CHECK(rfc4343_2_2
.isPartOf(example
));
143 BOOST_CHECK_EQUAL(rfc4343_2_1
.toString(), "~!.example.");
145 auto labels
=rfc4343_2_2
.getRawLabels();
146 BOOST_CHECK_EQUAL(*labels
.begin(), "Donald E. Eastlake 3rd");
147 BOOST_CHECK_EQUAL(*labels
.rbegin(), "example");
148 BOOST_CHECK_EQUAL(labels
.size(), 2);
151 build
.appendRawLabel("Donald E. Eastlake 3rd");
152 build
.appendRawLabel("example");
153 BOOST_CHECK_EQUAL(build
.toString(), R
"(Donald\032E\.\032Eastlake\0323rd.example.)");
154 BOOST_CHECK_THROW(DNSName
broken("bert..hubert."), std::runtime_error
);
157 n
.appendRawLabel("powerdns.dnsmaster");
158 n
.appendRawLabel("powerdns");
159 n
.appendRawLabel("com");
161 BOOST_CHECK_EQUAL(n
.toString(), "powerdns\\.dnsmaster.powerdns.com.");
163 // BOOST_CHECK(DNSName().toString() != ".");
166 string
label("power");
167 label
.append(1, (char)0);
169 p
.appendRawLabel(label
);
170 p
.appendRawLabel("com");
172 BOOST_CHECK_EQUAL(p
.toString(), "power\\000dns.com.");
175 BOOST_AUTO_TEST_CASE(test_trim
) {
176 DNSName
w("www.powerdns.com.");
177 BOOST_CHECK_EQUAL(w
.countLabels(), 3);
179 BOOST_CHECK_EQUAL(w
.toString(), "powerdns.com.");
180 DNSName
w2("powerdns.com.");
184 BOOST_CHECK_EQUAL(root
.countLabels(), 0);
187 BOOST_AUTO_TEST_CASE(test_toolong
) {
189 BOOST_CHECK_THROW(DNSName
w("1234567890123456789012345678901234567890123456789012345678901234567890.com."), std::range_error
);
191 BOOST_CHECK_THROW(DNSName
w("12345678901234567890.12345678901234567890123456.789012345678901.234567890.12345678901234567890.12345678901234567890123456.789012345678901.234567890.12345678901234567890.12345678901234567890123456.789012345678901.234567890.234567890.789012345678901.234567890.234567890.789012345678901.234567890.234567890.com."), std::range_error
);
194 BOOST_AUTO_TEST_CASE(test_dnsstrings
) {
195 DNSName
w("www.powerdns.com.");
196 BOOST_CHECK_EQUAL(w
.toDNSString(), string("\003www\010powerdns\003com\000", 18));
199 BOOST_AUTO_TEST_CASE(test_empty
) {
201 BOOST_CHECK_THROW(empty
.toString(), std::out_of_range
);
202 BOOST_CHECK_THROW(empty
.toStringNoDot(), std::out_of_range
);
203 BOOST_CHECK_THROW(empty
.toDNSString(), std::out_of_range
);
204 BOOST_CHECK(empty
.empty());
205 BOOST_CHECK(!empty
.isRoot());
206 BOOST_CHECK(!empty
.isWildcard());
207 BOOST_CHECK_EQUAL(empty
, empty
);
208 BOOST_CHECK(!(empty
< empty
));
211 BOOST_CHECK(empty
< root
);
213 BOOST_CHECK_THROW(empty
.isPartOf(root
), std::out_of_range
);
214 BOOST_CHECK_THROW(root
.isPartOf(empty
), std::out_of_range
);
217 BOOST_AUTO_TEST_CASE(test_specials
) {
220 BOOST_CHECK(root
.isRoot());
221 BOOST_CHECK(root
!= DNSName());
223 DNSName
wcard("*.powerdns.com");
224 BOOST_CHECK(wcard
.isWildcard());
226 DNSName
notwcard("www.powerdns.com");
227 BOOST_CHECK(!notwcard
.isWildcard());
231 BOOST_AUTO_TEST_CASE(test_chopping
) {
232 DNSName
w("www.powerdns.com.");
233 BOOST_CHECK_EQUAL(w
.toString(), "www.powerdns.com.");
234 BOOST_CHECK(w
.chopOff());
235 BOOST_CHECK_EQUAL(w
.toString(), "powerdns.com.");
236 BOOST_CHECK(w
.chopOff());
237 BOOST_CHECK_EQUAL(w
.toString(), "com.");
238 BOOST_CHECK(w
.chopOff());
239 BOOST_CHECK_EQUAL(w
.toString(), ".");
240 BOOST_CHECK(!w
.chopOff());
241 BOOST_CHECK(!w
.chopOff());
243 w
.prependRawLabel("net");
244 w
.prependRawLabel("root-servers");
245 w
.prependRawLabel("a");
246 BOOST_CHECK_EQUAL(w
.toString(), "a.root-servers.net.");
249 BOOST_AUTO_TEST_CASE(test_Append
) {
250 DNSName
dn("www."), powerdns("powerdns.com.");
251 DNSName tot
=dn
+powerdns
;
253 BOOST_CHECK_EQUAL(tot
.toString(), "www.powerdns.com.");
254 BOOST_CHECK(tot
== DNSName("www.powerdns.com."));
258 BOOST_CHECK(dn
== DNSName("www.powerdns.com."));
261 BOOST_AUTO_TEST_CASE(test_packetCompress
) {
263 vector
<unsigned char> packet
;
264 DNSPacketWriter
dpw(packet
, DNSName("www.ds9a.nl."), QType::AAAA
);
265 dpw
.startRecord(DNSName("ds9a.nl"), QType::SOA
);
266 SOARecordContent
src("ns1.powerdns.nl admin.powerdns.nl 1 2 3 4 5");
268 AAAARecordContent
aaaa("::1");
269 dpw
.startRecord(DNSName("www.dS9A.nl"), QType::AAAA
);
271 dpw
.startRecord(DNSName("www.ds9A.nl"), QType::AAAA
);
273 dpw
.startRecord(DNSName("www.dS9a.nl"), QType::AAAA
);
275 dpw
.startRecord(DNSName("www2.DS9a.nl"), QType::AAAA
);
277 dpw
.startRecord(DNSName("www2.dS9a.nl"), QType::AAAA
);
280 string
str((const char*)&packet
[0], (const char*)&packet
[0] + packet
.size());
283 while((pos
= str
.find("ds9a", pos
)) != string::npos
) {
287 BOOST_CHECK_EQUAL(count
, 1);
290 while((pos
= str
.find("powerdns", pos
)) != string::npos
) {
294 BOOST_CHECK_EQUAL(count
, 1);
298 BOOST_AUTO_TEST_CASE(test_packetCompressLong
) {
300 vector
<unsigned char> packet
;
301 DNSName
loopback("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa");
302 DNSPacketWriter
dpw(packet
, loopback
, QType::PTR
);
304 dpw
.startRecord(loopback
, QType::PTR
);
305 PTRRecordContent
prc(DNSName("localhost"));
308 DNSName
roundtrip((char*)&packet
[0], packet
.size(), 12, false);
309 BOOST_CHECK_EQUAL(loopback
,roundtrip
);
312 DNSName
longer("1.2.3.4.5.6.7.8.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa");
313 DNSPacketWriter
dpw2(packet
, longer
, QType::PTR
);
315 dpw2
.startRecord(DNSName("a.b.c.d.e")+longer
, QType::PTR
);
316 PTRRecordContent
prc2(DNSName("localhost"));
325 BOOST_AUTO_TEST_CASE(test_PacketParse
) {
326 vector
<unsigned char> packet
;
329 DNSPacketWriter
dpw1(packet
, g_rootdnsname
, QType::AAAA
);
330 DNSName
p((char*)&packet
[0], packet
.size(), 12, false);
331 BOOST_CHECK_EQUAL(p
, root
);
332 unsigned char* buffer
=&packet
[0];
333 /* set invalid label len:
334 - packet.size() == 17 (sizeof(dnsheader) + 1 + 2 + 2)
335 - label len < packet.size() but
336 - offset is 12, label len of 15 should be rejected
337 because offset + 15 >= packet.size()
339 buffer
[sizeof(dnsheader
)] = 15;
340 BOOST_CHECK_THROW(DNSName((char*)&packet
[0], packet
.size(), 12, false), std::range_error
);
344 BOOST_AUTO_TEST_CASE(test_hash
) {
345 DNSName
a("wwW.Ds9A.Nl"), b("www.ds9a.nl");
346 BOOST_CHECK_EQUAL(a
.hash(), b
.hash());
348 vector
<uint32_t> counts(1500);
350 for(unsigned int n
=0; n
< 100000; ++n
) {
351 DNSName
dn(std::to_string(n
)+"."+std::to_string(n
*2)+"ds9a.nl");
352 DNSName
dn2(std::to_string(n
)+"."+std::to_string(n
*2)+"Ds9a.nL");
353 BOOST_CHECK_EQUAL(dn
.hash(), dn2
.hash());
354 counts
[dn
.hash() % counts
.size()]++;
357 double sum
= std::accumulate(std::begin(counts
), std::end(counts
), 0.0);
358 double m
= sum
/ counts
.size();
361 std::for_each (std::begin(counts
), std::end(counts
), [&](const double d
) {
362 accum
+= (d
- m
) * (d
- m
);
365 double stdev
= sqrt(accum
/ (counts
.size()-1));
366 BOOST_CHECK(stdev
< 10);
369 BOOST_AUTO_TEST_CASE(test_hashContainer
) {
370 std::unordered_set
<DNSName
> s
;
371 s
.insert(DNSName("www.powerdns.com"));
372 BOOST_CHECK(s
.count(DNSName("WwW.PoWerDNS.CoM")));
373 BOOST_CHECK_EQUAL(s
.size(), 1);
374 s
.insert(DNSName("www.POWERDNS.com"));
375 BOOST_CHECK_EQUAL(s
.size(), 1);
376 s
.insert(DNSName("www2.POWERDNS.com"));
377 BOOST_CHECK_EQUAL(s
.size(), 2);
381 for(; n
< 100000; ++n
)
382 s
.insert(DNSName(std::to_string(n
)+".test.nl"));
383 BOOST_CHECK_EQUAL(s
.size(), n
);
388 BOOST_AUTO_TEST_CASE(test_QuestionHash
) {
389 vector
<unsigned char> packet
;
391 DNSPacketWriter
dpw1(packet
, DNSName("www.ds9a.nl."), QType::AAAA
);
393 auto hash1
=hashQuestion((char*)&packet
[0], packet
.size(), 0);
394 DNSPacketWriter
dpw2(packet
, DNSName("wWw.Ds9A.nL."), QType::AAAA
);
395 auto hash2
=hashQuestion((char*)&packet
[0], packet
.size(), 0);
396 BOOST_CHECK_EQUAL(hash1
, hash2
);
398 vector
<uint32_t> counts(1500);
400 for(unsigned int n
=0; n
< 100000; ++n
) {
402 DNSPacketWriter
dpw3(packet
, DNSName(std::to_string(n
)+"."+std::to_string(n
*2)+"."), QType::AAAA
);
403 counts
[hashQuestion((char*)&packet
[0], packet
.size(), 0) % counts
.size()]++;
406 double sum
= std::accumulate(std::begin(counts
), std::end(counts
), 0.0);
407 double m
= sum
/ counts
.size();
410 std::for_each (std::begin(counts
), std::end(counts
), [&](const double d
) {
411 accum
+= (d
- m
) * (d
- m
);
414 double stdev
= sqrt(accum
/ (counts
.size()-1));
415 BOOST_CHECK(stdev
< 10);
419 BOOST_AUTO_TEST_CASE(test_packetParse
) {
420 vector
<unsigned char> packet
;
422 DNSPacketWriter
dpw(packet
, DNSName("www.ds9a.nl."), QType::AAAA
);
424 uint16_t qtype
, qclass
;
425 DNSName
dn((char*)&packet
[0], packet
.size(), 12, false, &qtype
, &qclass
);
426 BOOST_CHECK_EQUAL(dn
.toString(), "www.ds9a.nl.");
427 BOOST_CHECK(qtype
== QType::AAAA
);
428 BOOST_CHECK_EQUAL(qclass
, 1);
430 dpw
.startRecord(DNSName("ds9a.nl."), DNSRecordContent::TypeToNumber("NS"));
431 NSRecordContent
nrc("ns1.powerdns.com");
436 /* packet now looks like this:
437 012345678901 12 bytes of header
438 3www4ds9a2nl0 13 bytes of name
439 0001 0001 4 bytes of qtype and qclass
441 0001 0001 4 bytes of qtype and class
442 0000 0000 4 bytes of TTL
443 0000 2 bytes of content length
446 DNSName
dn2((char*)&packet
[0], packet
.size(), 12+13+4, true, &qtype
, &qclass
);
447 BOOST_CHECK_EQUAL(dn2
.toString(), "ds9a.nl.");
448 BOOST_CHECK(qtype
== QType::NS
);
449 BOOST_CHECK_EQUAL(qclass
, 1);
451 DNSName
dn3((char*)&packet
[0], packet
.size(), 12+13+4+2 + 4 + 4 + 2, true);
452 BOOST_CHECK_EQUAL(dn3
.toString(), "ns1.powerdns.com.");
454 DNSName
dn4((char*)&packet
[0], packet
.size(), 12+13+4, false); // compressed, should fail
460 BOOST_AUTO_TEST_CASE(test_escaping
) {
464 for(int i
= 0; i
< 250; ++i
) {
466 n
.appendRawLabel(label
);
469 label
.append(1,(char)i
);
472 n
.appendRawLabel(label
);
474 DNSName
n2(n
.toString());
478 BOOST_AUTO_TEST_CASE(test_suffixmatch
) {
480 DNSName
ezdns("ezdns.it.");
481 smn
.add(ezdns
.getRawLabels());
483 smn
.add(DNSName("org.").getRawLabels());
485 DNSName
wwwpowerdnscom("www.powerdns.com.");
486 DNSName
wwwezdnsit("www.ezdns.it.");
487 BOOST_CHECK(smn
.check(wwwezdnsit
));
488 BOOST_CHECK(!smn
.check(wwwpowerdnscom
));
490 BOOST_CHECK(smn
.check(DNSName("www.powerdns.org.")));
491 BOOST_CHECK(smn
.check(DNSName("www.powerdns.oRG.")));
493 smn
.add(DNSName("news.bbc.co.uk."));
494 BOOST_CHECK(smn
.check(DNSName("news.bbc.co.uk.")));
495 BOOST_CHECK(smn
.check(DNSName("www.news.bbc.co.uk.")));
496 BOOST_CHECK(smn
.check(DNSName("www.www.www.www.www.news.bbc.co.uk.")));
497 BOOST_CHECK(!smn
.check(DNSName("images.bbc.co.uk.")));
499 BOOST_CHECK(!smn
.check(DNSName("www.news.gov.uk.")));
501 smn
.add(g_rootdnsname
); // block the root
502 BOOST_CHECK(smn
.check(DNSName("a.root-servers.net.")));
504 DNSName
examplenet("example.net.");
508 BOOST_CHECK(smn
.check(examplenet
));
509 BOOST_CHECK(smn
.check(net
));
511 // Remove .net and check that example.net still exists
513 BOOST_CHECK_EQUAL(smn
.check(net
), false);
514 BOOST_CHECK(smn
.check(examplenet
));
517 BOOST_AUTO_TEST_CASE(test_suffixmatch_tree
) {
518 SuffixMatchTree
<DNSName
> smt
;
519 DNSName
ezdns("ezdns.it.");
520 smt
.add(ezdns
, ezdns
);
522 smt
.add(DNSName("org.").getRawLabels(), DNSName("org."));
524 DNSName
wwwpowerdnscom("www.powerdns.com.");
525 DNSName
wwwezdnsit("www.ezdns.it.");
526 BOOST_REQUIRE(smt
.lookup(wwwezdnsit
));
527 BOOST_CHECK_EQUAL(*smt
.lookup(wwwezdnsit
), ezdns
);
528 BOOST_CHECK(smt
.lookup(wwwpowerdnscom
) == nullptr);
530 BOOST_REQUIRE(smt
.lookup(DNSName("www.powerdns.org.")));
531 BOOST_CHECK_EQUAL(*smt
.lookup(DNSName("www.powerdns.org.")), DNSName("org."));
532 BOOST_REQUIRE(smt
.lookup(DNSName("www.powerdns.oRG.")));
533 BOOST_CHECK_EQUAL(*smt
.lookup(DNSName("www.powerdns.oRG.")), DNSName("org."));
535 smt
.add(DNSName("news.bbc.co.uk."), DNSName("news.bbc.co.uk."));
536 BOOST_REQUIRE(smt
.lookup(DNSName("news.bbc.co.uk.")));
537 BOOST_CHECK_EQUAL(*smt
.lookup(DNSName("news.bbc.co.uk.")), DNSName("news.bbc.co.uk."));
538 BOOST_REQUIRE(smt
.lookup(DNSName("www.news.bbc.co.uk.")));
539 BOOST_CHECK_EQUAL(*smt
.lookup(DNSName("www.news.bbc.co.uk.")), DNSName("news.bbc.co.uk."));
540 BOOST_REQUIRE(smt
.lookup(DNSName("www.www.www.www.www.news.bbc.co.uk.")));
541 BOOST_CHECK_EQUAL(*smt
.lookup(DNSName("www.www.www.www.www.news.bbc.co.uk.")), DNSName("news.bbc.co.uk."));
542 BOOST_CHECK(smt
.lookup(DNSName("images.bbc.co.uk.")) == nullptr);
543 BOOST_CHECK(smt
.lookup(DNSName("www.news.gov.uk.")) == nullptr);
545 smt
.add(g_rootdnsname
, g_rootdnsname
); // block the root
546 BOOST_REQUIRE(smt
.lookup(DNSName("a.root-servers.net.")));
547 BOOST_CHECK_EQUAL(*smt
.lookup(DNSName("a.root-servers.net.")), g_rootdnsname
);
549 DNSName
apowerdnscom("a.powerdns.com.");
550 DNSName
bpowerdnscom("b.powerdns.com.");
551 smt
.add(apowerdnscom
, apowerdnscom
);
552 smt
.add(bpowerdnscom
, bpowerdnscom
);
553 BOOST_REQUIRE(smt
.lookup(apowerdnscom
));
554 BOOST_CHECK_EQUAL(*smt
.lookup(apowerdnscom
), apowerdnscom
);
555 BOOST_REQUIRE(smt
.lookup(bpowerdnscom
));
556 BOOST_CHECK_EQUAL(*smt
.lookup(bpowerdnscom
), bpowerdnscom
);
558 DNSName
examplenet("example.net.");
560 smt
.add(examplenet
, examplenet
);
562 BOOST_REQUIRE(smt
.lookup(examplenet
));
563 BOOST_CHECK_EQUAL(*smt
.lookup(examplenet
), examplenet
);
564 BOOST_REQUIRE(smt
.lookup(net
));
565 BOOST_CHECK_EQUAL(*smt
.lookup(net
), net
);
567 // Remove .net, and check that example.net remains
569 BOOST_CHECK(smt
.lookup(net
) == nullptr);
570 BOOST_CHECK_EQUAL(*smt
.lookup(examplenet
), examplenet
);
572 smt
= SuffixMatchTree
<DNSName
>();
573 smt
.add(examplenet
, examplenet
);
575 smt
.add(DNSName("news.bbc.co.uk."), DNSName("news.bbc.co.uk."));
576 smt
.add(apowerdnscom
, apowerdnscom
);
578 smt
.remove(DNSName("not-such-entry.news.bbc.co.uk."));
579 BOOST_REQUIRE(smt
.lookup(DNSName("news.bbc.co.uk.")));
580 smt
.remove(DNSName("news.bbc.co.uk."));
581 BOOST_CHECK(smt
.lookup(DNSName("news.bbc.co.uk.")) == nullptr);
584 BOOST_REQUIRE(smt
.lookup(examplenet
));
585 BOOST_CHECK_EQUAL(*smt
.lookup(examplenet
), examplenet
);
586 BOOST_CHECK(smt
.lookup(net
) == nullptr);
588 smt
.remove(examplenet
);
589 BOOST_CHECK(smt
.lookup(net
) == nullptr);
590 BOOST_CHECK(smt
.lookup(examplenet
) == nullptr);
592 smt
.add(examplenet
, examplenet
);
594 BOOST_REQUIRE(smt
.lookup(examplenet
));
595 BOOST_CHECK_EQUAL(*smt
.lookup(examplenet
), examplenet
);
596 BOOST_REQUIRE(smt
.lookup(net
));
597 BOOST_CHECK_EQUAL(*smt
.lookup(net
), net
);
599 smt
.remove(examplenet
);
600 BOOST_CHECK_EQUAL(*smt
.lookup(examplenet
), net
);
601 BOOST_CHECK_EQUAL(*smt
.lookup(net
), net
);
602 smt
.remove(examplenet
);
603 BOOST_CHECK_EQUAL(*smt
.lookup(examplenet
), net
);
604 BOOST_CHECK_EQUAL(*smt
.lookup(net
), net
);
606 BOOST_CHECK(smt
.lookup(net
) == nullptr);
607 BOOST_CHECK(smt
.lookup(examplenet
) == nullptr);
611 smt
.visit([apowerdnscom
, &count
](const SuffixMatchTree
<DNSName
>& smt
) {
613 BOOST_CHECK_EQUAL(smt
.d_value
, apowerdnscom
);
615 BOOST_CHECK_EQUAL(count
, 1);
617 BOOST_CHECK_EQUAL(*smt
.lookup(apowerdnscom
), apowerdnscom
);
618 smt
.remove(apowerdnscom
);
619 BOOST_CHECK(smt
.lookup(apowerdnscom
) == nullptr);
622 smt
.visit([&count
](const SuffixMatchTree
<DNSName
>& smt
) {
625 BOOST_CHECK_EQUAL(count
, 0);
629 BOOST_AUTO_TEST_CASE(test_concat
) {
630 DNSName
first("www."), second("powerdns.com.");
631 BOOST_CHECK_EQUAL((first
+second
).toString(), "www.powerdns.com.");
634 BOOST_AUTO_TEST_CASE(test_compare_naive
) {
635 BOOST_CHECK(DNSName("abc.com.") < DNSName("zdf.com."));
636 BOOST_CHECK(DNSName("Abc.com.") < DNSName("zdf.com."));
637 BOOST_CHECK(DNSName("Abc.com.") < DNSName("Zdf.com."));
638 BOOST_CHECK(DNSName("abc.com.") < DNSName("Zdf.com."));
641 BOOST_AUTO_TEST_CASE(test_compare_empty
) {
644 BOOST_CHECK(!a
.canonCompare(b
));
647 BOOST_AUTO_TEST_CASE(test_casing
) {
648 DNSName
a("WwW.PoWeRdNS.Com"), b("www.powerdns.com.");
649 BOOST_CHECK_EQUAL(a
,b
);
650 BOOST_CHECK_EQUAL(a
.toString(), "WwW.PoWeRdNS.Com.");
651 DNSName c
=a
.makeLowerCase();
652 BOOST_CHECK_EQUAL(a
,c
);
653 BOOST_CHECK_EQUAL(b
,c
);
654 BOOST_CHECK_EQUAL(c
.toString(), b
.toString());
655 BOOST_CHECK_EQUAL(c
.toString(), "www.powerdns.com.");
660 BOOST_AUTO_TEST_CASE(test_compare_canonical
) {
661 DNSName
lower("bert.com."), higher("alpha.nl.");
662 BOOST_CHECK(lower
.canonCompare(higher
));
664 BOOST_CHECK(DNSName("bert.com").canonCompare(DNSName("www.bert.com")));
665 BOOST_CHECK(DNSName("BeRt.com").canonCompare(DNSName("WWW.berT.com")));
666 BOOST_CHECK(!DNSName("www.BeRt.com").canonCompare(DNSName("WWW.berT.com")));
668 CanonDNSNameCompare a
;
669 BOOST_CHECK(a(g_rootdnsname
, DNSName("www.powerdns.com")));
670 BOOST_CHECK(a(g_rootdnsname
, DNSName("www.powerdns.net")));
671 BOOST_CHECK(!a(DNSName("www.powerdns.net"), g_rootdnsname
));
674 for(const std::string
& b
: {"bert.com.", "alpha.nl.", "articles.xxx.",
675 "Aleph1.powerdns.com.", "ZOMG.powerdns.com.", "aaa.XXX.", "yyy.XXX.",
676 "test.powerdns.com.", "\\128.com"}) {
677 vec
.push_back(DNSName(b
));
679 sort(vec
.begin(), vec
.end(), CanonDNSNameCompare());
680 // for(const auto& v : vec)
681 // cerr<<'"'<<v<<'"'<<endl;
683 vector
<DNSName
> right
;
684 for(const auto& b
: {"bert.com.", "Aleph1.powerdns.com.",
685 "test.powerdns.com.",
686 "ZOMG.powerdns.com.",
692 right
.push_back(DNSName(b
));
695 BOOST_CHECK(vec
==right
);
699 BOOST_AUTO_TEST_CASE(test_empty_label
) { // empty label
703 BOOST_CHECK_THROW(dn
.appendRawLabel(""), std::range_error
);
708 BOOST_CHECK_THROW(dn
.prependRawLabel(""), std::range_error
);
712 BOOST_AUTO_TEST_CASE(test_label_length_max
) { // 63 char label
714 string
label("123456789012345678901234567890123456789012345678901234567890123");
718 dn
.appendRawLabel(label
);
719 BOOST_CHECK_EQUAL(dn
.toString(), "www." + label
+ ".");
724 dn
.prependRawLabel(label
);
725 BOOST_CHECK_EQUAL(dn
.toString(), label
+ ".www.");
729 BOOST_AUTO_TEST_CASE(test_label_length_too_long
) { // 64 char label
731 string
label("1234567890123456789012345678901234567890123456789012345678901234");
735 BOOST_CHECK_THROW(dn
.appendRawLabel(label
), std::range_error
);
740 BOOST_CHECK_THROW(dn
.prependRawLabel(label
), std::range_error
);
744 BOOST_AUTO_TEST_CASE(test_name_length_max
) { // 255 char name
746 string
name("123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789."
747 "123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789."
748 "123456789.123456789.123456789.123456789.123456789.");
753 dn
.appendRawLabel(label
);
754 BOOST_CHECK_EQUAL(dn
.toString().size(), 254);
759 dn
.prependRawLabel(label
);
760 BOOST_CHECK_EQUAL(dn
.toString().size(), 254);
766 dn
+= DNSName(label
+ ".");
767 BOOST_CHECK_EQUAL(dn
.toString().size(), 254);
771 BOOST_AUTO_TEST_CASE(test_name_length_too_long
) { // 256 char name
773 string
name("123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789."
774 "123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789."
775 "123456789.123456789.123456789.123456789.123456789.");
776 string
label("1234");
780 BOOST_CHECK_THROW(dn
.appendRawLabel(label
), std::range_error
);
785 BOOST_CHECK_THROW(dn
.prependRawLabel(label
), std::range_error
);
790 BOOST_CHECK_THROW(dn
+= DNSName(label
+ "."), std::range_error
);
795 BOOST_AUTO_TEST_CASE(test_invalid_label_length
) { // Invalid label length in qname
797 string
name("\x02""ns\x07""example\x04""com\x00", 16);
799 BOOST_CHECK_THROW(DNSName
dn(name
.c_str(), name
.size(), 0, true), std::range_error
);
802 BOOST_AUTO_TEST_CASE(test_compression
) { // Compression test
804 string
name("\x03""com\x00""\x07""example\xc0""\x00""\x03""www\xc0""\x05", 21);
806 DNSName
dn(name
.c_str(), name
.size(), 15, true);
807 BOOST_CHECK_EQUAL(dn
.toString(), "www.example.com.");
810 BOOST_AUTO_TEST_CASE(test_compression_qtype_qclass
) { // Compression test with QClass and QType extraction
816 string
name("\x03""com\x00""\x07""example\xc0""\x00""\x03""www\xc0""\x05""\x00""\x01""\x00""\x01", 25);
817 DNSName
dn(name
.c_str(), name
.size(), 15, true, &qtype
, &qclass
);
818 BOOST_CHECK_EQUAL(dn
.toString(), "www.example.com.");
819 BOOST_CHECK_EQUAL(qtype
, 1);
820 BOOST_CHECK_EQUAL(qclass
, 1);
824 /* same but this time we are one byte short for the qclass */
825 string
name("\x03""com\x00""\x07""example\xc0""\x00""\x03""www\xc0""\x05""\x00""\x01""\x00""", 24);
826 BOOST_CHECK_THROW(DNSName
dn(name
.c_str(), name
.size(), 15, true, &qtype
, &qclass
), std::range_error
);
830 /* this time with a compression pointer such as (labellen << 8) != 0, see #4718 */
831 string
name("\x03""com\x00""\x07""example\xc1""\x00""\x03""www\xc1""\x05""\x00""\x01""\x00""\x01", 25);
832 name
.insert(0, 256, '0');
834 DNSName
dn(name
.c_str(), name
.size(), 271, true, &qtype
, &qclass
);
835 BOOST_CHECK_EQUAL(dn
.toString(), "www.example.com.");
836 BOOST_CHECK_EQUAL(qtype
, 1);
837 BOOST_CHECK_EQUAL(qclass
, 1);
841 /* same but this time we are one byte short for the qclass */
842 string
name("\x03""com\x00""\x07""example\xc1""\x00""\x03""www\xc1""\x05""\x00""\x01""\x00", 24);
843 name
.insert(0, 256, '0');
845 BOOST_CHECK_THROW(DNSName
dn(name
.c_str(), name
.size(), 271, true, &qtype
, &qclass
), std::range_error
);
849 BOOST_AUTO_TEST_CASE(test_compression_single_bit_set
) { // first 2 bits as 10 or 01, not 11
853 string
name("\x03""com\x00""\x07""example\x80""\x00""\x03""www\x80""\x05", 21);
855 BOOST_CHECK_THROW(DNSName
dn(name
.c_str(), name
.size(), 15, true), std::range_error
);
860 string
name("\x03""com\x00""\x07""example\x40""\x00""\x03""www\x40""\x05", 21);
862 BOOST_CHECK_THROW(DNSName
dn(name
.c_str(), name
.size(), 15, true), std::range_error
);
867 BOOST_AUTO_TEST_CASE(test_pointer_pointer_root
) { // Pointer to pointer to root
869 string
name("\x00""\xc0""\x00""\x03""com\xc0""\x01",9);
871 DNSName
dn(name
.c_str(), name
.size(), 3, true);
872 BOOST_CHECK_EQUAL(dn
.toString(), "com.");
875 BOOST_AUTO_TEST_CASE(test_bad_compression_pointer
) { // Pointing beyond packet boundary
877 std::string
name("\x03""com\x00""\x07""example\xc0""\x11""xc0""\x00", 17);
879 BOOST_CHECK_THROW(DNSName
dn(name
.c_str(), name
.length(), 5, true), std::range_error
);
882 BOOST_AUTO_TEST_CASE(test_compression_loop
) { // Compression loop (add one label)
884 std::string
name("\x03""www\xc0""\x00", 6);
886 BOOST_CHECK_THROW(DNSName
dn(name
.c_str(), name
.length(), 0, true), std::range_error
);
889 BOOST_AUTO_TEST_CASE(test_compression_loop1
) { // Compression loop (pointer loop)
891 string
name("\xc0""\x00", 2);
893 BOOST_CHECK_THROW(DNSName
dn(name
.c_str(), name
.size(), 0, true), std::range_error
);
896 BOOST_AUTO_TEST_CASE(test_compression_loop2
) { // Compression loop (deep recursion)
899 string
name("\x00\xc0\x00", 3);
900 for (i
=0; i
<98; ++i
) {
901 name
.append( 1, ((i
>> 7) & 0xff) | 0xc0);
902 name
.append( 1, ((i
<< 1) & 0xff) | 0x01);
904 BOOST_CHECK_NO_THROW(DNSName
dn(name
.c_str(), name
.size(), name
.size()-2, true));
907 name
.append( 1, ((i
>> 7) & 0xff) | 0xc0);
908 name
.append( 1, ((i
<< 1) & 0xff) | 0x01);
910 BOOST_CHECK_THROW(DNSName
dn(name
.c_str(), name
.size(), name
.size()-2, true), std::range_error
);
913 BOOST_AUTO_TEST_CASE(test_wirelength
) { // Testing if we get the correct value from the wirelength function
914 DNSName
name("www.powerdns.com");
915 BOOST_CHECK_EQUAL(name
.wirelength(), 18);
917 DNSName
sname("powerdns.com");
918 sname
.prependRawLabel(string("ww\x00""w", 4));
919 BOOST_CHECK_EQUAL(sname
.wirelength(), 19);
921 sname
= DNSName("powerdns.com");
922 sname
.prependRawLabel(string("www\x00", 4));
923 BOOST_CHECK_EQUAL(sname
.wirelength(), 19);
926 BOOST_AUTO_TEST_CASE(test_getrawlabel
) {
927 DNSName
name("a.bb.ccc.dddd.");
928 BOOST_CHECK_EQUAL(name
.getRawLabel(0), "a");
929 BOOST_CHECK_EQUAL(name
.getRawLabel(1), "bb");
930 BOOST_CHECK_EQUAL(name
.getRawLabel(2), "ccc");
931 BOOST_CHECK_EQUAL(name
.getRawLabel(3), "dddd");
932 BOOST_CHECK_THROW(name
.getRawLabel(name
.countLabels()), std::out_of_range
);
935 BOOST_AUTO_TEST_CASE(test_getlastlabel
) {
936 DNSName
name("www.powerdns.com");
937 DNSName ans
= name
.getLastLabel();
939 // Check the const-ness
940 BOOST_CHECK_EQUAL(name
, DNSName("www.powerdns.com"));
942 // Check if the last label is indeed returned
943 BOOST_CHECK_EQUAL(ans
, DNSName("com"));
946 BOOST_AUTO_TEST_CASE(test_getcommonlabels
) {
947 const DNSName
name1("www.powerdns.com");
948 const DNSName
name2("a.long.list.of.labels.powerdns.com");
950 BOOST_CHECK_EQUAL(name1
.getCommonLabels(name1
), name1
);
951 BOOST_CHECK_EQUAL(name2
.getCommonLabels(name2
), name2
);
953 BOOST_CHECK_EQUAL(name1
.getCommonLabels(name2
), DNSName("powerdns.com"));
954 BOOST_CHECK_EQUAL(name2
.getCommonLabels(name1
), DNSName("powerdns.com"));
956 const DNSName
name3("www.powerdns.org");
957 BOOST_CHECK_EQUAL(name1
.getCommonLabels(name3
), DNSName());
958 BOOST_CHECK_EQUAL(name2
.getCommonLabels(name3
), DNSName());
959 BOOST_CHECK_EQUAL(name3
.getCommonLabels(name1
), DNSName());
960 BOOST_CHECK_EQUAL(name3
.getCommonLabels(name2
), DNSName());
962 const DNSName
name4("WWw.PowErDnS.org");
963 BOOST_CHECK_EQUAL(name3
.getCommonLabels(name4
), name3
);
964 BOOST_CHECK_EQUAL(name4
.getCommonLabels(name3
), name4
);
967 BOOST_AUTO_TEST_SUITE_END()