Lumiera 0.pre.04~rc.1
»edit your freedom«
Loading...
Searching...
No Matches
scoped-collection-test.cpp
Go to the documentation of this file.
1/*
2 ScopedCollection(Test) - holding and owning a fixed collection of noncopyable objects
3
4 Copyright (C)
5 2012, 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
26
27
28namespace lib {
29namespace test{
30
31 namespace error = lumiera::error;
32
33
34 namespace { // our explosive special Dummy
35
36 LUMIERA_ERROR_DEFINE(SUBVERSIVE, "undercover action");
37
39 : public Dummy
40 {
42
46 virtual long
47 calc (int i)
48 {
49 if (!i)
50 return getVal() + trigger_;
51 else
52 return Dummy::calc(i);
53 }
54
55 public:
56 SubDummy (int id, int trigger)
57 : Dummy(id)
58 , trigger_(trigger)
59 {
60 if (trigger == getVal())
61 throw error::Fatal ("Subversive Bomb", LUMIERA_ERROR_SUBVERSIVE);
62 }
63
65 : Dummy()
66 , trigger_(-1)
67 { }
68 };
69
70
71 inline uint
72 sum (uint n)
73 {
74 return n*(n+1) / 2;
75 }
76
77 }//(End) subversive test data
78
79
80
81
82 using util::isnil;
83 using LERR_(ITER_EXHAUST);
84
85 typedef ScopedCollection<Dummy, sizeof(SubDummy)> CollD;
86
87
88 /****************************************************************/
95 class ScopedCollection_test : public Test
96 {
97
98 virtual void
99 run (Arg)
100 {
101 seedRand();
102 simpleUsage();
105 iterating();
109 }
110
111
112 void
114 {
115 CHECK (0 == Dummy::checksum());
116 {
117 CollD container(5);
118 CHECK (isnil (container));
119 CHECK (0 == container.size());
120 CHECK (0 == Dummy::checksum());
121
122 container.populate();
123 CHECK (!isnil (container));
124 CHECK (5 == container.size());
125 CHECK (0 != Dummy::checksum());
126
127 container.clear();
128 CHECK (isnil (container));
129 CHECK (0 == container.size());
130 CHECK (0 == Dummy::checksum());
131
132 container.populate();
133 CHECK (Dummy::checksum() == container[0].getVal()
134 + container[1].getVal()
135 + container[2].getVal()
136 + container[3].getVal()
137 + container[4].getVal());
138 }
139 CHECK (0 == Dummy::checksum());
140 }
141
142
143 void
145 {
146 CHECK (0 == Dummy::checksum());
147 {
148 CollD coll(50);
149 for (uint i=0; i<coll.capacity(); ++i)
150 coll.emplace<Dummy>(i);
151
152 int check=0;
153 CollD::iterator ii = coll.begin();
154 while (ii)
155 {
156 CHECK (check == ii->getVal());
157 CHECK (check == ii->calc(+5) - 5);
158 ++check;
159 ++ii;
160 }
161
162
163 // Test the const iterator
164 CollD const& const_coll (coll);
165 check = 0;
166 CollD::const_iterator cii = const_coll.begin();
167 while (cii)
168 {
169 CHECK (check == cii->getVal());
170 ++check;
171 ++cii;
172 }
173
174
175 // Test c++11 foreach iteration
176 check = 0;
177 for (auto& entry : coll)
178 {
179 CHECK (check == entry.getVal());
180 ++check;
181 }
182 check = 0;
183 for (auto const& entry : const_coll)
184 {
185 CHECK (check == entry.getVal());
186 ++check;
187 }
188
189
190 // Verify correct behaviour of iteration end
191 CHECK (! (coll.end()));
192 CHECK (isnil (coll.end()));
193
194 VERIFY_ERROR (ITER_EXHAUST, *coll.end() );
195 VERIFY_ERROR (ITER_EXHAUST, ++coll.end() );
196
197 CHECK (ii == coll.end());
198 CHECK (cii == coll.end());
199 VERIFY_ERROR (ITER_EXHAUST, ++ii );
200 VERIFY_ERROR (ITER_EXHAUST, ++cii );
201
202 }
203 CHECK (0 == Dummy::checksum());
204 }
205
206
216 void
218 {
219 CHECK (0 == Dummy::checksum());
220 {
221
222 int rr = rani(100);
223
224 CollD coll(3);
225 CHECK (0 == coll.size());
226 CHECK (0 == Dummy::checksum());
227
228 Dummy& d0 = coll.emplaceElement();
229 CHECK (1 == coll.size());
230
231 Dummy& d1 = coll.emplace<Dummy> (rr);
232 CHECK (2 == coll.size());
233
234 int sum = Dummy::checksum();
235
236 // trigger the bomb
237 VERIFY_ERROR (SUBVERSIVE, coll.emplace<SubDummy>(rr,rr) );
238
239 CHECK ( 2 == coll.size()); // the other objects survived
240 CHECK (sum == Dummy::checksum());
241
242 Dummy& d2 = coll.emplace<SubDummy> (rr, rr+1);
243 CHECK (3 == coll.size());
244
245 CHECK (sum + rr == Dummy::checksum());
246
247 VERIFY_ERROR (CAPACITY, coll.emplaceElement());
248 VERIFY_ERROR (CAPACITY, coll.emplaceElement());
249 VERIFY_ERROR (CAPACITY, coll.emplaceElement());
250
251 CHECK (3 == coll.size());
252 CHECK (sum + rr == Dummy::checksum());
253
254
255 CHECK (d0.calc(11) == coll[0].getVal() + 11 );
256 CHECK (d1.calc(22) == rr + 22);
257 CHECK (d2.calc(33) == rr + 33);
258 CHECK (d2.calc(0) == rr + (rr+1) ); // SubDummy's special implementation of the acc()-function
259 // returns the trigger value, when the argument is zero
260
261 coll.clear();
262 coll.emplace<SubDummy> (11,22);
263
264 CHECK ( 1 == coll.size());
265 CHECK (11 == Dummy::checksum());
266
267 // NOTE DANGEROUS:
268 // The previously obtained references just point into the object storage.
269 // Thus we're now accessing a different object, even a different type!
270 CHECK (d0.calc(0) == 11 + 22);
271
272 // The others even point into obsoleted storage holding zombie objects
273 CHECK (d1.getVal() == Dummy::DEAD);
274
275 }
276 CHECK (0 == Dummy::checksum());
277 }
278
279
296 void
298 {
299 CHECK (0 == Dummy::checksum());
300 {
301 int rr = rani(100);
302 int trigger = 100 + 5 + 1; // prevents the bomb from exploding (since rr < 100)
303
304 CollD coll (6, Populator(rr, trigger));
305
306 CHECK (!isnil (coll));
307 CHECK (6 == coll.size());
308 CHECK (0 != Dummy::checksum());
309
310 CHECK (coll[0].calc(0) == 0 + rr);
311 CHECK (coll[1].calc(0) == 1 + rr + trigger);
312 CHECK (coll[2].calc(0) == 2 + rr);
313 CHECK (coll[3].calc(0) == 3 + rr + trigger);
314 CHECK (coll[4].calc(0) == 4 + rr);
315 CHECK (coll[5].calc(0) == 5 + rr + trigger);
316 // what does this check prove?
317 // - the container was indeed populated with DubDummy objects
318 // since the overridden version of Dummy::acc() did run and
319 // reveal the trigger value
320 // - the population was indeed done with the anonymous Populator
321 // instance fed to the ctor, since this object was "marked" with
322 // the random value rr, and adds this mark to the built values.
323
324 coll.clear();
325 CHECK (0 == Dummy::checksum());
326
327 // Verify Error handling while in creation:
328 // SubDummy explodes on equal ctor parameters
329 // which here happens for i==7
330 VERIFY_ERROR (SUBVERSIVE, CollD(10, Populator(0, 7)) );
331
332 // any already created object was properly destroyed
333 CHECK (0 == Dummy::checksum());
334
335 }
336 CHECK (0 == Dummy::checksum());
337 }
338
341 {
343 int off_;
345
346 public:
347 Populator (int baseOffset, int triggerCode)
348 : i_(0)
349 , off_(baseOffset)
350 , trigg_(triggerCode)
351 { }
352
353 void
354 operator() (CollD::ElementHolder& storage)
355 {
356 switch (i_ % 2)
357 {
358 case 0:
359 storage.create<Dummy> (i_+off_);
360 break;
361
362 case 1:
363 storage.create<SubDummy> (i_+off_, trigg_);
364 break;
365 }
366 ++i_;
367 }
368 };
369
370
371
377 void
379 {
380 CHECK (0 == Dummy::checksum());
381
382 CollD coll (25, CollD::FillAll() );
383
384 CHECK (!isnil (coll));
385 CHECK (25 == coll.size());
386 CHECK (0 != Dummy::checksum());
387
388 for (CollD::iterator ii = coll.begin(); ii; ++ii)
389 {
390 CHECK ( INSTANCEOF (Dummy, & (*ii)));
391 CHECK (!INSTANCEOF (SubDummy, & (*ii)));
392 }
393 }
394
395
396 void
398 {
399 CHECK (0 == Dummy::checksum());
400
401 CollD coll (25, CollD::FillWith<SubDummy>() );
402
403 CHECK (!isnil (coll));
404 CHECK (25 == coll.size());
405 CHECK (0 != Dummy::checksum());
406
407 for (CollD::iterator ii = coll.begin(); ii; ++ii)
408 CHECK (INSTANCEOF (SubDummy, & (*ii)));
409 }
410
411
412 void
414 {
415 typedef ScopedCollection<uint> CollI;
416
417 CollI source (25);
418 for (uint i=0; i < source.capacity(); ++i)
419 source.emplace<uint>(i); // holding the numbers 0..24
420
421 CollI coll (20, CollI::pull(source.begin()));
422 // this immediately pulls in the first 20 elements
423 CHECK (!isnil (coll));
424 CHECK (20 == coll.size());
425 CHECK (25 == source.size());
426
427 for (uint i=0; i < coll.size(); ++i)
428 {
429 CHECK (coll[i] == i );
430 CHECK (coll[i] == source[i]);
431 }
432
433 // note: the iterator is assumed to deliver a sufficient amount of elements
434 VERIFY_ERROR (ITER_EXHAUST, CollI (50, CollI::pull (source.begin())));
435 }
436
437
445 void
447 {
448 ManagerDemo object_with_embedded_Collection(50);
449 CHECK (sum(50) == object_with_embedded_Collection.useMyNumbers());
450 }
451
453 {
455
458
459 void
460 buildNumbers (CollI::ElementHolder& storage)
461 {
462 storage.create<uint>(memberVar_);
463 --memberVar_;
464 }
465
466 public:
468 : memberVar_(cnt)
470 {
471 CHECK (0 == memberVar_);
472 CHECK (cnt == my_own_Numbers_.size());
473 }
474
475 uint
477 {
478 uint sum(0);
479 for (CollI::const_iterator ii = my_own_Numbers_.begin(); ii; ++ii)
480 sum += *ii;
481 return sum;
482 }
483 };
484 };
485
486
487
489
490
491}} // namespace lib::test
492
A fixed collection of non-copyable polymorphic objects.
A Dummy object for tests.
virtual long calc(int i)
a dummy API operation
static constexpr int DEAD
static long & checksum()
void operator()(CollD::ElementHolder &storage)
virtual long calc(int i)
special variant of the dummy API operation:
#define LUMIERA_ERROR_DEFINE(err, msg)
Definition and initialisation of an error constant.
Definition error.h:71
#define LERR_(_NAME_)
Definition error.hpp:45
unsigned int uint
Definition integral.hpp:29
ScopedCollection< Dummy, sizeof(SubDummy)> CollD
Implementation namespace for support and library code.
int rani(uint bound=_iBOUND())
Definition random.hpp:135
LumieraError< LERR_(FATAL), Logic > Fatal
Definition error.hpp:208
Test runner and basic definitions for tests.
bool isnil(lib::time::Duration const &dur)
Simplistic test class runner.
#define LAUNCHER(_TEST_CLASS_, _GROUPS_)
Definition run.hpp:116
Managing a collection of non-copyable polymorphic objects in compact storage.
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.
unittest helper code: test dummy objects to track instances.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
#define INSTANCEOF(CLASS, EXPR)
shortcut for subclass test, intended for assertions only.
Definition util.hpp:514