From: Piotrek Zadroga Date: Tue, 17 Oct 2023 10:48:59 +0000 (+0200) Subject: [#3074] add more UTs X-Git-Tag: Kea-2.5.5~59 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=73edb9dccadcd737da6749368f765b60efc2919f;p=thirdparty%2Fkea.git [#3074] add more UTs --- diff --git a/src/lib/dhcp/option_classless_static_route.cc b/src/lib/dhcp/option_classless_static_route.cc index 4a6f640cdc..816583ec63 100644 --- a/src/lib/dhcp/option_classless_static_route.cc +++ b/src/lib/dhcp/option_classless_static_route.cc @@ -6,9 +6,9 @@ #include +#include #include -#include #include using namespace isc::asiolink; @@ -88,10 +88,8 @@ OptionClasslessStaticRoute::toText(int indent) const { << "len=" << (len() - getHeaderLen()); int i = 0; for (const auto& route : static_routes_) { - stream << ", Route " << ++i - << " (subnet " << get<0>(route).toText() << "/" - << static_cast(get<1>(route)) << ", router IP " - << get<2>(route) << ")"; + stream << ", Route " << ++i << " (subnet " << get<0>(route).toText() << "/" + << static_cast(get<1>(route)) << ", router IP " << get<2>(route) << ")"; } return (stream.str()); @@ -186,8 +184,8 @@ OptionClasslessStaticRoute::parseWireData(OptionBufferConstIter begin, OptionBuf // once we know haw many significant octets there are, check for truncated data again if (distance(begin, end) < (significant_octets + V4ADDRESS_LEN)) { - isc_throw(OutOfRange, "DHCPv4 OptionClasslessStaticRoute " - << type_ << " is truncated."); + isc_throw(OutOfRange, + "DHCPv4 OptionClasslessStaticRoute " << type_ << " is truncated."); } // following octets are significant octets of the subnet nr @@ -201,18 +199,18 @@ OptionClasslessStaticRoute::parseWireData(OptionBufferConstIter begin, OptionBuf case 1: subnet_octets = *begin; subnet_nr = IOAddress(subnet_octets << 24); - break ; + break; case 2: subnet_octets = readUint16(&(*begin), distance(begin, end)); subnet_nr = IOAddress(subnet_octets << 16); - break ; + break; case 3: // we are reading one octet too much in this case, // but since we did check for truncated data before, // we are safe do so and mask 4th octet with zeros subnet_octets = readUint32(&(*begin), distance(begin, end)); subnet_nr = IOAddress(subnet_octets & 0xFFFFFF00); - break ; + break; case 4: subnet_octets = readUint32(&(*begin), distance(begin, end)); subnet_nr = IOAddress(subnet_octets); @@ -238,9 +236,10 @@ OptionClasslessStaticRoute::parseConfigData(const std::string& config_txt) { std::vector parts = str::tokens(str::trim(route_str), std::string("-")); if (parts.size() != 2) { isc_throw(BadValue, "DHCPv4 OptionClasslessStaticRoute " - << type_ << " has invalid value, route definition must" - " have format as in example: 10.229.0.128/25" - " - 10.229.0.1"); + << type_ + << " has invalid value, option definition must" + " have comma separated routes formatted as in " + "example: 10.229.0.128/25 - 10.229.0.1"); } std::string txt_prefix = str::trim(parts[0]); @@ -276,7 +275,7 @@ OptionClasslessStaticRoute::parseConfigData(const std::string& config_txt) { if (len > 32) { isc_throw(BadValue, ""); } - } catch (...) { + } catch (...) { isc_throw(BadValue, "DHCPv4 OptionClasslessStaticRoute " << type_ << " has invalid value, provided prefix len " << txt_prefix_len << " is not valid."); diff --git a/src/lib/dhcp/option_classless_static_route.h b/src/lib/dhcp/option_classless_static_route.h index 5ebcfcadfd..f0b2438ffa 100644 --- a/src/lib/dhcp/option_classless_static_route.h +++ b/src/lib/dhcp/option_classless_static_route.h @@ -21,7 +21,9 @@ typedef std::tuple StaticRout class OptionClasslessStaticRoute : public Option { public: /// @brief Empty Constructor - OptionClasslessStaticRoute() : Option(V4, DHO_CLASSLESS_STATIC_ROUTE), static_routes_(), data_len_(0) {} + OptionClasslessStaticRoute() + : Option(V4, DHO_CLASSLESS_STATIC_ROUTE), static_routes_(), data_len_(0) { + } /// @brief Constructor of the %Option from on-wire data. /// @@ -103,7 +105,8 @@ private: /// @return number of significant octets static uint8_t calcSignificantOctets(const uint8_t& mask_width); - /// @brief Calculates length in octets of all encoded static routes and stores it in @c data_len_ + /// @brief Calculates length in octets of all encoded static routes and stores it in @c + /// data_len_ /// /// Calculation is done according to static routes encoding rules in RFC3442. /// This should be called whenever @c static_routes_ is changed. diff --git a/src/lib/dhcp/tests/option_classless_static_route_unittest.cc b/src/lib/dhcp/tests/option_classless_static_route_unittest.cc index ef0d615e12..c81fd8979d 100644 --- a/src/lib/dhcp/tests/option_classless_static_route_unittest.cc +++ b/src/lib/dhcp/tests/option_classless_static_route_unittest.cc @@ -7,6 +7,7 @@ #include #include +#include #include @@ -47,16 +48,238 @@ TEST(OptionClasslessStaticRouteTest, emptyCtorAddOneRoute) { option->toText()); } +// This test verifies adding more routes to OptionClasslessStaticRoute class. +TEST(OptionClasslessStaticRouteTest, emptyCtorAddMoreRoutes) { + // Create option instance. Check that constructor doesn't throw. + OptionClasslessStaticRoutePtr option; + EXPECT_NO_THROW(option.reset(new OptionClasslessStaticRoute())); + ASSERT_TRUE(option); + + // Add 3 static routes. + StaticRouteTuple route1 = std::make_tuple(IOAddress("0.0.0.0"), 0, IOAddress("10.198.122.1")); + option->addRoute(route1); + StaticRouteTuple route2 = std::make_tuple(IOAddress("1.2.3.4"), 32, IOAddress("10.20.30.40")); + option->addRoute(route2); + StaticRouteTuple route3 = std::make_tuple(IOAddress("5.6.0.0"), 16, IOAddress("50.60.70.80")); + option->addRoute(route3); + + // Expected len: 2 (option code + option len headers) + 5 (1 dest descriptor + 4 router addr) + // + 9 (5 d.d. + 4 r.a.) + 7 (3 d.d. + 4 r.a.). + EXPECT_EQ(23, option->len()); + + // Verify toText() is working fine. + EXPECT_EQ("type=121(CLASSLESS_STATIC_ROUTE), len=21, " + "Route 1 (subnet 0.0.0.0/0, router IP 10.198.122.1), " + "Route 2 (subnet 1.2.3.4/32, router IP 10.20.30.40), " + "Route 3 (subnet 5.6.0.0/16, router IP 50.60.70.80)", + option->toText()); +} + // This test verifies constructor of the OptionClasslessStaticRoute class from config data. // Only one static route is defined. -TEST(OptionClasslessStaticRouteTest, bufferCtorWithOneRoute) { +TEST(OptionClasslessStaticRouteTest, bufferFromStrCtorWithOneRoute) { + // Prepare data to decode - one route with mask width = 8. + const std::string config = "'10.0.0.0/8 - 10.198.122.1'"; + OptionBuffer buf = isc::util::str::quotedStringToBinary(config); + + // Create option instance. Check that constructor doesn't throw. Unpack is also tested here. + OptionClasslessStaticRoutePtr option; + EXPECT_NO_THROW(option.reset(new OptionClasslessStaticRoute(buf.begin(), buf.end()))); + ASSERT_TRUE(option); + + // Expected len: 2 (option code + option len headers) + 6 (2 dest descriptor + 4 router addr). + EXPECT_EQ(8, option->len()); + + // Verify toText() is working fine. + EXPECT_EQ("type=121(CLASSLESS_STATIC_ROUTE), len=6, Route 1 (subnet 10.0.0.0/8," + " router IP 10.198.122.1)", + option->toText()); +} + +// This test verifies constructor of the OptionClasslessStaticRoute class from config data. +// 3 static routes are defined. +TEST(OptionClasslessStaticRouteTest, bufferFromStrCtorWithMoreRoutes) { + // Prepare data to decode - 3 static routes + const std::string config = "'0.0.0.0/0 - 10.17.0.1,10.229.0.128/25-10.229.0.1, " + "10.27.129.0/24 - 10.27.129.1'"; + OptionBuffer buf = isc::util::str::quotedStringToBinary(config); + + // Create option instance. Check that constructor doesn't throw. Unpack is also tested here. + OptionClasslessStaticRoutePtr option; + EXPECT_NO_THROW(option.reset(new OptionClasslessStaticRoute(buf.begin(), buf.end()))); + ASSERT_TRUE(option); + + // Expected len: 2 (option code + option len headers) + 5 (1 dest descriptor + 4 router addr) + // + 9 (5 dest descriptor + 4 router addr) + 8 (4 dest descriptor + 4 router addr). + EXPECT_EQ(24, option->len()); + + // Verify toText() is working fine. + EXPECT_EQ("type=121(CLASSLESS_STATIC_ROUTE), len=22, " + "Route 1 (subnet 0.0.0.0/0, router IP 10.17.0.1), " + "Route 2 (subnet 10.229.0.128/25, router IP 10.229.0.1), " + "Route 3 (subnet 10.27.129.0/24, router IP 10.27.129.1)", + option->toText()); +} + +// This test verifies that constructor from config data throws an exception +// when data in the buffer has wrong format. +TEST(OptionClasslessStaticRouteTest, bufferFromStrCtorMissingDash) { + // Prepare data to decode - second route has missing dash separator + const std::string config = "'0.0.0.0/0 - 10.17.0.1,10.229.0.128/25 10.229.0.1, " + "10.27.129.0/24 - 10.27.129.1'"; + OptionBuffer buf = isc::util::str::quotedStringToBinary(config); + + // Create option instance. Check that constructor throws BadValue during Unpack. + OptionClasslessStaticRoutePtr option; + EXPECT_THROW(option.reset(new OptionClasslessStaticRoute(buf.begin(), buf.end())), + isc::BadValue); + ASSERT_FALSE(option); +} + +// This test verifies that constructor from config data throws an exception +// when data in the buffer has wrong format. +TEST(OptionClasslessStaticRouteTest, bufferFromStrCtorMissingPrefixLen) { + // Prepare data to decode - second route has missing "/prefix len" + const std::string config = "'0.0.0.0/0 - 10.17.0.1,10.229.0.128 - 10.229.0.1, " + "10.27.129.0/24 - 10.27.129.1'"; + OptionBuffer buf = isc::util::str::quotedStringToBinary(config); + + // Create option instance. Check that constructor throws BadValue during Unpack. + OptionClasslessStaticRoutePtr option; + EXPECT_THROW(option.reset(new OptionClasslessStaticRoute(buf.begin(), buf.end())), + isc::BadValue); + ASSERT_FALSE(option); +} + +// This test verifies that constructor from config data throws an exception +// when data in the buffer has wrong format. +TEST(OptionClasslessStaticRouteTest, bufferFromStrCtorDestIpV6Given) { + // Prepare data to decode - second route has IPv6 prefix + const std::string config = "'0.0.0.0/0 - 10.17.0.1,3001::5/64 - 10.229.0.1, " + "10.27.129.0/24 - 10.27.129.1'"; + OptionBuffer buf = isc::util::str::quotedStringToBinary(config); + + // Create option instance. Check that constructor throws BadValue during Unpack. + OptionClasslessStaticRoutePtr option; + EXPECT_THROW(option.reset(new OptionClasslessStaticRoute(buf.begin(), buf.end())), + isc::BadValue); + ASSERT_FALSE(option); +} + +// This test verifies that constructor from config data throws an exception +// when data in the buffer has wrong format. +TEST(OptionClasslessStaticRouteTest, bufferFromStrCtorDestInvalidAddr) { + // Prepare data to decode - second route has invalid IP address + const std::string config = "'0.0.0.0/0 - 10.17.0.1,1.2.3.a/32 - 10.229.0.1, " + "10.27.129.0/24 - 10.27.129.1'"; + OptionBuffer buf = isc::util::str::quotedStringToBinary(config); + + // Create option instance. Check that constructor throws BadValue during Unpack. + OptionClasslessStaticRoutePtr option; + EXPECT_THROW(option.reset(new OptionClasslessStaticRoute(buf.begin(), buf.end())), + isc::BadValue); + ASSERT_FALSE(option); +} + +// This test verifies that constructor from config data throws an exception +// when data in the buffer has wrong format. +TEST(OptionClasslessStaticRouteTest, bufferFromStrCtorInvalidPrefixLen) { + // Prepare data to decode - second route has invalid prefix len + const std::string config = "'0.0.0.0/0 - 10.17.0.1,1.2.3.4/a - 10.229.0.1, " + "10.27.129.0/24 - 10.27.129.1'"; + OptionBuffer buf = isc::util::str::quotedStringToBinary(config); + + // Create option instance. Check that constructor throws BadValue during Unpack. + OptionClasslessStaticRoutePtr option; + EXPECT_THROW(option.reset(new OptionClasslessStaticRoute(buf.begin(), buf.end())), + isc::BadValue); + ASSERT_FALSE(option); +} + +// This test verifies that constructor from config data throws an exception +// when data in the buffer has wrong format. +TEST(OptionClasslessStaticRouteTest, bufferFromStrCtorPrefixLenTooBig) { + // Prepare data to decode - second route has prefix len too big for IPv4 + const std::string config = "'0.0.0.0/0 - 10.17.0.1,1.2.3.4/64 - 10.229.0.1, " + "10.27.129.0/24 - 10.27.129.1'"; + OptionBuffer buf = isc::util::str::quotedStringToBinary(config); + + // Create option instance. Check that constructor throws BadValue during Unpack. + OptionClasslessStaticRoutePtr option; + EXPECT_THROW(option.reset(new OptionClasslessStaticRoute(buf.begin(), buf.end())), + isc::BadValue); + ASSERT_FALSE(option); +} + +// This test verifies that constructor from config data throws an exception +// when data in the buffer has wrong format. +TEST(OptionClasslessStaticRouteTest, bufferFromStrCtorRouterInvalidAddr) { + // Prepare data to decode - second route has invalid router IP address + const std::string config = "'0.0.0.0/0 - 10.17.0.1,1.2.3.4/31 - 10.229.0.a, " + "10.27.129.0/24 - 10.27.129.1'"; + OptionBuffer buf = isc::util::str::quotedStringToBinary(config); + + // Create option instance. Check that constructor throws BadValue during Unpack. + OptionClasslessStaticRoutePtr option; + EXPECT_THROW(option.reset(new OptionClasslessStaticRoute(buf.begin(), buf.end())), + isc::BadValue); + ASSERT_FALSE(option); +} + +// This test verifies that constructor from config data throws an exception +// when data in the buffer has wrong format. +TEST(OptionClasslessStaticRouteTest, bufferFromStrCtorRouterIpV6Given) { + // Prepare data to decode - second route has IPv6 router address + const std::string config = "'0.0.0.0/0 - 10.17.0.1,1.2.3.4/31 - 3001::5, " + "10.27.129.0/24 - 10.27.129.1'"; + OptionBuffer buf = isc::util::str::quotedStringToBinary(config); + + // Create option instance. Check that constructor throws BadValue during Unpack. + OptionClasslessStaticRoutePtr option; + EXPECT_THROW(option.reset(new OptionClasslessStaticRoute(buf.begin(), buf.end())), + isc::BadValue); + ASSERT_FALSE(option); +} + +// This test verifies that constructor from config data throws an exception +// when data in the buffer has wrong format. +TEST(OptionClasslessStaticRouteTest, bufferFromStrCtorCommaMissing) { + // Prepare data to decode - comma separators are missing + const std::string config = "'0.0.0.0/0 - 10.17.0.1 1.2.3.4/31 - 1.2.3.4 " + "10.27.129.0/24 - 10.27.129.1'"; + OptionBuffer buf = isc::util::str::quotedStringToBinary(config); + + // Create option instance. Check that constructor throws BadValue during Unpack. + OptionClasslessStaticRoutePtr option; + EXPECT_THROW(option.reset(new OptionClasslessStaticRoute(buf.begin(), buf.end())), + isc::BadValue); + ASSERT_FALSE(option); +} + +// This test verifies that constructor from config data throws an exception +// when data in the buffer is truncated. +TEST(OptionClasslessStaticRouteTest, bufferFromStrCtorDataTruncated) { + // Prepare data to decode - truncated data + const std::string config = "'0.0.'"; + OptionBuffer buf = isc::util::str::quotedStringToBinary(config); + + // Create option instance. Check that constructor throws OutOfRange during Unpack. + OptionClasslessStaticRoutePtr option; + EXPECT_THROW(option.reset(new OptionClasslessStaticRoute(buf.begin(), buf.end())), + isc::OutOfRange); + ASSERT_FALSE(option); +} + +// This test verifies constructor of the OptionClasslessStaticRoute class from +// on wire binary hex data. +// Only one static route is defined. +TEST(OptionClasslessStaticRouteTest, wireDatabufferCtorWithOneRoute) { // Prepare data to decode - one route with mask width = 8. const uint8_t buf_data[] = { - 10, 0, 0, 0, // subnet nr - 255, 0, 0, 0, // mask - 10, 198, 122, 1 // router IP + 8, // mask width + 10, // significant subnet octet for 10.0.0.0/8 + 10, 198, 122, 1 // router IP address }; - OptionBuffer buf(buf_data, buf_data + sizeof(buf_data)); // Create option instance. Check that constructor doesn't throw. Unpack is also tested here. @@ -73,22 +296,21 @@ TEST(OptionClasslessStaticRouteTest, bufferCtorWithOneRoute) { option->toText()); } -// This test verifies constructor of the OptionClasslessStaticRoute class from config data. +// This test verifies constructor of the OptionClasslessStaticRoute class from +// on wire binary hex data. // 3 static routes are defined. -TEST(OptionClasslessStaticRouteTest, bufferCtorWithMoreRoutes) { +TEST(OptionClasslessStaticRouteTest, wireDatabufferCtorWithMoreRoutes) { // Prepare data to decode - 3 static routes const uint8_t buf_data[] = { - 0, 0, 0, 0, // subnet nr - 0, 0, 0, 0, // mask - 10, 17, 0, 1, // router IP - 10, 229, 0, 128, // subnet nr - 255, 255, 255, 128, // mask - 10, 229, 0, 1, // router IP - 10, 27, 129, 0, // subnet nr - 255, 255, 255, 0, // mask - 10, 27, 129, 1 // router IP + 0, // mask width + 10, 17, 0, 1, // router IP address + 25, // mask width + 10, 229, 0, 128, // significant subnet octets for 10.229.0.128/25 + 10, 229, 0, 1, // router IP address + 24, // mask width + 10, 27, 129, // significant subnet octets for 10.27.129.0/24 + 10, 27, 129, 1 // router IP address }; - OptionBuffer buf(buf_data, buf_data + sizeof(buf_data)); // Create option instance. Check that constructor doesn't throw. Unpack is also tested here. @@ -108,4 +330,154 @@ TEST(OptionClasslessStaticRouteTest, bufferCtorWithMoreRoutes) { option->toText()); } -} \ No newline at end of file +// This test verifies that constructor from on wire binary hex data throws an exception +// when data in the buffer is truncated. +TEST(OptionClasslessStaticRouteTest, wireDatabufferCtorDataTruncated) { + // Prepare data to decode - truncated data + const uint8_t buf_data[] = { + 8, // mask width + 10, // significant subnet octet for 10.0.0.0/8 + 10, // router IP address truncated + }; + OptionBuffer buf(buf_data, buf_data + sizeof(buf_data)); + + // Create option instance. Check that constructor throws OutOfRange during Unpack. + OptionClasslessStaticRoutePtr option; + EXPECT_THROW(option.reset(new OptionClasslessStaticRoute(buf.begin(), buf.end())), + isc::OutOfRange); + ASSERT_FALSE(option); +} + +// This test verifies that constructor from on wire binary hex data throws an exception +// when data of the second static route in the buffer is truncated. +TEST(OptionClasslessStaticRouteTest, wireDatabufferCtorSecondRouteDataTruncated) { + // Prepare data to decode - truncated data + const uint8_t buf_data[] = { + 0, // mask width + 10, 17, 0, 1, // router IP address + 25, // mask width + 10, 229 // significant subnet octets truncated + }; + OptionBuffer buf(buf_data, buf_data + sizeof(buf_data)); + + // Create option instance. Check that constructor throws OutOfRange during Unpack. + OptionClasslessStaticRoutePtr option; + EXPECT_THROW(option.reset(new OptionClasslessStaticRoute(buf.begin(), buf.end())), + isc::OutOfRange); + ASSERT_FALSE(option); +} + +// This test verifies that constructor from on wire binary hex data throws an exception +// when data of the second static route in the buffer contains bad subnet width. +TEST(OptionClasslessStaticRouteTest, wireDatabufferCtorSecondRouteBadSubnetWidth) { + // Prepare data to decode - truncated data + const uint8_t buf_data[] = { + 0, // mask width + 10, 17, 0, 1, // router IP address + 125, // bad mask width + 10, 229, 0, 128, // significant subnet octets for 10.229.0.128/25 + 10, 229, 0, 1 // router IP address + }; + OptionBuffer buf(buf_data, buf_data + sizeof(buf_data)); + + // Create option instance. Check that constructor throws BadValue during Unpack. + OptionClasslessStaticRoutePtr option; + EXPECT_THROW(option.reset(new OptionClasslessStaticRoute(buf.begin(), buf.end())), + isc::BadValue); + ASSERT_FALSE(option); +} + +// This test verifies toText() method +TEST(OptionClasslessStaticRouteTest, toText) { + // Prepare data to decode - 3 static routes + const uint8_t buf_data[] = { + 0, // mask width + 10, 17, 0, 1, // router IP address + 25, // mask width + 10, 229, 0, 128, // significant subnet octets for 10.229.0.128/25 + 10, 229, 0, 1, // router IP address + 24, // mask width + 10, 27, 129, // significant subnet octets for 10.27.129.0/24 + 10, 27, 129, 1 // router IP address + }; + OptionBuffer buf(buf_data, buf_data + sizeof(buf_data)); + + // Create option instance. Check that constructor doesn't throw. Unpack is also tested here. + OptionClasslessStaticRoutePtr option; + EXPECT_NO_THROW(option.reset(new OptionClasslessStaticRoute(buf.begin(), buf.end()))); + ASSERT_TRUE(option); + + const uint8_t indent = 4; + + // Verify toText() is working fine. + EXPECT_EQ(" type=121(CLASSLESS_STATIC_ROUTE), len=22, " // 4 spaces of indentation + "Route 1 (subnet 0.0.0.0/0, router IP 10.17.0.1), " + "Route 2 (subnet 10.229.0.128/25, router IP 10.229.0.1), " + "Route 3 (subnet 10.27.129.0/24, router IP 10.27.129.1)", + option->toText(indent)); +} + +// This test verifies pack() method +TEST(OptionClasslessStaticRouteTest, pack) { + // Prepare data to decode - 3 static routes + const std::string config = "'0.0.0.0/0 - 10.17.0.1,10.229.0.128/25-10.229.0.1, " + "10.27.129.0/24 - 10.27.129.1'"; + OptionBuffer buf = isc::util::str::quotedStringToBinary(config); + + // Prepare expected packed data + const uint8_t ref_data[] = { + DHO_CLASSLESS_STATIC_ROUTE, // option code + 22, // data len + 0, // mask width + 10, 17, 0, 1, // router IP address + 25, // mask width + 10, 229, 0, 128, // significant subnet octets for 10.229.0.128/25 + 10, 229, 0, 1, // router IP address + 24, // mask width + 10, 27, 129, // significant subnet octets for 10.27.129.0/24 + 10, 27, 129, 1 // router IP address + }; + + size_t ref_data_size = sizeof(ref_data) / sizeof(ref_data[0]); + + // Create option instance. Check that constructor doesn't throw. Unpack is also tested here. + OptionClasslessStaticRoutePtr option; + EXPECT_NO_THROW(option.reset(new OptionClasslessStaticRoute(buf.begin(), buf.end()))); + ASSERT_TRUE(option); + + // Prepare on-wire format of the option. + isc::util::OutputBuffer output_buf(10); + ASSERT_NO_THROW(option->pack(output_buf)); + + // Check if the buffer has the same length as the reference data, + // so as they can be compared directly. + ASSERT_EQ(ref_data_size, output_buf.getLength()); + EXPECT_EQ(0, memcmp(ref_data, output_buf.getData(), output_buf.getLength())); +} + +// This test verifies that pack() method throws an exception when option len to be packed is +// bigger than 255 octets. +TEST(OptionClasslessStaticRouteTest, packThrows) { + // Create option instance. Check that constructor doesn't throw. + OptionClasslessStaticRoutePtr option; + EXPECT_NO_THROW(option.reset(new OptionClasslessStaticRoute())); + ASSERT_TRUE(option); + + // Create 9 octets long static route. + StaticRouteTuple route = std::make_tuple(IOAddress("1.2.3.4"), 32, IOAddress("10.198.122.1")); + // Add 50 routes + uint8_t i = 0; + while (i < 50) { + option->addRoute(route); + ++i; + } + + // Expected len: 2 (headers) + 50x9 = 452 + EXPECT_EQ(452, option->len()); + + // Check that pack() method throws an exception for option len > 255 + isc::util::OutputBuffer output_buf(10); + ASSERT_THROW(option->pack(output_buf), isc::OutOfRange); +} + +} // namespace \ No newline at end of file