summaryrefslogtreecommitdiffstats
path: root/src/lib
diff options
context:
space:
mode:
authorJelte Jansen <jelte@isc.org>2012-07-25 11:41:33 +0200
committerJelte Jansen <jelte@isc.org>2012-07-25 11:41:33 +0200
commit1780e99cd241758c591d84565e11631b827f109c (patch)
treeb987885d388f249ded564800f3c5415432d5035a /src/lib
parent[2091a] more clarification on the use of separate memsgmt for each zone. (diff)
downloadkea-1780e99cd241758c591d84565e11631b827f109c.tar.xz
kea-1780e99cd241758c591d84565e11631b827f109c.zip
[2148] 'extendable' labelsequence constructor
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/dns/labelsequence.cc19
-rw-r--r--src/lib/dns/labelsequence.h26
-rw-r--r--src/lib/dns/tests/labelsequence_unittest.cc134
3 files changed, 171 insertions, 8 deletions
diff --git a/src/lib/dns/labelsequence.cc b/src/lib/dns/labelsequence.cc
index 5675e5a044..8f22415892 100644
--- a/src/lib/dns/labelsequence.cc
+++ b/src/lib/dns/labelsequence.cc
@@ -55,6 +55,25 @@ LabelSequence::LabelSequence(const void* buf) {
}
}
+LabelSequence::LabelSequence(const LabelSequence& src,
+ uint8_t buf[MAX_SERIALIZED_LENGTH])
+{
+ size_t data_len;
+ const uint8_t *data = src.getData(&data_len);
+ memcpy(buf, data, data_len);
+
+ for (size_t i = 0; i < src.getLabelCount(); ++i) {
+ buf[Name::MAX_WIRE + i] = src.offsets_[i + src.first_label_] -
+ src.offsets_[src.first_label_];
+ }
+
+ first_label_ = 0;
+ last_label_ = src.last_label_ - src.first_label_;
+ data_ = buf;
+ offsets_ = &buf[Name::MAX_WIRE];
+}
+
+
const uint8_t*
LabelSequence::getData(size_t *len) const {
*len = getDataLength();
diff --git a/src/lib/dns/labelsequence.h b/src/lib/dns/labelsequence.h
index 5aad3d1bc2..ca30c46e78 100644
--- a/src/lib/dns/labelsequence.h
+++ b/src/lib/dns/labelsequence.h
@@ -45,6 +45,14 @@ class LabelSequence {
friend std::string Name::toText(bool) const;
public:
+ /// \brief Max possible size of serialized image generated by \c serialize
+ ///
+ /// A fixed length buffer of this size can be always passed to
+ /// \c serialize() safely. (But the application shouldn't use the
+ /// specific size value; it must use this constant variable).
+ static const size_t MAX_SERIALIZED_LENGTH =
+ Name::MAX_WIRE + Name::MAX_LABELS + 1;
+
/// \brief Constructs a LabelSequence for the given name
///
/// \note The associated Name MUST remain in scope during the lifetime
@@ -78,6 +86,16 @@ public:
/// \param buf Pointer to the serialized image generated by \c serialize().
explicit LabelSequence(const void* buf);
+ /// \brief Construct 'extendable' LabelSequence
+ ///
+ /// This form of LabelSequence copies the data from the given
+ /// labelsequence into the given external buffer, which is subsequently
+ /// extendable by calling extend()
+ ///
+ /// \param src LabelSequence to copy the initial data from
+ /// \param buf external buffer to store this labelsequence's data in
+ LabelSequence(const LabelSequence& src, uint8_t buf[MAX_SERIALIZED_LENGTH]);
+
/// \brief Copy constructor.
///
/// \note The associated data MUST remain in scope during the lifetime
@@ -125,14 +143,6 @@ public:
/// \return The length of the data of the label sequence in octets.
size_t getDataLength() const;
- /// \brief Max possible size of serialized image generated by \c serialize
- ///
- /// A fixed length buffer of this size can be always passed to
- /// \c serialize() safely. (But the application shouldn't use the
- /// specific size value; it must use this constant variable).
- static const size_t MAX_SERIALIZED_LENGTH =
- Name::MAX_WIRE + Name::MAX_LABELS + 1;
-
/// \brief Return the size of serialized image of the \c LabelSequence.
///
/// This method calculates the size of necessary storage to store
diff --git a/src/lib/dns/tests/labelsequence_unittest.cc b/src/lib/dns/tests/labelsequence_unittest.cc
index b999b9d5b1..3e96d94854 100644
--- a/src/lib/dns/tests/labelsequence_unittest.cc
+++ b/src/lib/dns/tests/labelsequence_unittest.cc
@@ -34,6 +34,25 @@ const size_t LabelSequence::MAX_SERIALIZED_LENGTH;
namespace {
+// Common check that two labelsequences are equal
+void check_equal(const LabelSequence& ls1, const LabelSequence& ls2) {
+ NameComparisonResult result = ls1.compare(ls2);
+ EXPECT_EQ(isc::dns::NameComparisonResult::EQUAL,
+ result.getRelation()) << ls1.toText() << " <> " << ls2.toText();
+ EXPECT_EQ(0, result.getOrder()) << ls1.toText() << " <> " << ls2.toText();
+ EXPECT_EQ(ls1.getLabelCount(), result.getCommonLabels());
+}
+
+// Common check for general comparison of two labelsequences
+void check_compare(const LabelSequence& ls1, const LabelSequence& ls2,
+ isc::dns::NameComparisonResult::NameRelation relation,
+ size_t common_labels) {
+ NameComparisonResult result = ls1.compare(ls2);
+ EXPECT_EQ(relation, result.getRelation());
+ EXPECT_EQ(common_labels, result.getCommonLabels());
+}
+
+
class LabelSequenceTest : public ::testing::Test {
public:
LabelSequenceTest() : n1("example.org"), n2("example.com"),
@@ -784,4 +803,119 @@ TEST_F(LabelSequenceTest, badDeserialize) {
EXPECT_THROW(LabelSequence ls(offsets_noincrease), isc::BadValue);
}
+namespace {
+
+// Helper function; repeatedly calls
+// - Initially, all three labelsequences should be the same
+// - repeatedly performs:
+// - checks all three are equal
+// - stripLeft on ls1
+// - checks ls1 and ls2 are different, and ls2 and ls3 are equal
+// - stripLeft on ls2
+// - checks ls1 and ls2 are equal, and ls2 and ls3 are different
+// - stripLeft on ls3
+//
+// (this test makes sure the stripLeft of one has no effect on the other
+// two, and that the strip properties hold regardless of how they were
+// constructed)
+//
+void stripLeftCheck(LabelSequence ls1, LabelSequence ls2, LabelSequence ls3) {
+ ASSERT_LT(1, ls1.getLabelCount());
+ while (ls1.getLabelCount() > 1) {
+ check_equal(ls1, ls2);
+ check_equal(ls2, ls3);
+
+ ls1.stripLeft(1);
+ check_compare(ls1, ls2, isc::dns::NameComparisonResult::SUPERDOMAIN,
+ ls1.getLabelCount());
+ check_equal(ls2, ls3);
+
+ ls2.stripLeft(1);
+ check_equal(ls1, ls2);
+ check_compare(ls2, ls3, isc::dns::NameComparisonResult::SUPERDOMAIN,
+ ls1.getLabelCount());
+
+ ls3.stripLeft(1);
+ }
+}
+
+// Similar to stripLeftCheck, but using stripRight()
+void stripRightCheck(LabelSequence ls1, LabelSequence ls2, LabelSequence ls3) {
+ ASSERT_LT(1, ls1.getLabelCount());
+ while (ls1.getLabelCount() > 1) {
+ check_equal(ls1, ls2);
+ check_equal(ls2, ls3);
+
+ ls1.stripRight(1);
+ check_compare(ls1, ls2, isc::dns::NameComparisonResult::NONE, 0);
+ check_equal(ls2, ls3);
+
+ ls2.stripRight(1);
+ check_equal(ls1, ls2);
+ check_compare(ls2, ls3, isc::dns::NameComparisonResult::NONE, 0);
+
+ ls3.stripRight(1);
+ }
+}
+
+} // end anonymous namespace
+
+// Test that 'extendable' labelsequences behave correctly when using
+// stripLeft() and stripRight()
+TEST(LabelSequence, extendableLabelSequence) {
+ Name n1("example.org.");
+ LabelSequence ls1(n1);
+ LabelSequence ls2(n1);
+
+ uint8_t buf[LabelSequence::MAX_SERIALIZED_LENGTH];
+ memset(buf, 0, LabelSequence::MAX_SERIALIZED_LENGTH);
+ LabelSequence els(ls1, buf);
+
+ ASSERT_EQ(ls1.getDataLength(), els.getDataLength());
+ stripLeftCheck(ls1, els, ls2);
+ stripRightCheck(ls1, els, ls2);
+}
+
+// Test that 'extendable' LabelSequences behave correctly when initialized
+// with a stripped source LabelSequence
+TEST(LabelSequence, extendableLabelSequenceStrippedSource) {
+ Name n1("foo.bar.example.org.");
+ LabelSequence ls1(n1);
+ LabelSequence ls2(n1);
+
+ while (ls1.getLabelCount() > 2) {
+ ls1.stripLeft(1);
+ ls2.stripLeft(1);
+
+ uint8_t buf[LabelSequence::MAX_SERIALIZED_LENGTH];
+ memset(buf, 0, LabelSequence::MAX_SERIALIZED_LENGTH);
+ LabelSequence els(ls1, buf);
+
+ ASSERT_EQ(ls1.getDataLength(), els.getDataLength());
+ stripLeftCheck(ls1, els, ls2);
+ stripRightCheck(ls1, els, ls2);
+ }
+}
+
+TEST(LabelSequence, extendableLabelSequenceRightStrippedSource) {
+ Name n1("foo.bar.example.org.");
+ LabelSequence ls1(n1);
+ LabelSequence ls2(n1);
+
+ while (ls1.getLabelCount() > 2) {
+ ls1.stripRight(1);
+ ls2.stripRight(1);
+
+ uint8_t buf[LabelSequence::MAX_SERIALIZED_LENGTH];
+ memset(buf, 0, LabelSequence::MAX_SERIALIZED_LENGTH);
+ LabelSequence els(ls1, buf);
+
+ ASSERT_EQ(ls1.getDataLength(), els.getDataLength());
+ stripLeftCheck(ls1, els, ls2);
+ stripRightCheck(ls1, els, ls2);
+ }
+}
+
+
+
}