openMSX
circular_buffer_test.cc
Go to the documentation of this file.
1#include "catch.hpp"
2#include "circular_buffer.hh"
3#include "xrange.hh"
4#include <memory>
5#include <vector>
6
7using namespace std;
8
9static void check_buf(
10 const circular_buffer<int>& buf,
11 size_t expectedCapacity, const vector<int>& expectedElements)
12{
13 auto expectedSize = expectedElements.size();
14 REQUIRE(buf.size() == expectedSize);
15 CHECK(buf.capacity() == expectedCapacity);
16 CHECK(buf.reserve() == expectedCapacity - expectedSize);
17 CHECK(buf.empty() == (expectedSize == 0));
18 CHECK(buf.full() == (expectedCapacity == expectedSize));
19
20 if (expectedSize != 0) {
21 CHECK(buf.front() == expectedElements.front());
22 CHECK(buf.back() == expectedElements.back());
23 }
24
25 for (auto i : xrange(expectedSize)) {
26 CHECK(buf[i] == expectedElements[i]);
27 }
28
29 auto it1 = expectedElements.begin();
30 for (auto& i : buf) {
31 CHECK(i == *it1++);
32 }
33
34 auto rit = expectedElements.rbegin();
35 for (auto it = buf.rbegin(); it != buf.rend(); ++it) {
36 CHECK(*it == *rit++);
37 }
38}
39TEST_CASE("circular_buffer") {
40 circular_buffer<int> buf1; check_buf(buf1, 0, {});
41 buf1.set_capacity(3); check_buf(buf1, 3, {});
42 buf1.push_back(1); check_buf(buf1, 3, {1});
43 buf1.push_back(2); check_buf(buf1, 3, {1,2});
44 buf1.push_front(3); check_buf(buf1, 3, {3,1,2});
45 buf1.pop_front(); check_buf(buf1, 3, {1,2});
46 buf1.pop_back(); check_buf(buf1, 3, {1});
47 buf1.clear(); check_buf(buf1, 3, {});
48
49 circular_buffer<int> buf2(5); check_buf(buf2, 5, {});
50 buf1.push_back({4,5}); check_buf(buf1, 3, {4,5});
51 buf2.push_back({7,8,9}); check_buf(buf2, 5, {7,8,9});
52
53 swap(buf1, buf2); check_buf(buf1, 5, {7,8,9});
54 check_buf(buf2, 3, {4,5});
55}
56
57static void check_buf(
58 const circular_buffer<unique_ptr<int>>& buf,
59 size_t expectedCapacity, const vector<int>& expectedElements)
60{
61 auto expectedSize = expectedElements.size();
62 REQUIRE(buf.size() == expectedSize);
63 CHECK(buf.capacity() == expectedCapacity);
64 CHECK(buf.reserve() == expectedCapacity - expectedSize);
65 CHECK(buf.empty() == (expectedSize == 0));
66 CHECK(buf.full() == (expectedCapacity == expectedSize));
67
68 if (expectedSize != 0) {
69 CHECK(*buf.front() == expectedElements.front());
70 CHECK(*buf.back() == expectedElements.back());
71 }
72
73 for (auto i : xrange(expectedSize)) {
74 CHECK(*buf[i] == expectedElements[i]);
75 }
76
77 auto it1 = expectedElements.begin();
78 for (auto& i : buf) {
79 CHECK(*i == *it1++);
80 }
81
82 auto rit = expectedElements.rbegin();
83 for (auto it = buf.rbegin(); it != buf.rend(); ++it) {
84 CHECK(**it == *rit++);
85 }
86}
87TEST_CASE("circular_buffer, move-only") {
88 circular_buffer<unique_ptr<int>> buf1; check_buf(buf1, 0, {});
89 buf1.set_capacity(3); check_buf(buf1, 3, {});
90 buf1.push_back (make_unique<int>(1)); check_buf(buf1, 3, {1});
91 buf1.push_back (make_unique<int>(2)); check_buf(buf1, 3, {1,2});
92 buf1.push_front(make_unique<int>(3)); check_buf(buf1, 3, {3,1,2});
93 buf1.pop_front(); check_buf(buf1, 3, {1,2});
94 buf1.pop_back(); check_buf(buf1, 3, {1});
95 buf1.clear(); check_buf(buf1, 3, {});
96
97 // doesn't work, see
98 // http://stackoverflow.com/questions/8193102/initializer-list-and-move-semantics
99 //buf1.push_back({make_unique<int>(4),
100 // make_unique<int>(5)}); check_buf(buf1, 3, {4,5});
101}
102
103static void check_queue(
104 const cb_queue<int>& q, int expectedCapacity,
105 const vector<int>& expectedElements)
106{
107 check_buf(q.getBuffer(), expectedCapacity, expectedElements);
108}
109TEST_CASE("cb_queue") {
110 cb_queue<int> q; check_queue(q, 0, {});
111 q.push_back(1); check_queue(q, 4, {1});
112 q.push_back(2); check_queue(q, 4, {1,2});
113 CHECK(q.pop_front() == 1); check_queue(q, 4, {2});
114 q.push_back({4,5,6,7}); check_queue(q, 8, {2,4,5,6,7});
115 CHECK(q.pop_front() == 2); check_queue(q, 8, {4,5,6,7});
116 CHECK(q.pop_front() == 4); check_queue(q, 8, {5,6,7});
117 q.clear(); check_queue(q, 8, {});
118}
119
120static void check_queue(
121 const cb_queue<unique_ptr<int>>& q, int expectedCapacity,
122 const vector<int>& expectedElements)
123{
124 check_buf(q.getBuffer(), expectedCapacity, expectedElements);
125}
126TEST_CASE("cb_queue, move-only") {
127 cb_queue<unique_ptr<int>> q; check_queue(q, 0, {});
128 q.push_back(make_unique<int>(1)); check_queue(q, 4, {1});
129 q.push_back(make_unique<int>(2)); check_queue(q, 4, {1,2});
130 CHECK(*q.pop_front() == 1); check_queue(q, 4, {2});
131 q.clear(); check_queue(q, 4, {});
132}
TEST_CASE("circular_buffer")
This implements a queue on top of circular_buffer (not part of boost).
auto & getBuffer()
void push_back(U &&u)
Circular buffer class, based on boost::circular_buffer/.
void push_front(T2 &&t)
void push_back(T2 &&t)
size_t size() const
void set_capacity(size_t new_capacity)
size_t capacity() const
size_t reserve() const
CHECK(m3==m3)
STL namespace.
constexpr auto xrange(T e)
Definition xrange.hh:132