Direct-BT  2.3.1
Direct-BT - Direct Bluetooth Programming.
test_lfringbuffer12.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 #include <thread>
30 #include <pthread.h>
31 
32 #define CATCH_CONFIG_MAIN
33 #include <catch2/catch_amalgamated.hpp>
34 #include <jau/test/catch2_ext.hpp>
35 
36 #include <jau/ringbuffer.hpp>
37 
38 using namespace jau;
39 
41 
42 class Integer {
43  public:
44  IntegralType value;
45 
46  Integer(IntegralType v) : value(v) {}
47 
48  Integer() noexcept : value(0) { }
49 
50  Integer(const Integer &o) noexcept = default;
51  Integer(Integer &&o) noexcept = default;
52  Integer& operator=(const Integer &o) noexcept = default;
53  Integer& operator=(Integer &&o) noexcept = default;
54 
55  operator IntegralType() const {
56  return value;
57  }
58  IntegralType intValue() const { return value; }
59  static Integer valueOf(const IntegralType i) { return Integer(i); }
60 };
61 
65 
66 // Test examples.
68  private:
69 
70  TrivialTypeRingbuffer createEmpty(jau::nsize_t initialCapacity) {
71  TrivialTypeRingbuffer rb(Integer(-1), initialCapacity);
72  REQUIRE_MSG("empty "+rb.toString(), rb.isEmpty());
73  return rb;
74  }
75  TrivialTypeRingbuffer createFull(const std::vector<TrivialType> & source) {
76  TrivialTypeRingbuffer rb(Integer(-1), source);
77  REQUIRE_MSG("full "+rb.toString(), rb.isFull());
78  return rb;
79  }
80 
81  std::vector<TrivialType> createIntArray(const jau::nsize_t capacity, const IntegralType startValue) {
82  std::vector<TrivialType> array(capacity);
83  for(jau::nsize_t i=0; i<capacity; i++) {
84  array[i] = TrivialType(startValue+i);
85  }
86  return array;
87  }
88 
89  void getThreadType01(const std::string msg, TrivialTypeRingbuffer* rb, jau::nsize_t len) {
90  // std::thread::id this_id = std::this_thread::get_id();
91  // pthread_t this_id = pthread_self();
92 
93  // INFO_STR, INFO: Not thread safe yet
94  // INFO_STR(msg+": Created / " + rb->toString());
95  for(jau::nsize_t i=0; i<len; i++) {
96  TrivialType svI = rb->getBlocking();
97  REQUIRE_MSG("not empty at read #"+std::to_string(i+1)+": "+rb->toString(), svI!=TrivialTypeNullElem);
98  // INFO_STR("Got "+std::to_string(svI->intValue())+" / " + rb->toString());
99  }
100  // INFO_STR(msg+": Dies / " + rb->toString());
101  (void)msg;
102  }
103 
104  void getRangeThreadType02(const std::string msg, TrivialTypeRingbuffer* rb, jau::nsize_t len) {
105  // std::thread::id this_id = std::this_thread::get_id();
106  // pthread_t this_id = pthread_self();
107 
108  // INFO_STR, INFO: Not thread safe yet
109  // INFO_STR(msg+": Created / " + rb->toString());
110  std::vector<TrivialType> array(len);
111  REQUIRE_MSG("get-range of "+std::to_string(array.size())+" elem in "+rb->toString(), len==rb->getBlocking( &(*array.begin()), len, len) );
112 
113  for(jau::nsize_t i=0; i<len; i++) {
114  TrivialType svI = array[i];
115  REQUIRE_MSG("not empty at read #"+std::to_string(i+1)+": "+rb->toString(), svI!=TrivialTypeNullElem);
116  // INFO_STR("Got "+std::to_string(svI.intValue())+" / " + rb->toString());
117  }
118  // INFO_STR(msg+": Dies / " + rb->toString());
119  (void)msg;
120  }
121 
122  void putThreadType01(const std::string msg, TrivialTypeRingbuffer* rb, jau::nsize_t len, IntegralType startValue) {
123  // std::thread::id this_id = std::this_thread::get_id();
124  // pthread_t this_id = pthread_self();
125 
126  // INFO_STR(msg+": Created / " + rb->toString());
127  for(jau::nsize_t i=0; i<len; i++) {
128  Integer vI(startValue+i);
129  // INFO_STR("Putting "+std::to_string(vI->intValue())+" ... / " + rb->toString());
130  rb->putBlocking( vI );
131  }
132  // INFO_STR(msg+": Dies / " + rb->toString());
133  (void)msg;
134  }
135 
136  void putRangeThreadType02(const std::string msg, TrivialTypeRingbuffer* rb, jau::nsize_t len, IntegralType startValue) {
137  // std::thread::id this_id = std::this_thread::get_id();
138  // pthread_t this_id = pthread_self();
139 
140  // INFO_STR(msg+": Created / " + rb->toString());
141  std::vector<TrivialType> data = createIntArray(len, startValue);
142  REQUIRE_MSG("put-range of "+std::to_string(data.size())+" elem in "+rb->toString(), rb->put( &(*data.begin()), &(*data.end()) ) );
143 
144  // INFO_STR(msg+": Dies / " + rb->toString());
145  (void)msg;
146  }
147 
148  public:
149 
151  INFO_STR("\n\ntest01a_Read1Write1\n");
152  jau::nsize_t capacity = 100;
153  TrivialTypeRingbuffer rb = createEmpty(capacity);
154  REQUIRE_MSG("empty size "+rb.toString(), 0 == rb.getSize());
155  REQUIRE_MSG("empty "+rb.toString(), rb.isEmpty());
156 
157  std::thread getThread01(&TestRingbuffer12::getThreadType01, this, "test01a.get01", &rb, capacity); // @suppress("Invalid arguments")
158  std::thread putThread01(&TestRingbuffer12::putThreadType01, this, "test01a.put01", &rb, capacity, 0); // @suppress("Invalid arguments")
159  putThread01.join();
160  getThread01.join();
161 
162  REQUIRE_MSG("empty "+rb.toString(), rb.isEmpty());
163  REQUIRE_MSG("empty size "+rb.toString(), 0 == rb.getSize());
164  }
165 
167  INFO_STR("\n\ntest01b_Read1Write1_Range\n");
168  jau::nsize_t capacity = 100;
169  TrivialTypeRingbuffer rb = createEmpty(capacity);
170  REQUIRE_MSG("empty size "+rb.toString(), 0 == rb.getSize());
171  REQUIRE_MSG("empty "+rb.toString(), rb.isEmpty());
172 
173  std::thread getThread01(&TestRingbuffer12::getRangeThreadType02, this, "test01b.getR01", &rb, capacity); // @suppress("Invalid arguments")
174  std::thread putThread01(&TestRingbuffer12::putRangeThreadType02, this, "test01b.putR01", &rb, capacity, 0); // @suppress("Invalid arguments")
175  putThread01.join();
176  getThread01.join();
177 
178  REQUIRE_MSG("empty "+rb.toString(), rb.isEmpty());
179  REQUIRE_MSG("empty size "+rb.toString(), 0 == rb.getSize());
180  }
181 
183  INFO_STR("\n\ntest02a_Read4Write1\n");
184  jau::nsize_t capacity = 400;
185  TrivialTypeRingbuffer rb = createEmpty(capacity);
186  REQUIRE_MSG("empty size "+rb.toString(), 0 == rb.getSize());
187  REQUIRE_MSG("empty "+rb.toString(), rb.isEmpty());
188 
189  std::thread getThread01(&TestRingbuffer12::getThreadType01, this, "test02a.get01", &rb, capacity/4); // @suppress("Invalid arguments")
190  std::thread getThread02(&TestRingbuffer12::getThreadType01, this, "test02a.get02", &rb, capacity/4); // @suppress("Invalid arguments")
191  std::thread putThread01(&TestRingbuffer12::putThreadType01, this, "test02a.put01", &rb, capacity, 0); // @suppress("Invalid arguments")
192  std::thread getThread03(&TestRingbuffer12::getThreadType01, this, "test02a.get03", &rb, capacity/4); // @suppress("Invalid arguments")
193  std::thread getThread04(&TestRingbuffer12::getThreadType01, this, "test02a.get04", &rb, capacity/4); // @suppress("Invalid arguments")
194  putThread01.join();
195  getThread01.join();
196  getThread02.join();
197  getThread03.join();
198  getThread04.join();
199 
200  REQUIRE_MSG("empty "+rb.toString(), rb.isEmpty());
201  REQUIRE_MSG("empty size "+rb.toString(), 0 == rb.getSize());
202  }
203 
205  INFO_STR("\n\ntest02b_Read4Write1_Range\n");
206  jau::nsize_t capacity = 400;
207  TrivialTypeRingbuffer rb = createEmpty(capacity);
208  REQUIRE_MSG("empty size "+rb.toString(), 0 == rb.getSize());
209  REQUIRE_MSG("empty "+rb.toString(), rb.isEmpty());
210 
211  std::thread getThread01(&TestRingbuffer12::getRangeThreadType02, this, "test02b.getR01", &rb, capacity/4); // @suppress("Invalid arguments")
212  std::thread getThread02(&TestRingbuffer12::getRangeThreadType02, this, "test02b.getR02", &rb, capacity/4); // @suppress("Invalid arguments")
213  std::thread putThread01(&TestRingbuffer12::putRangeThreadType02, this, "test02b.putR01", &rb, capacity, 0); // @suppress("Invalid arguments")
214  std::thread getThread03(&TestRingbuffer12::getRangeThreadType02, this, "test02b.getR03", &rb, capacity/4); // @suppress("Invalid arguments")
215  std::thread getThread04(&TestRingbuffer12::getRangeThreadType02, this, "test02b.getR04", &rb, capacity/4); // @suppress("Invalid arguments")
216  putThread01.join();
217  getThread01.join();
218  getThread02.join();
219  getThread03.join();
220  getThread04.join();
221 
222  REQUIRE_MSG("empty "+rb.toString(), rb.isEmpty());
223  REQUIRE_MSG("empty size "+rb.toString(), 0 == rb.getSize());
224  }
225 
227  INFO_STR("\n\ntest03a_Read8Write2\n");
228  jau::nsize_t capacity = 800;
229  TrivialTypeRingbuffer rb = createEmpty(capacity);
230  REQUIRE_MSG("empty size "+rb.toString(), 0 == rb.getSize());
231  REQUIRE_MSG("empty "+rb.toString(), rb.isEmpty());
232 
233  std::thread getThread01(&TestRingbuffer12::getThreadType01, this, "test03a.get01", &rb, capacity/8); // @suppress("Invalid arguments")
234  std::thread getThread02(&TestRingbuffer12::getThreadType01, this, "test03a.get02", &rb, capacity/8); // @suppress("Invalid arguments")
235  std::thread putThread01(&TestRingbuffer12::putThreadType01, this, "test03a.put01", &rb, capacity/2, 0); // @suppress("Invalid arguments")
236  std::thread getThread03(&TestRingbuffer12::getThreadType01, this, "test03a.get03", &rb, capacity/8); // @suppress("Invalid arguments")
237  std::thread getThread04(&TestRingbuffer12::getThreadType01, this, "test03a.get04", &rb, capacity/8); // @suppress("Invalid arguments")
238 
239  std::thread getThread05(&TestRingbuffer12::getThreadType01, this, "test03a.get05", &rb, capacity/8); // @suppress("Invalid arguments")
240  std::thread getThread06(&TestRingbuffer12::getThreadType01, this, "test03a.get06", &rb, capacity/8); // @suppress("Invalid arguments")
241  std::thread putThread02(&TestRingbuffer12::putThreadType01, this, "test03a.put02", &rb, capacity/2, 400); // @suppress("Invalid arguments")
242  std::thread getThread07(&TestRingbuffer12::getThreadType01, this, "test03a.get07", &rb, capacity/8); // @suppress("Invalid arguments")
243  std::thread getThread08(&TestRingbuffer12::getThreadType01, this, "test03a.get08", &rb, capacity/8); // @suppress("Invalid arguments")
244 
245  putThread01.join();
246  putThread02.join();
247  getThread01.join();
248  getThread02.join();
249  getThread03.join();
250  getThread04.join();
251  getThread05.join();
252  getThread06.join();
253  getThread07.join();
254  getThread08.join();
255 
256  REQUIRE_MSG("empty "+rb.toString(), rb.isEmpty());
257  REQUIRE_MSG("empty size "+rb.toString(), 0 == rb.getSize());
258  }
259 
261  INFO_STR("\n\ntest03b_Read8Write2_Range\n");
262  jau::nsize_t capacity = 800;
263  TrivialTypeRingbuffer rb = createEmpty(capacity);
264  REQUIRE_MSG("empty size "+rb.toString(), 0 == rb.getSize());
265  REQUIRE_MSG("empty "+rb.toString(), rb.isEmpty());
266 
267  std::thread getThread01(&TestRingbuffer12::getRangeThreadType02, this, "test03b.getR01", &rb, capacity/8); // @suppress("Invalid arguments")
268  std::thread getThread02(&TestRingbuffer12::getRangeThreadType02, this, "test03b.getR02", &rb, capacity/8); // @suppress("Invalid arguments")
269  std::thread putThread01(&TestRingbuffer12::putRangeThreadType02, this, "test03b.putR01", &rb, capacity/2, 0); // @suppress("Invalid arguments")
270  std::thread getThread03(&TestRingbuffer12::getRangeThreadType02, this, "test03b.getR03", &rb, capacity/8); // @suppress("Invalid arguments")
271  std::thread getThread04(&TestRingbuffer12::getRangeThreadType02, this, "test03b.getR04", &rb, capacity/8); // @suppress("Invalid arguments")
272 
273  std::thread getThread05(&TestRingbuffer12::getRangeThreadType02, this, "test03b.getR05", &rb, capacity/8); // @suppress("Invalid arguments")
274  std::thread getThread06(&TestRingbuffer12::getRangeThreadType02, this, "test03b.getR06", &rb, capacity/8); // @suppress("Invalid arguments")
275  std::thread putThread02(&TestRingbuffer12::putRangeThreadType02, this, "test03b.putR02", &rb, capacity/2, 400); // @suppress("Invalid arguments")
276  std::thread getThread07(&TestRingbuffer12::getRangeThreadType02, this, "test03b.getR07", &rb, capacity/8); // @suppress("Invalid arguments")
277  std::thread getThread08(&TestRingbuffer12::getRangeThreadType02, this, "test03b.getR08", &rb, capacity/8); // @suppress("Invalid arguments")
278 
279  putThread01.join();
280  putThread02.join();
281  getThread01.join();
282  getThread02.join();
283  getThread03.join();
284  getThread04.join();
285  getThread05.join();
286  getThread06.join();
287  getThread07.join();
288  getThread08.join();
289 
290  REQUIRE_MSG("empty "+rb.toString(), rb.isEmpty());
291  REQUIRE_MSG("empty size "+rb.toString(), 0 == rb.getSize());
292  }
293 
295  test01a_Read1Write1();
296  test02a_Read4Write1();
297  test03a_Read8Write2();
298 
299  test01a_Read1Write1();
300  test02a_Read4Write1();
301  test03a_Read8Write2();
302 
303  test03a_Read8Write2();
304  test03a_Read8Write2();
305  test03a_Read8Write2();
306  }
307 
308  void test_range() {
309  test01b_Read1Write1_Range();
310  test02b_Read4Write1_Range();
311  test03b_Read8Write2_Range();
312 
313  test01b_Read1Write1_Range();
314  test02b_Read4Write1_Range();
315  test03b_Read8Write2_Range();
316 
317  test01b_Read1Write1_Range();
318  test02b_Read4Write1_Range();
319  test03b_Read8Write2_Range();
320  }
321 };
322 
323 METHOD_AS_TEST_CASE( TestRingbuffer12::test_sequential, "Test TestRingbuffer 12- test_sequential");
324 METHOD_AS_TEST_CASE( TestRingbuffer12::test_range, "Test TestRingbuffer 12- test_range");
325 
TestRingbuffer12::test01b_Read1Write1_Range
void test01b_Read1Write1_Range()
Definition: test_lfringbuffer12.cpp:166
jau::ringbuffer::put
bool put(Value_type &&e) noexcept
Enqueues the given element by moving it into this ringbuffer storage.
Definition: ringbuffer.hpp:1140
jau::ringbuffer::isEmpty
bool isEmpty() const noexcept
Returns true if this ring buffer is empty, otherwise false.
Definition: ringbuffer.hpp:938
Integer::operator=
Integer & operator=(const Integer &o) noexcept=default
TestRingbuffer12::test_range
void test_range()
Definition: test_lfringbuffer12.cpp:308
IntegralType
uint8_t IntegralType
Definition: test_lfringbuffer01.cpp:38
Integer::Integer
Integer(Integer &&o) noexcept=default
TestRingbuffer12::test02b_Read4Write1_Range
void test02b_Read4Write1_Range()
Definition: test_lfringbuffer12.cpp:204
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
TestRingbuffer12::test03a_Read8Write2
void test03a_Read8Write2()
Definition: test_lfringbuffer12.cpp:226
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
Integer::Integer
Integer() noexcept
Definition: test_lfringbuffer12.cpp:48
INFO_STR
#define INFO_STR(msg)
Definition: catch2_ext.hpp:59
TrivialTypeRingbuffer
ringbuffer< TrivialType, TrivialType, jau::nsize_t > TrivialTypeRingbuffer
Definition: test_lfringbuffer12.cpp:64
TestRingbuffer12::test01a_Read1Write1
void test01a_Read1Write1()
Definition: test_lfringbuffer12.cpp:150
Integer::operator=
Integer & operator=(Integer &&o) noexcept=default
jau::ringbuffer::putBlocking
bool putBlocking(Value_type &&e, const int timeoutMS=0) noexcept
Enqueues the given element by moving it into this ringbuffer storage.
Definition: ringbuffer.hpp:1153
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
TestRingbuffer12
Definition: test_lfringbuffer12.cpp:67
TestRingbuffer12::test02a_Read4Write1
void test02a_Read4Write1()
Definition: test_lfringbuffer12.cpp:182
TestRingbuffer12::test03b_Read8Write2_Range
void test03b_Read8Write2_Range()
Definition: test_lfringbuffer12.cpp:260
Integer::Integer
Integer(const Integer &o) noexcept=default
TestRingbuffer12::test_sequential
void test_sequential()
Definition: test_lfringbuffer12.cpp:294
jau::ringbuffer::toString
std::string toString() const noexcept
Returns a short string representation incl.
Definition: ringbuffer.hpp:758
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
METHOD_AS_TEST_CASE
METHOD_AS_TEST_CASE(TestRingbuffer12::test_sequential, "Test TestRingbuffer 12- test_sequential")
ringbuffer.hpp
jau::ringbuffer::getSize
Size_type getSize() const noexcept
Returns the number of elements in this ring buffer.
Definition: ringbuffer.hpp:926
TrivialType
Integer TrivialType
Definition: test_lfringbuffer12.cpp:62
Integer::intValue
IntegralType intValue() const
Definition: test_lfringbuffer12.cpp:58
jau::ringbuffer::getBlocking
Value_type getBlocking(const int timeoutMS=0) noexcept
Dequeues the oldest enqueued element.
Definition: ringbuffer.hpp:1040
Integer::valueOf
static Integer valueOf(const IntegralType i)
Definition: test_lfringbuffer12.cpp:59
catch2_ext.hpp
Integer::Integer
Integer(IntegralType v)
Definition: test_lfringbuffer12.cpp:46
TrivialTypeNullElem
static const TrivialType TrivialTypeNullElem(-1)
REQUIRE_MSG
#define REQUIRE_MSG(MSG,...)
Definition: catch2_ext.hpp:58
TrivialType
uint8_t TrivialType
Definition: test_lfringbuffer01.cpp:39
IntegralType
jau::snsize_t IntegralType
Definition: test_lfringbuffer12.cpp:40