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 std::make_pair;
56  using std::string;
57  using std::list;
58  using std::rand;
59 
60  using LERR_(ITER_EXHAUST);
61 
62  using iter_source::eachEntry;
63  using iter_source::transform;
64  using iter_source::singleVal;
65  using iter_source::eachMapKey;
66  using iter_source::eachMapVal;
67  using iter_source::eachValForKey;
68  using iter_source::eachDistinctKey;
69 
70 
71 
72  namespace { // Subject of test
73 
74 
75  uint NUM_ELMS = 10;
76 
77  typedef const char* CStr;
78 
83  class TestSource
84  : public IterSource<CStr>
86  {
87 
88  string buffer_;
89  CStr current_;
90 
91  virtual Pos
92  firstResult () override
93  {
94  current_ = buffer_.c_str();
95  ENSURE (current_);
96  return &current_;
97  }
98 
99  virtual void
100  nextResult (Pos& pos) override
101  {
102  if (pos && *pos && **pos)
103  ++(*pos);
104 
105  if (!(pos && *pos && **pos))
106  pos = 0;
107  }
108 
109 
110 
111  public:
112  TestSource (uint num)
113  : buffer_(randStr (num))
114  , current_(0)
115  {
116  INFO (test, "created TestSource(\"%s\")", cStr(buffer_));
117  }
118  };
119 
120 
121 
125  struct WrappedList
126  {
127  list<int> data_;
128 
129  WrappedList(uint num)
130  {
131  while (num)
132  data_.push_back(num--);
133  }
134 
135  typedef list<int>::iterator sourceIter;
137 
138  iterator begin() { return iterator(data_.begin(),data_.end()); }
139  iterator end() { return iterator(); }
140 
141  };
142 
143 
145  template<class IT>
146  inline void
147  pullOut (IT& iter)
148  {
149  for ( ; iter; ++iter )
150  cout << "::" << *iter;
151  cout << endl;
152  }
153  } // (END) impl test dummy containers
154 
155 
156 
157 
158 
159 
160 
161  /**************************************************************/
171  class IterSource_test : public Test
172  {
173 
175  typedef IterSource<CStr>::iterator StrIter;
178 
179  typedef std::map<string,TimeVar> TreeMap;
180  typedef std::unordered_map<string,TimeVar> HashMap;
181 
182  typedef std::multimap<int,int> TreeMultimap;
183  typedef std::unordered_multimap<int,int>HashMultimap;
184 
185 
186  virtual void
187  run (Arg arg)
188  {
189  if (0 < arg.size()) NUM_ELMS = lexical_cast<uint> (arg[1]);
190 
191  verify_simpleIters();
192  verify_transformIter();
193 
194  verify_MapWrappers<TreeMap>();
195  verify_MapWrappers<HashMap>();
196 
197  verify_MultimapIters<TreeMultimap>();
198  verify_MultimapIters<HashMultimap>();
199  }
200 
201 
202  void
203  verify_simpleIters()
204  {
205  // build the test data sources
206  WrappedList customList(NUM_ELMS);
207  TestSource dedicatedSource(NUM_ELMS);
208  list<int>& rawList(customList.data_);
209 
210  IntIter iii (eachEntry (customList));
211  IntIter isi (eachEntry (rawList.begin(), rawList.end()));
212  StrIter cii (IterSource<CStr>::build(dedicatedSource));
213 
214  CHECK (!isnil (iii));
215  CHECK (!isnil (isi));
216  CHECK (!isnil (cii));
217 
218  pullOut (iii);
219  pullOut (isi);
220  pullOut (cii);
221 
222  CHECK (!iii);
223  CHECK (!isi);
224  CHECK (!cii);
225  }
226 
227 
236  void
238  {
239  WrappedList customList(NUM_ELMS);
240  WrappedList::iterator sourceValues = customList.begin();
241 
242  // transformation function
243  auto makeTime = [](int input_sec) -> TimeVar
244  {
245  return time::Time (time::FSecs (input_sec, 4));
246  };
247 
248  TimeIter tIt (transform (sourceValues, makeTime));
249  CHECK (!isnil (tIt));
250  pullOut (tIt);
251  CHECK (!tIt);
252  }
253 
254 
256  void
258  {
259  int i{-9};
260 
261  IntIter ii = singleVal(12);
262  CHECK (not isnil(ii));
263  CHECK (12 == *ii);
264 
265  ++ii;
266  CHECK (isnil (ii));
267  VERIFY_ERROR (ITER_EXHAUST, *ii );
268 
269  // IterSource is an abstracting interface,
270  // thus we're able to reassign an embedded iterator
271  // with a different value type (int& instead of int)
272  ii = singleVal(i);
273 
274  CHECK (not isnil(ii));
275  CHECK (-9 == *ii);
276 
277  // NOTE: since we passed a reference, a reference got wrapped
278  i = 23;
279  CHECK (23 == *ii);
280  ++ii;
281  CHECK (isnil (ii));
282  }
283 
284 
285 
286 
287  template<class MAP>
288  void
289  verify_MapWrappers()
290  {
291  MAP testMap;
292  for (uint i=0; i<NUM_ELMS; ++i)
293  testMap['X'+randStr(11)] = randTime();
294 
295  StringIter sIter = eachMapKey (testMap);
296  TimeIter tIter = eachMapVal (testMap);
297 
298  CHECK (sIter && tIter);
299  pullOut (sIter);
300  pullOut (tIter);
301 
302  CHECK (!sIter && !tIter);
303 
304 
305  // The each-value-for-given-key-Iterator can be used for a map or multimap.
306  // In case of a map, it should yield exactly one result for existing values
307  // and zero results for non-existing mappings
308  StringIter justSomeKey = eachMapKey (testMap);
309  TimeIter correspondingVal = eachMapVal (testMap);
310  ++justSomeKey;
311  ++correspondingVal;
312  CHECK (justSomeKey);
313 
314  TimeIter value4key = eachValForKey (testMap, "nonexistent key");
315  CHECK (!value4key);
316 
317  value4key = eachValForKey (testMap, *justSomeKey);
318  CHECK (value4key);
319  CHECK (*value4key == *correspondingVal);
320  ++value4key;
321  CHECK (!value4key);
322  }
323 
324 
325  template<class MAP>
326  void
327  verify_MultimapIters()
328  {
329  MAP testMap;
330  for (uint i=0; i<NUM_ELMS; ++i)
331  {
332  uint n = 1 + rand() % 100;
333  do testMap.insert (make_pair (i,n));
334  while (--n);
335  }
336  CHECK (NUM_ELMS < testMap.size(), "no repetition in test data??");
337 
338  IntIter keys = eachDistinctKey (testMap);
339 
340  cout << "distinct_keys";
341  CHECK (keys);
342  pullOut (keys);
343  CHECK (!keys);
344 
345  cout << "values_4_key";
346  IntIter vals = eachValForKey (testMap, NUM_ELMS); // non-existent key
347  CHECK (!vals);
348 
349  vals = eachValForKey (testMap, 0);
350  CHECK (vals);
351  pullOut (vals); // should produce anything between 1 and 100 entries
352  CHECK (!vals);
353  }
354  };
355 
356 
357  LAUNCHER (IterSource_test, "unit common");
358 
359 
360 }} // namespace lib::test
361 
a mutable time value, behaving like a plain number, allowing copy and re-accessing ...
Definition: timevalue.hpp:241
virtual void nextResult(Pos &pos) override
iteration step: switch on to the next element.
Automatically use custom string conversion in C++ stream output.
CStr cStr(std::string const &rendered)
convenience shortcut: forced conversion to c-String via string.
Definition: symbol.hpp:68
Definition: run.hpp:49
Any copy and copy construction prohibited.
Definition: nocopy.hpp:46
#define VERIFY_ERROR(ERROR_ID, ERRONEOUS_STATEMENT)
Macro to verify that a statement indeed raises an exception.
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:308
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:229
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.