mirror of
https://github.com/reactos/reactos.git
synced 2025-02-28 19:32:59 +00:00
454 lines
12 KiB
C++
454 lines
12 KiB
C++
//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
|