Files
Alicho/tests/unit/engine/ring_buffer_test.cpp
2025-10-28 10:27:49 +08:00

307 lines
9.3 KiB
C++

// ================================================================================================
// Audio Backend - 环形缓冲区测试
// ================================================================================================
#include <gtest/gtest.h>
#include "engine/audio_buffer.h"
#include "tests/common/test_fixtures.h"
#include "tests/common/test_utils.h"
#include <thread>
#include <atomic>
#include <vector>
using namespace audio_backend;
using namespace audio_backend::engine;
// 环形缓冲区测试固定装置
class RingBufferTest : public test::BaseTest {
protected:
void SetUp() override {
test::BaseTest::SetUp();
}
void TearDown() override {
test::BaseTest::TearDown();
}
// 测试不同类型的环形缓冲区
template<typename T>
void test_basic_operations(size_t capacity) {
RingBuffer<T> buffer(capacity);
// 初始状态
EXPECT_EQ(buffer.capacity(), capacity);
EXPECT_EQ(buffer.available(), 0);
EXPECT_EQ(buffer.space(), capacity);
EXPECT_TRUE(buffer.empty());
EXPECT_FALSE(buffer.full());
}
template<typename T>
void test_single_element_operations(size_t capacity, const std::vector<T>& test_data) {
RingBuffer<T> buffer(capacity);
// 推入和弹出单个元素
for (const T& value : test_data) {
EXPECT_TRUE(buffer.write(&value, 1));
EXPECT_EQ(buffer.available(), 1);
T output;
EXPECT_TRUE(buffer.read(&output, 1));
EXPECT_EQ(buffer.available(), 0);
EXPECT_EQ(output, value);
}
}
template<typename T>
void test_batch_operations(size_t capacity, const std::vector<T>& test_data) {
RingBuffer<T> buffer(capacity);
// 批量写入
size_t batch_size = std::min(test_data.size(), capacity);
size_t written = buffer.write(test_data.data(), batch_size);
EXPECT_EQ(written, batch_size);
EXPECT_EQ(buffer.available(), batch_size);
// 批量读取
std::vector<T> output(batch_size);
size_t read = buffer.read(output.data(), batch_size);
EXPECT_EQ(read, batch_size);
EXPECT_EQ(buffer.available(), 0);
for (size_t i = 0; i < batch_size; ++i) {
EXPECT_EQ(output[i], test_data[i]);
}
}
template<typename T>
void test_wrap_around(size_t capacity, const std::vector<T>& test_data) {
RingBuffer<T> buffer(capacity);
// 填充一半
size_t half = capacity / 2;
EXPECT_EQ(buffer.write(test_data.data(), half), half);
// 读取一半
std::vector<T> output(half);
EXPECT_EQ(buffer.read(output.data(), half), half);
// 现在写入超过一半,测试环绕
size_t to_write = std::min(test_data.size(), capacity - half + half);
EXPECT_EQ(buffer.write(test_data.data(), to_write), to_write);
// 读取全部
output.resize(to_write);
EXPECT_EQ(buffer.read(output.data(), to_write), to_write);
for (size_t i = 0; i < to_write; ++i) {
EXPECT_EQ(output[i], test_data[i]);
}
}
};
// 测试基本的Float类型RingBuffer操作
TEST_F(RingBufferTest, FloatBasicOperations) {
test_basic_operations<float>(1024);
}
// 测试基本的Int16类型RingBuffer操作
TEST_F(RingBufferTest, Int16BasicOperations) {
test_basic_operations<int16_t>(1024);
}
// 测试单元素Float操作
TEST_F(RingBufferTest, FloatSingleElementOperations) {
std::vector<float> test_data = {0.1f, 0.2f, 0.3f, 0.4f, 0.5f};
test_single_element_operations<float>(16, test_data);
}
// 测试单元素Int16操作
TEST_F(RingBufferTest, Int16SingleElementOperations) {
std::vector<int16_t> test_data = {100, 200, 300, 400, 500};
test_single_element_operations<int16_t>(16, test_data);
}
// 测试批量Float操作
TEST_F(RingBufferTest, FloatBatchOperations) {
std::vector<float> test_data(128);
for (size_t i = 0; i < test_data.size(); ++i) {
test_data[i] = static_cast<float>(i) / 100.0f;
}
test_batch_operations<float>(256, test_data);
}
// 测试批量Int16操作
TEST_F(RingBufferTest, Int16BatchOperations) {
std::vector<int16_t> test_data(128);
for (size_t i = 0; i < test_data.size(); ++i) {
test_data[i] = static_cast<int16_t>(i * 10);
}
test_batch_operations<int16_t>(256, test_data);
}
// 测试环绕逻辑
TEST_F(RingBufferTest, FloatWrapAround) {
std::vector<float> test_data(256);
for (size_t i = 0; i < test_data.size(); ++i) {
test_data[i] = static_cast<float>(i) / 100.0f;
}
test_wrap_around<float>(128, test_data);
}
// 测试环绕逻辑
TEST_F(RingBufferTest, Int16WrapAround) {
std::vector<int16_t> test_data(256);
for (size_t i = 0; i < test_data.size(); ++i) {
test_data[i] = static_cast<int16_t>(i * 10);
}
test_wrap_around<int16_t>(128, test_data);
}
// 测试缓冲区容量边界
TEST_F(RingBufferTest, CapacityBoundaries) {
// 零容量
RingBuffer<float> zero_buffer(0);
EXPECT_EQ(zero_buffer.capacity(), 0);
EXPECT_TRUE(zero_buffer.empty());
EXPECT_TRUE(zero_buffer.full()); // 零容量缓冲区应该同时是空的和满的
float value = 1.0f;
EXPECT_EQ(zero_buffer.write(&value, 1), 0); // 无法写入
// 最小容量
RingBuffer<float> min_buffer(1);
EXPECT_EQ(min_buffer.capacity(), 1);
EXPECT_TRUE(min_buffer.empty());
EXPECT_FALSE(min_buffer.full());
// 写入一个元素,缓冲区应该是满的
EXPECT_EQ(min_buffer.write(&value, 1), 1);
EXPECT_FALSE(min_buffer.empty());
EXPECT_TRUE(min_buffer.full());
// 再写入应该失败
EXPECT_EQ(min_buffer.write(&value, 1), 0);
}
// 测试清空操作
TEST_F(RingBufferTest, ClearOperation) {
RingBuffer<float> buffer(128);
// 填充一些数据
std::vector<float> test_data(64);
for (size_t i = 0; i < test_data.size(); ++i) {
test_data[i] = static_cast<float>(i) / 100.0f;
}
EXPECT_EQ(buffer.write(test_data.data(), test_data.size()), test_data.size());
EXPECT_EQ(buffer.available(), test_data.size());
// 清空
buffer.clear();
EXPECT_EQ(buffer.available(), 0);
EXPECT_EQ(buffer.space(), buffer.capacity());
EXPECT_TRUE(buffer.empty());
EXPECT_FALSE(buffer.full());
}
// 测试尝试写入超过容量
TEST_F(RingBufferTest, WriteBeyondCapacity) {
const size_t capacity = 128;
RingBuffer<float> buffer(capacity);
std::vector<float> test_data(capacity * 2); // 两倍容量
for (size_t i = 0; i < test_data.size(); ++i) {
test_data[i] = static_cast<float>(i) / 100.0f;
}
// 应该只写入容量大小
size_t written = buffer.write(test_data.data(), test_data.size());
EXPECT_EQ(written, capacity);
EXPECT_EQ(buffer.available(), capacity);
EXPECT_TRUE(buffer.full());
}
// 测试并发安全性
TEST_F(RingBufferTest, ConcurrentAccess) {
const size_t capacity = 1024;
const size_t iterations = 1000;
RingBuffer<int> buffer(capacity);
std::atomic<bool> done(false);
std::atomic<size_t> producer_count(0);
std::atomic<size_t> consumer_count(0);
// 生产者线程
auto producer = [&]() {
for (size_t i = 0; i < iterations; ++i) {
int value = static_cast<int>(i);
if (buffer.write(&value, 1) == 1) {
producer_count++;
}
}
};
// 消费者线程
auto consumer = [&]() {
while (!done || buffer.available() > 0) {
int value;
if (buffer.read(&value, 1) == 1) {
consumer_count++;
} else {
// 给生产者一些时间
std::this_thread::yield();
}
}
};
// 启动线程
std::thread producer_thread(producer);
std::thread consumer_thread(consumer);
// 等待生产者完成
producer_thread.join();
done = true;
// 等待消费者完成
consumer_thread.join();
// 验证所有数据都被正确处理
EXPECT_EQ(producer_count.load(), iterations);
EXPECT_EQ(consumer_count.load(), iterations);
EXPECT_TRUE(buffer.empty());
}
// 测试调整大小
TEST_F(RingBufferTest, Resize) {
RingBuffer<float> buffer(128);
// 填充一些数据
std::vector<float> test_data(64);
for (size_t i = 0; i < test_data.size(); ++i) {
test_data[i] = static_cast<float>(i) / 100.0f;
}
EXPECT_EQ(buffer.write(test_data.data(), test_data.size()), test_data.size());
// 调整大小(会清空缓冲区)
buffer.resize(256);
EXPECT_EQ(buffer.capacity(), 256);
EXPECT_EQ(buffer.available(), 0);
EXPECT_EQ(buffer.space(), 256);
// 再次写入
EXPECT_EQ(buffer.write(test_data.data(), test_data.size()), test_data.size());
EXPECT_EQ(buffer.available(), test_data.size());
// 调整到更小(会清空缓冲区)
buffer.resize(32);
EXPECT_EQ(buffer.capacity(), 32);
EXPECT_EQ(buffer.available(), 0);
EXPECT_EQ(buffer.space(), 32);
}
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}