Init: Migrate SimpleRemoter (Since v1.3.1) to Gitea

This commit is contained in:
yuanyuanxiang
2026-04-19 19:55:01 +02:00
commit 5a325a202b
744 changed files with 235562 additions and 0 deletions

View File

@@ -0,0 +1,660 @@
/**
* @file PacketFragmentTest.cpp
* @brief 粘包/分包处理测试
*
* 测试覆盖:
* - 完整包接收和解析
* - 分包(不完整包)处理
* - 粘包(多个包粘在一起)处理
* - 混合场景测试
* - 边界条件处理
*/
#include <gtest/gtest.h>
#include <cstring>
#include <cstdint>
#include <vector>
#include <queue>
#include <functional>
// ============================================
// 协议常量
// ============================================
const int FLAG_LENGTH = 8;
const int HDR_LENGTH = 16; // FLAG(8) + PackedLen(4) + OrigLen(4)
// ============================================
// 简化版 CBuffer测试专用
// ============================================
class TestBuffer {
public:
TestBuffer() {}
void WriteBuffer(const uint8_t* data, size_t len) {
m_data.insert(m_data.end(), data, data + len);
}
size_t ReadBuffer(uint8_t* dst, size_t len) {
size_t toRead = std::min(len, m_data.size());
if (toRead > 0) {
memcpy(dst, m_data.data(), toRead);
m_data.erase(m_data.begin(), m_data.begin() + toRead);
}
return toRead;
}
void Skip(size_t len) {
size_t toSkip = std::min(len, m_data.size());
m_data.erase(m_data.begin(), m_data.begin() + toSkip);
}
size_t GetBufferLength() const {
return m_data.size();
}
const uint8_t* GetBuffer(size_t pos = 0) const {
if (pos >= m_data.size()) return nullptr;
return m_data.data() + pos;
}
bool CopyBuffer(uint8_t* dst, size_t pos, size_t len) const {
if (pos + len > m_data.size()) return false;
memcpy(dst, m_data.data() + pos, len);
return true;
}
void Clear() {
m_data.clear();
}
private:
std::vector<uint8_t> m_data;
};
// ============================================
// 数据包构建辅助函数
// ============================================
#pragma pack(push, 1)
struct PacketHeader {
char flag[FLAG_LENGTH];
uint32_t packedLength; // 包含头部的总长度
uint32_t originalLength; // 原始数据长度
};
#pragma pack(pop)
std::vector<uint8_t> BuildPacket(const std::vector<uint8_t>& payload, uint8_t key = 0x42) {
std::vector<uint8_t> packet(HDR_LENGTH + payload.size());
PacketHeader* hdr = reinterpret_cast<PacketHeader*>(packet.data());
memcpy(hdr->flag, "HELL", 4);
hdr->flag[6] = key;
hdr->flag[7] = ~key;
hdr->packedLength = static_cast<uint32_t>(HDR_LENGTH + payload.size());
hdr->originalLength = static_cast<uint32_t>(payload.size());
if (!payload.empty()) {
memcpy(packet.data() + HDR_LENGTH, payload.data(), payload.size());
}
return packet;
}
std::vector<uint8_t> BuildPacketWithData(size_t dataSize, uint8_t fillByte = 0xAA) {
std::vector<uint8_t> payload(dataSize, fillByte);
return BuildPacket(payload);
}
// ============================================
// 粘包/分包处理器(模拟 OnServerReceiving 逻辑)
// ============================================
class PacketProcessor {
public:
using PacketCallback = std::function<void(const std::vector<uint8_t>&)>;
PacketProcessor(PacketCallback callback) : m_callback(callback) {}
// 接收数据(模拟网络接收)
void OnReceive(const uint8_t* data, size_t len) {
m_buffer.WriteBuffer(data, len);
ProcessBuffer();
}
// 获取待处理的字节数
size_t GetPendingBytes() const {
return m_buffer.GetBufferLength();
}
// 获取已处理的包数量
size_t GetProcessedCount() const {
return m_processedCount;
}
private:
void ProcessBuffer() {
while (m_buffer.GetBufferLength() >= HDR_LENGTH) {
// 验证头部
const uint8_t* buf = m_buffer.GetBuffer();
if (memcmp(buf, "HELL", 4) != 0) {
// 无效头部,跳过一个字节重试
m_buffer.Skip(1);
continue;
}
// 读取包长度
uint32_t packedLength;
m_buffer.CopyBuffer(reinterpret_cast<uint8_t*>(&packedLength),
FLAG_LENGTH, sizeof(uint32_t));
// 检查长度有效性
if (packedLength < HDR_LENGTH || packedLength > 100 * 1024 * 1024) {
// 无效长度,跳过头部
m_buffer.Skip(FLAG_LENGTH);
continue;
}
// 检查包是否完整
if (m_buffer.GetBufferLength() < packedLength) {
// 不完整,等待更多数据
break;
}
// 读取完整包
std::vector<uint8_t> packet(packedLength);
m_buffer.ReadBuffer(packet.data(), packedLength);
// 提取 payload
std::vector<uint8_t> payload(packet.begin() + HDR_LENGTH, packet.end());
m_callback(payload);
m_processedCount++;
}
}
TestBuffer m_buffer;
PacketCallback m_callback;
size_t m_processedCount = 0;
};
// ============================================
// 完整包接收测试
// ============================================
class CompletePacketTest : public ::testing::Test {
protected:
std::vector<std::vector<uint8_t>> receivedPackets;
void SetUp() override {
receivedPackets.clear();
}
PacketProcessor::PacketCallback GetCallback() {
return [this](const std::vector<uint8_t>& payload) {
receivedPackets.push_back(payload);
};
}
};
TEST_F(CompletePacketTest, SinglePacket) {
PacketProcessor processor(GetCallback());
std::vector<uint8_t> payload = {0x01, 0x02, 0x03, 0x04};
auto packet = BuildPacket(payload);
processor.OnReceive(packet.data(), packet.size());
ASSERT_EQ(receivedPackets.size(), 1u);
EXPECT_EQ(receivedPackets[0], payload);
EXPECT_EQ(processor.GetPendingBytes(), 0u);
}
TEST_F(CompletePacketTest, EmptyPayload) {
PacketProcessor processor(GetCallback());
std::vector<uint8_t> payload;
auto packet = BuildPacket(payload);
processor.OnReceive(packet.data(), packet.size());
ASSERT_EQ(receivedPackets.size(), 1u);
EXPECT_TRUE(receivedPackets[0].empty());
}
TEST_F(CompletePacketTest, LargePayload) {
PacketProcessor processor(GetCallback());
std::vector<uint8_t> payload(64 * 1024); // 64 KB
for (size_t i = 0; i < payload.size(); ++i) {
payload[i] = static_cast<uint8_t>(i & 0xFF);
}
auto packet = BuildPacket(payload);
processor.OnReceive(packet.data(), packet.size());
ASSERT_EQ(receivedPackets.size(), 1u);
EXPECT_EQ(receivedPackets[0], payload);
}
// ============================================
// 分包(不完整包)测试
// ============================================
class FragmentedPacketTest : public ::testing::Test {
protected:
std::vector<std::vector<uint8_t>> receivedPackets;
PacketProcessor::PacketCallback GetCallback() {
return [this](const std::vector<uint8_t>& payload) {
receivedPackets.push_back(payload);
};
}
};
TEST_F(FragmentedPacketTest, TwoFragments) {
PacketProcessor processor(GetCallback());
std::vector<uint8_t> payload = {0xAA, 0xBB, 0xCC, 0xDD};
auto packet = BuildPacket(payload);
// 分两次发送
size_t half = packet.size() / 2;
processor.OnReceive(packet.data(), half);
EXPECT_EQ(receivedPackets.size(), 0u);
EXPECT_EQ(processor.GetPendingBytes(), half);
processor.OnReceive(packet.data() + half, packet.size() - half);
ASSERT_EQ(receivedPackets.size(), 1u);
EXPECT_EQ(receivedPackets[0], payload);
}
TEST_F(FragmentedPacketTest, ManyFragments) {
PacketProcessor processor(GetCallback());
std::vector<uint8_t> payload(100);
for (size_t i = 0; i < payload.size(); ++i) {
payload[i] = static_cast<uint8_t>(i);
}
auto packet = BuildPacket(payload);
// 每次发送 10 字节
for (size_t i = 0; i < packet.size(); i += 10) {
size_t len = std::min(size_t(10), packet.size() - i);
processor.OnReceive(packet.data() + i, len);
}
ASSERT_EQ(receivedPackets.size(), 1u);
EXPECT_EQ(receivedPackets[0], payload);
}
TEST_F(FragmentedPacketTest, OnlyHeader) {
PacketProcessor processor(GetCallback());
std::vector<uint8_t> payload = {0x01, 0x02};
auto packet = BuildPacket(payload);
// 只发送头部
processor.OnReceive(packet.data(), HDR_LENGTH);
EXPECT_EQ(receivedPackets.size(), 0u);
EXPECT_EQ(processor.GetPendingBytes(), HDR_LENGTH);
// 发送剩余数据
processor.OnReceive(packet.data() + HDR_LENGTH, packet.size() - HDR_LENGTH);
ASSERT_EQ(receivedPackets.size(), 1u);
}
TEST_F(FragmentedPacketTest, PartialHeader) {
PacketProcessor processor(GetCallback());
std::vector<uint8_t> payload = {0xFF};
auto packet = BuildPacket(payload);
// 发送不完整的头部
processor.OnReceive(packet.data(), 4); // 只有 "HELL"
EXPECT_EQ(receivedPackets.size(), 0u);
// 发送剩余部分
processor.OnReceive(packet.data() + 4, packet.size() - 4);
ASSERT_EQ(receivedPackets.size(), 1u);
}
// ============================================
// 粘包测试
// ============================================
class StickyPacketTest : public ::testing::Test {
protected:
std::vector<std::vector<uint8_t>> receivedPackets;
PacketProcessor::PacketCallback GetCallback() {
return [this](const std::vector<uint8_t>& payload) {
receivedPackets.push_back(payload);
};
}
};
TEST_F(StickyPacketTest, TwoPacketsStuckTogether) {
PacketProcessor processor(GetCallback());
std::vector<uint8_t> payload1 = {0x11, 0x22};
std::vector<uint8_t> payload2 = {0x33, 0x44, 0x55};
auto packet1 = BuildPacket(payload1);
auto packet2 = BuildPacket(payload2);
// 合并两个包
std::vector<uint8_t> combined;
combined.insert(combined.end(), packet1.begin(), packet1.end());
combined.insert(combined.end(), packet2.begin(), packet2.end());
processor.OnReceive(combined.data(), combined.size());
ASSERT_EQ(receivedPackets.size(), 2u);
EXPECT_EQ(receivedPackets[0], payload1);
EXPECT_EQ(receivedPackets[1], payload2);
}
TEST_F(StickyPacketTest, ThreePacketsStuckTogether) {
PacketProcessor processor(GetCallback());
std::vector<uint8_t> payload1 = {0x01};
std::vector<uint8_t> payload2 = {0x02, 0x03};
std::vector<uint8_t> payload3 = {0x04, 0x05, 0x06};
auto packet1 = BuildPacket(payload1);
auto packet2 = BuildPacket(payload2);
auto packet3 = BuildPacket(payload3);
// 合并三个包
std::vector<uint8_t> combined;
combined.insert(combined.end(), packet1.begin(), packet1.end());
combined.insert(combined.end(), packet2.begin(), packet2.end());
combined.insert(combined.end(), packet3.begin(), packet3.end());
processor.OnReceive(combined.data(), combined.size());
ASSERT_EQ(receivedPackets.size(), 3u);
EXPECT_EQ(receivedPackets[0], payload1);
EXPECT_EQ(receivedPackets[1], payload2);
EXPECT_EQ(receivedPackets[2], payload3);
}
TEST_F(StickyPacketTest, ManyPacketsStuckTogether) {
PacketProcessor processor(GetCallback());
std::vector<uint8_t> combined;
const int numPackets = 100;
for (int i = 0; i < numPackets; ++i) {
std::vector<uint8_t> payload(i % 10 + 1, static_cast<uint8_t>(i));
auto packet = BuildPacket(payload);
combined.insert(combined.end(), packet.begin(), packet.end());
}
processor.OnReceive(combined.data(), combined.size());
EXPECT_EQ(receivedPackets.size(), numPackets);
}
// ============================================
// 混合场景测试
// ============================================
class MixedScenarioTest : public ::testing::Test {
protected:
std::vector<std::vector<uint8_t>> receivedPackets;
PacketProcessor::PacketCallback GetCallback() {
return [this](const std::vector<uint8_t>& payload) {
receivedPackets.push_back(payload);
};
}
};
TEST_F(MixedScenarioTest, OneAndHalfPackets) {
PacketProcessor processor(GetCallback());
std::vector<uint8_t> payload1 = {0xAA, 0xBB};
std::vector<uint8_t> payload2 = {0xCC, 0xDD, 0xEE, 0xFF};
auto packet1 = BuildPacket(payload1);
auto packet2 = BuildPacket(payload2);
// 发送完整包1 + 半个包2
std::vector<uint8_t> firstSend;
firstSend.insert(firstSend.end(), packet1.begin(), packet1.end());
firstSend.insert(firstSend.end(), packet2.begin(), packet2.begin() + packet2.size() / 2);
processor.OnReceive(firstSend.data(), firstSend.size());
EXPECT_EQ(receivedPackets.size(), 1u); // 只处理了包1
// 发送剩余的半个包2
processor.OnReceive(packet2.data() + packet2.size() / 2, packet2.size() - packet2.size() / 2);
ASSERT_EQ(receivedPackets.size(), 2u);
EXPECT_EQ(receivedPackets[0], payload1);
EXPECT_EQ(receivedPackets[1], payload2);
}
TEST_F(MixedScenarioTest, HalfPacketThenOneAndHalf) {
PacketProcessor processor(GetCallback());
std::vector<uint8_t> payload1 = {0x11};
std::vector<uint8_t> payload2 = {0x22, 0x33};
auto packet1 = BuildPacket(payload1);
auto packet2 = BuildPacket(payload2);
// 发送半个包1
processor.OnReceive(packet1.data(), packet1.size() / 2);
EXPECT_EQ(receivedPackets.size(), 0u);
// 发送剩余包1 + 完整包2
std::vector<uint8_t> secondSend;
secondSend.insert(secondSend.end(), packet1.begin() + packet1.size() / 2, packet1.end());
secondSend.insert(secondSend.end(), packet2.begin(), packet2.end());
processor.OnReceive(secondSend.data(), secondSend.size());
ASSERT_EQ(receivedPackets.size(), 2u);
}
TEST_F(MixedScenarioTest, RandomChunkSizes) {
PacketProcessor processor(GetCallback());
// 准备多个包
std::vector<std::vector<uint8_t>> payloads;
std::vector<uint8_t> allData;
for (int i = 0; i < 10; ++i) {
std::vector<uint8_t> payload(i * 5 + 10, static_cast<uint8_t>(i));
payloads.push_back(payload);
auto packet = BuildPacket(payload);
allData.insert(allData.end(), packet.begin(), packet.end());
}
// 使用"随机"大小的块发送
size_t chunkSizes[] = {1, 7, 15, 16, 17, 31, 32, 33, 64, 128};
size_t pos = 0;
size_t chunkIdx = 0;
while (pos < allData.size()) {
size_t chunkSize = chunkSizes[chunkIdx % (sizeof(chunkSizes) / sizeof(chunkSizes[0]))];
size_t len = std::min(chunkSize, allData.size() - pos);
processor.OnReceive(allData.data() + pos, len);
pos += len;
chunkIdx++;
}
ASSERT_EQ(receivedPackets.size(), payloads.size());
for (size_t i = 0; i < payloads.size(); ++i) {
EXPECT_EQ(receivedPackets[i], payloads[i]) << "Mismatch at packet " << i;
}
}
// ============================================
// 边界条件测试
// ============================================
class PacketBoundaryTest : public ::testing::Test {
protected:
std::vector<std::vector<uint8_t>> receivedPackets;
PacketProcessor::PacketCallback GetCallback() {
return [this](const std::vector<uint8_t>& payload) {
receivedPackets.push_back(payload);
};
}
};
TEST_F(PacketBoundaryTest, ExactlyHdrLength) {
PacketProcessor processor(GetCallback());
// 只有头部,无 payload
std::vector<uint8_t> packet(HDR_LENGTH);
PacketHeader* hdr = reinterpret_cast<PacketHeader*>(packet.data());
memcpy(hdr->flag, "HELL", 4);
hdr->flag[6] = 0x42;
hdr->flag[7] = ~0x42;
hdr->packedLength = HDR_LENGTH;
hdr->originalLength = 0;
processor.OnReceive(packet.data(), packet.size());
ASSERT_EQ(receivedPackets.size(), 1u);
EXPECT_TRUE(receivedPackets[0].empty());
}
TEST_F(PacketBoundaryTest, SingleBytePayload) {
PacketProcessor processor(GetCallback());
std::vector<uint8_t> payload = {0xFF};
auto packet = BuildPacket(payload);
processor.OnReceive(packet.data(), packet.size());
ASSERT_EQ(receivedPackets.size(), 1u);
EXPECT_EQ(receivedPackets[0].size(), 1u);
EXPECT_EQ(receivedPackets[0][0], 0xFF);
}
TEST_F(PacketBoundaryTest, ByteByByteReceive) {
PacketProcessor processor(GetCallback());
std::vector<uint8_t> payload = {0x12, 0x34, 0x56};
auto packet = BuildPacket(payload);
// 每次接收 1 字节
for (size_t i = 0; i < packet.size(); ++i) {
processor.OnReceive(packet.data() + i, 1);
}
ASSERT_EQ(receivedPackets.size(), 1u);
EXPECT_EQ(receivedPackets[0], payload);
}
// ============================================
// 数据完整性测试
// ============================================
class DataIntegrityTest : public ::testing::Test {
protected:
std::vector<std::vector<uint8_t>> receivedPackets;
PacketProcessor::PacketCallback GetCallback() {
return [this](const std::vector<uint8_t>& payload) {
receivedPackets.push_back(payload);
};
}
};
TEST_F(DataIntegrityTest, BinaryData) {
PacketProcessor processor(GetCallback());
// 包含所有字节值的 payload
std::vector<uint8_t> payload(256);
for (int i = 0; i < 256; ++i) {
payload[i] = static_cast<uint8_t>(i);
}
auto packet = BuildPacket(payload);
processor.OnReceive(packet.data(), packet.size());
ASSERT_EQ(receivedPackets.size(), 1u);
EXPECT_EQ(receivedPackets[0], payload);
}
TEST_F(DataIntegrityTest, AllZeros) {
PacketProcessor processor(GetCallback());
std::vector<uint8_t> payload(100, 0x00);
auto packet = BuildPacket(payload);
processor.OnReceive(packet.data(), packet.size());
ASSERT_EQ(receivedPackets.size(), 1u);
for (uint8_t b : receivedPackets[0]) {
EXPECT_EQ(b, 0x00);
}
}
TEST_F(DataIntegrityTest, AllOnes) {
PacketProcessor processor(GetCallback());
std::vector<uint8_t> payload(100, 0xFF);
auto packet = BuildPacket(payload);
processor.OnReceive(packet.data(), packet.size());
ASSERT_EQ(receivedPackets.size(), 1u);
for (uint8_t b : receivedPackets[0]) {
EXPECT_EQ(b, 0xFF);
}
}
// ============================================
// 性能相关测试
// ============================================
class PacketPerformanceTest : public ::testing::Test {
protected:
size_t packetCount = 0;
PacketProcessor::PacketCallback GetCallback() {
return [this](const std::vector<uint8_t>& payload) {
packetCount++;
};
}
};
TEST_F(PacketPerformanceTest, ManySmallPackets) {
PacketProcessor processor(GetCallback());
const int numPackets = 10000;
std::vector<uint8_t> allData;
for (int i = 0; i < numPackets; ++i) {
std::vector<uint8_t> payload = {static_cast<uint8_t>(i & 0xFF)};
auto packet = BuildPacket(payload);
allData.insert(allData.end(), packet.begin(), packet.end());
}
processor.OnReceive(allData.data(), allData.size());
EXPECT_EQ(packetCount, numPackets);
}
TEST_F(PacketPerformanceTest, LargePacketInSmallChunks) {
PacketProcessor processor(GetCallback());
std::vector<uint8_t> payload(100 * 1024); // 100 KB
for (size_t i = 0; i < payload.size(); ++i) {
payload[i] = static_cast<uint8_t>(i & 0xFF);
}
auto packet = BuildPacket(payload);
// 每次发送 1 KB
const size_t chunkSize = 1024;
for (size_t i = 0; i < packet.size(); i += chunkSize) {
size_t len = std::min(chunkSize, packet.size() - i);
processor.OnReceive(packet.data() + i, len);
}
EXPECT_EQ(packetCount, 1u);
}