//Has to be first for StackAllocator swap overload to be taken //into account (at least using GCC 4.0.1) #include "stack_allocator.h" #include <map> #include <algorithm> #include "cppunit/cppunit_proxy.h" #if !defined (STLPORT) || defined(_STLP_USE_NAMESPACES) using namespace std; #endif // // TestCase class // class MapTest : public CPPUNIT_NS::TestCase { CPPUNIT_TEST_SUITE(MapTest); CPPUNIT_TEST(map1); CPPUNIT_TEST(mmap1); CPPUNIT_TEST(mmap2); CPPUNIT_TEST(iterators); CPPUNIT_TEST(equal_range); CPPUNIT_TEST(allocator_with_state); #if !defined (STLPORT) || !defined (_STLP_USE_CONTAINERS_EXTENSION) CPPUNIT_IGNORE; #endif CPPUNIT_TEST(template_methods); CPPUNIT_TEST_SUITE_END(); protected: void map1(); void mmap1(); void mmap2(); void iterators(); void equal_range(); void allocator_with_state(); void template_methods(); }; CPPUNIT_TEST_SUITE_REGISTRATION(MapTest); // // tests implementation // void MapTest::map1() { typedef map<char, int, less<char> > maptype; maptype m; // Store mappings between roman numerals and decimals. m['l'] = 50; m['x'] = 20; // Deliberate mistake. m['v'] = 5; m['i'] = 1; // cout << "m['x'] = " << m['x'] << endl; CPPUNIT_ASSERT( m['x']== 20 ); m['x'] = 10; // Correct mistake. CPPUNIT_ASSERT( m['x']== 10 ); CPPUNIT_ASSERT( m['z']== 0 ); //cout << "m['z'] = " << m['z'] << endl; // Note default value is added. CPPUNIT_ASSERT( m.count('z') == 1 ); //cout << "m.count('z') = " << m.count('z') << endl; pair<maptype::iterator, bool> p = m.insert(pair<const char, int>('c', 100)); CPPUNIT_ASSERT( p.second ); CPPUNIT_ASSERT( p.first != m.end() ); CPPUNIT_ASSERT( (*p.first).first == 'c' ); CPPUNIT_ASSERT( (*p.first).second == 100 ); p = m.insert(pair<const char, int>('c', 100)); CPPUNIT_ASSERT( !p.second ); // already existing pair CPPUNIT_ASSERT( p.first != m.end() ); CPPUNIT_ASSERT( (*p.first).first == 'c' ); CPPUNIT_ASSERT( (*p.first).second == 100 ); } void MapTest::mmap1() { typedef multimap<char, int, less<char> > mmap; mmap m; CPPUNIT_ASSERT(m.count('X')==0); m.insert(pair<const char, int>('X', 10)); // Standard way. CPPUNIT_ASSERT(m.count('X')==1); m.insert(pair<const char, int>('X', 20)); // jbuck: standard way CPPUNIT_ASSERT(m.count('X')==2); m.insert(pair<const char, int>('Y', 32)); // jbuck: standard way mmap::iterator i = m.find('X'); // Find first match. #ifndef _STLP_CONST # define _STLP_CONST const #endif pair<_STLP_CONST char, int> p('X', 10); CPPUNIT_ASSERT(*i == p); CPPUNIT_ASSERT((*i).first == 'X'); CPPUNIT_ASSERT((*i).second == 10); i++; CPPUNIT_ASSERT((*i).first == 'X'); CPPUNIT_ASSERT((*i).second == 20); i++; CPPUNIT_ASSERT((*i).first == 'Y'); CPPUNIT_ASSERT((*i).second == 32); i++; CPPUNIT_ASSERT(i == m.end()); size_t count = m.erase('X'); CPPUNIT_ASSERT(count==2); } void MapTest::mmap2() { typedef pair<const int, char> pair_type; pair_type p1(3, 'c'); pair_type p2(6, 'f'); pair_type p3(1, 'a'); pair_type p4(2, 'b'); pair_type p5(3, 'x'); pair_type p6(6, 'f'); typedef multimap<int, char, less<int> > mmap; pair_type array [] = { p1, p2, p3, p4, p5, p6 }; mmap m(array + 0, array + 6); mmap::iterator i; i = m.lower_bound(3); CPPUNIT_ASSERT((*i).first==3); CPPUNIT_ASSERT((*i).second=='c'); i = m.upper_bound(3); CPPUNIT_ASSERT((*i).first==6); CPPUNIT_ASSERT((*i).second=='f'); } void MapTest::iterators() { typedef map<int, char, less<int> > int_map; int_map imap; { int_map::iterator ite(imap.begin()); int_map::const_iterator cite(imap.begin()); CPPUNIT_ASSERT( ite == cite ); CPPUNIT_ASSERT( !(ite != cite) ); CPPUNIT_ASSERT( cite == ite ); CPPUNIT_ASSERT( !(cite != ite) ); } typedef multimap<int, char, less<int> > mmap; typedef mmap::value_type pair_type; pair_type p1(3, 'c'); pair_type p2(6, 'f'); pair_type p3(1, 'a'); pair_type p4(2, 'b'); pair_type p5(3, 'x'); pair_type p6(6, 'f'); pair_type array [] = { p1, p2, p3, p4, p5, p6 }; mmap m(array+0, array + 6); { mmap::iterator ite(m.begin()); mmap::const_iterator cite(m.begin()); //test compare between const_iterator and iterator CPPUNIT_ASSERT( ite == cite ); CPPUNIT_ASSERT( !(ite != cite) ); CPPUNIT_ASSERT( cite == ite ); CPPUNIT_ASSERT( !(cite != ite) ); } #if 0 /* * A check that map and multimap iterators are NOT comparable * the following code should generate a compile time error */ { int_map::iterator mite(imap.begin()); int_map::const_iterator mcite(imap.begin()); mmap::iterator mmite(m.begin()); mmap::const_iterator mmcite(m.begin()); CPPUNIT_ASSERT( !(mite == mmite) ); CPPUNIT_ASSERT( !(mcite == mmcite) ); CPPUNIT_ASSERT( mite != mmite ); CPPUNIT_ASSERT( mcite != mmcite ); CPPUNIT_ASSERT( !(mite == mmcite) ); CPPUNIT_ASSERT( !(mite == mmcite) ); CPPUNIT_ASSERT( mite != mmcite ); CPPUNIT_ASSERT( mite != mmcite ); } #endif mmap::reverse_iterator ri = m.rbegin(); CPPUNIT_ASSERT( ri != m.rend() ); CPPUNIT_ASSERT( ri == m.rbegin() ); CPPUNIT_ASSERT( (*ri).first == 6 ); CPPUNIT_ASSERT( (*ri++).second == 'f' ); CPPUNIT_ASSERT( (*ri).first == 6 ); CPPUNIT_ASSERT( (*ri).second == 'f' ); mmap const& cm = m; mmap::const_reverse_iterator rci = cm.rbegin(); CPPUNIT_ASSERT( rci != cm.rend() ); CPPUNIT_ASSERT( (*rci).first == 6 ); CPPUNIT_ASSERT( (*rci++).second == 'f' ); CPPUNIT_ASSERT( (*rci).first == 6 ); CPPUNIT_ASSERT( (*rci).second == 'f' ); } void MapTest::equal_range() { typedef map<char, int, less<char> > maptype; { maptype m; m['x'] = 10; pair<maptype::iterator, maptype::iterator> ret; ret = m.equal_range('x'); CPPUNIT_ASSERT( ret.first != ret.second ); CPPUNIT_ASSERT( (*(ret.first)).first == 'x' ); CPPUNIT_ASSERT( (*(ret.first)).second == 10 ); CPPUNIT_ASSERT( ++(ret.first) == ret.second ); } { { maptype m; maptype::iterator i = m.lower_bound( 'x' ); CPPUNIT_ASSERT( i == m.end() ); i = m.upper_bound( 'x' ); CPPUNIT_ASSERT( i == m.end() ); pair<maptype::iterator, maptype::iterator> ret; ret = m.equal_range('x'); CPPUNIT_ASSERT( ret.first == ret.second ); CPPUNIT_ASSERT( ret.first == m.end() ); } { const maptype m; pair<maptype::const_iterator, maptype::const_iterator> ret; ret = m.equal_range('x'); CPPUNIT_ASSERT( ret.first == ret.second ); CPPUNIT_ASSERT( ret.first == m.end() ); } } } void MapTest::allocator_with_state() { char buf1[1024]; StackAllocator<pair<const int, int> > stack1(buf1, buf1 + sizeof(buf1)); char buf2[1024]; StackAllocator<pair<const int, int> > stack2(buf2, buf2 + sizeof(buf2)); { typedef map<int, int, less<int>, StackAllocator<pair<const int, int> > > MapInt; less<int> intLess; MapInt mint1(intLess, stack1); int i; for (i = 0; i < 5; ++i) mint1.insert(MapInt::value_type(i, i)); MapInt mint1Cpy(mint1); MapInt mint2(intLess, stack2); for (; i < 10; ++i) mint2.insert(MapInt::value_type(i, i)); MapInt mint2Cpy(mint2); mint1.swap(mint2); CPPUNIT_ASSERT( mint1.get_allocator().swaped() ); CPPUNIT_ASSERT( mint2.get_allocator().swaped() ); CPPUNIT_ASSERT( mint1 == mint2Cpy ); CPPUNIT_ASSERT( mint2 == mint1Cpy ); CPPUNIT_ASSERT( mint1.get_allocator() == stack2 ); CPPUNIT_ASSERT( mint2.get_allocator() == stack1 ); } CPPUNIT_ASSERT( stack1.ok() ); CPPUNIT_ASSERT( stack2.ok() ); } struct Key { Key() : m_data(0) {} explicit Key(int data) : m_data(data) {} int m_data; }; struct KeyCmp { bool operator () (Key lhs, Key rhs) const { return lhs.m_data < rhs.m_data; } bool operator () (Key lhs, int rhs) const { return lhs.m_data < rhs; } bool operator () (int lhs, Key rhs) const { return lhs < rhs.m_data; } }; struct KeyCmpPtr { bool operator () (Key const volatile *lhs, Key const volatile *rhs) const { return (*lhs).m_data < (*rhs).m_data; } bool operator () (Key const volatile *lhs, int rhs) const { return (*lhs).m_data < rhs; } bool operator () (int lhs, Key const volatile *rhs) const { return lhs < (*rhs).m_data; } }; void MapTest::template_methods() { #if defined (STLPORT) && defined (_STLP_USE_CONTAINERS_EXTENSION) { typedef map<Key, int, KeyCmp> Container; typedef Container::value_type value; Container cont; cont.insert(value(Key(1), 1)); cont.insert(value(Key(2), 2)); cont.insert(value(Key(3), 3)); cont.insert(value(Key(4), 4)); CPPUNIT_ASSERT( cont.count(Key(1)) == 1 ); CPPUNIT_ASSERT( cont.count(1) == 1 ); CPPUNIT_ASSERT( cont.count(5) == 0 ); CPPUNIT_ASSERT( cont.find(2) != cont.end() ); CPPUNIT_ASSERT( cont.lower_bound(2) != cont.end() ); CPPUNIT_ASSERT( cont.upper_bound(2) != cont.end() ); CPPUNIT_ASSERT( cont.equal_range(2) != make_pair(cont.begin(), cont.end()) ); Container const& ccont = cont; CPPUNIT_ASSERT( ccont.find(2) != ccont.end() ); CPPUNIT_ASSERT( ccont.lower_bound(2) != ccont.end() ); CPPUNIT_ASSERT( ccont.upper_bound(2) != ccont.end() ); CPPUNIT_ASSERT( ccont.equal_range(2) != make_pair(ccont.end(), ccont.end()) ); } { typedef map<Key*, int, KeyCmpPtr> Container; typedef Container::value_type value; Container cont; Key key1(1), key2(2), key3(3), key4(4); cont.insert(value(&key1, 1)); cont.insert(value(&key2, 2)); cont.insert(value(&key3, 3)); cont.insert(value(&key4, 4)); CPPUNIT_ASSERT( cont.count(1) == 1 ); CPPUNIT_ASSERT( cont.count(5) == 0 ); CPPUNIT_ASSERT( cont.find(2) != cont.end() ); CPPUNIT_ASSERT( cont.lower_bound(2) != cont.end() ); CPPUNIT_ASSERT( cont.upper_bound(2) != cont.end() ); CPPUNIT_ASSERT( cont.equal_range(2) != make_pair(cont.begin(), cont.end()) ); Container const& ccont = cont; CPPUNIT_ASSERT( ccont.find(2) != ccont.end() ); CPPUNIT_ASSERT( ccont.lower_bound(2) != ccont.end() ); CPPUNIT_ASSERT( ccont.upper_bound(2) != ccont.end() ); CPPUNIT_ASSERT( ccont.equal_range(2) != make_pair(ccont.begin(), ccont.end()) ); } { typedef multimap<Key, int, KeyCmp> Container; typedef Container::value_type value; Container cont; cont.insert(value(Key(1), 1)); cont.insert(value(Key(2), 2)); cont.insert(value(Key(3), 3)); cont.insert(value(Key(4), 4)); CPPUNIT_ASSERT( cont.count(Key(1)) == 1 ); CPPUNIT_ASSERT( cont.count(1) == 1 ); CPPUNIT_ASSERT( cont.count(5) == 0 ); CPPUNIT_ASSERT( cont.find(2) != cont.end() ); CPPUNIT_ASSERT( cont.lower_bound(2) != cont.end() ); CPPUNIT_ASSERT( cont.upper_bound(2) != cont.end() ); CPPUNIT_ASSERT( cont.equal_range(2) != make_pair(cont.begin(), cont.end()) ); Container const& ccont = cont; CPPUNIT_ASSERT( ccont.find(2) != ccont.end() ); CPPUNIT_ASSERT( ccont.lower_bound(2) != ccont.end() ); CPPUNIT_ASSERT( ccont.upper_bound(2) != ccont.end() ); CPPUNIT_ASSERT( ccont.equal_range(2) != make_pair(ccont.end(), ccont.end()) ); } { typedef multimap<Key const volatile*, int, KeyCmpPtr> Container; typedef Container::value_type value; Container cont; Key key1(1), key2(2), key3(3), key4(4); cont.insert(value(&key1, 1)); cont.insert(value(&key2, 2)); cont.insert(value(&key3, 3)); cont.insert(value(&key4, 4)); CPPUNIT_ASSERT( cont.count(1) == 1 ); CPPUNIT_ASSERT( cont.count(5) == 0 ); CPPUNIT_ASSERT( cont.find(2) != cont.end() ); CPPUNIT_ASSERT( cont.lower_bound(2) != cont.end() ); CPPUNIT_ASSERT( cont.upper_bound(2) != cont.end() ); CPPUNIT_ASSERT( cont.equal_range(2) != make_pair(cont.begin(), cont.end()) ); Container const& ccont = cont; CPPUNIT_ASSERT( ccont.find(2) != ccont.end() ); CPPUNIT_ASSERT( ccont.lower_bound(2) != ccont.end() ); CPPUNIT_ASSERT( ccont.upper_bound(2) != ccont.end() ); CPPUNIT_ASSERT( ccont.equal_range(2) != make_pair(ccont.begin(), ccont.end()) ); } #endif } #if !defined (STLPORT) || \ !defined (_STLP_USE_PTR_SPECIALIZATIONS) || defined (_STLP_CLASS_PARTIAL_SPECIALIZATION) # if !defined (__DMC__) /* Simple compilation test: Check that nested types like iterator * can be access even if type used to instanciate container is not * yet completely defined. */ class IncompleteClass { map<IncompleteClass, IncompleteClass> instances; typedef map<IncompleteClass, IncompleteClass>::iterator it; multimap<IncompleteClass, IncompleteClass> minstances; typedef multimap<IncompleteClass, IncompleteClass>::iterator mit; }; # endif #endif