]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#4274] Checkpoint: adding Tcp UTs
authorFrancis Dupont <fdupont@isc.org>
Sat, 24 Jan 2026 11:47:11 +0000 (12:47 +0100)
committerFrancis Dupont <fdupont@isc.org>
Mon, 9 Feb 2026 21:05:46 +0000 (22:05 +0100)
src/hooks/dhcp/radius/radius_status.cc
src/hooks/dhcp/radius/tests/exchange_unittests.cc
src/hooks/dhcp/radius/tests/tcp_exchange_unittests.cc

index 27933a643035c886384f451e67e2848737284bcb..52fb16876785bc10becf87da19f2a82ecd87acc6 100644 (file)
@@ -38,7 +38,8 @@ RadiusAuthStatus::RadiusAuthStatus(const AttributesPtr& send_attrs,
     exchange_ = Exchange::create(RadiusImpl::instance().getIOContext(),
                                  request, maxretries, servers,
                                  std::bind(&RadiusAuthStatus::invokeCallback,
-                                           handler, ph::_1));
+                                           handler, ph::_1),
+                                 RadiusImpl::instance().proto_);
 }
 
 void
@@ -114,7 +115,8 @@ RadiusAcctStatus::RadiusAcctStatus(const AttributesPtr& send_attrs,
     exchange_ = Exchange::create(RadiusImpl::instance().getIOContext(),
                                  request, maxretries, servers,
                                  std::bind(&RadiusAcctStatus::invokeCallback,
-                                           handler, ph::_1));
+                                           handler, ph::_1),
+                                 RadiusImpl::instance().proto_);
 }
 
 void
@@ -190,7 +192,8 @@ RadiusTlsStatus::RadiusTlsStatus(const AttributesPtr& send_attrs,
     exchange_ = Exchange::create(RadiusImpl::instance().getIOContext(),
                                  request, maxretries, servers,
                                  std::bind(&RadiusTlsStatus::invokeCallback,
-                                           handler, ph::_1));
+                                           handler, ph::_1),
+                                 PW_PROTO_TLS);
 }
 
 void
index 475adf79bd53627d8596861061d870feac25cac2..dffd9592fe79798c244db3fb9d0c7a5a48a84281 100644 (file)
@@ -4,9 +4,6 @@
 // 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/.
 
-/// @file This file contains tests which exercise the attribute,
-/// attribute collection and config attribute collection classes.
-
 #include <config.h>
 
 #include <client_exchange.h>
@@ -81,6 +78,9 @@ TEST(TestExchange, async) {
     MessagePtr response = exchange->getResponse();
     EXPECT_FALSE(response);
 
+    // Verify it is an UDP Exchange.
+    EXPECT_TRUE(boost::dynamic_pointer_cast<UdpExchange>(exchange));
+
     // As a best practice, call any remaining handlers.
     io_service->stopAndPoll();
 }
@@ -123,6 +123,9 @@ TEST(TestExchange, sync) {
     EXPECT_EQ(request, msg);
     MessagePtr response = exchange->getResponse();
     EXPECT_FALSE(response);
+
+    // Verify it is an UDP Exchange.
+    EXPECT_TRUE(boost::dynamic_pointer_cast<UdpExchange>(exchange));
 }
 
 /// Test Exchange class.
@@ -142,6 +145,7 @@ public:
     using Exchange::identifier_;
     using Exchange::sync_;
     using Exchange::rc_;
+    using Exchange::sent_;
     using Exchange::received_;
     using UdpExchange::started_;
     using UdpExchange::terminated_;
@@ -151,7 +155,6 @@ public:
     using UdpExchange::timer_;
     using UdpExchange::server_;
     using UdpExchange::idx_;
-    using UdpExchange::sent_;
     using UdpExchange::buffer_;
     using UdpExchange::size_;
     using UdpExchange::retries_;
index 78c25411691cbc3fd7b84c40cf5e5a585039575d..3537e5dad6dc1238be7ed092ee452fd6f1259139 100644 (file)
@@ -6,7 +6,7 @@
 
 #include <config.h>
 
-#include <client_exchange.h>
+#include <radius.h>
 #include <testutils/gtest_utils.h>
 #include <testutils/test_to_element.h>
 #include <attribute_test.h>
@@ -18,14 +18,15 @@ using namespace isc::asiolink;
 using namespace isc::data;
 using namespace isc::dhcp;
 using namespace isc::radius;
