diff options
| -rw-r--r-- | libnvxx/const_nv_list.cc | 7 | ||||
| -rw-r--r-- | libnvxx/nvxx_base.h | 2 | ||||
| -rw-r--r-- | libnvxx/tests/nvxx_basic.cc | 85 |
3 files changed, 90 insertions, 4 deletions
diff --git a/libnvxx/const_nv_list.cc b/libnvxx/const_nv_list.cc index 22d3771..0098d60 100644 --- a/libnvxx/const_nv_list.cc +++ b/libnvxx/const_nv_list.cc @@ -116,10 +116,11 @@ __const_nv_list::send(int fd) const { __throw_if_error(); - if (::nvlist_send(fd, __m_nv) == 0) - return; + if (auto ret = ::nvlist_send(fd, __m_nv); ret != 0) + throw std::system_error( + std::make_error_code(static_cast<std::errc>(errno))); - throw std::system_error(error()); + return; } void diff --git a/libnvxx/nvxx_base.h b/libnvxx/nvxx_base.h index 9eebb4e..07cd9e7 100644 --- a/libnvxx/nvxx_base.h +++ b/libnvxx/nvxx_base.h @@ -432,7 +432,7 @@ struct nv_list final * Receive an nv_list from a file descriptor by calling nvlist_recv(), * to which flags is passed. On failure, throws std::system_error. */ - [[nodiscard]] static auto recv(int, int) -> nv_list; + [[nodiscard]] static auto recv(int __fd, int __flags = 0) -> nv_list; /* * Send an nv_list over a file descriptor and receive another nv_list diff --git a/libnvxx/tests/nvxx_basic.cc b/libnvxx/tests/nvxx_basic.cc index 09b8976..31d2b11 100644 --- a/libnvxx/tests/nvxx_basic.cc +++ b/libnvxx/tests/nvxx_basic.cc @@ -11,6 +11,8 @@ #include <string> #include <string_view> +#include <sys/types.h> +#include <sys/socket.h> #include <atf-c++.hpp> #include "nvxx.h" @@ -393,6 +395,84 @@ TEST_CASE(nvxx_unpack_range) ATF_REQUIRE_EQ(value, nvl.get_number(key)); } +TEST_CASE(nvxx_send_non_socket) +{ + using namespace std::literals; + auto constexpr key = "test"sv; + auto constexpr value = 42u; + + auto nvl = bsd::nv_list(); + nvl.add_number(key, value); + + auto fds = std::array<int, 2>{}; + auto ret = ::pipe(&fds[0]); + ATF_REQUIRE_EQ(0, ret); + + bsd::nv_fd fd0(fds[0]); + bsd::nv_fd fd1(fds[1]); + + ATF_REQUIRE_THROW(std::system_error, nvl.send(fd0.get())); + + try { + nvl.send(fd0.get()); + } catch (std::system_error const &exc) { + ATF_REQUIRE_EQ(true, exc.code().value() == ENOTSOCK); + } +} + +TEST_CASE(nvxx_send_recv) +{ + using namespace std::literals; + auto constexpr key = "test"sv; + auto constexpr value = 42u; + + auto nvl = bsd::nv_list(); + nvl.add_number(key, value); + + auto fds = std::array<int, 2>{}; + auto ret = ::socketpair(AF_UNIX, SOCK_STREAM, 0, &fds[0]); + ATF_REQUIRE_EQ(0, ret); + + bsd::nv_fd fd0(fds[0]); + bsd::nv_fd fd1(fds[1]); + + nvl.send(fd0.get()); + + auto nvl2 = bsd::nv_list::recv(fd1.get()); + ATF_REQUIRE_EQ(value, nvl2.get_number(key)); +} + +TEST_CASE(nvxx_send_error) +{ + using namespace std::literals; + + auto nvl = bsd::nv_list(); + nvl.set_error(std::errc::invalid_argument); + + auto fds = std::array<int, 2>{}; + auto ret = ::socketpair(AF_UNIX, SOCK_STREAM, 0, &fds[0]); + ATF_REQUIRE_EQ(0, ret); + + bsd::nv_fd fd0(fds[0]); + bsd::nv_fd fd1(fds[1]); + + ATF_REQUIRE_THROW(bsd::nv_error_state, nvl.send(fd0.get())); +} + +TEST_CASE(nvxx_send_empty) +{ + auto cnv = bsd::const_nv_list(); + + auto fds = std::array<int, 2>{}; + auto ret = ::socketpair(AF_UNIX, SOCK_STREAM, 0, &fds[0]); + ATF_REQUIRE_EQ(0, ret); + + bsd::nv_fd fd0(fds[0]); + bsd::nv_fd fd1(fds[1]); + + ATF_REQUIRE_THROW(std::logic_error, cnv.send(fd0.get())); +} + /* * exists(_type) */ @@ -1933,6 +2013,11 @@ ATF_INIT_TEST_CASES(tcs) ATF_ADD_TEST_CASE(tcs, nvxx_unpack); ATF_ADD_TEST_CASE(tcs, nvxx_unpack_range); + ATF_ADD_TEST_CASE(tcs, nvxx_send_non_socket); + ATF_ADD_TEST_CASE(tcs, nvxx_send_recv); + ATF_ADD_TEST_CASE(tcs, nvxx_send_empty); + ATF_ADD_TEST_CASE(tcs, nvxx_send_error); + ATF_ADD_TEST_CASE(tcs, nvxx_exists); ATF_ADD_TEST_CASE(tcs, nvxx_exists_nul_key); ATF_ADD_TEST_CASE(tcs, nvxx_exists_type); |
