Lumiera 0.pre.04~rc.1
»edit your freedom«
Loading...
Searching...
No Matches
linked-elements-test.cpp
Go to the documentation of this file.
1/*
2 LinkedElements(Test) - verify the intrusive single linked list template
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
27#include "lib/iter-source.hpp"
28
29#include <memory>
30
31
32
33namespace lib {
34namespace test{
35
36 namespace error = lumiera::error;
37
38 using util::isnil;
40 using LERR_(ITER_EXHAUST);
41
42
43 namespace { // test data...
44
45 LUMIERA_ERROR_DEFINE(PROVOKED_FAILURE, "provoked failure");
46
47 const uint NUM_ELEMENTS = 500;
49
50 inline void __triggerErrorAt(int i) { exception_trigger = i; }
52
53
58 struct Nummy
59 : Dummy
60 {
62
64 : Dummy()
65 , next{0}
66 { }
67
68 explicit
69 Nummy (int i)
70 : Dummy{i}
71 , next{0}
72 {
73 if (i == exception_trigger)
74 throw error::Fatal("simulated error", LUMIERA_ERROR_PROVOKED_FAILURE);
75 }
76 };
77
78
82 template<uint I>
83 struct Num
84 : Nummy
85 {
86 void* storage[I]; // note size depends on template parameter
87
88 Num (int i=0, int j=0, int k=0)
89 : Nummy(I+i+j+k)
90 { }
91 };
92
93
94
104 : public IterSource<Nummy>
105 {
107
108 virtual Pos
110 {
111 return new Nummy(1);
112 }
113
114 virtual void
116 {
117 uint current = num->getVal();
118 if (maxNum_ <= current)
119 num = 0;
120 else
121 num = new Nummy(current+1);
122 }
123
124 public:
126 : maxNum_(maxElms)
127 { }
128 };
129
132 : public NummyGenerator::iterator
133 {
134 public:
135 explicit
136 Populator (uint numElms)
137 : NummyGenerator::iterator (
138 NummyGenerator::build (new NummyGenerator(numElms)))
139 { }
140 };
141
142
143
144
145 inline uint
146 sum (uint n)
147 {
148 return n*(n+1) / 2;
149 }
150
151 }//(End) test data and helpers
152
153
154
155
156
159
162
163
164
165 /****************************************************************/
170 class LinkedElements_test : public Test
171 {
172
173 virtual void
186
187
188 void
190 {
191 CHECK (0 == Dummy::checksum());
192 {
194 CHECK (isnil (elements));
195 CHECK (0 == elements.size());
196 CHECK (0 == Dummy::checksum());
197
198 elements.emplace<Nummy>(1);
199 elements.emplace<Nummy>(2);
200 elements.emplace<Nummy>(3);
201 elements.emplace<Nummy>(4);
202 elements.emplace<Nummy>(5);
203 CHECK (!isnil (elements));
204 CHECK (5 == elements.size());
205 CHECK (0 != Dummy::checksum());
206
207 CHECK (Dummy::checksum() == elements[0].getVal()
208 + elements[1].getVal()
209 + elements[2].getVal()
210 + elements[3].getVal()
211 + elements[4].getVal());
212
213 elements.clear();
214 CHECK (isnil (elements));
215 CHECK (0 == elements.size());
216 CHECK (0 == Dummy::checksum());
217
218 elements.emplace<Nummy>();
219 elements.emplace<Nummy>();
220 elements.emplace<Nummy>();
221
222 CHECK (3 == elements.size());
223 CHECK (0 != Dummy::checksum());
224 }
225 CHECK (0 == Dummy::checksum());
226 }
227
228
229 void
231 {
232 CHECK (0 == Dummy::checksum());
233 {
235 for (uint i=1; i<=NUM_ELEMENTS; ++i)
236 elements.emplace<Nummy>(i);
237
238 // since elements where pushed,
239 // they should appear in reversed order
240 int check=NUM_ELEMENTS;
241 List::iterator ii = elements.begin();
242 while (ii)
243 {
244 CHECK (check == ii->getVal());
245 CHECK (check == ii->calc(+5) - 5);
246 --check;
247 ++ii;
248 }
249 CHECK (0 == check);
250
251
252 // Test the const iterator
253 List const& const_elm (elements);
254 check = NUM_ELEMENTS;
255 List::const_iterator cii = const_elm.begin();
256 while (cii)
257 {
258 CHECK (check == cii->getVal());
259 --check;
260 ++cii;
261 }
262 CHECK (0 == check);
263
264
265 // Verify correct behaviour of iteration end
266 CHECK (! (elements.end()));
267 CHECK (isnil (elements.end()));
268
269 VERIFY_ERROR (ITER_EXHAUST, *elements.end() );
270 VERIFY_ERROR (ITER_EXHAUST, ++elements.end() );
271
272 CHECK (ii == elements.end());
273 CHECK (ii == List::iterator());
274 CHECK (cii == elements.end());
275 CHECK (cii == List::const_iterator());
276 VERIFY_ERROR (ITER_EXHAUST, ++ii );
277 VERIFY_ERROR (ITER_EXHAUST, ++cii );
278
279 }
280 CHECK (0 == Dummy::checksum());
281 }
282
283
284 void
286 {
287 CHECK (0 == Dummy::checksum());
288 {
289 List list;
290 CHECK (isnil (list));
291 list.reverse();
292 CHECK (isnil (list));
293 CHECK (0 == Dummy::checksum());
294
295 list.emplace<Nummy>(1);
296 CHECK (not isnil (list));
297 CHECK (1 == list[0].getVal());
298 CHECK (1 == Dummy::checksum());
299 list.reverse();
300 CHECK (1 == Dummy::checksum());
301 CHECK (1 == list[0].getVal());
302 CHECK (not isnil (list));
303
304 list.emplace<Nummy>(2);
305 CHECK (not isnil (list));
306 CHECK (2 == list.size());
307 CHECK (2 == list[0].getVal());
308 CHECK (2+1 == Dummy::checksum());
309 list.reverse();
310 CHECK (1+2 == Dummy::checksum());
311 CHECK (1 == list[0].getVal());
312 CHECK (2 == list.size());
313
314 list.emplace<Nummy>(3);
315 CHECK (3 == list.size());
316 CHECK (3 == list.top().getVal());
317 CHECK (3+1+2 == Dummy::checksum());
318 list.reverse();
319 CHECK (2 == list[0].getVal());
320 CHECK (1 == list[1].getVal());
321 CHECK (3 == list[2].getVal());
322 List::iterator ii = list.begin();
323 CHECK (2 == ii->getVal());
324 ++ii;
325 CHECK (1 == ii->getVal());
326 ++ii;
327 CHECK (3 == ii->getVal());
328 ++ii;
329 CHECK (isnil (ii));
330 CHECK (2+1+3 == Dummy::checksum());
331
332 list.emplace<Nummy>(4);
333 CHECK (4 == list.top().getVal());
334 CHECK (3 == list[3].getVal());
335 list.reverse();
336 CHECK (3 == list[0].getVal());
337 CHECK (1 == list[1].getVal());
338 CHECK (2 == list[2].getVal());
339 CHECK (4 == list[3].getVal());
340 CHECK (3+1+2+4 == Dummy::checksum());
341 }
342 CHECK (0 == Dummy::checksum());
343 }
344
345
354 void
356 {
357 CHECK (0 == Dummy::checksum());
358 {
360 CHECK (isnil (elements));
361
362 Num<22> n2;
363 Num<44> n4;
364 Num<66> n6;
365 CHECK (22+44+66 == Dummy::checksum());
366
367 elements.push(n2);
368 elements.push(n4);
369 elements.push(n6);
370 CHECK (!isnil (elements));
371 CHECK (3 == elements.size());
372 CHECK (22+44+66 == Dummy::checksum()); // not altered: we're referring the originals
373
374 CHECK (66 == elements[0].getVal());
375 CHECK (44 == elements[1].getVal());
376 CHECK (22 == elements[2].getVal());
377 CHECK (isSameObject(n2, elements[2]));
378 CHECK (isSameObject(n4, elements[1]));
379 CHECK (isSameObject(n6, elements[0]));
380
381 elements.clear();
382 CHECK (isnil (elements));
383 CHECK (22+44+66 == Dummy::checksum()); // referred elements unaffected
384 }
385 CHECK (0 == Dummy::checksum());
386 }
387
388
389 void
391 {
392 CHECK (0 == Dummy::checksum());
393 {
395 CHECK (isnil (elements));
396
397 __triggerErrorAt(3);
398
399 elements.emplace<Nummy>(1);
400 elements.emplace<Nummy>(2);
401 CHECK (1+2 == Dummy::checksum());
402
403 VERIFY_ERROR (PROVOKED_FAILURE, elements.emplace<Nummy>(3) );
404 CHECK (1+2 == Dummy::checksum());
405 CHECK (2 == elements.size());
406
407 CHECK (2 == elements[0].getVal());
408 CHECK (1 == elements[1].getVal());
409
410 elements.clear();
411 CHECK (0 == Dummy::checksum());
412 __triggerError_reset();
413 }
414 CHECK (0 == Dummy::checksum());
415 }
416
417
418 void
420 {
421 CHECK (0 == Dummy::checksum());
422 {
423 Populator yieldSomeElements(NUM_ELEMENTS);
424 List elements (yieldSomeElements);
425
426 CHECK (!isnil (elements));
427 CHECK (NUM_ELEMENTS == elements.size());
428 CHECK (sum(NUM_ELEMENTS) == Dummy::checksum());
429
430 int check=NUM_ELEMENTS;
431 List::iterator ii = elements.begin();
432 while (ii)
433 {
434 CHECK (check == ii->getVal());
435 --check;
436 ++ii;
437 }
438 CHECK (0 == check);
439 }
440 CHECK (0 == Dummy::checksum());
441 }
442
443
450 void
452 {
453 CHECK (0 == Dummy::checksum());
454
455 __triggerErrorAt(3);
456 Populator yieldSomeElements(NUM_ELEMENTS);
457 VERIFY_ERROR (PROVOKED_FAILURE, List elements(yieldSomeElements) );
458
459 CHECK (0 == Dummy::checksum());
460 __triggerError_reset();
461 }
462
463
464
468 {
470
472
476
477 template<class TY, typename...ARGS>
478 TY*
479 create (ARGS&& ...args)
480 {
481 return & cluster_.create<TY> (std::forward<ARGS> (args)...);
482 }
483
484 void dispose (void*) { /* does nothing */ }
485 };
486
498 void
500 {
501 CHECK (0 == Dummy::checksum());
502 {
503 AllocationCluster cluster;
504
506
507 elements.emplace<Num<1>> (2);
508 elements.emplace<Num<3>> (4,5);
509 elements.emplace<Num<6>> (7,8,9);
510
511 const size_t EXPECT = sizeof(Num<1>) + sizeof(Num<3>) + sizeof(Num<6>)
512 + 3*2*sizeof(void*); // ◁┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄overhead for storing 3 dtor-invokers
513 CHECK (EXPECT == cluster.numBytes());
514 CHECK (sum(9) == Dummy::checksum());
515
516 CHECK (3 == elements.size());
517 CHECK (1+2 == elements[2].getVal());
518 CHECK (3+4+5 == elements[1].getVal());
519 CHECK (6+7+8+9 == elements[0].getVal());
520
521 elements.clear();
522 CHECK (EXPECT == cluster.numBytes());
523 CHECK (sum(9) == Dummy::checksum());
524 // note: elements won't be discarded unless
525 // the AllocationCluster goes out of scope
526 }
527 CHECK (0 == Dummy::checksum());
528 {
529 // now use AllocationCluster through the default allocator adapter...
530 AllocationCluster cluster;
533
534 Elms elements{cluster.getAllocator<Nummy>()};
535
536 elements.emplace<Num<1>> (2);
537 elements.emplace<Num<3>> (4,5);
538
539 const size_t EXPECT = sizeof(Num<1>) + sizeof(Num<3>);
540 CHECK (EXPECT == cluster.numBytes());
541 CHECK (sum(5) == Dummy::checksum());
542
543 CHECK (2 == elements.size());
544 CHECK (1+2 == elements[1].getVal());
545 CHECK (3+4+5 == elements[0].getVal());
546 // note: this time the destructors will be invoked
547 // from LinkedElements::clear(), but not from
548 // the destructor of AllocationCluster
549 }
550 CHECK (0 == Dummy::checksum());
551 }
552 };
553
554
555
557
558
559}} // namespace lib::test
Memory management for the low-level model (render nodes network).
A pile of objects sharing common allocation and lifecycle.
TY & create(ARGS &&...)
Iteration source interface to abstract a data source, which then can be accessed through IterAdapter ...
Intrusive single linked list, possibly taking ownership of node elements.
A Dummy object for tests.
static long & checksum()
Helper to produce a pre-determined series of objects to populate a LinkedElements list.
virtual void nextResult(Pos &num)
iteration step: switch on to the next element.
virtual Pos firstResult()
iteration start: prepare the first element.
Iterator-Frontend to generate this series of objects.
#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
Extension module to build an opaque data source, accessible as Lumiera Forward Iterator.
Intrusive single linked list with optional ownership.
LinkedElements< Nummy, linked_elements::NoOwnership > ListNotOwner
managing existing node elements without taking ownership
LinkedElements< Nummy > List
default case: ownership for heap allocated nodes
Implementation namespace for support and library code.
IterQueue< T > elements(T const &elm)
convenience free function to build an iterable sequence
LumieraError< LERR_(FATAL), Logic > Fatal
Definition error.hpp:208
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
bool isnil(lib::time::Duration const &dur)
Simplistic test class runner.
#define LAUNCHER(_TEST_CLASS_, _GROUPS_)
Definition run.hpp:116
Policy to use an Allocation cluster, but also to invoke all object destructors.
Test-Element, supporting intrusive linked list 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.
#define EXPECT(_TY_, RENDERED_STRUCTURE)
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...