From 6e9c747b2d248d58d02f7adf4cd8f0ff38457447 Mon Sep 17 00:00:00 2001 From: Persson-dev Date: Thu, 18 Jul 2024 15:28:01 +0200 Subject: [PATCH] begin packet serialization --- include/blitz/common/Format.h | 36 +++ include/blitz/common/Log.h | 30 ++ include/blitz/protocol/PacketData.h | 49 +++ include/blitz/protocol/PacketFactory.h | 19 ++ include/blitz/protocol/PacketSerializer.h | 19 ++ include/blitz/protocol/PacketVisitor.h | 35 +++ include/blitz/protocol/Packets.h | 121 ++++++++ include/blitz/utils/Test.h | 70 +++++ src/blitz/common/Log.cpp | 35 +++ src/blitz/protocol/PacketFactory.cpp | 37 +++ src/blitz/protocol/PacketSerializer.cpp | 279 ++++++++++++++++++ src/blitz/protocol/PacketVisitor.cpp | 11 + src/blitz/protocol/Packets.cpp | 18 ++ src/blitz/utils/Test.cpp | 14 + test/blitz/protocol/PacketFactory_test.cpp | 15 + test/blitz/protocol/PacketSerializer_test.cpp | 23 ++ xmake.lua | 31 ++ 17 files changed, 842 insertions(+) create mode 100644 include/blitz/common/Format.h create mode 100644 include/blitz/common/Log.h create mode 100644 include/blitz/protocol/PacketData.h create mode 100644 include/blitz/protocol/PacketFactory.h create mode 100644 include/blitz/protocol/PacketSerializer.h create mode 100644 include/blitz/protocol/PacketVisitor.h create mode 100644 include/blitz/protocol/Packets.h create mode 100644 include/blitz/utils/Test.h create mode 100644 src/blitz/common/Log.cpp create mode 100644 src/blitz/protocol/PacketFactory.cpp create mode 100644 src/blitz/protocol/PacketSerializer.cpp create mode 100644 src/blitz/protocol/PacketVisitor.cpp create mode 100644 src/blitz/protocol/Packets.cpp create mode 100644 src/blitz/utils/Test.cpp create mode 100644 test/blitz/protocol/PacketFactory_test.cpp create mode 100644 test/blitz/protocol/PacketSerializer_test.cpp diff --git a/include/blitz/common/Format.h b/include/blitz/common/Format.h new file mode 100644 index 0000000..8b53040 --- /dev/null +++ b/include/blitz/common/Format.h @@ -0,0 +1,36 @@ +#pragma once + +/** + * \file Format.h + * \brief This file contains the definition of the `Format` function. + */ + +#include +#include +#include + +namespace blitz { + +/** + * \brief Formats a string using a format string and variadic arguments. + * + * This function takes a format string and a variable number of arguments and returns a formatted string. + * The format string can contain placeholders that will be replaced by the corresponding arguments. + * + * \param format The format string. + * \param args The variadic arguments to be formatted. + * \return The formatted string. + * \throws std::runtime_error if an error occurs during formatting. + */ +template +std::string Format(const std::string& format, Args... args) { + int size = snprintf(nullptr, 0, format.c_str(), args...) + 1; // Extra space for '\0' + if (size <= 0) { + throw std::runtime_error("Error during formatting."); + } + std::unique_ptr buf(new char[size]); + snprintf(buf.get(), static_cast(size), format.c_str(), args...); + return std::string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside +} + +} // namespace blitz diff --git a/include/blitz/common/Log.h b/include/blitz/common/Log.h new file mode 100644 index 0000000..c9106cd --- /dev/null +++ b/include/blitz/common/Log.h @@ -0,0 +1,30 @@ +#pragma once + +/** + * \file Log.h + * \brief File defining log functions + */ + +#include + +namespace blitz { + +/** + * \brief Logs a normal message. + * \param msg The message to be logged. + */ +void Log(const std::string& msg); + +/** + * \brief Logs a normal message in debug mode. + * \param msg The message to be logged. + */ +void LogD(const std::string& msg); + +/** + * \brief Logs an error message. + * \param err The error message to be logged. + */ +void LogE(const std::string& err); + +} // namespace blitz diff --git a/include/blitz/protocol/PacketData.h b/include/blitz/protocol/PacketData.h new file mode 100644 index 0000000..d213a1c --- /dev/null +++ b/include/blitz/protocol/PacketData.h @@ -0,0 +1,49 @@ +#pragma once + +#include + +namespace blitz { +namespace protocol { +namespace data { + +struct PlayerLogin { + std::string m_PlayerName; +}; + +struct UpdateHealth { + float m_NewHealth; +}; + +struct LoggingSuccess {}; + +struct PlayerDeath {}; + +struct PlayerJoin {}; + +struct PlayerLeave {}; + +struct PlayerStats {}; + +struct PlayerList {}; + +struct ServerConfig {}; + +struct ServerTps {}; + +struct UpdateGameState {}; + +struct KeepAlive {}; + +struct Disconnect {}; + +struct ChatMessage { + std::string m_Text; +}; + +struct PlayerPositionAndRotation {}; + +struct PlayerShoot {}; + +} // namespace data +} // namespace protocol +} // namespace blitz diff --git a/include/blitz/protocol/PacketFactory.h b/include/blitz/protocol/PacketFactory.h new file mode 100644 index 0000000..ae57714 --- /dev/null +++ b/include/blitz/protocol/PacketFactory.h @@ -0,0 +1,19 @@ +#pragma once + +#include +#include + +namespace blitz { +namespace protocol { +namespace PacketFactory { + +template::value>::type> +std::unique_ptr CreatePacket() { + return std::make_unique(); +} + +const std::unique_ptr& CreateReadOnlyPacket(PacketType a_Type); + +} // namespace PacketFactory +} // namespace protocol +} // namespace blitz diff --git a/include/blitz/protocol/PacketSerializer.h b/include/blitz/protocol/PacketSerializer.h new file mode 100644 index 0000000..5b6ab9b --- /dev/null +++ b/include/blitz/protocol/PacketSerializer.h @@ -0,0 +1,19 @@ +#pragma once + +#include +#include + +namespace blitz { +namespace protocol { + +using PacketPtr = std::unique_ptr; + +namespace PacketSerializer { + +Nz::ByteArray Serialize(const Packet& a_Packet); + +std::unique_ptr Deserialize(Nz::ByteArray& a_Data); + +} +} // namespace protocol +} // namespace blitz diff --git a/include/blitz/protocol/PacketVisitor.h b/include/blitz/protocol/PacketVisitor.h new file mode 100644 index 0000000..7ce8ef7 --- /dev/null +++ b/include/blitz/protocol/PacketVisitor.h @@ -0,0 +1,35 @@ +#pragma once + +#include + +namespace blitz { +namespace protocol { + +class PacketVisitor { + protected: + PacketVisitor() {} + virtual ~PacketVisitor() {} + + public: + void Check(const Packet& packet); + + virtual void Visit(const packets::PlayerLogin&) {} + virtual void Visit(const packets::UpdateHealth&) {} + virtual void Visit(const packets::LoggingSuccess&) {} + virtual void Visit(const packets::PlayerDeath&) {} + virtual void Visit(const packets::PlayerJoin&) {} + virtual void Visit(const packets::PlayerLeave&) {} + virtual void Visit(const packets::PlayerList&) {} + virtual void Visit(const packets::PlayerStats&) {} + virtual void Visit(const packets::ServerConfig&) {} + virtual void Visit(const packets::ServerTps&) {} + virtual void Visit(const packets::UpdateGameState&) {} + virtual void Visit(const packets::KeepAlive&) {} + virtual void Visit(const packets::Disconnect&) {} + virtual void Visit(const packets::ChatMessage&) {} + virtual void Visit(const packets::PlayerPositionAndRotation&) {} + virtual void Visit(const packets::PlayerShoot&) {} +}; + +} // namespace protocol +} // namespace blitz diff --git a/include/blitz/protocol/Packets.h b/include/blitz/protocol/Packets.h new file mode 100644 index 0000000..02970b6 --- /dev/null +++ b/include/blitz/protocol/Packets.h @@ -0,0 +1,121 @@ +#pragma once + +#include +#include + +namespace blitz { +namespace protocol { + +class PacketVisitor; + +using PacketID = std::uint8_t; + +enum class PacketType : PacketID { + // client --> server + + PlayerLogin = 0, + UpdateHealth, + + // client <-- server + + LoggingSuccess, + PlayerDeath, + PlayerJoin, + PlayerLeave, + PlayerList, + PlayerStats, + ServerConfig, + ServerTps, + UpdateGameState, + + // client <--> server + + KeepAlive, + Disconnect, + ChatMessage, + PlayerPositionAndRotation, + PlayerShoot, + + PACKET_COUNT +}; + + + + + +class Packet { + public: + virtual PacketType GetType() const = 0; + + virtual void Accept(PacketVisitor& a_Visitor) const = 0; +}; + + + + + +namespace packets { + +/** + * \tparam PT The packet type + * \tparam Data The structure holding the data of the packet + */ +template +class ConcretePacket : public Packet { + public: + using PacketDataType = Data; + + PacketDataType m_Data; + + ConcretePacket(const PacketDataType& a_Data = {}); + + constexpr PacketType GetType() const override { + return PT; + }; + + private: + void Accept(PacketVisitor& a_Visitor) const override; + + friend class PacketVisitor; +}; + + + + + +// define BLITZ_INSTANCIATE_PACKETS +// before including this file +// if you want to instantiate templates +#ifdef BLITZ_INSTANCIATE_PACKETS +#define DeclarePacket(Type) \ + using Type = ConcretePacket; \ + template class ConcretePacket +#else +#define DeclarePacket(Type) using Type = ConcretePacket +#endif + + + + + +DeclarePacket(PlayerLogin); +DeclarePacket(UpdateHealth); +DeclarePacket(LoggingSuccess); +DeclarePacket(PlayerDeath); +DeclarePacket(PlayerJoin); +DeclarePacket(PlayerLeave); +DeclarePacket(PlayerStats); +DeclarePacket(PlayerList); +DeclarePacket(ServerConfig); +DeclarePacket(ServerTps); +DeclarePacket(UpdateGameState); +DeclarePacket(KeepAlive); +DeclarePacket(Disconnect); +DeclarePacket(ChatMessage); +DeclarePacket(PlayerPositionAndRotation); +DeclarePacket(PlayerShoot); + +} // namespace packets + +} // namespace protocol +} // namespace blitz diff --git a/include/blitz/utils/Test.h b/include/blitz/utils/Test.h new file mode 100644 index 0000000..1a56e7e --- /dev/null +++ b/include/blitz/utils/Test.h @@ -0,0 +1,70 @@ +#pragma once + +/** + * \file Test.h + * \brief File containing unit testing utilities + */ + +#include +#include + +namespace blitz { +namespace test { + +/** + * \def BLITZ_TEST_SUCCESSFUL + * \brief Used in tests to indicate that a test was successful + */ +#define BLITZ_TEST_SUCCESSFUL 0 + +/** + * \def BLITZ_TEST_FAILED + * \brief Used in tests to indicate that a test failed + */ +#define BLITZ_TEST_FAILED 1 + +#ifndef __FUNCTION_NAME__ +#ifdef _WIN32 +#define __FUNCTION_NAME__ __FUNCTION__ +#else +#define __FUNCTION_NAME__ __PRETTY_FUNCTION__ +#endif +#endif + +/** + * \def blitz_test_assert + * \param ... The expression to evaluate + * \brief Evaluates the expression and exits the program if not valid. + * \note It works like a basic assert() but also in release mode + */ +#define blitz_test_assert(...) \ + if (!static_cast(__VA_ARGS__)) { \ + blitz::test::LogAssert(#__VA_ARGS__, __FILE__, __LINE__, __FUNCTION_NAME__); \ + std::exit(BLITZ_TEST_FAILED); \ + } + + +/** + * \def blitz_debug_assert + * \param ... The expression to execute + * \brief Assertion without checks in release mode + * \note The expression is always executed. However, in release, no checks are made ! + */ +#ifdef NDEBUG +#define blitz_debug_assert(...) __VA_ARGS__ +#else +#define blitz_debug_assert blitz_test_assert +#endif + + +/** + * \brief Prints an error message associated with a failed assertion + * \param expression The expression that was tested + * \param file The file in which the assertion failed + * \param line The line in the file in which the assertion failed + * \param function The function in which the assertion failed + */ +void LogAssert(const char* expression, const char* file, int line, const char* function); + +} // namespace test +} // namespace blitz diff --git a/src/blitz/common/Log.cpp b/src/blitz/common/Log.cpp new file mode 100644 index 0000000..75c9728 --- /dev/null +++ b/src/blitz/common/Log.cpp @@ -0,0 +1,35 @@ +#include + + + +#ifdef BLITZ_ANDROID_LOGGING +#include +#else +#include +#endif + +namespace blitz { + +void Log(const std::string& msg) { +#ifdef BLITZ_ANDROID_LOGGING + __android_log_print(ANDROID_LOG_INFO, "TRACKERS", "%s", msg.c_str()); +#else + std::cout << msg << "\n"; +#endif +} + +void LogD(const std::string& msg) { +#if !defined(NDEBUG) + Log(msg); +#endif +} + +void LogE(const std::string& err) { +#ifdef BLITZ_ANDROID_LOGGING + __android_log_print(ANDROID_LOG_ERROR, "TRACKERS", "%s", err.c_str()); +#else + std::cerr << err << "\n"; +#endif +} + +} // namespace blitz diff --git a/src/blitz/protocol/PacketFactory.cpp b/src/blitz/protocol/PacketFactory.cpp new file mode 100644 index 0000000..4ad0764 --- /dev/null +++ b/src/blitz/protocol/PacketFactory.cpp @@ -0,0 +1,37 @@ +#include + +#include +#include + +namespace blitz { +namespace protocol { +namespace PacketFactory { + +using PacketCreator = std::function()>; + +static const std::array, static_cast(PacketType::PACKET_COUNT)> Packets = { + std::make_unique(), + std::make_unique(), + std::make_unique(), + std::make_unique(), + std::make_unique(), + std::make_unique(), + std::make_unique(), + std::make_unique(), + std::make_unique(), + std::make_unique(), + std::make_unique(), + std::make_unique(), + std::make_unique(), + std::make_unique(), + std::make_unique(), + std::make_unique(), +}; + +const std::unique_ptr& CreateReadOnlyPacket(PacketType a_Type) { + return Packets[static_cast(a_Type)]; +} + +} // namespace PacketFactory +} // namespace protocol +} // namespace blitz diff --git a/src/blitz/protocol/PacketSerializer.cpp b/src/blitz/protocol/PacketSerializer.cpp new file mode 100644 index 0000000..60350e5 --- /dev/null +++ b/src/blitz/protocol/PacketSerializer.cpp @@ -0,0 +1,279 @@ +#include + +#include +#include +#include + +#include + +namespace blitz { +namespace protocol { + +namespace PacketSerializer { + +#define VisitSerialize(ClassName) \ + void Visit(const ClassName& a_Packet) override { \ + const auto& packetData = a_Packet.m_Data; \ + SerializePacketData(packetData); \ + } \ + \ + void SerializePacketData(const ClassName::PacketDataType& a_Packet) + +#define VisitDeserialize(ClassName) \ + void Visit(const ClassName& a_Packet) override { \ + auto packetPtr = PacketFactory::CreatePacket(); \ + auto& packetData = packetPtr->m_Data; \ + \ + DeserializePacketData(packetData); \ + \ + m_Packet = std::move(packetPtr); \ + } \ + \ + void DeserializePacketData(ClassName::PacketDataType& a_Packet) + + +class Serializer : public PacketVisitor { + private: + Nz::ByteStream& m_Buffer; + + public: + Serializer(Nz::ByteStream& a_Buffer) : m_Buffer(a_Buffer) {} + + void Serialize(const Packet& a_Packet) { + m_Buffer << static_cast(a_Packet.GetType()); + Check(a_Packet); + } + + VisitSerialize(packets::PlayerLogin); + VisitSerialize(packets::UpdateHealth); + VisitSerialize(packets::LoggingSuccess); + VisitSerialize(packets::PlayerDeath); + VisitSerialize(packets::PlayerJoin); + VisitSerialize(packets::PlayerLeave); + VisitSerialize(packets::PlayerList); + VisitSerialize(packets::PlayerStats); + VisitSerialize(packets::ServerConfig); + VisitSerialize(packets::ServerTps); + VisitSerialize(packets::UpdateGameState); + VisitSerialize(packets::KeepAlive); + VisitSerialize(packets::Disconnect); + VisitSerialize(packets::ChatMessage); + VisitSerialize(packets::PlayerPositionAndRotation); + VisitSerialize(packets::PlayerShoot); +}; + +class Deserializer : public PacketVisitor { + private: + Nz::ByteStream& m_Buffer; + PacketPtr m_Packet; + + public: + Deserializer(Nz::ByteStream&& a_Buffer) : m_Buffer(a_Buffer) {} + + bool Deserialize(const PacketPtr& a_Packet) { + try { + Check(*a_Packet.get()); + } catch (std::exception& e) { + return false; + } + return true; + } + + PacketPtr& GetPacket() { + return m_Packet; + } + + VisitDeserialize(packets::PlayerLogin); + VisitDeserialize(packets::UpdateHealth); + VisitDeserialize(packets::LoggingSuccess); + VisitDeserialize(packets::PlayerDeath); + VisitDeserialize(packets::PlayerJoin); + VisitDeserialize(packets::PlayerLeave); + VisitDeserialize(packets::PlayerList); + VisitDeserialize(packets::PlayerStats); + VisitDeserialize(packets::ServerConfig); + VisitDeserialize(packets::ServerTps); + VisitDeserialize(packets::UpdateGameState); + VisitDeserialize(packets::KeepAlive); + VisitDeserialize(packets::Disconnect); + VisitDeserialize(packets::ChatMessage); + VisitDeserialize(packets::PlayerPositionAndRotation); + VisitDeserialize(packets::PlayerShoot); +}; + + + + + +Nz::ByteArray Serialize(const Packet& a_Packet) { + Nz::ByteArray buffer; + Nz::ByteStream stream(&buffer, Nz::OpenMode::Write); + + Serializer serializer(stream); + serializer.Serialize(a_Packet); + + buffer.ShrinkToFit(); + + return buffer; +} + +std::unique_ptr Deserialize(Nz::ByteArray& a_Data) { + Nz::ByteStream stream(&a_Data, Nz::OpenMode::Read); + + PacketID packetId; + stream >> packetId; + + if (packetId >= static_cast(PacketType::PACKET_COUNT)) + return nullptr; + + PacketType packetType = PacketType(packetId); + + // for double-dispatch + const PacketPtr& emptyPacket = PacketFactory::CreateReadOnlyPacket(packetType); + + Deserializer deserializer(std::move(stream)); + if (deserializer.Deserialize(emptyPacket)) { + PacketPtr packet = std::move(deserializer.GetPacket()); + return packet; + } + + return nullptr; +} + + + + + +//--------------------------------------------- +// Packet serializer implementation +//---------------------------------------------- + + + + + +void Serializer::SerializePacketData(const data::PlayerLogin& a_Packet) { + m_Buffer << a_Packet.m_PlayerName; +} + +void Deserializer::DeserializePacketData(data::PlayerLogin& a_Packet) { + m_Buffer >> a_Packet.m_PlayerName; +} + + + + +void Serializer::SerializePacketData(const data::UpdateHealth& a_Packet) { + m_Buffer << a_Packet.m_NewHealth; +} + +void Deserializer::DeserializePacketData(data::UpdateHealth& a_Packet) { + m_Buffer >> a_Packet.m_NewHealth; +} + + + + + +void Serializer::SerializePacketData(const data::LoggingSuccess& a_Packet) {} + +void Deserializer::DeserializePacketData(data::LoggingSuccess& a_Packet) {} + + + + +void Serializer::SerializePacketData(const data::PlayerDeath& a_Packet) {} + +void Deserializer::DeserializePacketData(data::PlayerDeath& a_Packet) {} + + + + +void Serializer::SerializePacketData(const data::PlayerJoin& a_Packet) {} + +void Deserializer::DeserializePacketData(data::PlayerJoin& a_Packet) {} + + + + +void Serializer::SerializePacketData(const data::PlayerLeave& a_Packet) {} + +void Deserializer::DeserializePacketData(data::PlayerLeave& a_Packet) {} + + + + +void Serializer::SerializePacketData(const data::PlayerList& a_Packet) {} + +void Deserializer::DeserializePacketData(data::PlayerList& a_Packet) {} + + + + +void Serializer::SerializePacketData(const data::PlayerStats& a_Packet) {} + +void Deserializer::DeserializePacketData(data::PlayerStats& a_Packet) {} + + + + +void Serializer::SerializePacketData(const data::ServerConfig& a_Packet) {} + +void Deserializer::DeserializePacketData(data::ServerConfig& a_Packet) {} + + + + +void Serializer::SerializePacketData(const data::ServerTps& a_Packet) {} + +void Deserializer::DeserializePacketData(data::ServerTps& a_Packet) {} + + + + +void Serializer::SerializePacketData(const data::UpdateGameState& a_Packet) {} + +void Deserializer::DeserializePacketData(data::UpdateGameState& a_Packet) {} + + + + +void Serializer::SerializePacketData(const data::KeepAlive& a_Packet) {} + +void Deserializer::DeserializePacketData(data::KeepAlive& a_Packet) {} + + + + +void Serializer::SerializePacketData(const data::Disconnect& a_Packet) {} + +void Deserializer::DeserializePacketData(data::Disconnect& a_Packet) {} + + + + +void Serializer::SerializePacketData(const data::ChatMessage& a_Packet) {} + +void Deserializer::DeserializePacketData(data::ChatMessage& a_Packet) {} + + + + +void Serializer::SerializePacketData(const data::PlayerPositionAndRotation& a_Packet) {} + +void Deserializer::DeserializePacketData(data::PlayerPositionAndRotation& a_Packet) {} + + + + +void Serializer::SerializePacketData(const data::PlayerShoot& a_Packet) {} + +void Deserializer::DeserializePacketData(data::PlayerShoot& a_Packet) {} + + + + + +} // namespace PacketSerializer +} // namespace protocol +} // namespace blitz diff --git a/src/blitz/protocol/PacketVisitor.cpp b/src/blitz/protocol/PacketVisitor.cpp new file mode 100644 index 0000000..90f1382 --- /dev/null +++ b/src/blitz/protocol/PacketVisitor.cpp @@ -0,0 +1,11 @@ +#include + +namespace blitz { +namespace protocol { + +void PacketVisitor::Check(const Packet& a_Packet) { + a_Packet.Accept(*this); +} + +} // namespace protocol +} // namespace blitz diff --git a/src/blitz/protocol/Packets.cpp b/src/blitz/protocol/Packets.cpp new file mode 100644 index 0000000..84913b0 --- /dev/null +++ b/src/blitz/protocol/Packets.cpp @@ -0,0 +1,18 @@ +#define BLITZ_INSTANCIATE_PACKETS +#include + +#include + +namespace blitz { +namespace protocol { + +template +packets::ConcretePacket::ConcretePacket(const PacketDataType& a_Data) : m_Data(a_Data) {} + +template +void packets::ConcretePacket::Accept(PacketVisitor& a_Visitor) const { + a_Visitor.Visit(*this); +} + +} // namespace protocol +} // namespace blitz diff --git a/src/blitz/utils/Test.cpp b/src/blitz/utils/Test.cpp new file mode 100644 index 0000000..782c658 --- /dev/null +++ b/src/blitz/utils/Test.cpp @@ -0,0 +1,14 @@ +#include +#include +#include + +namespace blitz { +namespace test { + +void LogAssert(const char* expression, const char* file, int line, const char* function) { + LogE(Format("%s:%i: %s: Assertion failed !", file, line, function)); + LogE(Format(" %i |\t%s;", line, expression)); +} + +} // namespace utils +} // namespace blitz diff --git a/test/blitz/protocol/PacketFactory_test.cpp b/test/blitz/protocol/PacketFactory_test.cpp new file mode 100644 index 0000000..783f3ac --- /dev/null +++ b/test/blitz/protocol/PacketFactory_test.cpp @@ -0,0 +1,15 @@ +#include + +static int Test() { + for (std::size_t i = 0; i < static_cast(blitz::protocol::PacketType::PACKET_COUNT); i++) { + blitz::protocol::PacketType packetType = blitz::protocol::PacketType(i); + + if (blitz::protocol::PacketFactory::CreateReadOnlyPacket(packetType)->GetType() != packetType) + return 1; + } + return 0; +} + +int main() { + return Test(); +} \ No newline at end of file diff --git a/test/blitz/protocol/PacketSerializer_test.cpp b/test/blitz/protocol/PacketSerializer_test.cpp new file mode 100644 index 0000000..ead8b2a --- /dev/null +++ b/test/blitz/protocol/PacketSerializer_test.cpp @@ -0,0 +1,23 @@ +#include + +#include +#include + +static int Test() { + for (std::size_t i = 0; i < static_cast(blitz::protocol::PacketType::PACKET_COUNT); i++) { + const auto& packet = blitz::protocol::PacketFactory::CreateReadOnlyPacket(blitz::protocol::PacketType(i)); + + Nz::ByteArray buffer = blitz::protocol::PacketSerializer::Serialize(*packet.get()); + + blitz::protocol::PacketPtr packet2 = blitz::protocol::PacketSerializer::Deserialize(buffer); + + blitz_test_assert(packet2 != nullptr); + + blitz_test_assert(packet2->GetType() == packet->GetType()); + } + return 0; +} + +int main() { + return Test(); +} \ No newline at end of file diff --git a/xmake.lua b/xmake.lua index 84784ee..7414239 100644 --- a/xmake.lua +++ b/xmake.lua @@ -4,13 +4,44 @@ add_repositories("nazara-repo https://github.com/NazaraEngine/xmake-repo.git") add_requires("nazaraengine", { debug = is_mode("debug") }) set_languages("c++20") +set_warnings("all") + +target("BlitzLib") + set_kind("static") + add_files("src/blitz/**.cpp") + add_includedirs("include") + add_packages("nazaraengine") target("Blitz2") set_kind("binary") add_files("src/*.cpp") add_packages("nazaraengine") + add_includedirs("include") + add_deps("BlitzLib") set_rundir(".") + + +-- Tests were introduced in that version +set_xmakever("2.8.5") + +-- Tests +for _, file in ipairs(os.files("test/**.cpp")) do + local name = path.basename(file) + target(name) + set_kind("binary") + + add_includedirs("include", "test") + add_files(file) + + set_default(false) + + add_deps("BlitzLib") + add_packages("nazaraengine") + + add_tests("compile_and_run") +end + -- -- If you want to known more usage about xmake, please see https://xmake.io --