lumiera_/tests/library/iter-adapter-stl-test.cpp
Ichthyostega 806db414dd Copyright: clarify and simplify the file headers
* Lumiera source code always was copyrighted by individual contributors
 * there is no entity "Lumiera.org" which holds any copyrights
 * Lumiera source code is provided under the GPL Version 2+

== Explanations ==
Lumiera as a whole is distributed under Copyleft, GNU General Public License Version 2 or above.
For this to become legally effective, the ''File COPYING in the root directory is sufficient.''

The licensing header in each file is not strictly necessary, yet considered good practice;
attaching a licence notice increases the likeliness that this information is retained
in case someone extracts individual code files. However, it is not by the presence of some
text, that legally binding licensing terms become effective; rather the fact matters that a
given piece of code was provably copyrighted and published under a license. Even reformatting
the code, renaming some variables or deleting parts of the code will not alter this legal
situation, but rather creates a derivative work, which is likewise covered by the GPL!

The most relevant information in the file header is the notice regarding the
time of the first individual copyright claim. By virtue of this initial copyright,
the first author is entitled to choose the terms of licensing. All further
modifications are permitted and covered by the License. The specific wording
or format of the copyright header is not legally relevant, as long as the
intention to publish under the GPL remains clear. The extended wording was
based on a recommendation by the FSF. It can be shortened, because the full terms
of the license are provided alongside the distribution, in the file COPYING.
2024-11-17 23:42:55 +01:00

235 lines
7.4 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
IterAdapterSTL(Test) - building various custom iterators for a given container
Copyright (C)
2010, Hermann Vosseler <Ichthyostega@web.de>
  **Lumiera** 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. See the file COPYING for further details.
* *****************************************************************/
/** @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