- Rename util/io_utilities.h to util/io.h to escape redundancy.
- Create readUint and writeUint templates.
- Use reverse_copy for potential performance boost.
- Add missing unit tests.
#include <hooks/hooks_manager.h>
#include <stats/stats_mgr.h>
#include <util/encode/encode.h>
-#include <util/io_utilities.h>
+#include <util/io.h>
#include <util/pointer_util.h>
#include <util/range_utilities.h>
#include <log/logger.h>
#include <dns/name.h>
#include <dns/rcode.h>
#include <util/buffer.h>
-#include <util/io_utilities.h>
+#include <util/io.h>
#include <gtest/gtest.h>
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <util/buffer.h>
-#include <util/io_utilities.h>
+#include <util/io.h>
#include <asiolink/io_asio_socket.h>
#include <asiolink/io_endpoint.h>
#include <asiolink/tcp_endpoint.h>
#include <asiolink/tcp_socket.h>
#include <util/buffer.h>
-#include <util/io_utilities.h>
+#include <util/io.h>
#include <boost/shared_ptr.hpp>
#include <gtest/gtest.h>
#include <asiolink/tls_socket.h>
#include <asiolink/testutils/test_tls.h>
#include <util/buffer.h>
-#include <util/io_utilities.h>
+#include <util/io.h>
#include <boost/shared_ptr.hpp>
#include <gtest/gtest.h>
#include <asiolink/udp_endpoint.h>
#include <asiolink/udp_socket.h>
#include <util/buffer.h>
-#include <util/io_utilities.h>
+#include <util/io.h>
#include <boost/shared_ptr.hpp>
#include <gtest/gtest.h>
#include <dhcp/duid.h>
#include <exceptions/exceptions.h>
-#include <util/io_utilities.h>
+#include <util/io.h>
#include <iomanip>
#include <cctype>
#include <sstream>
#include <dhcp/duid_factory.h>
#include <dhcp/iface_mgr.h>
#include <exceptions/exceptions.h>
-#include <util/io_utilities.h>
+#include <util/io.h>
#include <util/range_utilities.h>
#include <util/strutil.h>
#include <ctime>
#include <dhcp/option.h>
#include <util/buffer.h>
-#include <util/io_utilities.h>
+#include <util/io.h>
#include <iostream>
#include <iterator>
#include <dhcp/option_space.h>
#include <exceptions/exceptions.h>
#include <util/encode/encode.h>
-#include <util/io_utilities.h>
+#include <util/io.h>
#include <boost/make_shared.hpp>
#include <asiolink/io_address.h>
#include <dhcp/option4_addrlst.h>
#include <exceptions/exceptions.h>
-#include <util/io_utilities.h>
+#include <util/io.h>
#include <iomanip>
#include <sstream>
#include <dhcp/option4_client_fqdn.h>
#include <dns/labelsequence.h>
#include <util/buffer.h>
-#include <util/io_utilities.h>
+#include <util/io.h>
#include <util/strutil.h>
#include <sstream>
#include <dhcp/libdhcp++.h>
#include <dhcp/option6_addrlst.h>
#include <exceptions/exceptions.h>
-#include <util/io_utilities.h>
+#include <util/io.h>
#include <sstream>
#include <dhcp/option6_auth.h>
#include <dhcp/option_space.h>
#include <exceptions/exceptions.h>
-#include <util/io_utilities.h>
+#include <util/io.h>
#include <util/encode/encode.h>
#include <sstream>
#include <dhcp/option6_client_fqdn.h>
#include <dns/labelsequence.h>
#include <util/buffer.h>
-#include <util/io_utilities.h>
+#include <util/io.h>
#include <util/strutil.h>
#include <sstream>
#include <dhcp/option6_ia.h>
#include <dhcp/option_space.h>
#include <exceptions/exceptions.h>
-#include <util/io_utilities.h>
+#include <util/io.h>
#include <arpa/inet.h>
#include <sstream>
#include <dhcp/option6_iaaddr.h>
#include <dhcp/option_space.h>
#include <exceptions/exceptions.h>
-#include <util/io_utilities.h>
+#include <util/io.h>
#include <sstream>
#include <dhcp/option6_iaprefix.h>
#include <dhcp/option_space.h>
#include <exceptions/exceptions.h>
-#include <util/io_utilities.h>
+#include <util/io.h>
#include <sstream>
#include <dhcp/option6_pdexclude.h>
#include <exceptions/exceptions.h>
#include <util/encode/encode.h>
-#include <util/io_utilities.h>
+#include <util/io.h>
#include <boost/dynamic_bitset.hpp>
#include <iostream>
#include <dhcp/dhcp6.h>
#include <dhcp/option6_status_code.h>
#include <dhcp/option_data_types.h>
-#include <util/io_utilities.h>
+#include <util/io.h>
#include <iterator>
#include <sstream>
#include <dhcp/option.h>
#include <dhcp/option_definition.h>
#include <exceptions/isc_assert.h>
-#include <util/io_utilities.h>
+#include <util/io.h>
namespace isc {
namespace dhcp {
#include <dhcp/opaque_data_tuple.h>
#include <dhcp/option.h>
#include <exceptions/exceptions.h>
-#include <util/io_utilities.h>
+#include <util/io.h>
#include <stdint.h>
#include <utility>
#include <dhcp/option.h>
#include <dhcp/option_data_types.h>
#include <dhcp/option_space.h>
-#include <util/io_utilities.h>
+#include <util/io.h>
#include <stdint.h>
#include <sstream>
#include <dhcp/libdhcp++.h>
#include <dhcp/option.h>
#include <dhcp/option_data_types.h>
-#include <util/io_utilities.h>
+#include <util/io.h>
#include <boost/shared_ptr.hpp>
#include <sstream>
#include <stdint.h>
#include <dhcp/libdhcp++.h>
#include <dhcp/option.h>
#include <dhcp/option_data_types.h>
-#include <util/io_utilities.h>
+#include <util/io.h>
#include <stdint.h>
#include <dhcp/option_vendor.h>
#include <dhcp/pkt6.h>
#include <dhcp/docsis3_option_defs.h>
-#include <util/io_utilities.h>
+#include <util/io.h>
#include <exceptions/exceptions.h>
#include <dhcp/duid.h>
#include <dhcp/iface_mgr.h>
#include <eval/eval_log.h>
#include <eval/eval_context.h>
#include <util/encode/encode.h>
-#include <util/io_utilities.h>
+#include <util/io.h>
#include <asiolink/io_address.h>
#include <dhcp/pkt4.h>
#include <dhcp/pkt6.h>
libkea_util_la_SOURCES =
libkea_util_la_SOURCES += bigints.h
libkea_util_la_SOURCES += boost_time_utils.h boost_time_utils.cc
-libkea_util_la_SOURCES += buffer.h io_utilities.h
+libkea_util_la_SOURCES += buffer.h
libkea_util_la_SOURCES += chrono_time_utils.h chrono_time_utils.cc
libkea_util_la_SOURCES += csv_file.h csv_file.cc
libkea_util_la_SOURCES += dhcp_space.h dhcp_space.cc
libkea_util_la_SOURCES += doubles.h
libkea_util_la_SOURCES += filesystem.h filesystem.cc
libkea_util_la_SOURCES += hash.h
+libkea_util_la_SOURCES += io.h
libkea_util_la_SOURCES += labeled_value.h labeled_value.cc
libkea_util_la_SOURCES += memory_segment.h
libkea_util_la_SOURCES += memory_segment_local.h memory_segment_local.cc
doubles.h \
filesystem.h \
hash.h \
- io_utilities.h \
+ io.h \
labeled_value.h \
memory_segment.h \
memory_segment_local.h \
--- /dev/null
+// Copyright (C) 2011-2024 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
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef KEA_UTIL_IO_H
+#define KEA_UTIL_IO_H
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+
+namespace isc {
+namespace util {
+
+/// \brief Read an unsigned integer from given buffer.
+///
+/// \tparam uint_t Data type of the unsigned integer.
+/// \param buffer Data buffer at least two bytes long of which the first bytes are assumed to
+/// represent an unsigned integer in network-byte order.
+/// \param length Length of the data buffer.
+///
+/// \return Value of the integer.
+template <typename uint_t>
+uint_t
+readUint(void const* const buffer, size_t const length) {
+ constexpr size_t size(sizeof(uint_t));
+ if (length < size) {
+ isc_throw(OutOfRange, "Expected buffer to be long enough to read a "
+ << size << "-byte integer, but got " << length << " byte"
+ << (length == 1 ? "" : "s") << " instead");
+ }
+
+ uint8_t const* const byte_buffer(static_cast<uint8_t const* const>(buffer));
+ uint_t result;
+ uint8_t* pointer_to_result(static_cast<uint8_t*>(static_cast<void*>(&result)));
+
+ std::reverse_copy(byte_buffer, byte_buffer + size, pointer_to_result);
+
+ return (result);
+}
+
+/// \brief Write the given unsigned integer to the given buffer.
+///
+/// \tparam uint_t Data type of the unsigned integer.
+/// \param value Value to convert.
+/// \param buffer Data buffer at least two bytes long into which the unsigned integer value is
+/// written in network-byte order.
+/// \param length Length of the data buffer.
+///
+/// \return pointer to the next byte after stored value
+template <typename uint_t>
+uint8_t*
+writeUint(uint_t const value, void* const buffer, size_t const length) {
+ constexpr size_t size(sizeof(uint_t));
+ if (length < size) {
+ isc_throw(OutOfRange, "Expected buffer to be long enough to write a "
+ << size << "-byte integer, but got " << length << " byte"
+ << (length == 1 ? "" : "s") << " instead");
+ }
+
+ uint8_t const* const pointer_to_value(
+ static_cast<uint8_t const* const>(static_cast<void const* const>(&value)));
+ uint8_t* const byte_buffer(static_cast<uint8_t* const>(buffer));
+
+ std::reverse_copy(pointer_to_value, pointer_to_value + size, byte_buffer);
+
+ return (byte_buffer + size);
+}
+
+/// \brief uint16_t wrapper over readUint.
+inline uint16_t
+readUint16(void const* const buffer, size_t const length) {
+ return readUint<uint16_t>(buffer, length);
+}
+
+/// \brief uint32_t wrapper over readUint.
+inline uint32_t
+readUint32(void const* const buffer, size_t const length) {
+ return readUint<uint32_t>(buffer, length);
+}
+
+/// \brief uint16_t wrapper over readUint.
+inline uint64_t
+readUint64(void const* const buffer, size_t const length) {
+ return readUint<uint64_t>(buffer, length);
+}
+
+/// \brief uint16_t wrapper over writeUint.
+inline uint8_t*
+writeUint16(uint16_t const value, void* const buffer, size_t const length) {
+ return writeUint(value, buffer, length);
+}
+
+/// \brief uint32_t wrapper over writeUint.
+inline uint8_t*
+writeUint32(uint32_t const value, void* const buffer, size_t const length) {
+ return writeUint(value, buffer, length);
+}
+
+/// \brief uint64_t wrapper over writeUint.
+inline uint8_t*
+writeUint64(uint64_t const value, void* const buffer, size_t const length) {
+ return writeUint(value, buffer, length);
+}
+
+} // namespace util
+} // namespace isc
+
+#endif // KEA_UTIL_IO_H
+++ /dev/null
-// Copyright (C) 2011-2023 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
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef IO_UTILITIES_H
-#define IO_UTILITIES_H
-
-#include <exceptions/exceptions.h>
-#include <cstddef>
-
-namespace isc {
-namespace util {
-
-/// \brief Read Unsigned 16-Bit Integer from Buffer
-///
-/// This is essentially a copy of the isc::util::InputBuffer::readUint16. It
-/// should really be moved into a separate library.
-///
-/// \param buffer Data buffer at least two bytes long of which the first two
-/// bytes are assumed to represent a 16-bit integer in network-byte
-/// order.
-/// \param length Length of the data buffer.
-///
-/// \return Value of 16-bit integer
-inline uint16_t
-readUint16(const void* buffer, size_t length) {
- if (length < sizeof(uint16_t)) {
- isc_throw(isc::OutOfRange,
- "Length (" << length << ") of buffer is insufficient " <<
- "to read a uint16_t");
- }
-
- const uint8_t* byte_buffer = static_cast<const uint8_t*>(buffer);
-
- uint16_t result = (static_cast<uint16_t>(byte_buffer[0])) << 8;
- result |= static_cast<uint16_t>(byte_buffer[1]);
-
- return (result);
-}
-
-/// \brief Write Unsigned 16-Bit Integer to Buffer
-///
-/// This is essentially a copy of isc::util::OutputBuffer::writeUint16. It
-/// should really be moved into a separate library.
-///
-/// \param value 16-bit value to convert
-/// \param buffer Data buffer at least two bytes long into which the 16-bit
-/// value is written in network-byte order.
-/// \param length Length of the data buffer.
-///
-/// \return pointer to the next byte after stored value
-inline uint8_t*
-writeUint16(uint16_t value, void* buffer, size_t length) {
- if (length < sizeof(uint16_t)) {
- isc_throw(isc::OutOfRange,
- "Length (" << length << ") of buffer is insufficient " <<
- "to write a uint16_t");
- }
-
- uint8_t* byte_buffer = static_cast<uint8_t*>(buffer);
-
- byte_buffer[0] = static_cast<uint8_t>((value & 0xff00U) >> 8);
- byte_buffer[1] = static_cast<uint8_t>(value & 0x00ffU);
-
- return (byte_buffer + sizeof(uint16_t));
-}
-
-/// \brief Read Unsigned 32-Bit Integer from Buffer
-///
-/// \param buffer Data buffer at least four bytes long of which the first four
-/// bytes are assumed to represent a 32-bit integer in network-byte
-/// order.
-/// \param length Length of the data buffer.
-///
-/// \return Value of 32-bit unsigned integer
-inline uint32_t
-readUint32(const void* buffer, size_t length) {
- if (length < sizeof(uint32_t)) {
- isc_throw(isc::OutOfRange,
- "Length (" << length << ") of buffer is insufficient " <<
- "to read a uint32_t");
- }
-
- const uint8_t* byte_buffer = static_cast<const uint8_t*>(buffer);
-
- uint32_t result = (static_cast<uint32_t>(byte_buffer[0])) << 24;
- result |= (static_cast<uint32_t>(byte_buffer[1])) << 16;
- result |= (static_cast<uint32_t>(byte_buffer[2])) << 8;
- result |= (static_cast<uint32_t>(byte_buffer[3]));
-
- return (result);
-}
-
-/// \brief Write Unsigned 32-Bit Integer to Buffer
-///
-/// \param value 32-bit value to convert
-/// \param buffer Data buffer at least four bytes long into which the 32-bit
-/// value is written in network-byte order.
-/// \param length Length of the data buffer.
-///
-/// \return pointer to the next byte after stored value
-inline uint8_t*
-writeUint32(uint32_t value, void* buffer, size_t length) {
- if (length < sizeof(uint32_t)) {
- isc_throw(isc::OutOfRange,
- "Length (" << length << ") of buffer is insufficient " <<
- "to write a uint32_t");
- }
-
- uint8_t* byte_buffer = static_cast<uint8_t*>(buffer);
-
- byte_buffer[0] = static_cast<uint8_t>((value & 0xff000000U) >> 24);
- byte_buffer[1] = static_cast<uint8_t>((value & 0x00ff0000U) >> 16);
- byte_buffer[2] = static_cast<uint8_t>((value & 0x0000ff00U) >> 8);
- byte_buffer[3] = static_cast<uint8_t>((value & 0x000000ffU));
-
- return (byte_buffer + sizeof(uint32_t));
-}
-
-/// \brief Read Unsigned 64-Bit Integer from Buffer
-///
-/// \param buffer Data buffer at least four bytes long of which the first four
-/// bytes are assumed to represent a 64-bit integer in network-byte
-/// order.
-/// \param length Length of the data buffer.
-///
-/// \return Value of 64-bit unsigned integer
-inline uint64_t
-readUint64(const void* buffer, size_t length) {
- if (length < sizeof(uint64_t)) {
- isc_throw(isc::OutOfRange,
- "Length (" << length << ") of buffer is insufficient " <<
- "to read a uint64_t");
- }
-
- const uint8_t* byte_buffer = static_cast<const uint8_t*>(buffer);
-
- uint64_t result = (static_cast<uint64_t>(byte_buffer[0])) << 56;
- result |= (static_cast<uint64_t>(byte_buffer[1])) << 48;
- result |= (static_cast<uint64_t>(byte_buffer[2])) << 40;
- result |= (static_cast<uint64_t>(byte_buffer[3])) << 32;
- result |= (static_cast<uint64_t>(byte_buffer[4])) << 24;
- result |= (static_cast<uint64_t>(byte_buffer[5])) << 16;
- result |= (static_cast<uint64_t>(byte_buffer[6])) << 8;
- result |= (static_cast<uint64_t>(byte_buffer[7]));
-
- return (result);
-}
-
-/// \brief Write Unsigned 64-Bit Integer to Buffer
-///
-/// \param value 64-bit value to convert
-/// \param buffer Data buffer at least four bytes long into which the 64-bit
-/// value is written in network-byte order.
-/// \param length Length of the data buffer.
-///
-/// \return pointer to the next byte after stored value
-inline uint8_t*
-writeUint64(uint64_t value, void* buffer, size_t length) {
- if (length < sizeof(uint64_t)) {
- isc_throw(isc::OutOfRange,
- "Length (" << length << ") of buffer is insufficient " <<
- "to write a uint64_t");
- }
-
- uint8_t* byte_buffer = static_cast<uint8_t*>(buffer);
-
- byte_buffer[0] = static_cast<uint8_t>((value & 0xff00000000000000UL) >> 56);
- byte_buffer[1] = static_cast<uint8_t>((value & 0x00ff000000000000UL) >> 48);
- byte_buffer[2] = static_cast<uint8_t>((value & 0x0000ff0000000000UL) >> 40);
- byte_buffer[3] = static_cast<uint8_t>((value & 0x000000ff00000000UL) >> 32);
- byte_buffer[4] = static_cast<uint8_t>((value & 0x00000000ff000000UL) >> 24);
- byte_buffer[5] = static_cast<uint8_t>((value & 0x0000000000ff0000UL) >> 16);
- byte_buffer[6] = static_cast<uint8_t>((value & 0x000000000000ff00UL) >> 8);
- byte_buffer[7] = static_cast<uint8_t>((value & 0x00000000000000ffUL));
-
- return (byte_buffer + sizeof(uint64_t));
-}
-
-} // namespace util
-} // namespace isc
-
-#endif // IO_UTILITIES_H
--- /dev/null
+// Copyright (C) 2011-2024 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
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+/// \brief Test of asiolink utilities
+///
+/// Tests the functionality of the asiolink utilities code by comparing them
+/// with the equivalent methods in isc::dns::[Input/Output]Buffer.
+
+#include <config.h>
+
+#include <testutils/gtest_utils.h>
+#include <util/buffer.h>
+#include <util/io.h>
+
+#include <cstddef>
+#include <cstdint>
+
+#include <arpa/inet.h>
+#include <gtest/gtest.h>
+
+using namespace isc;
+using namespace isc::util;
+
+namespace {
+
+/// @brief Check whether uint16_t can be read from a buffer properly.
+TEST(asioutil, readUint16) {
+ // Reference buffer
+ uint8_t data[2] = {0, 0};
+ InputBuffer buffer(data, sizeof(data));
+
+ // Avoid possible compiler warnings by only setting uint8_t variables to
+ // uint8_t values.
+ uint8_t i8 = 0;
+ uint8_t j8 = 0;
+ for (int i = 0; i < (2 << 8); ++i, ++i8) {
+ for (int j = 0; j < (2 << 8); ++j, ++j8) {
+ data[0] = i8;
+ data[1] = j8;
+ buffer.setPosition(0);
+ EXPECT_EQ(buffer.readUint16(), readUint16(data, sizeof(data)));
+ }
+ }
+}
+
+/// @brief Check whether reading an uint16_t results in an exception.
+TEST(asioutil, readUint16OutOfRange) {
+ uint8_t data = 0;
+ EXPECT_THROW_MSG(readUint16(&data, sizeof(data)), OutOfRange,
+ "Expected buffer to be long enough to read a 2-byte integer, but got 1 byte "
+ "instead");
+}
+
+/// @brief Check whether uint16_t can be written to a buffer properly.
+TEST(asioutil, writeUint16) {
+ // Reference buffer
+ OutputBuffer buffer(2);
+ uint8_t test[2];
+
+ // Avoid possible compiler warnings by only setting uint16_t variables to
+ // uint16_t values.
+ uint16_t i16 = 0;
+ for (uint32_t i = 0; i < (2 << 16); ++i, ++i16) {
+ // Write the reference data
+ buffer.clear();
+ buffer.writeUint16(i16);
+
+ // ... and the test data
+ writeUint16(i16, test, sizeof(test));
+
+ // ... and compare
+ const uint8_t* ref = static_cast<const uint8_t*>(buffer.getData());
+ EXPECT_EQ(ref[0], test[0]);
+ EXPECT_EQ(ref[1], test[1]);
+ }
+}
+
+/// @brief Check whether writing an uint16_t results in an exception.
+TEST(asioutil, writeUint16OutOfRange) {
+ uint16_t i16 = 42;
+ uint8_t data;
+ EXPECT_THROW_MSG(writeUint16(i16, &data, sizeof(data)), OutOfRange,
+ "Expected buffer to be long enough to write a 2-byte integer, but got 1 byte "
+ "instead");
+}
+
+/// @brief Test data shared amount readUint32 and writeUint32 tests.
+const static uint32_t test32[] = {0, 1, 2000, 0x80000000, 0xffffffff};
+
+/// @brief Check whether uint32_t can be read from a buffer properly.
+TEST(asioutil, readUint32) {
+ uint8_t data[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+
+ // Make sure that we can read data, regardless of
+ // the memory alignment. That is why we need to repeat
+ // it 4 times.
+ for (int offset = 0; offset < 4; offset++) {
+ for (size_t i = 0; i < sizeof(test32) / sizeof(uint32_t); i++) {
+ uint32_t tmp = htonl(test32[i]);
+ memcpy(&data[offset], &tmp, sizeof(uint32_t));
+
+ EXPECT_EQ(test32[i], readUint32(&data[offset], sizeof(uint32_t)));
+ }
+ }
+}
+
+/// @brief Check whether reading an uint32_t results in an exception.
+TEST(asioutil, readUint32OutOfRange) {
+ uint8_t data[3] = {0, 0, 0};
+ EXPECT_THROW_MSG(readUint32(data, sizeof(data)), OutOfRange,
+ "Expected buffer to be long enough to read a 4-byte integer, but got 3 bytes "
+ "instead");
+}
+
+/// @brief Check whether uint32_t can be written to a buffer properly.
+TEST(asioutil, writeUint32) {
+ uint8_t data[8];
+
+ // make sure that we can write data, regardless of
+ // the memory alignment. That's why we need to repeat
+ // it 4 times.
+ for (int offset = 0; offset < 4; offset++) {
+ for (size_t i = 0; i < sizeof(test32) / sizeof(uint32_t); i++) {
+ uint8_t* ptr = writeUint32(test32[i], &data[offset], sizeof(uint32_t));
+
+ EXPECT_EQ(&data[offset] + sizeof(uint32_t), ptr);
+
+ uint32_t tmp = htonl(test32[i]);
+
+ EXPECT_EQ(0, memcmp(&tmp, &data[offset], sizeof(uint32_t)));
+ }
+ }
+}
+
+/// @brief Check whether writing an uint32_t results in an exception.
+TEST(asioutil, writeUint32OutOfRange) {
+ uint32_t i32 = 28;
+ uint8_t data[3];
+ EXPECT_THROW_MSG(writeUint32(i32, data, sizeof(data)), OutOfRange,
+ "Expected buffer to be long enough to write a 4-byte integer, but got 3 bytes "
+ "instead");
+}
+
+/// @brief Check whether uint64_t can be read from a buffer properly.
+TEST(asioutil, readUint64) {
+ uint8_t buf[8];
+ for (size_t offset = 0; offset < sizeof(buf); offset++) {
+ buf[offset] = offset + 1;
+ }
+
+ // Now check if a real value could be read.
+ const uint64_t exp_val = 0x0102030405060708ul;
+ uint64_t val;
+
+ EXPECT_NO_THROW_LOG(val = readUint64(buf, 8));
+ EXPECT_EQ(val, exp_val);
+
+ // Now check if there are no buffer overflows.
+ memset(buf, 0xff, 8);
+
+ EXPECT_NO_THROW_LOG(val = readUint64(buf, 8));
+ EXPECT_EQ(0xfffffffffffffffful, val);
+}
+
+/// @brief Check whether reading an uint64_t results in an exception.
+TEST(asioutil, readUint64OutOfRange) {
+ uint8_t buf[8];
+
+ // Let's do some simple sanity checks first.
+ EXPECT_THROW_MSG(readUint64(NULL, 0), OutOfRange,
+ "Expected buffer to be long enough to read a 8-byte integer, but got 0 bytes "
+ "instead");
+ EXPECT_THROW_MSG(readUint64(buf, 7), OutOfRange,
+ "Expected buffer to be long enough to read a 8-byte integer, but got 7 bytes "
+ "instead");
+}
+
+/// @brief Check whether uint64 can be written to a buffer properly.
+TEST(asioutil, writeUint64) {
+ uint8_t data[8];
+
+ // make sure that we can write data, regardless of
+ // the memory alignment. That's why we need to repeat
+ // it 4 times.
+ for (int offset = 0; offset < 4; offset++) {
+ for (size_t i = 0; i < sizeof(test32) / sizeof(uint32_t); i++) {
+ uint8_t* ptr = writeUint32(test32[i], &data[offset], sizeof(uint32_t));
+
+ EXPECT_EQ(&data[offset] + sizeof(uint32_t), ptr);
+
+ uint32_t tmp = htonl(test32[i]);
+
+ EXPECT_EQ(0, memcmp(&tmp, &data[offset], sizeof(uint32_t)));
+ }
+ }
+}
+
+/// @brief Check whether writing an uint64_t results in an exception.
+TEST(asioutil, writeUint64OutOfRange) {
+ uint32_t i32 = 28;
+ uint8_t data[3];
+ EXPECT_THROW_MSG(writeUint32(i32, data, sizeof(data)), OutOfRange,
+ "Expected buffer to be long enough to write a 4-byte integer, but got 3 bytes "
+ "instead");
+}
+
+} // namespace
+++ /dev/null
-// Copyright (C) 2011-2024 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
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-/// \brief Test of asiolink utilities
-///
-/// Tests the functionality of the asiolink utilities code by comparing them
-/// with the equivalent methods in isc::dns::[Input/Output]Buffer.
-
-#include <config.h>
-
-#include <cstddef>
-
-#include <arpa/inet.h>
-#include <gtest/gtest.h>
-
-#include <util/buffer.h>
-#include <util/io_utilities.h>
-
-using namespace isc::util;
-
-TEST(asioutil, readUint16) {
-
- // Reference buffer
- uint8_t data[2] = {0, 0};
- InputBuffer buffer(data, sizeof(data));
-
- // Avoid possible compiler warnings by only setting uint8_t variables to
- // uint8_t values.
- uint8_t i8 = 0;
- uint8_t j8 = 0;
- for (int i = 0; i < (2 << 8); ++i, ++i8) {
- for (int j = 0; j < (2 << 8); ++j, ++j8) {
- data[0] = i8;
- data[1] = j8;
- buffer.setPosition(0);
- EXPECT_EQ(buffer.readUint16(), readUint16(data, sizeof(data)));
- }
- }
-}
-
-TEST(asioutil, readUint16OutOfRange) {
- uint8_t data = 0;
- EXPECT_THROW(readUint16(&data, sizeof(data)), isc::OutOfRange);
-}
-
-TEST(asioutil, writeUint16) {
-
- // Reference buffer
- OutputBuffer buffer(2);
- uint8_t test[2];
-
- // Avoid possible compiler warnings by only setting uint16_t variables to
- // uint16_t values.
- uint16_t i16 = 0;
- for (uint32_t i = 0; i < (2 << 16); ++i, ++i16) {
-
- // Write the reference data
- buffer.clear();
- buffer.writeUint16(i16);
-
- // ... and the test data
- writeUint16(i16, test, sizeof(test));
-
- // ... and compare
- const uint8_t* ref = buffer.getData();
- EXPECT_EQ(ref[0], test[0]);
- EXPECT_EQ(ref[1], test[1]);
- }
-}
-
-TEST(asioutil, writeUint16OutOfRange) {
- uint16_t i16 = 42;
- uint8_t data;
- EXPECT_THROW(writeUint16(i16, &data, sizeof(data)), isc::OutOfRange);
-}
-
-// test data shared amount readUint32 and writeUint32 tests
-const static uint32_t test32[] = {
- 0,
- 1,
- 2000,
- 0x80000000,
- 0xffffffff
-};
-
-TEST(asioutil, readUint32) {
- uint8_t data[8] = {0, 0, 0, 0, 0, 0, 0, 0};
-
- // make sure that we can read data, regardless of
- // the memory alignment. That' why we need to repeat
- // it 4 times.
- for (int offset=0; offset < 4; offset++) {
- for (int i=0; i < sizeof(test32)/sizeof(uint32_t); i++) {
- uint32_t tmp = htonl(test32[i]);
- memcpy(&data[offset], &tmp, sizeof(uint32_t));
-
- EXPECT_EQ(test32[i], readUint32(&data[offset], sizeof(uint32_t)));
- }
- }
-}
-
-TEST(asioutil, readUint32OutOfRange) {
- uint8_t data[3] = {0, 0, 0};
- EXPECT_THROW(readUint32(data, sizeof(data)), isc::OutOfRange);
-}
-
-TEST(asioutil, writeUint32) {
- uint8_t data[8];
-
- // make sure that we can write data, regardless of
- // the memory alignment. That's why we need to repeat
- // it 4 times.
- for (int offset=0; offset < 4; offset++) {
- for (int i=0; i < sizeof(test32)/sizeof(uint32_t); i++) {
- uint8_t* ptr = writeUint32(test32[i], &data[offset],
- sizeof(uint32_t));
-
- EXPECT_EQ(&data[offset]+sizeof(uint32_t), ptr);
-
- uint32_t tmp = htonl(test32[i]);
-
- EXPECT_EQ(0, memcmp(&tmp, &data[offset], sizeof(uint32_t)));
- }
- }
-}
-
-TEST(asioutil, writeUint32OutOfRange) {
- uint32_t i32 = 28;
- uint8_t data[3];
- EXPECT_THROW(writeUint32(i32, data, sizeof(data)), isc::OutOfRange);
-}
-
-// Tests whether uint64 can be read from a buffer properly.
-TEST(asioutil, readUint64) {
-
- uint8_t buf[8];
- for (int offset = 0; offset < sizeof(buf); offset++) {
- buf[offset] = offset+1;
- }
-
- // Let's do some simple sanity checks first.
- EXPECT_THROW(readUint64(NULL, 0), isc::OutOfRange);
- EXPECT_THROW(readUint64(buf, 7), isc::OutOfRange);
-
- // Now check if a real value could be read.
- const uint64_t exp_val = 0x0102030405060708ul;
- uint64_t val;
-
- EXPECT_NO_THROW(val = readUint64(buf, 8));
- EXPECT_EQ(val, exp_val);
-
- // Now check if there are no buffer overflows.
- memset(buf, 0xff, 8);
-
- EXPECT_NO_THROW(val = readUint64(buf, 8));
- EXPECT_EQ(0xfffffffffffffffful, val);
-}