LUMIERA.clone/tests/lib/iter-source-test.cpp

293 lines
7.6 KiB
C++
Raw Normal View History

2010-01-05 02:53:20 +01:00
/*
IterSource(Test) - how to build an opaque iterator-based data source
2010-12-17 23:28:49 +01:00
2010-01-05 02:53:20 +01:00
Copyright (C) Lumiera.org
2010, Hermann Vosseler <Ichthyostega@web.de>
2010-12-17 23:28:49 +01:00
2010-01-05 02:53:20 +01:00
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
2010-12-17 23:28:49 +01:00
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
2010-01-05 02:53:20 +01:00
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
2010-12-17 23:28:49 +01:00
2010-01-05 02:53:20 +01:00
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
2010-12-17 23:28:49 +01:00
2010-01-05 02:53:20 +01:00
* *****************************************************/
#include "lib/test/run.hpp"
#include "lib/test/test-helper.hpp"
2010-01-06 04:14:16 +01:00
#include "lib/lumitime-fmt.hpp"
2010-01-05 02:53:20 +01:00
#include "lib/util.hpp"
#include "lib/iter-source.hpp"
#include <boost/lexical_cast.hpp>
2010-01-05 04:10:23 +01:00
#include <boost/noncopyable.hpp>
2010-01-06 04:14:16 +01:00
#include <tr1/unordered_map>
2010-01-05 02:53:20 +01:00
#include <iostream>
#include <cstdlib>
#include <string>
2010-01-05 02:53:20 +01:00
#include <list>
2010-01-06 04:14:16 +01:00
#include <map>
2010-01-05 02:53:20 +01:00
namespace lib {
namespace test{
using ::Test;
2010-01-06 04:14:16 +01:00
using lumiera::Time;
2010-01-05 02:53:20 +01:00
using boost::lexical_cast;
2010-01-05 04:10:23 +01:00
using boost::noncopyable;
using lib::test::randStr;
2010-01-06 04:14:16 +01:00
using lib::test::randTime;
2010-01-05 02:53:20 +01:00
using util::isnil;
using util::cStr;
using std::make_pair;
using std::string;
2010-01-05 02:53:20 +01:00
using std::list;
using std::rand;
2010-01-05 02:53:20 +01:00
using std::cout;
using std::endl;
namespace { // Subject of test
uint NUM_ELMS = 10;
typedef const char* CStr;
/**
2010-01-05 02:53:20 +01:00
* Explicit implementation of the IterSource interface (test dummy)
* Creates a random string and chops off a character on each iteration
2010-01-05 02:53:20 +01:00
*/
class TestSource
: public IterSource<CStr>
2010-01-05 04:10:23 +01:00
, noncopyable
2010-01-05 02:53:20 +01:00
{
2010-01-05 04:10:23 +01:00
string buffer_;
CStr current_;
virtual Pos
firstResult ()
{
current_ = buffer_.c_str();
ENSURE (current_);
return &current_;
}
virtual void
nextResult (Pos& pos)
{
if (pos && *pos && **pos)
++(*pos);
if (!(pos && *pos && **pos))
pos = 0;
}
2010-01-05 04:10:23 +01:00
public:
TestSource (uint num)
: buffer_(randStr (num))
, current_(0)
2010-01-05 04:10:23 +01:00
{
INFO (test, "created TestSource(\"%s\")", cStr(buffer_));
2010-01-05 04:10:23 +01:00
}
2010-01-05 02:53:20 +01:00
};
/** test dummy: simply wrapping an STL container
2010-01-05 02:53:20 +01:00
* and exposing a range as Lumiera Forward Iterator
*/
struct WrappedList
{
list<int> data_;
WrappedList(uint num)
{
while (num)
data_.push_back(num--);
}
typedef list<int>::iterator sourceIter;
typedef RangeIter<sourceIter> iterator;
iterator begin() { return iterator(data_.begin(),data_.end()); }
iterator end() { return iterator(); }
2010-01-05 02:53:20 +01:00
};
} // (END) impl test dummy containers
/******************************************************************
* @test create some (opaque) data sources,
* and then pull the data out by iteration.
* Demonstrates simple usage of the IterSource interface
2010-01-05 02:53:20 +01:00
*
* @see IterSource
* @see PlacementIndex::Table#_eachEntry_4check real world usage example
2010-01-05 02:53:20 +01:00
*/
class IterSource_test : public Test
{
typedef IterSource<int>::iterator IntIter;
typedef IterSource<CStr>::iterator StrIter;
typedef IterSource<string>::iterator StringIter;
2010-01-06 04:14:16 +01:00
typedef IterSource<Time>::iterator TimeIter;
typedef std::map<string,Time> TreeMap;
typedef std::tr1::unordered_map<string,Time> HashMap;
typedef std::multimap<int,int> TreeMultimap;
typedef std::tr1::unordered_multimap<int,int>HashMultimap;
2010-01-05 02:53:20 +01:00
virtual void
run (Arg arg)
{
if (0 < arg.size()) NUM_ELMS = lexical_cast<uint> (arg[0]);
2010-01-06 04:14:16 +01:00
verify_simpleIters();
verify_MapWrappers<TreeMap>();
verify_MapWrappers<HashMap>();
verify_MultimapIters<TreeMultimap>();
verify_MultimapIters<HashMultimap>();
2010-01-06 04:14:16 +01:00
}
void
verify_simpleIters()
{
2010-01-05 02:53:20 +01:00
// build the test data sources
WrappedList customList(NUM_ELMS);
TestSource dedicatedSource(NUM_ELMS);
list<int>& rawList(customList.data_);
2010-01-05 02:53:20 +01:00
IntIter iii (eachEntry (customList));
IntIter isi (eachEntry (rawList.begin(), rawList.end()));
StrIter cii (IterSource<CStr>::build(dedicatedSource));
2010-01-05 02:53:20 +01:00
CHECK (!isnil (iii));
CHECK (!isnil (isi));
CHECK (!isnil (cii));
2010-01-05 02:53:20 +01:00
pullOut (iii);
pullOut (isi);
2010-01-05 02:53:20 +01:00
pullOut (cii);
CHECK (!iii);
CHECK (!isi);
CHECK (!cii);
2010-01-05 02:53:20 +01:00
}
template<class IT>
void
pullOut (IT& iter)
2010-01-05 02:53:20 +01:00
{
for ( ; iter; ++iter )
2010-01-05 02:53:20 +01:00
cout << "::" << *iter;
cout << endl;
}
2010-01-06 04:14:16 +01:00
template<class MAP>
void
verify_MapWrappers()
{
MAP testMap;
for (uint i=0; i<NUM_ELMS; ++i)
testMap['X'+randStr(11)] = randTime();
StringIter sIter = eachMapKey (testMap);
TimeIter tIter = eachMapVal (testMap);
CHECK (sIter && tIter);
2010-01-06 04:14:16 +01:00
pullOut (sIter);
pullOut (tIter);
CHECK (!sIter && !tIter);
// The each-value-for-given-key-Iterator can be used for a map or multimap.
// In case of a map, it should yield exactly one result for existing values
// and zero results for non-existing mappings
StringIter justSomeKey = eachMapKey (testMap);
TimeIter correspondingVal = eachMapVal (testMap);
++justSomeKey;
++correspondingVal;
CHECK (justSomeKey);
TimeIter value4key = eachValForKey (testMap, "nonexistent key");
CHECK (!value4key);
value4key = eachValForKey (testMap, *justSomeKey);
CHECK (value4key);
CHECK (*value4key == *correspondingVal);
++value4key;
CHECK (!value4key);
2010-01-06 04:14:16 +01:00
}
template<class MAP>
void
verify_MultimapIters() ///< @see IterTools_test#verify_filterRepetitions
{
MAP testMap;
for (uint i=0; i<NUM_ELMS; ++i)
{
uint n = 1 + rand() % 100;
do testMap.insert (make_pair (i,n));
while (--n);
}
CHECK (NUM_ELMS < testMap.size(), "no repetition in test data??");
IntIter keys = eachDistinctKey (testMap);
cout << "distinct_keys";
CHECK (keys);
pullOut (keys);
CHECK (!keys);
cout << "values_4_key";
IntIter vals = eachValForKey (testMap, NUM_ELMS); // non-existent key
CHECK (!vals);
vals = eachValForKey (testMap, 0);
CHECK (vals);
pullOut (vals); // should produce anything between 1 and 100 entries
CHECK (!vals);
}
2010-01-05 02:53:20 +01:00
};
2010-01-05 02:53:20 +01:00
LAUNCHER (IterSource_test, "unit common");
}} // namespace lib::test