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 auto iter_diff = buf.end() - buf.begin();
21 CHECK(ptrdiff_t(buf.size()) == iter_diff);
22
23 if (expectedSize != 0) {
24 CHECK(buf.front() == expectedElements.front());
25 CHECK(buf.back() == expectedElements.back());
26 }
27
28 for (auto i : xrange(expectedSize)) {
29 CHECK(buf[i] == expectedElements[i]);
30 }
31
32 auto it1 = expectedElements.begin();
33 for (auto& i : buf) {
34 CHECK(i == *it1++);
35 }
36
37 auto rit = expectedElements.rbegin();
38 for (auto it = buf.rbegin(); it != buf.rend(); ++it) {
39 CHECK(*it == *rit++);
40 }
41}
42TEST_CASE("circular_buffer") {
43 circular_buffer<int> buf1; check_buf(buf1, 0, {});
44 buf1.set_capacity(3); check_buf(buf1, 3, {});
45 buf1.push_back(1); check_buf(buf1, 3, {1});
46 buf1.push_back(2); check_buf(buf1, 3, {1,2});
47 buf1.push_front(3); check_buf(buf1, 3, {3,1,2});
48 buf1.pop_front(); check_buf(buf1, 3, {1,2});
49 buf1.pop_back(); check_buf(buf1, 3, {1});
50 buf1.clear(); check_buf(buf1, 3, {});
51
52 circular_buffer<int> buf2(5); check_buf(buf2, 5, {});
53 buf1.push_back({4,5}); check_buf(buf1, 3, {4,5});
54 buf2.push_back({7,8,9}); check_buf(buf2, 5, {7,8,9});
55
56 swap(buf1, buf2); check_buf(buf1, 5, {7,8,9});
57 check_buf(buf2, 3, {4,5});
58}
59
60static void check_buf(
61 const circular_buffer<unique_ptr<int>>& buf,
62 size_t expectedCapacity, const vector<int>& expectedElements)
63{
64 auto expectedSize = expectedElements.size();
65 REQUIRE(buf.size() == expectedSize);
66 CHECK(buf.capacity() == expectedCapacity);
67 CHECK(buf.reserve() == expectedCapacity - expectedSize);
68 CHECK(buf.empty() == (expectedSize == 0));
69 CHECK(buf.full() == (expectedCapacity == expectedSize));
70
71 auto iter_diff = buf.end() - buf.begin();
72 CHECK(ptrdiff_t(buf.size()) == iter_diff);
73
74 if (expectedSize != 0) {
75 CHECK(*buf.front() == expectedElements.front());
76 CHECK(*buf.back() == expectedElements.back());
77 }
78
79 for (auto i : xrange(expectedSize)) {
80 CHECK(*buf[i] == expectedElements[i]);
81 }
82
83 auto it1 = expectedElements.begin();
84 for (auto& i : buf) {
85 CHECK(*i == *it1++);
86 }
87
88 auto rit = expectedElements.rbegin();
89 for (auto it = buf.rbegin(); it != buf.rend(); ++it) {
90 CHECK(**it == *rit++);
91 }
92}
93TEST_CASE("circular_buffer, move-only") {
94 circular_buffer<unique_ptr<int>> buf1; check_buf(buf1, 0, {});
95 buf1.set_capacity(3); check_buf(buf1, 3, {});
96 buf1.push_back (make_unique<int>(1)); check_buf(buf1, 3, {1});
97 buf1.push_back (make_unique<int>(2)); check_buf(buf1, 3, {1,2});
98 buf1.push_front(make_unique<int>(3)); check_buf(buf1, 3, {3,1,2});
99 buf1.pop_front(); check_buf(buf1, 3, {1,2});
100 buf1.pop_back(); check_buf(buf1, 3, {1});
101 buf1.clear(); check_buf(buf1, 3, {});
102
103 // doesn't work, see
104 // http://stackoverflow.com/questions/8193102/initializer-list-and-move-semantics
105 //buf1.push_back({make_unique<int>(4),
106 // make_unique<int>(5)}); check_buf(buf1, 3, {4,5});
107}
108
109static void check_queue(
110 const cb_queue<int>& q, int expectedCapacity,
111 const vector<int>& expectedElements)
112{
113 check_buf(q.getBuffer(), expectedCapacity, expectedElements);
114}
115TEST_CASE("cb_queue") {
116 cb_queue<int> q; check_queue(q, 0, {});
117 q.push_back(1); check_queue(q, 4, {1});
118 q.push_back(2); check_queue(q, 4, {1,2});
119 CHECK(q.pop_front() == 1); check_queue(q, 4, {2});
120 q.push_back({4,5,6,7}); check_queue(q, 8, {2,4,5,6,7});
121 CHECK(q.pop_front() == 2); check_queue(q, 8, {4,5,6,7});
122 CHECK(q.pop_front() == 4); check_queue(q, 8, {5,6,7});
123 q.clear(); check_queue(q, 8, {});
124}
125
126static void check_queue(
127 const cb_queue<unique_ptr<int>>& q, int expectedCapacity,
128 const vector<int>& expectedElements)
129{
130 check_buf(q.getBuffer(), expectedCapacity, expectedElements);
131}
132TEST_CASE("cb_queue, move-only") {
133 cb_queue<unique_ptr<int>> q; check_queue(q, 0, {});
134 q.push_back(make_unique<int>(1)); check_queue(q, 4, {1});
135 q.push_back(make_unique<int>(2)); check_queue(q, 4, {1,2});
136 CHECK(*q.pop_front() == 1); check_queue(q, 4, {2});
137 q.clear(); check_queue(q, 4, {});
138}
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