Commit 07b884ef authored by Jelte Jansen's avatar Jelte Jansen
Browse files

[1278] implementation of Serial class

parent c35d0dde
...@@ -102,6 +102,7 @@ libdns___la_SOURCES += rrsetlist.h rrsetlist.cc ...@@ -102,6 +102,7 @@ libdns___la_SOURCES += rrsetlist.h rrsetlist.cc
libdns___la_SOURCES += rrttl.h rrttl.cc libdns___la_SOURCES += rrttl.h rrttl.cc
libdns___la_SOURCES += rrtype.cc libdns___la_SOURCES += rrtype.cc
libdns___la_SOURCES += question.h question.cc libdns___la_SOURCES += question.h question.cc
libdns___la_SOURCES += serial.h serial.cc
libdns___la_SOURCES += tsig.h tsig.cc libdns___la_SOURCES += tsig.h tsig.cc
libdns___la_SOURCES += tsigerror.h tsigerror.cc libdns___la_SOURCES += tsigerror.h tsigerror.cc
libdns___la_SOURCES += tsigkey.h tsigkey.cc libdns___la_SOURCES += tsigkey.h tsigkey.cc
......
// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include <dns/serial.h>
namespace isc {
namespace dns {
bool
Serial::operator==(const Serial& other) const {
return (value_ == other.getValue());
}
bool
Serial::operator!=(const Serial& other) const {
return (value_ != other.getValue());
}
bool
Serial::operator<(const Serial& other) const {
uint32_t other_val = other.getValue();
bool result = false;
if (value_ < other_val) {
result = ((other_val - value_) <= MAX_INCREMENT);
} else if (other_val < value_) {
result = ((value_ - other_val) > MAX_INCREMENT);
}
return (result);
}
bool
Serial::operator<=(const Serial& other) const {
return (operator==(other) || operator<(other));
}
bool
Serial::operator>(const Serial& other) const {
return (!operator==(other) && !operator<(other));
}
bool
Serial::operator>=(const Serial& other) const {
return (operator==(other) || !operator>(other));
}
Serial
Serial::operator+(uint32_t other_val) const {
if (value_ <= MAX_INCREMENT) {
// just add
return (Serial(value_ + other_val));
} else {
// check whether it wouldn't wrap
// Note the +1 here and the -2 below, these operations use
// the MAX_INCREMENT constant, which is 2^31-1, while it really
// needs 2^31 itself.
if (value_ - MAX_INCREMENT + other_val <= MAX_INCREMENT + 1) {
return (Serial(value_ + other_val));
} else {
return (Serial(value_ - MAX_INCREMENT +
other_val - MAX_INCREMENT - 2));
}
}
}
Serial
Serial::operator+(const Serial& other) const {
return (operator+(other.getValue()));
}
std::ostream&
operator<<(std::ostream& os, const Serial& serial) {
return (os << serial.getValue());
}
} // end namespace dns
} // end namespace isc
// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#ifndef __SERIAL_H
#define __SERIAL_H 1
#include <stdint.h>
#include <iostream>
namespace isc {
namespace dns {
/// The maximum difference between two serial numbers. If the (plain uint32_t)
/// difference between two serials is greater than this number, the smaller one
/// is considered greater.
const uint32_t MAX_INCREMENT = 2147483647;
/// \brief This class defines DNS serial numbers and serial arithmetic.
///
/// DNS Serial number are in essence unsigned 32-bits numbers, with one
/// catch; they should be compared using sequence space arithmetic.
/// So given that they are 32-bits; as soon as the difference between two
/// serial numbers is greater than 2147483647 (2^31 - 1), the lower number
/// (in plain comparison) is considered the higher one.
///
/// In order to do this as transparently as possible, these numbers are
/// stored in the Serial class, which overrides the basic comparison operators.
///
/// In this specific context, these operations are called 'serial number
/// arithmetic', and they are defined in RFC 1982.
///
/// \note RFC 1982 defines everything based on the value SERIAL_BITS. Since
/// the serial number has a fixed length of 32 bits, the values we use are
/// hard-coded, and not computed based on variable bit lengths.
class Serial {
public:
/// \brief Constructor with value
///
/// \param value The uint32_t value of the serial
explicit Serial(uint32_t value) : value_(value) {}
/// \brief Copy constructor
Serial(const Serial& other) : value_(other.getValue()) {}
/// \brief Direct assignment from other Serial
///
/// \param other The Serial to assign the value from
void operator=(const Serial& other) { value_ = other.getValue(); }
/// \brief Direct assignment from value
///
/// \param value the uint32_t value to assing
void operator=(uint32_t value) { value_ = value; }
/// \brief Returns the uint32_t representation of this serial value
///
/// \return The uint32_t value of this Serial
uint32_t getValue() const { return (value_); }
/// \brief Returns true if the serial values are equal
///
/// \return True if the values are equal
bool operator==(const Serial& other) const;
/// \brief Returns true if the serial values are not equal
///
/// \return True if the values are not equal
bool operator!=(const Serial& other) const;
/// \brief Returns true if the serial value of this serial is smaller than
/// the other, according to serial arithmetic as described in RFC 1982
///
/// \param other The Serial to compare to
///
/// \return True if this is smaller than the given value
bool operator<(const Serial& other) const;
/// \brief Returns true if the serial value of this serial is equal to or
/// smaller than the other, according to serial arithmetic as described
/// in RFC 1982
///
/// \param other The Serial to compare to
///
/// \return True if this is smaller than or equal to the given value
bool operator<=(const Serial& other) const;
/// \brief Returns true if the serial value of this serial is greater than
/// the other, according to serial arithmetic as described in RFC 1982
///
/// \param other The Serial to compare to
///
/// \return True if this is greater than the given value
bool operator>(const Serial& other) const;
/// \brief Returns true if the serial value of this serial is equal to or
/// greater than the other, according to serial arithmetic as described in
/// RFC 1982
///
/// \param other The Serial to compare to
///
/// \return True if this is greater than or equal to the given value
bool operator>=(const Serial& other) const;
/// \brief Adds the given value to the serial number. If this would make
/// the number greater than 2^32-1, it is 'wrapped'.
/// \note According to the specification, an addition greater than
/// MAX_INCREMENT is undefined. We do NOT catch this error (so as not
/// to raise exceptions), but this behaviour remains undefined.
///
/// \param other The Serial to add
///
/// \return The result of the addition
Serial operator+(const Serial& other) const;
/// \brief Adds the given value to the serial number. If this would make
/// the number greater than 2^32-1, it is 'wrapped'.
///
/// \note According to the specification, an addition greater than
/// MAX_INCREMENT is undefined. We do NOT catch this error (so as not
/// to raise exceptions), but this behaviour remains undefined.
///
/// \param other_val The uint32_t value to add
///
/// \return The result of the addition
Serial operator+(uint32_t other_val) const;
private:
uint32_t value_;
};
/// \brief Helper operator for output streams, writes the value to the stream
///
/// \param os The ostream to write to
/// \param serial The Serial to write
/// \return the output stream
std::ostream& operator<<(std::ostream& os, const Serial& serial);
} // end namespace dns
} // end namespace isc
#endif // __SERIAL_H
...@@ -54,6 +54,7 @@ run_unittests_SOURCES += question_unittest.cc ...@@ -54,6 +54,7 @@ run_unittests_SOURCES += question_unittest.cc
run_unittests_SOURCES += rrparamregistry_unittest.cc run_unittests_SOURCES += rrparamregistry_unittest.cc
run_unittests_SOURCES += masterload_unittest.cc run_unittests_SOURCES += masterload_unittest.cc
run_unittests_SOURCES += message_unittest.cc run_unittests_SOURCES += message_unittest.cc
run_unittests_SOURCES += serial_unittest.cc
run_unittests_SOURCES += tsig_unittest.cc run_unittests_SOURCES += tsig_unittest.cc
run_unittests_SOURCES += tsigerror_unittest.cc run_unittests_SOURCES += tsigerror_unittest.cc
run_unittests_SOURCES += tsigkey_unittest.cc run_unittests_SOURCES += tsigkey_unittest.cc
......
// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include <gtest/gtest.h>
#include <dns/serial.h>
using namespace isc::dns;
class SerialTest : public ::testing::Test {
public:
SerialTest() : one(1), one_2(1), two(2),
date_zero(1980120100), date_one(1980120101),
min(0), max(4294967295),
number_low(12345),
number_medium(2000000000),
number_high(4000000000)
{}
Serial one, one_2, two, date_zero, date_one, min, max, number_low, number_medium, number_high;
};
//
// Basic tests
//
TEST_F(SerialTest, get_value) {
EXPECT_EQ(1, one.getValue());
EXPECT_NE(2, one.getValue());
EXPECT_EQ(2, two.getValue());
EXPECT_EQ(1980120100, date_zero.getValue());
EXPECT_EQ(1980120101, date_one.getValue());
EXPECT_EQ(0, min.getValue());
EXPECT_EQ(4294967295, max.getValue());
EXPECT_EQ(12345, number_low.getValue());
EXPECT_EQ(2000000000, number_medium.getValue());
EXPECT_EQ(4000000000, number_high.getValue());
}
TEST_F(SerialTest, equals) {
EXPECT_EQ(one, one);
EXPECT_EQ(one, one);
EXPECT_EQ(one, one_2);
EXPECT_NE(one, two);
EXPECT_NE(two, one);
EXPECT_EQ(Serial(12345), number_low);
EXPECT_NE(Serial(12346), number_low);
}
TEST_F(SerialTest, comparison) {
// These should be true/false even without serial arithmetic
EXPECT_LE(one, one);
EXPECT_LE(one, one_2);
EXPECT_LT(one, two);
EXPECT_LE(one, two);
EXPECT_GE(two, two);
EXPECT_GT(two, one);
EXPECT_LT(one, number_low);
EXPECT_LT(number_low, number_medium);
EXPECT_LT(number_medium, number_high);
// now let's try some that 'wrap', as it were
EXPECT_GT(min, max);
EXPECT_LT(max, min);
EXPECT_LT(number_high, number_low);
}
//
// RFC 1982 Section 3.1
//
TEST_F(SerialTest, addition) {
EXPECT_EQ(two, one + one);
EXPECT_EQ(two, one + one_2);
EXPECT_EQ(max, max + min);
EXPECT_EQ(min, max + one);
EXPECT_EQ(one, max + two);
EXPECT_EQ(one, max + one + one);
EXPECT_EQ(one + 100, max + 102);
EXPECT_EQ(min + 2147483645, max + 2147483646);
EXPECT_EQ(min + 2147483646, max + MAX_INCREMENT);
}
//
// RFC 1982 Section 3.2 has been checked by the basic tests above
//
//
// RFC 1982 Section 4.1
//
// Helper function for addition_always_larger test, add some numbers
// and check that the result is always larger than the original
void do_addition_larger_test(const Serial& number) {
EXPECT_GE(number + 0, number);
EXPECT_EQ(number + 0, number);
EXPECT_GT(number + 1, number);
EXPECT_GT(number + 2, number);
EXPECT_GT(number + 100, number);
EXPECT_GT(number + 1111111, number);
EXPECT_GT(number + 2147483646, number);
EXPECT_GT(number + MAX_INCREMENT, number);
// Try MAX_INCREMENT as a hardcoded number as well
EXPECT_GT(number + 2147483647, number);
}
TEST_F(SerialTest, addition_always_larger) {
do_addition_larger_test(one);
do_addition_larger_test(two);
do_addition_larger_test(date_zero);
do_addition_larger_test(date_one);
do_addition_larger_test(min);
do_addition_larger_test(max);
do_addition_larger_test(number_low);
do_addition_larger_test(number_medium);
do_addition_larger_test(number_high);
}
//
// RFC 1982 Section 4.2
//
// Helper function to do the second addition
void
do_two_additions_test_second(const Serial &original,
const Serial &number)
{
EXPECT_NE(original, number);
EXPECT_NE(original, number + 0);
EXPECT_NE(original, number + 1);
EXPECT_NE(original, number + 2);
EXPECT_NE(original, number + 100);
EXPECT_NE(original, number + 1111111);
EXPECT_NE(original, number + 2147483646);
EXPECT_NE(original, number + MAX_INCREMENT);
EXPECT_NE(original, number + 2147483647);
}
void do_two_additions_test_first(const Serial &number) {
do_two_additions_test_second(number, number + 1);
do_two_additions_test_second(number, number + 2);
do_two_additions_test_second(number, number + 100);
do_two_additions_test_second(number, number + 1111111);
do_two_additions_test_second(number, number + 2147483646);
do_two_additions_test_second(number, number + MAX_INCREMENT);
do_two_additions_test_second(number, number + 2147483647);
}
TEST_F(SerialTest, two_additions_never_equal) {
do_two_additions_test_first(one);
do_two_additions_test_first(two);
do_two_additions_test_first(date_zero);
do_two_additions_test_first(date_one);
do_two_additions_test_first(min);
do_two_additions_test_first(max);
do_two_additions_test_first(number_low);
do_two_additions_test_first(number_medium);
do_two_additions_test_first(number_high);
}
//
// RFC 1982 Section 4.3 and 4.4 have nothing to test
//
//
// Tests from RFC 1982 examples
//
TEST(SerialTextRFCExamples, rfc_example_tests) {
}
Markdown is supported
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