]> granicus.if.org Git - pdns/commitdiff
implement a canonical ordering mode for DNSName plus add testcases for it. Preliminar...
authorbert hubert <bert.hubert@netherlabs.nl>
Tue, 16 Jun 2015 11:14:32 +0000 (13:14 +0200)
committerbert hubert <bert.hubert@netherlabs.nl>
Tue, 16 Jun 2015 11:14:32 +0000 (13:14 +0200)
pdns/dnsname.cc
pdns/dnsname.hh
pdns/test-dnsname_cc.cc

index a3d2778e9d2f97d04e99deea5dc4df816de86213..85f5c277f29178deeab7c4c9007c24b31bb85781 100644 (file)
@@ -1,6 +1,7 @@
 #include "dnsname.hh"
 #include <boost/format.hpp>
 #include <string>
+
 #include "dnswriter.hh"
 
 /* raw storage
@@ -143,6 +144,13 @@ vector<string> DNSName::getRawLabels() const
   return ret;
 }
 
+
+bool DNSName::canonCompare(const DNSName& rhs) const
+{
+  auto ours=getRawLabels(), rhsLabels = rhs.getRawLabels();
+  return std::lexicographical_compare(ours.rbegin(), ours.rend(), rhsLabels.rbegin(), rhsLabels.rend(), CIStringCompare());
+}
+
 bool DNSName::chopOff() 
 {
   if(d_storage.empty())
index de5623502c5935fd2794db0d2bd0ee60292d6815..542c85fa3cd01e136a0faf8c6336a2d311dcd346 100644 (file)
@@ -47,15 +47,17 @@ public:
     return *this;
   }
 
-  bool operator<(const DNSName& rhs)  const
+  bool operator<(const DNSName& rhs)  const // this delivers _some_ kind of ordering, but not one useful in a DNS context. Really fast though.
   {
     return std::lexicographical_compare(d_storage.rbegin(), d_storage.rend(), 
                                 rhs.d_storage.rbegin(), rhs.d_storage.rend(),
                                 [](const char& a, const char& b) {
                                          return tolower(a) < tolower(b); 
-                                });
+                                       }); // note that this is case insensitive, including on the label lengths
   }
 
+  bool canonCompare(const DNSName& rhs) const;
+  
 private:
   //  typedef __gnu_cxx::__sso_string string_t;
   typedef std::string string_t;
@@ -67,6 +69,14 @@ private:
   static std::string unescapeLabel(const std::string& orig);
 };
 
+struct CanonDNSNameCompare: public std::binary_function<DNSName, DNSName, bool>
+{
+  bool operator()(const DNSName&a, const DNSName& b) const
+  {
+    return a.canonCompare(b);
+  }
+};
+
 inline DNSName operator+(const DNSName& lhs, const DNSName& rhs)
 {
   DNSName ret=lhs;
index a457a9e12f7d85d6de6cc8a609edc914ca5d36d1..1c58066316a3c25961fd433ad767a76c8b05d30d 100644 (file)
@@ -267,8 +267,42 @@ BOOST_AUTO_TEST_CASE(test_suffixmatch) {
 
   smn.add(DNSName()); // block the root
   BOOST_CHECK(smn.check(DNSName("a.root-servers.net.")));
+}
+
+
+BOOST_AUTO_TEST_CASE(test_concat) {
+  DNSName first("www."), second("powerdns.com.");
+  BOOST_CHECK_EQUAL((first+second).toString(), "www.powerdns.com.");
+}
+
+BOOST_AUTO_TEST_CASE(test_compare_naive) {
+  BOOST_CHECK(DNSName("abc.com.") < DNSName("zdf.com."));
+  BOOST_CHECK(DNSName("Abc.com.") < DNSName("zdf.com."));
+  BOOST_CHECK(DNSName("Abc.com.") < DNSName("Zdf.com."));
+  BOOST_CHECK(DNSName("abc.com.") < DNSName("Zdf.com."));
+}
+
+BOOST_AUTO_TEST_CASE(test_compare_canonical) {
+  DNSName lower("bert.com."), higher("alpha.nl.");
+  BOOST_CHECK(lower.canonCompare(higher));
+
 
+  vector<DNSName> vec({"bert.com.", "alpha.nl.", "articles.xxx.",
+       "Aleph1.powerdns.com.", "ZOMG.powerdns.com.", "aaa.XXX.", "yyy.XXX.", 
+       "test.powerdns.com."});
+  sort(vec.begin(), vec.end(), CanonDNSNameCompare());
+  //  for(const auto& v : vec)
+  //  cerr<<'"'<<v.toString()<<'"'<<endl;
 
+  vector<DNSName> right({"bert.com.",  "Aleph1.powerdns.com.",
+       "test.powerdns.com.",
+       "ZOMG.powerdns.com.",
+       "alpha.nl.",
+       "aaa.XXX.",
+       "articles.xxx.",
+       "yyy.XXX."});
+
+  BOOST_CHECK(vec==right);
 }
 
 
@@ -366,6 +400,7 @@ BOOST_AUTO_TEST_CASE(test_name_length_too_long) { // 256 char name
   }
 }
 
+
 BOOST_AUTO_TEST_CASE(test_invalid_label_length) { // Invalid label length in qname
 
   string name("\x02""ns\x07""example\x04""com\x00", 16);