ts_RingBuffer.cpp
Go to the documentation of this file.
1 // this is for emacs file handling -*- mode: c++; indent-tabs-mode: nil -*-
2 
3 // -- BEGIN LICENSE BLOCK ----------------------------------------------
4 // This file is part of FZIs ic_workspace.
5 //
6 // This program is free software licensed under the LGPL
7 // (GNU LESSER GENERAL PUBLIC LICENSE Version 3).
8 // You can find a copy of this license in LICENSE folder in the top
9 // directory of the source code.
10 //
11 // © Copyright 2016 FZI Forschungszentrum Informatik, Karlsruhe, Germany
12 //
13 // -- END LICENSE BLOCK ------------------------------------------------
14 
15 //----------------------------------------------------------------------
22 //----------------------------------------------------------------------
23 #include <icl_core/RingBuffer.h>
24 
25 #include <boost/test/unit_test.hpp>
26 #include <boost/mpl/list.hpp>
27 
29 
30 BOOST_AUTO_TEST_SUITE(ts_RingBuffer)
31 
32 typedef boost::mpl::list<char, short, int, long, float, double> TestTypes;
33 
34 BOOST_AUTO_TEST_CASE_TEMPLATE(RingBufferCapacity, T, TestTypes)
35 {
36  RingBuffer<T> ringbuffer(10);
37 
38  // Check empty
39  BOOST_CHECK_EQUAL(ringbuffer.size(), 0u);
40  BOOST_CHECK_EQUAL(ringbuffer.capacity(), 10u);
41  BOOST_CHECK_EQUAL(ringbuffer.reserve(), 10u);
42  BOOST_CHECK_EQUAL(ringbuffer.empty(), true);
43  BOOST_CHECK_EQUAL(ringbuffer.full(), false);
44 
45  // Check some exceptions
46  bool read_exception_called = false;
47  try { ringbuffer.read(); }
48  catch (std::out_of_range&) { read_exception_called = true; }
49  BOOST_CHECK_EQUAL(read_exception_called, true);
50 
51  // Add one element and check size
52  ringbuffer.write(0);
53 
54  BOOST_CHECK_EQUAL(ringbuffer.size(), 1u);
55  BOOST_CHECK_EQUAL(ringbuffer.capacity(), 10u);
56  BOOST_CHECK_EQUAL(ringbuffer.reserve(), 9u);
57  BOOST_CHECK_EQUAL(ringbuffer.empty(), false);
58  BOOST_CHECK_EQUAL(ringbuffer.full(), false);
59 
60  // Add six more elements, check again
61  ringbuffer.write(1);
62  ringbuffer.write(2);
63  ringbuffer.write(3);
64  ringbuffer.write(4);
65  ringbuffer.write(5);
66  ringbuffer.write(6);
67 
68  BOOST_CHECK_EQUAL(ringbuffer.size(), 7u);
69  BOOST_CHECK_EQUAL(ringbuffer.capacity(), 10u);
70  BOOST_CHECK_EQUAL(ringbuffer.reserve(), 3u);
71  BOOST_CHECK_EQUAL(ringbuffer.empty(), false);
72  BOOST_CHECK_EQUAL(ringbuffer.full(), false);
73 
74  // Fill up, check full
75  ringbuffer.write(7);
76  ringbuffer.write(8);
77  ringbuffer.write(9);
78 
79  BOOST_CHECK_EQUAL(ringbuffer.size(), 10u);
80  BOOST_CHECK_EQUAL(ringbuffer.capacity(), 10u);
81  BOOST_CHECK_EQUAL(ringbuffer.reserve(), 0u);
82  BOOST_CHECK_EQUAL(ringbuffer.empty(), false);
83  BOOST_CHECK_EQUAL(ringbuffer.full(), true);
84 
85  // Check all contained element values
86  BOOST_CHECK_EQUAL(ringbuffer.at(0), T(0));
87  BOOST_CHECK_EQUAL(ringbuffer.at(1), T(1));
88  BOOST_CHECK_EQUAL(ringbuffer.at(2), T(2));
89  BOOST_CHECK_EQUAL(ringbuffer.at(3), T(3));
90  BOOST_CHECK_EQUAL(ringbuffer.at(4), T(4));
91  BOOST_CHECK_EQUAL(ringbuffer.at(5), T(5));
92  BOOST_CHECK_EQUAL(ringbuffer.at(6), T(6));
93  BOOST_CHECK_EQUAL(ringbuffer.at(7), T(7));
94  BOOST_CHECK_EQUAL(ringbuffer.at(8), T(8));
95  BOOST_CHECK_EQUAL(ringbuffer.at(9), T(9));
96 
97  // Remove the first four elements
98  BOOST_CHECK_EQUAL(ringbuffer.read(), T(0));
99  BOOST_CHECK_EQUAL(ringbuffer.read(), T(1));
100  BOOST_CHECK_EQUAL(ringbuffer.read(), T(2));
101  BOOST_CHECK_EQUAL(ringbuffer.read(), T(3));
102 
103  // Check size
104  BOOST_CHECK_EQUAL(ringbuffer.size(), 6u);
105  BOOST_CHECK_EQUAL(ringbuffer.capacity(), 10u);
106  BOOST_CHECK_EQUAL(ringbuffer.reserve(), 4u);
107  BOOST_CHECK_EQUAL(ringbuffer.empty(), false);
108  BOOST_CHECK_EQUAL(ringbuffer.full(), false);
109 
110  // Check remaining element values
111  BOOST_CHECK_EQUAL(ringbuffer.at(0), T(4));
112  BOOST_CHECK_EQUAL(ringbuffer.at(1), T(5));
113  BOOST_CHECK_EQUAL(ringbuffer.at(2), T(6));
114  BOOST_CHECK_EQUAL(ringbuffer.at(3), T(7));
115  BOOST_CHECK_EQUAL(ringbuffer.at(4), T(8));
116  BOOST_CHECK_EQUAL(ringbuffer.at(5), T(9));
117 
118  // Fill up again, check full
119  ringbuffer.write(10);
120  ringbuffer.write(11);
121  ringbuffer.write(12);
122  ringbuffer.write(13);
123 
124  BOOST_CHECK_EQUAL(ringbuffer.size(), 10u);
125  BOOST_CHECK_EQUAL(ringbuffer.capacity(), 10u);
126  BOOST_CHECK_EQUAL(ringbuffer.reserve(), 0u);
127  BOOST_CHECK_EQUAL(ringbuffer.empty(), false);
128  BOOST_CHECK_EQUAL(ringbuffer.full(), true);
129 
130  // Check all element values
131  BOOST_CHECK_EQUAL(ringbuffer.at(0), T(4));
132  BOOST_CHECK_EQUAL(ringbuffer.at(1), T(5));
133  BOOST_CHECK_EQUAL(ringbuffer.at(2), T(6));
134  BOOST_CHECK_EQUAL(ringbuffer.at(3), T(7));
135  BOOST_CHECK_EQUAL(ringbuffer.at(4), T(8));
136  BOOST_CHECK_EQUAL(ringbuffer.at(5), T(9));
137  BOOST_CHECK_EQUAL(ringbuffer.at(6), T(10));
138  BOOST_CHECK_EQUAL(ringbuffer.at(7), T(11));
139  BOOST_CHECK_EQUAL(ringbuffer.at(8), T(12));
140  BOOST_CHECK_EQUAL(ringbuffer.at(9), T(13));
141 
142  // Check some exceptions
143  bool write_exception_called = false;
144  try { ringbuffer.write(14); }
145  catch (std::out_of_range&) { write_exception_called = true; }
146  BOOST_CHECK_EQUAL(write_exception_called, true);
147 
148  // Skip some elements, check size
149  ringbuffer.skip();
150  ringbuffer.skip(3);
151 
152  BOOST_CHECK_EQUAL(ringbuffer.size(), 6u);
153  BOOST_CHECK_EQUAL(ringbuffer.capacity(), 10u);
154  BOOST_CHECK_EQUAL(ringbuffer.reserve(), 4u);
155  BOOST_CHECK_EQUAL(ringbuffer.empty(), false);
156  BOOST_CHECK_EQUAL(ringbuffer.full(), false);
157 
158  // Check all element values
159  BOOST_CHECK_EQUAL(ringbuffer.at(0), T(8));
160  BOOST_CHECK_EQUAL(ringbuffer.at(1), T(9));
161  BOOST_CHECK_EQUAL(ringbuffer.at(2), T(10));
162  BOOST_CHECK_EQUAL(ringbuffer.at(3), T(11));
163  BOOST_CHECK_EQUAL(ringbuffer.at(4), T(12));
164  BOOST_CHECK_EQUAL(ringbuffer.at(5), T(13));
165 
166  // Empty buffer, check empty
167  ringbuffer.skip(10);
168 
169  BOOST_CHECK_EQUAL(ringbuffer.size(), 0u);
170  BOOST_CHECK_EQUAL(ringbuffer.capacity(), 10u);
171  BOOST_CHECK_EQUAL(ringbuffer.reserve(), 10u);
172  BOOST_CHECK_EQUAL(ringbuffer.empty(), true);
173  BOOST_CHECK_EQUAL(ringbuffer.full(), false);
174 
175  // Check some exceptions
176  bool skip_exception_called = false;
177  try { ringbuffer.skip(); }
178  catch (std::out_of_range&) { skip_exception_called = true; }
179  BOOST_CHECK_EQUAL(skip_exception_called, true);
180 
181  // Check arrays. Since the ringbuffer has been emptied completely,
182  // the read/write pointers should be at entry 0 again.
183  BOOST_CHECK_EQUAL(ringbuffer.arrayOne().first, ringbuffer.arrayTwo().first);
184 
185  BOOST_CHECK_EQUAL(ringbuffer.arrayOne().second, 0u);
186  BOOST_CHECK_EQUAL(ringbuffer.arrayTwo().second, 0u);
187  BOOST_CHECK_EQUAL(ringbuffer.emptyArrayOne().second, 10u);
188  BOOST_CHECK_EQUAL(ringbuffer.emptyArrayTwo().second, 0u);
189 
190  // Add some more elemets to move the read/write pointers.
191  ringbuffer.write(0);
192  ringbuffer.write(1);
193  ringbuffer.write(2);
194  ringbuffer.write(3);
195  ringbuffer.write(4);
196  ringbuffer.skip(2);
197 
198  // [ - | 2 3 4 - - - - - - ]
199  BOOST_CHECK_EQUAL(ringbuffer.arrayOne().second, 3u);
200  BOOST_CHECK_EQUAL(ringbuffer.arrayTwo().second, 0u);
201  BOOST_CHECK_EQUAL(ringbuffer.emptyArrayOne().second, 6u);
202  BOOST_CHECK_EQUAL(ringbuffer.emptyArrayTwo().second, 1u);
203 
204  // Add some more elemets to move the read/write pointers.
205  ringbuffer.write(5);
206  ringbuffer.write(6);
207  ringbuffer.write(7);
208  ringbuffer.write(8);
209  ringbuffer.write(9);
210  ringbuffer.skip(3);
211 
212  // [ - - - - | 5 6 7 8 9 - ]
213  BOOST_CHECK_EQUAL(ringbuffer.arrayOne().second, 5u);
214  BOOST_CHECK_EQUAL(ringbuffer.arrayTwo().second, 0u);
215  BOOST_CHECK_EQUAL(ringbuffer.emptyArrayOne().second, 1u);
216  BOOST_CHECK_EQUAL(ringbuffer.emptyArrayTwo().second, 4u);
217 
218  // Add some more elemets to move the read/write pointers.
219  ringbuffer.write(10);
220  ringbuffer.write(11);
221  ringbuffer.write(12);
222  ringbuffer.write(13);
223  ringbuffer.skip(3);
224 
225  // [ 11 12 13 - - - - | 8 9 10 ]
226  BOOST_CHECK_EQUAL(ringbuffer.arrayOne().second, 3u);
227  BOOST_CHECK_EQUAL(ringbuffer.arrayTwo().second, 3u);
228  BOOST_CHECK_EQUAL(ringbuffer.emptyArrayOne().second, 4u);
229  BOOST_CHECK_EQUAL(ringbuffer.emptyArrayTwo().second, 0u);
230 
231  // Check that iterators behave correctly.
232  size_t i = 0;
233  for (typename RingBuffer<T>::iterator it = ringbuffer.begin(); it != ringbuffer.end(); ++it, ++i)
234  {
235  BOOST_CHECK_EQUAL(ringbuffer.at(i), *it);
236  }
237  // Same for postfix increment.
238  i = 0;
239  for (typename RingBuffer<T>::iterator it = ringbuffer.begin(); it != ringbuffer.end(); it++, ++i)
240  {
241  BOOST_CHECK_EQUAL(ringbuffer.at(i), *it);
242  }
243  // Check that const_iterators behave correctly.
244  i = 0;
245  for (typename RingBuffer<T>::const_iterator it = ringbuffer.begin(); it != ringbuffer.end(); ++it, ++i)
246  {
247  BOOST_CHECK_EQUAL(ringbuffer.at(i), *it);
248  }
249  // Same for postfix increment.
250  i = 0;
251  for (typename RingBuffer<T>::const_iterator it = ringbuffer.begin(); it != ringbuffer.end(); it++, ++i)
252  {
253  BOOST_CHECK_EQUAL(ringbuffer.at(i), *it);
254  }
255 
256  // Check that we can move the iterator around.
257  BOOST_CHECK((ringbuffer.begin() + 3) - 3 == ringbuffer.begin());
258  BOOST_CHECK((ringbuffer.begin() - 3) + 3 == ringbuffer.begin());
259  BOOST_CHECK_EQUAL(ringbuffer.end() - ringbuffer.begin(), 6);
260  BOOST_CHECK_EQUAL(ringbuffer.begin() - ringbuffer.end(), -6);
261 
262  // Now make some more room, then add some elements externally.
263  ringbuffer.skip(3);
264  // [ 11 12 13 - - - - - - - | ]
265  T *empty_space = ringbuffer.emptyArrayOne().first;
266  for (size_t i=0; i<5; ++i)
267  {
268  empty_space[i] = T(i+14);
269  }
270  // [ 11 12 13 (14) (15) (16) (17) (18) - - | ]
271  ringbuffer.fakeWrite(5);
272 
273  // [ 11 12 13 14 15 16 17 18 - - | ]
274  BOOST_CHECK_EQUAL(ringbuffer.size(), 8u);
275  BOOST_CHECK_EQUAL(ringbuffer.capacity(), 10u);
276  BOOST_CHECK_EQUAL(ringbuffer.reserve(), 2u);
277  BOOST_CHECK_EQUAL(ringbuffer.empty(), false);
278  BOOST_CHECK_EQUAL(ringbuffer.full(), false);
279  BOOST_CHECK_EQUAL(ringbuffer.at(0), T(11));
280  BOOST_CHECK_EQUAL(ringbuffer.at(1), T(12));
281  BOOST_CHECK_EQUAL(ringbuffer.at(2), T(13));
282  BOOST_CHECK_EQUAL(ringbuffer.at(3), T(14));
283  BOOST_CHECK_EQUAL(ringbuffer.at(4), T(15));
284  BOOST_CHECK_EQUAL(ringbuffer.at(5), T(16));
285  BOOST_CHECK_EQUAL(ringbuffer.at(6), T(17));
286  BOOST_CHECK_EQUAL(ringbuffer.at(7), T(18));
287 
288  BOOST_CHECK_EQUAL(ringbuffer.arrayOne().second, 8u);
289  BOOST_CHECK_EQUAL(ringbuffer.arrayTwo().second, 0u);
290  BOOST_CHECK_EQUAL(ringbuffer.emptyArrayOne().second, 2u);
291  BOOST_CHECK_EQUAL(ringbuffer.emptyArrayTwo().second, 0u);
292 
293  // Now fill it up completely.
294  ringbuffer.write(T(19));
295  ringbuffer.write(T(20));
296  BOOST_CHECK_EQUAL(ringbuffer.size(), 10u);
297  BOOST_CHECK_EQUAL(ringbuffer.capacity(), 10u);
298  BOOST_CHECK_EQUAL(ringbuffer.reserve(), 0u);
299  BOOST_CHECK_EQUAL(ringbuffer.empty(), false);
300  BOOST_CHECK_EQUAL(ringbuffer.full(), true);
301  BOOST_CHECK_EQUAL(ringbuffer.at(8), T(19));
302  BOOST_CHECK_EQUAL(ringbuffer.at(9), T(20));
303  BOOST_CHECK_EQUAL(ringbuffer.arrayOne().second, 10u);
304  BOOST_CHECK_EQUAL(ringbuffer.arrayTwo().second, 0u);
305  BOOST_CHECK_EQUAL(ringbuffer.emptyArrayOne().second, 0u);
306  BOOST_CHECK_EQUAL(ringbuffer.emptyArrayTwo().second, 0u);
307 
308  // Check that we can move the iterator around.
309  BOOST_CHECK((ringbuffer.begin() + 3) - 3 == ringbuffer.begin());
310  BOOST_CHECK((ringbuffer.begin() - 3) + 3 == ringbuffer.begin());
311  BOOST_CHECK_EQUAL(ringbuffer.end() - ringbuffer.begin(), 10);
312  BOOST_CHECK_EQUAL(ringbuffer.begin() - ringbuffer.end(), -10);
313 }
314 
315 BOOST_AUTO_TEST_CASE_TEMPLATE(RingBufferConstness, T, TestTypes)
316 {
317  RingBuffer<T> ringbuffer(10);
318 
319  // Add some elements until it's completely full.
320  ringbuffer.write(0);
321  ringbuffer.write(1);
322  ringbuffer.write(2);
323  ringbuffer.write(3);
324  ringbuffer.write(4);
325  ringbuffer.write(5);
326  ringbuffer.write(6);
327  ringbuffer.write(7);
328  ringbuffer.write(8);
329  ringbuffer.write(9);
330 
331  const RingBuffer<T>& ringbuffer_const = ringbuffer;
332 
333  BOOST_CHECK_EQUAL(ringbuffer_const.size(), 10u);
334  BOOST_CHECK_EQUAL(ringbuffer_const.capacity(), 10u);
335  BOOST_CHECK_EQUAL(ringbuffer_const.reserve(), 0u);
336  BOOST_CHECK_EQUAL(ringbuffer_const.empty(), false);
337  BOOST_CHECK_EQUAL(ringbuffer_const.full(), true);
338 
339  // Check all contained element values
340  BOOST_CHECK_EQUAL(ringbuffer_const.at(0), T(0));
341  BOOST_CHECK_EQUAL(ringbuffer_const.at(1), T(1));
342  BOOST_CHECK_EQUAL(ringbuffer_const.at(2), T(2));
343  BOOST_CHECK_EQUAL(ringbuffer_const.at(3), T(3));
344  BOOST_CHECK_EQUAL(ringbuffer_const.at(4), T(4));
345  BOOST_CHECK_EQUAL(ringbuffer_const.at(5), T(5));
346  BOOST_CHECK_EQUAL(ringbuffer_const.at(6), T(6));
347  BOOST_CHECK_EQUAL(ringbuffer_const.at(7), T(7));
348  BOOST_CHECK_EQUAL(ringbuffer_const.at(8), T(8));
349  BOOST_CHECK_EQUAL(ringbuffer_const.at(9), T(9));
350 
351  // Check that const_iterators behave correctly.
352  size_t i = 0;
353  for (typename RingBuffer<T>::const_iterator it = ringbuffer_const.begin(); it != ringbuffer_const.end(); ++it, ++i)
354  {
355  BOOST_CHECK_EQUAL(ringbuffer_const.at(i), *it);
356  }
357  // Same for postfix increment.
358  i = 0;
359  for (typename RingBuffer<T>::const_iterator it = ringbuffer_const.begin(); it != ringbuffer_const.end(); it++, ++i)
360  {
361  BOOST_CHECK_EQUAL(ringbuffer_const.at(i), *it);
362  }
363 
364  // Check that we can move the iterator around.
365  BOOST_CHECK((ringbuffer_const.begin() + 3) - 3 == ringbuffer_const.begin());
366  BOOST_CHECK((ringbuffer_const.begin() - 3) + 3 == ringbuffer_const.begin());
367  BOOST_CHECK_EQUAL(ringbuffer_const.end() - ringbuffer_const.begin(), 10);
368  BOOST_CHECK_EQUAL(ringbuffer_const.begin() - ringbuffer_const.end(), -10);
369 }
370 
371 BOOST_AUTO_TEST_SUITE_END()
const T & at(size_type pos) const
Read an arbitrary element from the ring buffer without removing it.
Definition: RingBuffer.h:269
size_type capacity() const
Returns the capacity of the ring buffer.
Definition: RingBuffer.h:362
boost::mpl::list< char, short, uint32_t, int, long, float, double > TestTypes
void fakeWrite(size_t count)
Definition: RingBuffer.hpp:160
size_type size() const
Returns the current number of elements in the ring buffer.
Definition: RingBuffer.h:349
void skip()
Removes an element from the ring buffer without returning it.
Definition: RingBuffer.h:312
bool empty() const
Returns true if the buffer is empty.
Definition: RingBuffer.h:224
T read()
Removes an element from the ring buffer provided there is one present.
Definition: RingBuffer.h:333
void write(const T &val, bool overwrite=false)
Adds an element to the ring buffer provided there is room.
Definition: RingBuffer.h:234
size_type reserve() const
Returns the remaining reserve (free space) of the ring buffer.
Definition: RingBuffer.h:365
const_iterator end() const
Definition: RingBuffer.h:416
array_range arrayOne()
Definition: RingBuffer.hpp:29
array_range emptyArrayOne()
Definition: RingBuffer.hpp:81
array_range arrayTwo()
Definition: RingBuffer.hpp:55
BOOST_AUTO_TEST_CASE_TEMPLATE(RingBufferCapacity, T, TestTypes)
array_range emptyArrayTwo()
Definition: RingBuffer.hpp:121
A simple ring buffer implementation based on std::vector.
Definition: RingBuffer.h:45
bool full() const
Returns true if the buffer is full.
Definition: RingBuffer.h:227
const_iterator begin() const
Definition: RingBuffer.h:411


fzi_icl_core
Author(s):
autogenerated on Mon Jun 10 2019 13:17:58