• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2014-2014.
4 //
5 // Distributed under the Boost Software License, Version 1.0.
6 // (See accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
8 //
9 // See http://www.boost.org/libs/move for documentation.
10 //
11 //////////////////////////////////////////////////////////////////////////////
12 #include <boost/move/make_unique.hpp>
13 #include <boost/core/lightweight_test.hpp>
14 #include <cstring>
15 
16 struct A
17 {
18    int a, b, c;
19    static int count;
AA20    A() : a (999), b(1000), c(1001) {++count;}
AA21    A(int a) : a (a), b(1000), c(1001) {++count;}
AA22    A(int a, int b) : a (a), b(b), c(1001) {++count;}
AA23    A(int a, int b, int c) : a (a), b(b), c(c) {++count;}
AA24    A(const A&) {++count;}
~AA25    virtual ~A() {--count;}
26 };
27 
28 int A::count = 0;
29 
30 struct B
31    : public A
32 {
33    static int count;
BB34    B() : A() {++count;}
BB35    B(const B&) : A() {++count;}
~BB36    virtual ~B() {--count;}
37 };
38 
39 int B::count = 0;
40 
reset_counters()41 void reset_counters()
42 {  A::count = B::count = 0;  }
43 
44 static const unsigned PatternSize = 8;
45 static const unsigned char ff_patternbuf[PatternSize] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
46 static const unsigned char ee_patternbuf[PatternSize] = { 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE };
47 static const unsigned char dd_patternbuf[PatternSize] = { 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD };
48 static const unsigned char cc_patternbuf[PatternSize] = { 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC };
49 
volatile_memset(volatile void * p,int ch,std::size_t len)50 void volatile_memset(volatile void *p, int ch, std::size_t len)
51 {
52    volatile unsigned char *puch = static_cast<volatile unsigned char *>(p);
53    for(std::size_t i = 0; i != len; ++i){
54       *puch = (unsigned char)ch;
55       ++puch;
56    }
57 }
58 
volatile_memcmp(const volatile void * p1,const volatile void * p2,std::size_t len)59 int volatile_memcmp(const volatile void *p1, const volatile void *p2, std::size_t len)
60 {
61    const volatile unsigned char *s1 = static_cast<const volatile unsigned char *>(p1);
62    const volatile unsigned char *s2 = static_cast<const volatile unsigned char *>(p2);
63    unsigned char u1, u2;
64 
65    for ( ; len-- ; s1++, s2++) {
66       u1 = *s1;
67       u2 = *s2;
68       if (u1 != u2) {
69          return (u1-u2);
70       }
71    }
72    return 0;
73 }
74 
volatile_memcmp(volatile void * p,int ch,std::size_t len)75 void volatile_memcmp(volatile void *p, int ch, std::size_t len)
76 {
77    volatile unsigned char *puch = static_cast<volatile unsigned char *>(p);
78    for(std::size_t i = 0; i != len; ++i){
79       *puch = (unsigned char)ch;
80       ++puch;
81    }
82 }
83 
84 #include <iostream>
85 
86 struct default_init
87 {
operator newdefault_init88    static void* operator new(std::size_t sz)
89    {
90       void *const p = ::operator new(sz);
91       //Make sure they are not optimized out
92       volatile_memset(p, 0xFF, sz);
93       std::cout << "0xFF" << '\n';
94       return p;
95    }
operator new[]default_init96    static void* operator new[](std::size_t sz)
97    {
98       void *const p = ::operator new[](sz);
99       //Make sure they are not optimized out
100       volatile_memset(p, 0xEE, sz);
101       std::cout << "0xEE" << '\n';
102       return p;
103    }
operator newdefault_init104    static void* operator new(std::size_t sz, const std::nothrow_t &)
105    {
106       void *const p = ::operator new(sz);
107       //Make sure they are not optimized out
108       volatile_memset(p, 0xDD, sz);
109       std::cout << "0xDD" << '\n';
110       return p;
111    }
operator new[]default_init112    static void* operator new[](std::size_t sz, const std::nothrow_t &)
113    {
114       void *const p = ::operator new[](sz);
115       //Make sure they are not optimized out
116       volatile_memset(p, 0xCC, sz);
117       std::cout << "0xCC" << '\n';
118       return p;
119    }
120    unsigned char buf[PatternSize];
121 };
122 
123 namespace bml = ::boost::movelib;
124 
125 ////////////////////////////////
126 //   make_unique_single
127 ////////////////////////////////
128 
129 namespace make_unique_single{
130 
test()131 void test()
132 {
133    //Single element deleter
134    reset_counters();
135    {
136    bml::unique_ptr<default_init> p(bml::make_unique_definit<default_init>());
137    BOOST_TEST(0 == volatile_memcmp(p.get(), ff_patternbuf, sizeof(ff_patternbuf)));
138    }
139    {
140    bml::unique_ptr<default_init> p(bml::make_unique_nothrow_definit<default_init>());
141 
142    BOOST_TEST(0 == volatile_memcmp(p.get(), dd_patternbuf, sizeof(dd_patternbuf)));
143    }
144 
145    BOOST_TEST(A::count == 0);
146    {
147    bml::unique_ptr<A> p(bml::make_unique<A>());
148    BOOST_TEST(A::count == 1);
149    BOOST_TEST(p->a == 999);
150    BOOST_TEST(p->b == 1000);
151    BOOST_TEST(p->c == 1001);
152    }
153    BOOST_TEST(A::count == 0);
154    {
155    bml::unique_ptr<A> p(bml::make_unique_nothrow<A>(0));
156    BOOST_TEST(A::count == 1);
157    BOOST_TEST(p->a == 0);
158    BOOST_TEST(p->b == 1000);
159    BOOST_TEST(p->c == 1001);
160    }
161    BOOST_TEST(A::count == 0);
162    {
163    bml::unique_ptr<A> p(bml::make_unique<A>(0, 1));
164    BOOST_TEST(A::count == 1);
165    BOOST_TEST(p->a == 0);
166    BOOST_TEST(p->b == 1);
167    BOOST_TEST(p->c == 1001);
168    }
169    BOOST_TEST(A::count == 0);
170    {
171    bml::unique_ptr<A> p(bml::make_unique_nothrow<A>(0, 1, 2));
172    BOOST_TEST(A::count == 1);
173    BOOST_TEST(p->a == 0);
174    BOOST_TEST(p->b == 1);
175    BOOST_TEST(p->c == 2);
176    }
177    BOOST_TEST(A::count == 0);
178 }
179 
180 }  //namespace make_unique_single{
181 
182 
183 ////////////////////////////////
184 //    make_unique_array
185 ////////////////////////////////
186 
187 namespace make_unique_array{
188 
test()189 void test()
190 {
191    //Array element
192    reset_counters();
193    {
194       bml::unique_ptr<A[]> p(bml::make_unique<A[]>(10));
195       BOOST_TEST(A::count == 10);
196       for(int i = 0; i != 10; ++i){
197          BOOST_TEST(p[i].a == 999);
198          BOOST_TEST(p[i].b == 1000);
199          BOOST_TEST(p[i].c == 1001);
200       }
201    }
202    BOOST_TEST(A::count == 0);
203    {
204       bml::unique_ptr<A[]> p(bml::make_unique_nothrow<A[]>(10));
205       BOOST_TEST(A::count == 10);
206       for(int i = 0; i != 10; ++i){
207          BOOST_TEST(p[i].a == 999);
208          BOOST_TEST(p[i].b == 1000);
209          BOOST_TEST(p[i].c == 1001);
210       }
211    }
212    BOOST_TEST(A::count == 0);
213    reset_counters();
214    {
215       bml::unique_ptr<default_init[]> p(bml::make_unique_definit<default_init[]>(10));
216       for(unsigned i = 0; i != 10; ++i){
217          BOOST_TEST(0 == volatile_memcmp(&p[i], ee_patternbuf, sizeof(ee_patternbuf)));
218       }
219    }
220    reset_counters();
221    {
222       bml::unique_ptr<default_init[]> p(bml::make_unique_nothrow_definit<default_init[]>(10));
223       for(unsigned i = 0; i != 10; ++i){
224          BOOST_TEST(0 == volatile_memcmp(&p[i], cc_patternbuf, sizeof(cc_patternbuf)));
225       }
226    }
227 }
228 
229 }  //namespace make_unique_array{
230 
231 ////////////////////////////////
232 //       unique_compare
233 ////////////////////////////////
234 
235 namespace unique_compare{
236 
test()237 void test()
238 {
239    //Single element deleter
240    reset_counters();
241    {
242       bml::unique_ptr<A> pa(bml::make_unique<A>());
243       bml::unique_ptr<A> pb(bml::make_unique<A>());
244       BOOST_TEST(A::count == 2);
245 
246       //Take references to less and greater
247       bml::unique_ptr<A> &rpl = pa < pb ? pa : pb;
248       bml::unique_ptr<A> &rpg = pa < pb ? pb : pa;
249 
250       //Now test operations with .get()
251 
252       //Equal
253       BOOST_TEST(rpl == rpl && rpl.get() == rpl.get());
254       BOOST_TEST(!(rpl == rpg) && !(rpl.get() == rpg.get()));
255       //Unequal
256       BOOST_TEST(rpl != rpg && rpl.get() != rpg.get());
257       BOOST_TEST(!(rpl != rpl) && !(rpl.get() != rpl.get()));
258       //Less
259       BOOST_TEST(rpl < rpg && rpl.get() < rpg.get());
260       BOOST_TEST(!(rpg < rpl) && !(rpg.get() < rpl.get()));
261       //Greater
262       BOOST_TEST(rpg > rpl && rpg.get() > rpl.get());
263       BOOST_TEST(!(rpg > rpg) && !(rpg.get() > rpg.get()));
264       //Less or equal
265       BOOST_TEST(rpl <= rpg && rpl.get() <= rpg.get());
266       BOOST_TEST(rpl <= rpl && rpl.get() <= rpl.get());
267       BOOST_TEST(!(rpg <= rpl) && !(rpg.get() <= rpl.get()));
268       //Greater or equal
269       BOOST_TEST(rpg >= rpl && rpg.get() >= rpl.get());
270       BOOST_TEST(rpg >= rpg && rpg.get() >= rpg.get());
271       BOOST_TEST(!(rpl >= rpg) && !(rpl.get() >= rpg.get()));
272    }
273    BOOST_TEST(A::count == 0);
274 }
275 
276 }  //namespace unique_compare{
277 
278 ////////////////////////////////
279 //       unique_compare_zero
280 ////////////////////////////////
281 namespace unique_compare_zero{
282 
test()283 void test()
284 {
285    //Single element deleter
286    reset_counters();
287    {
288       bml::unique_ptr<A> pa(bml::make_unique<A>());
289       bml::unique_ptr<A> pb;
290       BOOST_TEST(A::count == 1);
291 
292       //Equal
293       BOOST_TEST(!(pa == 0));
294       BOOST_TEST(!(0  == pa));
295       BOOST_TEST((pb == 0));
296       BOOST_TEST((0  == pb));
297       //Unequal
298       BOOST_TEST((pa != 0));
299       BOOST_TEST((0  != pa));
300       BOOST_TEST(!(pb != 0));
301       BOOST_TEST(!(0  != pb));
302       //Less
303       BOOST_TEST((pa < 0) == (pa.get() < (A*)0));
304       BOOST_TEST((0 < pa) == ((A*)0 < pa.get()));
305       BOOST_TEST((pb < 0) == (pb.get() < (A*)0));
306       BOOST_TEST((0 < pb) == ((A*)0 < pb.get()));
307       //Greater
308       BOOST_TEST((pa > 0) == (pa.get() > (A*)0));
309       BOOST_TEST((0 > pa) == ((A*)0 > pa.get()));
310       BOOST_TEST((pb > 0) == (pb.get() > (A*)0));
311       BOOST_TEST((0 > pb) == ((A*)0 > pb.get()));
312       //Less or equal
313       BOOST_TEST((pa <= 0) == (pa.get() <= (A*)0));
314       BOOST_TEST((0 <= pa) == ((A*)0 <= pa.get()));
315       BOOST_TEST((pb <= 0) == (pb.get() <= (A*)0));
316       BOOST_TEST((0 <= pb) == ((A*)0 <= pb.get()));
317       //Greater or equal
318       BOOST_TEST((pa >= 0) == (pa.get() >= (A*)0));
319       BOOST_TEST((0 >= pa) == ((A*)0 >= pa.get()));
320       BOOST_TEST((pb >= 0) == (pb.get() >= (A*)0));
321       BOOST_TEST((0 >= pb) == ((A*)0 >= pb.get()));
322    }
323    BOOST_TEST(A::count == 0);
324 }
325 
326 }  //namespace unique_compare_zero{
327 
328 ////////////////////////////////
329 //       unique_compare_nullptr
330 ////////////////////////////////
331 
332 namespace unique_compare_nullptr{
333 
test()334 void test()
335 {
336    #if !defined(BOOST_NO_CXX11_NULLPTR)
337    //Single element deleter
338    reset_counters();
339    {
340       bml::unique_ptr<A> pa(bml::make_unique<A>());
341       bml::unique_ptr<A> pb;
342       BOOST_TEST(A::count == 1);
343 
344       //Equal
345       BOOST_TEST(!(pa == nullptr));
346       BOOST_TEST(!(nullptr  == pa));
347       BOOST_TEST((pb == nullptr));
348       BOOST_TEST((nullptr  == pb));
349       //Unequal
350       BOOST_TEST((pa != nullptr));
351       BOOST_TEST((nullptr  != pa));
352       BOOST_TEST(!(pb != nullptr));
353       BOOST_TEST(!(nullptr  != pb));
354       //Less
355       BOOST_TEST((pa < nullptr) == (pa.get() < (A*)nullptr));
356       BOOST_TEST((nullptr < pa) == ((A*)nullptr < pa.get()));
357       BOOST_TEST((pb < nullptr) == (pb.get() < (A*)nullptr));
358       BOOST_TEST((nullptr < pb) == ((A*)nullptr < pb.get()));
359       //Greater
360       BOOST_TEST((pa > nullptr) == (pa.get() > (A*)nullptr));
361       BOOST_TEST((nullptr > pa) == ((A*)nullptr > pa.get()));
362       BOOST_TEST((pb > nullptr) == (pb.get() > (A*)nullptr));
363       BOOST_TEST((nullptr > pb) == ((A*)nullptr > pb.get()));
364       //Less or equal
365       BOOST_TEST((pa <= nullptr) == (pa.get() <= (A*)nullptr));
366       BOOST_TEST((nullptr <= pa) == ((A*)nullptr <= pa.get()));
367       BOOST_TEST((pb <= nullptr) == (pb.get() <= (A*)nullptr));
368       BOOST_TEST((nullptr <= pb) == ((A*)nullptr <= pb.get()));
369       //Greater or equal
370       BOOST_TEST((pa >= nullptr) == (pa.get() >= (A*)nullptr));
371       BOOST_TEST((nullptr >= pa) == ((A*)nullptr >= pa.get()));
372       BOOST_TEST((pb >= nullptr) == (pb.get() >= (A*)nullptr));
373       BOOST_TEST((nullptr >= pb) == ((A*)nullptr >= pb.get()));
374    }
375    BOOST_TEST(A::count == 0);
376    #endif   //#if !defined(BOOST_NO_CXX11_NULLPTR)
377 }
378 
379 }  //namespace unique_compare_nullptr{
380 
381 
382 ////////////////////////////////
383 //             main
384 ////////////////////////////////
main()385 int main()
386 {
387    make_unique_single::test();
388    make_unique_array::test();
389    unique_compare::test();
390    unique_compare_zero::test();
391    unique_compare_nullptr::test();
392 
393    //Test results
394    return boost::report_errors();
395 }
396