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
16struct A
17{
18 int a, b, c;
19 static int count;
20 A() : a (999), b(1000), c(1001) {++count;}
21 A(int x) : a (x), b(1000), c(1001) {++count;}
22 A(int x, int y) : a (x), b(y), c(1001) {++count;}
23 A(int x, int y, int z) : a (x), b(y), c(z) {++count;}
24 A(const A&) {++count;}
25 virtual ~A() {--count;}
26};
27
28int A::count = 0;
29
30struct B
31 : public A
32{
33 static int count;
34 B() : A() {++count;}
35 B(const B&) : A() {++count;}
36 virtual ~B() {--count;}
37};
38
39int B::count = 0;
40
41void reset_counters()
42{ A::count = B::count = 0; }
43
44static const unsigned PatternSize = 8;
45static const unsigned char ff_patternbuf[PatternSize] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
46static const unsigned char ee_patternbuf[PatternSize] = { 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE };
47static const unsigned char dd_patternbuf[PatternSize] = { 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD };
48static const unsigned char cc_patternbuf[PatternSize] = { 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC };
49
50void 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
59int 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
75void 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
86struct default_init
87{
88 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, ch: 0xFF, len: sz);
93 std::cout << "0xFF" << '\n';
94 return p;
95 }
96 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, ch: 0xEE, len: sz);
101 std::cout << "0xEE" << '\n';
102 return p;
103 }
104 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, ch: 0xDD, len: sz);
109 std::cout << "0xDD" << '\n';
110 return p;
111 }
112 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, ch: 0xCC, len: sz);
117 std::cout << "0xCC" << '\n';
118 return p;
119 }
120 unsigned char buf[PatternSize];
121};
122
123namespace bml = ::boost::movelib;
124
125////////////////////////////////
126// make_unique_single
127////////////////////////////////
128
129namespace make_unique_single{
130
131void 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>(args: 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>(args: 0, args: 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>(args: 0, args: 1, args: 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
187namespace make_unique_array{
188
189void test()
190{
191 //Array element
192 reset_counters();
193 {
194 bml::unique_ptr<A[]> p(bml::make_unique<A[]>(n: 10));
195 BOOST_TEST(A::count == 10);
196 for(std::size_t i = 0; i != 10u; ++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[]>(n: 10));
205 BOOST_TEST(A::count == 10);
206 for(std::size_t i = 0; i != 10u; ++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[]>(n: 10));
216 for(std::size_t i = 0; i != 10u; ++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[]>(n: 10));
223 for(std::size_t i = 0; i != 10u; ++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
235namespace unique_compare{
236
237void 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////////////////////////////////
281namespace unique_compare_zero{
282
283void 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
332namespace unique_compare_nullptr{
333
334void 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////////////////////////////////
385int 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

source code of boost/libs/move/test/unique_ptr_functions.cpp