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