Lumiera 0.pre.04
»edit your freedom«
Loading...
Searching...
No Matches
iter-adapter-test.cpp
Go to the documentation of this file.
1/*
2 IterAdapter(Test) - building various custom iterators for a given container
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/format-cout.hpp"
25
26#include "lib/iter-adapter.hpp"
28
29#include <boost/lexical_cast.hpp>
30#include <vector>
31
32
33
34namespace lib {
35namespace test{
36
37 using ::Test;
38 using LERR_(ITER_EXHAUST);
39 using boost::lexical_cast;
40 using util::for_each;
41 using util::isnil;
42 using std::vector;
43
44
45 namespace {
51 {
52 vector<int> data_;
53
55 {
56 while (num)
57 data_.push_back(num--);
58 }
59
60 typedef vector<int>::iterator sourceIter;
62
63 typedef vector<int>::const_iterator const_sourceIter;
65
66 iterator begin() { return iterator(data_.begin(),data_.end()); }
67 iterator end() { return iterator(); }
68 const_iterator begin() const { return const_iterator(data_.begin(),data_.end()); }
69 const_iterator end() const { return const_iterator(); }
70 };
71
72
82 {
83 typedef vector<int *> _Vec;
84
86
87 static void killIt (int *it) { delete it; }
88
89
90 public:
92 : numberz_(count)
93 {
94 for (uint i=0; i<count; ++i)
95 numberz_[i] = new int(i);
96 }
97
99 {
100 for_each (numberz_, killIt);
101 }
102
103
104 /* ==== Exposing Iterator interface(s) for the clients ====== */
105
108
111
112
113 iterator begin () { return iterator (this, numberz_.begin()); }
114 const_iterator begin () const { return const_iterator (this, numberz_.begin()); }
115 ref_iterator begin_ref () { return ref_iterator (begin()); }
116 const_ref_iter begin_ref () const { return const_ref_iter (begin()); }
117
118 iterator end () { return iterator(); }
119 const_iterator end () const { return const_iterator(); }
120
121 size_t size() const { return numberz_.size(); }
122
123
124
125 protected: /* ==== API for the IterAdapter ==== */
126
133 template<class ITER>
134 friend void
135 iterNext (const TestContainer*, ITER& pos)
136 {
137 ++pos;
138 }
139
150 template<class ITER>
151 friend bool
152 checkPoint (const TestContainer* src, ITER& pos)
153 {
154 REQUIRE (src);
155 if ((pos != ITER()) and (pos != src->numberz_.end()))
156 return true;
157 else
158 {
159 pos = ITER();
160 return false;
161 } }
162 };
163
164 } // (END) impl test dummy container
165
166
167
168
169
170
171
172 /*****************************************************************/
182 class IterAdapter_test : public Test
183 {
185
186 virtual void
187 run (Arg arg)
188 {
189 NUM_ELMS = firstVal (arg, 10);
190
192
193 enumerate();
195 TestContainer testElms (NUM_ELMS);
196 simpleUsage (testElms);
197
198 iterTypeVariations (testElms);
199 verifyComparisons (testElms);
201 }
202
203
205 void
207 {
208 long sum=0;
209 const int N = NUM_ELMS;
210 auto i = eachNum(1, N);
211 while (i)
212 {
213 sum += *i;
214 ++i;
215 }
216
217 CHECK (sum == (N-1)*N / 2);
218
219 CHECK (!i);
220 VERIFY_ERROR (ITER_EXHAUST, *i );
221 VERIFY_ERROR (ITER_EXHAUST, ++i );
222
223 i = eachNum (N, 2*N);
224 CHECK (i);
225 CHECK (N == *i);
226 ++i;
227 CHECK (N+1 == *i);
228 for ( ; i; ++i)
229 cout << "++" << *i;
230 cout << endl;
231
232 CHECK (!i);
233 }
234
235
240 void
242 {
243 vector<int> iVec (NUM_ELMS);
244 for (uint i=0; i < NUM_ELMS; ++i)
245 iVec[i] = i;
246
247 typedef vector<int>::iterator I;
248 typedef RangeIter<I> Range;
249
250 Range range (iVec.begin(), iVec.end());
251 CHECK (not isnil(range) or not NUM_ELMS);
252
253 // now for example the client could....
254 while ( range )
255 {
256 cout << "::" << *range;
257 ++range;
258 }
259
260 cout << endl;
261 CHECK (isnil (range));
262 CHECK (range == Range());
263 }
264
265
266
268 template<class CON>
269 void
270 simpleUsage (CON& elms)
271 {
272 for_each (elms, showIntP);
273 cout << endl;
274 }
275
276 static void showIntP (int* elm) { cout << "::" << *elm; }
277 static void showInt (int elm) { cout << "::" << elm; }
278
279
280
281 void
283 {
284 WrappedVector testVec (NUM_ELMS);
285 for_each (testVec, showInt);
286 cout << endl;
287
288 WrappedVector const& ref (testVec);
289 for_each (ref, showInt); // uses const_iterator
290 cout << endl;
291 }
292
293
296 void
297 iterTypeVariations (TestContainer& elms)
298 {
299 TestContainer const& const_elms (elms);
300
301 int i = 0;
302 for (TestContainer::iterator iter = elms.begin();
303 iter; ++iter, ++i
304 )
305 {
306 CHECK (iter);
307 CHECK (iter != elms.end());
308 CHECK (**iter == i);
309 --(**iter);
310 CHECK (**iter == i-1);
311 }
312
313 i = 0;
314 for (TestContainer::const_iterator iter = const_elms.begin();
315 iter; ++iter, ++i
316 )
317 {
318 CHECK (iter);
319 CHECK (iter != elms.end());
320 CHECK (**iter == i-1);
321
322 // note: the previous run indeed modified
323 // the element within the container.
324
325 // ++(*iter); // doesn't compile, because it yields a "* const"
326 }
327
328 i = 0;
329 for (TestContainer::ref_iterator iter = elms.begin_ref();
330 iter; ++iter, ++i
331 )
332 {
333 CHECK (iter);
334 CHECK ((*iter) == i-1);
335 ++(*iter);
336 CHECK ((*iter) == i);
337 }
338
339 i = 0;
340 for (TestContainer::const_ref_iter iter = const_elms.begin_ref();
341 iter; ++iter, ++i
342 )
343 {
344 CHECK (iter);
345 CHECK ((*iter) == i);
346
347 // *iter = i+1; ///////////TODO this should be const, but it isn't
348 }
349
350
351 //---- verify support for C++11 element iteration
352 i = 0;
353 for (auto& elm : elms) // NOTE: TestContainer exposes pointers
354 {
355 ++elm; // can indeed modify contents
356 --elm;
357 CHECK (*elm == i);
358 ++i;
359 }
360 CHECK (size_t(i) == elms.size());
361
362 i = 0;
363 for (auto const& elm : elms)
364 {
365 CHECK (*elm == i);
366 // ++elm; // can not modify contents
367 ++i;
368 }
369 CHECK (size_t(i) == elms.size());
370
371 i = 0;
372 for (auto const& elm : const_elms)
373 {
374 CHECK (*elm == i);
375 // ++elm; // can not modify contents
376 ++i;
377 }
378 CHECK (size_t(i) == elms.size());
379 }
380
381
384 void
386 {
387 vector<int> numbz;
388 for (uint i=0; i < NUM_ELMS; ++i)
389 numbz.push_back(i);
390
391 typedef vector<int>::iterator RawIter;
392 typedef RangeIter<RawIter> Range;
393 typedef AddressExposingIter<Range> AddrIter;
394
395 AddrIter ii(Range(numbz.begin(), numbz.end()));
396 for (uint i=0; i < numbz.size(); ++i)
397 {
398 CHECK (ii);
399 int* p = *ii;
400 CHECK (p == & numbz[i]);
401 ++ii;
402 }
403 CHECK (!ii);
404
405 // building a const iterator needs to be done in a somewhat weird way;
406 // since we're exposing the pointer as value, the solution is to add
407 // the const on the immediately wrapped iterator type
408 typedef vector<int>::const_iterator ConstRawIter;
409 typedef RangeIter<ConstRawIter> ConstRange;
410 typedef AddressExposingIter<ConstRange> ConstAddrIter;
411
412 ConstAddrIter iic(ConstRange(Range(numbz.begin(), numbz.end())));
413 for (uint i=0; i < numbz.size(); ++i)
414 {
415 CHECK (iic);
416 const int* p = *iic;
417 CHECK (p == & numbz[i]);
418 ++iic;
419 }
420 CHECK (!iic);
421 }
422
423
424
425
427 void
428 verifyComparisons (TestContainer& elms)
429 {
430 TestContainer::ref_iterator rI (elms.begin_ref());
431
432 CHECK (0 == *rI );
433 ++rI;
434 CHECK (1 == *rI );
435 CHECK (2 == *++rI);
436
437 TestContainer const& const_elms (elms);
438 TestContainer::const_ref_iter rI2 (const_elms.begin_ref());
439
440 CHECK (rI2 != rI);
441 CHECK (rI2 == elms.begin_ref());
442 CHECK (rI2 == const_elms.begin_ref());
443
444 ++++rI2;
445
446 CHECK (rI2 == rI);
447 CHECK (rI2 != ++rI);
448 CHECK (!isnil (rI2));
449
450 CHECK (TestContainer::iterator() == elms.end());
451 CHECK (!(TestContainer::iterator()));
452 CHECK (!(elms.end()));
453 CHECK (isnil (elms.end()));
454
455 CHECK (elms.begin());
456 CHECK (!isnil (elms.begin()));
457 }
458
459
460 };
461
462 LAUNCHER (IterAdapter_test, "unit common");
463
464
465}} // namespace lib::test
466
wrapper for an existing Iterator type to expose the address of each value yielded.
Adapter for building an implementation of the »Lumiera Forward Iterator« concept.
wrapper for an existing Iterator type, automatically dereferencing the output of the former.
Accessing a STL element range through a Lumiera forward iterator, An instance of this iterator adapte...
void iterTypeVariations(TestContainer &elms)
void verifyComparisons(TestContainer &elms)
Example of a more elaborate custom container exposing an iteration API.
IterAdapter< _Vec::iterator, const TestContainer * > iterator
friend bool checkPoint(const TestContainer *src, ITER &pos)
Implementation of Iteration-logic: detect iteration end.
friend void iterNext(const TestContainer *, ITER &pos)
Implementation of Iteration-logic: pull next element.
IterAdapter< _Vec::const_iterator, const TestContainer * > const_iterator
#define LERR_(_NAME_)
Definition error.hpp:45
Automatically use custom string conversion in C++ stream output.
unsigned int uint
Definition integral.hpp:29
Extension adapter for Lumiera Forward Iterators to dereference any pointer values automatically.
Helper template(s) for creating Lumiera Forward Iterators.
Implementation namespace for support and library code.
NumIter< INT > eachNum(INT start=std::numeric_limits< INT >::min(), INT end=std::numeric_limits< INT >::max())
convenience function to iterate "each number"
Test runner and basic definitions for tests.
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)
Simplistic test class runner.
#define LAUNCHER(_TEST_CLASS_, _GROUPS_)
Definition run.hpp:116
example of simply wrapping an STL container and exposing a range as Lumiera Forward Iterator
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...