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)
5  2008, 2010, Hermann Vosseler <Ichthyostega@web.de>
6 
7   **Lumiera** is free software; you can redistribute it and/or modify it
8   under the terms of the GNU General Public License as published by the
9   Free Software Foundation; either version 2 of the License, or (at your
10   option) any later version. See the file COPYING for further details.
11 
12 * *****************************************************************/
13 
19 #include "lib/test/run.hpp"
20 #include "lib/test/test-helper.hpp"
21 #include "lib/util.hpp"
22 
23 #include "lib/p.hpp"
24 
25 #include <boost/operators.hpp>
26 
27 
28 
29 namespace lib {
30 namespace test{
31 
32  using std::string;
33  using std::shared_ptr;
34  using std::weak_ptr;
35 
36  using lumiera::error::LUMIERA_ERROR_ASSERTION;
37 
38 
39  struct X
40  : boost::totally_ordered<X>
41  {
42  long x_;
43 
44  X(long x=0) : x_(x) {}
45  operator long () { return x_; }
46 
47  bool operator< (const X& ox) const { return x_ < ox.x_; }
48  bool operator== (const X& ox) const { return x_ == ox.x_; }
49 
50  virtual ~X() {} // using RTTI
51  };
52 
53  struct XX : public X
54  {
55  long xx_;
56 
57  XX(long x=0) : X(x), xx_(x+1) {}
58  };
59 
60 
61  /************************************************************/
67  class CustomSharedPtr_test : public Test
68  {
69  virtual void
70  run (Arg)
71  {
72  check_refcounting ();
73  check_shared_ownership ();
74  check_ownership_transfer ();
75  check_type_relations ();
76  check_ordering ();
77  }
78 
79 
81  void
83  {
84  P<X> p1 (new X(7));
85  CHECK (p1);
86  CHECK (1 == p1.use_count());
87  CHECK (7 == p1->x_);
88 
89  {
90  P<X> p2 (new X(9));
91  CHECK (1 == p2.use_count());
92 
93  p2.swap (p1);
94  CHECK (1 == p1.use_count());
95  CHECK (1 == p2.use_count());
96 
97  p2 = p1;
98  CHECK (2 == p1.use_count());
99  CHECK (2 == p2.use_count());
100  }
101 
102  CHECK (1 == p1.use_count());
103  CHECK (9 == p1->x_);
104 
105  p1.reset();
106  CHECK (0 == p1.use_count());
107  CHECK (!p1);
108  }
109 
110 
112  void
114  {
115  P<X> pX (new X(22));
116  CHECK (pX);
117  CHECK (1 == pX.use_count());
118 
119  weak_ptr<X> wX (pX);
120  CHECK (wX.lock());
121  CHECK (1 == pX.use_count());
122 
123  shared_ptr<X> sp1 (wX);
124  shared_ptr<X> sp2 (pX);
125  shared_ptr<X> sp3; sp3 = pX;
126 
127  CHECK (22 == sp3->x_);
128  CHECK (4 == pX.use_count());
129  CHECK (*pX == *sp1);
130  CHECK (*sp1 == *sp2);
131  CHECK (*sp2 == *sp3);
132 
133  P<X> pX2;
134  pX2.swap(pX);
135  CHECK (!pX);
136  CHECK (0 == pX.use_count());
137  CHECK (4 == pX2.use_count());
138 
139  P<X, P<X>> pXX (pX2); // a different type, but compatible pointers
140  pX2 = pX;
141  CHECK (!pX2);
142  CHECK (0 == pX2.use_count());
143  CHECK (4 == pXX.use_count());
144 
145  sp3 = sp2 = sp1 = pX;
146  CHECK (22 == pXX->x_);
147  CHECK (1 == pXX.use_count());
148  CHECK (!sp1);
149  CHECK (!sp2);
150  CHECK (!sp3);
151 
152  CHECK (22 == wX.lock()->x_);
153  CHECK (1 == pXX.use_count());
154 
155  pXX.reset();
156  CHECK (!pXX);
157  CHECK (!wX.lock());
158  }
159 
160 
161  void
162  check_ownership_transfer ()
163  {
164  std::unique_ptr<X> up (new X(23));
165  CHECK (up.get());
166 
167  P<X> pX (std::move(up));
168  CHECK (!up.get());
169  CHECK (pX);
170  CHECK (1 == pX.use_count());
171  CHECK (23 == pX->x_);
172  }
173 
174 
176  void
178  {
179  P<X> pX; // Base: shared_ptr<X>
180  P<XX> pX1; // Base: shared_ptr<XX>
181  P<XX,P<X>> pX2; // Base: P<X>
182  P<XX,shared_ptr<X>> pX3; // Base: shared_ptr<X>
183  P<XX,shared_ptr<long>> pLo;// Base: shared_ptr<long> (rather nonsense, but well...)
184  P<X,string> pLoL; // Base: std::string
185  P<string> pLoLoL; // Base: shared_ptr<string>
186 
187  CHECK (INSTANCEOF (shared_ptr<X>, &pX));
188 
189  CHECK ( INSTANCEOF (shared_ptr<XX>, &pX1));
190 // CHECK (!INSTANCEOF (shared_ptr<X>, &pX1)); // doesn't compile (no RTTI) -- that's correct
191 // CHECK (!INSTANCEOF (P<X>, &pX1)); // similar, type mismatch detected by compiler
192 
193  CHECK ( INSTANCEOF (shared_ptr<X>, &pX2));
194 // CHECK (!INSTANCEOF (shared_ptr<XX>, &pX2));
195  CHECK ( INSTANCEOF (P<X>, &pX2));
196 
197  CHECK ( INSTANCEOF (shared_ptr<X>, &pX3));
198 // CHECK (!INSTANCEOF (shared_ptr<XX>, &pX3));
199 // CHECK (!INSTANCEOF (P<X>, &pX3));
200 
201  CHECK ( INSTANCEOF (shared_ptr<long>, &pLo));
202 // CHECK (!INSTANCEOF (shared_ptr<X>, &pLo));
203 // CHECK (!INSTANCEOF (P<X>, &pLo));
204 
205 // CHECK (!INSTANCEOF (shared_ptr<long>, &pLoL));
206 // CHECK (!INSTANCEOF (shared_ptr<X>, &pLoL));
207 // CHECK (!INSTANCEOF (P<X>, &pLoL));
208  CHECK ( INSTANCEOF (string, &pLoL));
209 
210  CHECK ( INSTANCEOF (shared_ptr<string>, &pLoLoL));
211 // CHECK (!INSTANCEOF (string, &pLoLoL));
212 // CHECK (!INSTANCEOF (shared_ptr<X>, &pLoLoL));
213 
214  pX = pX1; // OK: pointee subtype...
215  pX = pX2; // invokes shared_ptr<X>::operator= (shared_ptr<X> const&)
216  pX = pX3;
217 // pX = pLo; // similar, but long* not assignable to X*
218 // pX = pLoL; // similar, but string* not assignable to X*
219 // pX = pLoLoL; // same...
220  // you won't be able to do much with the "LoLo"-Types,
221  // as their types and pointee types's relations don't match
222 
223  pX.reset (new XX(5));
224  CHECK (5 == *pX); // implicit conversion from X to long
225 
226  pX2 = pX; // works, because both are implemented in terms of shared_ptr<X>
227  CHECK (5 == pX2->x_);
228  CHECK (6 == pX2->xx_); // using the XX interface (performing dynamic downcast)
229 
230  pX3.reset (new X(7)); // again works because implemented in terms of shared_ptr<X>
231  pX2 = pX3; // same
232  CHECK (pX2); // both contain indeed a valid pointer....
233  CHECK (pX3);
234  CHECK (! pX2.get()); // but dynamic cast to XX at access fails
235  CHECK (! pX3.get());
236  }
237 
238 
240  void
242  {
243  typedef P<X> PX;
244  typedef P<XX,PX> PXX;
245 
246  PX pX1 (new X(3));
247  PX pX2 (new XX(5));
248  PX pX3, pX4, pX5, pX6;
249  PXX pXX (new XX(7));
250 
251  pX3 = pXX;
252  pX4.reset(new X(*pXX));
253 
254  CHECK ( (pX1 == pX1)); // reflexivity
255  CHECK (!(pX1 != pX1));
256  CHECK (!(pX1 < pX1));
257  CHECK (!(pX1 > pX1));
258  CHECK ( (pX1 <= pX1));
259  CHECK ( (pX1 >= pX1));
260 
261  CHECK (!(pX1 == pX2)); // compare to same ptr type with larger pointee of subtype
262  CHECK ( (pX1 != pX2));
263  CHECK ( (pX1 < pX2));
264  CHECK (!(pX1 > pX2));
265  CHECK ( (pX1 <= pX2));
266  CHECK (!(pX1 >= pX2));
267 
268  CHECK (!(pX2 == pXX)); // compare to ptr subtype with larger pointee of same subtype
269  CHECK ( (pX2 != pXX));
270  CHECK ( (pX2 < pXX));
271  CHECK (!(pX2 > pXX));
272  CHECK ( (pX2 <= pXX));
273  CHECK (!(pX2 >= pXX));
274 
275  CHECK (!(pX1 == pXX)); // transitively compare to ptr subtype with larger pointee of subtype
276  CHECK ( (pX1 != pXX));
277  CHECK ( (pX1 < pXX));
278  CHECK (!(pX1 > pXX));
279  CHECK ( (pX1 <= pXX));
280  CHECK (!(pX1 >= pXX));
281 
282  CHECK ( (pX3 == pXX)); // compare ptr to subtype ptr both referring to same pointee
283  CHECK (!(pX3 != pXX));
284  CHECK (!(pX3 < pXX));
285  CHECK (!(pX3 > pXX));
286  CHECK ( (pX3 <= pXX));
287  CHECK ( (pX3 >= pXX));
288 
289  CHECK ( (pX4 == pXX)); // compare ptr to subtype ptr both referring to different but equal pointees
290  CHECK (!(pX4 != pXX));
291  CHECK (!(pX4 < pXX));
292  CHECK (!(pX4 > pXX));
293  CHECK ( (pX4 <= pXX));
294  CHECK ( (pX4 >= pXX));
295 
296  CHECK (!(pXX == pX5)); // compare subtype ptr to empty ptr: "unequal but not orderable"
297  CHECK ( (pXX != pX5));
298 
299  CHECK ( (pX5 == pX6)); // compare two empty ptrs: "equal, equivalent but not orderable"
300  CHECK (!(pX5 != pX6));
301 
302  // order relations on NIL pointers disallowed
303 
304 #if false
305  VERIFY_ERROR (ASSERTION, pXX < pX5 );
306  VERIFY_ERROR (ASSERTION, pXX > pX5 );
307  VERIFY_ERROR (ASSERTION, pXX <= pX5 );
308  VERIFY_ERROR (ASSERTION, pXX >= pX5 );
309 
310  VERIFY_ERROR (ASSERTION, pX5 < pXX );
311  VERIFY_ERROR (ASSERTION, pX5 > pXX );
312  VERIFY_ERROR (ASSERTION, pX5 <= pXX );
313  VERIFY_ERROR (ASSERTION, pX5 >= pXX );
314 
315  VERIFY_ERROR (ASSERTION, pX5 < pX6 );
316  VERIFY_ERROR (ASSERTION, pX5 > pX6 );
317  VERIFY_ERROR (ASSERTION, pX5 <= pX6 );
318  VERIFY_ERROR (ASSERTION, pX5 >= pX6 );
319 #endif
320  }
321  };
322 
323 
325  LAUNCHER (CustomSharedPtr_test, "unit common");
326 
327 
328 
329 }} // namespace lib::test
Definition: run.hpp:40
#define INSTANCEOF(CLASS, EXPR)
shortcut for subclass test, intended for assertions only.
Definition: util.hpp:514
#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.
Simplistic 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:71