From c68312987dc16f7f952e4ed7d56f550a85b9b45c Mon Sep 17 00:00:00 2001 From: Razvan Becheriu Date: Tue, 28 Oct 2025 21:49:42 +0200 Subject: [PATCH] [#4141] unify selectCheck --- .../libloadtests/close_unittests.cc | 1 + src/lib/dhcp/iface_mgr.cc | 30 +++++----- src/lib/dhcp/tests/pkt_filter_bpf_unittest.cc | 19 +----- .../dhcp/tests/pkt_filter_inet6_unittest.cc | 11 +--- .../dhcp/tests/pkt_filter_inet_unittest.cc | 11 +--- src/lib/dhcp/tests/pkt_filter_lpf_unittest.cc | 19 +----- src/lib/dhcp_ddns/tests/meson.build | 1 - src/lib/dhcp_ddns/tests/ncr_udp_unittests.cc | 2 +- src/lib/dhcp_ddns/tests/test_utils.cc | 37 ------------ src/lib/dhcp_ddns/tests/test_utils.h | 29 ---------- src/lib/dhcpsrv/tests/d2_udp_unittest.cc | 15 +---- .../generic_host_data_source_unittest.cc | 2 +- src/lib/testutils/unix_control_client.cc | 39 ++----------- src/lib/testutils/unix_control_client.h | 2 +- src/lib/util/meson.build | 2 + src/lib/util/ready_check.cc | 58 +++++++++++++++++++ src/lib/util/ready_check.h | 23 ++++++++ src/lib/util/tests/watch_socket_unittests.cc | 29 +--------- src/lib/util/unittests/interprocess_util.cc | 27 ++++----- 19 files changed, 136 insertions(+), 221 deletions(-) delete mode 100644 src/lib/dhcp_ddns/tests/test_utils.cc delete mode 100644 src/lib/dhcp_ddns/tests/test_utils.h create mode 100644 src/lib/util/ready_check.cc create mode 100644 src/lib/util/ready_check.h diff --git a/src/hooks/dhcp/high_availability/libloadtests/close_unittests.cc b/src/hooks/dhcp/high_availability/libloadtests/close_unittests.cc index 921ae886ce..8db3352151 100644 --- a/src/hooks/dhcp/high_availability/libloadtests/close_unittests.cc +++ b/src/hooks/dhcp/high_availability/libloadtests/close_unittests.cc @@ -255,6 +255,7 @@ CloseHATest::runPartners(bool const backup /* = true */) { } struct timeval tm; tm.tv_sec = tm.tv_usec = 0; + // r4z: should move to epoll/kqueue? int n = select(nfd + 1, &fds, 0, 0, &tm); if ((n < 0) && (errno == EINTR)) { cerr << "interrupted" << endl; diff --git a/src/lib/dhcp/iface_mgr.cc b/src/lib/dhcp/iface_mgr.cc index 960e71db3e..5c9432ff9e 100644 --- a/src/lib/dhcp/iface_mgr.cc +++ b/src/lib/dhcp/iface_mgr.cc @@ -135,7 +135,7 @@ Iface::getPlainMac() const { for (unsigned i = 0; i < mac_len_; i++) { tmp.width(2); tmp << static_cast(mac_[i]); - if (i < mac_len_-1) { + if (i < mac_len_ - 1) { tmp << ":"; } } @@ -439,7 +439,7 @@ IfaceMgr::setPacketFilter(const PktFilter6Ptr& packet_filter) { << " filter when there are open IPv6 sockets - need" << " to close them first"); } - + // Everything is fine, so replace packet filter. packet_filter6_ = packet_filter; } @@ -519,30 +519,30 @@ IfaceMgr::openSockets4(const uint16_t port, const bool use_bcast, // allowed if (iface->flag_loopback_ && !allow_loopback_) { IFACEMGR_ERROR(SocketConfigError, error_handler, iface, - "must not open socket on the loopback" - " interface " << iface->getName()); + "must not open socket on the loopback" + " interface " << iface->getName()); continue; } if (!iface->flag_up_) { IFACEMGR_ERROR(SocketConfigError, error_handler, iface, - "the interface " << iface->getName() - << " is down"); + "the interface " << iface->getName() + << " is down"); continue; } if (!iface->flag_running_) { IFACEMGR_ERROR(SocketConfigError, error_handler, iface, - "the interface " << iface->getName() - << " is not running"); + "the interface " << iface->getName() + << " is not running"); continue; } IOAddress out_address("0.0.0.0"); if (!iface->getAddress4(out_address)) { IFACEMGR_ERROR(SocketConfigError, error_handler, iface, - "the interface " << iface->getName() - << " has no usable IPv4 addresses configured"); + "the interface " << iface->getName() + << " has no usable IPv4 addresses configured"); continue; } @@ -1391,6 +1391,10 @@ IfaceMgr::addFDtoSet(int fd, int& maxfd, fd_set* sockets) { isc_throw(BadValue, "addFDtoSet: sockets can't be null"); } + if (fd >= FD_SETSIZE) { + isc_throw(BadValue, "addFDtoSet: sockets fd too large: " << fd << " >= " << FD_SETSIZE); + } + FD_SET(fd, sockets); if (maxfd < fd) { maxfd = fd; @@ -1889,10 +1893,8 @@ IfaceMgr::getSocket(const isc::dhcp::Pkt6Ptr& pkt) { // If we want to send something to link-local and the socket is // bound to link-local or we want to send to global and the socket // is bound to global, then use it as candidate - if ( (pkt->getRemoteAddr().isV6LinkLocal() && - s->addr_.isV6LinkLocal()) || - (!pkt->getRemoteAddr().isV6LinkLocal() && - !s->addr_.isV6LinkLocal()) ) { + if ((pkt->getRemoteAddr().isV6LinkLocal() && s->addr_.isV6LinkLocal()) || + (!pkt->getRemoteAddr().isV6LinkLocal() && !s->addr_.isV6LinkLocal())) { candidate = s; } } diff --git a/src/lib/dhcp/tests/pkt_filter_bpf_unittest.cc b/src/lib/dhcp/tests/pkt_filter_bpf_unittest.cc index cfc093607d..f5b6478c1a 100644 --- a/src/lib/dhcp/tests/pkt_filter_bpf_unittest.cc +++ b/src/lib/dhcp/tests/pkt_filter_bpf_unittest.cc @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -116,14 +117,7 @@ TEST_F(RootPktFilterBPFTest, send) { testPktEvents(test_message_, start_time_, std::list{PktEvent::RESPONSE_SENT}); // Read the data from socket. - fd_set readfds; - FD_ZERO(&readfds); - FD_SET(sock_info_.sockfd_, &readfds); - - struct timeval timeout; - timeout.tv_sec = 5; - timeout.tv_usec = 0; - int result = select(sock_info_.sockfd_ + 1, &readfds, NULL, NULL, &timeout); + int result = selectCheck(sock_info_.sockfd_, 5); // We should receive some data from loopback interface. ASSERT_GT(result, 0); @@ -238,14 +232,7 @@ TEST_F(RootPktFilterBPFTest, filterOutUnicast) { // Perform select on the socket to make sure that the packet has // been dropped. - fd_set readfds; - FD_ZERO(&readfds); - FD_SET(sock_info_.sockfd_, &readfds); - - struct timeval timeout; - timeout.tv_sec = 1; - timeout.tv_usec = 0; - int result = select(sock_info_.sockfd_ + 1, &readfds, NULL, NULL, &timeout); + int result = selectCheck(sock_info_.sockfd_, 1); ASSERT_LE(result, 0); } diff --git a/src/lib/dhcp/tests/pkt_filter_inet6_unittest.cc b/src/lib/dhcp/tests/pkt_filter_inet6_unittest.cc index 9688c5cfc1..3b21710e4a 100644 --- a/src/lib/dhcp/tests/pkt_filter_inet6_unittest.cc +++ b/src/lib/dhcp/tests/pkt_filter_inet6_unittest.cc @@ -10,11 +10,13 @@ #include #include #include +#include #include using namespace isc::asiolink; using namespace isc::dhcp; +using namespace isc::util; namespace { @@ -86,14 +88,7 @@ TEST_F(PktFilterInet6Test, send) { testPktEvents(test_message_, start_time_, std::list{PktEvent::RESPONSE_SENT}); // Read the data from socket. - fd_set readfds; - FD_ZERO(&readfds); - FD_SET(sock_info_.sockfd_, &readfds); - - struct timeval timeout; - timeout.tv_sec = 5; - timeout.tv_usec = 0; - result = select(sock_info_.sockfd_ + 1, &readfds, NULL, NULL, &timeout); + result = selectCheck(sock_info_.sockfd_, 5); // We should receive some data from loopback interface. ASSERT_GT(result, 0); diff --git a/src/lib/dhcp/tests/pkt_filter_inet_unittest.cc b/src/lib/dhcp/tests/pkt_filter_inet_unittest.cc index a83f5431cd..46d7caee32 100644 --- a/src/lib/dhcp/tests/pkt_filter_inet_unittest.cc +++ b/src/lib/dhcp/tests/pkt_filter_inet_unittest.cc @@ -10,6 +10,7 @@ #include #include #include +#include #include @@ -17,6 +18,7 @@ using namespace isc::asiolink; using namespace isc::dhcp; +using namespace isc::util; namespace { @@ -100,14 +102,7 @@ TEST_F(PktFilterInetTest, send) { testPktEvents(test_message_, start_time_, std::list{PktEvent::RESPONSE_SENT}); // Read the data from socket. - fd_set readfds; - FD_ZERO(&readfds); - FD_SET(sock_info_.sockfd_, &readfds); - - struct timeval timeout; - timeout.tv_sec = 5; - timeout.tv_usec = 0; - result = select(sock_info_.sockfd_ + 1, &readfds, NULL, NULL, &timeout); + result = selectCheck(sock_info_.sockfd_, 5); // We should receive some data from loopback interface. ASSERT_GT(result, 0); diff --git a/src/lib/dhcp/tests/pkt_filter_lpf_unittest.cc b/src/lib/dhcp/tests/pkt_filter_lpf_unittest.cc index 928699e2d7..3dc6c6014f 100644 --- a/src/lib/dhcp/tests/pkt_filter_lpf_unittest.cc +++ b/src/lib/dhcp/tests/pkt_filter_lpf_unittest.cc @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -129,14 +130,7 @@ TEST_F(RootPktFilterLPFTest, send) { testPktEvents(test_message_, start_time_, std::list{PktEvent::RESPONSE_SENT}); // Read the data from socket. - fd_set readfds; - FD_ZERO(&readfds); - FD_SET(sock_info_.sockfd_, &readfds); - - struct timeval timeout; - timeout.tv_sec = 5; - timeout.tv_usec = 0; - int result = select(sock_info_.sockfd_ + 1, &readfds, NULL, NULL, &timeout); + int result = selectCheck(sock_info_.sockfd_, 5); // We should receive some data from loopback interface. ASSERT_GT(result, 0); @@ -229,14 +223,7 @@ TEST_F(RootPktFilterLPFTest, filterOutUnicast) { // Perform select on the socket to make sure that the packet has // been dropped. - fd_set readfds; - FD_ZERO(&readfds); - FD_SET(sock_info_.sockfd_, &readfds); - - struct timeval timeout; - timeout.tv_sec = 1; - timeout.tv_usec = 0; - int result = select(sock_info_.sockfd_ + 1, &readfds, NULL, NULL, &timeout); + int result = selectCheck(sock_info_.sockfd_, 1); ASSERT_LE(result, 0); } diff --git a/src/lib/dhcp_ddns/tests/meson.build b/src/lib/dhcp_ddns/tests/meson.build index fa607edd76..c208f7775d 100644 --- a/src/lib/dhcp_ddns/tests/meson.build +++ b/src/lib/dhcp_ddns/tests/meson.build @@ -7,7 +7,6 @@ kea_dhcp_ddns_tests = executable( 'ncr_udp_unittests.cc', 'ncr_unittests.cc', 'run_unittests.cc', - 'test_utils.cc', dependencies: [GTEST_DEP], include_directories: [include_directories('.')] + INCLUDES, link_with: [kea_testutils_lib, kea_util_unittests_lib] + LIBS_BUILT_SO_FAR, diff --git a/src/lib/dhcp_ddns/tests/ncr_udp_unittests.cc b/src/lib/dhcp_ddns/tests/ncr_udp_unittests.cc index 3274f9b01e..a1d2b54266 100644 --- a/src/lib/dhcp_ddns/tests/ncr_udp_unittests.cc +++ b/src/lib/dhcp_ddns/tests/ncr_udp_unittests.cc @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include diff --git a/src/lib/dhcp_ddns/tests/test_utils.cc b/src/lib/dhcp_ddns/tests/test_utils.cc deleted file mode 100644 index 322df62a90..0000000000 --- a/src/lib/dhcp_ddns/tests/test_utils.cc +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (C) 2014-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/. - -#include - -#include - -#include -#include - -using namespace std; - -namespace isc { -namespace dhcp_ddns { - -int selectCheck(int fd_to_check) { - fd_set read_fds; - int maxfd = 0; - - FD_ZERO(&read_fds); - - // Add this socket to listening set - FD_SET(fd_to_check, &read_fds); - maxfd = fd_to_check; - - struct timeval select_timeout; - select_timeout.tv_sec = 0; - select_timeout.tv_usec = 0; - - return (select(maxfd + 1, &read_fds, NULL, NULL, &select_timeout)); -} - -} // namespace isc::d2 -} // namespace isc diff --git a/src/lib/dhcp_ddns/tests/test_utils.h b/src/lib/dhcp_ddns/tests/test_utils.h deleted file mode 100644 index eeaf14f67c..0000000000 --- a/src/lib/dhcp_ddns/tests/test_utils.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (C) 2014-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 TEST_UTILS_H -#define TEST_UTILS_H - -/// @file test_utils.h Common dhcp_ddns testing elements - -#include - - -namespace isc { -namespace dhcp_ddns { - -/// @brief Returns the result of select() given an fd to check for read status. -/// -/// @param fd_to_check The file descriptor to test -/// -/// @return Returns less than one on an error, 0 if the fd is not ready to -/// read, > 0 if it is ready to read. -int selectCheck(int fd_to_check); - -} // namespace isc::dhcp_ddns; -} // namespace isc; - -#endif diff --git a/src/lib/dhcpsrv/tests/d2_udp_unittest.cc b/src/lib/dhcpsrv/tests/d2_udp_unittest.cc index c387fb57a5..5a32279842 100644 --- a/src/lib/dhcpsrv/tests/d2_udp_unittest.cc +++ b/src/lib/dhcpsrv/tests/d2_udp_unittest.cc @@ -14,6 +14,7 @@ #include #include #include +#include #include @@ -126,10 +127,6 @@ public: /// @param expect_ready Expected state of readiness (True if expecting /// a ready to ready result, false if expecting otherwise). void selectCheck(bool expect_ready) { - fd_set read_fds; - int maxfd = 0; - - FD_ZERO(&read_fds); // cppcheck-suppress redundantAssignment int select_fd = -1; @@ -138,15 +135,7 @@ public: select_fd = handle_->getSelectFd() ); - FD_SET(select_fd, &read_fds); - maxfd = select_fd; - - struct timeval select_timeout; - select_timeout.tv_sec = 0; - select_timeout.tv_usec = 0; - - int result = (select(maxfd + 1, &read_fds, NULL, NULL, - &select_timeout)); + int result = util::selectCheck(select_fd); if (result < 0) { const char *errstr = strerror(errno); diff --git a/src/lib/dhcpsrv/testutils/generic_host_data_source_unittest.cc b/src/lib/dhcpsrv/testutils/generic_host_data_source_unittest.cc index c9c0e3c5e3..cb77a90751 100644 --- a/src/lib/dhcpsrv/testutils/generic_host_data_source_unittest.cc +++ b/src/lib/dhcpsrv/testutils/generic_host_data_source_unittest.cc @@ -81,7 +81,7 @@ GenericHostDataSourceTest::compareHostsIdentifier(const ConstHostPtr& host1, if (count1 > count2) { count1 = count2; } - for (uint8_t i = 0; i < count1; ++i) { + for (size_t i = 0; i < count1; ++i) { if (host1_i[i] != host2_i[i]) { return (host1_i[i] < host2_i[i]); } diff --git a/src/lib/testutils/unix_control_client.cc b/src/lib/testutils/unix_control_client.cc index 1d1fdc7540..3a426d84fd 100644 --- a/src/lib/testutils/unix_control_client.cc +++ b/src/lib/testutils/unix_control_client.cc @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -138,44 +139,14 @@ int UnixControlClient::selectCheck(const unsigned int timeout_sec, bool write_check) { if (socket_fd_ < 0) { ADD_FAILURE() << "select check with closed socket"; - return -1; + return (-1); } - if (socket_fd_ > 1023) { + if (socket_fd_ >= FD_SETSIZE) { ADD_FAILURE() << "select check with out of bound socket"; - return -1; + return (-1); } - int maxfd = 0; - fd_set read_fds; - FD_ZERO(&read_fds); - - fd_set write_fds; - FD_ZERO(&write_fds); - - maxfd = socket_fd_; - - // Add this socket to read set - FD_SET(socket_fd_, &read_fds); - - // Add this socket to write set - FD_SET(socket_fd_, &write_fds); - - struct timeval select_timeout; - select_timeout.tv_sec = static_cast(timeout_sec); - select_timeout.tv_usec = 0; - - fd_set* read_p = 0; - fd_set* write_p = 0; - - if (read_check) { - read_p = &read_fds; - } - - if (write_check) { - write_p = &write_fds; - } - - return (select(maxfd + 1, read_p, write_p, NULL, &select_timeout)); + return (util::selectCheck(socket_fd_, timeout_sec, read_check, write_check)); } } diff --git a/src/lib/testutils/unix_control_client.h b/src/lib/testutils/unix_control_client.h index 74daa839f9..19b487bb31 100644 --- a/src/lib/testutils/unix_control_client.h +++ b/src/lib/testutils/unix_control_client.h @@ -54,7 +54,7 @@ public: /// @param timeout_sec Select timeout in seconds /// @param read_check flag to check socket for read ready state /// @param write_check flag to check socket for write ready state - /// @return -1 on error, 0 if no data is available, 1 if data is ready + /// @return -1 on error, 0 if no data is available, 1 if data is ready int selectCheck(const unsigned int timeout_sec, bool read_check, bool write_check); /// @brief Retains the fd of the open socket diff --git a/src/lib/util/meson.build b/src/lib/util/meson.build index 4728383c40..845a8dd3f6 100644 --- a/src/lib/util/meson.build +++ b/src/lib/util/meson.build @@ -11,6 +11,7 @@ kea_util_lib = shared_library( 'memory_segment_local.cc', 'multi_threading_mgr.cc', 'pid_file.cc', + 'ready_check.cc', 'reconnect_ctl.cc', 'state_model.cc', 'stopwatch.cc', @@ -57,6 +58,7 @@ kea_util_headers = [ 'pointer_util.h', 'range_utilities.h', 'readwrite_mutex.h', + 'ready_check.h', 'reconnect_ctl.h', 'staged_value.h', 'state_model.h', diff --git a/src/lib/util/ready_check.cc b/src/lib/util/ready_check.cc new file mode 100644 index 0000000000..fd3c08c530 --- /dev/null +++ b/src/lib/util/ready_check.cc @@ -0,0 +1,58 @@ +// Copyright (C) 2025 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/. + +#include + +#include +#include + +namespace isc { +namespace util { + +int selectCheck(const int fd_to_check, const unsigned int timeout_sec, + bool read_check, bool write_check) { + if (fd_to_check < 0) { + return (-1); + } + if (fd_to_check >= FD_SETSIZE) { + return (-1); + } + int maxfd = 0; + + fd_set read_fds; + FD_ZERO(&read_fds); + + fd_set write_fds; + FD_ZERO(&write_fds); + + maxfd = fd_to_check; + + // Add this socket to read set + FD_SET(fd_to_check, &read_fds); + + // Add this socket to write set + FD_SET(fd_to_check, &write_fds); + + struct timeval select_timeout; + select_timeout.tv_sec = static_cast(timeout_sec); + select_timeout.tv_usec = 0; + + fd_set* read_p = 0; + fd_set* write_p = 0; + + if (read_check) { + read_p = &read_fds; + } + + if (write_check) { + write_p = &write_fds; + } + + return (select(maxfd + 1, read_p, write_p, 0, &select_timeout)); +} + +} // end of isc::util namespace +} // end of isc namespace diff --git a/src/lib/util/ready_check.h b/src/lib/util/ready_check.h new file mode 100644 index 0000000000..6cc734d5f6 --- /dev/null +++ b/src/lib/util/ready_check.h @@ -0,0 +1,23 @@ +// Copyright (C) 2025 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 READY_CHECK_H +#define READY_CHECK_H + +namespace isc { +namespace util { + +/// @param fd_to_check The file descriptor to test +/// @param timeout_sec Select timeout in seconds +/// @param read_check flag to check socket for read ready state +/// @param write_check flag to check socket for write ready state +/// @return -1 on error, 0 if no data is available, 1 if data is ready +int selectCheck(const int fd_to_check, const unsigned int timeout_sec = 0, bool read_check = true, bool write_check = false); + +} // end of isc::util namespace +} // end of isc namespace + +#endif // READY_CHECK_H diff --git a/src/lib/util/tests/watch_socket_unittests.cc b/src/lib/util/tests/watch_socket_unittests.cc index b503844aef..b19096c568 100644 --- a/src/lib/util/tests/watch_socket_unittests.cc +++ b/src/lib/util/tests/watch_socket_unittests.cc @@ -4,12 +4,12 @@ // 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/. #include -#include -#include +#include +#include -#include #include +#include #ifdef HAVE_SYS_FILIO_H // FIONREAD is here on Solaris @@ -22,29 +22,6 @@ using namespace isc::util; namespace { -/// @brief Returns the result of select() given an fd to check for read status. -/// -/// @param fd_to_check The file descriptor to test -/// -/// @return Returns less than one on an error, 0 if the fd is not ready to -/// read, > 0 if it is ready to read. -int selectCheck(int fd_to_check) { - fd_set read_fds; - int maxfd = 0; - - FD_ZERO(&read_fds); - - // Add this socket to listening set - FD_SET(fd_to_check, &read_fds); - maxfd = fd_to_check; - - struct timeval select_timeout; - select_timeout.tv_sec = 0; - select_timeout.tv_usec = 0; - - return (select(maxfd + 1, &read_fds, NULL, NULL, &select_timeout)); -} - /// @brief Tests the basic functionality of WatchSocket. TEST(WatchSocketTest, basics) { WatchSocketPtr watch; diff --git a/src/lib/util/unittests/interprocess_util.cc b/src/lib/util/unittests/interprocess_util.cc index 98944e5014..eee7d58bf3 100644 --- a/src/lib/util/unittests/interprocess_util.cc +++ b/src/lib/util/unittests/interprocess_util.cc @@ -6,9 +6,10 @@ #include +#include + #include -#include #include namespace isc { @@ -17,24 +18,18 @@ namespace unittests { unsigned char parentReadState(int fd) { - unsigned char result = 0xff; - - fd_set rfds; - FD_ZERO(&rfds); - FD_SET(fd, &rfds); - - struct timeval tv = {5, 0}; + unsigned char result = 0xff; - const int nfds = select(fd + 1, &rfds, NULL, NULL, &tv); - EXPECT_EQ(1, nfds); + const int nfds = util::selectCheck(fd, 5); + EXPECT_EQ(1, nfds); - if (nfds == 1) { - // Read status - const ssize_t bytes_read = read(fd, &result, sizeof(result)); - EXPECT_EQ(static_cast(sizeof(result)), bytes_read); - } + if (nfds == 1) { + // Read status + const ssize_t bytes_read = read(fd, &result, sizeof(result)); + EXPECT_EQ(static_cast(sizeof(result)), bytes_read); + } - return (result); + return (result); } } -- 2.47.3