Modules/Containers/tests/benchLinearRingBuffer.cpp
Шурупов Илья Викторович 0f15c37c2e
Some checks failed
Windows / build (push) Has been cancelled
CMake on a single platform / build (push) Has been cancelled
CMake / build (push) Has been cancelled
tmp
2025-11-24 18:24:00 +03:00

188 lines
4.6 KiB
C++

#include "LinearRingBuffer.hpp"
#include <gtest/gtest.h>
#include <cstring>
#include <cstdint>
#include <random>
static void fill(void* ptr, size_t n, uint8_t value) { std::memset(ptr, value, n); }
static bool check(const void* ptr, size_t n, uint8_t value) {
const uint8_t* p = static_cast<const uint8_t*>(ptr);
for (size_t i = 0; i < n; ++i) {
if (p[i] != value) return false;
}
return true;
}
static bool expect_mem_eq(const void* ptr, size_t n, uint8_t value) {
const uint8_t* p = static_cast<const uint8_t*>(ptr);
for (size_t i = 0; i < n; ++i) {
if (p[i] != value) return false;
}
return true;
}
using Data = std::vector<uint8_t>;
using DataStorage = std::vector<Data>;
typedef ::testing::Types<
std::integral_constant<size_t, 64>,
std::integral_constant<size_t, 128>,
std::integral_constant<size_t, 1000>,
std::integral_constant<size_t, 4096>,
std::integral_constant<size_t, 4096 * 2>>
BufferSizes;
template <typename TypeParam>
class LinearRingBufferTest : public ::testing::Test {
protected:
LinearRingBuffer rb;
LinearRingBufferTest() :
historySize_(10),
rb(size_t(TypeParam::value), size_t(historySize_)) {}
static constexpr auto ITERATIONS = TypeParam::value * 10;
size_t messagesPushed_ = 0;
size_t historySize_ = 0;
auto iterations() { return ITERATIONS; }
auto historySize() { return historySize_; }
size_t randomSize() {
static std::random_device rnd;
std::uniform_int_distribution<size_t> dist(0, 1000);
return dist(rnd);
}
auto write_and_advance(size_t messageSize, DataStorage* storage) {
Data pushedSample(messageSize);
for (auto idx = 0; idx < messageSize; idx++) {
pushedSample[idx] = (idx + messagesPushed_++ * 53) % 321;
}
std::memcpy(this->rb.write_data(), pushedSample.data(), pushedSample.size());
this->rb.write_advance(pushedSample.size());
if (storage) {
storage->push_back(pushedSample);
}
};
auto read_and_advance(size_t messageSize, DataStorage* storage) {
Data poppedSample(messageSize);
std::memcpy(poppedSample.data(), this->rb.read_data(), poppedSample.size());
this->rb.read_advance(poppedSample.size());
if (storage) {
storage->push_back(poppedSample);
}
};
auto reset_with_history() { this->rb.read_reset_with_history(); };
auto read_with_history(size_t messageSize, DataStorage* storage) {
Data poppedSample(messageSize);
std::memcpy(poppedSample.data(), this->rb.read_data(), poppedSample.size());
if (storage) {
storage->push_back(poppedSample);
}
};
};
TYPED_TEST_SUITE(LinearRingBufferTest, BufferSizes);
TYPED_TEST(LinearRingBufferTest, LinearWriteAcrossBoundary) {
constexpr size_t N = TypeParam::value;
if (N % 4096 != 0) {
return;
}
auto* base = this->rb.write_data();
size_t half = N - 16;
fill(base, half, 0xAA);
fill(base + half, 32, 0xBB);
EXPECT_EQ(expect_mem_eq(base, 16, 0xBB), true);
EXPECT_EQ(expect_mem_eq(base + 16, half - 16, 0xAA), true);
EXPECT_EQ(expect_mem_eq(base + half, 32, 0xBB), true);
}
TYPED_TEST(LinearRingBufferTest, Chase) {
DataStorage pushed;
DataStorage popped;
static constexpr auto MSG_SIZE = 31;
for (auto iteration = 0; iteration < this->iterations(); iteration++) {
this->write_and_advance(MSG_SIZE, &pushed);
this->read_and_advance(MSG_SIZE, &popped);
}
ASSERT_EQ(pushed.size(), popped.size());
for (auto idx = 0; idx < popped.size(); idx++) {
ASSERT_EQ(pushed[idx], popped[idx]);
}
}
Data makeMessageWithHistory(const Data& prev, const Data& current, size_t historySize) {
if (historySize > prev.size()) historySize = prev.size();
std::vector<uint8_t> result;
result.reserve(historySize + current.size());
result.insert(result.end(), prev.end() - historySize, prev.end());
result.insert(result.end(), current.begin(), current.end());
return result;
}
TYPED_TEST(LinearRingBufferTest, History) {
DataStorage pushed;
DataStorage popped;
pushed.push_back(Data(this->historySize()));
static constexpr auto MAX_MSG_SIZE = 111;
for (auto iteration = 0; iteration < this->iterations(); iteration++) {
const auto MSG_SIZE = this->historySize() + this->randomSize() % MAX_MSG_SIZE;
auto prevPushed = pushed.back();
pushed.clear();
this->reset_with_history();
this->write_and_advance(MSG_SIZE, &pushed);
auto currentPushed = pushed.back();
this->read_with_history(this->historySize() + MSG_SIZE, &popped);
auto poppedWithHistory = popped.back();
popped.clear();
auto correctResult = makeMessageWithHistory(prevPushed, currentPushed, this->historySize());
ASSERT_EQ(correctResult, poppedWithHistory);
}
}
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}