diff --git a/test/unit/network/MessageSerializerTest.cpp b/test/unit/network/MessageSerializerTest.cpp index 72b5648..6c567ac 100644 --- a/test/unit/network/MessageSerializerTest.cpp +++ b/test/unit/network/MessageSerializerTest.cpp @@ -18,11 +18,12 @@ using namespace UNO::GAME; TEST(MessageSerializerTest, SerializeJoinGameMessage) { JoinGamePayload payload{"Player1"}; - Message message(MessagePayloadType::JOIN_GAME, payload); + Message message(MessageStatus::OK, MessagePayloadType::JOIN_GAME, payload); std::string result = MessageSerializer::serialize(message); nlohmann::json json = nlohmann::json::parse(result); + EXPECT_EQ(json["status_code"], "OK"); EXPECT_EQ(json["payload_type"], "JOIN_GAME"); EXPECT_EQ(json["payload"]["name"], "Player1"); } @@ -30,11 +31,12 @@ TEST(MessageSerializerTest, SerializeJoinGameMessage) TEST(MessageSerializerTest, SerializeJoinGameMessageWithEmptyName) { JoinGamePayload payload{""}; - Message message(MessagePayloadType::JOIN_GAME, payload); + Message message(MessageStatus::OK, MessagePayloadType::JOIN_GAME, payload); std::string result = MessageSerializer::serialize(message); nlohmann::json json = nlohmann::json::parse(result); + EXPECT_EQ(json["status_code"], "OK"); EXPECT_EQ(json["payload_type"], "JOIN_GAME"); EXPECT_EQ(json["payload"]["name"], ""); } @@ -42,11 +44,12 @@ TEST(MessageSerializerTest, SerializeJoinGameMessageWithEmptyName) TEST(MessageSerializerTest, SerializeJoinGameMessageWithSpecialCharacters) { JoinGamePayload payload{"Player<>\"&\n\t"}; - Message message(MessagePayloadType::JOIN_GAME, payload); + Message message(MessageStatus::OK, MessagePayloadType::JOIN_GAME, payload); std::string result = MessageSerializer::serialize(message); nlohmann::json json = nlohmann::json::parse(result); + EXPECT_EQ(json["status_code"], "OK"); EXPECT_EQ(json["payload_type"], "JOIN_GAME"); EXPECT_EQ(json["payload"]["name"], "Player<>\"&\n\t"); } @@ -54,48 +57,80 @@ TEST(MessageSerializerTest, SerializeJoinGameMessageWithSpecialCharacters) TEST(MessageSerializerTest, SerializeStartGameMessage) { StartGamePayload payload{}; - Message message(MessagePayloadType::START_GAME, payload); + Message message(MessageStatus::OK, MessagePayloadType::START_GAME, payload); std::string result = MessageSerializer::serialize(message); nlohmann::json json = nlohmann::json::parse(result); + EXPECT_EQ(json["status_code"], "OK"); EXPECT_EQ(json["payload_type"], "START_GAME"); EXPECT_TRUE(json["payload"].is_null()); } TEST(MessageSerializerTest, SerializeDrawCardMessage) { - DrawCardPayload payload{5}; - Message message(MessagePayloadType::DRAW_CARD, payload); + std::vector cards = {Card(CardColor::RED, CardType::NUM5), Card(CardColor::BLUE, CardType::SKIP)}; + DrawCardPayload payload{5, cards}; + Message message(MessageStatus::OK, MessagePayloadType::DRAW_CARD, payload); std::string result = MessageSerializer::serialize(message); nlohmann::json json = nlohmann::json::parse(result); + EXPECT_EQ(json["status_code"], "OK"); EXPECT_EQ(json["payload_type"], "DRAW_CARD"); EXPECT_EQ(json["payload"]["draw_count"], 5); + EXPECT_TRUE(json["payload"]["cards"].is_array()); + EXPECT_EQ(json["payload"]["cards"].size(), 2); + EXPECT_EQ(json["payload"]["cards"][0]["card_color"], "Red"); + EXPECT_EQ(json["payload"]["cards"][0]["card_type"], "5"); + EXPECT_EQ(json["payload"]["cards"][1]["card_color"], "Blue"); + EXPECT_EQ(json["payload"]["cards"][1]["card_type"], "Skip"); } TEST(MessageSerializerTest, SerializeDrawCardMessageWithZero) { - DrawCardPayload payload{0}; - Message message(MessagePayloadType::DRAW_CARD, payload); + DrawCardPayload payload{0, {}}; + Message message(MessageStatus::OK, MessagePayloadType::DRAW_CARD, payload); std::string result = MessageSerializer::serialize(message); nlohmann::json json = nlohmann::json::parse(result); + EXPECT_EQ(json["status_code"], "OK"); EXPECT_EQ(json["payload_type"], "DRAW_CARD"); EXPECT_EQ(json["payload"]["draw_count"], 0); + EXPECT_TRUE(json["payload"]["cards"].is_array()); + EXPECT_EQ(json["payload"]["cards"].size(), 0); +} + +TEST(MessageSerializerTest, SerializeDrawCardMessageWithMultipleCards) +{ + std::vector cards = {Card(CardColor::RED, CardType::NUM1), + Card(CardColor::GREEN, CardType::NUM2), + Card(CardColor::YELLOW, CardType::REVERSE), + Card(CardColor::BLUE, CardType::DRAW2)}; + DrawCardPayload payload{4, cards}; + Message message(MessageStatus::OK, MessagePayloadType::DRAW_CARD, payload); + + std::string result = MessageSerializer::serialize(message); + nlohmann::json json = nlohmann::json::parse(result); + + EXPECT_EQ(json["status_code"], "OK"); + EXPECT_EQ(json["payload_type"], "DRAW_CARD"); + EXPECT_EQ(json["payload"]["draw_count"], 4); + EXPECT_TRUE(json["payload"]["cards"].is_array()); + EXPECT_EQ(json["payload"]["cards"].size(), 4); } TEST(MessageSerializerTest, SerializePlayCardMessage) { Card card(CardColor::RED, CardType::NUM5); PlayCardPayload payload{card}; - Message message(MessagePayloadType::PLAY_CARD, payload); + Message message(MessageStatus::OK, MessagePayloadType::PLAY_CARD, payload); std::string result = MessageSerializer::serialize(message); nlohmann::json json = nlohmann::json::parse(result); + EXPECT_EQ(json["status_code"], "OK"); EXPECT_EQ(json["payload_type"], "PLAY_CARD"); EXPECT_EQ(json["payload"]["card"]["card_color"], "Red"); EXPECT_EQ(json["payload"]["card"]["card_type"], "5"); @@ -109,11 +144,12 @@ TEST(MessageSerializerTest, SerializePlayCardMessageAllColors) for (const auto &[color, expected] : colors) { Card card(color, CardType::NUM1); PlayCardPayload payload{card}; - Message message(MessagePayloadType::PLAY_CARD, payload); + Message message(MessageStatus::OK, MessagePayloadType::PLAY_CARD, payload); std::string result = MessageSerializer::serialize(message); nlohmann::json json = nlohmann::json::parse(result); + EXPECT_EQ(json["status_code"], "OK"); EXPECT_EQ(json["payload"]["card"]["card_color"], expected); } } @@ -139,11 +175,12 @@ TEST(MessageSerializerTest, SerializePlayCardMessageAllTypes) for (const auto &[type, expected] : types) { Card card(CardColor::RED, type); PlayCardPayload payload{card}; - Message message(MessagePayloadType::PLAY_CARD, payload); + Message message(MessageStatus::OK, MessagePayloadType::PLAY_CARD, payload); std::string result = MessageSerializer::serialize(message); nlohmann::json json = nlohmann::json::parse(result); + EXPECT_EQ(json["status_code"], "OK"); EXPECT_EQ(json["payload"]["card"]["card_type"], expected); } } @@ -159,11 +196,12 @@ TEST(MessageSerializerTest, SerializeInitGameMessage) handCard.draw(Card(CardColor::YELLOW, CardType::REVERSE)); InitGamePayload payload{discardPile, handCard, 2}; - Message message(MessagePayloadType::INIT_GAME, payload); + Message message(MessageStatus::OK, MessagePayloadType::INIT_GAME, payload); std::string result = MessageSerializer::serialize(message); nlohmann::json json = nlohmann::json::parse(result); + EXPECT_EQ(json["status_code"], "OK"); EXPECT_EQ(json["payload_type"], "INIT_GAME"); EXPECT_EQ(json["payload"]["current_player"], 2); EXPECT_TRUE(json["payload"]["discard_pile"].is_array()); @@ -178,11 +216,12 @@ TEST(MessageSerializerTest, SerializeInitGameMessageWithEmptyPiles) HandCard handCard; InitGamePayload payload{discardPile, handCard, 0}; - Message message(MessagePayloadType::INIT_GAME, payload); + Message message(MessageStatus::OK, MessagePayloadType::INIT_GAME, payload); std::string result = MessageSerializer::serialize(message); nlohmann::json json = nlohmann::json::parse(result); + EXPECT_EQ(json["status_code"], "OK"); EXPECT_EQ(json["payload_type"], "INIT_GAME"); EXPECT_EQ(json["payload"]["current_player"], 0); EXPECT_TRUE(json["payload"]["discard_pile"].is_array()); @@ -194,23 +233,82 @@ TEST(MessageSerializerTest, SerializeInitGameMessageWithEmptyPiles) TEST(MessageSerializerTest, SerializeEndGameMessage) { EndGamePayload payload{}; - Message message(MessagePayloadType::END_GAME, payload); + Message message(MessageStatus::OK, MessagePayloadType::END_GAME, payload); std::string result = MessageSerializer::serialize(message); nlohmann::json json = nlohmann::json::parse(result); + EXPECT_EQ(json["status_code"], "OK"); EXPECT_EQ(json["payload_type"], "END_GAME"); EXPECT_TRUE(json["payload"].is_null()); } +// ========== Serialize Status Tests ========== + +TEST(MessageSerializerTest, SerializeMessageWithOKStatus) +{ + JoinGamePayload payload{"TestPlayer"}; + Message message(MessageStatus::OK, MessagePayloadType::JOIN_GAME, payload); + + std::string result = MessageSerializer::serialize(message); + nlohmann::json json = nlohmann::json::parse(result); + + EXPECT_EQ(json["status_code"], "OK"); +} + +TEST(MessageSerializerTest, SerializeMessageWithINVALIDStatus) +{ + Message message(MessageStatus::INVALID, MessagePayloadType::EMPTY, std::monostate{}); + + std::string result = MessageSerializer::serialize(message); + nlohmann::json json = nlohmann::json::parse(result); + + EXPECT_EQ(json["status_code"], "INVALID"); + EXPECT_EQ(json["payload_type"], "EMPTY"); + EXPECT_TRUE(json["payload"].is_null()); +} + +// ========== Deserialize Status Tests ========== + +TEST(MessageSerializerTest, DeserializeMessageWithOKStatus) +{ + std::string json = R"({"status_code":"OK","payload_type":"START_GAME","payload":null})"; + + Message message = MessageSerializer::deserialize(json); + + EXPECT_EQ(message.getMessageStatus(), MessageStatus::OK); +} + +TEST(MessageSerializerTest, DeserializeMessageWithINVALIDStatus) +{ + std::string json = R"({"status_code":"INVALID","payload_type":"EMPTY","payload":null})"; + + Message message = MessageSerializer::deserialize(json); + + EXPECT_EQ(message.getMessageStatus(), MessageStatus::INVALID); + EXPECT_EQ(message.getMessagePayloadType(), MessagePayloadType::EMPTY); +} + +TEST(MessageSerializerTest, RoundTripMessageWithINVALIDStatus) +{ + Message original(MessageStatus::INVALID, MessagePayloadType::EMPTY, std::monostate{}); + + std::string serialized = MessageSerializer::serialize(original); + Message deserialized = MessageSerializer::deserialize(serialized); + + EXPECT_EQ(deserialized.getMessageStatus(), MessageStatus::INVALID); + EXPECT_EQ(deserialized.getMessagePayloadType(), MessagePayloadType::EMPTY); +} + // ========== Deserialize Tests ========== TEST(MessageSerializerTest, DeserializeJoinGameMessage) { - std::string json = R"({"payload_type":"JOIN_GAME","payload":{"name":"Player1"}})"; + std::string json = R"({"status_code":"OK","payload_type":"JOIN_GAME","payload":{"name":"Player1"}})"; Message message = MessageSerializer::deserialize(json); + EXPECT_EQ(message.getMessageStatus(), MessageStatus::OK); EXPECT_EQ(message.getMessagePayloadType(), MessagePayloadType::JOIN_GAME); auto payload = std::get(message.getMessagePayload()); EXPECT_EQ(payload.playerName, "Player1"); @@ -218,10 +316,11 @@ TEST(MessageSerializerTest, DeserializeJoinGameMessage) TEST(MessageSerializerTest, DeserializeJoinGameMessageWithEmptyName) { - std::string json = R"({"payload_type":"JOIN_GAME","payload":{"name":""}})"; + std::string json = R"({"status_code":"OK","payload_type":"JOIN_GAME","payload":{"name":""}})"; Message message = MessageSerializer::deserialize(json); + EXPECT_EQ(message.getMessageStatus(), MessageStatus::OK); EXPECT_EQ(message.getMessagePayloadType(), MessagePayloadType::JOIN_GAME); auto payload = std::get(message.getMessagePayload()); EXPECT_EQ(payload.playerName, ""); @@ -229,30 +328,52 @@ TEST(MessageSerializerTest, DeserializeJoinGameMessageWithEmptyName) TEST(MessageSerializerTest, DeserializeStartGameMessage) { - std::string json = R"({"payload_type":"START_GAME","payload":null})"; + std::string json = R"({"status_code":"OK","payload_type":"START_GAME","payload":null})"; Message message = MessageSerializer::deserialize(json); + EXPECT_EQ(message.getMessageStatus(), MessageStatus::OK); EXPECT_EQ(message.getMessagePayloadType(), MessagePayloadType::START_GAME); } TEST(MessageSerializerTest, DeserializeDrawCardMessage) { - std::string json = R"({"payload_type":"DRAW_CARD","payload":{"draw_count":5}})"; + std::string json = + R"({"status_code":"OK","payload_type":"DRAW_CARD","payload":{"draw_count":5,"cards":[{"card_color":"Red","card_type":"5"},{"card_color":"Blue","card_type":"Skip"}]}})"; Message message = MessageSerializer::deserialize(json); + EXPECT_EQ(message.getMessageStatus(), MessageStatus::OK); EXPECT_EQ(message.getMessagePayloadType(), MessagePayloadType::DRAW_CARD); auto payload = std::get(message.getMessagePayload()); EXPECT_EQ(payload.drawCount, 5); + EXPECT_EQ(payload.cards.size(), 2); + EXPECT_EQ(payload.cards[0].getColor(), CardColor::RED); + EXPECT_EQ(payload.cards[0].getType(), CardType::NUM5); + EXPECT_EQ(payload.cards[1].getColor(), CardColor::BLUE); + EXPECT_EQ(payload.cards[1].getType(), CardType::SKIP); +} + +TEST(MessageSerializerTest, DeserializeDrawCardMessageWithEmptyCards) +{ + std::string json = R"({"status_code":"OK","payload_type":"DRAW_CARD","payload":{"draw_count":0,"cards":[]}})"; + + Message message = MessageSerializer::deserialize(json); + + EXPECT_EQ(message.getMessageStatus(), MessageStatus::OK); + EXPECT_EQ(message.getMessagePayloadType(), MessagePayloadType::DRAW_CARD); + auto payload = std::get(message.getMessagePayload()); + EXPECT_EQ(payload.drawCount, 0); + EXPECT_EQ(payload.cards.size(), 0); } TEST(MessageSerializerTest, DeserializePlayCardMessage) { - std::string json = R"({"payload_type":"PLAY_CARD","payload":{"card":{"card_color":"Red","card_type":"5"}}})"; + std::string json = R"({"status_code":"OK","payload_type":"PLAY_CARD","payload":{"card":{"card_color":"Red","card_type":"5"}}})"; Message message = MessageSerializer::deserialize(json); + EXPECT_EQ(message.getMessageStatus(), MessageStatus::OK); EXPECT_EQ(message.getMessagePayloadType(), MessagePayloadType::PLAY_CARD); auto payload = std::get(message.getMessagePayload()); EXPECT_EQ(payload.card.getColor(), CardColor::RED); @@ -262,6 +383,7 @@ TEST(MessageSerializerTest, DeserializePlayCardMessage) TEST(MessageSerializerTest, DeserializeInitGameMessage) { std::string json = R"({ + "status_code":"OK", "payload_type":"INIT_GAME", "payload":{ "discard_pile":[{"card_color":"Red","card_type":"5"}], @@ -272,6 +394,7 @@ TEST(MessageSerializerTest, DeserializeInitGameMessage) Message message = MessageSerializer::deserialize(json); + EXPECT_EQ(message.getMessageStatus(), MessageStatus::OK); EXPECT_EQ(message.getMessagePayloadType(), MessagePayloadType::INIT_GAME); auto payload = std::get(message.getMessagePayload()); EXPECT_EQ(payload.currentPlayerIndex, 2); @@ -279,10 +402,11 @@ TEST(MessageSerializerTest, DeserializeInitGameMessage) TEST(MessageSerializerTest, DeserializeEndGameMessage) { - std::string json = R"({"payload_type":"END_GAME","payload":null})"; + std::string json = R"({"status_code":"OK","payload_type":"END_GAME","payload":null})"; Message message = MessageSerializer::deserialize(json); + EXPECT_EQ(message.getMessageStatus(), MessageStatus::OK); EXPECT_EQ(message.getMessagePayloadType(), MessagePayloadType::END_GAME); } @@ -291,11 +415,12 @@ TEST(MessageSerializerTest, DeserializeEndGameMessage) TEST(MessageSerializerTest, RoundTripJoinGameMessage) { JoinGamePayload payload{"Player1"}; - Message original(MessagePayloadType::JOIN_GAME, payload); + Message original(MessageStatus::OK, MessagePayloadType::JOIN_GAME, payload); std::string serialized = MessageSerializer::serialize(original); Message deserialized = MessageSerializer::deserialize(serialized); + EXPECT_EQ(deserialized.getMessageStatus(), MessageStatus::OK); EXPECT_EQ(deserialized.getMessagePayloadType(), MessagePayloadType::JOIN_GAME); auto deserializedPayload = std::get(deserialized.getMessagePayload()); EXPECT_EQ(deserializedPayload.playerName, "Player1"); @@ -305,19 +430,45 @@ TEST(MessageSerializerTest, RoundTripAllMessageTypes) { std::vector messages; - messages.emplace_back(MessagePayloadType::JOIN_GAME, JoinGamePayload{"TestPlayer"}); - messages.emplace_back(MessagePayloadType::START_GAME, StartGamePayload{}); - messages.emplace_back(MessagePayloadType::DRAW_CARD, DrawCardPayload{3}); - messages.emplace_back(MessagePayloadType::PLAY_CARD, PlayCardPayload{Card(CardColor::RED, CardType::NUM5)}); - messages.emplace_back(MessagePayloadType::END_GAME, EndGamePayload{}); + messages.emplace_back(MessageStatus::OK, MessagePayloadType::JOIN_GAME, JoinGamePayload{"TestPlayer"}); + messages.emplace_back(MessageStatus::OK, MessagePayloadType::START_GAME, StartGamePayload{}); + messages.emplace_back(MessageStatus::OK, + MessagePayloadType::DRAW_CARD, + DrawCardPayload{3, {Card(CardColor::RED, CardType::NUM1), Card(CardColor::BLUE, CardType::NUM2)}}); + messages.emplace_back(MessageStatus::OK, MessagePayloadType::PLAY_CARD, PlayCardPayload{Card(CardColor::RED, CardType::NUM5)}); + messages.emplace_back(MessageStatus::OK, MessagePayloadType::END_GAME, EndGamePayload{}); for (const auto &original : messages) { std::string serialized = MessageSerializer::serialize(original); Message deserialized = MessageSerializer::deserialize(serialized); + EXPECT_EQ(deserialized.getMessageStatus(), original.getMessageStatus()); EXPECT_EQ(deserialized.getMessagePayloadType(), original.getMessagePayloadType()); } } +TEST(MessageSerializerTest, RoundTripDrawCardMessageWithCards) +{ + std::vector cards = { + Card(CardColor::GREEN, CardType::NUM3), Card(CardColor::YELLOW, CardType::REVERSE), Card(CardColor::RED, CardType::WILD)}; + DrawCardPayload payload{3, cards}; + Message original(MessageStatus::OK, MessagePayloadType::DRAW_CARD, payload); + + std::string serialized = MessageSerializer::serialize(original); + Message deserialized = MessageSerializer::deserialize(serialized); + + EXPECT_EQ(deserialized.getMessageStatus(), MessageStatus::OK); + EXPECT_EQ(deserialized.getMessagePayloadType(), MessagePayloadType::DRAW_CARD); + auto deserializedPayload = std::get(deserialized.getMessagePayload()); + EXPECT_EQ(deserializedPayload.drawCount, 3); + EXPECT_EQ(deserializedPayload.cards.size(), 3); + EXPECT_EQ(deserializedPayload.cards[0].getColor(), CardColor::GREEN); + EXPECT_EQ(deserializedPayload.cards[0].getType(), CardType::NUM3); + EXPECT_EQ(deserializedPayload.cards[1].getColor(), CardColor::YELLOW); + EXPECT_EQ(deserializedPayload.cards[1].getType(), CardType::REVERSE); + EXPECT_EQ(deserializedPayload.cards[2].getColor(), CardColor::RED); + EXPECT_EQ(deserializedPayload.cards[2].getType(), CardType::WILD); +} + // ========== Invalid Input Tests ========== TEST(MessageSerializerTest, DeserializeInvalidJSON) @@ -358,43 +509,79 @@ TEST(MessageSerializerTest, DeserializeBooleanJSON) TEST(MessageSerializerTest, DeserializeMissingPayloadType) { - std::string json = R"({"payload":null})"; + std::string json = R"({"status_code":"OK","payload":null})"; + EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); +} + +TEST(MessageSerializerTest, DeserializeMissingStatusCode) +{ + std::string json = R"({"payload_type":"START_GAME","payload":null})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializeMissingPayload) { - std::string json = R"({"payload_type":"START_GAME"})"; + std::string json = R"({"status_code":"OK","payload_type":"START_GAME"})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializeInvalidPayloadType) { - std::string json = R"({"payload_type":"INVALID_TYPE","payload":null})"; + std::string json = R"({"status_code":"OK","payload_type":"INVALID_TYPE","payload":null})"; + EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); +} + +TEST(MessageSerializerTest, DeserializeInvalidStatusCode) +{ + std::string json = R"({"status_code":"UNKNOWN","payload_type":"START_GAME","payload":null})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializePayloadTypeAsNumber) { - std::string json = R"({"payload_type":123,"payload":null})"; + std::string json = R"({"status_code":"OK","payload_type":123,"payload":null})"; + EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); +} + +TEST(MessageSerializerTest, DeserializeStatusCodeAsNumber) +{ + std::string json = R"({"status_code":200,"payload_type":"START_GAME","payload":null})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializePayloadTypeAsNull) { - std::string json = R"({"payload_type":null,"payload":null})"; + std::string json = R"({"status_code":"OK","payload_type":null,"payload":null})"; + EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); +} + +TEST(MessageSerializerTest, DeserializeStatusCodeAsNull) +{ + std::string json = R"({"status_code":null,"payload_type":"START_GAME","payload":null})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializePayloadTypeAsArray) { - std::string json = R"({"payload_type":[],"payload":null})"; + std::string json = R"({"status_code":"OK","payload_type":[],"payload":null})"; + EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); +} + +TEST(MessageSerializerTest, DeserializeStatusCodeAsArray) +{ + std::string json = R"({"status_code":[],"payload_type":"START_GAME","payload":null})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializePayloadTypeAsObject) { - std::string json = R"({"payload_type":{},"payload":null})"; + std::string json = R"({"status_code":"OK","payload_type":{},"payload":null})"; + EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); +} + +TEST(MessageSerializerTest, DeserializeStatusCodeAsObject) +{ + std::string json = R"({"status_code":{},"payload_type":"START_GAME","payload":null})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } @@ -402,49 +589,49 @@ TEST(MessageSerializerTest, DeserializePayloadTypeAsObject) TEST(MessageSerializerTest, DeserializeJoinGameWithNullPayload) { - std::string json = R"({"payload_type":"JOIN_GAME","payload":null})"; + std::string json = R"({"status_code":"OK","payload_type":"JOIN_GAME","payload":null})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializeJoinGameWithArrayPayload) { - std::string json = R"({"payload_type":"JOIN_GAME","payload":[]})"; + std::string json = R"({"status_code":"OK","payload_type":"JOIN_GAME","payload":[]})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializeJoinGameWithNumberPayload) { - std::string json = R"({"payload_type":"JOIN_GAME","payload":123})"; + std::string json = R"({"status_code":"OK","payload_type":"JOIN_GAME","payload":123})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializeJoinGameWithMissingName) { - std::string json = R"({"payload_type":"JOIN_GAME","payload":{}})"; + std::string json = R"({"status_code":"OK","payload_type":"JOIN_GAME","payload":{}})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializeJoinGameWithNumberName) { - std::string json = R"({"payload_type":"JOIN_GAME","payload":{"name":123}})"; + std::string json = R"({"status_code":"OK","payload_type":"JOIN_GAME","payload":{"name":123}})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializeJoinGameWithNullName) { - std::string json = R"({"payload_type":"JOIN_GAME","payload":{"name":null}})"; + std::string json = R"({"status_code":"OK","payload_type":"JOIN_GAME","payload":{"name":null}})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializeJoinGameWithArrayName) { - std::string json = R"({"payload_type":"JOIN_GAME","payload":{"name":[]}})"; + std::string json = R"({"status_code":"OK","payload_type":"JOIN_GAME","payload":{"name":[]}})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializeJoinGameWithObjectName) { - std::string json = R"({"payload_type":"JOIN_GAME","payload":{"name":{}}})"; + std::string json = R"({"status_code":"OK","payload_type":"JOIN_GAME","payload":{"name":{}}})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } @@ -452,19 +639,19 @@ TEST(MessageSerializerTest, DeserializeJoinGameWithObjectName) TEST(MessageSerializerTest, DeserializeStartGameWithNonNullPayload) { - std::string json = R"({"payload_type":"START_GAME","payload":{}})"; + std::string json = R"({"status_code":"OK","payload_type":"START_GAME","payload":{}})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializeStartGameWithArrayPayload) { - std::string json = R"({"payload_type":"START_GAME","payload":[]})"; + std::string json = R"({"status_code":"OK","payload_type":"START_GAME","payload":[]})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializeStartGameWithStringPayload) { - std::string json = R"({"payload_type":"START_GAME","payload":"test"})"; + std::string json = R"({"status_code":"OK","payload_type":"START_GAME","payload":"test"})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } @@ -472,43 +659,82 @@ TEST(MessageSerializerTest, DeserializeStartGameWithStringPayload) TEST(MessageSerializerTest, DeserializeDrawCardWithNullPayload) { - std::string json = R"({"payload_type":"DRAW_CARD","payload":null})"; + std::string json = R"({"status_code":"OK","payload_type":"DRAW_CARD","payload":null})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializeDrawCardWithArrayPayload) { - std::string json = R"({"payload_type":"DRAW_CARD","payload":[]})"; + std::string json = R"({"status_code":"OK","payload_type":"DRAW_CARD","payload":[]})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializeDrawCardWithMissingDrawCount) { - std::string json = R"({"payload_type":"DRAW_CARD","payload":{}})"; + std::string json = R"({"status_code":"OK","payload_type":"DRAW_CARD","payload":{"cards":[]}})"; + EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); +} + +TEST(MessageSerializerTest, DeserializeDrawCardWithMissingCards) +{ + std::string json = R"({"status_code":"OK","payload_type":"DRAW_CARD","payload":{"draw_count":5}})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializeDrawCardWithStringDrawCount) { - std::string json = R"({"payload_type":"DRAW_CARD","payload":{"draw_count":"5"}})"; + std::string json = R"({"status_code":"OK","payload_type":"DRAW_CARD","payload":{"draw_count":"5"}})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializeDrawCardWithNullDrawCount) { - std::string json = R"({"payload_type":"DRAW_CARD","payload":{"draw_count":null}})"; + std::string json = R"({"status_code":"OK","payload_type":"DRAW_CARD","payload":{"draw_count":null}})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializeDrawCardWithNegativeDrawCount) { - std::string json = R"({"payload_type":"DRAW_CARD","payload":{"draw_count":-5}})"; + std::string json = R"({"status_code":"OK","payload_type":"DRAW_CARD","payload":{"draw_count":-5}})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializeDrawCardWithFloatDrawCount) { - std::string json = R"({"payload_type":"DRAW_CARD","payload":{"draw_count":5.5}})"; + std::string json = R"({"status_code":"OK","payload_type":"DRAW_CARD","payload":{"draw_count":5.5,"cards":[]}})"; + EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); +} + +TEST(MessageSerializerTest, DeserializeDrawCardWithNullCards) +{ + std::string json = R"({"status_code":"OK","payload_type":"DRAW_CARD","payload":{"draw_count":5,"cards":null}})"; + EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); +} + +TEST(MessageSerializerTest, DeserializeDrawCardWithStringCards) +{ + std::string json = R"({"status_code":"OK","payload_type":"DRAW_CARD","payload":{"draw_count":5,"cards":"invalid"}})"; + EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); +} + +TEST(MessageSerializerTest, DeserializeDrawCardWithInvalidCardInArray) +{ + std::string json = + R"({"status_code":"OK","payload_type":"DRAW_CARD","payload":{"draw_count":2,"cards":[{"card_color":"Red","card_type":"5"},"invalid"]}})"; + EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); +} + +TEST(MessageSerializerTest, DeserializeDrawCardWithInvalidCardColor) +{ + std::string json = + R"({"status_code":"OK","payload_type":"DRAW_CARD","payload":{"draw_count":1,"cards":[{"card_color":"Purple","card_type":"5"}]}})"; + EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); +} + +TEST(MessageSerializerTest, DeserializeDrawCardWithInvalidCardType) +{ + std::string json = + R"({"status_code":"OK","payload_type":"DRAW_CARD","payload":{"draw_count":1,"cards":[{"card_color":"Red","card_type":"Invalid"}]}})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } @@ -516,109 +742,109 @@ TEST(MessageSerializerTest, DeserializeDrawCardWithFloatDrawCount) TEST(MessageSerializerTest, DeserializePlayCardWithNullPayload) { - std::string json = R"({"payload_type":"PLAY_CARD","payload":null})"; + std::string json = R"({"status_code":"OK","payload_type":"PLAY_CARD","payload":null})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializePlayCardWithArrayPayload) { - std::string json = R"({"payload_type":"PLAY_CARD","payload":[]})"; + std::string json = R"({"status_code":"OK","payload_type":"PLAY_CARD","payload":[]})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializePlayCardWithMissingCard) { - std::string json = R"({"payload_type":"PLAY_CARD","payload":{}})"; + std::string json = R"({"status_code":"OK","payload_type":"PLAY_CARD","payload":{}})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializePlayCardWithNullCard) { - std::string json = R"({"payload_type":"PLAY_CARD","payload":{"card":null}})"; + std::string json = R"({"status_code":"OK","payload_type":"PLAY_CARD","payload":{"card":null}})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializePlayCardWithArrayCard) { - std::string json = R"({"payload_type":"PLAY_CARD","payload":{"card":[]}})"; + std::string json = R"({"status_code":"OK","payload_type":"PLAY_CARD","payload":{"card":[]}})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializePlayCardWithStringCard) { - std::string json = R"({"payload_type":"PLAY_CARD","payload":{"card":"Red 5"}})"; + std::string json = R"({"status_code":"OK","payload_type":"PLAY_CARD","payload":{"card":"Red 5"}})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializePlayCardWithMissingCardColor) { - std::string json = R"({"payload_type":"PLAY_CARD","payload":{"card":{"card_type":"5"}}})"; + std::string json = R"({"status_code":"OK","payload_type":"PLAY_CARD","payload":{"card":{"card_type":"5"}}})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializePlayCardWithMissingCardType) { - std::string json = R"({"payload_type":"PLAY_CARD","payload":{"card":{"card_color":"Red"}}})"; + std::string json = R"({"status_code":"OK","payload_type":"PLAY_CARD","payload":{"card":{"card_color":"Red"}}})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializePlayCardWithInvalidCardColor) { - std::string json = R"({"payload_type":"PLAY_CARD","payload":{"card":{"card_color":"Purple","card_type":"5"}}})"; + std::string json = R"({"status_code":"OK","payload_type":"PLAY_CARD","payload":{"card":{"card_color":"Purple","card_type":"5"}}})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializePlayCardWithInvalidCardType) { - std::string json = R"({"payload_type":"PLAY_CARD","payload":{"card":{"card_color":"Red","card_type":"Invalid"}}})"; + std::string json = R"({"status_code":"OK","payload_type":"PLAY_CARD","payload":{"card":{"card_color":"Red","card_type":"Invalid"}}})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializePlayCardWithNumberCardColor) { - std::string json = R"({"payload_type":"PLAY_CARD","payload":{"card":{"card_color":123,"card_type":"5"}}})"; + std::string json = R"({"status_code":"OK","payload_type":"PLAY_CARD","payload":{"card":{"card_color":123,"card_type":"5"}}})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializePlayCardWithNumberCardType) { - std::string json = R"({"payload_type":"PLAY_CARD","payload":{"card":{"card_color":"Red","card_type":5}}})"; + std::string json = R"({"status_code":"OK","payload_type":"PLAY_CARD","payload":{"card":{"card_color":"Red","card_type":5}}})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializePlayCardWithNullCardColor) { - std::string json = R"({"payload_type":"PLAY_CARD","payload":{"card":{"card_color":null,"card_type":"5"}}})"; + std::string json = R"({"status_code":"OK","payload_type":"PLAY_CARD","payload":{"card":{"card_color":null,"card_type":"5"}}})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializePlayCardWithNullCardType) { - std::string json = R"({"payload_type":"PLAY_CARD","payload":{"card":{"card_color":"Red","card_type":null}}})"; + std::string json = R"({"status_code":"OK","payload_type":"PLAY_CARD","payload":{"card":{"card_color":"Red","card_type":null}}})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializePlayCardWithEmptyCardColor) { - std::string json = R"({"payload_type":"PLAY_CARD","payload":{"card":{"card_color":"","card_type":"5"}}})"; + std::string json = R"({"status_code":"OK","payload_type":"PLAY_CARD","payload":{"card":{"card_color":"","card_type":"5"}}})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializePlayCardWithEmptyCardType) { - std::string json = R"({"payload_type":"PLAY_CARD","payload":{"card":{"card_color":"Red","card_type":""}}})"; + std::string json = R"({"status_code":"OK","payload_type":"PLAY_CARD","payload":{"card":{"card_color":"Red","card_type":""}}})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializePlayCardWithCaseSensitiveColor) { - std::string json = R"({"payload_type":"PLAY_CARD","payload":{"card":{"card_color":"red","card_type":"5"}}})"; + std::string json = R"({"status_code":"OK","payload_type":"PLAY_CARD","payload":{"card":{"card_color":"red","card_type":"5"}}})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializePlayCardWithCaseSensitiveType) { - std::string json = R"({"payload_type":"PLAY_CARD","payload":{"card":{"card_color":"Red","card_type":"skip"}}})"; + std::string json = R"({"status_code":"OK","payload_type":"PLAY_CARD","payload":{"card":{"card_color":"Red","card_type":"skip"}}})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } @@ -626,105 +852,115 @@ TEST(MessageSerializerTest, DeserializePlayCardWithCaseSensitiveType) TEST(MessageSerializerTest, DeserializeInitGameWithNullPayload) { - std::string json = R"({"payload_type":"INIT_GAME","payload":null})"; + std::string json = R"({"status_code":"OK","payload_type":"INIT_GAME","payload":null})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializeInitGameWithArrayPayload) { - std::string json = R"({"payload_type":"INIT_GAME","payload":[]})"; + std::string json = R"({"status_code":"OK","payload_type":"INIT_GAME","payload":[]})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializeInitGameWithMissingDiscardPile) { - std::string json = R"({"payload_type":"INIT_GAME","payload":{"hand_card":[],"current_player":0}})"; + std::string json = R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"hand_card":[],"current_player":0}})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializeInitGameWithMissingHandCard) { - std::string json = R"({"payload_type":"INIT_GAME","payload":{"discard_pile":[],"current_player":0}})"; + std::string json = R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"discard_pile":[],"current_player":0}})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializeInitGameWithMissingCurrentPlayer) { - std::string json = R"({"payload_type":"INIT_GAME","payload":{"discard_pile":[],"hand_card":[]}})"; + std::string json = R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"discard_pile":[],"hand_card":[]}})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializeInitGameWithNullDiscardPile) { - std::string json = R"({"payload_type":"INIT_GAME","payload":{"discard_pile":null,"hand_card":[],"current_player":0}})"; + std::string json = + R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"discard_pile":null,"hand_card":[],"current_player":0}})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializeInitGameWithNullHandCard) { - std::string json = R"({"payload_type":"INIT_GAME","payload":{"discard_pile":[],"hand_card":null,"current_player":0}})"; + std::string json = + R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"discard_pile":[],"hand_card":null,"current_player":0}})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializeInitGameWithStringDiscardPile) { - std::string json = R"({"payload_type":"INIT_GAME","payload":{"discard_pile":"test","hand_card":[],"current_player":0}})"; + std::string json = + R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"discard_pile":"test","hand_card":[],"current_player":0}})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializeInitGameWithStringHandCard) { - std::string json = R"({"payload_type":"INIT_GAME","payload":{"discard_pile":[],"hand_card":"test","current_player":0}})"; + std::string json = + R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"discard_pile":[],"hand_card":"test","current_player":0}})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializeInitGameWithStringCurrentPlayer) { - std::string json = R"({"payload_type":"INIT_GAME","payload":{"discard_pile":[],"hand_card":[],"current_player":"0"}})"; + 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, DeserializeInitGameWithNullCurrentPlayer) { - std::string json = R"({"payload_type":"INIT_GAME","payload":{"discard_pile":[],"hand_card":[],"current_player":null}})"; + std::string json = + R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"discard_pile":[],"hand_card":[],"current_player":null}})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializeInitGameWithNegativeCurrentPlayer) { - std::string json = R"({"payload_type":"INIT_GAME","payload":{"discard_pile":[],"hand_card":[],"current_player":-1}})"; + std::string json = + R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"discard_pile":[],"hand_card":[],"current_player":-1}})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializeInitGameWithFloatCurrentPlayer) { - std::string json = R"({"payload_type":"INIT_GAME","payload":{"discard_pile":[],"hand_card":[],"current_player":1.5}})"; + std::string json = + R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"discard_pile":[],"hand_card":[],"current_player":1.5}})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializeInitGameWithInvalidCardInDiscardPile) { std::string json = - R"({"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":{"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"({"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":{"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"({"payload_type":"INIT_GAME","payload":{"discard_pile":["string"],"hand_card":[],"current_player":0}})"; + std::string json = + R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"discard_pile":["string"],"hand_card":[],"current_player":0}})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializeInitGameWithNonObjectCardInHandCard) { - std::string json = R"({"payload_type":"INIT_GAME","payload":{"discard_pile":[],"hand_card":[123],"current_player":0}})"; + std::string json = + R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"discard_pile":[],"hand_card":[123],"current_player":0}})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } @@ -732,19 +968,19 @@ TEST(MessageSerializerTest, DeserializeInitGameWithNonObjectCardInHandCard) TEST(MessageSerializerTest, DeserializeEndGameWithNonNullPayload) { - std::string json = R"({"payload_type":"END_GAME","payload":{}})"; + std::string json = R"({"status_code":"OK","payload_type":"END_GAME","payload":{}})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializeEndGameWithArrayPayload) { - std::string json = R"({"payload_type":"END_GAME","payload":[]})"; + std::string json = R"({"status_code":"OK","payload_type":"END_GAME","payload":[]})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializeEndGameWithStringPayload) { - std::string json = R"({"payload_type":"END_GAME","payload":"test"})"; + std::string json = R"({"status_code":"OK","payload_type":"END_GAME","payload":"test"})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } @@ -752,14 +988,14 @@ TEST(MessageSerializerTest, DeserializeEndGameWithStringPayload) TEST(MessageSerializerTest, DeserializeWithExtraFields) { - std::string json = R"({"payload_type":"START_GAME","payload":null,"extra_field":"ignored"})"; + std::string json = R"({"status_code":"OK","payload_type":"START_GAME","payload":null,"extra_field":"ignored"})"; Message message = MessageSerializer::deserialize(json); EXPECT_EQ(message.getMessagePayloadType(), MessagePayloadType::START_GAME); } TEST(MessageSerializerTest, DeserializeJoinGameWithExtraPayloadFields) { - std::string json = R"({"payload_type":"JOIN_GAME","payload":{"name":"Player1","extra":"ignored"}})"; + std::string json = R"({"status_code":"OK","payload_type":"JOIN_GAME","payload":{"name":"Player1","extra":"ignored"}})"; Message message = MessageSerializer::deserialize(json); auto payload = std::get(message.getMessagePayload()); EXPECT_EQ(payload.playerName, "Player1"); @@ -768,7 +1004,7 @@ TEST(MessageSerializerTest, DeserializeJoinGameWithExtraPayloadFields) TEST(MessageSerializerTest, DeserializeVeryLongPlayerName) { std::string longName(10000, 'a'); - nlohmann::json json = {{"payload_type", "JOIN_GAME"}, {"payload", {{"name", longName}}}}; + nlohmann::json json = {{"status_code", "OK"}, {"payload_type", "JOIN_GAME"}, {"payload", {{"name", longName}}}}; Message message = MessageSerializer::deserialize(json.dump()); auto payload = std::get(message.getMessagePayload()); EXPECT_EQ(payload.playerName, longName); @@ -776,7 +1012,7 @@ TEST(MessageSerializerTest, DeserializeVeryLongPlayerName) TEST(MessageSerializerTest, DeserializeLargeDrawCount) { - std::string json = R"({"payload_type":"DRAW_CARD","payload":{"draw_count":2147483647}})"; + std::string json = R"({"status_code":"OK","payload_type":"DRAW_CARD","payload":{"draw_count":2147483647,"cards":[]}})"; Message message = MessageSerializer::deserialize(json); auto payload = std::get(message.getMessagePayload()); EXPECT_EQ(payload.drawCount, 2147483647); @@ -784,15 +1020,16 @@ TEST(MessageSerializerTest, DeserializeLargeDrawCount) TEST(MessageSerializerTest, DeserializeLargeCurrentPlayer) { - std::string json = R"({"payload_type":"INIT_GAME","payload":{"discard_pile":[],"hand_card":[],"current_player":4294967295}})"; - Message message = MessageSerializer::deserialize(json); - auto payload = std::get(message.getMessagePayload()); + std::string json = + R"({"status_code":"OK","payload_type":"INIT_GAME","payload":{"discard_pile":[],"hand_card":[],"current_player":4294967295}})"; + Message message = MessageSerializer::deserialize(json); + auto payload = std::get(message.getMessagePayload()); EXPECT_EQ(payload.currentPlayerIndex, 4294967295); } TEST(MessageSerializerTest, DeserializeUnicodePlayerName) { - std::string json = R"({"payload_type":"JOIN_GAME","payload":{"name":"玩家123🎮"}})"; + std::string json = R"({"status_code":"OK","payload_type":"JOIN_GAME","payload":{"name":"玩家123🎮"}})"; Message message = MessageSerializer::deserialize(json); auto payload = std::get(message.getMessagePayload()); EXPECT_EQ(payload.playerName, "玩家123🎮"); @@ -802,6 +1039,7 @@ TEST(MessageSerializerTest, DeserializeWithWhitespace) { std::string json = R"( { + "status_code": "OK", "payload_type" : "START_GAME" , "payload" : null } @@ -812,7 +1050,7 @@ TEST(MessageSerializerTest, DeserializeWithWhitespace) TEST(MessageSerializerTest, DeserializeCompactJSON) { - std::string json = R"({"payload_type":"START_GAME","payload":null})"; + std::string json = R"({"status_code":"OK","payload_type":"START_GAME","payload":null})"; Message message = MessageSerializer::deserialize(json); EXPECT_EQ(message.getMessagePayloadType(), MessagePayloadType::START_GAME); } @@ -823,9 +1061,10 @@ TEST(MessageSerializerTest, DeserializeAllCardColors) {"Red", CardColor::RED}, {"Blue", CardColor::BLUE}, {"Green", CardColor::GREEN}, {"Yellow", CardColor::YELLOW}}; for (const auto &[colorStr, colorEnum] : colors) { - nlohmann::json json = {{"payload_type", "PLAY_CARD"}, {"payload", {{"card", {{"card_color", colorStr}, {"card_type", "5"}}}}}}; - Message message = MessageSerializer::deserialize(json.dump()); - auto payload = std::get(message.getMessagePayload()); + nlohmann::json json = { + {"status_code", "OK"}, {"payload_type", "PLAY_CARD"}, {"payload", {{"card", {{"card_color", colorStr}, {"card_type", "5"}}}}}}; + Message message = MessageSerializer::deserialize(json.dump()); + auto payload = std::get(message.getMessagePayload()); EXPECT_EQ(payload.card.getColor(), colorEnum); } } @@ -849,9 +1088,10 @@ TEST(MessageSerializerTest, DeserializeAllCardTypes) {"Wild Draw 4", CardType::WILDDRAWFOUR}}; for (const auto &[typeStr, typeEnum] : types) { - nlohmann::json json = {{"payload_type", "PLAY_CARD"}, {"payload", {{"card", {{"card_color", "Red"}, {"card_type", typeStr}}}}}}; - Message message = MessageSerializer::deserialize(json.dump()); - auto payload = std::get(message.getMessagePayload()); + nlohmann::json json = { + {"status_code", "OK"}, {"payload_type", "PLAY_CARD"}, {"payload", {{"card", {{"card_color", "Red"}, {"card_type", typeStr}}}}}}; + Message message = MessageSerializer::deserialize(json.dump()); + auto payload = std::get(message.getMessagePayload()); EXPECT_EQ(payload.card.getType(), typeEnum); } } @@ -861,7 +1101,7 @@ TEST(MessageSerializerTest, DeserializeAllCardTypes) TEST(MessageSerializerTest, DeserializeJSONBomb) { // Test deeply nested JSON (potential DoS) - std::string json = R"({"payload_type":"JOIN_GAME","payload":{"name":"player"}})"; + std::string json = R"({"status_code":"OK","payload_type":"JOIN_GAME","payload":{"name":"player"}})"; for (int i = 0; i < 100; ++i) { json = std::string(R"({"nested":)").append(json).append("}"); } @@ -872,6 +1112,7 @@ TEST(MessageSerializerTest, DeserializeHugeArray) { // Test with a very large array nlohmann::json json; + json["status_code"] = "OK"; json["payload_type"] = "INIT_GAME"; json["payload"]["discard_pile"] = nlohmann::json::array(); for (int i = 0; i < 10000; ++i) { @@ -885,13 +1126,13 @@ TEST(MessageSerializerTest, DeserializeHugeArray) TEST(MessageSerializerTest, DeserializeNullCharacterInString) { - std::string json = R"({"payload_type":"JOIN_GAME","payload":{"name":"Player)" + std::string(1, '\0') + R"(1"}})"; + std::string json = R"({"status_code":"OK","payload_type":"JOIN_GAME","payload":{"name":"Player)" + std::string(1, '\0') + R"(1"}})"; EXPECT_THROW(MessageSerializer::deserialize(json), std::invalid_argument); } TEST(MessageSerializerTest, DeserializeControlCharactersInString) { - std::string json = R"({"payload_type":"JOIN_GAME","payload":{"name":"Player\u0001\u001f"}})"; + std::string json = R"({"status_code":"OK","payload_type":"JOIN_GAME","payload":{"name":"Player\u0001\u001f"}})"; Message message = MessageSerializer::deserialize(json); auto payload = std::get(message.getMessagePayload()); EXPECT_EQ(payload.playerName.length(), 8); @@ -899,7 +1140,7 @@ TEST(MessageSerializerTest, DeserializeControlCharactersInString) TEST(MessageSerializerTest, DeserializeSQLInjectionAttempt) { - std::string json = R"({"payload_type":"JOIN_GAME","payload":{"name":"'; DROP TABLE users; --"}})"; + std::string json = R"({"status_code":"OK","payload_type":"JOIN_GAME","payload":{"name":"'; DROP TABLE users; --"}})"; Message message = MessageSerializer::deserialize(json); auto payload = std::get(message.getMessagePayload()); EXPECT_EQ(payload.playerName, "'; DROP TABLE users; --"); @@ -907,7 +1148,7 @@ TEST(MessageSerializerTest, DeserializeSQLInjectionAttempt) TEST(MessageSerializerTest, DeserializeXSSAttempt) { - std::string json = R"({"payload_type":"JOIN_GAME","payload":{"name":""}})"; + std::string json = R"({"status_code":"OK","payload_type":"JOIN_GAME","payload":{"name":""}})"; Message message = MessageSerializer::deserialize(json); auto payload = std::get(message.getMessagePayload()); EXPECT_EQ(payload.playerName, ""); @@ -915,7 +1156,7 @@ TEST(MessageSerializerTest, DeserializeXSSAttempt) TEST(MessageSerializerTest, DeserializePathTraversalAttempt) { - std::string json = R"({"payload_type":"JOIN_GAME","payload":{"name":"../../etc/passwd"}})"; + std::string json = R"({"status_code":"OK","payload_type":"JOIN_GAME","payload":{"name":"../../etc/passwd"}})"; Message message = MessageSerializer::deserialize(json); auto payload = std::get(message.getMessagePayload()); EXPECT_EQ(payload.playerName, "../../etc/passwd");