Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4478,6 +4478,59 @@ network_gtest_discover_tests(network_experimental_quic_server_test

message(STATUS "Experimental unit tests enabled (quic_client, quic_server)")

##################################################
# Core Messaging Unit Tests (Issue #966)
##################################################

# Helper macro to create a standard test target
macro(add_network_test TEST_NAME TEST_SOURCE)
add_executable(${TEST_NAME} ${TEST_SOURCE})

target_link_libraries(${TEST_NAME} PRIVATE
network_system
GTest::gtest
GTest::gtest_main
Threads::Threads
)

setup_asio_integration(${TEST_NAME})

if(COMMON_SYSTEM_INCLUDE_DIR)
target_include_directories(${TEST_NAME} PRIVATE ${COMMON_SYSTEM_INCLUDE_DIR})
target_compile_definitions(${TEST_NAME} PRIVATE WITH_COMMON_SYSTEM)
endif()

if(THREAD_SYSTEM_INCLUDE_DIR)
target_include_directories(${TEST_NAME} PRIVATE ${THREAD_SYSTEM_INCLUDE_DIR})
target_compile_definitions(${TEST_NAME} PRIVATE WITH_THREAD_SYSTEM)
endif()

if(LOGGER_SYSTEM_INCLUDE_DIR)
target_include_directories(${TEST_NAME} PRIVATE ${LOGGER_SYSTEM_INCLUDE_DIR})
target_compile_definitions(${TEST_NAME} PRIVATE WITH_LOGGER_SYSTEM)
endif()

set_target_properties(${TEST_NAME} PROPERTIES
CXX_STANDARD 20
CXX_STANDARD_REQUIRED ON
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
)

network_gtest_discover_tests(${TEST_NAME}
DISCOVERY_TIMEOUT 60
)
endmacro()

add_network_test(network_messaging_client_test unit/messaging_client_test.cpp)
add_network_test(network_messaging_server_test unit/messaging_server_test.cpp)
add_network_test(network_messaging_udp_client_test unit/messaging_udp_client_test.cpp)
add_network_test(network_messaging_udp_server_test unit/messaging_udp_server_test.cpp)
# secure_messaging_udp tests excluded: dtls_socket symbols in libs/network-udp, not main library

message(STATUS "Core messaging unit tests enabled (tcp, udp)")

# WebSocket tests already exist: test_messaging_ws_client.cpp, test_messaging_ws_server.cpp

##################################################
# Integration Tests
##################################################
Expand Down
145 changes: 145 additions & 0 deletions tests/unit/messaging_client_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
/*****************************************************************************
BSD 3-Clause License

Copyright (c) 2024-2025, kcenon
All rights reserved.
*****************************************************************************/

/**
* @file messaging_client_test.cpp
* @brief Unit tests for messaging_client class
*
* Tests validate:
* - Construction with client ID
* - Initial state (not running, not connected)
* - Client ID accessor
* - Callback registration
* - Error paths (send before connect, empty host)
* - Stop when not started
* - Interface compliance (i_protocol_client)
*/

#include "internal/core/messaging_client.h"

#include <gtest/gtest.h>

#include <memory>
#include <string>
#include <vector>

using namespace kcenon::network::core;

// ============================================================================
// Construction Tests
// ============================================================================

TEST(MessagingClientTest, ConstructWithClientId)
{
auto client = std::make_shared<messaging_client>("tcp-client-1");

EXPECT_EQ(client->client_id(), "tcp-client-1");
EXPECT_FALSE(client->is_running());
EXPECT_FALSE(client->is_connected());
}

TEST(MessagingClientTest, EmptyClientId)
{
auto client = std::make_shared<messaging_client>("");

EXPECT_TRUE(client->client_id().empty());
EXPECT_FALSE(client->is_running());
}

// ============================================================================
// Error Path Tests
// ============================================================================

TEST(MessagingClientTest, SendBeforeConnectFails)
{
auto client = std::make_shared<messaging_client>("client");

auto result = client->send_packet(std::vector<uint8_t>{0x01, 0x02});
EXPECT_TRUE(result.is_err());
}

TEST(MessagingClientTest, SendViaInterfaceBeforeConnectFails)
{
auto client = std::make_shared<messaging_client>("client");

auto result = client->send(std::vector<uint8_t>{0x01});
EXPECT_TRUE(result.is_err());
}

TEST(MessagingClientTest, StartWithEmptyHostFails)
{
auto client = std::make_shared<messaging_client>("client");

auto result = client->start_client("", 8080);
EXPECT_TRUE(result.is_err());
}

TEST(MessagingClientTest, StopWhenNotStartedSucceeds)
{
auto client = std::make_shared<messaging_client>("client");

auto result = client->stop_client();
EXPECT_TRUE(result.is_ok());
}

TEST(MessagingClientTest, StopViaInterfaceWhenNotStarted)
{
auto client = std::make_shared<messaging_client>("client");

auto result = client->stop();
EXPECT_TRUE(result.is_ok());
}

// ============================================================================
// Callback Tests
// ============================================================================

TEST(MessagingClientTest, SetReceiveCallback)
{
auto client = std::make_shared<messaging_client>("client");
EXPECT_NO_FATAL_FAILURE(
client->set_receive_callback([](const std::vector<uint8_t>&) {}));
}

TEST(MessagingClientTest, SetConnectedCallback)
{
auto client = std::make_shared<messaging_client>("client");
EXPECT_NO_FATAL_FAILURE(
client->set_connected_callback([]() {}));
}

TEST(MessagingClientTest, SetDisconnectedCallback)
{
auto client = std::make_shared<messaging_client>("client");
EXPECT_NO_FATAL_FAILURE(
client->set_disconnected_callback([]() {}));
}

TEST(MessagingClientTest, SetErrorCallback)
{
auto client = std::make_shared<messaging_client>("client");
EXPECT_NO_FATAL_FAILURE(
client->set_error_callback([](std::error_code) {}));
}

TEST(MessagingClientTest, SetNullCallbacks)
{
auto client = std::make_shared<messaging_client>("client");
EXPECT_NO_FATAL_FAILURE(client->set_receive_callback(nullptr));
EXPECT_NO_FATAL_FAILURE(client->set_connected_callback(nullptr));
EXPECT_NO_FATAL_FAILURE(client->set_disconnected_callback(nullptr));
EXPECT_NO_FATAL_FAILURE(client->set_error_callback(nullptr));
}

// ============================================================================
// Destructor Tests
// ============================================================================

TEST(MessagingClientTest, DestructorWhenNotRunning)
{
{ auto client = std::make_shared<messaging_client>("client"); }
}
115 changes: 115 additions & 0 deletions tests/unit/messaging_server_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*****************************************************************************
BSD 3-Clause License

Copyright (c) 2024-2025, kcenon
All rights reserved.
*****************************************************************************/

/**
* @file messaging_server_test.cpp
* @brief Unit tests for messaging_server class
*
* Tests validate:
* - Construction with server ID
* - Initial state (not running)
* - Server ID accessor
* - Callback registration
* - Stop when not started
*/

#include "internal/core/messaging_server.h"

#include <gtest/gtest.h>

#include <memory>
#include <string>
#include <vector>

using namespace kcenon::network::core;

// ============================================================================
// Construction Tests
// ============================================================================

TEST(MessagingServerTest, ConstructWithServerId)
{
auto server = std::make_shared<messaging_server>("tcp-server-1");

EXPECT_EQ(server->server_id(), "tcp-server-1");
EXPECT_FALSE(server->is_running());
}

TEST(MessagingServerTest, EmptyServerId)
{
auto server = std::make_shared<messaging_server>("");

EXPECT_TRUE(server->server_id().empty());
EXPECT_FALSE(server->is_running());
}

// ============================================================================
// Error Path Tests
// ============================================================================

TEST(MessagingServerTest, StopWhenNotStartedSucceeds)
{
auto server = std::make_shared<messaging_server>("server");

auto result = server->stop_server();
EXPECT_TRUE(result.is_ok());
}

// ============================================================================
// Callback Tests
// ============================================================================

TEST(MessagingServerTest, SetConnectionCallback)
{
auto server = std::make_shared<messaging_server>("server");
EXPECT_NO_FATAL_FAILURE(
server->set_connection_callback(
[](std::shared_ptr<kcenon::network::session::messaging_session>) {}));
}

TEST(MessagingServerTest, SetDisconnectionCallback)
{
auto server = std::make_shared<messaging_server>("server");
EXPECT_NO_FATAL_FAILURE(
server->set_disconnection_callback([](const std::string&) {}));
}

TEST(MessagingServerTest, SetReceiveCallback)
{
auto server = std::make_shared<messaging_server>("server");
EXPECT_NO_FATAL_FAILURE(
server->set_receive_callback(
[](std::shared_ptr<kcenon::network::session::messaging_session>,
const std::vector<uint8_t>&) {}));
}

TEST(MessagingServerTest, SetErrorCallback)
{
auto server = std::make_shared<messaging_server>("server");
EXPECT_NO_FATAL_FAILURE(
server->set_error_callback(
[](std::shared_ptr<kcenon::network::session::messaging_session>,
std::error_code) {}));
}

TEST(MessagingServerTest, SetNullCallbacks)
{
auto server = std::make_shared<messaging_server>("server");
EXPECT_NO_FATAL_FAILURE(server->set_connection_callback(nullptr));
EXPECT_NO_FATAL_FAILURE(server->set_disconnection_callback(nullptr));
EXPECT_NO_FATAL_FAILURE(server->set_receive_callback(nullptr));
EXPECT_NO_FATAL_FAILURE(server->set_error_callback(nullptr));
}

// ============================================================================
// Destructor Tests
// ============================================================================

TEST(MessagingServerTest, DestructorWhenNotRunning)
{
{ auto server = std::make_shared<messaging_server>("server"); }
}
Loading
Loading