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