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