tests: cover quest framing and restart cooldowns
Some checks failed
build / Linux asan (push) Has been cancelled
build / Linux release (push) Has been cancelled
build / FreeBSD build (push) Has been cancelled

This commit is contained in:
server
2026-04-14 14:38:21 +02:00
parent cf6deb1895
commit 44f9d92e8c
8 changed files with 185 additions and 58 deletions

View File

@@ -5,6 +5,7 @@ endif()
add_executable(metin_smoke_tests
smoke_auth.cpp
${CMAKE_SOURCE_DIR}/src/game/SecureCipher.cpp
${CMAKE_SOURCE_DIR}/src/game/quest_packet.cpp
)
add_executable(metin_login_smoke

View File

@@ -5,9 +5,14 @@
#include <exception>
#include <iostream>
#include <stdexcept>
#include <vector>
#include "common/packet_headers.h"
#include "game/stdafx.h"
#include "common/packet_headers.h"
#include "common/tables.h"
#include "game/packet_structs.h"
#include "game/quest_packet.h"
#include "game/request_cooldown.h"
#include "game/SecureCipher.h"
#include "libthecore/fdwatch.h"
#include "libthecore/signal.h"
@@ -366,6 +371,55 @@ void TestFdwatchSlotReuseAfterDelete()
close(sockets_b[0]);
close(sockets_b[1]);
}
void TestQuestInfoPacketFraming()
{
quest::QuestInfoPacketData data {};
data.quest_index = 77;
data.send_flags = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
data.is_begin = true;
data.title = "Mall reward";
data.clock_name = "Soon";
data.clock_value = 15;
data.counter_name = "Kills";
data.counter_value = 2;
data.icon_file = "d:/icon/test.tga";
const auto quest_packet = quest::BuildQuestInfoPacket(data);
Expect(!quest_packet.empty(), "Quest info packet is empty");
Expect(quest_packet.size() == sizeof(packet_quest_info) + 1 + 31 + 17 + 4 + 17 + 4 + 25,
"Unexpected quest info packet size");
const auto* quest_header = reinterpret_cast<const packet_quest_info*>(quest_packet.data());
Expect(quest_header->header == GC::QUEST_INFO, "Unexpected quest info header");
Expect(quest_header->length == quest_packet.size(), "Quest info packet length does not match payload size");
Expect(quest_packet[sizeof(packet_quest_info)] == 1, "Quest begin flag payload mismatch");
TPacketGCItemGet item_get {};
item_get.header = GC::ITEM_GET;
item_get.length = sizeof(item_get);
item_get.dwItemVnum = 50187;
item_get.bCount = 1;
item_get.bArg = 0;
std::vector<uint8_t> stream = quest_packet;
const auto* item_bytes = reinterpret_cast<const uint8_t*>(&item_get);
stream.insert(stream.end(), item_bytes, item_bytes + sizeof(item_get));
const size_t next_frame_offset = quest_header->length;
Expect(stream.size() >= next_frame_offset + sizeof(item_get), "Combined stream truncated after quest packet");
const auto* next_frame = reinterpret_cast<const TPacketGCItemGet*>(stream.data() + next_frame_offset);
Expect(next_frame->header == GC::ITEM_GET, "Quest info packet left trailing bytes before next frame");
Expect(next_frame->length == sizeof(TPacketGCItemGet), "Item get packet length mismatch after quest packet");
}
void TestRequestCooldownGuard()
{
Expect(!HasRecentRequestCooldown(0, 5, 10), "Initial zero request pulse should not trigger cooldown");
Expect(HasRecentRequestCooldown(95, 100, 10), "Recent request pulse should still be on cooldown");
Expect(!HasRecentRequestCooldown(90, 100, 10), "Cooldown boundary should allow request");
}
}
int main()
@@ -379,6 +433,8 @@ int main()
TestCheckpointBackendMetadata();
TestFdwatchReadAndOneshotWrite();
TestFdwatchSlotReuseAfterDelete();
TestQuestInfoPacketFraming();
TestRequestCooldownGuard();
std::cout << "metin smoke tests passed\n";
return 0;
}