diff options
Diffstat (limited to 'src/lib/dhcp')
-rw-r--r-- | src/lib/dhcp/classify.cc | 15 | ||||
-rw-r--r-- | src/lib/dhcp/classify.h | 9 | ||||
-rw-r--r-- | src/lib/dhcp/pkt4.cc | 8 | ||||
-rw-r--r-- | src/lib/dhcp/tests/classify_unittest.cc | 26 | ||||
-rw-r--r-- | src/lib/dhcp/tests/iface_mgr_unittest.cc | 4 | ||||
-rw-r--r-- | src/lib/dhcp/tests/option_definition_unittest.cc | 28 | ||||
-rw-r--r-- | src/lib/dhcp/tests/pkt4_unittest.cc | 32 |
7 files changed, 105 insertions, 17 deletions
diff --git a/src/lib/dhcp/classify.cc b/src/lib/dhcp/classify.cc index ed499266c0..95fc5dd08b 100644 --- a/src/lib/dhcp/classify.cc +++ b/src/lib/dhcp/classify.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2014-2016 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -10,6 +10,7 @@ #include <boost/algorithm/string/classification.hpp> #include <boost/algorithm/string/constants.hpp> #include <boost/algorithm/string/split.hpp> +#include <sstream> #include <vector> namespace isc { @@ -28,6 +29,18 @@ ClientClasses::ClientClasses(const std::string& class_names) } } } + +std::string +ClientClasses::toText(const std::string& separator) const { + std::stringstream s; + for (const_iterator class_it = begin(); class_it != end(); ++class_it) { + if (class_it != begin()) { + s << separator; + } + s << *class_it; + } + return (s.str()); +} } // end of namespace isc::dhcp } // end of namespace isc diff --git a/src/lib/dhcp/classify.h b/src/lib/dhcp/classify.h index 61911f1047..174930c348 100644 --- a/src/lib/dhcp/classify.h +++ b/src/lib/dhcp/classify.h @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2014-2016 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -65,6 +65,13 @@ namespace dhcp { contains(const ClientClass& x) const { return (find(x) != end()); } + + /// @brief Returns all class names as text + /// + /// @param separator Separator to be used between class names. The + /// default separator comprises comma sign followed by space + /// character. + std::string toText(const std::string& separator = ", ") const; }; }; diff --git a/src/lib/dhcp/pkt4.cc b/src/lib/dhcp/pkt4.cc index 706574b5b0..3c980b5205 100644 --- a/src/lib/dhcp/pkt4.cc +++ b/src/lib/dhcp/pkt4.cc @@ -482,7 +482,9 @@ Pkt4::setSname(const uint8_t* sname, size_t snameLen /*= MAX_SNAME_LEN*/) { } std::copy(sname, (sname + snameLen), sname_); - std::fill((sname_ + snameLen), (sname_ + MAX_SNAME_LEN), 0); + if (snameLen < MAX_SNAME_LEN) { + std::fill((sname_ + snameLen), (sname_ + MAX_SNAME_LEN), 0); + } // No need to store snameLen as any empty space is filled with 0s } @@ -498,7 +500,9 @@ Pkt4::setFile(const uint8_t* file, size_t fileLen /*= MAX_FILE_LEN*/) { } std::copy(file, (file + fileLen), file_); - std::fill((file_ + fileLen), (file_ + MAX_FILE_LEN), 0); + if (fileLen < MAX_FILE_LEN) { + std::fill((file_ + fileLen), (file_ + MAX_FILE_LEN), 0); + } // No need to store fileLen as any empty space is filled with 0s } diff --git a/src/lib/dhcp/tests/classify_unittest.cc b/src/lib/dhcp/tests/classify_unittest.cc index 9de2e284c5..215551eb06 100644 --- a/src/lib/dhcp/tests/classify_unittest.cc +++ b/src/lib/dhcp/tests/classify_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2011-2016 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -107,3 +107,27 @@ TEST(ClassifyTest, ClientClassesIterator) { EXPECT_TRUE(seengamma); EXPECT_FALSE(seendelta); } + +// Check that the ClientClasses::toText function returns +// correct values. +TEST(ClassifyTest, ClientClassesToText) { + // No classes. + ClientClasses classes; + EXPECT_TRUE(classes.toText().empty()); + + // Insert single class name and see if it doesn't include spurious + // comma after it. + classes.insert("alpha"); + EXPECT_EQ("alpha", classes.toText()); + + // Insert next class name and see that both classes are present. + classes.insert("gamma"); + EXPECT_EQ("alpha, gamma", classes.toText()); + + // Insert third class and make sure they get ordered alphabetically. + classes.insert("beta"); + EXPECT_EQ("alpha, beta, gamma", classes.toText()); + + // Check non-standard separator. + EXPECT_EQ("alpha.beta.gamma", classes.toText(".")); +} diff --git a/src/lib/dhcp/tests/iface_mgr_unittest.cc b/src/lib/dhcp/tests/iface_mgr_unittest.cc index 0d244b7c7f..efd21df6a5 100644 --- a/src/lib/dhcp/tests/iface_mgr_unittest.cc +++ b/src/lib/dhcp/tests/iface_mgr_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2011-2016 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -883,7 +883,7 @@ TEST_F(IfaceMgrTest, multipleSockets) { init_sockets_it != init_sockets.end(); ++init_sockets_it) { // recv() must result in error when using invalid socket. char buf; - recv(*init_sockets_it, &buf, 1, MSG_PEEK); + static_cast<void>(recv(*init_sockets_it, &buf, 1, MSG_PEEK)); // EWOULDBLOCK would mean that socket is valid/open but // simply no data is received so we have to check for // other errors. diff --git a/src/lib/dhcp/tests/option_definition_unittest.cc b/src/lib/dhcp/tests/option_definition_unittest.cc index 399c62dcc7..ccf658b0d3 100644 --- a/src/lib/dhcp/tests/option_definition_unittest.cc +++ b/src/lib/dhcp/tests/option_definition_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2012-2016 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -362,6 +362,7 @@ TEST_F(OptionDefinitionTest, ipv6AddressArray) { option_v6 = opt_def.optionFactory(Option::V6, D6O_NIS_SERVERS, buf); ); const Option* optptr = option_v6.get(); + ASSERT_TRUE(optptr); ASSERT_TRUE(typeid(*optptr) == typeid(Option6AddrLst)); boost::shared_ptr<Option6AddrLst> option_cast_v6 = boost::static_pointer_cast<Option6AddrLst>(option_v6); @@ -418,6 +419,7 @@ TEST_F(OptionDefinitionTest, ipv6AddressArrayTokenized) { // should have Option6AddrLst type. ASSERT_TRUE(option_v6); const Option* optptr = option_v6.get(); + ASSERT_TRUE(optptr); ASSERT_TRUE(typeid(*optptr) == typeid(Option6AddrLst)); // Cast to the actual option type to get IPv6 addresses from it. boost::shared_ptr<Option6AddrLst> option_cast_v6 = @@ -462,6 +464,7 @@ TEST_F(OptionDefinitionTest, ipv4AddressArray) { option_v4 = opt_def.optionFactory(Option::V4, DHO_NAME_SERVERS, buf) ); const Option* optptr = option_v4.get(); + ASSERT_TRUE(optptr); ASSERT_TRUE(typeid(*optptr) == typeid(Option4AddrLst)); // Get the list of parsed addresses from the option object. boost::shared_ptr<Option4AddrLst> option_cast_v4 = @@ -515,6 +518,7 @@ TEST_F(OptionDefinitionTest, ipv4AddressArrayTokenized) { // should have Option6AddrLst type. ASSERT_TRUE(option_v4); const Option* optptr = option_v4.get(); + ASSERT_TRUE(optptr); ASSERT_TRUE(typeid(*optptr) == typeid(Option4AddrLst)); // Cast to the actual option type to get IPv4 addresses from it. boost::shared_ptr<Option4AddrLst> option_cast_v4 = @@ -540,6 +544,7 @@ TEST_F(OptionDefinitionTest, empty) { option_v6 = opt_def.optionFactory(Option::V6, D6O_RAPID_COMMIT, OptionBuffer()) ); const Option* optptr = option_v6.get(); + ASSERT_TRUE(optptr); ASSERT_TRUE(typeid(*optptr) == typeid(Option)); // Expect 'empty' DHCPv6 option. EXPECT_EQ(Option::V6, option_v6->getUniverse()); @@ -584,6 +589,7 @@ TEST_F(OptionDefinitionTest, emptyWithSuboptions) { ); // Returned option should be of the OptionCustom type. const Option* optptr = option_v6.get(); + ASSERT_TRUE(optptr); ASSERT_TRUE(typeid(*optptr) == typeid(OptionCustom)); // Sanity-check length, universe etc. EXPECT_EQ(Option::V6, option_v6->getUniverse()); @@ -623,6 +629,7 @@ TEST_F(OptionDefinitionTest, binary) { ); // Expect base option type returned. const Option* optptr = option_v6.get(); + ASSERT_TRUE(optptr); ASSERT_TRUE(typeid(*optptr) == typeid(Option)); // Sanity check on universe, length and size. These are // the basic parameters identifying any option. @@ -671,6 +678,7 @@ TEST_F(OptionDefinitionTest, recordIA6) { OptionPtr option_v6; ASSERT_NO_THROW(option_v6 = opt_def.optionFactory(Option::V6, D6O_IA_NA, buf)); const Option* optptr = option_v6.get(); + ASSERT_TRUE(optptr); ASSERT_TRUE(typeid(*optptr) == typeid(Option6IA)); boost::shared_ptr<Option6IA> option_cast_v6 = boost::static_pointer_cast<Option6IA>(option_v6); @@ -715,6 +723,7 @@ TEST_F(OptionDefinitionTest, recordIAAddr6) { } ASSERT_NO_THROW(option_v6 = opt_def.optionFactory(Option::V6, D6O_IAADDR, buf)); const Option* optptr = option_v6.get(); + ASSERT_TRUE(optptr); ASSERT_TRUE(typeid(*optptr) == typeid(Option6IAAddr)); boost::shared_ptr<Option6IAAddr> option_cast_v6 = boost::static_pointer_cast<Option6IAAddr>(option_v6); @@ -753,6 +762,7 @@ TEST_F(OptionDefinitionTest, recordIAAddr6Tokenized) { ASSERT_NO_THROW(option_v6 = opt_def.optionFactory(Option::V6, D6O_IAADDR, data_field_values)); const Option* optptr = option_v6.get(); + ASSERT_TRUE(optptr); ASSERT_TRUE(typeid(*optptr) == typeid(Option6IAAddr)); boost::shared_ptr<Option6IAAddr> option_cast_v6 = boost::static_pointer_cast<Option6IAAddr>(option_v6); @@ -776,6 +786,7 @@ TEST_F(OptionDefinitionTest, boolValue) { OptionBuffer(1, 1)); ); const Option* optptr = option_v4.get(); + ASSERT_TRUE(optptr); ASSERT_TRUE(typeid(*optptr) == typeid(OptionCustom)); // Validate parsed value in the received option. boost::shared_ptr<OptionCustom> option_cast_v4 = @@ -816,6 +827,7 @@ TEST_F(OptionDefinitionTest, boolTokenized) { values); ); const Option* optptr = option_v4.get(); + ASSERT_TRUE(optptr); ASSERT_TRUE(typeid(*optptr) == typeid(OptionCustom)); // Validate the value. OptionCustomPtr option_cast_v4 = @@ -829,6 +841,7 @@ TEST_F(OptionDefinitionTest, boolTokenized) { values); ); optptr = option_v4.get(); + ASSERT_TRUE(optptr); ASSERT_TRUE(typeid(*optptr) == typeid(OptionCustom)); // Validate the value. option_cast_v4 = boost::static_pointer_cast<OptionCustom>(option_v4); @@ -841,6 +854,7 @@ TEST_F(OptionDefinitionTest, boolTokenized) { values); ); optptr = option_v4.get(); + ASSERT_TRUE(optptr); ASSERT_TRUE(typeid(*optptr) == typeid(OptionCustom)); // Validate the value. option_cast_v4 = boost::static_pointer_cast<OptionCustom>(option_v4); @@ -853,6 +867,7 @@ TEST_F(OptionDefinitionTest, boolTokenized) { values); ); optptr = option_v4.get(); + ASSERT_TRUE(optptr); ASSERT_TRUE(typeid(*optptr) == typeid(OptionCustom)); // Validate the value. option_cast_v4 = boost::static_pointer_cast<OptionCustom>(option_v4); @@ -885,6 +900,7 @@ TEST_F(OptionDefinitionTest, uint8) { OptionBuffer(1, 1)); ); const Option* optptr = option_v6.get(); + ASSERT_TRUE(optptr); ASSERT_TRUE(typeid(*optptr) == typeid(OptionInt<uint8_t>)); // Validate the value. boost::shared_ptr<OptionInt<uint8_t> > option_cast_v6 = @@ -914,6 +930,7 @@ TEST_F(OptionDefinitionTest, uint8Tokenized) { option_v6 = opt_def.optionFactory(Option::V6, D6O_PREFERENCE, values); ); const Option* optptr = option_v6.get(); + ASSERT_TRUE(optptr); ASSERT_TRUE(typeid(*optptr) == typeid(OptionInt<uint8_t>)); // Validate the value. boost::shared_ptr<OptionInt<uint8_t> > option_cast_v6 = @@ -938,6 +955,7 @@ TEST_F(OptionDefinitionTest, uint16) { option_v6 = opt_def.optionFactory(Option::V6, D6O_ELAPSED_TIME, buf); ); const Option* optptr = option_v6.get(); + ASSERT_TRUE(optptr); ASSERT_TRUE(typeid(*optptr) == typeid(OptionInt<uint16_t>)); // Validate the value. boost::shared_ptr<OptionInt<uint16_t> > option_cast_v6 = @@ -968,6 +986,7 @@ TEST_F(OptionDefinitionTest, uint16Tokenized) { option_v6 = opt_def.optionFactory(Option::V6, D6O_ELAPSED_TIME, values); ); const Option* optptr = option_v6.get(); + ASSERT_TRUE(optptr); ASSERT_TRUE(typeid(*optptr) == typeid(OptionInt<uint16_t>)); // Validate the value. boost::shared_ptr<OptionInt<uint16_t> > option_cast_v6 = @@ -994,6 +1013,7 @@ TEST_F(OptionDefinitionTest, uint32) { option_v6 = opt_def.optionFactory(Option::V6, D6O_CLT_TIME, buf); ); const Option* optptr = option_v6.get(); + ASSERT_TRUE(optptr); ASSERT_TRUE(typeid(*optptr) == typeid(OptionInt<uint32_t>)); // Validate the value. boost::shared_ptr<OptionInt<uint32_t> > option_cast_v6 = @@ -1023,6 +1043,7 @@ TEST_F(OptionDefinitionTest, uint32Tokenized) { option_v6 = opt_def.optionFactory(Option::V6, D6O_CLT_TIME, values); ); const Option* optptr = option_v6.get(); + ASSERT_TRUE(optptr); ASSERT_TRUE(typeid(*optptr) == typeid(OptionInt<uint32_t>)); // Validate the value. boost::shared_ptr<OptionInt<uint32_t> > option_cast_v6 = @@ -1053,6 +1074,7 @@ TEST_F(OptionDefinitionTest, uint16Array) { option_v6 = opt_def.optionFactory(Option::V6, opt_code, buf); ); const Option* optptr = option_v6.get(); + ASSERT_TRUE(optptr); ASSERT_TRUE(typeid(*optptr) == typeid(OptionIntArray<uint16_t>)); boost::shared_ptr<OptionIntArray<uint16_t> > option_cast_v6 = boost::static_pointer_cast<OptionIntArray<uint16_t> >(option_v6); @@ -1096,6 +1118,7 @@ TEST_F(OptionDefinitionTest, uint16ArrayTokenized) { option_v6 = opt_def.optionFactory(Option::V6, opt_code, str_values); ); const Option* optptr = option_v6.get(); + ASSERT_TRUE(optptr); ASSERT_TRUE(typeid(*optptr) == typeid(OptionIntArray<uint16_t>)); boost::shared_ptr<OptionIntArray<uint16_t> > option_cast_v6 = boost::static_pointer_cast<OptionIntArray<uint16_t> >(option_v6); @@ -1128,6 +1151,7 @@ TEST_F(OptionDefinitionTest, uint32Array) { option_v6 = opt_def.optionFactory(Option::V6, opt_code, buf); ); const Option* optptr = option_v6.get(); + ASSERT_TRUE(optptr); ASSERT_TRUE(typeid(*optptr) == typeid(OptionIntArray<uint32_t>)); boost::shared_ptr<OptionIntArray<uint32_t> > option_cast_v6 = boost::static_pointer_cast<OptionIntArray<uint32_t> >(option_v6); @@ -1174,6 +1198,7 @@ TEST_F(OptionDefinitionTest, uint32ArrayTokenized) { option_v6 = opt_def.optionFactory(Option::V6, opt_code, str_values); ); const Option* optptr = option_v6.get(); + ASSERT_TRUE(optptr); ASSERT_TRUE(typeid(*optptr) == typeid(OptionIntArray<uint32_t>)); boost::shared_ptr<OptionIntArray<uint32_t> > option_cast_v6 = boost::static_pointer_cast<OptionIntArray<uint32_t> >(option_v6); @@ -1201,6 +1226,7 @@ TEST_F(OptionDefinitionTest, utf8StringTokenized) { ); ASSERT_TRUE(option_v6); const Option* optptr = option_v6.get(); + ASSERT_TRUE(optptr); ASSERT_TRUE(typeid(*optptr) == typeid(OptionString)); OptionStringPtr option_v6_string = boost::static_pointer_cast<OptionString>(option_v6); diff --git a/src/lib/dhcp/tests/pkt4_unittest.cc b/src/lib/dhcp/tests/pkt4_unittest.cc index ac3f1b66ef..1db3e61940 100644 --- a/src/lib/dhcp/tests/pkt4_unittest.cc +++ b/src/lib/dhcp/tests/pkt4_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2011-2016 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -485,13 +485,15 @@ TEST_F(Pkt4Test, sname) { uint8_t sname[Pkt4::MAX_SNAME_LEN]; scoped_ptr<Pkt4> pkt; - // Let's test each sname length, from 0 till 64 - for (size_t snameLen = 0; snameLen < Pkt4::MAX_SNAME_LEN; ++snameLen) { + // Let's test each sname length, from 0 till 64 (included) + for (size_t snameLen = 0; snameLen <= Pkt4::MAX_SNAME_LEN; ++snameLen) { for (size_t i = 0; i < snameLen; ++i) { sname[i] = i + 1; } - for (size_t i = snameLen; i < Pkt4::MAX_SNAME_LEN; ++i) { - sname[i] = 0; + if (snameLen < Pkt4::MAX_SNAME_LEN) { + for (size_t i = snameLen; i < Pkt4::MAX_SNAME_LEN; ++i) { + sname[i] = 0; + } } // Type and transaction doesn't matter in this test @@ -516,6 +518,11 @@ TEST_F(Pkt4Test, sname) { Pkt4 pkt4(DHCPOFFER, 1234); EXPECT_THROW(pkt4.setSname(NULL, Pkt4::MAX_SNAME_LEN), InvalidParameter); EXPECT_THROW(pkt4.setSname(NULL, 0), InvalidParameter); + + // Check that a too long argument generates an exception + // (the actual content doesn't matter). + uint8_t bigsname[Pkt4::MAX_SNAME_LEN + 1]; + EXPECT_THROW(pkt4.setSname(bigsname, Pkt4::MAX_SNAME_LEN + 1), OutOfRange); } TEST_F(Pkt4Test, file) { @@ -523,13 +530,15 @@ TEST_F(Pkt4Test, file) { uint8_t file[Pkt4::MAX_FILE_LEN]; scoped_ptr<Pkt4> pkt; - // Let's test each file length, from 0 till 128. - for (size_t fileLen = 0; fileLen < Pkt4::MAX_FILE_LEN; ++fileLen) { + // Let's test each file length, from 0 till 128 (included). + for (size_t fileLen = 0; fileLen <= Pkt4::MAX_FILE_LEN; ++fileLen) { for (size_t i = 0; i < fileLen; ++i) { file[i] = i + 1; } - for (size_t i = fileLen; i < Pkt4::MAX_FILE_LEN; ++i) { - file[i] = 0; + if (fileLen < Pkt4::MAX_FILE_LEN) { + for (size_t i = fileLen; i < Pkt4::MAX_FILE_LEN; ++i) { + file[i] = 0; + } } // Type and transaction doesn't matter in this test. @@ -554,6 +563,11 @@ TEST_F(Pkt4Test, file) { Pkt4 pkt4(DHCPOFFER, 1234); EXPECT_THROW(pkt4.setFile(NULL, Pkt4::MAX_FILE_LEN), InvalidParameter); EXPECT_THROW(pkt4.setFile(NULL, 0), InvalidParameter); + + // Check that a too long argument generates an exception + // (the actual content doesn't matter). + uint8_t bigfile[Pkt4::MAX_FILE_LEN + 1]; + EXPECT_THROW(pkt4.setFile(bigfile, Pkt4::MAX_FILE_LEN + 1), OutOfRange); } TEST_F(Pkt4Test, options) { |