Lumiera  0.pre.03
»edit your freedom«
item-wrapper-test.cpp
Go to the documentation of this file.
1 /*
2  ItemWrapper(Test) - wrapping and holding arbitrary values, pointers and references
3 
4  Copyright (C)
5  2009, 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/random.hpp"
24 #include "lib/util.hpp"
25 
26 #include "lib/wrapper.hpp"
27 
28 #include <functional>
29 #include <iostream>
30 #include <memory>
31 #include <string>
32 #include <vector>
33 
34 
35 
36 namespace lib {
37 namespace wrapper {
38 namespace test{
39 
40  using ::Test;
41  using lib::test::randStr;
42  using lib::test::showSizeof;
43  using util::isSameObject;
44 
45  using std::placeholders::_1;
46  using std::ref;
47  using std::shared_ptr;
48  using std::vector;
49  using std::string;
50 
51 
52 
53  namespace { // Test helper: yet another ctor/dtor counting class
54 
55  long cntTracker = 0;
56 
57  struct Tracker
58  {
59  uint i_;
60 
61  Tracker() : i_(rani(500)) { ++cntTracker; }
62  Tracker(Tracker const& ot) : i_(ot.i_) { ++cntTracker; }
63  ~Tracker() { --cntTracker; }
64  };
65 
66  bool operator== (Tracker const& t1, Tracker const& t2) { return t1.i_ == t2.i_; }
67  bool operator!= (Tracker const& t1, Tracker const& t2) { return t1.i_ != t2.i_; }
68 
69 
71  int&
72  pickElement (vector<int>& vec, size_t idx)
73  {
74  return vec[idx];
75  }
76 
77  function<int&(size_t)>
78  pickElement_ofVector (vector<int>& vec)
79  {
80  return std::bind (pickElement, ref(vec), _1 );
81  }
82  } // (END) Test helpers
83 
84 
85 
86 
87 
88 
89 
90  /***************************************************************************/
97  class ItemWrapper_test : public Test
98  {
99 
100 
101  virtual void
102  run (Arg)
103  {
104  seedRand();
105 
106  ulong l1 (rani (1000));
107  ulong l2 (rani (1000));
108  string s1 (randStr(50));
109  string s2 (randStr(50));
110  const char* cp (s1.c_str());
111 
112  verifyWrapper<ulong> (l1, l2);
113  verifyWrapper<ulong&> (l1, l2);
114  verifyWrapper<ulong*> (&l1, &l2);
115  verifyWrapper<ulong*> ((0), &l2);
116  verifyWrapper<ulong*> (&l1, (0));
117  verifyWrapper<ulong const&> (l1, l2);
118 
119  verifyWrapper<string> (s1, s2);
120  verifyWrapper<string&> (s1, s2);
121  verifyWrapper<string*> (&s1, &s2);
122 
123  verifyWrapper<const char*> (cp, "Lumiera");
124 
125 
126  verifySaneInstanceHandling();
127  verifySaneMoveHandling();
128  verifyWrappedRef ();
129 
130  verifyFunctionResult ();
131  verifyFunctionRefResult ();
132  }
133 
134 
135  template<typename X>
136  void
137  verifyWrapper (X val, X otherVal)
138  {
139  const ItemWrapper<X> wrap(val);
140  CHECK (wrap);
141 
142  cout << "ItemWrapper: " << showSizeof(wrap) << endl;
143 
144  ItemWrapper<X> copy1 (wrap);
145  ItemWrapper<X> copy2;
146  ItemWrapper<X> empty;
147 
148  CHECK (copy1);
149  CHECK (!copy2);
150  CHECK (false == bool(empty));
151 
152  CHECK (wrap == copy1);
153  CHECK (wrap != copy2);
154  CHECK (wrap != empty);
155 
156  copy2 = copy1;
157  CHECK (copy2);
158  CHECK (wrap == copy2);
159  CHECK (wrap != empty);
160 
161  copy2 = otherVal;
162  CHECK (copy2);
163  CHECK (wrap != copy2);
164  CHECK (wrap != empty);
165 
166  CHECK (val == *wrap);
167  CHECK (val == *copy1);
168  CHECK (val != *copy2);
169  VERIFY_ERROR (BOTTOM_VALUE, *empty );
170 
171  CHECK (otherVal == *copy2);
172  copy1 = copy2;
173  CHECK (otherVal == *copy1);
174  CHECK (otherVal == *copy2);
175  CHECK (wrap != copy1);
176  CHECK (wrap != copy2);
177 
178  copy1 = empty; // assign empty to discard value
179  copy1 = copy1; // self-assign empty value
180  CHECK (!copy1);
181 
182  copy1 = copy2;
183  CHECK (otherVal == *copy1);
184  copy1 = copy1; // self-assign (will be suppressed)
185  CHECK (otherVal == *copy1);
186  copy1 = *copy1; // self-assign also detected in this case
187  CHECK (otherVal == *copy2);
188 
189  CHECK (copy1);
190  copy1.reset();
191  CHECK (!copy1);
192  CHECK (empty == copy1);
193  CHECK (copy2 != copy1);
194  VERIFY_ERROR (BOTTOM_VALUE, *copy1 );
195  };
196 
197 
201  void
203  {
204  cntTracker = 0;
205  {
206  Tracker t1;
207  Tracker t2;
208 
209  verifyWrapper<Tracker> (t1, t2);
210  verifyWrapper<Tracker&> (t1, t2);
211  verifyWrapper<Tracker*> (&t1, &t2);
212 
213  }
214  CHECK (0 == cntTracker);
215  }
216 
217 
219  void
221  {
222  using Data = shared_ptr<int>;
223  using Wrap = ItemWrapper<Data>;
224 
225  Data data{new int(12345)};
226  CHECK (1 == data.use_count());
227 
228  Wrap wrap{data};
229  CHECK (2 == data.use_count());
230  CHECK (12345 == **wrap);
231  CHECK (isSameObject (*data, **wrap));
232  CHECK (!isSameObject (data, *wrap));
233 
234  Wrap wcopy{wrap};
235  CHECK (3 == data.use_count());
236 
237  Wrap wmove{move (wcopy)};
238  CHECK (3 == data.use_count());
239  CHECK (not wcopy);
240  CHECK (wmove);
241 
242  wcopy = move(wmove);
243  CHECK (3 == data.use_count());
244  CHECK (not wmove);
245  CHECK (wcopy);
246 
247  Wrap wmove2{move (data)};
248  CHECK (0 == data.use_count());
249  CHECK (3 == wmove2->use_count());
250  CHECK (not data);
251  CHECK (wmove2);
252  CHECK (wrap);
253 
254  wmove2 = move (wcopy);
255  CHECK (2 == wmove2->use_count());
256  CHECK (not wcopy);
257  CHECK (wmove2);
258  CHECK (wrap);
259 
260  wmove2 = move (wrap);
261  CHECK (1 == wmove2->use_count());
262  CHECK (not wrap);
263  CHECK (wmove2);
264 
265  wmove2 = move (wmove);
266  CHECK (not wcopy);
267  CHECK (not wmove);
268  CHECK (not wmove2);
269  }
270 
271 
275  void
277  {
278  int x = 5;
279  ItemWrapper<int&> refWrap;
280  CHECK (!refWrap);
281 
282  refWrap = x;
283  CHECK (refWrap);
284  CHECK (5 == *refWrap);
285  CHECK (x == *refWrap);
286 
287  *refWrap += 5;
288  CHECK (x == 10);
289 
290  ItemWrapper<int*> ptrWrap (& *refWrap);
291  CHECK ( isSameObject (**ptrWrap, x));
292  CHECK (!isSameObject ( *ptrWrap, &x));
293  **ptrWrap += 13;
294  CHECK (x == 23);
295  }
296 
297 
298  static auto produceResult() { return rani(); }
299 
305  void
307  {
308  FunctionResult<int(void)> randomVal (produceResult);
309 
310  // function was never invoked, thus the remembered result is NIL
311  CHECK (!randomVal);
312  VERIFY_ERROR (BOTTOM_VALUE, *randomVal );
313 
314  int v1 = randomVal();
315  CHECK (v1 == *randomVal);
316  CHECK (v1 == *randomVal);
317  CHECK (v1 == *randomVal);
318  CHECK (randomVal);
319 
320  int v2;
321  do v2 = randomVal();
322  while (v1 == v2);
323  CHECK (v2 == *randomVal);
324  CHECK (v2 == *randomVal);
325  CHECK (v1 != *randomVal);
326  }
327 
328 
337  void
339  {
340  vector<int> testVec;
341  for (uint i=0; i<10; ++i)
342  testVec.push_back(i);
343 
344  FunctionResult<int&(size_t)> funRes (pickElement_ofVector(testVec));
345 
346  // function was never invoked, thus the remembered result is NIL
347  CHECK (!funRes);
348  VERIFY_ERROR (BOTTOM_VALUE, *funRes );
349 
350  int& r5 = funRes (5);
351  CHECK (funRes); // indicates existence of cached result
352 
353  CHECK (5 == r5);
354  CHECK (isSameObject (r5, testVec[5]));
355 
356  int& r5x = *funRes;
357  CHECK (isSameObject (r5, r5x));
358 
359  CHECK ( isSameObject (r5, *funRes));
360  int& r7 = funRes (7);
361  CHECK (!isSameObject (r5, *funRes));
362  CHECK ( isSameObject (r7, *funRes));
363 
364  -- r5x;
365  ++ *funRes;
366  CHECK (5-1 == testVec[5]);
367  CHECK (7+1 == testVec[7]);
368  CHECK (7+1 == r7);
369  }
370  };
371 
372  LAUNCHER (ItemWrapper_test, "unit common");
373 
374 
375 }}} // namespace lib::wrapper::test
376 
Automatically use custom string conversion in C++ stream output.
Definition: run.hpp:40
int rani(uint bound=_iBOUND())
Definition: random.hpp:135
bool operator==(PtrDerefIter< I1 > const &il, PtrDerefIter< I2 > const &ir)
Supporting equality comparisons...
#define VERIFY_ERROR(ERROR_ID, ERRONEOUS_STATEMENT)
Macro to verify that a statement indeed raises an exception.
Universal value/ref wrapper accessible similar to a pointer.
Definition: wrapper.hpp:102
Implementation namespace for support and library code.
string randStr(size_t len)
create garbage string of given length
Definition: test-helper.cpp:61
Simplistic test class runner.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
Extension of ItemWrapper: a function remembering the result of the last invocation.
Definition: wrapper.hpp:401
int & pickElement(vector< int > &vec, size_t idx)
to be bound as test function....
A collection of frequently used helper functions to support unit testing.
Generating (pseudo) random numbers with controlled seed.
Library implementation: smart-pointer variations, wrappers and managing holders.
bool isSameObject(A const &a, B const &b)
compare plain object identity, based directly on the referee&#39;s memory identities. ...
Definition: util.hpp:421