1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
|
#include "ring_buffer.h"
#include <gtest/gtest.h>
#include <algorithm>
#include <cassert>
#include <vector>
namespace {
template <typename T>
class TypedRingBuffer;
template <typename T>
class TypedRingBuffer<T *> {
public:
explicit TypedRingBuffer(int size)
: rb_(rb_new(size))
{
}
~TypedRingBuffer() { rb_kill(rb_); }
TypedRingBuffer(TypedRingBuffer const &) = delete;
bool full() const { return rb_full(rb_); }
bool empty() const { return rb_empty(rb_); }
T *write(T *p) { return static_cast<T *>(rb_write(rb_, p)); }
bool read(T **p)
{
void *vp;
bool res = rb_read(rb_, &vp);
*p = static_cast<T *>(vp);
return res;
}
uint16_t size() const { return rb_size(rb_); }
uint16_t data(T **dest) const
{
std::vector<void *> vdest(size());
uint16_t res = rb_data(rb_, vdest.data());
for (uint16_t i = 0; i < size(); i++) {
dest[i] = static_cast<T *>(vdest.at(i));
}
return res;
}
bool contains(T *p) const
{
std::vector<T *> elts(size());
data(elts.data());
return std::find(elts.begin(), elts.end(), p) != elts.end();
}
bool ok() const { return rb_ != nullptr; }
private:
RingBuffer *rb_;
};
TEST(RingBuffer, EmptyBufferReportsEmpty)
{
TypedRingBuffer<int *> rb(10);
ASSERT_TRUE(rb.ok());
EXPECT_TRUE(rb.empty());
}
TEST(RingBuffer, EmptyBufferReportsNotFull)
{
TypedRingBuffer<int *> rb(10);
ASSERT_TRUE(rb.ok());
EXPECT_FALSE(rb.full());
}
TEST(RingBuffer, ZeroSizedRingBufferIsBothEmptyAndFull)
{
TypedRingBuffer<int *> rb(0);
ASSERT_TRUE(rb.ok());
EXPECT_TRUE(rb.empty());
EXPECT_TRUE(rb.full());
}
TEST(RingBuffer, WritingMakesBufferNotEmpty)
{
TypedRingBuffer<int *> rb(2);
ASSERT_TRUE(rb.ok());
int value0 = 123;
rb.write(&value0);
EXPECT_FALSE(rb.empty());
}
TEST(RingBuffer, WritingOneElementMakesBufferNotFull)
{
TypedRingBuffer<int *> rb(2);
ASSERT_TRUE(rb.ok());
int value0 = 123;
rb.write(&value0);
EXPECT_FALSE(rb.full());
}
TEST(RingBuffer, WritingAllElementsMakesBufferFull)
{
TypedRingBuffer<int *> rb(2);
ASSERT_TRUE(rb.ok());
int value0 = 123;
int value1 = 231;
rb.write(&value0);
rb.write(&value1);
EXPECT_TRUE(rb.full());
}
TEST(RingBuffer, ReadingElementFromFullBufferMakesItNotFull)
{
TypedRingBuffer<int *> rb(2);
ASSERT_TRUE(rb.ok());
int value0 = 123;
int value1 = 231;
rb.write(&value0);
rb.write(&value1);
EXPECT_TRUE(rb.full());
int *retrieved;
// Reading deletes the element.
EXPECT_TRUE(rb.read(&retrieved));
EXPECT_FALSE(rb.full());
}
TEST(RingBuffer, ZeroSizeBufferCanBeWrittenToOnce)
{
TypedRingBuffer<int *> rb(0);
ASSERT_TRUE(rb.ok());
int value0 = 123;
// Strange behaviour: we can write one element to a 0-size buffer.
EXPECT_EQ(nullptr, rb.write(&value0));
EXPECT_EQ(&value0, rb.write(&value0));
int *retrieved = nullptr;
// But then we can't read it.
EXPECT_FALSE(rb.read(&retrieved));
EXPECT_EQ(nullptr, retrieved);
}
TEST(RingBuffer, ReadingFromEmptyBufferFails)
{
TypedRingBuffer<int *> rb(2);
ASSERT_TRUE(rb.ok());
int *retrieved;
EXPECT_FALSE(rb.read(&retrieved));
}
TEST(RingBuffer, WritingToBufferWhenFullOverwritesBeginning)
{
TypedRingBuffer<int *> rb(2);
ASSERT_TRUE(rb.ok());
int value0 = 123;
int value1 = 231;
int value2 = 312;
int value3 = 432;
EXPECT_EQ(nullptr, rb.write(&value0));
EXPECT_EQ(nullptr, rb.write(&value1));
EXPECT_TRUE(rb.contains(&value0));
EXPECT_TRUE(rb.contains(&value1));
// Adding another element evicts the first element.
EXPECT_EQ(&value0, rb.write(&value2));
EXPECT_FALSE(rb.contains(&value0));
EXPECT_TRUE(rb.contains(&value2));
// Adding another evicts the second.
EXPECT_EQ(&value1, rb.write(&value3));
EXPECT_FALSE(rb.contains(&value1));
EXPECT_TRUE(rb.contains(&value3));
}
TEST(RingBuffer, SizeIsNumberOfElementsInBuffer)
{
TypedRingBuffer<int *> rb(10);
ASSERT_TRUE(rb.ok());
int value0 = 123;
EXPECT_EQ(rb.size(), 0);
rb.write(&value0);
EXPECT_EQ(rb.size(), 1);
rb.write(&value0);
EXPECT_EQ(rb.size(), 2);
rb.write(&value0);
EXPECT_EQ(rb.size(), 3);
rb.write(&value0);
EXPECT_EQ(rb.size(), 4);
int *retrieved;
rb.read(&retrieved);
EXPECT_EQ(rb.size(), 3);
rb.read(&retrieved);
EXPECT_EQ(rb.size(), 2);
rb.read(&retrieved);
EXPECT_EQ(rb.size(), 1);
rb.read(&retrieved);
EXPECT_EQ(rb.size(), 0);
}
TEST(RingBuffer, SizeIsLimitedByMaxSize)
{
TypedRingBuffer<int *> rb(4);
ASSERT_TRUE(rb.ok());
int value0 = 123;
rb.write(&value0);
rb.write(&value0);
rb.write(&value0);
rb.write(&value0);
EXPECT_EQ(rb.size(), 4);
// Add one more.
rb.write(&value0);
// Still size is 4.
EXPECT_EQ(rb.size(), 4);
}
} // namespace
|