Lumiera  0.pre.03
»edit your freedom«
scoped-holder-test.cpp
Go to the documentation of this file.
1 /*
2  ScopedHolder(Test) - holding and owning noncopyable objects
3 
4  Copyright (C)
5  2008, 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 
20 #include "lib/test/run.hpp"
21 #include "lib/test/test-helper.hpp"
22 #include "lib/format-cout.hpp"
23 #include "lib/util.hpp"
24 #include "lib/error.hpp"
25 
26 #include "lib/scoped-holder.hpp"
28 
29 #include <map>
30 
31 
32 namespace lib {
33 namespace test{
34 
35  using ::Test;
36  using util::isnil;
37  using lumiera::error::LUMIERA_ERROR_LOGIC;
38 
39  using std::map;
40 
41  typedef ScopedHolder<Dummy> HolderD;
42  typedef ScopedPtrHolder<Dummy> PtrHolderD;
43 
44 
45  /******************************************************************************/
53  class ScopedHolder_test : public Test
54  {
55 
56  virtual void
57  run (Arg)
58  {
59 
60  cout << "checking ScopedHolder<Dummy>...\n";
61  checkAllocation<HolderD>();
62  checkErrorHandling<HolderD>();
63  checkCopyProtocol<HolderD>();
64  checkSTLContainer<HolderD>();
65 
66  cout << "checking ScopedPtrHolder<Dummy>...\n";
67  checkAllocation<PtrHolderD>();
68  checkErrorHandling<PtrHolderD>();
69  checkCopyProtocol<PtrHolderD>();
70  checkSTLContainer<PtrHolderD>();
71  }
72 
73  void create_contained_object (HolderD& holder) { holder.create(); }
74  void create_contained_object (PtrHolderD& holder) { holder.reset(new Dummy()); }
75 
76 
77  template<class HO>
78  void
79  checkAllocation()
80  {
81  CHECK (0 == Dummy::checksum());
82  {
83  HO holder;
84  CHECK (!holder);
85  CHECK (0 == Dummy::checksum());
86 
87  create_contained_object (holder);
88  CHECK (holder);
89  CHECK (false != bool(holder));
90  CHECK (bool(holder) != false);
91 
92  CHECK (0 < Dummy::checksum());
93  CHECK ( &(*holder));
94  CHECK (holder->calc(2) == 2 + Dummy::checksum());
95 
96  Dummy *rawP = holder.get();
97  CHECK (rawP);
98  CHECK (holder);
99  CHECK (rawP == &(*holder));
100  CHECK (rawP->calc(-5) == holder->calc(-5));
101 
102  TRACE (test, "holder at %p", &holder);
103  TRACE (test, "object at %p", holder.get() );
104  TRACE (test, "size(object) = %zu", sizeof(*holder));
105  TRACE (test, "size(holder) = %zu", sizeof(holder));
106  }
107  CHECK (0 == Dummy::checksum());
108  }
109 
110 
111  template<class HO>
112  void
113  checkErrorHandling()
114  {
115  CHECK (0 == Dummy::checksum());
116  {
117  HO holder;
118 
119  Dummy::activateCtorFailure();
120  try
121  {
122  create_contained_object (holder);
123  NOTREACHED ("expect failure in ctor");
124  }
125  catch (int val)
126  {
127  CHECK (0 != Dummy::checksum());
128  Dummy::checksum() -= val;
129  CHECK (0 == Dummy::checksum());
130  }
131  CHECK (!holder); /* because the exception happens in ctor
132  object doesn't count as "created" */
133  Dummy::activateCtorFailure(false);
134  }
135  CHECK (0 == Dummy::checksum());
136  }
137 
138 
139  template<class HO>
140  void
141  checkCopyProtocol()
142  {
143  CHECK (0 == Dummy::checksum());
144  {
145  HO holder;
146  HO holder2 (holder);
147  holder2 = holder;
148  // copy and assignment of empty holders is tolerated
149 
150  // but after enclosing an object it will be copy protected...
151  CHECK (!holder);
152  create_contained_object (holder);
153  CHECK (holder);
154  long currSum = Dummy::checksum();
155  void* adr = holder.get();
156 
157  VERIFY_ERROR(LOGIC, holder2 = holder );
158  CHECK (holder);
159  CHECK (!holder2);
160  CHECK (holder.get()==adr);
161  CHECK (Dummy::checksum()==currSum);
162 
163  VERIFY_ERROR(LOGIC, holder = holder2 );
164  CHECK (holder);
165  CHECK (!holder2);
166  CHECK (holder.get()==adr);
167  CHECK (Dummy::checksum()==currSum);
168 
169  create_contained_object (holder2);
170  CHECK (holder2);
171  CHECK (Dummy::checksum() != currSum);
172  currSum = Dummy::checksum();
173 
174  VERIFY_ERROR(LOGIC, holder = holder2 );
175  CHECK (holder);
176  CHECK (holder2);
177  CHECK (holder.get()==adr);
178  CHECK (Dummy::checksum()==currSum);
179 
180  VERIFY_ERROR(LOGIC, HO holder3 (holder2) );
181  CHECK (holder);
182  CHECK (holder2);
183  CHECK (Dummy::checksum()==currSum);
184  }
185  CHECK (0 == Dummy::checksum());
186  }
187 
188 
192  template<class HO>
193  void
195  {
196  typedef std::map<int,HO> MapHO;
197 
198  CHECK (0 == Dummy::checksum());
199  {
200  MapHO maph;
201  CHECK (isnil (maph));
202 
203  for (uint i=0; i<100; ++i)
204  {
205  HO & contained = maph[i];
206  CHECK (!contained);
207  } // 100 holder objects created by sideeffect
208  // ..... without creating any contained object!
209  CHECK (0 == Dummy::checksum());
210  CHECK (!isnil (maph));
211  CHECK (100==maph.size());
212 
213  for (uint i=0; i<100; ++i)
214  {
215  create_contained_object (maph[i]);
216  CHECK (maph[i]);
217  CHECK (0 < maph[i]->calc(12));
218  }
219  CHECK (100==maph.size());
220  CHECK (0 != Dummy::checksum());
221 
222 
223  long value55 = maph[55]->calc(0);
224  long currSum = Dummy::checksum();
225 
226  CHECK (1 == maph.erase(55));
227  CHECK (Dummy::checksum() == currSum - value55); // proves object#55's dtor has been invoked
228  CHECK (maph.size() == 99);
229 
230  maph[55]; // create new empty holder by sideeffect...
231  CHECK (&maph[55]);
232  CHECK (!maph[55]);
233  CHECK (maph.size() == 100);
234  }
235  CHECK (0 == Dummy::checksum());
236  }
237 
238 
239  };
240 
241  LAUNCHER (ScopedHolder_test, "unit common");
242 
243 
244 }} // namespace lib::test
Some wrappers for coping with ownership problems.
Automatically use custom string conversion in C++ stream output.
Definition: run.hpp:40
#define VERIFY_ERROR(ERROR_ID, ERRONEOUS_STATEMENT)
Macro to verify that a statement indeed raises an exception.
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...
unittest helper code: test dummy objects to track instances.
A collection of frequently used helper functions to support unit testing.
A Dummy object for tests.
Lumiera error handling (C++ interface).