Lumiera  0.pre.03
»edityourfreedom«
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
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:421
#define VERIFY_ERROR(ERROR_ID, ERRONEOUS_STATEMENT)
Macro to verify a statement indeed raises an exception.
Customised refcounting smart pointer.
Implementation namespace for support and library code.
std::vector< string > & Arg
Definition: run.hpp:54
Simple test class runner.
bool operator<(const X &ox) const
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.
LAUNCHER(SyncClasslock_test, "unit common")
Register this test class...
bool operator==(const X &ox) const
void swap(P &b)
Definition: p.hpp:100
Customised refcounting smart pointer template, built upon std::shared_ptr, but forwarding type relati...
Definition: trait.hpp:76
TAR * get() const
Definition: p.hpp:96