123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809 |
- // Copyright (C) 2013 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 <config.h>
- #include <dhcp/option6_client_fqdn.h>
- #include <dns/name.h>
- #include <util/buffer.h>
- #include <boost/scoped_ptr.hpp>
- #include <gtest/gtest.h>
- namespace {
- using namespace isc;
- using namespace isc::dhcp;
- // This test verifies that constructor accepts empty partial domain-name but
- // does not accept empty fully qualified domain name.
- TEST(Option6ClientFqdnTest, constructEmptyName) {
- // Create an instance of the source option.
- boost::scoped_ptr<Option6ClientFqdn> option;
- ASSERT_NO_THROW(
- option.reset(new Option6ClientFqdn(Option6ClientFqdn::FLAG_S, "",
- Option6ClientFqdn::PARTIAL))
- );
- ASSERT_TRUE(option);
- EXPECT_FALSE(option->getFlag(Option6ClientFqdn::FLAG_O));
- EXPECT_FALSE(option->getFlag(Option6ClientFqdn::FLAG_N));
- EXPECT_TRUE(option->getFlag(Option6ClientFqdn::FLAG_S));
- EXPECT_TRUE(option->getDomainName().empty());
- EXPECT_EQ(Option6ClientFqdn::PARTIAL, option->getDomainNameType());
- // Constructor should not accept empty fully qualified domain name.
- EXPECT_THROW(Option6ClientFqdn(Option6ClientFqdn::FLAG_S, "",
- Option6ClientFqdn::FULL),
- InvalidOption6FqdnDomainName);
- // This check is similar to previous one, but using domain-name comprising
- // a single space character. This should be treated as empty domain-name.
- EXPECT_THROW(Option6ClientFqdn(Option6ClientFqdn::FLAG_S, " ",
- Option6ClientFqdn::FULL),
- InvalidOption6FqdnDomainName);
- // Try different constructor.
- ASSERT_NO_THROW(
- option.reset(new Option6ClientFqdn(Option6ClientFqdn::FLAG_O))
- );
- ASSERT_TRUE(option);
- EXPECT_TRUE(option->getFlag(Option6ClientFqdn::FLAG_O));
- EXPECT_FALSE(option->getFlag(Option6ClientFqdn::FLAG_N));
- EXPECT_FALSE(option->getFlag(Option6ClientFqdn::FLAG_S));
- EXPECT_TRUE(option->getDomainName().empty());
- EXPECT_EQ(Option6ClientFqdn::PARTIAL, option->getDomainNameType());
- }
- // This test verifies that copy constructor makes a copy of the option and
- // the source option instance can be deleted (both instances don't share
- // any resources).
- TEST(Option6ClientFqdnTest, copyConstruct) {
- // Create an instance of the source option.
- boost::scoped_ptr<Option6ClientFqdn> option;
- ASSERT_NO_THROW(
- option.reset(new Option6ClientFqdn(Option6ClientFqdn::FLAG_S,
- "myhost.example.com",
- Option6ClientFqdn::FULL))
- );
- ASSERT_TRUE(option);
- // Use copy constructor to create a second instance of the option.
- boost::scoped_ptr<Option6ClientFqdn> option_copy;
- ASSERT_NO_THROW(
- option_copy.reset(new Option6ClientFqdn(*option))
- );
- ASSERT_TRUE(option_copy);
- // Copy construction should result in no shared resources between
- // two objects. In particular, pointer to implementation should not
- // be shared. Thus, we can release the source object now.
- option.reset();
- // Verify that all parameters have been copied to the target object.
- EXPECT_TRUE(option_copy->getFlag(Option6ClientFqdn::FLAG_S));
- EXPECT_FALSE(option_copy->getFlag(Option6ClientFqdn::FLAG_O));
- EXPECT_FALSE(option_copy->getFlag(Option6ClientFqdn::FLAG_N));
- EXPECT_EQ("myhost.example.com.", option_copy->getDomainName());
- EXPECT_EQ(Option6ClientFqdn::FULL, option_copy->getDomainNameType());
- // Do another test with different parameters to verify that parameters
- // change when copied object is changed.
- // Create an option with different parameters.
- ASSERT_NO_THROW(
- option.reset(new Option6ClientFqdn(Option6ClientFqdn::FLAG_O,
- "example",
- Option6ClientFqdn::PARTIAL))
- );
- ASSERT_TRUE(option);
- // Call copy-constructor to copy the option.
- ASSERT_NO_THROW(
- option_copy.reset(new Option6ClientFqdn(*option))
- );
- ASSERT_TRUE(option_copy);
- option.reset();
- EXPECT_FALSE(option_copy->getFlag(Option6ClientFqdn::FLAG_S));
- EXPECT_TRUE(option_copy->getFlag(Option6ClientFqdn::FLAG_O));
- EXPECT_FALSE(option_copy->getFlag(Option6ClientFqdn::FLAG_N));
- EXPECT_EQ("example", option_copy->getDomainName());
- EXPECT_EQ(Option6ClientFqdn::PARTIAL, option_copy->getDomainNameType());
- }
- // This test verifies that copy constructor makes a copy of the option, when
- // domain-name is empty.
- TEST(Option6ClientFqdnTest, copyConstructEmptyDomainName) {
- // Create an instance of the source option.
- boost::scoped_ptr<Option6ClientFqdn> option;
- ASSERT_NO_THROW(
- option.reset(new Option6ClientFqdn(Option6ClientFqdn::FLAG_S));
- );
- ASSERT_TRUE(option);
- // Use copy constructor to create a second instance of the option.
- boost::scoped_ptr<Option6ClientFqdn> option_copy;
- ASSERT_NO_THROW(
- option_copy.reset(new Option6ClientFqdn(*option))
- );
- ASSERT_TRUE(option_copy);
- // Copy construction should result in no shared resources between
- // two objects. In particular, pointer to implementation should not
- // be shared. Thus, we can release the source object now.
- option.reset();
- // Verify that all parameters have been copied to the target object.
- EXPECT_TRUE(option_copy->getFlag(Option6ClientFqdn::FLAG_S));
- EXPECT_FALSE(option_copy->getFlag(Option6ClientFqdn::FLAG_O));
- EXPECT_FALSE(option_copy->getFlag(Option6ClientFqdn::FLAG_N));
- EXPECT_EQ("", option_copy->getDomainName());
- EXPECT_EQ(Option6ClientFqdn::PARTIAL, option_copy->getDomainNameType());
- }
- // This test verifies that the option in the on-wire format is parsed correctly.
- TEST(Option6ClientFqdnTest, constructFromWire) {
- const uint8_t in_data[] = {
- Option6ClientFqdn::FLAG_S, // flags
- 6, 109, 121, 104, 111, 115, 116, // myhost.
- 7, 101, 120, 97, 109, 112, 108, 101, // example.
- 3, 99, 111, 109, 0 // com.
- };
- size_t in_data_size = sizeof(in_data) / sizeof(in_data[0]);
- OptionBuffer in_buf(in_data, in_data + in_data_size);
- // Create option instance. Check that constructor doesn't throw.
- boost::scoped_ptr<Option6ClientFqdn> option;
- ASSERT_NO_THROW(
- option.reset(new Option6ClientFqdn(in_buf.begin(), in_buf.end()))
- );
- ASSERT_TRUE(option);
- EXPECT_TRUE(option->getFlag(Option6ClientFqdn::FLAG_S));
- EXPECT_FALSE(option->getFlag(Option6ClientFqdn::FLAG_O));
- EXPECT_FALSE(option->getFlag(Option6ClientFqdn::FLAG_N));
- EXPECT_EQ("myhost.example.com.", option->getDomainName());
- EXPECT_EQ(Option6ClientFqdn::FULL, option->getDomainNameType());
- }
- // Verify that exception is thrown if the domain-name label is
- // longer than 63.
- TEST(Option6ClientFqdnTest, constructFromWireTooLongLabel) {
- OptionBuffer in_buf(Option6ClientFqdn::FLAG_S);
- in_buf.push_back(70);
- in_buf.insert(in_buf.end(), 70, 109);
- in_buf.push_back(0);
- EXPECT_THROW(Option6ClientFqdn(in_buf.begin(), in_buf.end()),
- InvalidOption6FqdnDomainName);
- }
- // Verify that exception is thrown if the overall length of the domain-name
- // is over 255.
- TEST(Option6ClientFqdnTest, constructFromWireTooLongDomainName) {
- OptionBuffer in_buf(Option6ClientFqdn::FLAG_S);
- for (int i = 0; i < 26; ++i) {
- in_buf.push_back(10);
- in_buf.insert(in_buf.end(), 10, 109);
- }
- in_buf.push_back(0);
- try {
- Option6ClientFqdn(in_buf.begin(), in_buf.end());
- } catch (const Exception& ex) {
- std::cout << ex.what() << std::endl;
- }
- EXPECT_THROW(Option6ClientFqdn(in_buf.begin(), in_buf.end()),
- InvalidOption6FqdnDomainName);
- }
- // This test verifies that truncated option is rejected.
- TEST(Option6ClientFqdnTest, constructFromWireTruncated) {
- // Empty buffer is invalid. It should be at least one octet long.
- OptionBuffer in_buf;
- ASSERT_THROW(Option6ClientFqdn(in_buf.begin(), in_buf.end()),
- OutOfRange);
- }
- // This test verifies that the option in the on-wire format with partial
- // domain-name is parsed correctly.
- TEST(Option6ClientFqdnTest, constructFromWirePartial) {
- const uint8_t in_data[] = {
- Option6ClientFqdn::FLAG_N, // flags
- 6, 109, 121, 104, 111, 115, 116 // myhost
- };
- size_t in_data_size = sizeof(in_data) / sizeof(in_data[0]);
- OptionBuffer in_buf(in_data, in_data + in_data_size);
- // Create option instance. Check that constructor doesn't throw.
- boost::scoped_ptr<Option6ClientFqdn> option;
- ASSERT_NO_THROW(
- option.reset(new Option6ClientFqdn(in_buf.begin(), in_buf.end()))
- );
- ASSERT_TRUE(option);
- EXPECT_FALSE(option->getFlag(Option6ClientFqdn::FLAG_S));
- EXPECT_FALSE(option->getFlag(Option6ClientFqdn::FLAG_O));
- EXPECT_TRUE(option->getFlag(Option6ClientFqdn::FLAG_N));
- EXPECT_EQ("myhost", option->getDomainName());
- EXPECT_EQ(Option6ClientFqdn::PARTIAL, option->getDomainNameType());
- }
- // This test verifies that the option in the on-wire format with empty
- // domain-name is parsed correctly.
- TEST(Option6ClientFqdnTest, constructFromWireEmpty) {
- OptionBuffer in_buf(Option6ClientFqdn::FLAG_S);
- // Create option instance. Check that constructor doesn't throw.
- boost::scoped_ptr<Option6ClientFqdn> option;
- ASSERT_NO_THROW(
- option.reset(new Option6ClientFqdn(in_buf.begin(), in_buf.end()))
- );
- ASSERT_TRUE(option);
- // domain-name field should be empty because on-wire data comprised
- // flags field only.
- EXPECT_TRUE(option->getDomainName().empty());
- }
- // This test verifies that assignment operator can be used to assign one
- // instance of the option to another.
- TEST(Option6ClientFqdnTest, assignment) {
- // Usually the smart pointer is used to declare options and call
- // constructor within assert. Thanks to this approach, the option instance
- // is in the function scope and only initialization is done within assert.
- // In this particular test we can't use smart pointers because we are
- // testing assignment operator like this:
- //
- // option2 = option;
- //
- // The two asserts below do not create the instances that we will used to
- // test assignment. They just attempt to create instances of the options
- // with the same parameters as those that will be created for the actual
- // assignment test. If these asserts do not fail, we can create options
- // for the assignment test, do not surround them with asserts and be sure
- // they will not throw.
- ASSERT_NO_THROW(Option6ClientFqdn(Option6ClientFqdn::FLAG_S,
- "myhost.example.com",
- Option6ClientFqdn::FULL));
- ASSERT_NO_THROW(Option6ClientFqdn(Option6ClientFqdn::FLAG_N,
- "myhost",
- Option6ClientFqdn::PARTIAL));
- // Create options with the same parameters as tested above.
- // Create first option.
- Option6ClientFqdn option(Option6ClientFqdn::FLAG_S,
- "myhost.example.com",
- Option6ClientFqdn::FULL);
- // Verify that the values have been set correctly.
- ASSERT_TRUE(option.getFlag(Option6ClientFqdn::FLAG_S));
- ASSERT_FALSE(option.getFlag(Option6ClientFqdn::FLAG_O));
- ASSERT_FALSE(option.getFlag(Option6ClientFqdn::FLAG_N));
- ASSERT_EQ("myhost.example.com.", option.getDomainName());
- ASSERT_EQ(Option6ClientFqdn::FULL, option.getDomainNameType());
- // Create a second option.
- Option6ClientFqdn option2(Option6ClientFqdn::FLAG_N,
- "myhost",
- Option6ClientFqdn::PARTIAL);
- // Verify tha the values have been set correctly.
- ASSERT_FALSE(option2.getFlag(Option6ClientFqdn::FLAG_S));
- ASSERT_FALSE(option2.getFlag(Option6ClientFqdn::FLAG_O));
- ASSERT_TRUE(option2.getFlag(Option6ClientFqdn::FLAG_N));
- ASSERT_EQ("myhost", option2.getDomainName());
- ASSERT_EQ(Option6ClientFqdn::PARTIAL, option2.getDomainNameType());
- // Make the assignment.
- ASSERT_NO_THROW(option2 = option);
- // Both options should now have the same values.
- EXPECT_TRUE(option2.getFlag(Option6ClientFqdn::FLAG_S));
- EXPECT_FALSE(option2.getFlag(Option6ClientFqdn::FLAG_O));
- EXPECT_FALSE(option2.getFlag(Option6ClientFqdn::FLAG_N));
- EXPECT_EQ(option.getDomainName(), option2.getDomainName());
- EXPECT_EQ(option.getDomainNameType(), option2.getDomainNameType());
- }
- // This test verifies that assignment operator can be used to assign one
- // instance of the option to another, when the domain-name is empty.
- TEST(Option6ClientFqdnTest, assignmentEmptyDomainName) {
- ASSERT_NO_THROW(
- Option6ClientFqdn(static_cast<uint8_t>(Option6ClientFqdn::FLAG_S))
- );
- ASSERT_NO_THROW(Option6ClientFqdn(Option6ClientFqdn::FLAG_N,
- "myhost",
- Option6ClientFqdn::PARTIAL));
- // Create options with the same parameters as tested above.
- // Create first option.
- Option6ClientFqdn option(Option6ClientFqdn::FLAG_S);
- // Verify that the values have been set correctly.
- ASSERT_TRUE(option.getFlag(Option6ClientFqdn::FLAG_S));
- ASSERT_FALSE(option.getFlag(Option6ClientFqdn::FLAG_O));
- ASSERT_FALSE(option.getFlag(Option6ClientFqdn::FLAG_N));
- ASSERT_EQ("", option.getDomainName());
- ASSERT_EQ(Option6ClientFqdn::PARTIAL, option.getDomainNameType());
- // Create a second option.
- Option6ClientFqdn option2(Option6ClientFqdn::FLAG_N,
- "myhost",
- Option6ClientFqdn::PARTIAL);
- // Verify that the values have been set correctly.
- ASSERT_FALSE(option2.getFlag(Option6ClientFqdn::FLAG_S));
- ASSERT_FALSE(option2.getFlag(Option6ClientFqdn::FLAG_O));
- ASSERT_TRUE(option2.getFlag(Option6ClientFqdn::FLAG_N));
- ASSERT_EQ("myhost", option2.getDomainName());
- ASSERT_EQ(Option6ClientFqdn::PARTIAL, option2.getDomainNameType());
- // Make the assignment.
- ASSERT_NO_THROW(option2 = option);
- // Both options should now have the same values.
- EXPECT_TRUE(option2.getFlag(Option6ClientFqdn::FLAG_S));
- EXPECT_FALSE(option2.getFlag(Option6ClientFqdn::FLAG_O));
- EXPECT_FALSE(option2.getFlag(Option6ClientFqdn::FLAG_N));
- EXPECT_EQ("", option2.getDomainName());
- EXPECT_EQ(option.getDomainNameType(), option2.getDomainNameType());
- }
- // This test verifies that constructor will throw an exception if invalid
- // DHCPv6 Client FQDN Option flags are specified.
- TEST(Option6ClientFqdnTest, constructInvalidFlags) {
- // First, check that constructor does not throw an exception when
- // valid flags values are provided. That way we eliminate the issue
- // that constructor always throws exception.
- uint8_t flags = 0;
- ASSERT_NO_THROW(Option6ClientFqdn(flags, "myhost.example.com"));
- // Invalid flags: The maximal value is 0x7 when all flag bits are set
- // (00000111b). The flag value of 0x14 sets the bit from the Must Be
- // Zero (MBZ) bitset (00001100b).
- flags = 0x14;
- EXPECT_THROW(Option6ClientFqdn(flags, "myhost.example.com"),
- InvalidOption6FqdnFlags);
- // According to RFC 4704, section 4.1. if the N bit is set the S bit MUST
- // be zero. If both are set, constructor is expected to throw.
- flags = Option6ClientFqdn::FLAG_N | Option6ClientFqdn::FLAG_S;
- EXPECT_THROW(Option6ClientFqdn(flags, "myhost.example.com"),
- InvalidOption6FqdnFlags);
- }
- // This test verifies that constructor which parses option from on-wire format
- // will throw exception if parsed flags field is invalid.
- TEST(Option6ClientFqdnTest, constructFromWireInvalidFlags) {
- // Create a buffer which holds flags field only. Set valid flag field at
- // at first to make sure that constructor doesn't always throw an exception.
- OptionBuffer in_buf(Option6ClientFqdn::FLAG_N);
- ASSERT_NO_THROW(Option6ClientFqdn(in_buf.begin(), in_buf.end()));
- // Replace the flags with invalid value and verify that constructor throws
- // appropriate exception.
- in_buf[0] = Option6ClientFqdn::FLAG_N | Option6ClientFqdn::FLAG_S;
- EXPECT_THROW(Option6ClientFqdn(in_buf.begin(), in_buf.end()),
- InvalidOption6FqdnFlags);
- }
- // This test verifies that if invalid domain name is used the constructor
- // will throw appropriate exception.
- TEST(Option6ClientFqdnTest, constructInvalidName) {
- // First, check that constructor does not throw when valid domain name
- // is specified. That way we eliminate the possibility that constructor
- // always throws exception.
- ASSERT_NO_THROW(Option6ClientFqdn(0, "myhost.example.com"));
- // Specify invalid domain name and expect that exception is thrown.
- EXPECT_THROW(Option6ClientFqdn(0, "my...host.example.com"),
- InvalidOption6FqdnDomainName);
- }
- // This test verifies that getFlag throws an exception if flag value other
- // than FLAG_N, FLAG_S, FLAG_O is specified.
- TEST(Option6ClientFqdnTest, getFlag) {
- boost::scoped_ptr<Option6ClientFqdn> option;
- ASSERT_NO_THROW(
- option.reset(new Option6ClientFqdn(0, "myhost.example.com"))
- );
- ASSERT_TRUE(option);
- // The 0x3 (binary 011) specifies two distinct bits in the flags field.
- // This value is ambiguous for getFlag function and this function doesn't
- // know which flag the caller is attempting to check.
- EXPECT_THROW(option->getFlag(0x3), InvalidOption6FqdnFlags);
- }
- // This test verifies that flags can be modified and that incorrect flags
- // are rejected.
- TEST(Option6ClientFqdnTest, setFlag) {
- // Create option instance. Check that constructor doesn't throw.
- boost::scoped_ptr<Option6ClientFqdn> option;
- ASSERT_NO_THROW(
- option.reset(new Option6ClientFqdn(0, "myhost.example.com"))
- );
- ASSERT_TRUE(option);
- // All flags should be set to 0 initially.
- ASSERT_FALSE(option->getFlag(Option6ClientFqdn::FLAG_N));
- ASSERT_FALSE(option->getFlag(Option6ClientFqdn::FLAG_S));
- ASSERT_FALSE(option->getFlag(Option6ClientFqdn::FLAG_O));
- // Set N = 1
- ASSERT_NO_THROW(option->setFlag(Option6ClientFqdn::FLAG_N, true));
- ASSERT_TRUE(option->getFlag(Option6ClientFqdn::FLAG_N));
- // Set O = 1
- ASSERT_NO_THROW(option->setFlag(Option6ClientFqdn::FLAG_O, true));
- ASSERT_TRUE(option->getFlag(Option6ClientFqdn::FLAG_O));
- // Set S = 1, this should throw exception because S and N must not
- // be set in the same time.
- ASSERT_THROW(option->setFlag(Option6ClientFqdn::FLAG_S, true),
- InvalidOption6FqdnFlags);
- // Set N = 0
- ASSERT_NO_THROW(option->setFlag(Option6ClientFqdn::FLAG_N, false));
- ASSERT_FALSE(option->getFlag(Option6ClientFqdn::FLAG_N));
- // Set S = 1, this should not result in exception because N has been
- // cleared.
- ASSERT_NO_THROW(option->setFlag(Option6ClientFqdn::FLAG_S, true));
- ASSERT_TRUE(option->getFlag(Option6ClientFqdn::FLAG_S));
- // Set N = 1, this should result in exception because S = 1
- ASSERT_THROW(option->setFlag(Option6ClientFqdn::FLAG_N, true),
- InvalidOption6FqdnFlags);
- // Set O = 0
- ASSERT_NO_THROW(option->setFlag(Option6ClientFqdn::FLAG_O, false));
- ASSERT_FALSE(option->getFlag(Option6ClientFqdn::FLAG_O));
- // Try out of bounds settings.
- uint8_t flags = 0;
- ASSERT_THROW(option->setFlag(flags, true), InvalidOption6FqdnFlags);
- flags = 0x14;
- ASSERT_THROW(option->setFlag(flags, true), InvalidOption6FqdnFlags);
- }
- // This test verifies that flags field of the option is set to 0 when resetFlags
- // function is called.
- TEST(Option6ClientFqdnTest, resetFlags) {
- boost::scoped_ptr<Option6ClientFqdn> option;
- ASSERT_NO_THROW(
- option.reset(new Option6ClientFqdn(Option6ClientFqdn::FLAG_S |
- Option6ClientFqdn::FLAG_O,
- "myhost.example.com",
- Option6ClientFqdn::FULL))
- );
- ASSERT_TRUE(option);
- // Check that flags we set in the constructor are set.
- ASSERT_TRUE(option->getFlag(Option6ClientFqdn::FLAG_S));
- ASSERT_TRUE(option->getFlag(Option6ClientFqdn::FLAG_O));
- ASSERT_FALSE(option->getFlag(Option6ClientFqdn::FLAG_N));
- option->resetFlags();
- // After reset, all flags should be 0.
- EXPECT_FALSE(option->getFlag(Option6ClientFqdn::FLAG_S));
- EXPECT_FALSE(option->getFlag(Option6ClientFqdn::FLAG_O));
- EXPECT_FALSE(option->getFlag(Option6ClientFqdn::FLAG_N));
- }
- // This test verifies that current domain-name can be replaced with a new
- // domain-name.
- TEST(Option6ClientFqdnTest, setDomainName) {
- boost::scoped_ptr<Option6ClientFqdn> option;
- ASSERT_NO_THROW(
- option.reset(new Option6ClientFqdn(Option6ClientFqdn::FLAG_S,
- "myhost.example.com",
- Option6ClientFqdn::FULL))
- );
- ASSERT_TRUE(option);
- ASSERT_EQ("myhost.example.com.", option->getDomainName());
- ASSERT_EQ(Option6ClientFqdn::FULL, option->getDomainNameType());
- // Partial domain-name.
- ASSERT_NO_THROW(option->setDomainName("myhost",
- Option6ClientFqdn::PARTIAL));
- EXPECT_EQ("myhost", option->getDomainName());
- EXPECT_EQ(Option6ClientFqdn::PARTIAL, option->getDomainNameType());
- // Fully qualified domain-name.
- ASSERT_NO_THROW(option->setDomainName("example.com",
- Option6ClientFqdn::FULL));
- EXPECT_EQ("example.com.", option->getDomainName());
- EXPECT_EQ(Option6ClientFqdn::FULL, option->getDomainNameType());
- // Empty domain name (partial). This should be successful.
- ASSERT_NO_THROW(option->setDomainName("", Option6ClientFqdn::PARTIAL));
- EXPECT_TRUE(option->getDomainName().empty());
- // Fully qualified domain-names must not be empty.
- EXPECT_THROW(option->setDomainName("", Option6ClientFqdn::FULL),
- InvalidOption6FqdnDomainName);
- EXPECT_THROW(option->setDomainName(" ", Option6ClientFqdn::FULL),
- InvalidOption6FqdnDomainName);
- }
- // This test verifies that current domain-name can be reset to empty one.
- TEST(Option6ClientFqdnTest, resetDomainName) {
- boost::scoped_ptr<Option6ClientFqdn> option;
- ASSERT_NO_THROW(
- option.reset(new Option6ClientFqdn(Option6ClientFqdn::FLAG_S,
- "myhost.example.com",
- Option6ClientFqdn::FULL))
- );
- ASSERT_TRUE(option);
- ASSERT_EQ("myhost.example.com.", option->getDomainName());
- ASSERT_EQ(Option6ClientFqdn::FULL, option->getDomainNameType());
- // Set the domain-name to empty one.
- ASSERT_NO_THROW(option->resetDomainName());
- EXPECT_TRUE(option->getDomainName().empty());
- }
- // This test verifies on-wire format of the option is correctly created.
- TEST(Option6ClientFqdnTest, pack) {
- // Create option instance. Check that constructor doesn't throw.
- const uint8_t flags = Option6ClientFqdn::FLAG_S;
- boost::scoped_ptr<Option6ClientFqdn> option;
- ASSERT_NO_THROW(
- option.reset(new Option6ClientFqdn(flags, "myhost.example.com"))
- );
- ASSERT_TRUE(option);
- // Prepare on-wire format of the option.
- isc::util::OutputBuffer buf(10);
- ASSERT_NO_THROW(option->pack(buf));
- // Prepare reference data.
- const uint8_t ref_data[] = {
- 0, 39, 0, 21, // header
- Option6ClientFqdn::FLAG_S, // flags
- 6, 109, 121, 104, 111, 115, 116, // myhost.
- 7, 101, 120, 97, 109, 112, 108, 101, // example.
- 3, 99, 111, 109, 0 // com.
- };
- size_t ref_data_size = sizeof(ref_data) / sizeof(ref_data[0]);
- // Check if the buffer has the same length as the reference data,
- // so as they can be compared directly.
- ASSERT_EQ(ref_data_size, buf.getLength());
- EXPECT_EQ(0, memcmp(ref_data, buf.getData(), buf.getLength()));
- }
- // This test verifies on-wire format of the option with partial domain name
- // is correctly created.
- TEST(Option6ClientFqdnTest, packPartial) {
- // Create option instance. Check that constructor doesn't throw.
- const uint8_t flags = Option6ClientFqdn::FLAG_S;
- boost::scoped_ptr<Option6ClientFqdn> option;
- ASSERT_NO_THROW(
- option.reset(new Option6ClientFqdn(flags, "myhost",
- Option6ClientFqdn::PARTIAL))
- );
- ASSERT_TRUE(option);
- // Prepare on-wire format of the option.
- isc::util::OutputBuffer buf(10);
- ASSERT_NO_THROW(option->pack(buf));
- // Prepare reference data.
- const uint8_t ref_data[] = {
- 0, 39, 0, 8, // header
- Option6ClientFqdn::FLAG_S, // flags
- 6, 109, 121, 104, 111, 115, 116 // myhost
- };
- size_t ref_data_size = sizeof(ref_data) / sizeof(ref_data[0]);
- // Check if the buffer has the same length as the reference data,
- // so as they can be compared directly.
- ASSERT_EQ(ref_data_size, buf.getLength());
- EXPECT_EQ(0, memcmp(ref_data, buf.getData(), buf.getLength()));
- }
- // This test verifies that it is possible to encode the option which carries
- // empty domain-name in the wire format.
- TEST(Option6ClientFqdnTest, packEmpty) {
- // Create option instance. Check that constructor doesn't throw.
- const uint8_t flags = Option6ClientFqdn::FLAG_S;
- boost::scoped_ptr<Option6ClientFqdn> option;
- ASSERT_NO_THROW(
- option.reset(new Option6ClientFqdn(flags))
- );
- ASSERT_TRUE(option);
- // Prepare on-wire format of the option.
- isc::util::OutputBuffer buf(5);
- ASSERT_NO_THROW(option->pack(buf));
- // Prepare reference data.
- const uint8_t ref_data[] = {
- 0, 39, 0, 1, // header
- Option6ClientFqdn::FLAG_S // flags
- };
- size_t ref_data_size = sizeof(ref_data) / sizeof(ref_data[0]);
- // Check if the buffer has the same length as the reference data,
- // so as they can be compared directly.
- ASSERT_EQ(ref_data_size, buf.getLength());
- EXPECT_EQ(0, memcmp(ref_data, buf.getData(), buf.getLength()));
- }
- // This test verifies that on-wire option data holding fully qualified domain
- // name is parsed correctly.
- TEST(Option6ClientFqdnTest, unpack) {
- // Create option instance. Check that constructor doesn't throw.
- boost::scoped_ptr<Option6ClientFqdn> option;
- ASSERT_NO_THROW(
- option.reset(new Option6ClientFqdn(Option6ClientFqdn::FLAG_O,
- "myhost",
- Option6ClientFqdn::PARTIAL))
- );
- ASSERT_TRUE(option);
- // Make sure that the parameters have been set correctly. Later in this
- // test we will check that they will be replaced with new values when
- // unpack is called.
- EXPECT_FALSE(option->getFlag(Option6ClientFqdn::FLAG_S));
- EXPECT_FALSE(option->getFlag(Option6ClientFqdn::FLAG_N));
- EXPECT_TRUE(option->getFlag(Option6ClientFqdn::FLAG_O));
- EXPECT_EQ("myhost", option->getDomainName());
- EXPECT_EQ(Option6ClientFqdn::PARTIAL, option->getDomainNameType());
- const uint8_t in_data[] = {
- Option6ClientFqdn::FLAG_S, // flags
- 6, 109, 121, 104, 111, 115, 116, // myhost.
- 7, 101, 120, 97, 109, 112, 108, 101, // example.
- 3, 99, 111, 109, 0 // com.
- };
- size_t in_data_size = sizeof(in_data) / sizeof(in_data[0]);
- OptionBuffer in_buf(in_data, in_data + in_data_size);
- // Initialize new values from the on-wire format.
- ASSERT_NO_THROW(option->unpack(in_buf.begin(), in_buf.end()));
- // Check that new values are correct.
- EXPECT_TRUE(option->getFlag(Option6ClientFqdn::FLAG_S));
- EXPECT_FALSE(option->getFlag(Option6ClientFqdn::FLAG_N));
- EXPECT_FALSE(option->getFlag(Option6ClientFqdn::FLAG_O));
- EXPECT_EQ("myhost.example.com.", option->getDomainName());
- EXPECT_EQ(Option6ClientFqdn::FULL, option->getDomainNameType());
- }
- // This test verifies that on-wire option data holding partial domain name
- // is parsed correctly.
- TEST(Option6ClientFqdnTest, unpackPartial) {
- // Create option instance. Check that constructor doesn't throw.
- boost::scoped_ptr<Option6ClientFqdn> option;
- ASSERT_NO_THROW(
- option.reset(new Option6ClientFqdn(Option6ClientFqdn::FLAG_O,
- "myhost.example.com"))
- );
- ASSERT_TRUE(option);
- // Make sure that the parameters have been set correctly. Later in this
- // test we will check that they will be replaced with new values when
- // unpack is called.
- EXPECT_FALSE(option->getFlag(Option6ClientFqdn::FLAG_S));
- EXPECT_FALSE(option->getFlag(Option6ClientFqdn::FLAG_N));
- EXPECT_TRUE(option->getFlag(Option6ClientFqdn::FLAG_O));
- EXPECT_EQ("myhost.example.com.", option->getDomainName());
- EXPECT_EQ(Option6ClientFqdn::FULL, option->getDomainNameType());
- const uint8_t in_data[] = {
- Option6ClientFqdn::FLAG_S, // flags
- 6, 109, 121, 104, 111, 115, 116 // myhost
- };
- size_t in_data_size = sizeof(in_data) / sizeof(in_data[0]);
- OptionBuffer in_buf(in_data, in_data + in_data_size);
- // Initialize new values from the on-wire format.
- ASSERT_NO_THROW(option->unpack(in_buf.begin(), in_buf.end()));
- // Check that new values are correct.
- EXPECT_TRUE(option->getFlag(Option6ClientFqdn::FLAG_S));
- EXPECT_FALSE(option->getFlag(Option6ClientFqdn::FLAG_N));
- EXPECT_FALSE(option->getFlag(Option6ClientFqdn::FLAG_O));
- EXPECT_EQ("myhost", option->getDomainName());
- EXPECT_EQ(Option6ClientFqdn::PARTIAL, option->getDomainNameType());
- }
- // This test verifies that the empty buffer is rejected when decoding an option
- // from on-wire format.
- TEST(Option6ClientFqdnTest, unpackTruncated) {
- boost::scoped_ptr<Option6ClientFqdn> option;
- ASSERT_NO_THROW(
- option.reset(new Option6ClientFqdn(Option6ClientFqdn::FLAG_O))
- );
- ASSERT_TRUE(option);
- // Empty buffer is invalid. It should be at least 1 octet long.
- OptionBuffer in_buf;
- EXPECT_THROW(option->unpack(in_buf.begin(), in_buf.end()), OutOfRange);
- }
- // This test verifies that string representation of the option returned by
- // toText method is correctly formatted.
- TEST(Option6ClientFqdnTest, toText) {
- // Create option instance. Check that constructor doesn't throw.
- uint8_t flags = Option6ClientFqdn::FLAG_N | Option6ClientFqdn::FLAG_O;
- boost::scoped_ptr<Option6ClientFqdn> option;
- ASSERT_NO_THROW(
- option.reset(new Option6ClientFqdn(flags,
- "myhost.example.com"))
- );
- ASSERT_TRUE(option);
- // The base indentation of the option will be set to 2. It should appear
- // as follows.
- std::string ref_string =
- " type=39(CLIENT_FQDN), flags: (N=1, O=1, S=0), "
- "domain-name='myhost.example.com.' (full)";
- const int indent = 2;
- EXPECT_EQ(ref_string, option->toText(indent));
- // Create another option with different parameters:
- // - flags set to 0
- // - domain-name is now partial, not fully qualified
- // Also, remove base indentation.
- flags = 0;
- ASSERT_NO_THROW(
- option.reset(new Option6ClientFqdn(flags, "myhost",
- Option6ClientFqdn::PARTIAL))
- );
- ref_string =
- "type=39(CLIENT_FQDN), flags: (N=0, O=0, S=0), "
- "domain-name='myhost' (partial)";
- EXPECT_EQ(ref_string, option->toText());
- }
- // This test verifies that the correct length of the option in on-wire
- // format is returned.
- TEST(Option6ClientFqdnTest, len) {
- // Create option instance. Check that constructor doesn't throw.
- boost::scoped_ptr<Option6ClientFqdn> option;
- ASSERT_NO_THROW(
- option.reset(new Option6ClientFqdn(0, "myhost.example.com"))
- );
- ASSERT_TRUE(option);
- // This option comprises a header (4 octets), flag field (1 octet),
- // and wire representation of the domain name (length equal to the
- // length of the string representation of the domain name + 1).
- EXPECT_EQ(25, option->len());
- // Let's check that the size will change when domain name of a different
- // size is used.
- ASSERT_NO_THROW(
- option.reset(new Option6ClientFqdn(0, "example.com"))
- );
- ASSERT_TRUE(option);
- EXPECT_EQ(18, option->len());
- ASSERT_NO_THROW(
- option.reset(new Option6ClientFqdn(0, "myhost",
- Option6ClientFqdn::PARTIAL))
- );
- ASSERT_TRUE(option);
- EXPECT_EQ(12, option->len());
- }
- } // anonymous namespace
|