Commit 1780e99c authored by Jelte Jansen's avatar Jelte Jansen
Browse files

[2148] 'extendable' labelsequence constructor

parent 626757dd
......@@ -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();
......
......@@ -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
......
......@@ -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);
}
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment