1//////////////////////////////////////////////////////////////////////////////
2//
3// (C) Copyright Ion Gaztanaga 2006-2012. Distributed under the Boost
4// Software License, Version 1.0. (See accompanying file
5// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6//
7// See http://www.boost.org/libs/interprocess for documentation.
8//
9//////////////////////////////////////////////////////////////////////////////
10
11#ifndef BOOST_INTERPROCESS_NAMED_ALLOCATION_TEST_TEMPLATE_HEADER
12#define BOOST_INTERPROCESS_NAMED_ALLOCATION_TEST_TEMPLATE_HEADER
13
14#include <boost/interprocess/detail/config_begin.hpp>
15
16// interprocess
17#include <boost/interprocess/managed_shared_memory.hpp>
18#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp>
19#include <boost/interprocess/streams/bufferstream.hpp>
20#include <boost/interprocess/sync/mutex_family.hpp>
21// container
22#include <boost/container/detail/iterator.hpp>
23#include <boost/container/detail/minimal_char_traits_header.hpp> //char_traits
24// std
25#include <cstdio>
26#include <iostream>
27#include <new>
28#include <set>
29#include <vector>
30#include <typeinfo>
31
32// local
33#include "get_process_id_name.hpp"
34
35namespace boost { namespace interprocess { namespace test {
36
37namespace {
38 const wchar_t *get_prefix(wchar_t)
39 { return L"prefix_name_"; }
40
41 const char *get_prefix(char)
42 { return "prefix_name_"; }
43}
44
45//This test allocates until there is no more memory
46//and after that deallocates all in the same order
47template<class ManagedMemory>
48bool test_names_and_types(ManagedMemory &m)
49{
50 typedef typename ManagedMemory::char_type char_type;
51 typedef std::char_traits<char_type> char_traits_type;
52 std::vector<char*> buffers;
53 const std::size_t BufferLen = 100u;
54 char_type name[BufferLen];
55
56 basic_bufferstream<char_type> formatter(name, BufferLen);
57
58 for(std::size_t i = 0; true; ++i){
59 formatter.seekp(0);
60 formatter << get_prefix(char_type()) << i << std::ends;
61
62 char *ptr = m.template construct<char>(name, std::nothrow)((char)i);
63
64 if(!ptr)
65 break;
66
67 std::size_t namelen = char_traits_type::length(m.get_instance_name(ptr));
68 if(namelen != char_traits_type::length(name)){
69 return 1;
70 }
71
72 if(char_traits_type::compare(m.get_instance_name(ptr), name, namelen) != 0){
73 return 1;
74 }
75
76 if(m.template find<char>(name).first == 0)
77 return false;
78
79 if(m.get_instance_type(ptr) != named_type)
80 return false;
81
82 buffers.push_back(x: ptr);
83 }
84
85 if(m.get_num_named_objects() != buffers.size() || !m.check_sanity())
86 return false;
87
88 for(std::size_t j = 0, max = buffers.size()
89 ;j < max
90 ;++j){
91 m.destroy_ptr(buffers[j]);
92 }
93
94 if(m.get_num_named_objects() != 0 || !m.check_sanity())
95 return false;
96 m.shrink_to_fit_indexes();
97 if(!m.all_memory_deallocated())
98 return false;
99 return true;
100}
101
102
103//This test allocates until there is no more memory
104//and after that deallocates all in the same order
105template<class ManagedMemory>
106bool test_named_iterators(ManagedMemory &m)
107{
108 typedef typename ManagedMemory::char_type char_type;
109 std::vector<char*> buffers;
110 const std::size_t BufferLen = 100;
111 char_type name[BufferLen];
112 typedef std::basic_string<char_type> string_type;
113 std::set<string_type> names;
114
115 basic_bufferstream<char_type> formatter(name, BufferLen);
116
117 string_type aux_str;
118
119 for(std::size_t i = 0; true; ++i){
120 formatter.seekp(0);
121 formatter << get_prefix(char_type()) << i << std::ends;
122 char *ptr = m.template construct<char>(name, std::nothrow)((char)i);
123 if(!ptr)
124 break;
125 aux_str = name;
126 names.insert(aux_str);
127 buffers.push_back(x: ptr);
128 }
129
130 if(m.get_num_named_objects() != buffers.size() || !m.check_sanity())
131 return false;
132
133 typedef typename ManagedMemory::const_named_iterator const_named_iterator;
134 const_named_iterator named_beg = m.named_begin();
135 const_named_iterator named_end = m.named_end();
136
137 if((std::size_t)boost::container::iterator_distance(named_beg, named_end) != (std::size_t)buffers.size()){
138 return 1;
139 }
140
141 for(; named_beg != named_end; ++named_beg){
142 const char_type *name_str = named_beg->name();
143 aux_str = name_str;
144 if(names.find(aux_str) == names.end()){
145 return 1;
146 }
147
148 if(aux_str.size() != named_beg->name_length()){
149 return 1;
150 }
151
152 const void *found_value = m.template find<char>(name_str).first;
153
154 if(found_value == 0)
155 return false;
156 if(found_value != named_beg->value())
157 return false;
158 }
159
160 for(std::size_t j = 0, max = buffers.size()
161 ;j < max
162 ;++j){
163 m.destroy_ptr(buffers[j]);
164 }
165
166 if(m.get_num_named_objects() != 0 || !m.check_sanity())
167 return false;
168 m.shrink_to_fit_indexes();
169 if(!m.all_memory_deallocated())
170 return false;
171 return true;
172}
173
174//This test allocates until there is no more memory
175//and after that deallocates all in the same order
176template<class ManagedMemory>
177bool test_shrink_to_fit(ManagedMemory &m)
178{
179 typedef typename ManagedMemory::char_type char_type;
180 std::vector<char*> buffers;
181 const std::size_t BufferLen = 100;
182 char_type name[BufferLen];
183
184 basic_bufferstream<char_type> formatter(name, BufferLen);
185
186 std::size_t free_memory_before = m.get_free_memory();
187
188 for(std::size_t i = 0; true; ++i){
189 formatter.seekp(0);
190 formatter << get_prefix(char_type()) << i << std::ends;
191
192 char *ptr = m.template construct<char>(name, std::nothrow)((char)i);
193
194 if(!ptr)
195 break;
196 buffers.push_back(x: ptr);
197 }
198
199 for(std::size_t j = 0, max = buffers.size()
200 ;j < max
201 ;++j){
202 m.destroy_ptr(buffers[j]);
203 }
204
205 std::size_t free_memory_after = m.get_free_memory();
206
207 if(free_memory_before != free_memory_after){
208 m.shrink_to_fit_indexes();
209 if(free_memory_before != free_memory_after)
210 return false;
211 }
212 return true;
213}
214
215//This test allocates until there is no more memory
216//and after that deallocates all in the same order
217template<class ManagedMemory>
218bool test_direct_named_allocation_destruction(ManagedMemory &m)
219{
220 typedef typename ManagedMemory::char_type char_type;
221 std::vector<char*> buffers;
222 const std::size_t BufferLen = 100;
223 char_type name[BufferLen];
224
225 basic_bufferstream<char_type> formatter(name, BufferLen);
226
227 for(std::size_t i = 0; true; ++i){
228 formatter.seekp(0);
229 formatter << get_prefix(char_type()) << i << std::ends;
230 char *ptr = m.template construct<char>(name, std::nothrow)((char)i);
231 if(!ptr)
232 break;
233 if(m.template find<char>(name).first == 0)
234 return false;
235 buffers.push_back(x: ptr);
236 }
237
238 if(m.get_num_named_objects() != buffers.size() || !m.check_sanity())
239 return false;
240
241 for(std::size_t j = 0, max = buffers.size()
242 ;j < max
243 ;++j){
244 m.destroy_ptr(buffers[j]);
245 }
246
247 if(m.get_num_named_objects() != 0 || !m.check_sanity())
248 return false;
249 m.shrink_to_fit_indexes();
250 if(!m.all_memory_deallocated())
251 return false;
252 return true;
253}
254
255//This test allocates until there is no more memory
256//and after that deallocates all in the inverse order
257template<class ManagedMemory>
258bool test_named_allocation_inverse_destruction(ManagedMemory &m)
259{
260 typedef typename ManagedMemory::char_type char_type;
261
262 std::vector<char*> buffers;
263 const std::size_t BufferLen = 100;
264 char_type name[BufferLen];
265
266 basic_bufferstream<char_type> formatter(name, BufferLen);
267
268 for(std::size_t i = 0; true; ++i){
269 formatter.seekp(0);
270 formatter << get_prefix(char_type()) << i << std::ends;
271 char *ptr = m.template construct<char>(name, std::nothrow)((char)i);
272 if(!ptr)
273 break;
274 buffers.push_back(x: ptr);
275 }
276
277 if(m.get_num_named_objects() != buffers.size() || !m.check_sanity())
278 return false;
279
280 for(std::size_t j = buffers.size()
281 ;j--
282 ;){
283 m.destroy_ptr(buffers[j]);
284 }
285
286 if(m.get_num_named_objects() != 0 || !m.check_sanity())
287 return false;
288 m.shrink_to_fit_indexes();
289 if(!m.all_memory_deallocated())
290 return false;
291 return true;
292}
293
294//This test allocates until there is no more memory
295//and after that deallocates all following a pattern
296template<class ManagedMemory>
297bool test_named_allocation_mixed_destruction(ManagedMemory &m)
298{
299 typedef typename ManagedMemory::char_type char_type;
300
301 std::vector<char*> buffers;
302 const std::size_t BufferLen = 100;
303 char_type name[BufferLen];
304
305 basic_bufferstream<char_type> formatter(name, BufferLen);
306
307 for(std::size_t i = 0; true; ++i){
308 formatter.seekp(0);
309 formatter << get_prefix(char_type()) << i << std::ends;
310 char *ptr = m.template construct<char>(name, std::nothrow)((char)i);
311 if(!ptr)
312 break;
313 buffers.push_back(x: ptr);
314 }
315
316 if(m.get_num_named_objects() != buffers.size() || !m.check_sanity())
317 return false;
318
319 for(std::size_t j = 0, max = buffers.size()
320 ;j < max
321 ;++j){
322 std::size_t pos = (j%4u)*(buffers.size())/4u;
323 m.destroy_ptr(buffers[pos]);
324 buffers.erase(position: buffers.begin()+std::ptrdiff_t(pos));
325 }
326
327 if(m.get_num_named_objects() != 0 || !m.check_sanity())
328 return false;
329 m.shrink_to_fit_indexes();
330 if(!m.all_memory_deallocated())
331 return false;
332 return true;
333}
334
335//This test allocates until there is no more memory
336//and after that deallocates all in the same order
337template<class ManagedMemory>
338bool test_inverse_named_allocation_destruction(ManagedMemory &m)
339{
340 typedef typename ManagedMemory::char_type char_type;
341
342 std::vector<char*> buffers;
343 const std::size_t BufferLen = 100;
344 char_type name[BufferLen];
345
346 basic_bufferstream<char_type> formatter(name, BufferLen);
347
348 for(std::size_t i = 0; true; ++i){
349 formatter.seekp(0);
350 formatter << get_prefix(char_type()) << i << std::ends;
351 char *ptr = m.template construct<char>(name, std::nothrow)((char)i);
352 if(!ptr)
353 break;
354 buffers.push_back(x: ptr);
355 }
356
357 if(m.get_num_named_objects() != buffers.size() || !m.check_sanity())
358 return false;
359
360 for(std::size_t j = 0, max = (unsigned int)buffers.size()
361 ;j < max
362 ;++j){
363 m.destroy_ptr(buffers[j]);
364 }
365
366 if(m.get_num_named_objects() != 0 || !m.check_sanity())
367 return false;
368 m.shrink_to_fit_indexes();
369 if(!m.all_memory_deallocated())
370 return false;
371 return true;
372}
373
374///This function calls all tests
375template<class ManagedMemory>
376bool test_all_named_allocation(ManagedMemory &m)
377{
378 std::cout << "Starting test_names_and_types. Class: "
379 << typeid(m).name() << std::endl;
380
381 if(!test_names_and_types(m)){
382 std::cout << "test_names_and_types failed. Class: "
383 << typeid(m).name() << std::endl;
384 return false;
385 }
386
387 std::cout << "Starting test_direct_named_allocation_destruction. Class: "
388 << typeid(m).name() << std::endl;
389
390 if(!test_direct_named_allocation_destruction(m)){
391 std::cout << "test_direct_named_allocation_destruction failed. Class: "
392 << typeid(m).name() << std::endl;
393 return false;
394 }
395
396 std::cout << "Starting test_named_allocation_inverse_destruction. Class: "
397 << typeid(m).name() << std::endl;
398
399 if(!test_named_allocation_inverse_destruction(m)){
400 std::cout << "test_named_allocation_inverse_destruction failed. Class: "
401 << typeid(m).name() << std::endl;
402 return false;
403 }
404
405 std::cout << "Starting test_named_allocation_mixed_destruction. Class: "
406 << typeid(m).name() << std::endl;
407
408 if(!test_named_allocation_mixed_destruction(m)){
409 std::cout << "test_named_allocation_mixed_destruction failed. Class: "
410 << typeid(m).name() << std::endl;
411 return false;
412 }
413
414 std::cout << "Starting test_inverse_named_allocation_destruction. Class: "
415 << typeid(m).name() << std::endl;
416
417 if(!test_inverse_named_allocation_destruction(m)){
418 std::cout << "test_inverse_named_allocation_destruction failed. Class: "
419 << typeid(m).name() << std::endl;
420 return false;
421 }
422
423 if(!test_named_iterators(m)){
424 std::cout << "test_named_iterators failed. Class: "
425 << typeid(m).name() << std::endl;
426 return false;
427 }
428
429 return true;
430}
431
432//This function calls all tests
433template<template <class IndexConfig> class Index>
434bool test_named_allocation()
435{
436 using namespace boost::interprocess;
437
438 const int memsize = 163840;
439 const char *const shMemName = test::get_process_id_name();
440 BOOST_TRY
441 {
442 //A shared memory with rbtree best fit algorithm
443 typedef basic_managed_shared_memory
444 <char
445 ,rbtree_best_fit<mutex_family>
446 ,Index
447 > my_managed_shared_memory;
448
449 //Create shared memory
450 shared_memory_object::remove(filename: shMemName);
451 my_managed_shared_memory segment(create_only, shMemName, memsize);
452
453 //Now take the segment manager and launch memory test
454 if(!test::test_all_named_allocation(*segment.get_segment_manager())){
455 return false;
456 }
457 }
458 BOOST_CATCH(...){
459 shared_memory_object::remove(filename: shMemName);
460 BOOST_RETHROW
461 } BOOST_CATCH_END
462 shared_memory_object::remove(filename: shMemName);
463
464 //Now test it with wchar_t
465 BOOST_TRY
466 {
467 //A shared memory with simple sequential fit algorithm
468 typedef basic_managed_shared_memory
469 <wchar_t
470 ,rbtree_best_fit<mutex_family>
471 ,Index
472 > my_managed_shared_memory;
473
474 //Create shared memory
475 shared_memory_object::remove(filename: shMemName);
476 my_managed_shared_memory segment(create_only, shMemName, memsize);
477
478 //Now take the segment manager and launch memory test
479 if(!test::test_all_named_allocation(*segment.get_segment_manager())){
480 return false;
481 }
482 }
483 BOOST_CATCH(...){
484 shared_memory_object::remove(filename: shMemName);
485 BOOST_RETHROW
486 } BOOST_CATCH_END
487 shared_memory_object::remove(filename: shMemName);
488
489 return true;
490}
491
492}}} //namespace boost { namespace interprocess { namespace test {
493
494#include <boost/interprocess/detail/config_end.hpp>
495
496#endif //BOOST_INTERPROCESS_NAMED_ALLOCATION_TEST_TEMPLATE_HEADER
497

source code of boost/libs/interprocess/test/named_allocation_test_template.hpp