]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[1688] Add AbstractRRset::lthan()
authorStephen Morris <stephen@isc.org>
Thu, 15 Mar 2012 17:24:25 +0000 (17:24 +0000)
committerStephen Morris <stephen@isc.org>
Thu, 15 Mar 2012 17:25:11 +0000 (17:25 +0000)
Provides ordering needed for adding RRsets into a multiset for
duplicate RRset removal.

src/lib/dns/rrset.cc
src/lib/dns/rrset.h
src/lib/dns/tests/rrset_unittest.cc

index 9a55f5f55cc5c01762b6f5e4f0ac8e51afe0db18..c517feab2e5bda30aafcc2267276cef048c8983f 100644 (file)
@@ -123,6 +123,35 @@ AbstractRRset::isSameKind(const AbstractRRset& other) const {
          getClass() == other.getClass());
 }
 
+bool
+AbstractRRset::lthan(const AbstractRRset& other) const {
+
+    // Check on type first...
+    const uint16_t my_type = getType().getCode();
+    const uint16_t other_type = other.getType().getCode();
+    if (my_type < other_type) {
+        return (true);
+
+    } else if (my_type == other_type) {
+        // Types equal, so check class
+        const uint16_t my_class = getClass().getCode();
+        const uint16_t other_class = other.getClass().getCode();
+        if (my_class < other_class) {
+            return (true);
+
+        } else if (my_class == other_class) {
+            // Class equal, so check name
+            return (getName().lthan(other.getName()));
+
+        } else {
+            return (false);
+        }
+
+    } else {
+        return (false);
+    }
+}
+
 ostream&
 operator<<(ostream& os, const AbstractRRset& rrset) {
     os << rrset.toText();
index 7ad555ff747e0ec174bc181c03f30e6dbb7e0a51..082e17db1154d1c8b27df39ce52b7d7df960aa9c 100644 (file)
@@ -483,7 +483,29 @@ public:
     ///              against.
     virtual bool isSameKind(const AbstractRRset& other) const;
 
+    /// \brief Check if one RRset is "less" than another
+    ///
+    /// This method is needed for storing RRsets in STL containers such
+    /// as multisets.  It applies an ordering based on
+    /// - Type
+    /// - Class
+    /// - Name
+    /// (Type and Class are ordered by the values associated with those
+    /// constants.  Name is ordered according to case-insensitive comparison.)
+    ///
+    /// Note that unlike isSameKind, type and class are checked before name.
+    /// This is because with ordering based on A, B and C (in that order), the
+    /// algorithm needs to do two checks on A and B - a "less than" check and a
+    /// check for equality.  It only needs to do a "less than" check on C.
+    /// equality.  It only needs to do one check on C, 
+    ///
+    /// \param other The other AbstractRRset to compare against.
+    ///
+    /// \return true if "this" is less than the given RRset according to
+    ///         the criteria given.
+    virtual bool lthan(const AbstractRRset& other) const;
     //@}
+
 };
 
 /// \brief The \c RdataIterator class is an abstract base class that
index a10b5153393ce31f3c6b977a4c00e9f8dd621450..9e0d5e91c6669fd8dc0995fd0a4420335021e1b4 100644 (file)
@@ -13,6 +13,7 @@
 // PERFORMANCE OF THIS SOFTWARE.
 
 #include <stdexcept>
+#include <iostream>
 
 #include <util/buffer.h>
 #include <dns/messagerenderer.h>
@@ -126,6 +127,66 @@ TEST_F(RRsetTest, isSameKind) {
     EXPECT_FALSE(rrset_w.isSameKind(rrset_p));
 }
 
+// Utility function to create an add an RRset to a vector of RRsets for the
+// "less" test.  It's only purpose is to allow the RRset creation to be
+// written with arguments in an order that reflects the RRset ordering.
+void
+addRRset(std::vector<ConstRRsetPtr>& vec, const RRType& rrtype,
+            const RRClass& rrclass, const char* rrname)
+{
+    vec.push_back(ConstRRsetPtr(new RRset(Name(rrname), rrclass, rrtype,
+                                          RRTTL(3600))));
+}
+
+TEST_F(RRsetTest, lthan) {
+    // Check values of type codes: this effectively documents the expected
+    // order of the rrsets created.
+    ASSERT_EQ(1, RRType::A().getCode());
+    ASSERT_EQ(2, RRType::NS().getCode());
+
+    ASSERT_EQ(1, RRClass::IN().getCode());
+    ASSERT_EQ(3, RRClass::CH().getCode());
+
+    // Create a vector of RRsets in ascending sort order.
+    std::vector<ConstRRsetPtr> rrsets;
+    addRRset(rrsets, RRType::A(),  RRClass::IN(), "alpha.com");
+    addRRset(rrsets, RRType::A(),  RRClass::IN(), "beta.com");
+    addRRset(rrsets, RRType::A(),  RRClass::CH(), "alpha.com");
+    addRRset(rrsets, RRType::A(),  RRClass::CH(), "beta.com");
+    addRRset(rrsets, RRType::NS(), RRClass::IN(), "alpha.com");
+    addRRset(rrsets, RRType::NS(), RRClass::IN(), "beta.com");
+    addRRset(rrsets, RRType::NS(), RRClass::CH(), "alpha.com");
+    addRRset(rrsets, RRType::NS(), RRClass::CH(), "beta.com");
+
+    // ... and do the checks.  The ASSERT_ form is used to avoid a plethora
+    // of messages if there is an error.  And if there is an error, supply
+    // a more informative message.
+    for (int i = 0; i < rrsets.size(); ++i) {
+        // Check that an RRset is not less than itself
+        ostringstream ossi;
+        ossi << "i = ("
+             << rrsets[i]->getType().toText() << ", "
+             << rrsets[i]->getClass().toText() << ", "
+             << rrsets[i]->getName().toText()
+             << ")";
+        ASSERT_FALSE(rrsets[i]->lthan(*rrsets[i])) << ossi.str();
+        for (int j = i + 1; j < rrsets.size(); ++j) {
+            // Check it against the remaining RRsets.
+            ostringstream ossj;
+            ossj << ", j = ("
+                 << rrsets[j]->getType().toText() << ", "
+                 << rrsets[j]->getClass().toText() << ", "
+                 << rrsets[j]->getName().toText()
+                 << ")";
+            ASSERT_TRUE(rrsets[i]->lthan(*rrsets[j]))
+                << ossi.str() << ossj.str();
+            ASSERT_FALSE(rrsets[j]->lthan(*rrsets[i]))
+                << ossi.str() << ossj.str();
+        }
+    }
+}
+
+
 void
 addRdataTestCommon(const RRset& rrset) {
     EXPECT_EQ(2, rrset.getRdataCount());