Loki/test/RegressionTest/AssocVectorTest.h
syntheticpp 1ca2df042d GCC 4.3 fixes: at least compile
git-svn-id: svn://svn.code.sf.net/p/loki-lib/code/trunk@897 7ec92016-0320-0410-acc4-a06ded1c099a
2008-08-08 22:53:19 +00:00

450 lines
13 KiB
C++

///////////////////////////////////////////////////////////////////////////////
// Unit Test for Loki
//
// Copyright Terje Slettebø and Pavel Vozenilek 2002.
//
// Permission to use, copy, modify, and distribute this software for any
// purpose is hereby granted without fee, provided that this copyright and
// permissions notice appear in all copies and derivatives.
//
// This software is provided "as is" without express or implied warranty.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef ASSOCVECTORTEST_H
#define ASSOCVECTORTEST_H
// $Id$
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <loki/AssocVector.h>
#include "UnitTest.h"
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__MWERKS__)
#define C_Namespace
#else
#define C_Namespace std
#endif
///////////////////////////////////////////////////////////////////////////////
// AssocVectorTest
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// STL compatible allocator
///////////////////////////////////////////////////////////////////////////////
template <class T> class TestAllocator : public std::allocator<T>
{
public:
typedef T value_type;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef C_Namespace::size_t size_type;
typedef C_Namespace::ptrdiff_t difference_type;
template <class U>
struct rebind { typedef TestAllocator<U> other; };
TestAllocator() {}
TestAllocator(const TestAllocator&) {}
#if !(defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__MWERKS__))
template <class U>
TestAllocator(const TestAllocator<U>&) {}
#endif
~TestAllocator() {}
pointer address(reference x) const { return &x; }
const_pointer address(const_reference x) const {
return x;
}
pointer allocate(size_type n, const_pointer = 0) {
return static_cast<pointer>(::operator new(n * sizeof(T)));
}
void deallocate(pointer p, size_type size) {
::operator delete(p);
}
size_type max_size() const {
return static_cast<size_type>(-1) / sizeof(T);
}
void construct(pointer p, const value_type& x) {
new(p) value_type(x);
}
void destroy(pointer p) {
#ifndef _USE_OLD_RW_STL // ?? failed to compile when RogueWave is enabled !?!
p->~value_type();
#endif
}
private:
void operator=(const TestAllocator&);
};
///////////////////////////////////////////////////////////////////////////////
// AVTestClass
///////////////////////////////////////////////////////////////////////////////
class AVTestClass
{
public:
AVTestClass(int value) : value_(value) {}
AVTestClass(const AVTestClass& other) : value_(other.value_) {}
AVTestClass& operator=(const AVTestClass& other) {
value_ = other.value_;
return *this;
}
int value_;
};
bool operator<(const AVTestClass& lhs, const AVTestClass& rhs)
{
return lhs.value_ < rhs.value_;
}
///////////////////////////////////////////////////////////////////////////////
// str_less
///////////////////////////////////////////////////////////////////////////////
struct str_less : public std::binary_function<const char*, const char*, bool> {
bool operator()(const char* x, const char* y) const {
return strcmp(x, y) < 0;
}
};
///////////////////////////////////////////////////////////////////////////////
// int_less
///////////////////////////////////////////////////////////////////////////////
unsigned int_test_count = 0; // to verify usage
struct int_less : public std::less<int>
{
bool operator()(int x, int y) const {
++int_test_count;
return x < y;
}
};
///////////////////////////////////////////////////////////////////////////////
// is_sorted
///////////////////////////////////////////////////////////////////////////////
template<class Vect>
bool is_sorted(const Vect& v) {
if (v.size() < 2) return true;
typename Vect::const_iterator it = v.begin();
typename Vect::key_type previous = it->first;
++it;
while (it != v.end()) {
typename Vect::key_type current = it->first;
if (!v.key_comp()(previous, current)) return false;
previous = current;
++it;
}
return true;
}
///////////////////////////////////////////////////////////////////////////////
typedef Loki::AssocVector<int, int, std::less<int>, TestAllocator<std::pair<int, int> > > test_vect1_t;
typedef Loki::AssocVector<const char*, int, str_less, TestAllocator<std::pair<const char*, int> > > test_vect2_t;
typedef Loki::AssocVector<std::string, std::string> test_vect3_t;
typedef Loki::AssocVector<AVTestClass, AVTestClass, std::less<AVTestClass>, TestAllocator<std::pair<AVTestClass, AVTestClass> > > test_vect4_t;
typedef Loki::AssocVector<int, const char*> test_vect5_t;
///////////////////////////////////////////////////////////////////////////////
void check_insert1(test_vect1_t& v)
{
C_Namespace::srand(10);
for (unsigned i = 0; i < 100; ++i) {
int x = C_Namespace::rand();
v.insert(std::make_pair(x, x));
assert(is_sorted(v));
}
assert(v.size() == 100);
}
///////////////////////////////////////////////////////////////////////////////
// check_swap
///////////////////////////////////////////////////////////////////////////////
template <class Vect>
void check_swap(Vect& v1, Vect& v2)
{
size_t size1 = v1.size(); (void) size1;
size_t size2 = v2.size(); (void) size2;
v1.swap(v2);
assert(v1.size() == size2);
assert(v2.size() == size1);
}
///////////////////////////////////////////////////////////////////////////////
// test_vect1
///////////////////////////////////////////////////////////////////////////////
void test_vect1()
{
test_vect1_t vec11;
assert(vec11.size() == 0);
check_insert1(vec11);
size_t size1 = vec11.size();
(void) size1;
assert(size1);
test_vect1_t vec12(vec11.begin(), vec11.end());
assert(vec12.size() == vec11.size());
assert(vec11.size() == size1);
test_vect1_t vec13;
vec13 = vec11;
assert(vec13.size() == vec11.size());
assert(vec11.size() == size1);
// this doesn't compile on Borland C++ 6.0 !?!
//test_vect1_t vec99(test_vect1_t::key_compare(), TestAllocator<test_vect1_t::value_type>());
//assert(vec99.size() == 0); //- here ir cries
test_vect1_t::key_compare comp = test_vect1_t::key_compare();
test_vect1_t vec14(comp, TestAllocator<test_vect1_t::value_type>());
assert(vec14.size() == 0);
check_swap(vec11, vec14);
assert(vec14.size() == size1);
assert(vec11.size() == 0);
// this compiles, unlike object on stack
test_vect1_t* vec15 = new test_vect1_t(test_vect1_t::key_compare(), TestAllocator<test_vect1_t::value_type>());
assert(vec15->size() == 0);
check_insert1(*vec15);
delete vec15;
// different comparator test - doesn't work for Loki
//comp = int_less();
//test_vect1_t vec16(comp);
//assert(vec16.size() == 0);
//assert(int_test_count == 0);
//check_insert1(vec16);
//assert(int_test_count != 0);
}
///////////////////////////////////////////////////////////////////////////////
// test_vect2
///////////////////////////////////////////////////////////////////////////////
void test_vect2()
{
test_vect2_t vec21;
vec21.insert(std::make_pair("abc", 1));
vec21.insert(std::make_pair("xyz", 3));
vec21.insert(std::make_pair("def", 2));
assert(vec21.size() == 3);
assert(is_sorted(vec21));
test_vect2_t::iterator it = vec21.find("xyz");
assert(it != vec21.end());
assert(it->second == 3);
std::pair<test_vect2_t::iterator, bool> aux = vec21.insert(std::make_pair("xyz", 99));
assert(!aux.second);
assert(aux.first->first == "xyz");
assert(aux.first->second == 3);
it = vec21.find("xyz");
assert(it != vec21.end());
assert(it->second == 3);
vec21.erase(it);
assert(vec21.size() == 2);
it = vec21.find("xyz");
assert(it == vec21.end());
vec21.erase("xyz");
vec21.erase("abc");
assert(vec21.size() == 1);
vec21.clear();
assert(vec21.size() == 0);
}
///////////////////////////////////////////////////////////////////////////////
// test_vect3
///////////////////////////////////////////////////////////////////////////////
void test_vect3()
{
// To use string, you need:
// 1) enable _STLP_USE_NEWALLOC in include\stl\_site_config.h
// 2) either disable use of any dynamic RTL (menu Project | Options | Linker)
// 3) or recompile STLPort DLL.
// This all is related to bug in STLPort allocator.
test_vect3_t vec31;
C_Namespace::srand(111);
// a stress test
for (unsigned i = 0; i < 2 * 1000; ++i) {
char buffer[17];
C_Namespace::sprintf(buffer, "string%d", C_Namespace::rand());
std::string s(buffer);
vec31.insert(std::make_pair(s, s));
}
}
///////////////////////////////////////////////////////////////////////////////
// test_vect4
///////////////////////////////////////////////////////////////////////////////
void test_vect4()
{
test_vect4_t vec41;
for (int i = 0; i < 100; ++i) {
vec41.insert(std::make_pair(AVTestClass(i), AVTestClass(i)));
}
assert(vec41.size() == 100);
vec41.insert(std::make_pair(AVTestClass(300), AVTestClass(300)));
vec41.insert(std::make_pair(AVTestClass(200), AVTestClass(200)));
assert(vec41.size() == 102);
test_vect4_t::iterator it = vec41.find(AVTestClass(22));
assert(it != vec41.end());
assert(it->second.value_ == 22);
test_vect4_t vec42;
vec42.swap(vec41);
assert(vec41.size() == 0);
assert(vec42.size() == 102);
vec42.erase(vec42.begin(), vec42.end());
assert(vec42.size() == 0);
}
///////////////////////////////////////////////////////////////////////////////
// test_vect5
///////////////////////////////////////////////////////////////////////////////
void test_vect5()
{
test_vect5_t vec51;
vec51.insert(test_vect5_t::value_type(3, "XXX"));
vec51.insert(std::make_pair(1, "X"));
vec51.insert(std::make_pair(2, "XX"));
test_vect5_t::const_iterator it = vec51.begin();
std::string::size_type count=1;
while (it != vec51.end()) {
assert(std::string(it->second).length()==count);
++count;
it++; // intentionally
}
}
///////////////////////////////////////////////////////////////////////////////
// test_vect6
///////////////////////////////////////////////////////////////////////////////
void test_vect6()
{
srand( static_cast<unsigned int>(time(NULL)) );
typedef Loki::AssocVector<int, int> IntMap;
const unsigned int numTests = 20;
const unsigned int numSamples = 50;
for( unsigned int i = 0; i < numTests; ++i )
{
IntMap testVec;
for( unsigned int i = 0; i < numSamples; ++i )
{
std::pair<int, int> newValue(
rand() % numSamples,
rand() % numSamples );
IntMap backupVec( testVec );
// assuming the basic insert operator is correct:
testVec.insert( newValue );
// test the boundary cases:
{
IntMap newVec( backupVec );
newVec.insert( newVec.begin(), newValue );
assert( newVec == testVec );
// check to make sure repeated inserts do not
// break anything
newVec.insert( newVec.begin(), newValue );
newVec.insert( newVec.end(), newValue );
newVec.insert( newVec.begin() + newVec.size()/2, newValue );
newVec.insert( newVec.begin() + rand() % newVec.size(), newValue );
assert( newVec == testVec );
}
{
IntMap newVec( backupVec );
newVec.insert( newVec.end(), newValue );
assert( newVec == testVec );
}
// try the middle:
{
IntMap newVec( backupVec );
IntMap::iterator itr = newVec.begin();
std::advance( itr, newVec.size()/2 );
newVec.insert( itr, newValue );
assert( newVec == testVec );
}
// try a random spot:
if( testVec.size() >= 2 )
{
IntMap newVec( backupVec );
IntMap::iterator itr = newVec.begin();
std::advance( itr, rand() % (testVec.size()-1) + 1 );
newVec.insert( itr, newValue );
assert( newVec == testVec );
}
}
}
}
class AssocVectorTest : public Test
{
public:
AssocVectorTest() : Test("AssocVector.h") {}
virtual void execute(TestResult &result)
{
printName(result);
test_vect1();
test_vect2();
test_vect3();
test_vect4();
test_vect5();
test_vect6();
testAssert("AssocVector",true,result),
std::cout << '\n';
}
} assocVectorTest;
#endif