Lumiera  0.pre.03
»edit your freedom«
iter-source-test.cpp
Go to the documentation of this file.
1 /*
2  IterSource(Test) - how to build an opaque iterator-based data source
3 
4  Copyright (C) Lumiera.org
5  2010, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 * *****************************************************/
22 
29 #include "lib/test/run.hpp"
30 #include "lib/test/test-helper.hpp"
31 #include "lib/format-cout.hpp"
32 #include "lib/nocopy.hpp"
33 #include "lib/util.hpp"
34 
35 #include "lib/iter-source.hpp"
36 
37 #include <boost/lexical_cast.hpp>
38 #include <unordered_map>
39 #include <cstdlib>
40 #include <string>
41 #include <list>
42 #include <map>
43 
44 
45 
46 namespace lib {
47 namespace test{
48 
49  using ::Test;
50  using boost::lexical_cast;
51  using lib::time::TimeVar;
52  using lib::test::randStr;
53  using lib::test::randTime;
54  using util::isnil;
55  using util::cStr;
56  using std::make_pair;
57  using std::string;
58  using std::list;
59  using std::rand;
60 
61  using lumiera::error::LERR_(ITER_EXHAUST);
62 
63  using iter_source::eachEntry;
64  using iter_source::transform;
65  using iter_source::singleVal;
66  using iter_source::eachMapKey;
67  using iter_source::eachMapVal;
68  using iter_source::eachValForKey;
69  using iter_source::eachDistinctKey;
70 
71 
72 
73  namespace { // Subject of test
74 
75 
76  uint NUM_ELMS = 10;
77 
78  typedef const char* CStr;
79 
84  class TestSource
85  : public IterSource<CStr>
87  {
88 
89  string buffer_;
90  CStr current_;
91 
92  virtual Pos
93  firstResult () override
94  {
95  current_ = buffer_.c_str();
96  ENSURE (current_);
97  return &current_;
98  }
99 
100  virtual void
101  nextResult (Pos& pos) override
102  {
103  if (pos && *pos && **pos)
104  ++(*pos);
105 
106  if (!(pos && *pos && **pos))
107  pos = 0;
108  }
109 
110 
111 
112  public:
113  TestSource (uint num)
114  : buffer_(randStr (num))
115  , current_(0)
116  {
117  INFO (test, "created TestSource(\"%s\")", cStr(buffer_));
118  }
119  };
120 
121 
122 
126  struct WrappedList
127  {
128  list<int> data_;
129 
130  WrappedList(uint num)
131  {
132  while (num)
133  data_.push_back(num--);
134  }
135 
136  typedef list<int>::iterator sourceIter;
138 
139  iterator begin() { return iterator(data_.begin(),data_.end()); }
140  iterator end() { return iterator(); }
141 
142  };
143 
144 
146  template<class IT>
147  inline void
148  pullOut (IT& iter)
149  {
150  for ( ; iter; ++iter )
151  cout << "::" << *iter;
152  cout << endl;
153  }
154  } // (END) impl test dummy containers
155 
156 
157 
158 
159 
160 
161 
162  /**************************************************************/
172  class IterSource_test : public Test
173  {
174 
176  typedef IterSource<CStr>::iterator StrIter;
179 
180  typedef std::map<string,TimeVar> TreeMap;
181  typedef std::unordered_map<string,TimeVar> HashMap;
182 
183  typedef std::multimap<int,int> TreeMultimap;
184  typedef std::unordered_multimap<int,int>HashMultimap;
185 
186 
187  virtual void
188  run (Arg arg)
189  {
190  if (0 < arg.size()) NUM_ELMS = lexical_cast<uint> (arg[1]);
191 
192  verify_simpleIters();
193  verify_transformIter();
194 
195  verify_MapWrappers<TreeMap>();
196  verify_MapWrappers<HashMap>();
197 
198  verify_MultimapIters<TreeMultimap>();
199  verify_MultimapIters<HashMultimap>();
200  }
201 
202 
203  void
204  verify_simpleIters()
205  {
206  // build the test data sources
207  WrappedList customList(NUM_ELMS);
208  TestSource dedicatedSource(NUM_ELMS);
209  list<int>& rawList(customList.data_);
210 
211  IntIter iii (eachEntry (customList));
212  IntIter isi (eachEntry (rawList.begin(), rawList.end()));
213  StrIter cii (IterSource<CStr>::build(dedicatedSource));
214 
215  CHECK (!isnil (iii));
216  CHECK (!isnil (isi));
217  CHECK (!isnil (cii));
218 
219  pullOut (iii);
220  pullOut (isi);
221  pullOut (cii);
222 
223  CHECK (!iii);
224  CHECK (!isi);
225  CHECK (!cii);
226  }
227 
228 
237  void
239  {
240  WrappedList customList(NUM_ELMS);
241  WrappedList::iterator sourceValues = customList.begin();
242 
243  // transformation function
244  auto makeTime = [](int input_sec) -> TimeVar
245  {
246  return time::Time (time::FSecs (input_sec, 4));
247  };
248 
249  TimeIter tIt (transform (sourceValues, makeTime));
250  CHECK (!isnil (tIt));
251  pullOut (tIt);
252  CHECK (!tIt);
253  }
254 
255 
257  void
259  {
260  int i{-9};
261 
262  IntIter ii = singleVal(12);
263  CHECK (not isnil(ii));
264  CHECK (12 == *ii);
265 
266  ++ii;
267  CHECK (isnil (ii));
268  VERIFY_ERROR (ITER_EXHAUST, *ii );
269 
270  // IterSource is an abstracting interface,
271  // thus we're able to reassign an embedded iterator
272  // with a different value type (int& instead of int)
273  ii = singleVal(i);
274 
275  CHECK (not isnil(ii));
276  CHECK (-9 == *ii);
277 
278  // NOTE: since we passed a reference, a reference got wrapped
279  i = 23;
280  CHECK (23 == *ii);
281  ++ii;
282  CHECK (isnil (ii));
283  }
284 
285 
286 
287 
288  template<class MAP>
289  void
290  verify_MapWrappers()
291  {
292  MAP testMap;
293  for (uint i=0; i<NUM_ELMS; ++i)
294  testMap['X'+randStr(11)] = randTime();
295 
296  StringIter sIter = eachMapKey (testMap);
297  TimeIter tIter = eachMapVal (testMap);
298 
299  CHECK (sIter && tIter);
300  pullOut (sIter);
301  pullOut (tIter);
302 
303  CHECK (!sIter && !tIter);
304 
305 
306  // The each-value-for-given-key-Iterator can be used for a map or multimap.
307  // In case of a map, it should yield exactly one result for existing values
308  // and zero results for non-existing mappings
309  StringIter justSomeKey = eachMapKey (testMap);
310  TimeIter correspondingVal = eachMapVal (testMap);
311  ++justSomeKey;
312  ++correspondingVal;
313  CHECK (justSomeKey);
314 
315  TimeIter value4key = eachValForKey (testMap, "nonexistent key");
316  CHECK (!value4key);
317 
318  value4key = eachValForKey (testMap, *justSomeKey);
319  CHECK (value4key);
320  CHECK (*value4key == *correspondingVal);
321  ++value4key;
322  CHECK (!value4key);
323  }
324 
325 
326  template<class MAP>
327  void
328  verify_MultimapIters()
329  {
330  MAP testMap;
331  for (uint i=0; i<NUM_ELMS; ++i)
332  {
333  uint n = 1 + rand() % 100;
334  do testMap.insert (make_pair (i,n));
335  while (--n);
336  }
337  CHECK (NUM_ELMS < testMap.size(), "no repetition in test data??");
338 
339  IntIter keys = eachDistinctKey (testMap);
340 
341  cout << "distinct_keys";
342  CHECK (keys);
343  pullOut (keys);
344  CHECK (!keys);
345 
346  cout << "values_4_key";
347  IntIter vals = eachValForKey (testMap, NUM_ELMS); // non-existent key
348  CHECK (!vals);
349 
350  vals = eachValForKey (testMap, 0);
351  CHECK (vals);
352  pullOut (vals); // should produce anything between 1 and 100 entries
353  CHECK (!vals);
354  }
355  };
356 
357 
358  LAUNCHER (IterSource_test, "unit common");
359 
360 
361 }} // namespace lib::test
362 
a mutable time value, behaving like a plain number, allowing copy and re-accessing ...
Definition: timevalue.hpp:238
virtual void nextResult(Pos &pos) override
iteration step: switch on to the next element.
Automatically use custom string conversion in C++ stream output.
Definition: run.hpp:49
Any copy and copy construction prohibited.
Definition: nocopy.hpp:46
#define VERIFY_ERROR(ERROR_ID, ERRONEOUS_STATEMENT)
Macro to verify a statement indeed raises an exception.
const char * cStr(string const &org)
convenience shortcut: conversion to c-String via string.
Definition: util.hpp:423
Implementation namespace for support and library code.
string randStr(size_t len)
create garbage string of given length
Definition: test-helper.cpp:69
Lumiera&#39;s internal time value datatype.
Definition: timevalue.hpp:305
Explicit implementation of the IterSource interface (test dummy) Creates a random string and chops of...
virtual Pos firstResult() override
iteration start: prepare the first element.
Iteration source interface to abstract a data source, which then can be accessed through IterAdapter ...
Definition: iter-source.hpp:88
Mix-Ins to allow or prohibit various degrees of copying and cloning.
Simple test class runner.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
boost::rational< int64_t > FSecs
rational representation of fractional seconds
Definition: timevalue.hpp:226
A collection of frequently used helper functions to support unit testing.
lib::time::Time randTime()
create a random but not insane Time value between 1s ...
Accessing a STL element range through a Lumiera forward iterator, An instance of this iterator adapte...
test dummy: simply wrapping an STL container and exposing a range as Lumiera Forward Iterator ...
Extension module to build an opaque data source, accessible as Lumiera Forward Iterator.