pineapple-src/src/tests/common/ring_buffer.cpp

130 lines
3.4 KiB
C++
Raw Normal View History

2022-04-23 18:49:07 +00:00
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
2020-12-28 15:15:37 +00:00
#include <algorithm>
#include <array>
#include <cstddef>
#include <numeric>
#include <thread>
#include <vector>
#include <catch2/catch.hpp>
#include "common/ring_buffer.h"
namespace Common {
TEST_CASE("RingBuffer: Basic Tests", "[common]") {
2021-02-06 22:05:49 +00:00
RingBuffer<char, 4> buf;
2020-12-28 15:15:37 +00:00
// Pushing values into a ring buffer with space should succeed.
for (std::size_t i = 0; i < 4; i++) {
const char elem = static_cast<char>(i);
const std::size_t count = buf.Push(&elem, 1);
2021-01-12 09:22:33 +00:00
REQUIRE(count == 1U);
2020-12-28 15:15:37 +00:00
}
2021-01-12 09:22:33 +00:00
REQUIRE(buf.Size() == 4U);
2020-12-28 15:15:37 +00:00
// Pushing values into a full ring buffer should fail.
{
const char elem = static_cast<char>(42);
const std::size_t count = buf.Push(&elem, 1);
2021-01-12 09:22:33 +00:00
REQUIRE(count == 0U);
2020-12-28 15:15:37 +00:00
}
2021-01-12 09:22:33 +00:00
REQUIRE(buf.Size() == 4U);
2020-12-28 15:15:37 +00:00
// Popping multiple values from a ring buffer with values should succeed.
{
const std::vector<char> popped = buf.Pop(2);
2021-01-12 09:22:33 +00:00
REQUIRE(popped.size() == 2U);
2020-12-28 15:15:37 +00:00
REQUIRE(popped[0] == 0);
REQUIRE(popped[1] == 1);
}
2021-01-12 09:22:33 +00:00
REQUIRE(buf.Size() == 2U);
2020-12-28 15:15:37 +00:00
// Popping a single value from a ring buffer with values should succeed.
{
const std::vector<char> popped = buf.Pop(1);
2021-01-12 09:22:33 +00:00
REQUIRE(popped.size() == 1U);
2020-12-28 15:15:37 +00:00
REQUIRE(popped[0] == 2);
}
2021-01-12 09:22:33 +00:00
REQUIRE(buf.Size() == 1U);
2020-12-28 15:15:37 +00:00
// Pushing more values than space available should partially suceed.
{
std::vector<char> to_push(6);
std::iota(to_push.begin(), to_push.end(), 88);
const std::size_t count = buf.Push(to_push);
2021-01-12 09:22:33 +00:00
REQUIRE(count == 3U);
2020-12-28 15:15:37 +00:00
}
2021-01-12 09:22:33 +00:00
REQUIRE(buf.Size() == 4U);
2020-12-28 15:15:37 +00:00
// Doing an unlimited pop should pop all values.
{
const std::vector<char> popped = buf.Pop();
2021-01-12 09:22:33 +00:00
REQUIRE(popped.size() == 4U);
2020-12-28 15:15:37 +00:00
REQUIRE(popped[0] == 3);
REQUIRE(popped[1] == 88);
REQUIRE(popped[2] == 89);
REQUIRE(popped[3] == 90);
}
2021-01-12 09:22:33 +00:00
REQUIRE(buf.Size() == 0U);
2020-12-28 15:15:37 +00:00
}
TEST_CASE("RingBuffer: Threaded Test", "[common]") {
2021-02-06 22:05:49 +00:00
RingBuffer<char, 8> buf;
2020-12-28 15:15:37 +00:00
const char seed = 42;
const std::size_t count = 1000000;
std::size_t full = 0;
std::size_t empty = 0;
const auto next_value = [](std::array<char, 2>& value) {
value[0] += 1;
value[1] += 2;
};
std::thread producer{[&] {
std::array<char, 2> value = {seed, seed};
std::size_t i = 0;
while (i < count) {
2021-02-06 22:05:49 +00:00
if (const std::size_t c = buf.Push(&value[0], 2); c > 0) {
REQUIRE(c == 2U);
2020-12-28 15:15:37 +00:00
i++;
next_value(value);
} else {
full++;
std::this_thread::yield();
}
}
}};
std::thread consumer{[&] {
std::array<char, 2> value = {seed, seed};
std::size_t i = 0;
while (i < count) {
2021-02-06 22:05:49 +00:00
if (const std::vector<char> v = buf.Pop(2); v.size() > 0) {
2021-01-12 09:22:33 +00:00
REQUIRE(v.size() == 2U);
2020-12-28 15:15:37 +00:00
REQUIRE(v[0] == value[0]);
REQUIRE(v[1] == value[1]);
i++;
next_value(value);
} else {
empty++;
std::this_thread::yield();
}
}
}};
producer.join();
consumer.join();
2021-01-12 09:22:33 +00:00
REQUIRE(buf.Size() == 0U);
2020-12-28 15:15:37 +00:00
printf("RingBuffer: Threaded Test: full: %zu, empty: %zu\n", full, empty);
}
} // namespace Common