diff options
author | Jelte Jansen <jelte@isc.org> | 2012-07-25 11:41:33 +0200 |
---|---|---|
committer | Jelte Jansen <jelte@isc.org> | 2012-07-25 11:41:33 +0200 |
commit | 1780e99cd241758c591d84565e11631b827f109c (patch) | |
tree | b987885d388f249ded564800f3c5415432d5035a /src/lib | |
parent | [2091a] more clarification on the use of separate memsgmt for each zone. (diff) | |
download | kea-1780e99cd241758c591d84565e11631b827f109c.tar.xz kea-1780e99cd241758c591d84565e11631b827f109c.zip |
[2148] 'extendable' labelsequence constructor
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/dns/labelsequence.cc | 19 | ||||
-rw-r--r-- | src/lib/dns/labelsequence.h | 26 | ||||
-rw-r--r-- | src/lib/dns/tests/labelsequence_unittest.cc | 134 |
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); + } +} + + + } |