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