libjmmcg  release_579_6_g8cffd
A C++ library containing an eclectic mix of useful, advanced components.
unique_ptr.cpp
Go to the documentation of this file.
1 /******************************************************************************
2 ** Copyright © 2015 by J.M.McGuiness, coder@hussar.me.uk
3 **
4 ** This library is free software; you can redistribute it and/or
5 ** modify it under the terms of the GNU Lesser General Public
6 ** License as published by the Free Software Foundation; either
7 ** version 2.1 of the License, or (at your option) any later version.
8 **
9 ** This library is distributed in the hope that it will be useful,
10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 ** Lesser General Public License for more details.
13 **
14 ** You should have received a copy of the GNU Lesser General Public
15 ** License along with this library; if not, write to the Free Software
16 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18 
19 #include "stdafx.h"
20 
21 #define BOOST_TEST_MODULE libjmmcg_tests
22 #include <boost/test/included/unit_test.hpp>
23 
24 #include <boost/mpl/list.hpp>
25 
26 #include "core/unique_ptr.hpp"
27 #include "core/deleter.hpp"
28 #include "core/thread_api_traits.hpp"
29 
30 using namespace libjmmcg;
31 using namespace ppd;
32 
33 typedef boost::mpl::list<
37 
38 template<class Mdl>
39 struct base {
40  using lock_traits=api_lock_traits<platform_api, Mdl>;
41  using deleter_t=default_delete<base>;
42 
43  virtual ~base() noexcept(true) {}
44 
45  virtual void deleter() final {
46  deleter_t().operator()(this);
47  }
48 
49  bool __fastcall operator<(base const &a) const noexcept(true) {
50  return this<&a;
51  }
52 };
53 template<class Mdl>
54 struct derived final : public base<Mdl> {
55  using base_t=base<Mdl>;
56  using lock_traits=typename base_t::lock_traits;
57  using deleter_t=typename base_t::deleter_t;
58 };
59 template<class Mdl>
60 struct placement_dtor_test_t {
61  using lock_traits=api_lock_traits<platform_api, Mdl>;
62  using deleter_t=placement_dtor<placement_dtor_test_t>;
63 
64  const int val;
65 
66  placement_dtor_test_t() noexcept(true)
67  : val(42) {}
68  ~placement_dtor_test_t() noexcept(true) {}
69 
70  void deleter() {
71  deleter_t().operator()(this);
72  }
73 
74  bool __fastcall operator<(placement_dtor_test_t const &a) const noexcept(true) {
75  return this<&a;
76  }
77 };
78 
79 template<class Mdl>
80 struct base_inh_t {
81  using lock_traits=api_lock_traits<platform_api, Mdl>;
82  using deleter_t=default_delete<base_inh_t>;
83 
84  virtual ~base_inh_t() noexcept(true) {
85  }
86  virtual int val() const noexcept(true)=0;
87 
88  virtual void deleter() {
89  deleter_t().operator()(this);
90  }
91 };
92 template<class Mdl, template<class> class Del>
93 struct derived_inh_t final : public base_inh_t<Mdl> {
94  using base_t=base_inh_t<Mdl>;
95  using lock_traits=typename base_t::lock_traits;
96  using deleter_t=Del<derived_inh_t>;
97 
98  const int val_;
99 
100  explicit derived_inh_t(int i) noexcept(true)
101  : val_(i) {}
102 
103  int val() const noexcept(true) override {
104  return val_;
105  }
106 
107  void deleter() override {
108  deleter_t().operator()(this);
109  }
110 
111  bool __fastcall operator<(derived_inh_t const &a) const noexcept(true) {
112  return this<&a;
113  }
114 };
115 
116 template<class Mdl>
117 struct stack_test_t {
118  using lock_traits=api_lock_traits<platform_api, Mdl>;
119  using deleter_t=noop_dtor<stack_test_t>;
120 
121  const int val;
122 
123  stack_test_t() noexcept(true)
124  : val(42) {}
125  ~stack_test_t() noexcept(true) {}
126 
127  void deleter() {
128  deleter_t().operator()(this);
129  }
130 };
131 
132 BOOST_AUTO_TEST_SUITE(unique_ptr_tests)
133 
134 BOOST_AUTO_TEST_CASE_TEMPLATE(default_ctor_unique_ptr, Mdl, thread_types)
135 {
136  typedef unique_ptr<base<Mdl>, api_lock_traits<platform_api, Mdl>> ptr_t;
137 
138  ptr_t a;
139  BOOST_CHECK_EQUAL(a.get(), static_cast<typename ptr_t::value_type *>(0));
140  BOOST_CHECK(!a);
141 }
142 
143 BOOST_AUTO_TEST_CASE_TEMPLATE(ctor_unique_ptr, Mdl, thread_types)
144 {
145  typedef unique_ptr<base<Mdl>, api_lock_traits<platform_api, Mdl>> ptr_t;
146 
147  typename ptr_t::value_type *ptr_a=new typename ptr_t::value_type;
148  ptr_t a(ptr_a);
149  BOOST_CHECK_EQUAL(a.get(), ptr_a);
150  BOOST_CHECK(!(!a));
151 }
152 
153 BOOST_AUTO_TEST_CASE_TEMPLATE(placement_new_ctor_unique_ptr, Mdl, thread_types)
154 {
155  typedef unique_ptr<placement_dtor_test_t<Mdl>, api_lock_traits<platform_api, Mdl>> ptr_t;
156 
157  char buff[sizeof(typename ptr_t::value_type)];
158  typename ptr_t::value_type *ptr_a=new (buff) typename ptr_t::value_type;
159  ptr_t a(ptr_a);
160  BOOST_CHECK_EQUAL(a.get(), ptr_a);
161  BOOST_CHECK(!(!a));
162  BOOST_CHECK_EQUAL(a->val, 42);
163 }
164 
165 BOOST_AUTO_TEST_CASE_TEMPLATE(mixed_dtors_placement_new_ctor_unique_ptr, Mdl, thread_types)
166 {
167  typedef derived_inh_t<Mdl, default_delete> def_del_t;
168  typedef derived_inh_t<Mdl, placement_dtor> plment_del_t;
169  typedef unique_ptr<base_inh_t<Mdl>, api_lock_traits<platform_api, Mdl>> ptr_t;
170 
171  char buff[sizeof(plment_del_t)];
172  def_del_t *ptr_def_del=new def_del_t(42);
173  plment_del_t *ptr_plment_del=new (buff) plment_del_t(1066);
174  ptr_t sp_def_del(ptr_def_del);
175  ptr_t sp_plment_del(ptr_plment_del);
176  BOOST_CHECK_EQUAL(sp_def_del.get(), ptr_def_del);
177  BOOST_CHECK(!(!sp_def_del));
178  BOOST_CHECK_EQUAL(sp_def_del->val(), 42);
179  BOOST_CHECK_EQUAL(sp_plment_del.get(), ptr_plment_del);
180  BOOST_CHECK(!(!sp_plment_del));
181  BOOST_CHECK_EQUAL(sp_plment_del->val(), 1066);
182 }
183 
184 BOOST_AUTO_TEST_CASE_TEMPLATE(move_ctor_unique_ptr, Mdl, thread_types)
185 {
186  typedef unique_ptr<base<Mdl>, api_lock_traits<platform_api, Mdl>> ptr_t;
187 
188  typename ptr_t::value_type *ptr_a=new typename ptr_t::value_type;
189  ptr_t a(ptr_a);
190  ptr_t a1(std::move(a));
191  BOOST_CHECK_EQUAL(a1.get(), ptr_a);
192  BOOST_CHECK_EQUAL(a.get(), typename ptr_t::atomic_ptr_t());
193 }
194 
195 BOOST_AUTO_TEST_CASE_TEMPLATE(unique_ptr_ctor_unique_ptr, Mdl, thread_types)
196 {
197  typedef unique_ptr<base<Mdl>, api_lock_traits<platform_api, Mdl>> ptr_t;
198 
199  std::unique_ptr<typename ptr_t::value_type, typename ptr_t::value_type::deleter_t> ptr_a(new typename ptr_t::value_type);
200  ptr_t a(std::move(ptr_a));
201  BOOST_CHECK(a.get());
202  BOOST_CHECK_EQUAL(ptr_a.get(), static_cast<typename ptr_t::value_type *>(0));
203 }
204 
205 BOOST_AUTO_TEST_CASE_TEMPLATE(unique_ptr_move_ctor_unique_ptr, Mdl, thread_types)
206 {
207  typedef unique_ptr<base<Mdl>, api_lock_traits<platform_api, Mdl>> ptr_t;
208 
209  std::unique_ptr<typename ptr_t::value_type, typename ptr_t::value_type::deleter_t> ptr_a(new typename ptr_t::value_type);
210  ptr_t a(std::move(ptr_a));
211  BOOST_CHECK(dynamic_cast<typename ptr_t::value_type const *>(a.get().get()));
212 }
213 
214 BOOST_AUTO_TEST_CASE_TEMPLATE(reset_unique_ptr, Mdl, thread_types)
215 {
216  typedef unique_ptr<base<Mdl>, api_lock_traits<platform_api, Mdl>> ptr_t;
217 
218  typename ptr_t::value_type *ptr_a=new typename ptr_t::value_type;
219  ptr_t a(ptr_a);
220  a.reset();
221  BOOST_CHECK_EQUAL(a.get(), static_cast<typename ptr_t::value_type *>(0));
222  BOOST_CHECK(!a);
223 }
224 
225 BOOST_AUTO_TEST_CASE_TEMPLATE(assign_move_unique_ptr, Mdl, thread_types)
226 {
227  typedef unique_ptr<base<Mdl>, api_lock_traits<platform_api, Mdl>> ptr_t;
228 
229  typename ptr_t::value_type *ptr_a=new typename ptr_t::value_type;
230  ptr_t a(ptr_a);
231  ptr_t a1;
232  a1=std::move(a);
233  BOOST_CHECK_EQUAL(a.get(), static_cast<typename ptr_t::value_type *>(0));
234  BOOST_CHECK_EQUAL(a1.get(), ptr_a);
235 }
236 
237 BOOST_AUTO_TEST_CASE_TEMPLATE(ctor_assign_unique_ptr, Mdl, thread_types)
238 {
239  typedef unique_ptr<base<Mdl>, api_lock_traits<platform_api, Mdl>> ptr_t;
240 
241  ptr_t a;
242  a=ptr_t(new typename ptr_t::value_type);
243  BOOST_CHECK(a.get());
244 }
245 
246 BOOST_AUTO_TEST_CASE_TEMPLATE(ctor_assign_move_unique_ptr, Mdl, thread_types)
247 {
248  typedef unique_ptr<base<Mdl>, api_lock_traits<platform_api, Mdl>> ptr_t;
249 
250  std::unique_ptr<typename ptr_t::value_type, typename ptr_t::value_type::deleter_t> ptr_a(new typename ptr_t::value_type);
251  ptr_t a;
252  a=ptr_t(std::move(ptr_a));
253  BOOST_CHECK(a.get());
254  BOOST_CHECK_EQUAL(ptr_a.get(), static_cast<typename ptr_t::value_type *>(0));
255 }
256 
257 BOOST_AUTO_TEST_CASE_TEMPLATE(equals_move, Mdl, thread_types)
258 {
259  typedef unique_ptr<base<Mdl>, api_lock_traits<platform_api, Mdl>> ptr_t;
260 
261  typename ptr_t::value_type *ptr_a=new typename ptr_t::value_type;
262  ptr_t a(ptr_a);
263  ptr_t a1(std::move(a));
264  BOOST_CHECK(a!=a1);
265 }
266 
267 BOOST_AUTO_TEST_CASE_TEMPLATE(not_equals_unique_ptr, Mdl, thread_types)
268 {
269  typedef unique_ptr<base<Mdl>, api_lock_traits<platform_api, Mdl>> ptr_t;
270 
271  typename ptr_t::value_type *ptr_a=new typename ptr_t::value_type;
272  typename ptr_t::value_type *ptr_a1=new typename ptr_t::value_type;
273  ptr_t a(ptr_a);
274  ptr_t a1(ptr_a1);
275  BOOST_CHECK(a!=a1);
276  BOOST_CHECK(!(a==a1));
277 }
278 
279 BOOST_AUTO_TEST_CASE_TEMPLATE(equals_comparators_unique_ptr, Mdl, thread_types)
280 {
281  typedef unique_ptr<base<Mdl>, api_lock_traits<platform_api, Mdl>> ptr_t;
282 
283  typename ptr_t::value_type *ptr_a=new typename ptr_t::value_type;
284  ptr_t a(ptr_a);
285  ptr_t a1(std::move(a));
286  BOOST_CHECK(!(a<a1) && !(a>a1));
287 }
288 
289 BOOST_AUTO_TEST_CASE_TEMPLATE(not_equals_comparators_unique_ptr, Mdl, thread_types)
290 {
291  typedef unique_ptr<base<Mdl>, api_lock_traits<platform_api, Mdl>> ptr_t;
292 
293  typename ptr_t::value_type *ptr_a=new typename ptr_t::value_type;
294  typename ptr_t::value_type *ptr_a1=new typename ptr_t::value_type;
295  ptr_t a(ptr_a);
296  ptr_t a1(ptr_a1);
297  BOOST_CHECK((a<a1) || (a>a1));
298 }
299 
300 BOOST_AUTO_TEST_CASE_TEMPLATE(inheritance_wrapping, Mdl, thread_types)
301 {
302  typedef unique_ptr<base<Mdl>, api_lock_traits<platform_api, Mdl>> ptr_t;
303  typedef unique_ptr<derived<Mdl>, api_lock_traits<platform_api, Mdl>> ptr_b_t;
304 
305  typename ptr_b_t::value_type *ptr_b=new typename ptr_b_t::value_type;
306  ptr_t b(ptr_b);
307  BOOST_CHECK(b.get()==ptr_b);
308 }
309 
310 BOOST_AUTO_TEST_CASE_TEMPLATE(moves_the_ptr, Mdl, thread_types)
311 {
312  typedef unique_ptr<base<Mdl>, api_lock_traits<platform_api, Mdl>> ptr_t;
313 
314  typename ptr_t::value_type *ptr_a=new typename ptr_t::value_type;
315  ptr_t a(ptr_a);
316  {
317  ptr_t a1(std::move(a));
318  BOOST_CHECK(a.get()!=a1.get());
319  BOOST_CHECK(a!=a1);
320  }
321  BOOST_CHECK_EQUAL(a.get(), static_cast<typename ptr_t::value_type *>(0));
322 }
323 
324 BOOST_AUTO_TEST_CASE_TEMPLATE(default_ctor_stack_test, Mdl, thread_types)
325 {
326  typedef unique_ptr<stack_test_t<Mdl>, api_lock_traits<platform_api, Mdl>> ptr_t;
327 
328  ptr_t a;
329  BOOST_CHECK_EQUAL(a.get(), static_cast<typename ptr_t::value_type *>(0));
330  BOOST_CHECK(!a);
331 }
332 
333 BOOST_AUTO_TEST_CASE_TEMPLATE(ctor_stack_test, Mdl, thread_types)
334 {
335  typedef unique_ptr<stack_test_t<Mdl>, api_lock_traits<platform_api, Mdl>> ptr_t;
336 
337  typename ptr_t::value_type val_a;
338  ptr_t a(&val_a);
339  BOOST_CHECK(a.get()==&val_a);
340 }
341 
342 BOOST_AUTO_TEST_CASE_TEMPLATE(moves_stack_test, Mdl, thread_types)
343 {
344  typedef unique_ptr<stack_test_t<Mdl>, api_lock_traits<platform_api, Mdl>> ptr_t;
345 
346  typename ptr_t::value_type val_a;
347  ptr_t a(&val_a);
348  {
349  ptr_t a1(std::move(a));
350  BOOST_CHECK(a.get()!=a1.get());
351  BOOST_CHECK(a!=a1);
352  BOOST_CHECK_EQUAL(a1->val, 42);
353  }
354  BOOST_CHECK_EQUAL(a.get(), static_cast<typename ptr_t::value_type *>(0));
355 }
356 
357 BOOST_AUTO_TEST_SUITE_END()