Lumiera  0.pre.03
»edit your freedom«
custom-shared-ptr-test.cpp
Go to the documentation of this file.
1 /*
2  CustomSharedPtr(Test) - ref counting, equality and comparisons
3 
4  Copyright (C) Lumiera.org
5  2008, 2010, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 * *****************************************************/
22 
28 #include "lib/test/run.hpp"
29 #include "lib/test/test-helper.hpp"
30 #include "lib/util.hpp"
31 
32 #include "lib/p.hpp"
33 
34 #include <boost/operators.hpp>
35 
36 
37 
38 namespace lib {
39 namespace test{
40 
41  using std::string;
42  using std::shared_ptr;
43  using std::weak_ptr;
44 
45  using lumiera::error::LUMIERA_ERROR_ASSERTION;
46 
47 
48  struct X
49  : boost::totally_ordered<X>
50  {
51  long x_;
52 
53  X(long x=0) : x_(x) {}
54  operator long () { return x_; }
55 
56  bool operator< (const X& ox) const { return x_ < ox.x_; }
57  bool operator== (const X& ox) const { return x_ == ox.x_; }
58 
59  virtual ~X() {} // using RTTI
60  };
61 
62  struct XX : public X
63  {
64  long xx_;
65 
66  XX(long x=0) : X(x), xx_(x+1) {}
67  };
68 
69 
70  /************************************************************/
76  class CustomSharedPtr_test : public Test
77  {
78  virtual void
79  run (Arg)
80  {
81  check_refcounting ();
82  check_shared_ownership ();
83  check_ownership_transfer ();
84  check_type_relations ();
85  check_ordering ();
86  }
87 
88 
90  void
92  {
93  P<X> p1 (new X(7));
94  CHECK (p1);
95  CHECK (1 == p1.use_count());
96  CHECK (7 == p1->x_);
97 
98  {
99  P<X> p2 (new X(9));
100  CHECK (1 == p2.use_count());
101 
102  p2.swap (p1);
103  CHECK (1 == p1.use_count());
104  CHECK (1 == p2.use_count());
105 
106  p2 = p1;
107  CHECK (2 == p1.use_count());
108  CHECK (2 == p2.use_count());
109  }
110 
111  CHECK (1 == p1.use_count());
112  CHECK (9 == p1->x_);
113 
114  p1.reset();
115  CHECK (0 == p1.use_count());
116  CHECK (!p1);
117  }
118 
119 
121  void
123  {
124  P<X> pX (new X(22));
125  CHECK (pX);
126  CHECK (1 == pX.use_count());
127 
128  weak_ptr<X> wX (pX);
129  CHECK (wX.lock());
130  CHECK (1 == pX.use_count());
131 
132  shared_ptr<X> sp1 (wX);
133  shared_ptr<X> sp2 (pX);
134  shared_ptr<X> sp3; sp3 = pX;
135 
136  CHECK (22 == sp3->x_);
137  CHECK (4 == pX.use_count());
138  CHECK (*pX == *sp1);
139  CHECK (*sp1 == *sp2);
140  CHECK (*sp2 == *sp3);
141 
142  P<X> pX2;
143  pX2.swap(pX);
144  CHECK (!pX);
145  CHECK (0 == pX.use_count());
146  CHECK (4 == pX2.use_count());
147 
148  P<X, P<X>> pXX (pX2); // a different type, but compatible pointers
149  pX2 = pX;
150  CHECK (!pX2);
151  CHECK (0 == pX2.use_count());
152  CHECK (4 == pXX.use_count());
153 
154  sp3 = sp2 = sp1 = pX;
155  CHECK (22 == pXX->x_);
156  CHECK (1 == pXX.use_count());
157  CHECK (!sp1);
158  CHECK (!sp2);
159  CHECK (!sp3);
160 
161  CHECK (22 == wX.lock()->x_);
162  CHECK (1 == pXX.use_count());
163 
164  pXX.reset();
165  CHECK (!pXX);
166  CHECK (!wX.lock());
167  }
168 
169 
170  void
171  check_ownership_transfer ()
172  {
173  std::unique_ptr<X> up (new X(23));
174  CHECK (up.get());
175 
176  P<X> pX (std::move(up));
177  CHECK (!up.get());
178  CHECK (pX);
179  CHECK (1 == pX.use_count());
180  CHECK (23 == pX->x_);
181  }
182 
183 
185  void
187  {
188  P<X> pX; // Base: shared_ptr<X>
189  P<XX> pX1; // Base: shared_ptr<XX>
190  P<XX,P<X>> pX2; // Base: P<X>
191  P<XX,shared_ptr<X>> pX3; // Base: shared_ptr<X>
192  P<XX,shared_ptr<long>> pLo;// Base: shared_ptr<long> (rather nonsense, but well...)
193  P<X,string> pLoL; // Base: std::string
194  P<string> pLoLoL; // Base: shared_ptr<string>
195 
196  CHECK (INSTANCEOF (shared_ptr<X>, &pX));
197 
198  CHECK ( INSTANCEOF (shared_ptr<XX>, &pX1));
199 // CHECK (!INSTANCEOF (shared_ptr<X>, &pX1)); // doesn't compile (no RTTI) -- that's correct
200 // CHECK (!INSTANCEOF (P<X>, &pX1)); // similar, type mismatch detected by compiler
201 
202  CHECK ( INSTANCEOF (shared_ptr<X>, &pX2));
203 // CHECK (!INSTANCEOF (shared_ptr<XX>, &pX2));
204  CHECK ( INSTANCEOF (P<X>, &pX2));
205 
206  CHECK ( INSTANCEOF (shared_ptr<X>, &pX3));
207 // CHECK (!INSTANCEOF (shared_ptr<XX>, &pX3));
208 // CHECK (!INSTANCEOF (P<X>, &pX3));
209 
210  CHECK ( INSTANCEOF (shared_ptr<long>, &pLo));
211 // CHECK (!INSTANCEOF (shared_ptr<X>, &pLo));
212 // CHECK (!INSTANCEOF (P<X>, &pLo));
213 
214 // CHECK (!INSTANCEOF (shared_ptr<long>, &pLoL));
215 // CHECK (!INSTANCEOF (shared_ptr<X>, &pLoL));
216 // CHECK (!INSTANCEOF (P<X>, &pLoL));
217  CHECK ( INSTANCEOF (string, &pLoL));
218 
219  CHECK ( INSTANCEOF (shared_ptr<string>, &pLoLoL));
220 // CHECK (!INSTANCEOF (string, &pLoLoL));
221 // CHECK (!INSTANCEOF (shared_ptr<X>, &pLoLoL));
222 
223  pX = pX1; // OK: pointee subtype...
224  pX = pX2; // invokes shared_ptr<X>::operator= (shared_ptr<X> const&)
225  pX = pX3;
226 // pX = pLo; // similar, but long* not assignable to X*
227 // pX = pLoL; // similar, but string* not assignable to X*
228 // pX = pLoLoL; // same...
229  // you won't be able to do much with the "LoLo"-Types,
230  // as their types and pointee types's relations don't match
231 
232  pX.reset (new XX(5));
233  CHECK (5 == *pX); // implicit conversion from X to long
234 
235  pX2 = pX; // works, because both are implemented in terms of shared_ptr<X>
236  CHECK (5 == pX2->x_);
237  CHECK (6 == pX2->xx_); // using the XX interface (performing dynamic downcast)
238 
239  pX3.reset (new X(7)); // again works because implemented in terms of shared_ptr<X>
240  pX2 = pX3; // same
241  CHECK (pX2); // both contain indeed a valid pointer....
242  CHECK (pX3);
243  CHECK (! pX2.get()); // but dynamic cast to XX at access fails
244  CHECK (! pX3.get());
245  }
246 
247 
249  void
251  {
252  typedef P<X> PX;
253  typedef P<XX,PX> PXX;
254 
255  PX pX1 (new X(3));
256  PX pX2 (new XX(5));
257  PX pX3, pX4, pX5, pX6;
258  PXX pXX (new XX(7));
259 
260  pX3 = pXX;
261  pX4.reset(new X(*pXX));
262 
263  CHECK ( (pX1 == pX1)); // reflexivity
264  CHECK (!(pX1 != pX1));
265  CHECK (!(pX1 < pX1));
266  CHECK (!(pX1 > pX1));
267  CHECK ( (pX1 <= pX1));
268  CHECK ( (pX1 >= pX1));
269 
270  CHECK (!(pX1 == pX2)); // compare to same ptr type with larger pointee of subtype
271  CHECK ( (pX1 != pX2));
272  CHECK ( (pX1 < pX2));
273  CHECK (!(pX1 > pX2));
274  CHECK ( (pX1 <= pX2));
275  CHECK (!(pX1 >= pX2));
276 
277  CHECK (!(pX2 == pXX)); // compare to ptr subtype with larger pointee of same subtype
278  CHECK ( (pX2 != pXX));
279  CHECK ( (pX2 < pXX));
280  CHECK (!(pX2 > pXX));
281  CHECK ( (pX2 <= pXX));
282  CHECK (!(pX2 >= pXX));
283 
284  CHECK (!(pX1 == pXX)); // transitively compare to ptr subtype with larger pointee of subtype
285  CHECK ( (pX1 != pXX));
286  CHECK ( (pX1 < pXX));
287  CHECK (!(pX1 > pXX));
288  CHECK ( (pX1 <= pXX));
289  CHECK (!(pX1 >= pXX));
290 
291  CHECK ( (pX3 == pXX)); // compare ptr to subtype ptr both referring to same pointee
292  CHECK (!(pX3 != pXX));
293  CHECK (!(pX3 < pXX));
294  CHECK (!(pX3 > pXX));
295  CHECK ( (pX3 <= pXX));
296  CHECK ( (pX3 >= pXX));
297 
298  CHECK ( (pX4 == pXX)); // compare ptr to subtype ptr both referring to different but equal pointees
299  CHECK (!(pX4 != pXX));
300  CHECK (!(pX4 < pXX));
301  CHECK (!(pX4 > pXX));
302  CHECK ( (pX4 <= pXX));
303  CHECK ( (pX4 >= pXX));
304 
305  CHECK (!(pXX == pX5)); // compare subtype ptr to empty ptr: "unequal but not orderable"
306  CHECK ( (pXX != pX5));
307 
308  CHECK ( (pX5 == pX6)); // compare two empty ptrs: "equal, equivalent but not orderable"
309  CHECK (!(pX5 != pX6));
310 
311  // order relations on NIL pointers disallowed
312 
313 #if false
314  VERIFY_ERROR (ASSERTION, pXX < pX5 );
315  VERIFY_ERROR (ASSERTION, pXX > pX5 );
316  VERIFY_ERROR (ASSERTION, pXX <= pX5 );
317  VERIFY_ERROR (ASSERTION, pXX >= pX5 );
318 
319  VERIFY_ERROR (ASSERTION, pX5 < pXX );
320  VERIFY_ERROR (ASSERTION, pX5 > pXX );
321  VERIFY_ERROR (ASSERTION, pX5 <= pXX );
322  VERIFY_ERROR (ASSERTION, pX5 >= pXX );
323 
324  VERIFY_ERROR (ASSERTION, pX5 < pX6 );
325  VERIFY_ERROR (ASSERTION, pX5 > pX6 );
326  VERIFY_ERROR (ASSERTION, pX5 <= pX6 );
327  VERIFY_ERROR (ASSERTION, pX5 >= pX6 );
328 #endif
329  }
330  };
331 
332 
334  LAUNCHER (CustomSharedPtr_test, "unit common");
335 
336 
337 
338 }} // namespace lib::test
Definition: run.hpp:49
#define INSTANCEOF(CLASS, EXPR)
shortcut for subclass test, intended for assertions only.
Definition: util.hpp:492
#define VERIFY_ERROR(ERROR_ID, ERRONEOUS_STATEMENT)
Macro to verify that a statement indeed raises an exception.
Customised refcounting smart pointer.
Implementation namespace for support and library code.
Simple test class runner.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
A collection of frequently used helper functions to support unit testing.
Customised refcounting smart pointer template, built upon std::shared_ptr, but forwarding type relati...
Definition: trait.hpp:80