From: Reinhard Pfau Date: Mon, 7 Apr 2008 15:25:09 +0000 (+0000) Subject: libi2ncommon: (reinhard) added containerfunc and some unit tests. X-Git-Tag: v2.6~186 X-Git-Url: http://developer.intra2net.com/git/?a=commitdiff_plain;h=57e78ccdefedee3960c12c26c847ae11371f27e0;p=libi2ncommon libi2ncommon: (reinhard) added containerfunc and some unit tests. --- diff --git a/src/Makefile.am b/src/Makefile.am index 1ddd7c8..3dd6b92 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -4,11 +4,16 @@ INCLUDES = -I$(top_srcdir)/src @LIBGETTEXT_CFLAGS@ @LIBICONV_CFLAGS@ $(all_inclu # the library search path. lib_LTLIBRARIES = libi2ncommon.la -include_HEADERS = userfunc.hxx daemonfunc.hxx pidfile.hxx logread.hxx insocketstream.hxx oftmpstream.hxx pipestream.hxx filefunc.hxx stringfunc.hxx timefunc.hxx ipfunc.hxx ip_type.hxx -libi2ncommon_la_SOURCES = userfunc.cpp daemonfunc.cpp pidfile.cpp logread.cpp oftmpstream.cpp ipfunc.cpp timefunc.cpp filefunc.cpp stringfunc.cpp +include_HEADERS = containerfunc.hpp daemonfunc.hxx filefunc.hxx \ + insocketstream.hxx ip_type.hxx ipfunc.hxx logread.hxx oftmpstream.hxx pidfile.hxx \ + pipestream.hxx stringfunc.hxx timefunc.hxx userfunc.hxx +libi2ncommon_la_SOURCES = containerfunc.cpp daemonfunc.cpp filefunc.cpp \ + ipfunc.cpp logread.cpp oftmpstream.cpp pidfile.cpp stringfunc.cpp timefunc.cpp \ + userfunc.cpp # Note: If you specify a:b:c as the version in the next line, # the library that is made has version (a-c).c.b. In this # example, the version is 2.1.2. (3:2:1) libi2ncommon_la_LIBADD = @LIBGETTEXT_LIBS@ @LIBICONV_LIBS@ +_SOURCES = containerfunc.hxx diff --git a/src/containerfunc.cpp b/src/containerfunc.cpp new file mode 100644 index 0000000..4e09116 --- /dev/null +++ b/src/containerfunc.cpp @@ -0,0 +1,8 @@ +/** @file + * + * (c) Copyright 2007-2008 by Intra2net AG + * + * info@intra2net.com + */ + +#include "containerfunc.hpp" diff --git a/src/containerfunc.hpp b/src/containerfunc.hpp new file mode 100644 index 0000000..7c7b459 --- /dev/null +++ b/src/containerfunc.hpp @@ -0,0 +1,408 @@ +/** @file + * @brief some helper for handling (STL) data structures. + * + * @author Reinhard Pfau \ + * + * (c) Copyright 2007-2008 by Intra2net AG + * + * info@intra2net.com + */ + +#ifndef _I2N_CONTAINERFUNC_HPP_ +#define _I2N_CONTAINERFUNC_HPP_ + +#include +#include +#include +#include +#include + + +namespace I2n { + + +/** + * convenience class to insert key-value pairs into a map. + */ +template +class MapFiller +{ + std::map & MapRef; + + public: + MapFiller( std::map & map_ref) + : MapRef(map_ref) + { + } + + MapFiller& operator () (const K& key, const V& value) + { + MapRef[key]= value; + return *this; + } + +}; // eo class MapFiller + + +/** + * convenience class to fill values into a container (using push_back). + */ +template class C= std::list > +class PushBackFiller +{ + C &CRef; + public: + PushBackFiller( C & c ) + : CRef(c) + {} + + PushBackFiller& operator () (const T& value) + { + CRef.push_back(value); + return *this; + } // eo operator () + +}; // eo class PushBackFiller + + +template< typename T, template class C > +PushBackFiller< T, C > get_push_back_filler( C< T >& c) +{ + return PushBackFiller< T, C >(c); +} // eo get_push_back_filler(C< T >&) + + +/** + * convenience class for transient construction of a container including values. + */ +template class C= std::list > +class TransientPushBackFiller +{ + C< T > MyC; + public: + typedef C< T > CType; + + TransientPushBackFiller() + {} + + TransientPushBackFiller& operator () (const T& value) + { + MyC.push_back(value); + return *this; + } // eo operator () + + operator CType () const { return MyC; } +}; // eo class TransientPushBackFiller + + +/** + * convenience class for transient construction of a map including values. + */ +template +class TransientMapFiller +{ + std::map Map; + + public: + typedef std::map< K, V > CType; + + + TransientMapFiller( ) + { + } + + TransientMapFiller& operator () (const K& key, const V& value) + { + Map[key]= value; + return *this; + } + + operator CType () const { return Map; } +}; // eo class MapFiller + + + + +/** + * returns the keys of a map as a list. + * @param the_map the map. + * @param the_keys the list where the keys are added to. + * @return @a true. + */ +template< typename K, typename V > +bool get_key_list( const std::map< K, V >& the_map, std::list< K >& the_keys ) +{ + for(typename std::map< K, V >::const_iterator it= the_map.begin(); + it != the_map.end(); + ++it ) + { + the_keys.push_back( it->first ); + } + return true; +} // eo get_key_list(const std::map< K,V >, std::list< K >&) + + +/** + * returns the keys of a map as a list. + * @param the_map the map. + * @return the list of keys. + */ +template< typename K, typename V > +std::list< K > get_key_list( const std::map< K, V>& the_map) +{ + std::list< K > result; + get_key_list(the_map, result); + return result; +} // eo get_key_list(const std::map< K,V >) + + +/** + * returns the keys of a map as a set. + * @param the_map the map. + * @param the_keys the set where the keys are added to. + * @return @a true. + */ +template< typename K, typename V > +bool get_key_set( const std::map< K, V >& the_map, std::set< K >& the_keys ) +{ + for(typename std::map< K, V >::const_iterator it= the_map.begin(); + it != the_map.end(); + ++it ) + { + the_keys.insert( it->first ); + } + return true; +} // eo get_key_set(const std::map< K,V >, std::set< K >&) + + +/** + * returns the keys of a map as a set. + * @param the_map the map. + * @return the set of keys. + */ +template< typename K, typename V > +std::list< K > get_key_set( const std::map< K, V>& the_map) +{ + std::set< K > result; + get_key_set(the_map, result); + return result; +} // eo get_key_set(const std::map< K,V >) + + +/** + * functor version of new(). + * can be used for deferred instantiation of objects. + */ +template< + typename T +> +struct New +{ + typedef T* result_type; + + result_type operator() () + { + return new T; + } + + template + result_type operator() (Arg1 arg1) + { + return new T(arg1); + } + + template + result_type operator() (Arg1 arg1,Arg2 arg2) + { + return new T(arg1,arg2); + } + + template + result_type operator() (Arg1 arg1,Arg2 arg2,Arg3 arg3) + { + return new T(arg1,arg2,arg3); + } + + template + result_type operator() (Arg1 arg1,Arg2 arg2,Arg3 arg3,Arg4 arg4) + { + return new T(arg1,arg2,arg3,arg4); + } + + template + result_type operator() (Arg1 arg1,Arg2 arg2,Arg3 arg3,Arg4 arg4,Arg5 arg5) + { + return new T(arg1,arg2,arg3,arg4,arg5); + } + +}; // eo struct New + + + + +/** + * functor version of boost::shared_ptr = new(). + * can be used for deferred instantiation of objects. + */ +template< + typename T +> +struct SharedPtrNew +{ + typedef boost::shared_ptr result_type; + + result_type operator() () + { + return result_type(new T); + } + + template + result_type operator() (Arg1 arg1) + { + return result_type(new T(arg1)); + } + + template + result_type operator() (Arg1 arg1,Arg2 arg2) + { + return result_type(new T(arg1,arg2)); + } + + template + result_type operator() (Arg1 arg1,Arg2 arg2,Arg3 arg3) + { + return result_type(new T(arg1,arg2,arg3)); + } + + template + result_type operator() (Arg1 arg1,Arg2 arg2,Arg3 arg3,Arg4 arg4) + { + return result_type(new T(arg1,arg2,arg3,arg4)); + } + + template + result_type operator() (Arg1 arg1,Arg2 arg2,Arg3 arg3,Arg4 arg4,Arg5 arg5) + { + return result_type(new T(arg1,arg2,arg3,arg4,arg5)); + } + +}; // eo struct SharedPtrNew + + + +/* +** classes holding a shared or weak pointer. +** designed to be used as policy classes... +** (but may be used for other purposes, too) +*/ + +template< + class X +> +class SharedOwnership +{ + public: + + SharedOwnership( boost::shared_ptr< X > ptr) + : StoredPtr(ptr) + {} + + + boost::shared_ptr< X > get_ptr() const { return StoredPtr; } + + public: + + boost::shared_ptr< X > StoredPtr; +}; // eo class SharedOwnership + + + +template< + class X +> +class WeakOwnership +{ + public: + + WeakOwnership( boost::shared_ptr< X > ptr) + : StoredPtr(ptr) + {} + + + boost::shared_ptr< X > get_ptr() const { return StoredPtr.lock(); } + + public: + + boost::weak_ptr< X > StoredPtr; +}; // eo class WeakOwnership + + + +/* +** NoOperation +** =========== +*/ + + +/** + * @brief the ultimate class for doing nothing :-) + * + * Even it sounds odd to have a functor class which is doing nothing it makes + * sense to use this class in some situations. + * + * One example is the usage as Deleter for shared pointers which "own" a pointer to + * a static object (i.e. it is not allowed to be really deleted...). Using this class + * as Deleter in these pointers enables us to use interfaces which expect a shared pointer + * even if we want(/must) to pass pointers to static objects. + */ +struct NoOperation +{ + NoOperation() {}; + + template< + typename Arg1 + > + NoOperation(Arg1) {} + + + template< + typename Arg1, typename Arg2 + > + NoOperation(Arg1, Arg2) {} + + + template< + typename Arg1, typename Arg2, typename Arg3 + > + NoOperation(Arg1, Arg2, Arg3) {} + + + void operator() () const {} + + + template< + typename Arg1 + > + void operator() (Arg1) const {} + + + template< + typename Arg1, typename Arg2 + > + void operator() (Arg1, Arg2) const {} + + + template< + typename Arg1, typename Arg2, typename Arg3 + > + void operator() (Arg1, Arg2, Arg3) const {} + + + +}; // eo struct NoOperation + + + +} // eo namespace I2n + +#endif diff --git a/src/containerfunc.hxx b/src/containerfunc.hxx new file mode 100644 index 0000000..5b1314b --- /dev/null +++ b/src/containerfunc.hxx @@ -0,0 +1,3 @@ +// for those who are used to .hxx files... + +#include "containerfunc.hpp" \ No newline at end of file diff --git a/test/Makefile.am b/test/Makefile.am index 4aa118b..ac4c0b3 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,7 +1,7 @@ INCLUDES = -I$(top_srcdir)/src @CPPUNIT_CFLAGS@ METASOURCES = AUTO check_PROGRAMS = test -test_SOURCES = stringfunc.cpp ip_range.cpp test.cpp +test_SOURCES = ip_range.cpp stringfunc.cpp test.cpp test_containerfunc.cpp test_LDADD = $(top_builddir)/src/libi2ncommon.la @CPPUNIT_LIBS@ TESTS = test diff --git a/test/stringfunc.cpp b/test/stringfunc.cpp index c2a1c96..043c58f 100644 --- a/test/stringfunc.cpp +++ b/test/stringfunc.cpp @@ -14,9 +14,11 @@ #include #include +#include using namespace std; using namespace CppUnit; +using namespace I2n; class stringfunc : public TestFixture { @@ -37,8 +39,28 @@ class stringfunc : public TestFixture CPPUNIT_TEST(imaputf7_to_utf8); CPPUNIT_TEST(utf8_to_imaputf7); + + CPPUNIT_TEST(TestTrim); + CPPUNIT_TEST(TestChomp); + CPPUNIT_TEST(TestSuffixFuncs); + CPPUNIT_TEST(TestPrefixFuncs); + CPPUNIT_TEST(TestLowerUpperFuncs); + + CPPUNIT_TEST(PairSplit1); + CPPUNIT_TEST(SplitString1); + CPPUNIT_TEST(SplitString2); + CPPUNIT_TEST(JoinString1); + + CPPUNIT_TEST(ConversionStringInt); + + CPPUNIT_TEST(HexConversion); + + CPPUNIT_TEST_SUITE_END(); + protected: + typedef std::list< std::string > StringList; + public: void smart_html_entites1() { @@ -132,6 +154,306 @@ class stringfunc : public TestFixture string output = utf8_to_utf7imap("Späm"); CPPUNIT_ASSERT_EQUAL(string("Sp&AOQ-m"), output); } + + /* + ** + */ + + void TestTrim() + { + std::string s("s1"); + trim_mod(s); + CPPUNIT_ASSERT_EQUAL( std::string("s1"), s ); + + s=" s2"; + trim_mod(s); + CPPUNIT_ASSERT_EQUAL( std::string("s2"), s ); + + s="s3 "; + trim_mod(s); + CPPUNIT_ASSERT_EQUAL( std::string("s3"), s ); + + s="::s4:s4::++--aa"; + trim_mod(s,":+-a"); + CPPUNIT_ASSERT_EQUAL( std::string("s4:s4"), s); + + /* non modifying version */ + + s= "s1"; + CPPUNIT_ASSERT_EQUAL( std::string("s1"), trim(s) ); + + s=" s2"; + CPPUNIT_ASSERT_EQUAL( std::string("s2"), trim(s) ); + CPPUNIT_ASSERT_EQUAL( std::string(" s2"), s ); + + s="s3 "; + CPPUNIT_ASSERT_EQUAL( std::string("s3"), trim(s) ); + CPPUNIT_ASSERT_EQUAL( std::string("s3 "), s ); + + s="::s4:s4::++--aa"; + CPPUNIT_ASSERT_EQUAL( std::string("s4:s4"), trim(s,":+-a") ); + } // eo TestTrim() + + + + void TestChomp() + { + std::string s("s1"); + + chomp_mod(s); + CPPUNIT_ASSERT_EQUAL( std::string("s1"), s ); + + s="s2\n"; + chomp_mod(s); + CPPUNIT_ASSERT_EQUAL( std::string("s2"), s ); + + s="s3:"; + chomp_mod(s,":"); + CPPUNIT_ASSERT_EQUAL( std::string("s3"), s ); + + s=":s4::"; + chomp_mod(s,"s:"); + CPPUNIT_ASSERT_EQUAL( std::string(":s4:"), s); + + /* non modifiying versions */ + s= "s1"; + + CPPUNIT_ASSERT_EQUAL( std::string("s1"), chomp(s) ); + + s="s2\n"; + CPPUNIT_ASSERT_EQUAL( std::string("s2"), chomp(s) ); + CPPUNIT_ASSERT_EQUAL( std::string("s2\n"), s); + + s="s3:"; + CPPUNIT_ASSERT_EQUAL( std::string("s3"), chomp(s,":") ); + CPPUNIT_ASSERT_EQUAL( std::string("s3:"), s); + + s=":s4::"; + CPPUNIT_ASSERT_EQUAL( std::string(":s4:"), chomp(s,"s:") ); + CPPUNIT_ASSERT_EQUAL( std::string(":s4::"), s); + } // eo TestChomp() + + + + void TestSuffixFuncs() + { + std::string s1("12.cpp"); + + CPPUNIT_ASSERT_EQUAL( true, has_suffix(s1,".cpp") ); + CPPUNIT_ASSERT_EQUAL( true, has_suffix(s1,"pp") ); + CPPUNIT_ASSERT_EQUAL( false, has_suffix(s1,"hpp") ); + CPPUNIT_ASSERT_EQUAL( false, has_suffix(s1,"cp") ); + CPPUNIT_ASSERT_EQUAL( false, has_suffix(s1,"") ); + + std::string s1c1= remove_suffix(s1,".cpp"); + CPPUNIT_ASSERT_EQUAL( std::string("12"), s1c1 ); + + std::string s1c2= remove_suffix(s1,"p"); + CPPUNIT_ASSERT_EQUAL( std::string("12.cp"), s1c2 ); + + std::string s1c3= remove_suffix(s1,"cp"); + CPPUNIT_ASSERT_EQUAL( std::string("12.cpp"), s1c3 ); + + std::string s2(".cpp"); + CPPUNIT_ASSERT_EQUAL( true, has_suffix(s2,".cpp") ); + + std::string s2c1= remove_suffix(s2,".cpp"); + CPPUNIT_ASSERT_EQUAL( std::string(""), s2c1 ); + + } // eo TestSuffixFuncs() + + + + void TestPrefixFuncs() + { + std::string s1("12.cpp"); + + CPPUNIT_ASSERT_EQUAL( true, has_prefix(s1,"12") ); + CPPUNIT_ASSERT_EQUAL( true, has_prefix(s1, "1") ); + CPPUNIT_ASSERT_EQUAL( false, has_prefix(s1, "2") ); + CPPUNIT_ASSERT_EQUAL( false, has_prefix(s1, "") ); + + std::string s1c1= remove_prefix(s1, "12"); + CPPUNIT_ASSERT_EQUAL( std::string(".cpp"), s1c1); + } // eo TestPrefixFuncs() + + + + void TestLowerUpperFuncs() + { + std::string u1("CASE CONVERSION TEST.."); + std::string l1("case conversion test.."); + + std::string test1(l1); + + to_upper_mod(test1); + CPPUNIT_ASSERT_EQUAL( u1, test1 ); + + to_lower_mod(test1); + CPPUNIT_ASSERT_EQUAL( l1, test1 ); + + + CPPUNIT_ASSERT_EQUAL( u1, to_upper(l1) ); + CPPUNIT_ASSERT_EQUAL( l1, to_lower(u1) ); + } // eo TestLowerUpper + + + + void PairSplit1() + { + StringList str_list; + get_push_back_filler(str_list) + ("a=11")("a= 11")("a =11 ")("a = 11 ")(" a = 11 ") + ; + CPPUNIT_ASSERT_EQUAL( 5u, str_list.size() ); + for(StringList::iterator it= str_list.begin(); + it != str_list.end(); + ++it) + { + std::string key, value; + bool res= pair_split( *it, key, value); + + CPPUNIT_ASSERT_EQUAL( true , res ); + CPPUNIT_ASSERT_EQUAL( std::string("a"), key ); + CPPUNIT_ASSERT_EQUAL( std::string("11"), value ); + } + + std::string key, value; + bool res; + + res= pair_split(" 1 : 2 ", key, value, ':'); + CPPUNIT_ASSERT_EQUAL( true, res ); + CPPUNIT_ASSERT_EQUAL( std::string("1"), key); + CPPUNIT_ASSERT_EQUAL( std::string("2"), value); + } // eo PairSplit1 + + + + void SplitString1() + { + std::string block( + "Zeile 1\n" + "++Zeile-2--\n" + "Zeile 3\n" + "\n" + "Zeile 5\n" + ); + + StringList list1; + + split_string(block, list1, "\n"); + // since the blocks ends with \n we should have 6 lines (the last one empty): + CPPUNIT_ASSERT_EQUAL( 6u, list1.size() ); + CPPUNIT_ASSERT_EQUAL( std::string(), list1.back() ); + CPPUNIT_ASSERT_EQUAL( std::string("Zeile 1"), list1.front() ); + + StringList list2; + + split_string(block, list2, "\n", true); + + // now we omitted empty lines, now we should have only 4 lines left: + CPPUNIT_ASSERT_EQUAL( 4u, list2.size() ); + CPPUNIT_ASSERT_EQUAL( std::string("Zeile 5"), list2.back() ); + CPPUNIT_ASSERT_EQUAL( std::string("Zeile 1"), list2.front() ); + + list2= split_string(block, "\n", true, "+-"); + + // again, we omitted empty lines, but also trimmed away leading and trailing "+" and "-" + CPPUNIT_ASSERT_EQUAL( 4u, list2.size() ); + CPPUNIT_ASSERT_EQUAL( std::string("Zeile 5"), list2.back() ); + CPPUNIT_ASSERT_EQUAL( std::string("Zeile 1"), list2.front() ); + CPPUNIT_ASSERT_EQUAL( std::string("Zeile-2"), *(++list2.begin()) ); + } // eo SplitString1 + + + + void SplitString2() + { + std::string line("172.16.0.0/16 dev eth0 scope link src 172.16.1.111"); + + StringList list1; + + split_string(line, list1, " ", true, Whitespaces); + + CPPUNIT_ASSERT_EQUAL( 7u, list1.size() ); + + } // eo SplitString2 + + + + void JoinString1() + { + std::list< std::string > parts; + get_push_back_filler(parts)("1")("2")("drei"); + + std::string joined_string= join_string(parts,"/"); + // we should have slashes between the strings: + CPPUNIT_ASSERT_EQUAL( std::string("1/2/drei") , joined_string ); + + parts.push_back( std::string() ); + joined_string= join_string(parts,"/"); + // now we should have an additional trailing slash: + CPPUNIT_ASSERT_EQUAL( std::string("1/2/drei/") , joined_string ); + + parts.push_front( std::string() ); + joined_string= join_string(parts,"/"); + // now we should have an additional leading slash: + CPPUNIT_ASSERT_EQUAL( std::string("/1/2/drei/") , joined_string ); + + } // eo JoinString1 + + + + void ConversionStringInt() + { + std::string s1("24"); + std::string s1x("25x"); + int i1=0; + bool res= false; + + i1= string_to(s1); + CPPUNIT_ASSERT_EQUAL( 24, i1 ); + i1= string_to(s1x); + CPPUNIT_ASSERT_EQUAL( 25, i1 ); + + res= string_to(s1,i1); + CPPUNIT_ASSERT_EQUAL( true, res ); + CPPUNIT_ASSERT_EQUAL( 24, i1 ); + + res= string_to(s1x,i1); + CPPUNIT_ASSERT_EQUAL( false, res ); + + std::string ss1= to_string( 24 ); + CPPUNIT_ASSERT_EQUAL( std::string("24"), ss1); + + } // eo ConversionStringInt() + + + + void HexConversion() + { + std::string hex1("49324E"); + std::string bin1("I2N"); + + CPPUNIT_ASSERT_EQUAL( hex1, convert_binary_to_hex(bin1,true) ); + CPPUNIT_ASSERT_EQUAL( bin1, convert_hex_to_binary(hex1) ); + CPPUNIT_ASSERT_EQUAL( to_lower(hex1), convert_binary_to_hex(bin1) ); + + std::string hex2("0001"); + std::string hex2a("00 01"); + std::string hex2b("00:01"); + std::string bin2("\0\1",2); + + CPPUNIT_ASSERT_EQUAL( hex2, convert_binary_to_hex(bin2) ); + CPPUNIT_ASSERT_EQUAL( bin2, convert_hex_to_binary(hex2) ); + CPPUNIT_ASSERT_EQUAL( bin2, convert_hex_to_binary(hex2a) ); + CPPUNIT_ASSERT_EQUAL( bin2, convert_hex_to_binary(hex2b) ); + + CPPUNIT_ASSERT_THROW( convert_hex_to_binary("01 kein hex"), std::runtime_error); + } // eo HexConversion() + + + }; CPPUNIT_TEST_SUITE_REGISTRATION(stringfunc); diff --git a/test/test_containerfunc.cpp b/test/test_containerfunc.cpp new file mode 100644 index 0000000..585df32 --- /dev/null +++ b/test/test_containerfunc.cpp @@ -0,0 +1,123 @@ +/** @file + * + * tests for the module "containerfunc" + * + * (c) Copyright 2007-2008 by Intra2net AG + * + * info@intra2net.com + */ + +//#define NOISEDEBUG + +#include +#include +#include +#include + +#include +#include +#include + +#include + + + +using namespace I2n; + +using namespace CppUnit; + +namespace { + + +} // eo namespace + + +class TestContainerFunc : public TestFixture +{ + CPPUNIT_TEST_SUITE(TestContainerFunc); + + // data tools: + + CPPUNIT_TEST(FillStringVector); + CPPUNIT_TEST(RetrieveMapKeys); + + CPPUNIT_TEST_SUITE_END(); + + protected: + + + public: + + void setUp() + { + } // eo setUp + + + void tearDown() + { + } // eo tearDown + + + /* + * the tests: + */ + + + + void FillStringVector() + { + std::vector< std::string > v; + CPPUNIT_ASSERT_EQUAL( true, v.empty() ); + + get_push_back_filler(v)("1")("2")("drei"); + + CPPUNIT_ASSERT_EQUAL( 3u, v.size() ); + CPPUNIT_ASSERT_EQUAL( std::string("2"), v[1]); + CPPUNIT_ASSERT_EQUAL( std::string("drei"), v[2]); + CPPUNIT_ASSERT_EQUAL( std::string("1"), v[0]); + + get_push_back_filler(v)("i3")("i4"); + + CPPUNIT_ASSERT_EQUAL( 5u, v.size() ); + CPPUNIT_ASSERT_EQUAL( std::string("i4"), v[4]); + CPPUNIT_ASSERT_EQUAL( std::string("i3"), v[3]); + } // eo FillStringVector + + + + void RetrieveMapKeys() + { + std::map< int, std::string > map1; + std::list< int > key_list; + std::set< int > key_set; + + { + MapFiller< int, std::string > fill(map1); + fill + (1, "one") + (2, "two") + (3, "three" ) + (4, "many..." ) + ; + } + CPPUNIT_ASSERT_EQUAL( 4u, map1.size() ); + + get_key_list(map1, key_list); + CPPUNIT_ASSERT_EQUAL( 4u, key_list.size() ); + CPPUNIT_ASSERT( std::find(key_list.begin(), key_list.end(), 1) != key_list.end() ); + CPPUNIT_ASSERT( std::find(key_list.begin(), key_list.end(), 2) != key_list.end() ); + CPPUNIT_ASSERT( std::find(key_list.begin(), key_list.end(), 3) != key_list.end() ); + CPPUNIT_ASSERT( std::find(key_list.begin(), key_list.end(), 4) != key_list.end() ); + + get_key_set(map1, key_set); + CPPUNIT_ASSERT_EQUAL( 4u, key_set.size() ); + CPPUNIT_ASSERT( key_set.find(1) != key_set.end() ); + CPPUNIT_ASSERT( key_set.find(2) != key_set.end() ); + CPPUNIT_ASSERT( key_set.find(3) != key_set.end() ); + CPPUNIT_ASSERT( key_set.find(4) != key_set.end() ); + } // RetrieveMapKeys() + + +}; // eo class TestContainerFunc + +CPPUNIT_TEST_SUITE_REGISTRATION(TestContainerFunc);