Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
test_message_buffer.cpp
Go to the documentation of this file.
2
3#include <thread>
4
5#define BOOST_TEST_MODULE message_buffer
6#include <boost/test/included/unit_test.hpp>
7
8namespace {
9size_t mb_size(boost::asio::mutable_buffer& mb) {
10#if BOOST_VERSION >= 106600
11 return mb.size();
12#else
13 return boost::asio::detail::buffer_size_helper(mb);
14#endif
15}
16
17void* mb_data(boost::asio::mutable_buffer& mb) {
18#if BOOST_VERSION >= 106600
19 return mb.data();
20#else
21 return boost::asio::detail::buffer_cast_helper(mb);
22#endif
23}
24}
25
26
27BOOST_AUTO_TEST_SUITE(message_buffer_tests)
28
29constexpr size_t def_buffer_size_mb = 4;
30constexpr size_t def_buffer_size = 1024*1024*def_buffer_size_mb;
31
33BOOST_AUTO_TEST_CASE(message_buffer_construction)
34{
35 try {
37 BOOST_CHECK_EQUAL(mb.total_bytes(), def_buffer_size);
38 BOOST_CHECK_EQUAL(mb.bytes_to_write(), def_buffer_size);
39 BOOST_CHECK_EQUAL(mb.bytes_to_read(), 0u);
40 BOOST_CHECK_EQUAL(mb.read_ptr(), mb.write_ptr());
41
43 auto mbsi = mbs.begin();
44 BOOST_CHECK_EQUAL(mb_size(*mbsi), def_buffer_size);
45 BOOST_CHECK_EQUAL(mb_data(*mbsi), mb.write_ptr());
46 mbsi++;
47 BOOST_CHECK(mbsi == mbs.end());
48 }
50}
51
53BOOST_AUTO_TEST_CASE(message_buffer_growth)
54{
55 try {
58 BOOST_CHECK_EQUAL(mb.total_bytes(), 2 * def_buffer_size);
59 BOOST_CHECK_EQUAL(mb.bytes_to_write(), 2 * def_buffer_size);
60 BOOST_CHECK_EQUAL(mb.bytes_to_read(), 0u);
61 BOOST_CHECK_EQUAL(mb.read_ptr(), mb.write_ptr());
62
63 {
65 auto mbsi = mbs.begin();
66 BOOST_CHECK_EQUAL(mb_size(*mbsi), def_buffer_size);
67 BOOST_CHECK_EQUAL(mb_data(*mbsi), mb.write_ptr());
68 mbsi++;
69 BOOST_CHECK(mbsi != mbs.end());
70 BOOST_CHECK_EQUAL(mb_size(*mbsi), def_buffer_size);
71 BOOST_CHECK_NE(mb_data(*mbsi), nullptr);
72 mbsi++;
73 BOOST_CHECK(mbsi == mbs.end());
74 }
75
76 mb.advance_write_ptr(100);
77 BOOST_CHECK_EQUAL(mb.total_bytes(), 2 * def_buffer_size);
78 BOOST_CHECK_EQUAL(mb.bytes_to_write(), 2 * def_buffer_size - 100);
79 BOOST_CHECK_EQUAL(mb.bytes_to_read(), 100u);
80 BOOST_CHECK_NE(mb.read_ptr(), nullptr);
81 BOOST_CHECK_NE(mb.write_ptr(), nullptr);
82 BOOST_CHECK_EQUAL((mb.read_ptr() + 100), mb.write_ptr());
83
84 {
86 auto mbsi = mbs.begin();
87 BOOST_CHECK_EQUAL(mb_size(*mbsi), def_buffer_size - 100);
88 BOOST_CHECK_EQUAL(mb_data(*mbsi), mb.write_ptr());
89 mbsi++;
90 BOOST_CHECK(mbsi != mbs.end());
91 BOOST_CHECK_EQUAL(mb_size(*mbsi), def_buffer_size);
92 BOOST_CHECK_NE(mb_data(*mbsi), nullptr);
93 mbsi++;
94 BOOST_CHECK(mbsi == mbs.end());
95 }
96
97 mb.advance_read_ptr(50);
98 BOOST_CHECK_EQUAL(mb.total_bytes(), 2 * def_buffer_size);
99 BOOST_CHECK_EQUAL(mb.bytes_to_write(), 2 * def_buffer_size - 100);
100 BOOST_CHECK_EQUAL(mb.bytes_to_read(), 50u);
101
103 BOOST_CHECK_EQUAL(mb.total_bytes(), 2 * def_buffer_size);
104 BOOST_CHECK_EQUAL(mb.bytes_to_write(), def_buffer_size - 100);
105 BOOST_CHECK_EQUAL(mb.bytes_to_read(), 50 + def_buffer_size);
106
107 // Moving read_ptr into second block should reset second block to first
109 BOOST_CHECK_EQUAL(mb.total_bytes(), def_buffer_size);
110 BOOST_CHECK_EQUAL(mb.bytes_to_write(), def_buffer_size - 100);
111 BOOST_CHECK_EQUAL(mb.bytes_to_read(), 50u);
112
113 // Moving read_ptr to write_ptr should shrink chain and reset ptrs
114 mb.advance_read_ptr(50);
115 BOOST_CHECK_EQUAL(mb.total_bytes(), def_buffer_size);
116 BOOST_CHECK_EQUAL(mb.bytes_to_write(), def_buffer_size);
117 BOOST_CHECK_EQUAL(mb.bytes_to_read(), 0u);
118
120 BOOST_CHECK_EQUAL(mb.total_bytes(), 2 * def_buffer_size);
121 BOOST_CHECK_EQUAL(mb.bytes_to_write(), 2 * def_buffer_size);
122 BOOST_CHECK_EQUAL(mb.bytes_to_read(), 0u);
123
124 mb.advance_write_ptr(50);
125 BOOST_CHECK_EQUAL(mb.total_bytes(), 2 * def_buffer_size);
126 BOOST_CHECK_EQUAL(mb.bytes_to_write(), 2 * def_buffer_size - 50);
127 BOOST_CHECK_EQUAL(mb.bytes_to_read(), 50u);
128
129 // Moving read_ptr to write_ptr should shrink chain and reset ptrs
130 mb.advance_read_ptr(50);
131 BOOST_CHECK_EQUAL(mb.total_bytes(), def_buffer_size);
132 BOOST_CHECK_EQUAL(mb.bytes_to_write(), def_buffer_size);
133 BOOST_CHECK_EQUAL(mb.bytes_to_read(), 0u);
134 }
136}
137
139BOOST_AUTO_TEST_CASE(message_buffer_peek_read)
140{
141 try {
142 {
143 const uint32_t small = 32;
145 BOOST_CHECK_EQUAL(mb.total_bytes(), small);
146 BOOST_CHECK_EQUAL(mb.bytes_to_write(), small);
147 BOOST_CHECK_EQUAL(mb.bytes_to_read(), 0);
148 BOOST_CHECK_EQUAL(mb.read_ptr(), mb.write_ptr());
149 BOOST_CHECK_EQUAL(mb.read_index().first, 0);
150 BOOST_CHECK_EQUAL(mb.read_index().second, 0);
151 BOOST_CHECK_EQUAL(mb.write_index().first, 0);
152 BOOST_CHECK_EQUAL(mb.write_index().second, 0);
153
154 mb.add_space(100 - small);
155 BOOST_CHECK_EQUAL(mb.total_bytes(), 4 * small);
156 BOOST_CHECK_EQUAL(mb.bytes_to_write(), 4 * small);
157 BOOST_CHECK_EQUAL(mb.bytes_to_read(), 0);
158 BOOST_CHECK_EQUAL(mb.read_ptr(), mb.write_ptr());
159
160 char* write_ptr = mb.write_ptr();
161 for (char ind = 0; ind < 100; ) {
162 *write_ptr = ind;
163 ind++;
164 if (ind % small == 0) {
165 mb.advance_write_ptr(small);
166 write_ptr = mb.write_ptr();
167 } else {
168 write_ptr++;
169 }
170 }
171 mb.advance_write_ptr(100 % small);
172
173 BOOST_CHECK_EQUAL(mb.total_bytes(), 4 * small);
174 BOOST_CHECK_EQUAL(mb.bytes_to_write(), 4 * small - 100);
175 BOOST_CHECK_EQUAL(mb.bytes_to_read(), 100);
176 BOOST_CHECK_NE((void*) mb.read_ptr(), (void*) mb.write_ptr());
177 BOOST_CHECK_EQUAL(mb.read_index().first, 0);
178 BOOST_CHECK_EQUAL(mb.read_index().second, 0);
179 BOOST_CHECK_EQUAL(mb.write_index().first, 3);
180 BOOST_CHECK_EQUAL(mb.write_index().second, 4);
181
182 char buffer[100];
183 auto index = mb.read_index();
184 mb.peek(buffer, 50, index);
185 mb.peek(buffer+50, 50, index);
186 for (int i=0; i < 100; i++) {
187 BOOST_CHECK_EQUAL(i, buffer[i]);
188 }
189
190 BOOST_CHECK_EQUAL(mb.total_bytes(), 4 * small);
191 BOOST_CHECK_EQUAL(mb.bytes_to_write(), 4 * small - 100);
192 BOOST_CHECK_EQUAL(mb.bytes_to_read(), 100);
193 BOOST_CHECK_NE((void*) mb.read_ptr(), (void*) mb.write_ptr());
194
195 char buffer2[100];
196 mb.read(buffer2, 100);
197 for (int i=0; i < 100; i++) {
198 BOOST_CHECK_EQUAL(i, buffer2[i]);
199 }
200
201 BOOST_CHECK_EQUAL(mb.total_bytes(), small);
202 BOOST_CHECK_EQUAL(mb.bytes_to_write(), small);
203 BOOST_CHECK_EQUAL(mb.bytes_to_read(), 0);
204 BOOST_CHECK_EQUAL(mb.read_ptr(), mb.write_ptr());
205 }
206 }
208}
209
211BOOST_AUTO_TEST_CASE(message_buffer_write_ptr_to_end)
212{
213 try {
214 {
215 const uint32_t small = 32;
217 BOOST_CHECK_EQUAL(mb.total_bytes(), small);
218 BOOST_CHECK_EQUAL(mb.bytes_to_write(), small);
219 BOOST_CHECK_EQUAL(mb.bytes_to_read(), 0);
220 BOOST_CHECK_EQUAL(mb.read_ptr(), mb.write_ptr());
221 BOOST_CHECK_EQUAL(mb.read_index().first, 0);
222 BOOST_CHECK_EQUAL(mb.read_index().second, 0);
223 BOOST_CHECK_EQUAL(mb.write_index().first, 0);
224 BOOST_CHECK_EQUAL(mb.write_index().second, 0);
225
226 char* write_ptr = mb.write_ptr();
227 for (uint32_t ind = 0; ind < small; ind++) {
228 *write_ptr = ind;
229 write_ptr++;
230 }
231 mb.advance_write_ptr(small);
232
233 BOOST_CHECK_EQUAL(mb.total_bytes(), 2 * small);
234 BOOST_CHECK_EQUAL(mb.bytes_to_write(), small);
235 BOOST_CHECK_EQUAL(mb.bytes_to_read(), small);
236 BOOST_CHECK_NE((void*) mb.read_ptr(), (void*) mb.write_ptr());
237 BOOST_CHECK_EQUAL(mb.read_index().first, 0);
238 BOOST_CHECK_EQUAL(mb.read_index().second, 0);
239 BOOST_CHECK_EQUAL(mb.write_index().first, 1);
240 BOOST_CHECK_EQUAL(mb.write_index().second, 0);
241
243 auto mbsi = mbs.begin();
244 BOOST_CHECK_EQUAL(mb_size(*mbsi), small);
245 BOOST_CHECK_EQUAL(mb_data(*mbsi), mb.write_ptr());
246 mbsi++;
247 BOOST_CHECK(mbsi == mbs.end());
248 }
249 }
251}
252
253BOOST_AUTO_TEST_CASE(message_buffer_read_peek_bounds) {
254 using my_message_buffer_t = fc::message_buffer<1024>;
255 my_message_buffer_t mbuff;
256 unsigned char stuff[] = {
257 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
258 };
259 memcpy(mbuff.write_ptr(), stuff, sizeof(stuff));
260 mbuff.advance_write_ptr(sizeof(stuff));
261
262 my_message_buffer_t::index_t index = mbuff.read_index();
263 uint8_t throw_away_buffer[4];
264 mbuff.peek(&throw_away_buffer, 4, index); //8 bytes left to peek afterwards
265 mbuff.peek(&throw_away_buffer, 4, index); //4 bytes left to peek afterwards
266 mbuff.peek(&throw_away_buffer, 2, index); //2 bytes left to peek afterwards
267 BOOST_CHECK_THROW(mbuff.peek(&throw_away_buffer, 3, index), fc::out_of_range_exception);
268 mbuff.peek(&throw_away_buffer, 1, index); //1 byte left to peek afterwards
269 mbuff.peek(&throw_away_buffer, 0, index); //1 byte left to peek afterwards
270 mbuff.peek(&throw_away_buffer, 1, index); //no bytes left to peek afterwards
271 BOOST_CHECK_THROW(mbuff.peek(&throw_away_buffer, 1, index), fc::out_of_range_exception);
272
273 mbuff.read(&throw_away_buffer, 4); //8 bytes left to read afterwards
274 mbuff.read(&throw_away_buffer, 4); //4 bytes left to read afterwards
275 mbuff.read(&throw_away_buffer, 2); //2 bytes left to read afterwards
276 BOOST_CHECK_THROW(mbuff.read(&throw_away_buffer, 4), fc::out_of_range_exception);
277 mbuff.read(&throw_away_buffer, 1); //1 byte left to read afterwards
278 mbuff.read(&throw_away_buffer, 0); //1 byte left to read afterwards
279 mbuff.read(&throw_away_buffer, 1); //no bytes left to read afterwards
280 BOOST_CHECK_THROW(mbuff.read(&throw_away_buffer, 1), fc::out_of_range_exception);
281}
282
283BOOST_AUTO_TEST_CASE(message_buffer_read_peek_bounds_multi) {
284 using my_message_buffer_t = fc::message_buffer<5>;
285 my_message_buffer_t mbuff;
286 unsigned char stuff[] = {
287 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
288 };
289 memcpy(mbuff.write_ptr(), stuff, 5);
290 mbuff.advance_write_ptr(5);
291 memcpy(mbuff.write_ptr(), stuff+5, 5);
292 mbuff.advance_write_ptr(5);
293 memcpy(mbuff.write_ptr(), stuff+10, 2);
294 mbuff.advance_write_ptr(2);
295
296 my_message_buffer_t::index_t index = mbuff.read_index();
297 uint8_t throw_away_buffer[4];
298 mbuff.peek(&throw_away_buffer, 4, index); //8 bytes left to peek afterwards
299 mbuff.peek(&throw_away_buffer, 4, index); //4 bytes left to peek afterwards
300 mbuff.peek(&throw_away_buffer, 2, index); //2 bytes left to peek afterwards
301 BOOST_CHECK_THROW(mbuff.peek(&throw_away_buffer, 3, index), fc::out_of_range_exception);
302 mbuff.peek(&throw_away_buffer, 1, index); //1 bytes left to peek afterwards
303 mbuff.peek(&throw_away_buffer, 0, index); //1 bytes left to peek afterwards
304 mbuff.peek(&throw_away_buffer, 1, index); //no bytes left to peek afterwards
305 BOOST_CHECK_THROW(mbuff.peek(&throw_away_buffer, 1, index), fc::out_of_range_exception);
306
307 mbuff.read(&throw_away_buffer, 4); //8 bytes left to read afterwards
308 mbuff.read(&throw_away_buffer, 4); //4 bytes left to read afterwards
309 mbuff.read(&throw_away_buffer, 2); //2 bytes left to read afterwards
310 BOOST_CHECK_THROW(mbuff.read(&throw_away_buffer, 4), fc::out_of_range_exception);
311 mbuff.read(&throw_away_buffer, 1); //1 bytes left to read afterwards
312 mbuff.read(&throw_away_buffer, 0); //1 bytes left to read afterwards
313 mbuff.read(&throw_away_buffer, 1); //no bytes left to read afterwards
314 BOOST_CHECK_THROW(mbuff.read(&throw_away_buffer, 1), fc::out_of_range_exception);
315}
316
317BOOST_AUTO_TEST_CASE(message_buffer_datastream) {
318 using my_message_buffer_t = fc::message_buffer<1024>;
319 my_message_buffer_t mbuff;
320
321 char buf[1024];
322 fc::datastream<char*> ds( buf, 1024 );
323
324 int v = 13;
325 fc::raw::pack( ds, v );
326 v = 42;
327 fc::raw::pack( ds, 42 );
328 fc::raw::pack( ds, std::string( "hello" ) );
329
330 memcpy(mbuff.write_ptr(), buf, 1024);
331 mbuff.advance_write_ptr(1024);
332
333 for( int i = 0; i < 3; ++i ) {
334 auto ds2 = mbuff.create_peek_datastream();
335 fc::raw::unpack( ds2, v );
336 BOOST_CHECK_EQUAL( 13, v );
337 fc::raw::unpack( ds2, v );
338 BOOST_CHECK_EQUAL( 42, v );
339 std::string s;
340 fc::raw::unpack( ds2, s );
341 BOOST_CHECK_EQUAL( s, std::string( "hello" ) );
342 }
343
344 {
345 auto ds2 = mbuff.create_datastream();
346 fc::raw::unpack( ds2, v );
347 BOOST_CHECK_EQUAL( 13, v );
348 fc::raw::unpack( ds2, v );
349 BOOST_CHECK_EQUAL( 42, v );
350 std::string s;
351 fc::raw::unpack( ds2, s );
352 BOOST_CHECK_EQUAL( s, std::string( "hello" ) );
353 }
354}
355
356// Make sure that the memory allocation is thread-safe.
357// A previous version used boost::object_pool without synchronization.
358BOOST_AUTO_TEST_CASE(test_message_buffer) {
359 std::vector<std::thread> threads;
360 constexpr int num_threads = 4;
361 constexpr int iterations = 10000;
362 for(int i = 0; i < num_threads; ++i) {
363 threads.emplace_back([]{
364 for(int i = 0; i < iterations; ++i) {
365 // Use all functions that allocate or free buffers
369 mb.reset();
372 }
373 });
374 }
375 for(std::thread& t : threads) {
376 t.join();
377 }
378}
379
380BOOST_AUTO_TEST_SUITE_END()
abstraction for a message buffer that spans a chain of physical buffers
uint32_t bytes_to_read() const
void add_space(uint32_t bytes)
bool read(void *s, uint32_t size)
void advance_write_ptr(uint32_t bytes)
std::vector< boost::asio::mutable_buffer > get_buffer_sequence_for_boost_async_read()
index_t write_index() const
bool peek(void *s, uint32_t size, index_t &index) const
void advance_read_ptr(uint32_t bytes)
uint32_t total_bytes() const
index_t read_index() const
uint32_t bytes_to_write() const
#define FC_LOG_AND_RETHROW()
void unpack(Stream &s, std::deque< T > &value)
Definition raw.hpp:540
void pack(Stream &s, const std::deque< T > &value)
Definition raw.hpp:531
unsigned int uint32_t
Definition stdint.h:126
unsigned char uint8_t
Definition stdint.h:124
constexpr size_t def_buffer_size_mb
constexpr size_t def_buffer_size
BOOST_AUTO_TEST_CASE(message_buffer_construction)
Test default construction and buffer sequence generation.
char * s
uint8_t buf[2048]
memcpy((char *) pInfo->slotDescription, s, l)