/** * @file BufferTest.cpp * @brief 服务端 CBuffer 类单元测试 * * 测试覆盖: * - 基本读写操作 * - 延迟读取偏移机制 (m_ulReadOffset) * - 压缩/紧凑策略 (CompactBuffer) * - 边界条件和下溢防护 * - 线程安全(并发读写) * - 零拷贝写入接口 */ #include #include #include #include #include #include // Windows 头文件 #ifdef _WIN32 #include #else // Linux 模拟 Windows API #include #include #include typedef unsigned char BYTE; typedef BYTE* PBYTE; typedef BYTE* LPBYTE; typedef unsigned long ULONG; typedef void VOID; typedef int BOOL; typedef void* PVOID; #define TRUE 1 #define FALSE 0 #define MEM_COMMIT 0x1000 #define MEM_RELEASE 0x8000 #define PAGE_READWRITE 0x04 struct CRITICAL_SECTION { pthread_mutex_t mutex; }; inline void InitializeCriticalSection(CRITICAL_SECTION* cs) { pthread_mutex_init(&cs->mutex, NULL); } inline void DeleteCriticalSection(CRITICAL_SECTION* cs) { pthread_mutex_destroy(&cs->mutex); } inline void EnterCriticalSection(CRITICAL_SECTION* cs) { pthread_mutex_lock(&cs->mutex); } inline void LeaveCriticalSection(CRITICAL_SECTION* cs) { pthread_mutex_unlock(&cs->mutex); } inline void* VirtualAlloc(void*, size_t size, int, int) { return malloc(size); } inline void VirtualFree(void* ptr, size_t, int) { free(ptr); } inline void CopyMemory(void* dst, const void* src, size_t len) { memcpy(dst, src, len); } inline void MoveMemory(void* dst, const void* src, size_t len) { memmove(dst, src, len); } #endif #include // 服务端 Buffer 实现(测试专用内联版本) namespace ServerBuffer { #define U_PAGE_ALIGNMENT 4096 #define F_PAGE_ALIGNMENT 4096.0 #define COMPACT_THRESHOLD 0.5 // 简化的 Buffer 类(用于 GetMyBuffer 返回) class Buffer { private: PBYTE buf; ULONG len; public: Buffer() : buf(NULL), len(0) {} Buffer(const BYTE* b, ULONG n) : len(n) { if (n > 0 && b) { buf = new BYTE[n]; memcpy(buf, b, n); } else { buf = NULL; } } ~Buffer() { if (buf) { delete[] buf; buf = NULL; } } Buffer(const Buffer& o) : len(o.len) { if (o.buf && o.len > 0) { buf = new BYTE[o.len]; memcpy(buf, o.buf, o.len); } else { buf = NULL; } } ULONG length() const { return len; } LPBYTE GetBuffer(int idx = 0) const { return (idx >= (int)len) ? NULL : buf + idx; } }; class CBuffer { public: CBuffer() : m_ulMaxLength(0), m_ulReadOffset(0), m_Base(NULL), m_Ptr(NULL) { InitializeCriticalSection(&m_cs); } ~CBuffer() { if (m_Base) { VirtualFree(m_Base, 0, MEM_RELEASE); m_Base = NULL; } DeleteCriticalSection(&m_cs); m_Base = m_Ptr = NULL; m_ulMaxLength = 0; m_ulReadOffset = 0; } ULONG RemoveCompletedBuffer(ULONG ulLength) { EnterCriticalSection(&m_cs); ULONG totalDataLen = (ULONG)(m_Ptr - m_Base); ULONG effectiveDataLen = (totalDataLen > m_ulReadOffset) ? (totalDataLen - m_ulReadOffset) : 0; if (ulLength > effectiveDataLen) { ulLength = effectiveDataLen; } if (ulLength) { m_ulReadOffset += ulLength; if (m_ulReadOffset > (ULONG)(m_ulMaxLength * COMPACT_THRESHOLD)) { CompactBuffer(); } } LeaveCriticalSection(&m_cs); return ulLength; } VOID CompactBuffer() { if (m_ulReadOffset > 0 && m_Base) { ULONG totalDataLen = (ULONG)(m_Ptr - m_Base); ULONG remainingData = (totalDataLen > m_ulReadOffset) ? (totalDataLen - m_ulReadOffset) : 0; if (remainingData > 0) { MoveMemory(m_Base, m_Base + m_ulReadOffset, remainingData); } m_Ptr = m_Base + remainingData; m_ulReadOffset = 0; DeAllocateBuffer(remainingData); } } ULONG ReadBuffer(PBYTE Buffer, ULONG ulLength) { EnterCriticalSection(&m_cs); ULONG totalDataLen = (ULONG)(m_Ptr - m_Base); ULONG effectiveDataLen = (totalDataLen > m_ulReadOffset) ? (totalDataLen - m_ulReadOffset) : 0; if (ulLength > effectiveDataLen) { ulLength = effectiveDataLen; } if (ulLength) { CopyMemory(Buffer, m_Base + m_ulReadOffset, ulLength); m_ulReadOffset += ulLength; if (m_ulReadOffset > (ULONG)(m_ulMaxLength * COMPACT_THRESHOLD)) { CompactBuffer(); } } LeaveCriticalSection(&m_cs); return ulLength; } ULONG DeAllocateBuffer(ULONG ulLength) { if (ulLength < (ULONG)(m_Ptr - m_Base)) return 0; ULONG ulNewMaxLength = (ULONG)(ceil(ulLength / F_PAGE_ALIGNMENT) * U_PAGE_ALIGNMENT); if (m_ulMaxLength <= ulNewMaxLength) { return 0; } PBYTE NewBase = (PBYTE)VirtualAlloc(NULL, ulNewMaxLength, MEM_COMMIT, PAGE_READWRITE); ULONG ulv1 = (ULONG)(m_Ptr - m_Base); CopyMemory(NewBase, m_Base, ulv1); VirtualFree(m_Base, 0, MEM_RELEASE); m_Base = NewBase; m_Ptr = m_Base + ulv1; m_ulMaxLength = ulNewMaxLength; return m_ulMaxLength; } BOOL WriteBuffer(PBYTE Buffer, ULONG ulLength) { EnterCriticalSection(&m_cs); if (ReAllocateBuffer(ulLength + (ULONG)(m_Ptr - m_Base)) == (ULONG)-1) { LeaveCriticalSection(&m_cs); return FALSE; } CopyMemory(m_Ptr, Buffer, ulLength); m_Ptr += ulLength; LeaveCriticalSection(&m_cs); return TRUE; } ULONG ReAllocateBuffer(ULONG ulLength) { if (ulLength < m_ulMaxLength) return 0; ULONG ulNewMaxLength = (ULONG)(ceil(ulLength / F_PAGE_ALIGNMENT) * U_PAGE_ALIGNMENT); PBYTE NewBase = (PBYTE)VirtualAlloc(NULL, ulNewMaxLength, MEM_COMMIT, PAGE_READWRITE); if (NewBase == NULL) { return (ULONG)-1; } ULONG ulv1 = (ULONG)(m_Ptr - m_Base); CopyMemory(NewBase, m_Base, ulv1); if (m_Base) { VirtualFree(m_Base, 0, MEM_RELEASE); } m_Base = NewBase; m_Ptr = m_Base + ulv1; m_ulMaxLength = ulNewMaxLength; return m_ulMaxLength; } VOID ClearBuffer() { EnterCriticalSection(&m_cs); m_Ptr = m_Base; m_ulReadOffset = 0; DeAllocateBuffer(1024); LeaveCriticalSection(&m_cs); } ULONG GetBufferLength() { EnterCriticalSection(&m_cs); if (m_Base == NULL) { LeaveCriticalSection(&m_cs); return 0; } ULONG totalDataLen = (ULONG)(m_Ptr - m_Base); ULONG len = (totalDataLen > m_ulReadOffset) ? (totalDataLen - m_ulReadOffset) : 0; LeaveCriticalSection(&m_cs); return len; } std::string Skip(ULONG ulPos) { if (ulPos == 0) return ""; EnterCriticalSection(&m_cs); ULONG totalDataLen = (ULONG)(m_Ptr - m_Base); ULONG effectiveDataLen = (totalDataLen > m_ulReadOffset) ? (totalDataLen - m_ulReadOffset) : 0; if (ulPos > effectiveDataLen) { ulPos = effectiveDataLen; } std::string ret((char*)(m_Base + m_ulReadOffset), (char*)(m_Base + m_ulReadOffset + ulPos)); m_ulReadOffset += ulPos; if (m_ulReadOffset > (ULONG)(m_ulMaxLength * COMPACT_THRESHOLD)) { CompactBuffer(); } LeaveCriticalSection(&m_cs); return ret; } LPBYTE GetBuffer(ULONG ulPos = 0) { EnterCriticalSection(&m_cs); ULONG totalDataLen = (ULONG)(m_Ptr - m_Base); ULONG effectiveDataLen = (totalDataLen > m_ulReadOffset) ? (totalDataLen - m_ulReadOffset) : 0; if (m_Base == NULL || ulPos >= effectiveDataLen) { LeaveCriticalSection(&m_cs); return NULL; } LPBYTE result = m_Base + m_ulReadOffset + ulPos; LeaveCriticalSection(&m_cs); return result; } Buffer GetMyBuffer(ULONG ulPos = 0) { EnterCriticalSection(&m_cs); ULONG totalDataLen = (ULONG)(m_Ptr - m_Base); ULONG effectiveDataLen = (totalDataLen > m_ulReadOffset) ? (totalDataLen - m_ulReadOffset) : 0; if (m_Base == NULL || ulPos >= effectiveDataLen) { LeaveCriticalSection(&m_cs); return Buffer(); } Buffer result(m_Base + m_ulReadOffset + ulPos, effectiveDataLen - ulPos); LeaveCriticalSection(&m_cs); return result; } BYTE GetBYTE(ULONG ulPos) { EnterCriticalSection(&m_cs); ULONG totalDataLen = (ULONG)(m_Ptr - m_Base); ULONG effectiveDataLen = (totalDataLen > m_ulReadOffset) ? (totalDataLen - m_ulReadOffset) : 0; if (m_Base == NULL || ulPos >= effectiveDataLen) { LeaveCriticalSection(&m_cs); return 0; } BYTE p = *(m_Base + m_ulReadOffset + ulPos); LeaveCriticalSection(&m_cs); return p; } BOOL CopyBuffer(PVOID pDst, ULONG nLen, ULONG ulPos) { EnterCriticalSection(&m_cs); ULONG totalDataLen = (ULONG)(m_Ptr - m_Base); ULONG effectiveDataLen = (totalDataLen > m_ulReadOffset) ? (totalDataLen - m_ulReadOffset) : 0; if (m_Base == NULL || pDst == NULL || ulPos >= effectiveDataLen || (effectiveDataLen - ulPos) < nLen) { LeaveCriticalSection(&m_cs); return FALSE; } memcpy(pDst, m_Base + m_ulReadOffset + ulPos, nLen); LeaveCriticalSection(&m_cs); return TRUE; } LPBYTE GetWriteBuffer(ULONG requiredSize, ULONG& availableSize) { EnterCriticalSection(&m_cs); if (m_ulReadOffset > 0) { CompactBuffer(); } ULONG currentDataLen = (ULONG)(m_Ptr - m_Base); if (ReAllocateBuffer(currentDataLen + requiredSize) == (ULONG)-1) { LeaveCriticalSection(&m_cs); availableSize = 0; return NULL; } availableSize = m_ulMaxLength - currentDataLen; LPBYTE result = m_Ptr; LeaveCriticalSection(&m_cs); return result; } VOID CommitWrite(ULONG writtenSize) { EnterCriticalSection(&m_cs); m_Ptr += writtenSize; LeaveCriticalSection(&m_cs); } // 测试辅助:获取内部状态 ULONG GetReadOffset() const { return m_ulReadOffset; } ULONG GetMaxLength() const { return m_ulMaxLength; } protected: PBYTE m_Base; PBYTE m_Ptr; ULONG m_ulMaxLength; ULONG m_ulReadOffset; CRITICAL_SECTION m_cs; }; } // namespace ServerBuffer using ServerBuffer::CBuffer; using ServerBuffer::Buffer; // ============================================ // 测试夹具 // ============================================ class ServerBufferTest : public ::testing::Test { protected: CBuffer buffer; void SetUp() override {} void TearDown() override {} void WriteFillData(ULONG length, BYTE fillValue = 0x42) { std::vector data(length, fillValue); buffer.WriteBuffer(data.data(), length); } }; // ============================================ // 构造/析构测试 // ============================================ TEST_F(ServerBufferTest, Constructor_InitializesEmpty) { CBuffer newBuffer; EXPECT_EQ(newBuffer.GetBufferLength(), 0u); EXPECT_EQ(newBuffer.GetBuffer(), nullptr); } // ============================================ // WriteBuffer 测试 // ============================================ TEST_F(ServerBufferTest, WriteBuffer_ValidData_ReturnsTrue) { BYTE data[] = {1, 2, 3, 4, 5}; EXPECT_TRUE(buffer.WriteBuffer(data, 5)); EXPECT_EQ(buffer.GetBufferLength(), 5u); } TEST_F(ServerBufferTest, WriteBuffer_MultipleWrites_AccumulatesData) { BYTE data1[] = {1, 2, 3}; BYTE data2[] = {4, 5}; buffer.WriteBuffer(data1, 3); buffer.WriteBuffer(data2, 2); EXPECT_EQ(buffer.GetBufferLength(), 5u); } TEST_F(ServerBufferTest, WriteBuffer_LargeData_HandlesCorrectly) { const ULONG largeSize = 100000; std::vector data(largeSize, 0xAB); EXPECT_TRUE(buffer.WriteBuffer(data.data(), largeSize)); EXPECT_EQ(buffer.GetBufferLength(), largeSize); } // ============================================ // ReadBuffer 测试 // ============================================ TEST_F(ServerBufferTest, ReadBuffer_EmptyBuffer_ReturnsZero) { BYTE result[10]; EXPECT_EQ(buffer.ReadBuffer(result, 10), 0u); } TEST_F(ServerBufferTest, ReadBuffer_ExactLength_ReturnsAll) { BYTE data[] = {1, 2, 3, 4, 5}; buffer.WriteBuffer(data, 5); BYTE result[5]; ULONG bytesRead = buffer.ReadBuffer(result, 5); EXPECT_EQ(bytesRead, 5u); EXPECT_EQ(buffer.GetBufferLength(), 0u); } TEST_F(ServerBufferTest, ReadBuffer_PartialRead_UsesReadOffset) { BYTE data[] = {1, 2, 3, 4, 5}; buffer.WriteBuffer(data, 5); BYTE result[2]; buffer.ReadBuffer(result, 2); // 使用延迟偏移,不立即移动数据 EXPECT_EQ(buffer.GetBufferLength(), 3u); EXPECT_GT(buffer.GetReadOffset(), 0u); } TEST_F(ServerBufferTest, ReadBuffer_RequestExceedsAvailable_ReturnsAvailableOnly) { BYTE data[] = {1, 2, 3}; buffer.WriteBuffer(data, 3); BYTE result[10]; ULONG bytesRead = buffer.ReadBuffer(result, 10); EXPECT_EQ(bytesRead, 3u); EXPECT_EQ(buffer.GetBufferLength(), 0u); } // ============================================ // RemoveCompletedBuffer 测试 // ============================================ TEST_F(ServerBufferTest, RemoveCompletedBuffer_PartialRemove_UpdatesOffset) { BYTE data[] = {1, 2, 3, 4, 5}; buffer.WriteBuffer(data, 5); ULONG removed = buffer.RemoveCompletedBuffer(2); EXPECT_EQ(removed, 2u); EXPECT_EQ(buffer.GetBufferLength(), 3u); } TEST_F(ServerBufferTest, RemoveCompletedBuffer_ExceedsLength_ClampsToAvailable) { BYTE data[] = {1, 2, 3}; buffer.WriteBuffer(data, 3); ULONG removed = buffer.RemoveCompletedBuffer(100); EXPECT_EQ(removed, 3u); EXPECT_EQ(buffer.GetBufferLength(), 0u); } // ============================================ // Skip 测试 // ============================================ TEST_F(ServerBufferTest, Skip_ReturnsSkippedData) { BYTE data[] = {'H', 'e', 'l', 'l', 'o'}; buffer.WriteBuffer(data, 5); std::string skipped = buffer.Skip(3); EXPECT_EQ(skipped, "Hel"); EXPECT_EQ(buffer.GetBufferLength(), 2u); } TEST_F(ServerBufferTest, Skip_ExceedsLength_ClampsToAvailable) { BYTE data[] = {'A', 'B', 'C'}; buffer.WriteBuffer(data, 3); std::string skipped = buffer.Skip(100); EXPECT_EQ(skipped, "ABC"); EXPECT_EQ(buffer.GetBufferLength(), 0u); } TEST_F(ServerBufferTest, Skip_ZeroLength_ReturnsEmpty) { BYTE data[] = {1, 2, 3}; buffer.WriteBuffer(data, 3); std::string skipped = buffer.Skip(0); EXPECT_EQ(skipped, ""); EXPECT_EQ(buffer.GetBufferLength(), 3u); } // ============================================ // GetBuffer 测试 // ============================================ TEST_F(ServerBufferTest, GetBuffer_RespectsReadOffset) { BYTE data[] = {10, 20, 30, 40, 50}; buffer.WriteBuffer(data, 5); // 读取前两个字节,更新偏移 BYTE temp[2]; buffer.ReadBuffer(temp, 2); // GetBuffer(0) 应该返回第三个字节(30) EXPECT_EQ(*buffer.GetBuffer(0), 30); EXPECT_EQ(*buffer.GetBuffer(1), 40); EXPECT_EQ(*buffer.GetBuffer(2), 50); } TEST_F(ServerBufferTest, GetBuffer_PositionExceedsEffectiveLength_ReturnsNull) { BYTE data[] = {1, 2, 3, 4, 5}; buffer.WriteBuffer(data, 5); BYTE temp[3]; buffer.ReadBuffer(temp, 3); // 有效长度变为 2 EXPECT_NE(buffer.GetBuffer(0), nullptr); EXPECT_NE(buffer.GetBuffer(1), nullptr); EXPECT_EQ(buffer.GetBuffer(2), nullptr); // 超出有效范围 } // ============================================ // GetMyBuffer 测试 // ============================================ TEST_F(ServerBufferTest, GetMyBuffer_ReturnsCorrectBuffer) { BYTE data[] = {1, 2, 3, 4, 5}; buffer.WriteBuffer(data, 5); Buffer buf = buffer.GetMyBuffer(0); EXPECT_EQ(buf.length(), 5u); } TEST_F(ServerBufferTest, GetMyBuffer_RespectsReadOffset) { BYTE data[] = {1, 2, 3, 4, 5}; buffer.WriteBuffer(data, 5); BYTE temp[2]; buffer.ReadBuffer(temp, 2); Buffer buf = buffer.GetMyBuffer(0); EXPECT_EQ(buf.length(), 3u); EXPECT_EQ(*buf.GetBuffer(0), 3); } // ============================================ // GetBYTE 测试 // ============================================ TEST_F(ServerBufferTest, GetBYTE_ReturnsCorrectByte) { BYTE data[] = {10, 20, 30, 40, 50}; buffer.WriteBuffer(data, 5); EXPECT_EQ(buffer.GetBYTE(0), 10); EXPECT_EQ(buffer.GetBYTE(2), 30); EXPECT_EQ(buffer.GetBYTE(4), 50); } TEST_F(ServerBufferTest, GetBYTE_RespectsReadOffset) { BYTE data[] = {10, 20, 30, 40, 50}; buffer.WriteBuffer(data, 5); BYTE temp[2]; buffer.ReadBuffer(temp, 2); EXPECT_EQ(buffer.GetBYTE(0), 30); EXPECT_EQ(buffer.GetBYTE(1), 40); } TEST_F(ServerBufferTest, GetBYTE_OutOfRange_ReturnsZero) { BYTE data[] = {1, 2, 3}; buffer.WriteBuffer(data, 3); EXPECT_EQ(buffer.GetBYTE(100), 0); } // ============================================ // CopyBuffer 测试 // ============================================ TEST_F(ServerBufferTest, CopyBuffer_ValidRange_ReturnsTrue) { BYTE data[] = {1, 2, 3, 4, 5}; buffer.WriteBuffer(data, 5); BYTE dest[3]; EXPECT_TRUE(buffer.CopyBuffer(dest, 3, 1)); EXPECT_EQ(dest[0], 2); EXPECT_EQ(dest[1], 3); EXPECT_EQ(dest[2], 4); } TEST_F(ServerBufferTest, CopyBuffer_RespectsReadOffset) { BYTE data[] = {1, 2, 3, 4, 5}; buffer.WriteBuffer(data, 5); BYTE temp[2]; buffer.ReadBuffer(temp, 2); BYTE dest[2]; EXPECT_TRUE(buffer.CopyBuffer(dest, 2, 0)); EXPECT_EQ(dest[0], 3); EXPECT_EQ(dest[1], 4); } TEST_F(ServerBufferTest, CopyBuffer_ExceedsRange_ReturnsFalse) { BYTE data[] = {1, 2, 3}; buffer.WriteBuffer(data, 3); BYTE dest[10]; EXPECT_FALSE(buffer.CopyBuffer(dest, 10, 0)); } // ============================================ // 零拷贝写入测试 // ============================================ TEST_F(ServerBufferTest, GetWriteBuffer_ReturnsValidPointer) { ULONG availableSize = 0; LPBYTE writePtr = buffer.GetWriteBuffer(100, availableSize); EXPECT_NE(writePtr, nullptr); EXPECT_GE(availableSize, 100u); } TEST_F(ServerBufferTest, CommitWrite_UpdatesLength) { ULONG availableSize = 0; LPBYTE writePtr = buffer.GetWriteBuffer(100, availableSize); // 直接写入 for (int i = 0; i < 50; i++) { writePtr[i] = (BYTE)i; } buffer.CommitWrite(50); EXPECT_EQ(buffer.GetBufferLength(), 50u); EXPECT_EQ(buffer.GetBYTE(0), 0); EXPECT_EQ(buffer.GetBYTE(49), 49); } // ============================================ // ClearBuffer 测试 // ============================================ TEST_F(ServerBufferTest, ClearBuffer_ResetsEverything) { BYTE data[] = {1, 2, 3, 4, 5}; buffer.WriteBuffer(data, 5); BYTE temp[2]; buffer.ReadBuffer(temp, 2); // 创建读取偏移 buffer.ClearBuffer(); EXPECT_EQ(buffer.GetBufferLength(), 0u); EXPECT_EQ(buffer.GetReadOffset(), 0u); } // ============================================ // 下溢防护测试 // ============================================ TEST_F(ServerBufferTest, UnderflowProtection_ReadMoreThanLength_NoUnderflow) { BYTE data[] = {1, 2, 3}; buffer.WriteBuffer(data, 3); BYTE result[1000]; ULONG bytesRead = buffer.ReadBuffer(result, ULONG_MAX - 1); EXPECT_EQ(bytesRead, 3u); } TEST_F(ServerBufferTest, UnderflowProtection_SkipMoreThanLength_NoUnderflow) { BYTE data[] = {1, 2, 3}; buffer.WriteBuffer(data, 3); std::string skipped = buffer.Skip(ULONG_MAX - 1); EXPECT_EQ(skipped.length(), 3u); EXPECT_EQ(buffer.GetBufferLength(), 0u); } TEST_F(ServerBufferTest, UnderflowProtection_RemoveMoreThanLength_NoUnderflow) { BYTE data[] = {1, 2, 3}; buffer.WriteBuffer(data, 3); ULONG removed = buffer.RemoveCompletedBuffer(ULONG_MAX - 1); EXPECT_EQ(removed, 3u); } TEST_F(ServerBufferTest, UnderflowProtection_GetByteOutOfRange_ReturnsZero) { BYTE data[] = {1, 2, 3}; buffer.WriteBuffer(data, 3); EXPECT_EQ(buffer.GetBYTE(ULONG_MAX - 1), 0); } // ============================================ // 压缩策略测试 // ============================================ TEST_F(ServerBufferTest, Compaction_TriggersAtThreshold) { // 写入足够数据 // m_ulMaxLength 会被页对齐到 ceil(10000/4096)*4096 = 12288 // 压缩阈值 = 12288 * 0.5 = 6144 WriteFillData(10000); ULONG initialOffset = buffer.GetReadOffset(); EXPECT_EQ(initialOffset, 0u); // 读取超过阈值的数据(需要 > 6144) std::vector temp(7000); buffer.ReadBuffer(temp.data(), 7000); // 压缩后偏移应该重置 EXPECT_EQ(buffer.GetReadOffset(), 0u); EXPECT_EQ(buffer.GetBufferLength(), 3000u); } // ============================================ // 线程安全测试 // ============================================ TEST_F(ServerBufferTest, ThreadSafety_ConcurrentReadWrite_NoDataCorruption) { std::atomic running{true}; std::atomic writeCount{0}; std::atomic readCount{0}; // 写线程 std::thread writer([&]() { BYTE data[100]; for (int i = 0; i < 100; i++) { data[i] = (BYTE)i; } while (running) { if (buffer.WriteBuffer(data, 100)) { writeCount++; } std::this_thread::yield(); } }); // 读线程 std::thread reader([&]() { BYTE result[50]; while (running) { if (buffer.ReadBuffer(result, 50) > 0) { readCount++; } std::this_thread::yield(); } }); // 运行一段时间 std::this_thread::sleep_for(std::chrono::milliseconds(100)); running = false; writer.join(); reader.join(); // 验证无崩溃,且有数据交换 EXPECT_GT(writeCount.load(), 0); EXPECT_GT(readCount.load(), 0); } TEST_F(ServerBufferTest, ThreadSafety_MultipleReaders_NoDeadlock) { // 预填充数据 WriteFillData(10000); std::atomic running{true}; std::vector readers; for (int i = 0; i < 4; i++) { readers.emplace_back([&]() { while (running) { buffer.GetBufferLength(); buffer.GetBYTE(0); buffer.GetBuffer(0); std::this_thread::yield(); } }); } std::this_thread::sleep_for(std::chrono::milliseconds(50)); running = false; for (auto& t : readers) { t.join(); } // 无死锁即为成功 SUCCEED(); } // ============================================ // 数据完整性测试 // ============================================ TEST_F(ServerBufferTest, DataIntegrity_WriteReadCycle_PreservesData) { std::vector data(256); for (int i = 0; i < 256; i++) { data[i] = (BYTE)i; } buffer.WriteBuffer(data.data(), 256); std::vector result(256); ULONG bytesRead = buffer.ReadBuffer(result.data(), 256); EXPECT_EQ(bytesRead, 256u); for (int i = 0; i < 256; i++) { EXPECT_EQ(result[i], data[i]) << "Mismatch at index " << i; } } TEST_F(ServerBufferTest, DataIntegrity_PartialReads_PreservesSequence) { // 写入 1-100 std::vector data(100); for (int i = 0; i < 100; i++) { data[i] = (BYTE)(i + 1); } buffer.WriteBuffer(data.data(), 100); // 分多次读取 BYTE result[100]; ULONG totalRead = 0; totalRead += buffer.ReadBuffer(result, 30); totalRead += buffer.ReadBuffer(result + 30, 30); totalRead += buffer.ReadBuffer(result + 60, 40); EXPECT_EQ(totalRead, 100u); for (int i = 0; i < 100; i++) { EXPECT_EQ(result[i], (BYTE)(i + 1)); } } // ============================================ // 参数化测试 // ============================================ class ServerBufferParameterizedTest : public ::testing::TestWithParam> { protected: CBuffer buffer; }; TEST_P(ServerBufferParameterizedTest, ReadBuffer_VariousLengths) { auto [writeLen, readLen, expectedRead] = GetParam(); std::vector data(writeLen, 0x42); if (writeLen > 0) { buffer.WriteBuffer(data.data(), (ULONG)writeLen); } std::vector result(readLen > 0 ? readLen : 1); ULONG actual = buffer.ReadBuffer(result.data(), (ULONG)readLen); EXPECT_EQ(actual, expectedRead); } INSTANTIATE_TEST_SUITE_P( ReadLengths, ServerBufferParameterizedTest, ::testing::Values( std::make_tuple(10, 5, 5), std::make_tuple(5, 10, 5), std::make_tuple(0, 5, 0), std::make_tuple(100, 0, 0), std::make_tuple(10000, 5000, 5000) ) );