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