mirror of
https://github.com/kierankihn/uno-game.git
synced 2025-12-27 02:13:18 +08:00
test(network): simplify and consolidate NetworkClientTest
- Removed redundant tests and merged similar cases in `NetworkClientTest`. - Updated `Connect` and `Send` tests to streamline functionality. - Enhanced `MessageSerializerTest` to validate `playerId` in `InitGamePayload`.
This commit is contained in:
@@ -195,7 +195,7 @@ TEST(MessageSerializerTest, SerializeInitGameMessage)
|
||||
handCard.draw(Card(CardColor::GREEN, CardType::NUM3));
|
||||
handCard.draw(Card(CardColor::YELLOW, CardType::REVERSE));
|
||||
|
||||
InitGamePayload payload{discardPile, handCard.getCards(), 2};
|
||||
InitGamePayload payload{1, discardPile, handCard.getCards(), 2};
|
||||
Message message(MessageStatus::OK, MessagePayloadType::INIT_GAME, payload);
|
||||
|
||||
std::string result = MessageSerializer::serialize(message);
|
||||
@@ -203,6 +203,7 @@ TEST(MessageSerializerTest, SerializeInitGameMessage)
|
||||
|
||||
EXPECT_EQ(json["status_code"], "OK");
|
||||
EXPECT_EQ(json["payload_type"], "INIT_GAME");
|
||||
EXPECT_EQ(json["payload"]["player_id"], 1);
|
||||
EXPECT_EQ(json["payload"]["current_player"], 2);
|
||||
EXPECT_TRUE(json["payload"]["discard_pile"].is_array());
|
||||
EXPECT_TRUE(json["payload"]["hand_card"].is_array());
|
||||
@@ -215,7 +216,7 @@ TEST(MessageSerializerTest, SerializeInitGameMessageWithEmptyPiles)
|
||||
DiscardPile discardPile;
|
||||
HandCard handCard;
|
||||
|
||||
InitGamePayload payload{discardPile, handCard.getCards(), 0};
|
||||
InitGamePayload payload{0, discardPile, handCard.getCards(), 0};
|
||||
Message message(MessageStatus::OK, MessagePayloadType::INIT_GAME, payload);
|
||||
|
||||
std::string result = MessageSerializer::serialize(message);
|
||||
@@ -223,6 +224,7 @@ TEST(MessageSerializerTest, SerializeInitGameMessageWithEmptyPiles)
|
||||
|
||||
EXPECT_EQ(json["status_code"], "OK");
|
||||
EXPECT_EQ(json["payload_type"], "INIT_GAME");
|
||||
EXPECT_EQ(json["payload"]["player_id"], 0);
|
||||
EXPECT_EQ(json["payload"]["current_player"], 0);
|
||||
EXPECT_TRUE(json["payload"]["discard_pile"].is_array());
|
||||
EXPECT_TRUE(json["payload"]["hand_card"].is_array());
|
||||
@@ -386,6 +388,7 @@ TEST(MessageSerializerTest, DeserializeInitGameMessage)
|
||||
"status_code":"OK",
|
||||
"payload_type":"INIT_GAME",
|
||||
"payload":{
|
||||
"player_id":42,
|
||||
"discard_pile":[{"card_color":"Red","card_type":"5"}],
|
||||
"hand_card":[{"card_color":"Blue","card_type":"Skip"}],
|
||||
"current_player":2
|
||||
@@ -397,6 +400,7 @@ TEST(MessageSerializerTest, DeserializeInitGameMessage)
|
||||
EXPECT_EQ(message.getMessageStatus(), MessageStatus::OK);
|
||||
EXPECT_EQ(message.getMessagePayloadType(), MessagePayloadType::INIT_GAME);
|
||||
auto payload = std::get<InitGamePayload>(message.getMessagePayload());
|
||||
EXPECT_EQ(payload.playerId, 42);
|
||||
EXPECT_EQ(payload.currentPlayerIndex, 2);
|
||||
}
|
||||
|
||||
@@ -862,105 +866,139 @@ TEST(MessageSerializerTest, DeserializeInitGameWithArrayPayload)
|
||||
EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument);
|
||||
}
|
||||
|
||||
TEST(MessageSerializerTest, DeserializeInitGameWithMissingPlayerId)
|
||||
{
|
||||
std::string json = R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"discard_pile":[],"hand_card":[],"current_player":0}})";
|
||||
EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument);
|
||||
}
|
||||
|
||||
TEST(MessageSerializerTest, DeserializeInitGameWithNullPlayerId)
|
||||
{
|
||||
std::string json =
|
||||
R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"player_id":null,"discard_pile":[],"hand_card":[],"current_player":0}})";
|
||||
EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument);
|
||||
}
|
||||
|
||||
TEST(MessageSerializerTest, DeserializeInitGameWithStringPlayerId)
|
||||
{
|
||||
std::string json =
|
||||
R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"player_id":"0","discard_pile":[],"hand_card":[],"current_player":0}})";
|
||||
EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument);
|
||||
}
|
||||
|
||||
TEST(MessageSerializerTest, DeserializeInitGameWithNegativePlayerId)
|
||||
{
|
||||
std::string json =
|
||||
R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"player_id":-1,"discard_pile":[],"hand_card":[],"current_player":0}})";
|
||||
EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument);
|
||||
}
|
||||
|
||||
TEST(MessageSerializerTest, DeserializeInitGameWithFloatPlayerId)
|
||||
{
|
||||
std::string json =
|
||||
R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"player_id":1.5,"discard_pile":[],"hand_card":[],"current_player":0}})";
|
||||
EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument);
|
||||
}
|
||||
|
||||
TEST(MessageSerializerTest, DeserializeInitGameWithMissingDiscardPile)
|
||||
{
|
||||
std::string json = R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"hand_card":[],"current_player":0}})";
|
||||
std::string json = R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"player_id":0,"hand_card":[],"current_player":0}})";
|
||||
EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument);
|
||||
}
|
||||
|
||||
TEST(MessageSerializerTest, DeserializeInitGameWithMissingHandCard)
|
||||
{
|
||||
std::string json = R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"discard_pile":[],"current_player":0}})";
|
||||
std::string json = R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"player_id":0,"discard_pile":[],"current_player":0}})";
|
||||
EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument);
|
||||
}
|
||||
|
||||
TEST(MessageSerializerTest, DeserializeInitGameWithMissingCurrentPlayer)
|
||||
{
|
||||
std::string json = R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"discard_pile":[],"hand_card":[]}})";
|
||||
std::string json = R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"player_id":0,"discard_pile":[],"hand_card":[]}})";
|
||||
EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument);
|
||||
}
|
||||
|
||||
TEST(MessageSerializerTest, DeserializeInitGameWithNullDiscardPile)
|
||||
{
|
||||
std::string json =
|
||||
R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"discard_pile":null,"hand_card":[],"current_player":0}})";
|
||||
R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"player_id":0,"discard_pile":null,"hand_card":[],"current_player":0}})";
|
||||
EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument);
|
||||
}
|
||||
|
||||
TEST(MessageSerializerTest, DeserializeInitGameWithNullHandCard)
|
||||
{
|
||||
std::string json =
|
||||
R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"discard_pile":[],"hand_card":null,"current_player":0}})";
|
||||
R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"player_id":0,"discard_pile":[],"hand_card":null,"current_player":0}})";
|
||||
EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument);
|
||||
}
|
||||
|
||||
TEST(MessageSerializerTest, DeserializeInitGameWithStringDiscardPile)
|
||||
{
|
||||
std::string json =
|
||||
R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"discard_pile":"test","hand_card":[],"current_player":0}})";
|
||||
R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"player_id":0,"discard_pile":"test","hand_card":[],"current_player":0}})";
|
||||
EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument);
|
||||
}
|
||||
|
||||
TEST(MessageSerializerTest, DeserializeInitGameWithStringHandCard)
|
||||
{
|
||||
std::string json =
|
||||
R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"discard_pile":[],"hand_card":"test","current_player":0}})";
|
||||
R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"player_id":0,"discard_pile":[],"hand_card":"test","current_player":0}})";
|
||||
EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument);
|
||||
}
|
||||
|
||||
TEST(MessageSerializerTest, DeserializeInitGameWithStringCurrentPlayer)
|
||||
{
|
||||
std::string json =
|
||||
R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"discard_pile":[],"hand_card":[],"current_player":"0"}})";
|
||||
R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"player_id":0,"discard_pile":[],"hand_card":[],"current_player":"0"}})";
|
||||
EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument);
|
||||
}
|
||||
|
||||
TEST(MessageSerializerTest, DeserializeInitGameWithNullCurrentPlayer)
|
||||
{
|
||||
std::string json =
|
||||
R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"discard_pile":[],"hand_card":[],"current_player":null}})";
|
||||
R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"player_id":0,"discard_pile":[],"hand_card":[],"current_player":null}})";
|
||||
EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument);
|
||||
}
|
||||
|
||||
TEST(MessageSerializerTest, DeserializeInitGameWithNegativeCurrentPlayer)
|
||||
{
|
||||
std::string json =
|
||||
R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"discard_pile":[],"hand_card":[],"current_player":-1}})";
|
||||
R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"player_id":0,"discard_pile":[],"hand_card":[],"current_player":-1}})";
|
||||
EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument);
|
||||
}
|
||||
|
||||
TEST(MessageSerializerTest, DeserializeInitGameWithFloatCurrentPlayer)
|
||||
{
|
||||
std::string json =
|
||||
R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"discard_pile":[],"hand_card":[],"current_player":1.5}})";
|
||||
R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"player_id":0,"discard_pile":[],"hand_card":[],"current_player":1.5}})";
|
||||
EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument);
|
||||
}
|
||||
|
||||
TEST(MessageSerializerTest, DeserializeInitGameWithInvalidCardInDiscardPile)
|
||||
{
|
||||
std::string json =
|
||||
R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"discard_pile":[{"card_color":"Invalid","card_type":"5"}],"hand_card":[],"current_player":0}})";
|
||||
R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"player_id":0,"discard_pile":[{"card_color":"Invalid","card_type":"5"}],"hand_card":[],"current_player":0}})";
|
||||
EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument);
|
||||
}
|
||||
|
||||
TEST(MessageSerializerTest, DeserializeInitGameWithInvalidCardInHandCard)
|
||||
{
|
||||
std::string json =
|
||||
R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"discard_pile":[],"hand_card":[{"card_color":"Red","card_type":"Invalid"}],"current_player":0}})";
|
||||
R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"player_id":0,"discard_pile":[],"hand_card":[{"card_color":"Red","card_type":"Invalid"}],"current_player":0}})";
|
||||
EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument);
|
||||
}
|
||||
|
||||
TEST(MessageSerializerTest, DeserializeInitGameWithNonObjectCardInDiscardPile)
|
||||
{
|
||||
std::string json =
|
||||
R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"discard_pile":["string"],"hand_card":[],"current_player":0}})";
|
||||
R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"player_id":0,"discard_pile":["string"],"hand_card":[],"current_player":0}})";
|
||||
EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument);
|
||||
}
|
||||
|
||||
TEST(MessageSerializerTest, DeserializeInitGameWithNonObjectCardInHandCard)
|
||||
{
|
||||
std::string json =
|
||||
R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"discard_pile":[],"hand_card":[123],"current_player":0}})";
|
||||
R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"player_id":0,"discard_pile":[],"hand_card":[123],"current_player":0}})";
|
||||
EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument);
|
||||
}
|
||||
|
||||
@@ -1021,9 +1059,10 @@ TEST(MessageSerializerTest, DeserializeLargeDrawCount)
|
||||
TEST(MessageSerializerTest, DeserializeLargeCurrentPlayer)
|
||||
{
|
||||
std::string json =
|
||||
R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"discard_pile":[],"hand_card":[],"current_player":4294967295}})";
|
||||
R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"player_id":7,"discard_pile":[],"hand_card":[],"current_player":4294967295}})";
|
||||
Message message = MessageSerializer::deserialize(json);
|
||||
auto payload = std::get<InitGamePayload>(message.getMessagePayload());
|
||||
EXPECT_EQ(payload.playerId, 7);
|
||||
EXPECT_EQ(payload.currentPlayerIndex, 4294967295);
|
||||
}
|
||||
|
||||
@@ -1114,6 +1153,7 @@ TEST(MessageSerializerTest, DeserializeHugeArray)
|
||||
nlohmann::json json;
|
||||
json["status_code"] = "OK";
|
||||
json["payload_type"] = "INIT_GAME";
|
||||
json["payload"]["player_id"] = 0;
|
||||
json["payload"]["discard_pile"] = nlohmann::json::array();
|
||||
for (int i = 0; i < 10000; ++i) {
|
||||
json["payload"]["discard_pile"].push_back({{"card_color", "Red"}, {"card_type", "5"}});
|
||||
@@ -1161,4 +1201,3 @@ TEST(MessageSerializerTest, DeserializePathTraversalAttempt)
|
||||
auto payload = std::get<JoinGamePayload>(message.getMessagePayload());
|
||||
EXPECT_EQ(payload.playerName, "../../etc/passwd");
|
||||
}
|
||||
|
||||
|
||||
@@ -7,15 +7,10 @@
|
||||
|
||||
#include "../../../src/network/NetworkClient.h"
|
||||
|
||||
#include <asio.hpp>
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <gtest/gtest.h>
|
||||
#include <thread>
|
||||
|
||||
using namespace UNO::NETWORK;
|
||||
|
||||
// Helper class to create a simple echo server for testing
|
||||
class SimpleTestServer {
|
||||
private:
|
||||
asio::io_context io_context_;
|
||||
@@ -97,8 +92,6 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
// ========== NetworkClient Constructor Tests ==========
|
||||
|
||||
TEST(NetworkClientTest, ConstructorWithCallback)
|
||||
{
|
||||
auto callback = [](std::string message) {};
|
||||
@@ -106,452 +99,33 @@ TEST(NetworkClientTest, ConstructorWithCallback)
|
||||
EXPECT_NO_THROW({ NetworkClient client(callback); });
|
||||
}
|
||||
|
||||
TEST(NetworkClientTest, ConstructorWithEmptyCallback)
|
||||
{
|
||||
auto callback = [](std::string message) {};
|
||||
|
||||
EXPECT_NO_THROW({ NetworkClient client(callback); });
|
||||
}
|
||||
|
||||
// ========== NetworkClient Connect Tests ==========
|
||||
|
||||
TEST(NetworkClientTest, ConnectToValidServer)
|
||||
TEST(NetworkClientTest, ConnectToHost)
|
||||
{
|
||||
SimpleTestServer server(30001);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
auto callback = [](std::string message) {};
|
||||
NetworkClient client(callback);
|
||||
|
||||
EXPECT_NO_THROW({ client.connect("127.0.0.1", 30001); });
|
||||
}
|
||||
|
||||
TEST(NetworkClientTest, ConnectToLocalhost)
|
||||
{
|
||||
SimpleTestServer server(30002);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
auto callback = [](std::string message) {};
|
||||
NetworkClient client(callback);
|
||||
|
||||
EXPECT_NO_THROW({ client.connect("localhost", 30002); });
|
||||
EXPECT_NO_THROW({ client.connect("localhost", 30001); });
|
||||
}
|
||||
|
||||
TEST(NetworkClientTest, ConnectToInvalidHost)
|
||||
{
|
||||
SimpleTestServer server(30002);
|
||||
|
||||
auto callback = [](std::string message) {};
|
||||
NetworkClient client(callback);
|
||||
|
||||
// Should throw when trying to resolve invalid host
|
||||
EXPECT_THROW({ client.connect("invalid.host.that.does.not.exist.12345", 30003); }, std::exception);
|
||||
EXPECT_THROW({ client.connect("invalid.host.that.does.not.exist.12345", 30002); }, std::exception);
|
||||
}
|
||||
|
||||
TEST(NetworkClientTest, ConnectToUnreachablePort)
|
||||
TEST(NetworkClientTest, SendAfterConnect)
|
||||
{
|
||||
auto callback = [](std::string message) {};
|
||||
NetworkClient client(callback);
|
||||
|
||||
// Should throw when trying to connect to a port with no server
|
||||
EXPECT_THROW({ client.connect("127.0.0.1", 30004); }, std::exception);
|
||||
}
|
||||
|
||||
// ========== NetworkClient Send Tests ==========
|
||||
|
||||
TEST(NetworkClientTest, SendSimpleMessage)
|
||||
{
|
||||
SimpleTestServer server(30005);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
SimpleTestServer server(30003);
|
||||
|
||||
auto callback = [](std::string message) {};
|
||||
NetworkClient client(callback);
|
||||
client.connect("127.0.0.1", 30005);
|
||||
client.connect("localhost", 30003);
|
||||
|
||||
EXPECT_NO_THROW({ client.send("Hello, Server!"); });
|
||||
}
|
||||
|
||||
TEST(NetworkClientTest, SendEmptyMessage)
|
||||
{
|
||||
SimpleTestServer server(30006);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
auto callback = [](std::string message) {};
|
||||
NetworkClient client(callback);
|
||||
client.connect("127.0.0.1", 30006);
|
||||
|
||||
EXPECT_NO_THROW({ client.send(""); });
|
||||
}
|
||||
|
||||
TEST(NetworkClientTest, SendLargeMessage)
|
||||
{
|
||||
SimpleTestServer server(30007);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
auto callback = [](std::string message) {};
|
||||
NetworkClient client(callback);
|
||||
client.connect("127.0.0.1", 30007);
|
||||
|
||||
std::string large_message(1024 * 1024, 'X'); // 1MB message
|
||||
EXPECT_NO_THROW({ client.send(large_message); });
|
||||
}
|
||||
|
||||
TEST(NetworkClientTest, SendMessageWithSpecialCharacters)
|
||||
{
|
||||
SimpleTestServer server(30008);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
auto callback = [](std::string message) {};
|
||||
NetworkClient client(callback);
|
||||
client.connect("127.0.0.1", 30008);
|
||||
|
||||
EXPECT_NO_THROW({ client.send("Special: \n\t\r\"'\\"); });
|
||||
}
|
||||
|
||||
TEST(NetworkClientTest, SendMessageWithUnicode)
|
||||
{
|
||||
SimpleTestServer server(30009);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
auto callback = [](std::string message) {};
|
||||
NetworkClient client(callback);
|
||||
client.connect("127.0.0.1", 30009);
|
||||
|
||||
EXPECT_NO_THROW({ client.send("Unicode: 你好世界 🎮🃏"); });
|
||||
}
|
||||
|
||||
TEST(NetworkClientTest, SendMultipleMessages)
|
||||
{
|
||||
SimpleTestServer server(30010);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
auto callback = [](std::string message) {};
|
||||
NetworkClient client(callback);
|
||||
client.connect("127.0.0.1", 30010);
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
EXPECT_NO_THROW({ client.send("Message " + std::to_string(i)); });
|
||||
}
|
||||
}
|
||||
|
||||
TEST(NetworkClientTest, SendJSONMessage)
|
||||
{
|
||||
SimpleTestServer server(30011);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
auto callback = [](std::string message) {};
|
||||
NetworkClient client(callback);
|
||||
client.connect("127.0.0.1", 30011);
|
||||
|
||||
std::string json_message = R"({"status":"OK","type":"TEST","data":"value"})";
|
||||
EXPECT_NO_THROW({ client.send(json_message); });
|
||||
}
|
||||
|
||||
// ========== NetworkClient Read Tests ==========
|
||||
|
||||
TEST(NetworkClientTest, ReadMessageFromServer)
|
||||
{
|
||||
SimpleTestServer server(30012);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
auto callback = [](std::string message) {};
|
||||
NetworkClient client(callback);
|
||||
client.connect("127.0.0.1", 30012);
|
||||
|
||||
std::string test_message = "Test Message";
|
||||
client.send(test_message);
|
||||
|
||||
std::string received;
|
||||
EXPECT_NO_THROW({ received = client.read(); });
|
||||
|
||||
EXPECT_EQ(received, test_message);
|
||||
}
|
||||
|
||||
TEST(NetworkClientTest, ReadEmptyMessage)
|
||||
{
|
||||
SimpleTestServer server(30013);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
auto callback = [](std::string message) {};
|
||||
NetworkClient client(callback);
|
||||
client.connect("127.0.0.1", 30013);
|
||||
|
||||
client.send("");
|
||||
|
||||
std::string received;
|
||||
EXPECT_NO_THROW({ received = client.read(); });
|
||||
|
||||
EXPECT_EQ(received, "");
|
||||
}
|
||||
|
||||
TEST(NetworkClientTest, ReadLargeMessage)
|
||||
{
|
||||
SimpleTestServer server(30014);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
auto callback = [](std::string message) {};
|
||||
NetworkClient client(callback);
|
||||
client.connect("127.0.0.1", 30014);
|
||||
|
||||
std::string large_message(100 * 1024, 'L'); // 100KB
|
||||
client.send(large_message);
|
||||
|
||||
std::string received;
|
||||
EXPECT_NO_THROW({ received = client.read(); });
|
||||
|
||||
EXPECT_EQ(received, large_message);
|
||||
}
|
||||
|
||||
TEST(NetworkClientTest, ReadMessageWithSpecialCharacters)
|
||||
{
|
||||
SimpleTestServer server(30015);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
auto callback = [](std::string message) {};
|
||||
NetworkClient client(callback);
|
||||
client.connect("127.0.0.1", 30015);
|
||||
|
||||
std::string special_message = "Special: \n\t\r\"'\\";
|
||||
client.send(special_message);
|
||||
|
||||
std::string received = client.read();
|
||||
EXPECT_EQ(received, special_message);
|
||||
}
|
||||
|
||||
TEST(NetworkClientTest, ReadMessageWithUnicode)
|
||||
{
|
||||
SimpleTestServer server(30016);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
auto callback = [](std::string message) {};
|
||||
NetworkClient client(callback);
|
||||
client.connect("127.0.0.1", 30016);
|
||||
|
||||
std::string unicode_message = "Unicode: 你好世界 🎮";
|
||||
client.send(unicode_message);
|
||||
|
||||
std::string received = client.read();
|
||||
EXPECT_EQ(received, unicode_message);
|
||||
}
|
||||
|
||||
TEST(NetworkClientTest, ReadMultipleMessages)
|
||||
{
|
||||
SimpleTestServer server(30017);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
auto callback = [](std::string message) {};
|
||||
NetworkClient client(callback);
|
||||
client.connect("127.0.0.1", 30017);
|
||||
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
std::string test_message = "Message " + std::to_string(i);
|
||||
client.send(test_message);
|
||||
|
||||
std::string received = client.read();
|
||||
EXPECT_EQ(received, test_message);
|
||||
}
|
||||
}
|
||||
|
||||
// ========== Round-trip Tests ==========
|
||||
|
||||
TEST(NetworkClientTest, RoundTripSimpleMessage)
|
||||
{
|
||||
SimpleTestServer server(30018);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
auto callback = [](std::string message) {};
|
||||
NetworkClient client(callback);
|
||||
client.connect("127.0.0.1", 30018);
|
||||
|
||||
std::string original = "Round trip test";
|
||||
client.send(original);
|
||||
std::string received = client.read();
|
||||
|
||||
EXPECT_EQ(original, received);
|
||||
}
|
||||
|
||||
TEST(NetworkClientTest, RoundTripJSONMessage)
|
||||
{
|
||||
SimpleTestServer server(30019);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
auto callback = [](std::string message) {};
|
||||
NetworkClient client(callback);
|
||||
client.connect("127.0.0.1", 30019);
|
||||
|
||||
std::string json = R"({"player":"Alice","action":"DRAW_CARD","count":3})";
|
||||
client.send(json);
|
||||
std::string received = client.read();
|
||||
|
||||
EXPECT_EQ(json, received);
|
||||
}
|
||||
|
||||
TEST(NetworkClientTest, RoundTripMultipleMessages)
|
||||
{
|
||||
SimpleTestServer server(30020);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
auto callback = [](std::string message) {};
|
||||
NetworkClient client(callback);
|
||||
client.connect("127.0.0.1", 30020);
|
||||
|
||||
std::vector<std::string> messages = {"First message", "Second message with 123", "Third: special chars \n\t", "Fourth: 你好", ""};
|
||||
|
||||
for (const auto &msg : messages) {
|
||||
client.send(msg);
|
||||
std::string received = client.read();
|
||||
EXPECT_EQ(msg, received);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(NetworkClientTest, RoundTripLargeMessages)
|
||||
{
|
||||
SimpleTestServer server(30021);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
auto callback = [](std::string message) {};
|
||||
NetworkClient client(callback);
|
||||
client.connect("127.0.0.1", 30021);
|
||||
|
||||
for (size_t size : {1024, 10240, 102400}) {
|
||||
std::string large_msg(size, 'Z');
|
||||
client.send(large_msg);
|
||||
std::string received = client.read();
|
||||
EXPECT_EQ(large_msg.size(), received.size());
|
||||
EXPECT_EQ(large_msg, received);
|
||||
}
|
||||
}
|
||||
|
||||
// ========== Edge Cases ==========
|
||||
|
||||
TEST(NetworkClientTest, SendBeforeConnect)
|
||||
{
|
||||
auto callback = [](std::string message) {};
|
||||
NetworkClient client(callback);
|
||||
|
||||
// Should throw because not connected
|
||||
EXPECT_THROW({ client.send("Message before connect"); }, std::exception);
|
||||
}
|
||||
|
||||
TEST(NetworkClientTest, ReadBeforeConnect)
|
||||
{
|
||||
auto callback = [](std::string message) {};
|
||||
NetworkClient client(callback);
|
||||
|
||||
// Should throw because not connected
|
||||
EXPECT_THROW({ client.read(); }, std::exception);
|
||||
}
|
||||
|
||||
TEST(NetworkClientTest, MultipleConnectAttempts)
|
||||
{
|
||||
SimpleTestServer server1(30022);
|
||||
SimpleTestServer server2(30023);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
auto callback = [](std::string message) {};
|
||||
NetworkClient client(callback);
|
||||
|
||||
// First connection should succeed
|
||||
EXPECT_NO_THROW({ client.connect("127.0.0.1", 30022); });
|
||||
|
||||
// Second connection attempt should also work (replaces first connection)
|
||||
EXPECT_NO_THROW({ client.connect("127.0.0.1", 30023); });
|
||||
}
|
||||
|
||||
TEST(NetworkClientTest, RapidSendAndRead)
|
||||
{
|
||||
SimpleTestServer server(30025);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
auto callback = [](std::string message) {};
|
||||
NetworkClient client(callback);
|
||||
client.connect("127.0.0.1", 30025);
|
||||
|
||||
// Rapidly send and read 100 messages
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
std::string msg = std::to_string(i);
|
||||
client.send(msg);
|
||||
std::string received = client.read();
|
||||
EXPECT_EQ(msg, received);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(NetworkClientTest, VeryLongMessageContent)
|
||||
{
|
||||
SimpleTestServer server(30026);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
auto callback = [](std::string message) {};
|
||||
NetworkClient client(callback);
|
||||
client.connect("127.0.0.1", 30026);
|
||||
|
||||
// Create a complex message with various characters
|
||||
std::string complex_message;
|
||||
for (int i = 0; i < 1000; ++i) {
|
||||
complex_message += "Line " + std::to_string(i) + ": Hello World! 你好世界 🎮\n";
|
||||
}
|
||||
|
||||
client.send(complex_message);
|
||||
std::string received = client.read();
|
||||
EXPECT_EQ(complex_message, received);
|
||||
}
|
||||
|
||||
TEST(NetworkClientTest, SendBinaryData)
|
||||
{
|
||||
SimpleTestServer server(30027);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
auto callback = [](std::string message) {};
|
||||
NetworkClient client(callback);
|
||||
client.connect("127.0.0.1", 30027);
|
||||
|
||||
// Create binary data with all byte values
|
||||
std::string binary_data;
|
||||
for (int i = 1; i < 256; ++i) { // Skip 0 to avoid null terminator issues
|
||||
binary_data += static_cast<char>(i);
|
||||
}
|
||||
|
||||
client.send(binary_data);
|
||||
std::string received = client.read();
|
||||
EXPECT_EQ(binary_data.size(), received.size());
|
||||
EXPECT_EQ(binary_data, received);
|
||||
}
|
||||
|
||||
TEST(NetworkClientTest, AlternatingReadAndWrite)
|
||||
{
|
||||
SimpleTestServer server(30028);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
auto callback = [](std::string message) {};
|
||||
NetworkClient client(callback);
|
||||
client.connect("127.0.0.1", 30028);
|
||||
|
||||
for (int i = 0; i < 20; ++i) {
|
||||
if (i % 2 == 0) {
|
||||
client.send("Message " + std::to_string(i));
|
||||
}
|
||||
else {
|
||||
std::string received = client.read();
|
||||
EXPECT_FALSE(received.empty());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ========== Protocol Compliance Tests ==========
|
||||
|
||||
TEST(NetworkClientTest, MessageLengthPrefixCorrect)
|
||||
{
|
||||
SimpleTestServer server(30029);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
auto callback = [](std::string message) {};
|
||||
NetworkClient client(callback);
|
||||
client.connect("127.0.0.1", 30029);
|
||||
|
||||
// Test various message lengths
|
||||
for (size_t len : {0, 1, 10, 100, 1000, 10000}) {
|
||||
std::string msg(len, 'A');
|
||||
client.send(msg);
|
||||
std::string received = client.read();
|
||||
EXPECT_EQ(len, received.size());
|
||||
EXPECT_EQ(msg, received);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -445,7 +445,7 @@ TEST(SessionTest, SessionCreation)
|
||||
asio::io_context io_context;
|
||||
asio::ip::tcp::socket socket(io_context);
|
||||
|
||||
EXPECT_NO_THROW({ Session session(0, std::move(socket)); });
|
||||
EXPECT_NO_THROW({ Session session(std::move(socket)); });
|
||||
}
|
||||
|
||||
TEST(SessionTest, SessionStartWithCallback)
|
||||
@@ -453,13 +453,57 @@ TEST(SessionTest, SessionStartWithCallback)
|
||||
asio::io_context io_context;
|
||||
asio::ip::tcp::socket socket(io_context);
|
||||
|
||||
auto session = std::make_shared<Session>(0, std::move(socket));
|
||||
auto session = std::make_shared<Session>(std::move(socket));
|
||||
|
||||
auto callback = [](size_t player_id, std::string message) {};
|
||||
auto callback = [](std::string message) {};
|
||||
|
||||
EXPECT_NO_THROW({ session->start(callback); });
|
||||
}
|
||||
|
||||
TEST(SessionTest, SessionInvokesCallbackOnIncomingMessage)
|
||||
{
|
||||
asio::io_context server_context;
|
||||
asio::ip::tcp::acceptor acceptor(server_context, asio::ip::tcp::endpoint(asio::ip::tcp::v4(), 0));
|
||||
uint16_t port = acceptor.local_endpoint().port();
|
||||
|
||||
std::atomic<bool> callback_called{false};
|
||||
std::string received_message;
|
||||
std::mutex message_mutex;
|
||||
|
||||
acceptor.async_accept([&](const asio::error_code &ec, asio::ip::tcp::socket socket) {
|
||||
if (!ec) {
|
||||
auto session = std::make_shared<Session>(std::move(socket));
|
||||
session->start([&](std::string message) {
|
||||
std::lock_guard<std::mutex> lock(message_mutex);
|
||||
callback_called = true;
|
||||
received_message = std::move(message);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
std::thread server_thread([&]() { server_context.run(); });
|
||||
|
||||
asio::io_context client_context;
|
||||
asio::ip::tcp::socket client_socket(client_context);
|
||||
client_socket.connect(asio::ip::tcp::endpoint(asio::ip::address::from_string("127.0.0.1"), port));
|
||||
|
||||
std::string message = "Hello Session";
|
||||
size_t length = message.size();
|
||||
asio::write(client_socket, asio::buffer(&length, sizeof(length)));
|
||||
asio::write(client_socket, asio::buffer(message));
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
server_context.stop();
|
||||
if (server_thread.joinable()) {
|
||||
server_thread.join();
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(message_mutex);
|
||||
EXPECT_TRUE(callback_called);
|
||||
EXPECT_EQ(received_message, message);
|
||||
}
|
||||
|
||||
// ========== Concurrent Access Tests ==========
|
||||
|
||||
TEST(NetworkServerTest, ConcurrentSendToSamePlayer)
|
||||
|
||||
Reference in New Issue
Block a user