1//////////////////////////////////////////////////////////////////////////////
2//
3// (C) Copyright Ion Gaztanaga 2008-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#ifndef BOOST_INTERPROCESS_TEST_EMPLACE_TEST_HPP
11#define BOOST_INTERPROCESS_TEST_EMPLACE_TEST_HPP
12
13#include <iostream>
14#include <typeinfo>
15#include <boost/interprocess/detail/config_begin.hpp>
16#include <boost/interprocess/detail/workaround.hpp>
17#include <boost/interprocess/detail/mpl.hpp>
18#include <boost/move/utility_core.hpp>
19#include <boost/interprocess/detail/utilities.hpp>
20#include <boost/move/detail/type_traits.hpp> //make_unsigned, alignment_of
21
22namespace boost{
23namespace interprocess{
24namespace test{
25
26class EmplaceInt
27{
28 private:
29 BOOST_MOVABLE_BUT_NOT_COPYABLE(EmplaceInt)
30
31 public:
32 EmplaceInt()
33 : a_(0), b_(0), c_(0), d_(0), e_(0)
34 {}
35 EmplaceInt(int a, int b = 0, int c = 0, int d = 0, int e = 0)
36 : a_(a), b_(b), c_(c), d_(d), e_(e)
37 {}
38
39 EmplaceInt(BOOST_RV_REF(EmplaceInt) o)
40 : a_(o.a_), b_(o.b_), c_(o.c_), d_(o.d_), e_(o.e_)
41 {}
42
43 EmplaceInt& operator=(BOOST_RV_REF(EmplaceInt) o)
44 {
45 this->a_ = o.a_;
46 this->b_ = o.b_;
47 this->c_ = o.c_;
48 this->d_ = o.d_;
49 this->e_ = o.e_;
50 return *this;
51 }
52
53 friend bool operator==(const EmplaceInt &l, const EmplaceInt &r)
54 {
55 return l.a_ == r.a_ &&
56 l.b_ == r.b_ &&
57 l.c_ == r.c_ &&
58 l.d_ == r.d_ &&
59 l.e_ == r.e_;
60 }
61
62 friend bool operator<(const EmplaceInt &l, const EmplaceInt &r)
63 { return l.sum() < r.sum(); }
64
65 friend bool operator>(const EmplaceInt &l, const EmplaceInt &r)
66 { return l.sum() > r.sum(); }
67
68 friend bool operator!=(const EmplaceInt &l, const EmplaceInt &r)
69 { return !(l == r); }
70
71 friend std::ostream &operator <<(std::ostream &os, const EmplaceInt &v)
72 {
73 os << "EmplaceInt: " << v.a_ << ' ' << v.b_ << ' ' << v.c_ << ' ' << v.d_ << ' ' << v.e_;
74 return os;
75 }
76
77 //private:
78 int sum() const
79 { return this->a_ + this->b_ + this->c_ + this->d_ + this->e_; }
80
81 int a_, b_, c_, d_, e_;
82 int padding[6];
83};
84
85
86} //namespace test {
87
88namespace test {
89
90enum EmplaceOptions{
91 EMPLACE_BACK = 1 << 0,
92 EMPLACE_FRONT = 1 << 1,
93 EMPLACE_BEFORE = 1 << 2,
94 EMPLACE_AFTER = 1 << 3,
95 EMPLACE_ASSOC = 1 << 4,
96 EMPLACE_HINT = 1 << 5,
97 EMPLACE_ASSOC_PAIR = 1 << 6,
98 EMPLACE_HINT_PAIR = 1 << 7
99};
100
101template<class Container>
102bool test_expected_container(const Container &ec, const EmplaceInt *Expected, unsigned int only_first_n)
103{
104 typedef typename Container::const_iterator const_iterator;
105 const_iterator itb(ec.begin()), ite(ec.end());
106 unsigned int cur = 0;
107 if(only_first_n > ec.size()){
108 return false;
109 }
110 for(; itb != ite && only_first_n--; ++itb, ++cur){
111 const EmplaceInt & cr = *itb;
112 if(cr != Expected[cur]){
113 return false;
114 }
115 }
116 return true;
117}
118
119template<class Container>
120bool test_expected_container(const Container &ec, const std::pair<EmplaceInt, EmplaceInt> *Expected, unsigned int only_first_n)
121{
122 typedef typename Container::const_iterator const_iterator;
123 const_iterator itb(ec.begin()), ite(ec.end());
124 unsigned int cur = 0;
125 if(only_first_n > ec.size()){
126 return false;
127 }
128 for(; itb != ite && only_first_n--; ++itb, ++cur){
129 if(itb->first != Expected[cur].first){
130 std::cout << "Error in first: " << itb->first << ' ' << Expected[cur].first << std::endl;
131 return false;
132
133 }
134 else if(itb->second != Expected[cur].second){
135 std::cout << "Error in second: " << itb->second << ' ' << Expected[cur].second << std::endl;
136 return false;
137 }
138 }
139 return true;
140}
141
142static EmplaceInt expected [10];
143
144typedef std::pair<EmplaceInt, EmplaceInt> EmplaceIntPair;
145static boost::container::dtl::aligned_storage<sizeof(EmplaceIntPair)*10>::type pair_storage;
146
147static EmplaceIntPair* initialize_emplace_int_pair()
148{
149 EmplaceIntPair* ret = reinterpret_cast<EmplaceIntPair*>(&pair_storage);
150 for(unsigned int i = 0; i != 10; ++i){
151 new(&ret->first)EmplaceInt();
152 new(&ret->second)EmplaceInt();
153 }
154 return ret;
155}
156
157static EmplaceIntPair * expected_pair = initialize_emplace_int_pair();
158
159
160template<class Container>
161bool test_emplace_back(ipcdetail::true_)
162{
163 std::cout << "Starting test_emplace_back." << std::endl << " Class: "
164 << typeid(Container).name() << std::endl;
165
166 {
167 new(&expected [0]) EmplaceInt();
168 new(&expected [1]) EmplaceInt(1);
169 new(&expected [2]) EmplaceInt(1, 2);
170 new(&expected [3]) EmplaceInt(1, 2, 3);
171 new(&expected [4]) EmplaceInt(1, 2, 3, 4);
172 new(&expected [5]) EmplaceInt(1, 2, 3, 4, 5);
173 Container c;
174 c.emplace_back();
175 if(!test_expected_container(c, &expected[0], 1))
176 return false;
177 c.emplace_back(1);
178 if(!test_expected_container(c, &expected[0], 2))
179 return false;
180 c.emplace_back(1, 2);
181 if(!test_expected_container(c, &expected[0], 3))
182 return false;
183 c.emplace_back(1, 2, 3);
184 if(!test_expected_container(c, &expected[0], 4))
185 return false;
186 c.emplace_back(1, 2, 3, 4);
187 if(!test_expected_container(c, &expected[0], 5))
188 return false;
189 c.emplace_back(1, 2, 3, 4, 5);
190 if(!test_expected_container(c, &expected[0], 6))
191 return false;
192 }
193
194 return true;
195}
196
197template<class Container>
198bool test_emplace_back(ipcdetail::false_)
199{ return true; }
200
201template<class Container>
202bool test_emplace_front(ipcdetail::true_)
203{
204 std::cout << "Starting test_emplace_front." << std::endl << " Class: "
205 << typeid(Container).name() << std::endl;
206
207 {
208 new(&expected [0]) EmplaceInt(1, 2, 3, 4, 5);
209 new(&expected [1]) EmplaceInt(1, 2, 3, 4);
210 new(&expected [2]) EmplaceInt(1, 2, 3);
211 new(&expected [3]) EmplaceInt(1, 2);
212 new(&expected [4]) EmplaceInt(1);
213 new(&expected [5]) EmplaceInt();
214 Container c;
215 c.emplace_front();
216 if(!test_expected_container(c, &expected[0] + 5, 1))
217 return false;
218 c.emplace_front(1);
219 if(!test_expected_container(c, &expected[0] + 4, 2))
220 return false;
221 c.emplace_front(1, 2);
222 if(!test_expected_container(c, &expected[0] + 3, 3))
223 return false;
224 c.emplace_front(1, 2, 3);
225 if(!test_expected_container(c, &expected[0] + 2, 4))
226 return false;
227 c.emplace_front(1, 2, 3, 4);
228 if(!test_expected_container(c, &expected[0] + 1, 5))
229 return false;
230 c.emplace_front(1, 2, 3, 4, 5);
231 if(!test_expected_container(c, &expected[0] + 0, 6))
232 return false;
233 }
234 return true;
235}
236
237template<class Container>
238bool test_emplace_front(ipcdetail::false_)
239{ return true; }
240
241template<class Container>
242bool test_emplace_before(ipcdetail::true_)
243{
244 std::cout << "Starting test_emplace_before." << std::endl << " Class: "
245 << typeid(Container).name() << std::endl;
246
247 {
248 new(&expected [0]) EmplaceInt();
249 new(&expected [1]) EmplaceInt(1);
250 new(&expected [2]) EmplaceInt();
251 Container c;
252 c.emplace(c.cend(), 1);
253 c.emplace(c.cbegin());
254 if(!test_expected_container(c, &expected[0], 2))
255 return false;
256 c.emplace(c.cend());
257 if(!test_expected_container(c, &expected[0], 3))
258 return false;
259 }
260 {
261 new(&expected [0]) EmplaceInt();
262 new(&expected [1]) EmplaceInt(1);
263 new(&expected [2]) EmplaceInt(1, 2);
264 new(&expected [3]) EmplaceInt(1, 2, 3);
265 new(&expected [4]) EmplaceInt(1, 2, 3, 4);
266 new(&expected [5]) EmplaceInt(1, 2, 3, 4, 5);
267 //emplace_front-like
268 Container c;
269 c.emplace(c.cbegin(), 1, 2, 3, 4, 5);
270 c.emplace(c.cbegin(), 1, 2, 3, 4);
271 c.emplace(c.cbegin(), 1, 2, 3);
272 c.emplace(c.cbegin(), 1, 2);
273 c.emplace(c.cbegin(), 1);
274 c.emplace(c.cbegin());
275 if(!test_expected_container(c, &expected[0], 6))
276 return false;
277 c.clear();
278 //emplace_back-like
279 typename Container::const_iterator i = c.emplace(c.cend());
280 if(!test_expected_container(c, &expected[0], 1))
281 return false;
282 i = c.emplace(++i, 1);
283 if(!test_expected_container(c, &expected[0], 2))
284 return false;
285 i = c.emplace(++i, 1, 2);
286 if(!test_expected_container(c, &expected[0], 3))
287 return false;
288 i = c.emplace(++i, 1, 2, 3);
289 if(!test_expected_container(c, &expected[0], 4))
290 return false;
291 i = c.emplace(++i, 1, 2, 3, 4);
292 if(!test_expected_container(c, &expected[0], 5))
293 return false;
294 i = c.emplace(++i, 1, 2, 3, 4, 5);
295 if(!test_expected_container(c, &expected[0], 6))
296 return false;
297 c.clear();
298 //emplace in the middle
299 c.emplace(c.cbegin());
300 i = c.emplace(c.cend(), 1, 2, 3, 4, 5);
301 i = c.emplace(i, 1, 2, 3, 4);
302 i = c.emplace(i, 1, 2, 3);
303 i = c.emplace(i, 1, 2);
304 i = c.emplace(i, 1);
305
306 if(!test_expected_container(c, &expected[0], 6))
307 return false;
308 }
309 return true;
310}
311
312template<class Container>
313bool test_emplace_before(ipcdetail::false_)
314{ return true; }
315
316template<class Container>
317bool test_emplace_after(ipcdetail::true_)
318{
319 std::cout << "Starting test_emplace_after." << std::endl << " Class: "
320 << typeid(Container).name() << std::endl;
321 {
322 new(&expected [0]) EmplaceInt();
323 new(&expected [1]) EmplaceInt(1);
324 new(&expected [2]) EmplaceInt();
325 Container c;
326 typename Container::const_iterator i = c.emplace_after(c.cbefore_begin(), 1);
327 c.emplace_after(c.cbefore_begin());
328 if(!test_expected_container(c, &expected[0], 2))
329 return false;
330 c.emplace_after(i);
331 if(!test_expected_container(c, &expected[0], 3))
332 return false;
333 }
334 {
335 new(&expected [0]) EmplaceInt();
336 new(&expected [1]) EmplaceInt(1);
337 new(&expected [2]) EmplaceInt(1, 2);
338 new(&expected [3]) EmplaceInt(1, 2, 3);
339 new(&expected [4]) EmplaceInt(1, 2, 3, 4);
340 new(&expected [5]) EmplaceInt(1, 2, 3, 4, 5);
341 //emplace_front-like
342 Container c;
343 c.emplace_after(c.cbefore_begin(), 1, 2, 3, 4, 5);
344 c.emplace_after(c.cbefore_begin(), 1, 2, 3, 4);
345 c.emplace_after(c.cbefore_begin(), 1, 2, 3);
346 c.emplace_after(c.cbefore_begin(), 1, 2);
347 c.emplace_after(c.cbefore_begin(), 1);
348 c.emplace_after(c.cbefore_begin());
349 if(!test_expected_container(c, &expected[0], 6))
350 return false;
351 c.clear();
352 //emplace_back-like
353 typename Container::const_iterator i = c.emplace_after(c.cbefore_begin());
354 if(!test_expected_container(c, &expected[0], 1))
355 return false;
356 i = c.emplace_after(i, 1);
357 if(!test_expected_container(c, &expected[0], 2))
358 return false;
359 i = c.emplace_after(i, 1, 2);
360 if(!test_expected_container(c, &expected[0], 3))
361 return false;
362 i = c.emplace_after(i, 1, 2, 3);
363 if(!test_expected_container(c, &expected[0], 4))
364 return false;
365 i = c.emplace_after(i, 1, 2, 3, 4);
366 if(!test_expected_container(c, &expected[0], 5))
367 return false;
368 i = c.emplace_after(i, 1, 2, 3, 4, 5);
369 if(!test_expected_container(c, &expected[0], 6))
370 return false;
371 c.clear();
372 //emplace_after in the middle
373 i = c.emplace_after(c.cbefore_begin());
374 c.emplace_after(i, 1, 2, 3, 4, 5);
375 c.emplace_after(i, 1, 2, 3, 4);
376 c.emplace_after(i, 1, 2, 3);
377 c.emplace_after(i, 1, 2);
378 c.emplace_after(i, 1);
379
380 if(!test_expected_container(c, &expected[0], 6))
381 return false;
382 }
383 return true;
384}
385
386template<class Container>
387bool test_emplace_after(ipcdetail::false_)
388{ return true; }
389
390template<class Container>
391bool test_emplace_assoc(ipcdetail::true_)
392{
393 std::cout << "Starting test_emplace_assoc." << std::endl << " Class: "
394 << typeid(Container).name() << std::endl;
395
396 new(&expected [0]) EmplaceInt();
397 new(&expected [1]) EmplaceInt(1);
398 new(&expected [2]) EmplaceInt(1, 2);
399 new(&expected [3]) EmplaceInt(1, 2, 3);
400 new(&expected [4]) EmplaceInt(1, 2, 3, 4);
401 new(&expected [5]) EmplaceInt(1, 2, 3, 4, 5);
402 {
403 Container c;
404 c.emplace();
405 if(!test_expected_container(c, &expected[0], 1))
406 return false;
407 c.emplace(1);
408 if(!test_expected_container(c, &expected[0], 2))
409 return false;
410 c.emplace(1, 2);
411 if(!test_expected_container(c, &expected[0], 3))
412 return false;
413 c.emplace(1, 2, 3);
414 if(!test_expected_container(c, &expected[0], 4))
415 return false;
416 c.emplace(1, 2, 3, 4);
417 if(!test_expected_container(c, &expected[0], 5))
418 return false;
419 c.emplace(1, 2, 3, 4, 5);
420 if(!test_expected_container(c, &expected[0], 6))
421 return false;
422 }
423 return true;
424}
425
426template<class Container>
427bool test_emplace_assoc(ipcdetail::false_)
428{ return true; }
429
430template<class Container>
431bool test_emplace_hint(ipcdetail::true_)
432{
433 std::cout << "Starting test_emplace_hint." << std::endl << " Class: "
434 << typeid(Container).name() << std::endl;
435
436 new(&expected [0]) EmplaceInt();
437 new(&expected [1]) EmplaceInt(1);
438 new(&expected [2]) EmplaceInt(1, 2);
439 new(&expected [3]) EmplaceInt(1, 2, 3);
440 new(&expected [4]) EmplaceInt(1, 2, 3, 4);
441 new(&expected [5]) EmplaceInt(1, 2, 3, 4, 5);
442
443 {
444 Container c;
445 typename Container::const_iterator it;
446 it = c.emplace_hint(c.begin());
447 if(!test_expected_container(c, &expected[0], 1))
448 return false;
449 it = c.emplace_hint(it, 1);
450 if(!test_expected_container(c, &expected[0], 2))
451 return false;
452 it = c.emplace_hint(it, 1, 2);
453 if(!test_expected_container(c, &expected[0], 3))
454 return false;
455 it = c.emplace_hint(it, 1, 2, 3);
456 if(!test_expected_container(c, &expected[0], 4))
457 return false;
458 it = c.emplace_hint(it, 1, 2, 3, 4);
459 if(!test_expected_container(c, &expected[0], 5))
460 return false;
461 it = c.emplace_hint(it, 1, 2, 3, 4, 5);
462 if(!test_expected_container(c, &expected[0], 6))
463 return false;
464 }
465
466 return true;
467}
468
469template<class Container>
470bool test_emplace_hint(ipcdetail::false_)
471{ return true; }
472
473template<class Container>
474bool test_emplace_assoc_pair(ipcdetail::true_)
475{
476 std::cout << "Starting test_emplace_assoc_pair." << std::endl << " Class: "
477 << typeid(Container).name() << std::endl;
478
479 new(&expected_pair[0].first) EmplaceInt();
480 new(&expected_pair[0].second) EmplaceInt();
481 new(&expected_pair[1].first) EmplaceInt(1);
482 new(&expected_pair[1].second) EmplaceInt();
483 new(&expected_pair[2].first) EmplaceInt(2);
484 new(&expected_pair[2].second) EmplaceInt(2);
485// new(&expected_pair[3].first) EmplaceInt(3);
486// new(&expected_pair[3].second) EmplaceInt(2, 3);
487// new(&expected_pair[4].first) EmplaceInt(4);
488// new(&expected_pair[4].second) EmplaceInt(2, 3, 4);
489// new(&expected_pair[5].first) EmplaceInt(5);
490// new(&expected_pair[5].second) EmplaceInt(2, 3, 4, 5);
491 { //piecewise construct missing
492 /*
493 Container c;
494 c.emplace();
495 if(!test_expected_container(c, &expected_pair[0], 1)){
496 std::cout << "Error after c.emplace();\n";
497 return false;
498 }
499 c.emplace(1);
500 if(!test_expected_container(c, &expected_pair[0], 2)){
501 std::cout << "Error after c.emplace(1);\n";
502 return false;
503 }
504 c.emplace(2, 2);
505 if(!test_expected_container(c, &expected_pair[0], 3)){
506 std::cout << "Error after c.emplace(2, 2);\n";
507 return false;
508 }
509 c.emplace(3, 2, 3);
510 if(!test_expected_container(c, &expected_pair[0], 4)){
511 std::cout << "Error after c.emplace(3, 2, 3);\n";
512 return false;
513 }
514 c.emplace(4, 2, 3, 4);
515 if(!test_expected_container(c, &expected_pair[0], 5)){
516 std::cout << "Error after c.emplace(4, 2, 3, 4);\n";
517 return false;
518 }
519 c.emplace(5, 2, 3, 4, 5);
520 if(!test_expected_container(c, &expected_pair[0], 6)){
521 std::cout << "Error after c.emplace(5, 2, 3, 4, 5);\n";
522 return false;
523 }*/
524 }
525 return true;
526}
527
528template<class Container>
529bool test_emplace_assoc_pair(ipcdetail::false_)
530{ return true; }
531
532template<class Container>
533bool test_emplace_hint_pair(ipcdetail::true_)
534{
535 std::cout << "Starting test_emplace_hint_pair." << std::endl << " Class: "
536 << typeid(Container).name() << std::endl;
537
538 new(&expected_pair[0].first) EmplaceInt();
539 new(&expected_pair[0].second) EmplaceInt();
540 new(&expected_pair[1].first) EmplaceInt(1);
541 new(&expected_pair[1].second) EmplaceInt();
542 new(&expected_pair[2].first) EmplaceInt(2);
543 new(&expected_pair[2].second) EmplaceInt(2);/*
544 new(&expected_pair[3].first) EmplaceInt(3);
545 new(&expected_pair[3].second) EmplaceInt(2, 3);
546 new(&expected_pair[4].first) EmplaceInt(4);
547 new(&expected_pair[4].second) EmplaceInt(2, 3, 4);
548 new(&expected_pair[5].first) EmplaceInt(5);
549 new(&expected_pair[5].second) EmplaceInt(2, 3, 4, 5);*/
550 {/*
551 Container c;
552 typename Container::const_iterator it;
553 it = c.emplace_hint(c.begin());
554 if(!test_expected_container(c, &expected_pair[0], 1)){
555 std::cout << "Error after c.emplace(1);\n";
556 return false;
557 }
558 it = c.emplace_hint(it, 1);
559 if(!test_expected_container(c, &expected_pair[0], 2)){
560 std::cout << "Error after c.emplace(it, 1);\n";
561 return false;
562 }
563 it = c.emplace_hint(it, 2, 2);
564 if(!test_expected_container(c, &expected_pair[0], 3)){
565 std::cout << "Error after c.emplace(it, 2, 2);\n";
566 return false;
567 }
568 it = c.emplace_hint(it, 3, 2, 3);
569 if(!test_expected_container(c, &expected_pair[0], 4)){
570 std::cout << "Error after c.emplace(it, 3, 2, 3);\n";
571 return false;
572 }
573 it = c.emplace_hint(it, 4, 2, 3, 4);
574 if(!test_expected_container(c, &expected_pair[0], 5)){
575 std::cout << "Error after c.emplace(it, 4, 2, 3, 4);\n";
576 return false;
577 }
578 it = c.emplace_hint(it, 5, 2, 3, 4, 5);
579 if(!test_expected_container(c, &expected_pair[0], 6)){
580 std::cout << "Error after c.emplace(it, 5, 2, 3, 4, 5);\n";
581 return false;
582 }*/
583 }
584 return true;
585}
586
587template<class Container>
588bool test_emplace_hint_pair(ipcdetail::false_)
589{ return true; }
590
591template <EmplaceOptions O, EmplaceOptions Mask>
592struct emplace_active
593{
594 static const bool value = (0 != (O & Mask));
595 typedef ipcdetail::bool_<value> type;
596 operator type() const{ return type(); }
597};
598
599template<class Container, EmplaceOptions O>
600bool test_emplace()
601{
602 if(!test_emplace_back<Container>(emplace_active<O, EMPLACE_BACK>()))
603 return false;
604 if(!test_emplace_front<Container>(emplace_active<O, EMPLACE_FRONT>()))
605 return false;
606 if(!test_emplace_before<Container>(emplace_active<O, EMPLACE_BEFORE>()))
607 return false;
608 if(!test_emplace_after<Container>(emplace_active<O, EMPLACE_AFTER>()))
609 return false;
610 if(!test_emplace_assoc<Container>(emplace_active<O, EMPLACE_ASSOC>()))
611 return false;
612 if(!test_emplace_hint<Container>(emplace_active<O, EMPLACE_HINT>()))
613 return false;
614 if(!test_emplace_assoc_pair<Container>(emplace_active<O, EMPLACE_ASSOC_PAIR>()))
615 return false;
616 if(!test_emplace_hint_pair<Container>(emplace_active<O, EMPLACE_HINT_PAIR>()))
617 return false;
618 return true;
619}
620
621} //namespace test{
622} //namespace interprocess{
623} //namespace boost{
624
625#include <boost/interprocess/detail/config_end.hpp>
626
627#endif //#ifndef BOOST_INTERPROCESS_TEST_EMPLACE_TEST_HPP
628

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