diff --git a/CHANGELOG.md b/CHANGELOG.md index 0dc21c2..410d2d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,21 @@ # Change Log for _sockpp_ -## [Version 0.8.1](https://github.com/fpagliughi/sockpp/compare/v0.8.0..v0.8.1) +## [Version 1.0.0](https://github.com/fpagliughi/sockpp/compare/v0.8.3..v1.0.0) - (2023-12-17) -Released: 2023-01-30 +This is a release of the previous 0.8.x line as the initial, stable API. + +## [Version 0.8.3](https://github.com/fpagliughi/sockpp/compare/v0.8.2..v0.8.3) - (2023-12-11) + +- [#64](https://github.com/fpagliughi/sockpp/pull/84) Added support for Catch2 v3.x for unit tests. (v2.x still supported) + + +## [Version 0.8.2](https://github.com/fpagliughi/sockpp/compare/v0.8.1..v0.8.2) - (2023-12-05) + +- [#89](https://github.com/fpagliughi/sockpp/issue/89) Fixed generator expression for older CMake +- [#91](https://github.com/fpagliughi/sockpp/issue/91) Fixed uniform_int_distribution<> in UNIX socket example + + +## [Version 0.8.1](https://github.com/fpagliughi/sockpp/compare/v0.8.0..v0.8.1) - (2023-01-30) - Cherry picked most of the non-TLS commits in PR [#17](https://github.com/fpagliughi/sockpp/pull/17) - Connector timeouts @@ -15,9 +28,7 @@ Released: 2023-01-30 - [#56](https://github.com/fpagliughi/sockpp/issue/56) handling unix paths with maximum length (no NUL term) - Fixed outstanding build warnings on Windows when using MSVC -## [Version 0.8.0](https://github.com/fpagliughi/sockpp/compare/v0.7.1..v0.8.0) - -Released: 2023-01-17 +## [Version 0.8.0](https://github.com/fpagliughi/sockpp/compare/v0.7.1..v0.8.0) - (2023-01-17) - [Breaking] Library initializer now uses a static singleton created via `socket_initializer::initialize()` call, which can be called repeatedly with no ill effect. Also added global `socketpp::initialize()` function as shortcut. - Improvements to CMake to better follow modern standards. diff --git a/CMakeLists.txt b/CMakeLists.txt index 3250624..b6f828f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ # --------------------------------------------------------------------------- # This file is part of the "sockpp" C++ socket library. # -# Copyright (c) 2017-2018 Frank Pagliughi +# Copyright (c) 2017-2023 Frank Pagliughi # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -42,7 +42,7 @@ cmake_minimum_required(VERSION 3.12) # --- Project setup --- -project(sockpp VERSION "0.8.1") +project(sockpp VERSION "1.0.0") # --- Build Options --- diff --git a/README.md b/README.md index 3627440..5943a19 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,5 @@ # sockpp -[![Build Status](https://travis-ci.org/fpagliughi/sockpp.svg?branch=master)](https://travis-ci.org/fpagliughi/sockpp) - Simple, modern, C++ socket library. This is a fairly low-level C++ wrapper around the Berkeley sockets library using `socket`, `acceptor,` and `connector` classes that are familiar concepts from other languages. @@ -16,54 +14,21 @@ All code in the library lives within the `sockpp` C++ namespace. ## Latest News -The library is reaching a stable API, and is on track for a 1.0 release in the near future. Until then, there may be a few more breaking changes, but hopefully those will be fewer than we have seen so far. - -On that note, despite being recently refactored and re-versioned at 0.x, earlier implementations of this library have been in use on production systems since ~2003, particularly with remote embedded Linux data loggers. Things that we now call IoT gateways and edge devices. It can be counted on to be reliable, and if not, please report an issue! - To keep up with the latest announcements for this project, follow me at: -**Twitter:** [@fmpagliughi](https://twitter.com/fmpagliughi) - -If you're using this library, tweet at me or send me a message, and let me know how you're using it. I'm always curious to see where it winds up! - -## New in v0.8.1 +**Mastodon/Fosstodon:** [@fpagliughi@fosstodon.org](https://fosstodon.org/@fpagliughi) -This release attempts to fix some of the outstanding build issues on Windows with MSVC and resolve some old issues and PR commits. - -- Cherry picked most of the non-TLS commits in PR [#17](https://github.com/fpagliughi/sockpp/pull/17) - - Connector timeouts - - Stateless reads & writes for streaming sockets w/ functions returning `ioresult` - - Some small bug fixes - - No shutdown on invalid sockets -- [#38](https://github.com/fpagliughi/sockpp/issues/38) Made system libs public for static builds to fix Windows -- [#73](https://github.com/fpagliughi/sockpp/issue/73) Clone a datagram (UDP) socket -- [#74](https://github.com/fpagliughi/sockpp/issue/74) Added `` to properly get `timeval` in *nix builds. -- [#56](https://github.com/fpagliughi/sockpp/issue/56) handling unix paths with maximum length (no NUL term) -- Fixed outstanding build warnings on Windows when using MSVC - - -## New in v0.8.0 - -This was primarily a release of code that had been sitting in the develop branch for nearly a year. That code mostly improved CMake functionality for downstream projects. +**Twitter:** [@fmpagliughi](https://twitter.com/fmpagliughi) -- [Breaking] Library initializer now uses a static singleton created via `socket_initializer::initialize()` call, which can be called repeatedly with no ill effect. Also added global `socketpp::initialize()` function as shortcut. -- Improvements to CMake to better follow modern standards. - - CMake required version bumped up to 3.12 - - Generating CMake files for downstream projects (config, target, version) - - Windows builds default to shared DLL, not static library - - Lots of cleanup +If you're using this library, send me a message, and let me know how you're using it. I'm always curious to see where it winds up! ## Contributing -Contributions are accepted and appreciated. New and unstable work is done in the `develop` branch Please submit all pull requests against that branch, not _master_. +Contributions are accepted and appreciated. New and unstable work is done in the `develop` branch. Please submit all pull requests against that branch, not _master_. For more information, refer to: [CONTRIBUTING.md](https://github.com/fpagliughi/sockpp/blob/master/CONTRIBUTING.md) -## TODO - -- **Secure Sockets** - It would be extremely handy to have support for SSL/TLS built right into the library as an optional feature. -- **SCTP** - The _SCTP_ protocol never caught on, but it seems intriguing, and might be nice to have in the library for experimentation, if not for some internal applications. ## Building the Library @@ -76,7 +41,7 @@ CMake is the supported build system. - _Visual Studio 2015_, or later on WIndows. - _CMake_ v3.12 or newer. - _Doxygen_ (optional) to generate API docs. -- _Catch2_ (optional) to build and run unit tests. +- _Catch2_ (optional) v2.x or v3.x to build and run unit tests. To build with default options: @@ -102,7 +67,7 @@ SOCKPP_BUILD_SHARED | ON | Whether to build the shared library SOCKPP_BUILD_STATIC | OFF | Whether to build the static library SOCKPP_BUILD_DOCUMENTATION | OFF | Create and install the HTML based API documentation (requires _Doxygen)_ SOCKPP_BUILD_EXAMPLES | OFF | Build example programs -SOCKPP_BUILD_TESTS | OFF | Build the unit tests (requires _Catch2_) +SOCKPP_BUILD_TESTS | OFF | Build the unit tests (requires _Catch2_, v2.x or 3.x) SOCKPP_BUILD_CAN | OFF | Build SocketCAN support. (Linux only) Set these using the '-D' switch in the CMake configuration command. For example, to build documentation and example apps: diff --git a/examples/tcp/tcpechotest.cpp b/examples/tcp/tcpechotest.cpp index b73df37..fe70bf1 100644 --- a/examples/tcp/tcpechotest.cpp +++ b/examples/tcp/tcpechotest.cpp @@ -88,7 +88,7 @@ int main(int argc, char* argv[]) random_device rd; mt19937 reng(rd()); - uniform_int_distribution dist(0, 25); + uniform_int_distribution<> dist(0, 25); for (size_t i=0; i(dist(reng))); diff --git a/examples/unix/unechotest.cpp b/examples/unix/unechotest.cpp index 141059d..5b6405d 100644 --- a/examples/unix/unechotest.cpp +++ b/examples/unix/unechotest.cpp @@ -80,10 +80,10 @@ int main(int argc, char* argv[]) random_device rd; mt19937 reng(rd()); - uniform_int_distribution dist(0, 25); + uniform_int_distribution<> dist(0, 25); for (size_t i=0; i(dist(reng))); auto t_start_tx = high_resolution_clock::now(); diff --git a/include/sockpp/socket.h b/include/sockpp/socket.h index 944cd97..ada7849 100644 --- a/include/sockpp/socket.h +++ b/include/sockpp/socket.h @@ -517,7 +517,7 @@ class socket */ template bool set_option(int level, int optname, const T& val) { - return set_option(level, optname, (void*) &val, sizeof(T)); + return set_option(level, optname, static_cast(&val), sizeof(T)); } /** * Places the socket into or out of non-blocking mode. diff --git a/include/sockpp/tcp_acceptor.h b/include/sockpp/tcp_acceptor.h index cfd78e4..e1115fc 100644 --- a/include/sockpp/tcp_acceptor.h +++ b/include/sockpp/tcp_acceptor.h @@ -63,7 +63,7 @@ using tcp_acceptor = acceptor_tmpl; ///////////////////////////////////////////////////////////////////////////// // end namespace sockpp -}; +} #endif // __sockpp_tcp_acceptor_h diff --git a/include/sockpp/tcp_connector.h b/include/sockpp/tcp_connector.h index c5088b0..09e3802 100644 --- a/include/sockpp/tcp_connector.h +++ b/include/sockpp/tcp_connector.h @@ -60,6 +60,6 @@ using tcp_connector = connector_tmpl; ///////////////////////////////////////////////////////////////////////////// // end namespace sockpp -}; +} #endif // __sockpp_tcp_connector_h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 36e64f6..2b56aa2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -80,10 +80,9 @@ target_include_directories(sockpp-objs # --- Warnings --- -# Maybe set '-Werror' for Release builds? target_compile_options(sockpp-objs PRIVATE $<$:/W3> $<$:-Wall -Wextra -Wpedantic -Wdocumentation> - $<$>:-Wall -Wextra -Wpedantic> + $<$,$>>:-Wall -Wextra -Wpedantic> ) diff --git a/src/exception.cpp b/src/exception.cpp index 7cb010d..72aae7e 100644 --- a/src/exception.cpp +++ b/src/exception.cpp @@ -55,7 +55,7 @@ sys_error::sys_error(int err) : runtime_error(error_str(err)), errno_(err) // -------------------------------------------------------------------------- // Get a string description of the specified system error. -std::string sys_error::error_str(int err) +string sys_error::error_str(int err) { char buf[1024]; buf[0] = '\x0'; @@ -90,7 +90,6 @@ getaddrinfo_error::getaddrinfo_error(int err, const string& hostname) { } - ///////////////////////////////////////////////////////////////////////////// // end namespace 'sockpp' } diff --git a/src/inet6_address.cpp b/src/inet6_address.cpp index be9ed52..4ae90b7 100644 --- a/src/inet6_address.cpp +++ b/src/inet6_address.cpp @@ -114,7 +114,7 @@ void inet6_address::create(const string& saddr, in_port_t port) string inet6_address::to_string() const { char buf[INET6_ADDRSTRLEN]; - auto str = inet_ntop(AF_INET6, (void*) &(addr_.sin6_addr), + auto str = inet_ntop(AF_INET6, static_cast(&addr_.sin6_addr), buf, INET6_ADDRSTRLEN); return std::string("[") + std::string(str ? str : "") + "]:" + std::to_string(unsigned(port())); @@ -125,7 +125,7 @@ string inet6_address::to_string() const ostream& operator<<(ostream& os, const inet6_address& addr) { char buf[INET6_ADDRSTRLEN]; - auto str = inet_ntop(AF_INET6, (void*) &(addr.sockaddr_in6_ptr()->sin6_addr), + auto str = inet_ntop(AF_INET6, static_cast(&addr.sockaddr_in6_ptr()->sin6_addr), buf, INET6_ADDRSTRLEN); os << "[" << (str ? str : "") << "]:" << unsigned(addr.port()); return os; diff --git a/src/inet_address.cpp b/src/inet_address.cpp index 6e04103..1286126 100644 --- a/src/inet_address.cpp +++ b/src/inet_address.cpp @@ -110,7 +110,7 @@ void inet_address::create(const std::string& saddr, in_port_t port) string inet_address::to_string() const { char buf[INET_ADDRSTRLEN]; - auto str = inet_ntop(AF_INET, (void*) &(addr_.sin_addr), buf, INET_ADDRSTRLEN); + auto str = inet_ntop(AF_INET, static_cast(&addr_.sin_addr), buf, INET_ADDRSTRLEN); return std::string(str ? str : "") + ":" + std::to_string(unsigned(port())); } @@ -120,7 +120,7 @@ string inet_address::to_string() const ostream& operator<<(ostream& os, const inet_address& addr) { char buf[INET_ADDRSTRLEN]; - auto str = inet_ntop(AF_INET, (void*) &(addr.sockaddr_in_ptr()->sin_addr), + auto str = inet_ntop(AF_INET, static_cast(&addr.sockaddr_in_ptr()->sin_addr), buf, INET_ADDRSTRLEN); os << (str ? str : "") << ":" << unsigned(addr.port()); return os; diff --git a/src/unix/unix_address.cpp b/src/unix/unix_address.cpp index d0423ac..5cfd433 100644 --- a/src/unix/unix_address.cpp +++ b/src/unix/unix_address.cpp @@ -52,7 +52,8 @@ constexpr size_t unix_address::MAX_PATH_NAME; unix_address::unix_address(const string& path) { addr_.sun_family = ADDRESS_FAMILY; - ::strncpy(addr_.sun_path, path.c_str(), MAX_PATH_NAME); + ::strncpy(addr_.sun_path, path.c_str(), MAX_PATH_NAME - 1); + addr_.sun_path[MAX_PATH_NAME - 1] = '\0'; // Always ensure null-termination } unix_address::unix_address(const sockaddr& addr) : addr_{} diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index d525f08..2f25fb6 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -39,6 +39,13 @@ set(UNIT_TEST_DIR ${PROJECT_SOURCE_DIR}) find_package(Catch2 REQUIRED) +message(STATUS "Catch2 v${Catch2_VERSION}") +if (Catch2_VERSION VERSION_LESS "3.0") + add_definitions(-DCATCH2_V2) + # Put this in if/when deprecating v2. + #message(DEPRECATION "Catch2 version 2.x is deprecated") +endif() + # --- For apps that use threads --- set(THREADS_PREFER_PTHREAD_FLAG ON) @@ -71,6 +78,7 @@ target_include_directories(unit_tests ${SOCKPP_INCLUDE_DIR} PRIVATE ${SOCKPP_GENERATED_DIR}/include + ${CMAKE_CURRENT_SOURCE_DIR} ) set_target_properties(unit_tests PROPERTIES diff --git a/tests/unit/catch2_version.h b/tests/unit/catch2_version.h new file mode 100644 index 0000000..b0c115b --- /dev/null +++ b/tests/unit/catch2_version.h @@ -0,0 +1,48 @@ +// catch2_version.cpp +// +// Unit tests for the `acceptor` class(es). +// +// -------------------------------------------------------------------------- +// This file is part of the "sockpp" C++ socket library. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// -------------------------------------------------------------------------- +// + +#ifndef __catch2_version_h +#define __catch2_version_h + +#ifdef CATCH2_V2 + // For Catch2 v2.x + #include "catch2/catch.hpp" +#else + // For Catch2 v3.x + #include "catch2/catch_all.hpp" +#endif + +#endif // __catch2_version_h diff --git a/tests/unit/test_acceptor.cpp b/tests/unit/test_acceptor.cpp index 2ff5f38..c03096d 100644 --- a/tests/unit/test_acceptor.cpp +++ b/tests/unit/test_acceptor.cpp @@ -40,7 +40,7 @@ #include "sockpp/acceptor.h" #include "sockpp/inet_address.h" -#include "catch2/catch.hpp" +#include "catch2_version.h" #include using namespace sockpp; diff --git a/tests/unit/test_connector.cpp b/tests/unit/test_connector.cpp index 0ea0faa..1905389 100644 --- a/tests/unit/test_connector.cpp +++ b/tests/unit/test_connector.cpp @@ -40,7 +40,7 @@ #include "sockpp/connector.h" #include "sockpp/sock_address.h" -#include "catch2/catch.hpp" +#include "catch2_version.h" #include using namespace sockpp; @@ -57,7 +57,7 @@ TEST_CASE("connector unspecified address", "[connector]") { // Windows returns a different error code than *nix #if defined(_WIN32) - REQUIRE(conn.last_error() == WSAENOTSOCK); + REQUIRE(conn.last_error() == WSAEINVAL); #else REQUIRE(conn.last_error() == EAFNOSUPPORT); #endif diff --git a/tests/unit/test_datagram_socket.cpp b/tests/unit/test_datagram_socket.cpp index 925872a..70f44cc 100644 --- a/tests/unit/test_datagram_socket.cpp +++ b/tests/unit/test_datagram_socket.cpp @@ -40,7 +40,7 @@ #include "sockpp/datagram_socket.h" #include "sockpp/inet_address.h" -#include "catch2/catch.hpp" +#include "catch2_version.h" #include using namespace sockpp; diff --git a/tests/unit/test_inet6_address.cpp b/tests/unit/test_inet6_address.cpp new file mode 100644 index 0000000..1e8a955 --- /dev/null +++ b/tests/unit/test_inet6_address.cpp @@ -0,0 +1,173 @@ +// test_inet6_address.cpp +// +// Unit tests for the `inet6_address` class. +// + +// -------------------------------------------------------------------------- +// This file is part of the "sockpp" C++ socket library. +// +// Copyright (c) 2018-2023 Frank Pagliughi +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// -------------------------------------------------------------------------- +// + +#include "sockpp/inet6_address.h" +#include "catch2_version.h" +#include + +using namespace sockpp; + +const in6_addr ANY_ADDR IN6ADDR_ANY_INIT; // Any iface +const in6_addr LOCALHOST_ADDR IN6ADDR_LOOPBACK_INIT; // Localhost 0x7F000001 +const in_port_t PORT { 12345 }; + +TEST_CASE("inet6_address default constructor", "[address]") { + inet6_address addr; + in6_addr iaddr{}; + + REQUIRE(!addr); + REQUIRE(!addr.is_set()); + REQUIRE(memcmp(iaddr.s6_addr, addr.address().s6_addr, 16) == 0); + REQUIRE(0 == addr.port()); + REQUIRE(sizeof(sockaddr_in6) == addr.size()); +} + +// When created using only a port number this should use the +// "any" address to bind to all interfaces (typ for server) +TEST_CASE("inet6_address port-only constructor", "[address]") { + inet6_address addr(PORT); + + REQUIRE(addr); + REQUIRE(addr.is_set()); + REQUIRE(memcmp(ANY_ADDR.s6_addr, addr.address().s6_addr, 16) == 0); + REQUIRE(PORT == addr.port()); + + // Check the low-level struct + REQUIRE(AF_INET6 == addr.sockaddr_in6_ptr()->sin6_family); +} + +/* +TEST_CASE("inet_address int32_t constructor", "[address]") { + inet_address addr(LOCALHOST_ADDR, PORT); + + REQUIRE(addr); + REQUIRE(addr.is_set()); + REQUIRE(LOCALHOST_ADDR == addr.address()); + REQUIRE(PORT == addr.port()); + + REQUIRE(uint8_t((LOCALHOST_ADDR >> 0) &0xFF) == addr[0]); + REQUIRE(uint8_t((LOCALHOST_ADDR >> 8) &0xFF) == addr[1]); + REQUIRE(uint8_t((LOCALHOST_ADDR >> 16) &0xFF) == addr[2]); + REQUIRE(uint8_t((LOCALHOST_ADDR >> 24) &0xFF) == addr[3]); + + // Check the low-level struct + REQUIRE(AF_INET == addr.sockaddr_in_ptr()->sin_family); + REQUIRE(LOCALHOST_ADDR == ntohl(addr.sockaddr_in_ptr()->sin_addr.s_addr)); + REQUIRE(PORT == ntohs(addr.sockaddr_in_ptr()->sin_port)); +} +*/ + +TEST_CASE("inet6_address name constructor", "[address]") { + inet6_address addr{"FD80:CD00:0000:0CDE:1257:0000:211E:729C", PORT}; + + REQUIRE(addr); + REQUIRE(addr.is_set()); + REQUIRE(0xFD == addr[0]); + REQUIRE(0x9C == addr[15]); + REQUIRE(PORT == addr.port()); + + // Check the low-level struct + REQUIRE(AF_INET6 == addr.sockaddr_in6_ptr()->sin6_family); + REQUIRE(PORT == ntohs(addr.sockaddr_in6_ptr()->sin6_port)); +} + +TEST_CASE("IPv6 resolve address", "[address]") { + SECTION("local address") { + auto addr_res = inet6_address::resolve_name("::1"); + REQUIRE(addr_res.is_ok()); + auto addr = addr_res.value(); + + REQUIRE(memcmp(LOCALHOST_ADDR.s6_addr, addr.s6_addr, 16) == 0); + } + + SECTION("any address") { + auto addr_res = inet6_address::resolve_name("::"); + REQUIRE(addr_res.is_ok()); + auto addr = addr_res.value(); + REQUIRE(memcmp(ANY_ADDR.s6_addr, addr.s6_addr, 16) == 0); + } + + // According to RFC6761, "invalid." domain should not resolve + SECTION("resolve failure", "[address]") { + #if defined(SOCKPP_WITH_EXCEPTIONS) + REQUIRE_THROWS(inet6_address::resolve_name("invalid")); + #else + auto res = inet6_address::resolve_name("invalid"); + REQUIRE(!res); + REQUIRE(res.is_error()); + #endif + } +} + +TEST_CASE("IPv6 create address", "[address]") { + SECTION("local address") { + auto res = inet6_address::create("::1", PORT); + REQUIRE(res.is_ok()); + + auto addr = res.value(); + + REQUIRE(LOCALHOST_ADDR == addr.address()); + REQUIRE(PORT == addr.port()); + REQUIRE(inet6_address{LOCALHOST_ADDR, PORT} == addr); + } + + SECTION("any address") { + auto res = inet6_address::create("::", PORT); + REQUIRE(res.is_ok()); + + auto addr = res.value(); + + REQUIRE(ANY_ADDR == addr.address()); + REQUIRE(PORT == addr.port()); + REQUIRE(inet6_address{ANY_ADDR, PORT} == addr); + } + + // According to RFC6761, "invalid." domain should not resolve + SECTION("create failure", "[address]") { + #if defined(SOCKPP_WITH_EXCEPTIONS) + REQUIRE_THROWS(inet6_address::create("invalid", PORT)); + #else + auto res = inet6_address::create("invalid", PORT); + REQUIRE(!res); + REQUIRE(res.is_error()); + #endif + } +} + diff --git a/tests/unit/test_inet_address.cpp b/tests/unit/test_inet_address.cpp index e56835d..54b4410 100644 --- a/tests/unit/test_inet_address.cpp +++ b/tests/unit/test_inet_address.cpp @@ -39,7 +39,7 @@ // #include "sockpp/inet_address.h" -#include "catch2/catch.hpp" +#include "catch2_version.h" #include using namespace sockpp; diff --git a/tests/unit/test_result.cpp b/tests/unit/test_result.cpp new file mode 100644 index 0000000..b57dc57 --- /dev/null +++ b/tests/unit/test_result.cpp @@ -0,0 +1,71 @@ +// test_result.cpp +// +// Unit tests for the result class. +// + +// -------------------------------------------------------------------------- +// This file is part of the "sockpp" C++ socket library. +// +// Copyright (c) 2023 Frank Pagliughi All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// -------------------------------------------------------------------------- +// + +#include "sockpp/result.h" +#include "catch2_version.h" + +using namespace sockpp; + +TEST_CASE("test result success", "[result]") { + const int VAL = 42; + auto res = result(VAL); + + REQUIRE(res); + REQUIRE(res.is_ok()); + REQUIRE(!res.is_error()); + REQUIRE(res.value() == VAL); + REQUIRE(res.error() == error_code{}); + REQUIRE(res.error().value() == 0); + REQUIRE(res == success(VAL)); + REQUIRE(res == error_code{}); +} + +TEST_CASE("test result error", "[result]") { + const auto ERR = errc::interrupted; + auto res = result::from_error(ERR); + + REQUIRE(!res); + REQUIRE(!res.is_ok()); + REQUIRE(res.is_error()); + REQUIRE(res.error() == ERR); + REQUIRE(res == ERR); + REQUIRE(res == std::make_error_code(ERR)); + REQUIRE(res == error(ERR)); +} + diff --git a/tests/unit/test_socket.cpp b/tests/unit/test_socket.cpp index 22c58ae..6f5b124 100644 --- a/tests/unit/test_socket.cpp +++ b/tests/unit/test_socket.cpp @@ -40,7 +40,7 @@ #include "sockpp/socket.h" #include "sockpp/inet_address.h" -#include "catch2/catch.hpp" +#include "catch2_version.h" #include using namespace sockpp; diff --git a/tests/unit/test_stream_socket.cpp b/tests/unit/test_stream_socket.cpp index 6c59e12..f19cdcc 100644 --- a/tests/unit/test_stream_socket.cpp +++ b/tests/unit/test_stream_socket.cpp @@ -40,7 +40,7 @@ #include "sockpp/stream_socket.h" #include "sockpp/inet_address.h" -#include "catch2/catch.hpp" +#include "catch2_version.h" #include using namespace sockpp; diff --git a/tests/unit/test_tcp_socket.cpp b/tests/unit/test_tcp_socket.cpp index 8aa26d4..7745c2b 100644 --- a/tests/unit/test_tcp_socket.cpp +++ b/tests/unit/test_tcp_socket.cpp @@ -41,7 +41,7 @@ #include "sockpp/tcp_socket.h" #include "sockpp/tcp_connector.h" #include "sockpp/tcp_acceptor.h" -#include "catch2/catch.hpp" +#include "catch2_version.h" #include using namespace sockpp; @@ -124,9 +124,9 @@ TEST_CASE("tcp_socket read/write", "[stream_socket]") { N_TOT = N_HEADER + N + N_FOOTER; std::vector outv { - iovec { (void*) HEADER.data(), N_HEADER }, - iovec { (void*) STR.data(), N }, - iovec { (void*) FOOTER.data(), N_FOOTER } + iovec { const_cast(static_cast(HEADER.data())), N_HEADER }, + iovec { const_cast(static_cast(STR.data())), N }, + iovec { const_cast(static_cast(FOOTER.data())), N_FOOTER } }; char hbuf[512], // N_HEADER diff --git a/tests/unit/test_unix_address.cpp b/tests/unit/test_unix_address.cpp index 36d85ac..1009ab6 100644 --- a/tests/unit/test_unix_address.cpp +++ b/tests/unit/test_unix_address.cpp @@ -39,7 +39,7 @@ // #include "sockpp/unix_address.h" -#include "catch2/catch.hpp" +#include "catch2_version.h" #include using namespace sockpp; diff --git a/tests/unit/test_unix_dgram_socket.cpp b/tests/unit/test_unix_dgram_socket.cpp index 95e97d0..924edd3 100644 --- a/tests/unit/test_unix_dgram_socket.cpp +++ b/tests/unit/test_unix_dgram_socket.cpp @@ -39,7 +39,7 @@ // #include "sockpp/unix_dgram_socket.h" -#include "catch2/catch.hpp" +#include "catch2_version.h" #include using namespace sockpp; diff --git a/tests/unit/test_unix_stream_socket.cpp b/tests/unit/test_unix_stream_socket.cpp index 77b5960..e7ca1df 100644 --- a/tests/unit/test_unix_stream_socket.cpp +++ b/tests/unit/test_unix_stream_socket.cpp @@ -39,7 +39,7 @@ // #include "sockpp/unix_stream_socket.h" -#include "catch2/catch.hpp" +#include "catch2_version.h" #include using namespace sockpp; diff --git a/tests/unit/unit_tests.cpp b/tests/unit/unit_tests.cpp index e4c8c10..57ed719 100644 --- a/tests/unit/unit_tests.cpp +++ b/tests/unit/unit_tests.cpp @@ -56,7 +56,7 @@ #endif #define CATCH_CONFIG_RUNNER -#include "catch2/catch.hpp" +#include "catch2_version.h" int main(int argc, char* argv[]) {