+using namespace isc::tcp;
 using namespace isc::test;
 using namespace std;
 using namespace std::chrono;
 
 namespace {
 
-// Verify the async constructor.
-TEST(TestTcpExchange, factory) {
+// Verify the factory with TCP.
+TEST(TestTcpExchange, tcpFactory) {
     ExchangePtr exchange;
     IOServicePtr io_service;
     MessagePtr msg;
@@ -33,7 +34,7 @@ TEST(TestTcpExchange, factory) {
 
     // No message.
     EXPECT_THROW_MSG(Exchange::create(io_service, msg, 0, servers,
-                                      Exchange::Handler()),
+                                      Exchange::Handler(), PW_PROTO_TCP),
                      BadValue, "null request");
 
     // No servers.
@@ -43,7 +44,7 @@ TEST(TestTcpExchange, factory) {
     string secret = "foobar";
     ASSERT_NO_THROW_LOG(msg.reset(new Message(code, 0, auth, secret, attrs)));
     EXPECT_THROW_MSG(Exchange::create(io_service, msg, 0, servers,
-                                      Exchange::Handler()),
+                                      Exchange::Handler(), PW_PROTO_TCP),
                      BadValue, "no server");
 
     // No handler.
@@ -55,18 +56,73 @@ TEST(TestTcpExchange, factory) {
     ASSERT_TRUE(server);
     servers.push_back(server);
     EXPECT_THROW_MSG(Exchange::create(io_service, msg, 0, servers,
-                                      Exchange::Handler()),
+                                      Exchange::Handler(), PW_PROTO_TCP),
                      BadValue, "null handler");
 
-    // No IO service.
+    // No error (note that the IOservice is unused).
     auto handler = [] (const ExchangePtr) { };
-    EXPECT_THROW_MSG(Exchange::create(io_service, msg, 0, servers, handler),
-                     BadValue, "null IO service");
+    ASSERT_NO_THROW_LOG(exchange = Exchange::create(io_service, msg, 0,
+                                                    servers, handler,
+                                                    PW_PROTO_TCP));
+
+    // Check exchange.
+    ASSERT_TRUE(exchange);
+    // getId returns a random value.
+    EXPECT_EQ(ERROR_RC, exchange->getRC());
+    MessagePtr request = exchange->getRequest();
+    ASSERT_TRUE(request);
+    EXPECT_EQ(request, msg);
+    MessagePtr response = exchange->getResponse();
+    EXPECT_FALSE(response);
+
+    // Verify it is an TCP Exchange.
+    EXPECT_TRUE(boost::dynamic_pointer_cast<TcpExchange>(exchange));
+}
 
-    // No error.
-    io_service.reset(new IOService());
+// Verify the factory with TLS.
+TEST(TestTcpExchange, tlsFactory) {
+    ExchangePtr exchange;
+    IOServicePtr io_service;
+    MessagePtr msg;
+    Servers servers;
+
+    // No message.
+    EXPECT_THROW_MSG(Exchange::create(io_service, msg, 0, servers,
+                                      Exchange::Handler(), PW_PROTO_TLS),
+                     BadValue, "null request");
+
+    // No servers.
+    uint8_t code = PW_ACCOUNTING_REQUEST;
+    vector<uint8_t> auth;
+    AttributesPtr attrs;
+    string secret = "foobar";
+    ASSERT_NO_THROW_LOG(msg.reset(new Message(code, 0, auth, secret, attrs)));
+    EXPECT_THROW_MSG(Exchange::create(io_service, msg, 0, servers,
+                                      Exchange::Handler(), PW_PROTO_TLS),
+                     BadValue, "no server");
+
+    // No handler.
+    ServerPtr server;
+    IOAddress addr("127.0.0.1");
+    TlsContextPtr tls_context;
+    ASSERT_NO_THROW_LOG(TlsContext::configure(tls_context,
+                                              TlsRole::CLIENT,
+                                              TEST_CA_DIR,
+                                              TEST_CA_DIR "/kea-client.crt",
+                                              TEST_CA_DIR "/kea-client.key"));
+    ASSERT_NO_THROW_LOG(server.reset(new Server(addr, 11646, addr, tls_context,
+                                                secret, 0)));
+    ASSERT_TRUE(server);
+    servers.push_back(server);
+    EXPECT_THROW_MSG(Exchange::create(io_service, msg, 0, servers,
+                                      Exchange::Handler(), PW_PROTO_TLS),
+                     BadValue, "null handler");
+
+    // No error (note that the IOservice is unused).
+    auto handler = [] (const ExchangePtr) { };
     ASSERT_NO_THROW_LOG(exchange = Exchange::create(io_service, msg, 0,
-                                                    servers, handler));
+                                                    servers, handler,
+                                                    PW_PROTO_TLS));
 
     // Check exchange.
     ASSERT_TRUE(exchange);
@@ -78,74 +134,66 @@ TEST(TestTcpExchange, factory) {
     MessagePtr response = exchange->getResponse();
     EXPECT_FALSE(response);
 
-    // As a best practice, call any remaining handlers.
-    io_service->stopAndPoll();
+    // Verify it is an TCP Exchange.
+    EXPECT_TRUE(boost::dynamic_pointer_cast<TcpExchange>(exchange));
 }
 
-#if 0
 /// Test Exchange class.
-class TestExchange : public UdpExchange {
+class TestExchange : public TcpExchange {
 public:
     /// Constructor.
     ///
-    TestExchange(const asiolink::IOServicePtr io_service,
-                 const MessagePtr& request,
+    TestExchange(const MessagePtr& request,
                  unsigned maxretries,
                  const Servers& servers,
                  Exchange::Handler handler)
-        : UdpExchange(io_service, request, maxretries, servers, handler) {
+        : TcpExchange(request, maxretries, servers, handler) {
     }
 
     /// Visible members.
     using Exchange::identifier_;
     using Exchange::sync_;
     using Exchange::rc_;
+    using Exchange::sent_;
     using Exchange::received_;
-    using UdpExchange::started_;
-    using UdpExchange::terminated_;
-    using UdpExchange::start_time_;
-    using UdpExchange::socket_;
-    using UdpExchange::ep_;
-    using UdpExchange::timer_;
-    using UdpExchange::server_;
-    using UdpExchange::idx_;
-    using UdpExchange::sent_;
-    using UdpExchange::buffer_;
-    using UdpExchange::size_;
-    using UdpExchange::retries_;
-    using UdpExchange::postponed_;
+    using TcpExchange::start_time_;
+    using TcpExchange::server_;
 
     /// Visible methods.
-    using UdpExchange::buildRequest;
-    using UdpExchange::open;
-    using UdpExchange::receivedHandler;
+    using TcpExchange::buildRequest;
 };
 
 /// Type of shared pointers to test exchange objets.
 typedef boost::shared_ptr<TestExchange> TestExchangePtr;
 
-
 /// Test fixture for testing code of exchange class.
-class ExchangeTest : public radius::test::AttributeTest {
+class TcpExchangeTest : public radius::test::AttributeTest {
 public:
     // Constructor.
-    ExchangeTest()
-        : radius::test::AttributeTest (), io_service_(new IOService()),
+    TcpExchangeTest()
+        : radius::test::AttributeTest (), impl_(RadiusImpl::instance()),
+          io_service_(new IOService()),
           code_(0), secret_("foobar"), addr_("127.0.0.1"),
           port_(11460), timeout_(10), deadtime_(0), maxretries_(3),
           called_(false),
           handler_([this] (const ExchangePtr) { called_ = true; }) {
+        impl_.reset();
+        impl_.setIOService(io_service_);
+        impl_.setIOContext(io_service_);
+        impl_.proto_ = PW_PROTO_TCP;
+        impl_.tcp_client_.reset(new TcpClient(io_service_, false, 0));
     }
 
     // Destructor.
-    virtual ~ExchangeTest() {
+    virtual ~TcpExchangeTest() {
         if (exchange_) {
             exchange_->shutdown();
         }
         servers_.clear();
 
-        // As a best practice, call any remaining handlers before destroying the
-        // IO context.
+        impl_.tcp_client_.reset();
+        // As a best practice, call any remaining handlers before
+        // destroying the IO context.
         io_service_->stopAndPoll();
 
         exchange_.reset();
@@ -175,14 +223,16 @@ public:
 
     // Create exchange.
     void createExchange() {
-        ASSERT_NO_THROW_LOG(exchange_.reset(new TestExchange(io_service_,
-                                                             request_,
+        ASSERT_NO_THROW_LOG(exchange_.reset(new TestExchange(request_,
                                                              maxretries_,
                                                              servers_,
                                                              handler_)));
         ASSERT_TRUE(exchange_);
     }
 
+    /// @brief Radius implementation.
+    RadiusImpl& impl_;
+
     // IO service.
     IOServicePtr io_service_;
 
@@ -230,15 +280,11 @@ public:
 };
 
 // Verify the buildRequest method.
-TEST_F(ExchangeTest, buildRequest) {
+TEST_F(TcpExchangeTest, buildRequest) {
     code_ = PW_ACCESS_REQUEST;
     createRequest();
     addServer();
     createExchange();
-
-    // server_ is required.
-    EXPECT_THROW_MSG(exchange_->buildRequest(), Unexpected, "no server");
-    exchange_->server_ = servers_[0];
     EXPECT_NO_THROW_LOG(exchange_->buildRequest());
 
     // Check the to-be-sent message.
@@ -256,16 +302,12 @@ TEST_F(ExchangeTest, buildRequest) {
 }
 
 // Verify the buildRequest method for accounting and IPv6.
-TEST_F(ExchangeTest, buildRequest6) {
+TEST_F(TcpExchangeTest, buildRequest6) {
     code_ = PW_ACCOUNTING_REQUEST;
     createRequest();
     addr_ = IOAddress("::1");
     addServer();
     createExchange();
-
-    // server_ is required.
-    EXPECT_THROW_MSG(exchange_->buildRequest(), Unexpected, "no server");
-    exchange_->server_ = servers_[0];
     EXPECT_NO_THROW_LOG(exchange_->buildRequest());
 
     // Check the to-be-sent message.
@@ -283,8 +325,9 @@ TEST_F(ExchangeTest, buildRequest6) {
         << "got: " << attrs->toText() << "\n";
 }
 
+#if 0
 // Verify exchange initial state and start.
-TEST_F(ExchangeTest, start) {
+TEST_F(TcpExchangeTest, start) {
     code_ = PW_ACCESS_REQUEST;
     createRequest();
     addServer();
@@ -317,7 +360,7 @@ TEST_F(ExchangeTest, start) {
 }
 
 // Verify open in the initial case.
-TEST_F(ExchangeTest, openInit) {
+TEST_F(TcpExchangeTest, openInit) {
     code_ = PW_ACCESS_REQUEST;
     createRequest();
     addServer();
@@ -354,7 +397,7 @@ TEST_F(ExchangeTest, openInit) {
 }
 
 // Verify open with next server being null.
-TEST_F(ExchangeTest, openNullServer) {
+TEST_F(TcpExchangeTest, openNullServer) {
     code_ = PW_ACCESS_REQUEST;
     createRequest();
     ServerPtr null_server;
@@ -366,7 +409,7 @@ TEST_F(ExchangeTest, openNullServer) {
 }
 
 // Verify open with next server in hold-down state.
-TEST_F(ExchangeTest, openPostpone) {
+TEST_F(TcpExchangeTest, openPostpone) {
     code_ = PW_ACCESS_REQUEST;
     createRequest();
     deadtime_ = 60;
@@ -388,7 +431,7 @@ TEST_F(ExchangeTest, openPostpone) {
 }
 
 // Verify open in second pass with no postponed servers.
-TEST_F(ExchangeTest, openNoPostponed) {
+TEST_F(TcpExchangeTest, openNoPostponed) {
     code_ = PW_ACCESS_REQUEST;
     createRequest();
     addServer();
@@ -416,7 +459,7 @@ TEST_F(ExchangeTest, openNoPostponed) {
 }
 
 // Verify open in second pass with bad postponed index.
-TEST_F(ExchangeTest, openBadPostponed) {
+TEST_F(TcpExchangeTest, openBadPostponed) {
     code_ = PW_ACCESS_REQUEST;
     createRequest();
     addServer();
@@ -435,7 +478,7 @@ TEST_F(ExchangeTest, openBadPostponed) {
 }
 
 // Verify open in second pass with null postponed server.
-TEST_F(ExchangeTest, openNullPostponed) {
+TEST_F(TcpExchangeTest, openNullPostponed) {
     code_ = PW_ACCESS_REQUEST;
     createRequest();
     ServerPtr null_server;
@@ -454,7 +497,7 @@ TEST_F(ExchangeTest, openNullPostponed) {
 }
 
 // Verify open in second pass.
-TEST_F(ExchangeTest, openPostponed) {
+TEST_F(TcpExchangeTest, openPostponed) {
     code_ = PW_ACCESS_REQUEST;
     createRequest();
     addServer();
@@ -494,7 +537,7 @@ TEST_F(ExchangeTest, openPostponed) {
 }
 
 // Verify open with error in send.
-TEST_F(ExchangeTest, openSendError) {
+TEST_F(TcpExchangeTest, openSendError) {
     // Make the request encode to fail with too large message.
     send_attrs_.reset(new Attributes());
     string msg = "too too too too too too too too too too  too too ";
@@ -532,7 +575,7 @@ TEST_F(ExchangeTest, openSendError) {
 }
 
 // Verify open puts on timeout a server on hold-down.
-TEST_F(ExchangeTest, openHoldsDown) {
+TEST_F(TcpExchangeTest, openHoldsDown) {
     code_ = PW_ACCESS_REQUEST;
     createRequest();
     deadtime_ = 60;
@@ -557,7 +600,7 @@ TEST_F(ExchangeTest, openHoldsDown) {
 }
 
 // Verify open tries next server after last retry.
-TEST_F(ExchangeTest, openNextServer) {
+TEST_F(TcpExchangeTest, openNextServer) {
     code_ = PW_ACCESS_REQUEST;
     createRequest();
     addServer();
@@ -586,7 +629,7 @@ TEST_F(ExchangeTest, openNextServer) {
 }
 
 // Verify open terminates after the last retry of the last server.
-TEST_F(ExchangeTest, openLastServer) {
+TEST_F(TcpExchangeTest, openLastServer) {
     code_ = PW_ACCESS_REQUEST;
     createRequest();
     addServer();
@@ -619,7 +662,7 @@ TEST_F(ExchangeTest, openLastServer) {
 }
 
 // Verify open in second pass tries next postponed server after last retry.
-TEST_F(ExchangeTest, openNextPostponedServer) {
+TEST_F(TcpExchangeTest, openNextPostponedServer) {
     code_ = PW_ACCESS_REQUEST;
     createRequest();
     addServer();
@@ -658,7 +701,7 @@ TEST_F(ExchangeTest, openNextPostponedServer) {
 
 // Verify open in second pass terminates after the last retry of the last
 // postponed server.
-TEST_F(ExchangeTest, openLastPostponedServer) {
+TEST_F(TcpExchangeTest, openLastPostponedServer) {
     code_ = PW_ACCESS_REQUEST;
     createRequest();
     addServer();
@@ -694,7 +737,7 @@ TEST_F(ExchangeTest, openLastPostponedServer) {
 }
 
 // Verify open retries.
-TEST_F(ExchangeTest, openRetry) {
+TEST_F(TcpExchangeTest, openRetry) {
     code_ = PW_ACCESS_REQUEST;
     createRequest();
     addServer();
@@ -731,7 +774,7 @@ TEST_F(ExchangeTest, openRetry) {
 }
 
 // Verify open with error in retry.
-TEST_F(ExchangeTest, openRetryError) {
+TEST_F(TcpExchangeTest, openRetryError) {
     code_ = PW_ACCESS_REQUEST;
     createRequest();
     addServer();
@@ -753,7 +796,7 @@ TEST_F(ExchangeTest, openRetryError) {
 }
 
 // Verify receivedHandler with null exchange.
-TEST_F(ExchangeTest, receivedHandlerNull) {
+TEST_F(TcpExchangeTest, receivedHandlerNull) {
     auto no_error = boost::system::error_code();
     EXPECT_THROW_MSG(TestExchange::receivedHandler(TestExchangePtr(), no_error, 0),
                      Unexpected,
@@ -761,7 +804,7 @@ TEST_F(ExchangeTest, receivedHandlerNull) {
 }
 
 // Verify receivedHandler on error.
-TEST_F(ExchangeTest, receivedHandlerError) {
+TEST_F(TcpExchangeTest, receivedHandlerError) {
     code_ = PW_ACCESS_REQUEST;
     createRequest();
     addServer();
@@ -779,7 +822,7 @@ TEST_F(ExchangeTest, receivedHandlerError) {
 }
 
 // Verify receivedHandler removes servers from hold-down.
-TEST_F(ExchangeTest, receivedHandlerNoHoldDown) {
+TEST_F(TcpExchangeTest, receivedHandlerNoHoldDown) {
     code_ = PW_ACCESS_REQUEST;
     createRequest();
     deadtime_ = 60;