Lumiera 0.pre.04~rc.1
»edit your freedom«
Loading...
Searching...
No Matches
opaque-holder-test.cpp
Go to the documentation of this file.
1/*
2 OpaqueHolder(Test) - check the inline type erasure helper
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"
22#include "lib/util.hpp"
23#include "lib/util-foreach.hpp"
24#include "lib/opaque-holder.hpp"
25
26#include <iostream>
27#include <vector>
28
29
30namespace lib {
31namespace test{
32
33 using ::Test;
34 using util::isnil;
35 using util::for_each;
37 using LERR_(BOTTOM_VALUE);
38 using LERR_(WRONG_TYPE);
39 using LERR_(ASSERTION);
40
41 using std::vector;
42 using std::cout;
43 using std::endl;
44
45 namespace { // test dummy hierarchy
46 // Note: common storage but no vtable
47
48 long _checksum = 0;
50
51
52 struct Base
53 {
55
56 Base(uint i=0) : id_(i) { _checksum +=id_; ++_create_count; }
57 Base(Base const& o) : id_(o.id_) { _checksum +=id_; ++_create_count; }
58
59 uint getIt() { return id_; }
60 };
61
62
63 template<uint ii>
64 struct DD : Base
65 {
66 DD() : Base(ii) { }
67 ~DD() { _checksum -= ii; } // doing the decrement here
68 }; // verifies the correct dtor is called
69
70
71 struct Special
72 : DD<7>
73 {
75
77 : myVal_(val)
78 { }
79
80 explicit
81 operator bool() const
82 {
83 return myVal_ % 2;
84 }
85 };
86
87
92 const size_t _ALIGN_ = sizeof(size_t);
93
94 }
95
97 typedef vector<Opaque> TestList;
98
99
100
101 /******************************************************************************/
111 class OpaqueHolder_test : public Test
112 {
113
114 virtual void
115 run (Arg)
116 {
117 _checksum = 0;
118 _create_count = 0;
119 {
120 TestList objs = createDummies ();
121 for_each (objs, reAccess);
122 checkHandling (objs);
124 }
125 CHECK (0 == _checksum); // all dead
126 }
127
128
131 {
132 TestList list;
133 list.push_back (DD<1>());
134 list.push_back (DD<3>());
135 list.push_back (DD<5>());
136 list.push_back (DD<7>());
137 return list;
138 } //note: copy
139
140
141 static void
143 {
144 cout << elm->getIt() << endl;
145 }
146
147
151 void
153 {
154 Opaque oo;
155 CHECK (!oo);
156 CHECK (isnil(oo));
157
158 oo = objs[1];
159 CHECK (oo);
160 CHECK (!isnil(oo));
161
162 typedef DD<3> D3;
163 typedef DD<5> D5;
164 D3 d3 (oo.get<D3>() );
165 CHECK (3 == oo->getIt()); // re-access through Base interface
166 CHECK (!isSameObject (d3, *oo));
167 VERIFY_ERROR (WRONG_TYPE, oo.get<D5>() );
168
169 // direct assignment of target into Buffer
170 oo = D5();
171 CHECK (oo);
172 CHECK (5 == oo->getIt());
173 VERIFY_ERROR (WRONG_TYPE, oo.get<D3>() );
174
175 // can get a direct reference to contained object
176 D5 &rd5 (oo.get<D5>());
177 CHECK (isSameObject (rd5, *oo));
178
179 CHECK (!isnil(oo));
180 oo = objs[3]; // copy construction also works on non-empty object
181 CHECK (7 == oo->getIt());
182
183 // WARNING: direct ref has been messed up through the backdoor!
184 CHECK (7 == rd5.getIt());
185 CHECK (isSameObject (rd5, *oo));
186
187 uint cnt_before = _create_count;
188
189 oo.clear();
190 CHECK (!oo);
191 oo = D5(); // direct assignment also works on empty object
192 CHECK (oo);
193 CHECK (5 == oo->getIt());
194 CHECK (_create_count == 2 + cnt_before);
195 // one within buff and one for the anonymous temporary D5()
196
197
198 // verify that self-assignment is properly detected...
199 cnt_before = _create_count;
200 oo = oo;
201 CHECK (oo);
202 CHECK (_create_count == cnt_before);
203 oo = oo.get<D5>();
204 CHECK (_create_count == cnt_before);
205 oo = *oo;
206 CHECK (_create_count == cnt_before);
207 CHECK (oo);
208
209 oo.clear();
210 CHECK (!oo);
211 CHECK (isnil(oo));
212 VERIFY_ERROR (BOTTOM_VALUE, oo.get<D5>() );
213#if false
214 VERIFY_ERROR (ASSERTION, oo->getIt() );
215#endif
216 // can't access empty holder...
217
218 Opaque o1 (oo);
219 CHECK (!o1);
220
221 Opaque o2 (d3);
222 CHECK (!isSameObject (d3, *o2));
223 CHECK (3 == o2->getIt());
224
225 CHECK (sizeof(Opaque) <= sizeof(Base) + sizeof(void*) + _ALIGN_);
226 }
227
228
240 void
242 {
243 typedef OpaqueHolder<Base, sizeof(Special)> SpecialOpaque;
244
245 cout << showSizeof<Base>() << endl;
246 cout << showSizeof<Special>() << endl;
247 cout << showSizeof<Opaque>() << endl;
248 cout << showSizeof<SpecialOpaque>() << endl;
249
250 CHECK (sizeof(Special) > sizeof(Base));
251 CHECK (sizeof(SpecialOpaque) > sizeof(Opaque));
252 CHECK (sizeof(SpecialOpaque) <= sizeof(Special) + sizeof(void*) + _ALIGN_);
253
254 Special s1 (6);
255 Special s2 (3);
256 CHECK (!s1); // even value
257 CHECK (s2); // odd value
258 CHECK (7 == s1.getIt()); // indeed subclass of DD<7>
259 CHECK (7 == s2.getIt());
260
261 SpecialOpaque ospe0;
262 SpecialOpaque ospe1 (s1);
263 SpecialOpaque ospe2 (s2);
264
265 CHECK (!ospe0); // note: bool test (isValid)
266 CHECK (!ospe1); // also forwarded to contained object (myVal_==6 is even)
267 CHECK ( ospe2);
268 CHECK ( isnil(ospe0)); // while isnil just checks the empty state
269 CHECK (!isnil(ospe1));
270 CHECK (!isnil(ospe2));
271
272 CHECK (7 == ospe1->getIt());
273 CHECK (6 == ospe1.get<Special>().myVal_);
274 CHECK (3 == ospe2.get<Special>().myVal_);
275
276 ospe1 = DD<5>(); // but can be reassigned like any normal Opaque
277 CHECK (ospe1);
278 CHECK (5 == ospe1->getIt());
279 VERIFY_ERROR (WRONG_TYPE, ospe1.get<Special>() );
280
281 Opaque normal = DD<5>();
282 CHECK (normal);
283 CHECK (5 == normal->getIt());
284#if false
285 // Assertion protects against SEGV
286 VERIFY_ERROR (ASSERTION, normal = s1 );
287#endif
288 }
289 };
290
291
292 LAUNCHER (OpaqueHolder_test, "unit common");
293
294
295}} // namespace lib::test
296
Inline buffer to hold and own an object while concealing the concrete type.
static void reAccess(Opaque &elm)
#define LERR_(_NAME_)
Definition error.hpp:45
unsigned int uint
Definition integral.hpp:29
unsigned long int ulong
Definition integral.hpp:31
const size_t _ALIGN_
maximum additional storage maybe wasted due to alignment of the contained object within OpaqueHolder'...
vector< Opaque > TestList
OpaqueHolder< Base > Opaque
Implementation namespace for support and library code.
Test runner and basic definitions for tests.
bool isSameObject(A const &a, B const &b)
compare plain object identity, based directly on the referee's memory identities.
Definition util.hpp:421
disable_if< can_IterForEach< Container >, FUN > for_each(Container const &coll, FUN doIt)
operate on all elements of a STL container.
bool isnil(lib::time::Duration const &dur)
Helper allowing type erasure while holding the actual object inline.
Simplistic test class runner.
#define LAUNCHER(_TEST_CLASS_, _GROUPS_)
Definition run.hpp:116
A collection of frequently used helper functions to support unit testing.
#define VERIFY_ERROR(ERROR_ID, ERRONEOUS_STATEMENT)
Macro to verify that a statement indeed raises an exception.
Perform operations "for each element" of a collection.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...