LUMIERA.clone/tests/library/iter-adapter-stl-test.cpp
Ichthyostega 39d614f55f Library: Testsuite maintenance
- SchedulerStress_test simply takes too long to complete (~4 min)
  and is thus aborted by the testrunner. Add a switch to allow for
  a quick smoke test.

- SchedulerCommutator_test aborts due to an unresolved design problem,
  which I marked as failure

- add some convenience methods for passing arguments to tests
2024-11-16 00:38:57 +01:00

244 lines
7.8 KiB
C++

/*
IterAdapterSTL(Test) - building various custom iterators for a given container
Copyright (C) Lumiera.org
2010, Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
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.
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.
* *****************************************************/
/** @file iter-adapter-stl-test.cpp
** unit test \ref IterAdapterSTL_test
*/
#include "lib/test/run.hpp"
#include "lib/test/test-coll.hpp"
#include "lib/format-cout.hpp"
#include "lib/util.hpp"
#include "lib/iter-adapter-stl.hpp"
#include <boost/lexical_cast.hpp>
#include <vector>
namespace lib {
namespace test{
using ::Test;
using boost::lexical_cast;
using util::isnil;
namespace iter = lib::iter_stl;
/** test an iterator: create it by calling a constructor function
* and then pull out all contents and print them to STDOUT */
#define TEST_ITER(_CTOR_, _ARG_) \
cout << STRINGIFY(_CTOR_) ;\
pullOut (_CTOR_ _ARG_) ;\
cout << endl;
/** print descriptive separator to STDOUT */
#define PRINT_FUNC(_F_NAME_, _F_TYPE_) \
cout << "-----"<<STRINGIFY(_F_NAME_)<<"---" << util::typeStr<_F_TYPE_>() << endl;
/********************************************************************//**
* @test verify some of the adapters to expose typical container
* usage patterns as Lumiera Forward Iterators.
* - distinct values from a sequence
* - keys and values of a map / multimap
* - distinct keys from a multimap
* - multimap values associated with a given key
* - snapshot of an iterator, to be retrieved as iterator
*
* @see RangeIter
* @see iter-adapter.hpp
* @see iter-adapter-stl.hpp
* @todo this test just pulls all the values from the iterator
* and the testsuite verifies the retrieved values.
* But for the hash-map, the order of the results
* is not guaranteed, and implementation dependent.
*/
class IterAdapterSTL_test : public Test
{
uint NUM_ELMS{0};
virtual void
run (Arg arg)
{
NUM_ELMS = firstVal (arg, 10);
checkDistinctValIter();
iterateMapKeyVal (getTestMap_int<MapII> (NUM_ELMS));
iterateMapKeyVal (getTestMap_int<HMapII> (NUM_ELMS));
iterateMapKeyVal (getTestMultiMap_int<MMapII> (NUM_ELMS));
iterateMapKeyVal (getTestMultiMap_int<HMMapII> (NUM_ELMS));
iterateValues4Key (getTestMultiMap_int<MMapII> (NUM_ELMS));
iterateValues4Key (getTestMultiMap_int<HMMapII> (NUM_ELMS));
checkIteratorSnapshot();
}
template<class MAP>
void
iterateMapKeyVal (MAP const& map)
{
PRINT_FUNC (iterateMapKeyVal, MAP);
TEST_ITER (iter::eachKey, (map));
TEST_ITER (iter::eachKey, (map.begin(), map.end()));
TEST_ITER (iter::eachVal, (map));
TEST_ITER (iter::eachVal, (map.begin(), map.end()));
TEST_ITER (iter::eachDistinctKey, (map));
}
template<class MMAP>
void
iterateValues4Key (MMAP const& mumap)
{
PRINT_FUNC (iterateValues4Key, MMAP);
TEST_ITER (iter::eachValForKey, (mumap, 0));
// non-existing key should yield empty iterator
CHECK (! iter::eachValForKey (mumap, NUM_ELMS));
}
void
checkDistinctValIter()
{
PRINT_FUNC (filter-distinct-values, VecI);
VecI vec;
TEST_ITER(iter::eachDistinct, (vec));
vec.push_back (1);
vec.push_back (1);
vec.push_back (1);
TEST_ITER(iter::eachDistinct, (vec));
vec.push_back (2);
vec.push_back (3);
vec.push_back (3);
vec.push_back (1);
TEST_ITER(iter::eachDistinct, (vec));
vec.push_back (1);
vec.push_back (1);
vec.push_back (1);
vec.push_back (1);
vec.push_back (1);
TEST_ITER(iter::eachDistinct, (vec));
}
void
checkIteratorSnapshot()
{
typedef VecI::iterator Iter;
typedef RangeIter<Iter> Range;
typedef iter::IterSnapshot<int> Snapshot;
VecI vec = getTestSeq_int<VecI> (NUM_ELMS);
Snapshot capture1 (vec.begin(), vec.end());
Range range_of_all (vec.begin(), vec.end());
Snapshot capture2 = iter::snapshot(range_of_all); // NOTE: when specifically taken this way,
CHECK (range_of_all); // snapshot doesn't affect given source iterator pos
CHECK (capture2); // (but WARNING, the IterSnapshot ctor itself is destructive)
CHECK (vec.begin() == range_of_all.getPos());
CHECK (vec.end() == range_of_all.getEnd());
CHECK (!isnil (vec));
// concurrent or intermittent modification
vec.clear();
CHECK (isnil (vec));
CHECK (vec.end() != range_of_all.getEnd()); // range_of_all is now corrupted
CHECK (capture1); // ...but the snapshots remain unaffected
CHECK (capture2);
CHECK (capture1 == capture2); // can compare snapshots, based on actual contents
vec.push_back(22);
vec.push_back(44);
Snapshot capture3 (vec.begin(), vec.end()); // take another snapshot from current contents
CHECK (capture3);
CHECK (capture3 != capture1);
CHECK (capture3 != capture2);
uint sum_should_be = (NUM_ELMS-1)*NUM_ELMS/2;
CHECK (sum_should_be == sumAll (capture1));
CHECK (!capture1); // this one is exhausted now
CHECK ( capture2); // ...but the others are really independent
CHECK ( capture3);
CHECK (capture1 != capture2); // comparison includes the current position
CHECK (sum_should_be == sumAll (capture2));
CHECK (!capture1);
CHECK (!capture2);
CHECK ( capture3);
CHECK (capture1 == capture2); // now again equal (both exhausted and equal contents)
CHECK (22+44 == sumAll (capture3));
CHECK (!capture1);
CHECK (!capture2);
CHECK (!capture3);
CHECK (capture1 == capture2); // all exhausted iterators count as "equal"
CHECK (capture3 == capture1); // this ensures the idiom while(pos != end) works
CHECK (capture3 == capture2);
}
template<class IT>
uint
sumAll (IT& it)
{
uint sum(0);
cout << "snapshot";
while (it)
{
cout << "-" << *it;
sum += *it;
++it;
}
cout << endl;
return sum;
}
};
LAUNCHER (IterAdapterSTL_test, "unit common");
}} // namespace lib::test