Direct-BT  2.3.1
Direct-BT - Direct Bluetooth Programming.
test_lfringbuffer02.cpp
Go to the documentation of this file.
1 /*
2  * Author: Sven Gothel <sgothel@jausoft.com>
3  * Copyright (c) 2020 Gothel Software e.K.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sublicense, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be
14  * included in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 #include <iostream>
25 #include <cassert>
26 #include <cinttypes>
27 #include <cstring>
28 #include <memory>
29 
30 #define CATCH_CONFIG_MAIN
31 #include <catch2/catch_amalgamated.hpp>
32 #include <jau/test/catch2_ext.hpp>
33 
34 #include <jau/ringbuffer.hpp>
35 
36 using namespace jau;
37 
39 
40 class Integer {
41  public:
43 
44  Integer(IntegralType v) : value(v) {}
45 
46  Integer() noexcept : value(0) { }
47 
48  Integer(const Integer &o) noexcept = default;
49  Integer(Integer &&o) noexcept = default;
50  Integer& operator=(const Integer &o) noexcept = default;
51  Integer& operator=(Integer &&o) noexcept = default;
52 
53  operator IntegralType() const {
54  return value;
55  }
56  IntegralType intValue() const { return value; }
57  static Integer valueOf(const IntegralType i) { return Integer(i); }
58 };
59 
63 
64 // Test examples.
66  private:
67 
68  TrivialTypeRingbuffer createEmpty(jau::nsize_t initialCapacity) {
69  TrivialTypeRingbuffer rb(Integer(-1), initialCapacity);
70  REQUIRE_MSG("empty "+rb.toString(), rb.isEmpty());
71  return rb;
72  }
73  TrivialTypeRingbuffer createFull(const std::vector<TrivialType> & source) {
74  TrivialTypeRingbuffer rb(Integer(-1), source);
75  REQUIRE_MSG("full "+rb.toString(), rb.isFull());
76  return rb;
77  }
78 
79  std::vector<TrivialType> createIntArray(const jau::nsize_t capacity, const IntegralType startValue) {
80  std::vector<TrivialType> array(capacity);
81  for(jau::nsize_t i=0; i<capacity; i++) {
82  array[i] = TrivialType(startValue+i);
83  }
84  return array;
85  }
86 
87  void readTestImpl(TrivialTypeRingbuffer &rb, bool clearRef, jau::nsize_t capacity, jau::nsize_t len, IntegralType startValue) {
88  (void) clearRef;
89 
90  jau::nsize_t preSize = rb.getSize();
91  REQUIRE_MSG("capacity "+rb.toString(), capacity == rb.capacity());
92  REQUIRE_MSG("capacity at read "+std::to_string(len)+" elems: "+rb.toString(), capacity >= len);
93  REQUIRE_MSG("size at read "+std::to_string(len)+" elems: "+rb.toString(), preSize >= len);
94  REQUIRE_MSG("not empty "+rb.toString(), !rb.isEmpty());
95 
96  for(jau::nsize_t i=0; i<len; i++) {
97  TrivialType svI = rb.get();
98  REQUIRE_MSG("not empty at read #"+std::to_string(i+1)+": "+rb.toString(), svI!=TrivialTypeNullElem);
99  REQUIRE_MSG("value at read #"+std::to_string(i+1)+": "+rb.toString(), startValue+(IntegralType)i == svI.intValue());
100  }
101 
102  REQUIRE_MSG("size "+rb.toString(), preSize-len == rb.getSize());
103  REQUIRE_MSG("free slots after reading "+std::to_string(len)+": "+rb.toString(), rb.getFreeSlots()>= len);
104  REQUIRE_MSG("not full "+rb.toString(), !rb.isFull());
105  }
106  void readTestImpl2(TrivialTypeRingbuffer &rb, bool clearRef, jau::nsize_t capacity, jau::nsize_t len, IntegralType startValue) {
107  (void) clearRef;
108 
109  jau::nsize_t preSize = rb.getSize();
110  REQUIRE_MSG("capacity "+rb.toString(), capacity == rb.capacity());
111  REQUIRE_MSG("capacity at read "+std::to_string(len)+" elems: "+rb.toString(), capacity >= len);
112  REQUIRE_MSG("size at read "+std::to_string(len)+" elems: "+rb.toString(), preSize >= len);
113  REQUIRE_MSG("not empty "+rb.toString(), !rb.isEmpty());
114 
115  for(jau::nsize_t i=0; i<len; i++) {
116  TrivialType svI;
117  REQUIRE_MSG("ringbuffer get", rb.get(svI));
118  REQUIRE_MSG("not empty at read #"+std::to_string(i+1)+": "+rb.toString(), svI!=TrivialTypeNullElem);
119  REQUIRE_MSG("value at read #"+std::to_string(i+1)+": "+rb.toString(), startValue+(IntegralType)i == svI.intValue());
120  }
121 
122  REQUIRE_MSG("size "+rb.toString(), preSize-len == rb.getSize());
123  REQUIRE_MSG("free slots after reading "+std::to_string(len)+": "+rb.toString(), rb.getFreeSlots()>= len);
124  REQUIRE_MSG("not full "+rb.toString(), !rb.isFull());
125  }
126 
127  void readRangeTestImpl(TrivialTypeRingbuffer &rb, bool clearRef, jau::nsize_t capacity, jau::nsize_t len, IntegralType startValue) {
128  (void) clearRef;
129 
130  jau::nsize_t preSize = rb.getSize();
131  REQUIRE_MSG("capacity "+rb.toString(), capacity == rb.capacity());
132  REQUIRE_MSG("capacity at read "+std::to_string(len)+" elems: "+rb.toString(), capacity >= len);
133  REQUIRE_MSG("size at read "+std::to_string(len)+" elems: "+rb.toString(), preSize >= len);
134  REQUIRE_MSG("not empty "+rb.toString(), !rb.isEmpty());
135 
136  std::vector<TrivialType> array(len);
137  REQUIRE_MSG("get-range of "+std::to_string(array.size())+" elem in "+rb.toString(), len==rb.get( &(*array.begin()), len, len) );
138 
139  REQUIRE_MSG("size "+rb.toString(), preSize-len == rb.getSize());
140  REQUIRE_MSG("free slots after reading "+std::to_string(len)+": "+rb.toString(), rb.getFreeSlots()>= len);
141  REQUIRE_MSG("not full "+rb.toString(), !rb.isFull());
142 
143  for(jau::nsize_t i=0; i<len; i++) {
144  TrivialType svI = array[i];
145  REQUIRE_MSG("not empty at read #"+std::to_string(i+1)+": "+rb.toString(), svI!=TrivialTypeNullElem);
146  REQUIRE_MSG("value at read #"+std::to_string(i+1)+": "+rb.toString(), startValue+(IntegralType)i == svI.intValue());
147  }
148  }
149 
150  void writeTestImpl(TrivialTypeRingbuffer &rb, jau::nsize_t capacity, jau::nsize_t len, IntegralType startValue) {
151  jau::nsize_t preSize = rb.getSize();
152 
153  REQUIRE_MSG("capacity "+rb.toString(), capacity == rb.capacity());
154  REQUIRE_MSG("capacity at write "+std::to_string(len)+" elems: "+rb.toString(), capacity >= len);
155  REQUIRE_MSG("size at write "+std::to_string(len)+" elems: "+rb.toString(), preSize+len <= capacity);
156  REQUIRE_MSG("not full "+rb.toString(), !rb.isFull());
157 
158  for(jau::nsize_t i=0; i<len; i++) {
159  std::string m = "buffer put #"+std::to_string(i)+": "+rb.toString();
160  REQUIRE_MSG(m, rb.put( TrivialType( startValue+i ) ) );
161  }
162 
163  REQUIRE_MSG("size "+rb.toString(), preSize+len == rb.getSize());
164  REQUIRE_MSG("not empty "+rb.toString(), !rb.isEmpty());
165  }
166 
167  void writeRangeTestImpl(TrivialTypeRingbuffer &rb, jau::nsize_t capacity, const std::vector<TrivialType> & data) {
168  jau::nsize_t preSize = rb.getSize();
169  jau::nsize_t postSize = preSize+data.size();
170 
171  REQUIRE_MSG("capacity "+rb.toString(), capacity == rb.capacity());
172  REQUIRE_MSG("capacity at write "+std::to_string(data.size())+" elems: "+rb.toString(), capacity >= data.size());
173  REQUIRE_MSG("size at write "+std::to_string(data.size())+" elems: "+rb.toString(), postSize<= capacity);
174  REQUIRE_MSG("not full "+rb.toString(), !rb.isFull());
175  REQUIRE_MSG("data fits in RB capacity "+rb.toString(), rb.capacity() >= data.size());
176  REQUIRE_MSG("data fits in RB free-slots "+rb.toString(), rb.getFreeSlots() >= data.size());
177 
178  REQUIRE_MSG("put-range of "+std::to_string(data.size())+" elem in "+rb.toString(), rb.put( &(*data.begin()), &(*data.end()) ) );
179 
180  REQUIRE_MSG("size "+rb.toString(), postSize == rb.getSize());
181  REQUIRE_MSG("not empty "+rb.toString(), !rb.isEmpty());
182  }
183 
184  void moveGetPutImpl(TrivialTypeRingbuffer &rb, jau::nsize_t pos) {
185  REQUIRE_MSG("not empty "+rb.toString(), !rb.isEmpty());
186  for(jau::nsize_t i=0; i<pos; i++) {
187  REQUIRE_MSG("moveFull.get "+rb.toString(), (IntegralType)i == rb.get().intValue());
188  REQUIRE_MSG("moveFull.put "+rb.toString(), rb.put( TrivialType( (IntegralType)i ) ) );
189  }
190  }
191 
192  void movePutGetImpl(TrivialTypeRingbuffer &rb, jau::nsize_t pos) {
193  REQUIRE_MSG("RB is full "+rb.toString(), !rb.isFull());
194  for(jau::nsize_t i=0; i<pos; i++) {
195  REQUIRE_MSG("moveEmpty.put "+rb.toString(), rb.put( TrivialType( 600+(IntegralType)i ) ) );
196  REQUIRE_MSG("moveEmpty.get "+rb.toString(), 600+(IntegralType)i == rb.get().intValue());
197  }
198  }
199 
200  public:
201 
203  TrivialTypeRingbuffer rb = createEmpty(11);
204 
205  std::string msg("Ringbuffer: uses_memcpy "+std::to_string(TrivialTypeRingbuffer::uses_memcpy)+
207  ", trivially_copyable "+std::to_string(std::is_trivially_copyable<typename TrivialTypeRingbuffer::value_type>::value)+
208  ", size "+std::to_string(sizeof(rb))+" bytes");
209  fprintf(stderr, "%s", msg.c_str());
210  REQUIRE_MSG("Ringbuffer<T> using memcpy", TrivialTypeRingbuffer::uses_memcpy);
211  REQUIRE_MSG("Ringbuffer<T> not using memset", !TrivialTypeRingbuffer::uses_memset);
212  }
213 
215  jau::nsize_t capacity = 11;
216  std::vector<TrivialType> source = createIntArray(capacity, 0);
217  TrivialTypeRingbuffer rb = createFull(source);
218  INFO_STR("test01_FullRead: Created / "+ rb.toString());
219  REQUIRE_MSG("full size "+rb.toString(), capacity == rb.getSize());
220  REQUIRE_MSG("full "+rb.toString(), rb.isFull());
221 
222  readTestImpl(rb, true, capacity, capacity, 0);
223  INFO_STR("test01_FullRead: PostRead / " + rb.toString());
224  REQUIRE_MSG("empty "+rb.toString(), rb.isEmpty());
225  }
226 
228  jau::nsize_t capacity = 11;
229  TrivialTypeRingbuffer rb = createEmpty(capacity);
230  INFO( std::string("test02_EmptyWrite: Created / ") + rb.toString().c_str());
231  REQUIRE_MSG("zero size "+rb.toString(), 0 == rb.getSize());
232  REQUIRE_MSG("empty "+rb.toString(), rb.isEmpty());
233 
234  writeTestImpl(rb, capacity, capacity, 0);
235  INFO( std::string("test02_EmptyWrite: PostWrite / ") + rb.toString().c_str());
236  REQUIRE_MSG("full size "+rb.toString(), capacity == rb.getSize());
237  REQUIRE_MSG("full "+rb.toString(), rb.isFull());
238 
239  readTestImpl(rb, true, capacity, capacity, 0);
240  INFO( std::string("test02_EmptyWrite: PostRead / ") + rb.toString().c_str());
241  REQUIRE_MSG("empty "+rb.toString(), rb.isEmpty());
242  }
243 
245 #if 1
246  {
247  jau::nsize_t capacity = 11;
248  TrivialTypeRingbuffer rb = createEmpty(capacity);
249  INFO( std::string("test03_EmptyWriteRange: Created / ") + rb.toString().c_str());
250  REQUIRE_MSG("zero size "+rb.toString(), 0 == rb.getSize());
251  REQUIRE_MSG("empty "+rb.toString(), rb.isEmpty());
252 
253  /**
254  * Move R == W == 0
255  * Empty [RW][][ ][ ][ ][ ][ ][ ][ ][ ][ ] ; start
256  */
257  std::vector<TrivialType> new_data = createIntArray(capacity, 0);
258  writeRangeTestImpl(rb, capacity, new_data);
259 
260  INFO( std::string("test03_EmptyWriteRange: PostWrite / ") + rb.toString().c_str());
261  REQUIRE_MSG("full size "+rb.toString(), capacity == rb.getSize());
262  REQUIRE_MSG("full "+rb.toString(), rb.isFull());
263 
264  readRangeTestImpl(rb, true, capacity, capacity, 0);
265  INFO( std::string("test03_EmptyWriteRange: PostRead / ") + rb.toString().c_str());
266  REQUIRE_MSG("empty "+rb.toString(), rb.isEmpty());
267  }
268 #endif
269 #if 1
270  {
271  jau::nsize_t capacity = 11;
272 
273  TrivialTypeRingbuffer rb = createEmpty(capacity);
274  INFO( std::string("test03_EmptyWriteRange: Created / ") + rb.toString().c_str());
275  REQUIRE_MSG("zero size "+rb.toString(), 0 == rb.getSize());
276  REQUIRE_MSG("empty "+rb.toString(), rb.isEmpty());
277 
278  /**
279  * Move R == W == 3
280  * Empty [RW][][ ][ ][ ][ ][ ][ ][ ][ ][ ] ; start
281  * Empty [ ][ ][ ][RW][ ][ ][ ][ ][ ][ ][ ]
282  */
284  rb.put(dummy);
285  rb.put(dummy);
286  rb.put(dummy);
287  rb.drop(3);
288 
289  std::vector<TrivialType> new_data = createIntArray(capacity, 0);
290  writeRangeTestImpl(rb, capacity, new_data);
291  // writeTestImpl(rb, capacity, capacity, 0);
292 
293  INFO( std::string("test03_EmptyWriteRange: PostWrite / ") + rb.toString().c_str());
294  REQUIRE_MSG("full size "+rb.toString(), capacity == rb.getSize());
295  REQUIRE_MSG("full "+rb.toString(), rb.isFull());
296 
297  readRangeTestImpl(rb, true, capacity, capacity, 0);
298  // readTestImpl(rb, true, capacity, capacity, 0);
299 
300  INFO( std::string("test03_EmptyWriteRange: PostRead / ") + rb.toString().c_str());
301  REQUIRE_MSG("empty "+rb.toString(), rb.isEmpty());
302  }
303 #endif
304 #if 1
305  {
306  jau::nsize_t capacity = 11;
307  TrivialTypeRingbuffer rb = createEmpty(capacity);
308  INFO( std::string("test03_EmptyWriteRange: Created / ") + rb.toString().c_str());
309  REQUIRE_MSG("zero size "+rb.toString(), 0 == rb.getSize());
310  REQUIRE_MSG("empty "+rb.toString(), rb.isEmpty());
311 
312  /**
313  * Move R == 2, W == 4, size 2
314  * Empty [RW][][ ][ ][ ][ ][ ][ ][ ][ ][ ] ; start
315  * Avail [ ][ ][R][.][W][ ][ ][ ][ ][ ][ ] ; W > R
316  */
318  rb.put(dummy); // r idx 0 -> 1
319  rb.put(dummy);
320  rb.put(dummy);
321  rb.put(dummy); // r idx 3 -> 4
322  rb.drop(2); // r idx 0 -> 2
323 
324  // left = 11 - 2
325  REQUIRE_MSG("size 2 "+rb.toString(), 2 == rb.getSize());
326  REQUIRE_MSG("available 11-2 "+rb.toString(), capacity-2 == rb.getFreeSlots());
327 
328  std::vector<TrivialType> new_data = createIntArray(capacity-2, 0);
329  writeRangeTestImpl(rb, capacity, new_data);
330  // writeTestImpl(rb, capacity, capacity-2, 0);
331 
332  INFO( std::string("test03_EmptyWriteRange: PostWrite / ") + rb.toString().c_str());
333  REQUIRE_MSG("full size "+rb.toString(), capacity == rb.getSize());
334  REQUIRE_MSG("full "+rb.toString(), rb.isFull());
335 
336  // take off 2 remaining dummies
337  rb.drop(2);
338  REQUIRE_MSG("size capacity-2 "+rb.toString(), capacity-2 == rb.getSize());
339 
340  readRangeTestImpl(rb, true, capacity, capacity-2, 0);
341  // readTestImpl(rb, true, capacity, capacity-2, 0);
342  INFO( std::string("test03_EmptyWriteRange: PostRead / ") + rb.toString().c_str());
343  REQUIRE_MSG("size 0 "+rb.toString(), 0 == rb.getSize());
344  REQUIRE_MSG("empty "+rb.toString(), rb.isEmpty());
345  }
346 #endif
347 #if 1
348  {
349  jau::nsize_t capacity = 11;
350  TrivialTypeRingbuffer rb = createEmpty(capacity);
351  INFO( std::string("test03_EmptyWriteRange: Created / ") + rb.toString().c_str());
352  REQUIRE_MSG("zero size "+rb.toString(), 0 == rb.getSize());
353  REQUIRE_MSG("empty "+rb.toString(), rb.isEmpty());
354 
355  /**
356  * Move R == 9, W == 1, size 3
357  * Empty [RW][][ ][ ][ ][ ][ ][ ][ ][ ][ ] ; start
358  * Avail [.][W][ ][ ][ ][ ][ ][ ][ ][R][.] ; W < R - 1
359  */
361  for(int i=0; i<11; i++) { rb.put(dummy); } // fill all
362  REQUIRE_MSG("full "+rb.toString(), rb.isFull());
363 
364  // for(int i=0; i<10; i++) { rb.get(); } // pull
365  rb.drop(10); // pull
366  REQUIRE_MSG("size 1"+rb.toString(), 1 == rb.getSize());
367 
368  for(int i=0; i<2; i++) { rb.put(dummy); } // fill 2 more
369  REQUIRE_MSG("size 3"+rb.toString(), 3 == rb.getSize());
370 
371  // left = 11 - 3
372  REQUIRE_MSG("available 11-3 "+rb.toString(), capacity-3 == rb.getFreeSlots());
373 
374  std::vector<TrivialType> new_data = createIntArray(capacity-3, 0);
375  writeRangeTestImpl(rb, capacity, new_data);
376  // writeTestImpl(rb, capacity, capacity-3, 0);
377 
378  INFO( std::string("test03_EmptyWriteRange: PostWrite / ") + rb.toString().c_str());
379  REQUIRE_MSG("full size "+rb.toString(), capacity == rb.getSize());
380  REQUIRE_MSG("full "+rb.toString(), rb.isFull());
381 
382  // take off 3 remaining dummies
383  rb.drop(3); // pull
384  // for(int i=0; i<3; i++) { rb.get(); } // pull
385  REQUIRE_MSG("size capacity-3 "+rb.toString(), capacity-3 == rb.getSize());
386 
387  readRangeTestImpl(rb, true, capacity, capacity-3, 0);
388  // readTestImpl(rb, true, capacity, capacity-3, 0);
389  INFO( std::string("test03_EmptyWriteRange: PostRead / ") + rb.toString().c_str());
390  REQUIRE_MSG("size 0 "+rb.toString(), 0 == rb.getSize());
391  REQUIRE_MSG("empty "+rb.toString(), rb.isEmpty());
392  }
393 #endif
394  }
395 
397  jau::nsize_t capacity = 11;
398  std::vector<TrivialType> source = createIntArray(capacity, 0);
399  TrivialTypeRingbuffer rb = createFull(source);
400  INFO_STR("test04_FullReadReset: Created / " + rb.toString());
401  REQUIRE_MSG("full "+rb.toString(), rb.isFull());
402 
403  rb.reset(source);
404  INFO_STR("test04_FullReadReset: Post Reset w/ source / " + rb.toString());
405  REQUIRE_MSG("full "+rb.toString(), rb.isFull());
406 
407  readTestImpl(rb, false, capacity, capacity, 0);
408  INFO_STR("test04_FullReadReset: Post Read / " + rb.toString());
409  REQUIRE_MSG("empty "+rb.toString(), rb.isEmpty());
410 
411  rb.reset(source);
412  INFO_STR("test04_FullReadReset: Post Reset w/ source / " + rb.toString());
413  REQUIRE_MSG("full "+rb.toString(), rb.isFull());
414 
415  readTestImpl2(rb, false, capacity, capacity, 0);
416  INFO_STR("test04_FullReadReset: Post Read / " + rb.toString());
417  REQUIRE_MSG("empty "+rb.toString(), rb.isEmpty());
418  }
419 
421  jau::nsize_t capacity = 11;
422  TrivialTypeRingbuffer rb = createEmpty(capacity);
423  REQUIRE_MSG("empty "+rb.toString(), rb.isEmpty());
424 
425  rb.clear();
426  REQUIRE_MSG("empty "+rb.toString(), rb.isEmpty());
427 
428  writeTestImpl(rb, capacity, capacity, 0);
429  REQUIRE_MSG("full "+rb.toString(), rb.isFull());
430 
431  readTestImpl(rb, false, capacity, capacity, 0);
432  REQUIRE_MSG("empty "+rb.toString(), rb.isEmpty());
433 
434  rb.clear();
435  REQUIRE_MSG("empty "+rb.toString(), rb.isEmpty());
436 
437  writeTestImpl(rb, capacity, capacity, 0);
438  REQUIRE_MSG("full "+rb.toString(), rb.isFull());
439 
440  readTestImpl2(rb, false, capacity, capacity, 0);
441  REQUIRE_MSG("empty "+rb.toString(), rb.isEmpty());
442  }
443 
445  jau::nsize_t capacity = 11;
446  std::vector<TrivialType> source = createIntArray(capacity, 0);
447  TrivialTypeRingbuffer rb = createFull(source);
448  REQUIRE_MSG("full "+rb.toString(), rb.isFull());
449 
450  rb.reset(source);
451  REQUIRE_MSG("full "+rb.toString(), rb.isFull());
452 
453  readTestImpl(rb, false, capacity, 5, 0);
454  REQUIRE_MSG("not empty "+rb.toString(), !rb.isEmpty());
455  REQUIRE_MSG("not Full "+rb.toString(), !rb.isFull());
456 
457  rb.reset(source);
458  REQUIRE_MSG("full "+rb.toString(), rb.isFull());
459 
460  readTestImpl(rb, false, capacity, capacity, 0);
461  REQUIRE_MSG("empty "+rb.toString(), rb.isEmpty());
462  }
463 
465  jau::nsize_t capacity = 11;
466  std::vector<TrivialType> source = createIntArray(capacity, 0);
467  TrivialTypeRingbuffer rb = createFull(source);
468  REQUIRE_MSG("full "+rb.toString(), rb.isFull());
469 
470  rb.reset(source);
471  REQUIRE_MSG("full "+rb.toString(), rb.isFull());
472 
473  moveGetPutImpl(rb, 5);
474  readTestImpl(rb, false, capacity, 5, 5);
475  REQUIRE_MSG("not empty "+rb.toString(), !rb.isEmpty());
476  REQUIRE_MSG("not Full "+rb.toString(), !rb.isFull());
477 
478  rb.reset(source);
479  REQUIRE_MSG("full "+rb.toString(), rb.isFull());
480 
481  readTestImpl(rb, false, capacity, capacity, 0);
482  REQUIRE_MSG("empty "+rb.toString(), rb.isEmpty());
483  }
484 
485  private:
486 
487  void test_GrowFullImpl(jau::nsize_t initialCapacity, jau::nsize_t pos) {
488  jau::nsize_t growAmount = 5;
489  jau::nsize_t grownCapacity = initialCapacity+growAmount;
490  std::vector<TrivialType> source = createIntArray(initialCapacity, 0);
491  TrivialTypeRingbuffer rb = createFull(source);
492 
493  for(jau::nsize_t i=0; i<initialCapacity; i++) {
494  TrivialType svI = rb.get();
495  REQUIRE_MSG("not empty at read #"+std::to_string(i+1)+": "+rb.toString(), svI!=TrivialTypeNullElem);
496  REQUIRE_MSG("value at read #"+std::to_string(i+1)+": "+rb.toString(), IntegralType((0+i)%initialCapacity) == svI.intValue());
497  }
498  REQUIRE_MSG("zero size "+rb.toString(), 0 == rb.getSize());
499 
500  rb.reset(source);
501  REQUIRE_MSG("orig size "+rb.toString(), initialCapacity == rb.getSize());
502 
503  moveGetPutImpl(rb, pos);
504  // PRINTM("X02 "+rb.toString());
505  // rb.dump(stderr, "X02");
506 
507  rb.recapacity(grownCapacity);
508  REQUIRE_MSG("capacity "+rb.toString(), grownCapacity == rb.capacity());
509  REQUIRE_MSG("orig size "+rb.toString(), initialCapacity == rb.getSize());
510  REQUIRE_MSG("not full "+rb.toString(), !rb.isFull());
511  REQUIRE_MSG("not empty "+rb.toString(), !rb.isEmpty());
512  // PRINTM("X03 "+rb.toString());
513  // rb.dump(stderr, "X03");
514 
515  for(jau::nsize_t i=0; i<growAmount; i++) {
516  REQUIRE_MSG("buffer not full at put #"+std::to_string(i)+": "+rb.toString(), rb.put( TrivialType( 100+i ) ) );
517  }
518  REQUIRE_MSG("new size "+rb.toString(), grownCapacity == rb.getSize());
519  REQUIRE_MSG("full "+rb.toString(), rb.isFull());
520 
521  for(jau::nsize_t i=0; i<initialCapacity; i++) {
522  TrivialType svI = rb.get();
523  // PRINTM("X05["+std::to_string(i)+"]: "+rb.toString()+", svI-null: "+std::to_string(svI==TrivialTypeNullElem));
524  REQUIRE_MSG("not empty at read #"+std::to_string(i+1)+": "+rb.toString(), svI!=TrivialTypeNullElem);
525  REQUIRE_MSG("value at read #"+std::to_string(i+1)+": "+rb.toString(), IntegralType((pos+i)%initialCapacity) == svI.intValue());
526  }
527 
528  for(jau::nsize_t i=0; i<growAmount; i++) {
529  TrivialType svI = rb.get();
530  // PRINTM("X07["+std::to_string(i)+"]: "+rb.toString()+", svI-null: "+std::to_string(svI==TrivialTypeNullElem));
531  REQUIRE_MSG("not empty at read #"+std::to_string(i+1)+": "+rb.toString(), svI!=TrivialTypeNullElem);
532  REQUIRE_MSG("value at read #"+std::to_string(i+1)+": "+rb.toString(), IntegralType(100+i) == svI.intValue());
533  }
534 
535  REQUIRE_MSG("zero size "+rb.toString(), 0 == rb.getSize());
536  REQUIRE_MSG("empty "+rb.toString(), rb.isEmpty());
537 
538  REQUIRE_MSG("not full "+rb.toString(), !rb.isFull());
539  }
540 
541  public:
542 
544  test_GrowFullImpl(11, 0);
545  }
547  test_GrowFullImpl(11, 0+1);
548  }
550  test_GrowFullImpl(11, 0+2);
551  }
553  test_GrowFullImpl(11, 0+3);
554  }
556  test_GrowFullImpl(11, 11-1);
557  }
559  test_GrowFullImpl(11, 11-1-1);
560  }
562  test_GrowFullImpl(11, 11-1-2);
563  }
565  test_GrowFullImpl(11, 11-1-3);
566  }
567 
568 };
569 
570 #if 1
587 #else
588 METHOD_AS_TEST_CASE( TestRingbuffer02::test00_PrintInfo, "Test TestRingbuffer 02- 00");
589 METHOD_AS_TEST_CASE( TestRingbuffer02::test03_EmptyWriteRange, "Test TestRingbuffer 02- 03");
590 #endif
jau::ringbuffer::getFreeSlots
Size_type getFreeSlots() const noexcept
Returns the number of free slots available to put.
Definition: ringbuffer.hpp:935
TestRingbuffer02::test26_GrowFull12_End2
void test26_GrowFull12_End2()
Definition: test_lfringbuffer02.cpp:561
jau::ringbuffer::put
bool put(Value_type &&e) noexcept
Enqueues the given element by moving it into this ringbuffer storage.
Definition: ringbuffer.hpp:1140
TestRingbuffer02::test00_PrintInfo
void test00_PrintInfo()
Definition: test_lfringbuffer02.cpp:202
jau::ringbuffer::reset
void reset(const Value_type *copyFrom, const Size_type copyFromCount) noexcept
clear() all elements and add all copyFrom elements thereafter.
Definition: ringbuffer.hpp:911
Integer::value
IntegralType value
Definition: test_lfringbuffer02.cpp:42
jau::ringbuffer::isEmpty
bool isEmpty() const noexcept
Returns true if this ring buffer is empty, otherwise false.
Definition: ringbuffer.hpp:938
TestRingbuffer02::test25_GrowFull11_End1
void test25_GrowFull11_End1()
Definition: test_lfringbuffer02.cpp:558
Integer::operator=
Integer & operator=(const Integer &o) noexcept=default
IntegralType
uint8_t IntegralType
Definition: test_lfringbuffer01.cpp:38
Integer::Integer
Integer(Integer &&o) noexcept=default
TrivialTypeRingbuffer
ringbuffer< TrivialType, TrivialType, jau::nsize_t > TrivialTypeRingbuffer
Definition: test_lfringbuffer02.cpp:62
TestRingbuffer02::test22_GrowFull03_Begin2
void test22_GrowFull03_Begin2()
Definition: test_lfringbuffer02.cpp:549
jau::ringbuffer::clear
void clear() noexcept
Releasing all elements by assigning nullelem.
Definition: ringbuffer.hpp:900
jau
Definition: basic_algos.hpp:34
jau::ringbuffer::isFull
bool isFull() const noexcept
Returns true if this ring buffer is full, otherwise false.
Definition: ringbuffer.hpp:941
TestRingbuffer02::test20_GrowFull01_Begin
void test20_GrowFull01_Begin()
Definition: test_lfringbuffer02.cpp:543
jau::to_string
PRAGMA_DISABLE_WARNING_POP constexpr_cxx20 std::string to_string(const endian &v) noexcept
Return std::string representation of the given jau::endian.
Definition: byte_util.hpp:198
TestRingbuffer02::test03_EmptyWriteRange
void test03_EmptyWriteRange()
Definition: test_lfringbuffer02.cpp:244
TestRingbuffer02::test27_GrowFull13_End3
void test27_GrowFull13_End3()
Definition: test_lfringbuffer02.cpp:564
Integer::Integer
Integer() noexcept
Definition: test_lfringbuffer02.cpp:46
INFO_STR
#define INFO_STR(msg)
Definition: catch2_ext.hpp:59
METHOD_AS_TEST_CASE
METHOD_AS_TEST_CASE(TestRingbuffer02::test00_PrintInfo, "Test TestRingbuffer 02- 00")
Integer::operator=
Integer & operator=(Integer &&o) noexcept=default
jau::ringbuffer::uses_memcpy
constexpr static const bool uses_memcpy
Definition: ringbuffer.hpp:117
Integer
Definition: test_lfringbuffer02.cpp:40
jau::ringbuffer
Ring buffer implementation, a.k.a circular buffer, exposing lock-free get*(..) and put*(....
Definition: ringbuffer.hpp:115
jau::ringbuffer::uses_memset
constexpr static const bool uses_memset
Definition: ringbuffer.hpp:118
TestRingbuffer02::test01_FullRead
void test01_FullRead()
Definition: test_lfringbuffer02.cpp:214
TestRingbuffer02::test02_EmptyWrite
void test02_EmptyWrite()
Definition: test_lfringbuffer02.cpp:227
TestRingbuffer02::test23_GrowFull04_Begin3
void test23_GrowFull04_Begin3()
Definition: test_lfringbuffer02.cpp:552
Integer::Integer
Integer(const Integer &o) noexcept=default
jau::ringbuffer::toString
std::string toString() const noexcept
Returns a short string representation incl.
Definition: ringbuffer.hpp:758
TestRingbuffer02::test24_GrowFull05_End
void test24_GrowFull05_End()
Definition: test_lfringbuffer02.cpp:555
jau::ringbuffer::capacity
Size_type capacity() const noexcept
Returns the net capacity of this ring buffer.
Definition: ringbuffer.hpp:891
jau::snsize_t
int_fast32_t snsize_t
Natural 'ssize_t' alternative using int_fast32_t as its natural sized type.
Definition: int_types.hpp:56
jau::nsize_t
uint_fast32_t nsize_t
Natural 'size_t' alternative using uint_fast32_t as its natural sized type.
Definition: int_types.hpp:44
TestRingbuffer02::test04_FullReadReset
void test04_FullReadReset()
Definition: test_lfringbuffer02.cpp:396
jau::ringbuffer::get
Value_type get() noexcept
Dequeues the oldest enqueued element if available, otherwise null.
Definition: ringbuffer.hpp:1004
ringbuffer.hpp
jau::ringbuffer::getSize
Size_type getSize() const noexcept
Returns the number of elements in this ring buffer.
Definition: ringbuffer.hpp:926
TestRingbuffer02::test07_ReadResetMid02
void test07_ReadResetMid02()
Definition: test_lfringbuffer02.cpp:464
TrivialTypeNullElem
static const TrivialType TrivialTypeNullElem(-1)
Integer::intValue
IntegralType intValue() const
Definition: test_lfringbuffer02.cpp:56
TestRingbuffer02::test21_GrowFull02_Begin1
void test21_GrowFull02_Begin1()
Definition: test_lfringbuffer02.cpp:546
Integer::valueOf
static Integer valueOf(const IntegralType i)
Definition: test_lfringbuffer02.cpp:57
IntegralType
jau::snsize_t IntegralType
Definition: test_lfringbuffer02.cpp:38
jau::ringbuffer::drop
bool drop(const Size_type count) noexcept
Drops.
Definition: ringbuffer.hpp:1112
catch2_ext.hpp
TestRingbuffer02::test06_ReadResetMid01
void test06_ReadResetMid01()
Definition: test_lfringbuffer02.cpp:444
Integer::Integer
Integer(IntegralType v)
Definition: test_lfringbuffer02.cpp:44
TrivialType
Integer TrivialType
Definition: test_lfringbuffer02.cpp:60
REQUIRE_MSG
#define REQUIRE_MSG(MSG,...)
Definition: catch2_ext.hpp:58
TestRingbuffer02::test05_EmptyWriteClear
void test05_EmptyWriteClear()
Definition: test_lfringbuffer02.cpp:420
jau::ringbuffer::recapacity
void recapacity(const Size_type newCapacity)
Resizes this ring buffer's capacity.
Definition: ringbuffer.hpp:1222
TestRingbuffer02
Definition: test_lfringbuffer02.cpp:65
TrivialType
uint8_t TrivialType
Definition: test_lfringbuffer01.cpp:39