PLANTUML = find_program('plantuml', required: false)
PYTHON = find_program('python3', 'python', required: true)
SPHINX = find_program('sphinx-build', 'sphinx-build-3', required: false)
+SUDO = find_program('sudo', required: false)
XMLLINT = find_program('xmllint', required: false)
CD_AND_RUN = find_program(TOP_SOURCE_DIR / 'scripts/cd-and-run.sh')
endif
conf_data.set('PACKAGE_VERSION_TYPE', f'"@package_version_type@"')
+PASSWORDLESS_SUDO_SET_UP = false
+if SUDO.found()
+ result = run_command(SUDO, '-n', 'true', check: false)
+ if result.returncode() == 0
+ PASSWORDLESS_SUDO_SET_UP = true
+ endif
+endif
+
#### Compiler
compile_args = []
std::vector<uint8_t> input_buf_;
};
+// Test fixture used to distinguish tests that require root privileges.
+struct RootICMPSocketTest : ICMPSocketTest {};
// Verifies that an ICMP socket can be opened and closed.
-TEST_F(ICMPSocketTest, openClose) {
+TEST_F(RootICMPSocketTest, openClose) {
SKIP_IF(notRoot());
// For open the endpoint is only used to determine protocol, the address is irrelevant.
}
// Verifies that an ICMP socket can send and receive ICMP messages.
-TEST_F(ICMPSocketTest, sendReceive) {
+TEST_F(RootICMPSocketTest, sendReceive) {
SKIP_IF(notRoot());
PingSocket socket(io_service_);
include_directories: [include_directories('.'), include_directories('..')] + INCLUDES,
link_with: [dhcp_ping_check_archive] + LIBS_BUILT_SO_FAR,
)
-test('dhcp-ping-check-tests', dhcp_ping_check_tests, protocol: 'gtest')
+
+root_tests = 'RootICMPSocketTest.*:RootPingChannelTest.*:RootPingCheckMgr.*:RootPingCheckMgrTest.*'
+
+test(
+ 'dhcp-ping-check-tests',
+ dhcp_ping_check_tests,
+ args: [f'--gtest_filter=-@root_tests@'],
+ protocol: 'gtest',
+ is_parallel: false,
+ priority: -1,
+)
+
+if PASSWORDLESS_SUDO_SET_UP
+ test(
+ 'sudo-dhcp-ping-check-tests',
+ SUDO,
+ args: [dhcp_ping_check_tests, f'--gtest_filter=@root_tests@'],
+ protocol: 'gtest',
+ is_parallel: false,
+ priority: -1,
+ suite: 'sudo-tests',
+ )
+endif
bool stopped_;
};
+// Test fixture used to distinguish tests that require root privileges.
+struct RootPingChannelTest : PingChannelTest {};
+
void
PingChannelTest::sendReceiveTest(size_t num_threads, size_t num_targets /* = 25 */,
const std::function<void()>& set_error_trigger) {
}
// Verifies PingChannel open and close operations.
-TEST_F(PingChannelTest, openCloseST) {
+TEST_F(RootPingChannelTest, openCloseST) {
SKIP_IF(notRoot());
// Create the channel instance.
}
// Verifies PingChannel open and close operations.
-TEST_F(PingChannelTest, openCloseMT) {
+TEST_F(RootPingChannelTest, openCloseMT) {
SKIP_IF(notRoot());
MultiThreadingTest mt;
// Verifies that a PingChannel can perpetuate sending requests and receiving
// replies when driven by a single-threaded IOService.
-TEST_F(PingChannelTest, sendReceiveST) {
+TEST_F(RootPingChannelTest, sendReceiveST) {
sendReceiveTest(0);
}
// Verifies that a PingChannel can perpetuate sending requests and receiving
// replies when driven by a multi-threaded IOServiceThreadPool 3 threads
-TEST_F(PingChannelTest, sendReceiveMT) {
+TEST_F(RootPingChannelTest, sendReceiveMT) {
// Use a thread pool with 3 threads.
sendReceiveTest(3);
}
// Verifies that an exception throw from asyncRead triggers graceful channel
// shutdown and that operations can be resumed with a single-threaded channel.
-TEST_F(PingChannelTest, readExceptionErrorST) {
+TEST_F(RootPingChannelTest, readExceptionErrorST) {
ioErrorTest(
[this]() {
channel_->throw_on_read_number_ = 5;
// Verifies that an exception throw from asyncRead triggers graceful channel
// shutdown and that operations can be resumed with a multi-threaded channel.
-TEST_F(PingChannelTest, readExceptionErrorMT) {
+TEST_F(RootPingChannelTest, readExceptionErrorMT) {
// Use a thread pool with 3 threads.
ioErrorTest(
[this]() {
// Verifies that a fatal error code passed into socketReadCallback triggers graceful channel
// shutdown and that operations can be resumed with a single-threaded channel.
-TEST_F(PingChannelTest, readFatalErrorST) {
+TEST_F(RootPingChannelTest, readFatalErrorST) {
ioErrorTest(
[this]() {
channel_->ec_on_read_number_ = 3;
// Verifies that a fatal error code passed into socketReadCallback triggers graceful channel
// shutdown and that operations can be resumed with a single-threaded channel.
-TEST_F(PingChannelTest, readFatalErrorMT) {
+TEST_F(RootPingChannelTest, readFatalErrorMT) {
ioErrorTest(
[this]() {
channel_->ec_on_read_number_ = 3;
// Verifies that a non-fatal, EWOULDBLOCK error passed into socketReadCallback does
// not disrupt reading for a single-threaded channel.
-TEST_F(PingChannelTest, readAgainErrorST) {
+TEST_F(RootPingChannelTest, readAgainErrorST) {
sendReceiveTest(0, 10,
[this]() {
channel_->ec_on_read_number_ = 4;
// Verifies that a non-fatal, EWOULDBLOCK error passed into socketReadCallback does
// not disrupt reading for a multi-threaded channel.
-TEST_F(PingChannelTest, readAgainErrorMT) {
+TEST_F(RootPingChannelTest, readAgainErrorMT) {
sendReceiveTest(3, 10,
[this]() {
channel_->ec_on_read_number_ = 4;
// Verifies that an exception throw from asyncRead triggers graceful channel
// shutdown and that operations can be resumed with a single-threaded channel.
-TEST_F(PingChannelTest, writeExceptionErrorST) {
+TEST_F(RootPingChannelTest, writeExceptionErrorST) {
ioErrorTest(
[this]() {
channel_->throw_on_write_number_ = 5;
// Verifies that an exception throw from asyncRead triggers graceful channel
// shutdown and that operations can be resumed with a multi-threaded channel.
-TEST_F(PingChannelTest, writeExceptionErrorMT) {
+TEST_F(RootPingChannelTest, writeExceptionErrorMT) {
// Use a thread pool with 3 threads.
ioErrorTest(
[this]() {
// Verifies that a fatal error code passed into socketReadCallback triggers graceful channel
// shutdown and that operations can be resumed with a single-threaded channel.
-TEST_F(PingChannelTest, writeFatalErrorST) {
+TEST_F(RootPingChannelTest, writeFatalErrorST) {
ioErrorTest(
[this]() {
channel_->ec_on_write_number_ = 3;
// Verifies that a fatal error code passed into socketReadCallback triggers graceful channel
// shutdown and that operations can be resumed with a single-threaded channel.
-TEST_F(PingChannelTest, writeFatalErrorMT) {
+TEST_F(RootPingChannelTest, writeFatalErrorMT) {
ioErrorTest(
[this]() {
channel_->ec_on_write_number_ = 3;
// Verifies that a non-fatal, EWOULDBLOCK error passed into socketWriteCallback does
// not disrupt writing for a single-threaded channel.
-TEST_F(PingChannelTest, writeAgainErrorST) {
+TEST_F(RootPingChannelTest, writeAgainErrorST) {
sendReceiveTest(0, 10,
[this]() {
channel_->ec_on_write_number_ = 6;
// Verifies that a non-fatal, EWOULDBLOCK error passed into socketWriteCallback
// does not disrupt writing for a multi-threaded channel.
-TEST_F(PingChannelTest, writeAgainErrorMT) {
+TEST_F(RootPingChannelTest, writeAgainErrorMT) {
sendReceiveTest(3, 10,
[this]() {
channel_->ec_on_write_number_ = 6;
// Verify the recoverable write errors do not disrupt writing for a
// single-threaded channel.
-TEST_F(PingChannelTest, writeSendFailedErrorST) {
+TEST_F(RootPingChannelTest, writeSendFailedErrorST) {
SKIP_IF(notRoot());
std::list<boost::asio::error::basic_errors> errors = {
// Verify the recoverable write errors do not disrupt writing for a
// multi-threaded channel.
-TEST_F(PingChannelTest, writeSendFailedErrorMT) {
+TEST_F(RootPingChannelTest, writeSendFailedErrorMT) {
SKIP_IF(notRoot());
std::list<boost::asio::error::basic_errors> errors = {
namespace {
+// Test fixture used to distinguish tests that require root privileges.
+struct RootPingCheckMgr : PingCheckMgr {};
+
// Sanity check the basics for production class, PingCheckMgr, single-threaded mode.
-TEST(PingCheckMgr, basicsST) {
+TEST(RootPingCheckMgr, basicsST) {
SKIP_IF(IOServiceTest::notRoot());
MultiThreadingMgr::instance().setMode(false);
// Sanity check the basics for production class, PingCheckMgr. Bulk of testing
// is done with test derivation, TestPingCheckMgr.
-TEST(PingCheckMgr, basicsMT) {
+TEST(RootPingCheckMgr, basicsMT) {
SKIP_IF(IOServiceTest::notRoot());
MultiThreadingTest mt;
LeaseQueryPairs frees_;
};
-TEST_F(PingCheckMgrTest, operationalBasicsST) {
+// Test fixture used to distinguish tests that require root privileges.
+struct RootPingCheckMgrTest : PingCheckMgrTest {};
+
+
+TEST_F(RootPingCheckMgrTest, operationalBasicsST) {
testOperationalBasics(0);
}
-TEST_F(PingCheckMgrTest, operationalBasicsMT) {
+TEST_F(RootPingCheckMgrTest, operationalBasicsMT) {
MultiThreadingTest mt;
testOperationalBasics(3);
}
-TEST_F(PingCheckMgrTest, startPingST) {
+TEST_F(RootPingCheckMgrTest, startPingST) {
testStartPing();
}
-TEST_F(PingCheckMgrTest, startPingMT) {
+TEST_F(RootPingCheckMgrTest, startPingMT) {
MultiThreadingTest mt;
testStartPing();
}
-TEST_F(PingCheckMgrTest, nextToSendST) {
+TEST_F(RootPingCheckMgrTest, nextToSendST) {
testNextToSend();
}
-TEST_F(PingCheckMgrTest, nextToSendMT) {
+TEST_F(RootPingCheckMgrTest, nextToSendMT) {
MultiThreadingTest mt;
testNextToSend();
}
-TEST_F(PingCheckMgrTest, setNextExpirationST) {
+TEST_F(RootPingCheckMgrTest, setNextExpirationST) {
testSetNextExpiration();
}
-TEST_F(PingCheckMgrTest, setNextExpirationMT) {
+TEST_F(RootPingCheckMgrTest, setNextExpirationMT) {
MultiThreadingTest mt;
testSetNextExpiration();
}
-TEST_F(PingCheckMgrTest, sendCompletedST) {
+TEST_F(RootPingCheckMgrTest, sendCompletedST) {
testSendCompleted();
}
-TEST_F(PingCheckMgrTest, sendCompletedMT) {
+TEST_F(RootPingCheckMgrTest, sendCompletedMT) {
MultiThreadingTest mt;
testSendCompleted();
}
-TEST_F(PingCheckMgrTest, replyReceivedForEchoReplyST) {
+TEST_F(RootPingCheckMgrTest, replyReceivedForEchoReplyST) {
testReplyReceivedForEchoReply();
}
-TEST_F(PingCheckMgrTest, replyReceivedForEchoReplyMT) {
+TEST_F(RootPingCheckMgrTest, replyReceivedForEchoReplyMT) {
MultiThreadingTest mt;
testReplyReceivedForEchoReply();
}
-TEST_F(PingCheckMgrTest, replyReceivedForTargetUnreachableST) {
+TEST_F(RootPingCheckMgrTest, replyReceivedForTargetUnreachableST) {
testReplyReceivedForTargetUnreachable();
}
-TEST_F(PingCheckMgrTest, replyReceivedForTargetUnreachableMT) {
+TEST_F(RootPingCheckMgrTest, replyReceivedForTargetUnreachableMT) {
MultiThreadingTest mt;
testReplyReceivedForTargetUnreachable();
}
-TEST_F(PingCheckMgrTest, expirationProcessingST) {
+TEST_F(RootPingCheckMgrTest, expirationProcessingST) {
testExpirationProcessing();
}
-TEST_F(PingCheckMgrTest, expirationProcessingMT) {
+TEST_F(RootPingCheckMgrTest, expirationProcessingMT) {
MultiThreadingTest mt;
testExpirationProcessing();
}
-TEST_F(PingCheckMgrTest, multiplePingsWithReplyST) {
+TEST_F(RootPingCheckMgrTest, multiplePingsWithReplyST) {
testMultiplePingsWithReply();
}
-TEST_F(PingCheckMgrTest, multiplePingsWithReplyMT) {
+TEST_F(RootPingCheckMgrTest, multiplePingsWithReplyMT) {
MultiThreadingTest mt;
testMultiplePingsWithReply();
}
-TEST_F(PingCheckMgrTest, multiplePingsWithReplyAndPauseST) {
+TEST_F(RootPingCheckMgrTest, multiplePingsWithReplyAndPauseST) {
testMultiplePingsWithReplyAndPause();
}
-TEST_F(PingCheckMgrTest, multiplePingsWithReplyAndPauseMT) {
+TEST_F(RootPingCheckMgrTest, multiplePingsWithReplyAndPauseMT) {
MultiThreadingTest mt;
testMultiplePingsWithReplyAndPause();
}
-TEST_F(PingCheckMgrTest, sendCompletedSendFailedST) {
+TEST_F(RootPingCheckMgrTest, sendCompletedSendFailedST) {
testSendCompletedSendFailed();
}
-TEST_F(PingCheckMgrTest, sendCompletedSendFailedMT) {
+TEST_F(RootPingCheckMgrTest, sendCompletedSendFailedMT) {
MultiThreadingTest mt;
testSendCompletedSendFailed();
}
-TEST_F(PingCheckMgrTest, shouldPingST) {
+TEST_F(RootPingCheckMgrTest, shouldPingST) {
testShouldPingTest();
}
-TEST_F(PingCheckMgrTest, shouldPingMT) {
+TEST_F(RootPingCheckMgrTest, shouldPingMT) {
MultiThreadingTest mt;
testShouldPingTest();
}
testGetScopedConfig();
}
-TEST_F(PingCheckMgrTest, checkSuspendedST) {
+TEST_F(RootPingCheckMgrTest, checkSuspendedST) {
testCheckSuspended();
}
-TEST_F(PingCheckMgrTest, checkSuspendedMT) {
+TEST_F(RootPingCheckMgrTest, checkSuspendedMT) {
MultiThreadingTest mt;
testCheckSuspended();
}
include_directories: [include_directories('.')] + INCLUDES,
link_with: [kea_util_unittests_lib, libs_testutils] + LIBS_BUILT_SO_FAR,
)
+
+root_tests = 'RootPktFilterBPFTest.*:RootPktFilterLPFTest.*'
+
test(
'kea-dhcp-tests',
kea_dhcp_tests,
+ args: [f'--gtest_filter=-@root_tests@'],
protocol: 'gtest',
is_parallel: false,
priority: -1,
)
+
+if PASSWORDLESS_SUDO_SET_UP
+ test(
+ 'sudo-kea-dhcp-tests',
+ SUDO,
+ args: [kea_dhcp_tests, f'--gtest_filter=@root_tests@'],
+ protocol: 'gtest',
+ is_parallel: false,
+ priority: -1,
+ suite: 'sudo-tests',
+ )
+endif
-// Copyright (C) 2014-2024 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2014-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
}
};
+// Test fixture used to distinguish tests that require root privileges.
+struct RootPktFilterBPFTest : PktFilterBPFTest {};
+
// This test verifies that the PktFilterBPF class reports its capability
// to send packets to the host having no IP address assigned.
TEST_F(PktFilterBPFTest, isDirectResponseSupported) {
// This test verifies that the raw AF_PACKET family socket can
// be opened and bound to the specific interface.
-TEST_F(PktFilterBPFTest, openSocket) {
+TEST_F(RootPktFilterBPFTest, openSocket) {
SKIP_IF(notRoot());
// Create object representing loopback interface.
// test over the real interface but since we don't know what interfaces
// are present in the particular system we have to stick to local loopback
// interface as this one is almost always present.
-TEST_F(PktFilterBPFTest, send) {
+TEST_F(RootPktFilterBPFTest, send) {
SKIP_IF(notRoot());
// Packet will be sent over loopback interface.
// This test verifies correctness of reception of the DHCP packet over
// raw socket, whereby all IP stack headers are hand-crafted.
-TEST_F(PktFilterBPFTest, receive) {
+TEST_F(RootPktFilterBPFTest, receive) {
SKIP_IF(notRoot());
// Packet will be received over loopback interface.
// This test verifies that if the packet is received over the raw
// socket and its destination address doesn't match the address
// to which the socket is "bound", the packet is dropped.
-TEST_F(PktFilterBPFTest, filterOutUnicast) {
+TEST_F(RootPktFilterBPFTest, filterOutUnicast) {
SKIP_IF(notRoot());
// Packet will be received over loopback interface.
-// Copyright (C) 2013-2024 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013-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
}
};
+// Test fixture used to distinguish tests that require root privileges.
+struct RootPktFilterLPFTest : PktFilterLPFTest {};
+
// This test verifies that the PktFilterLPF class reports its capability
// to send packets to the host having no IP address assigned.
TEST_F(PktFilterLPFTest, isDirectResponseSupported) {
// This test verifies that the raw AF_PACKET family socket can
// be opened and bound to the specific interface.
-TEST_F(PktFilterLPFTest, openSocket) {
+TEST_F(RootPktFilterLPFTest, openSocket) {
SKIP_IF(notRoot());
// Create object representing loopback interface.
// This test verifies correctness of sending DHCP packet through the raw
// socket, whereby all IP stack headers are hand-crafted.
-TEST_F(PktFilterLPFTest, send) {
+TEST_F(RootPktFilterLPFTest, send) {
SKIP_IF(notRoot());
// Packet will be sent over loopback interface.
// This test verifies correctness of reception of the DHCP packet over
// raw socket, whereby all IP stack headers are hand-crafted.
-TEST_F(PktFilterLPFTest, receive) {
+TEST_F(RootPktFilterLPFTest, receive) {
SKIP_IF(notRoot());
// Packet will be received over loopback interface.
// This test verifies that if the packet is received over the raw
// socket and its destination address doesn't match the address
// to which the socket is "bound", the packet is dropped.
-TEST_F(PktFilterLPFTest, filterOutUnicast) {
+TEST_F(RootPktFilterLPFTest, filterOutUnicast) {
SKIP_IF(notRoot());
// Packet will be received over loopback interface.