New ContainerTest generic templates

This commit is contained in:
Vinnie Falco
2013-09-04 20:41:47 -07:00
parent 201221253d
commit 04d039eddd
2 changed files with 379 additions and 102 deletions

View File

@@ -17,49 +17,303 @@
*/
//==============================================================================
namespace ContainerTests
{
//------------------------------------------------------------------------------
/** Counts the number of occurrences of each type of operation. */
class Counts
{
public:
typedef std::size_t count_type;
Counts ()
: default_ctor (0)
, copy_ctor (0)
, copy_assign (0)
#if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS
, move_ctor (0)
, move_assign (0)
#endif
{
}
Counts (Counts const& other)
: default_ctor (other.default_ctor)
, copy_ctor (other.copy_ctor)
, copy_assign (other.copy_assign)
#if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS
, move_ctor (other.move_ctor)
, move_assign (other.move_assign)
#endif
{
}
Counts& operator= (Counts const& other)
{
default_ctor = other.default_ctor;
copy_ctor = other.copy_ctor;
copy_assign = other.copy_assign;
#if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS
move_ctor = other.move_ctor;
move_assign = other.move_assign;
#endif
return *this;
}
friend inline Counts operator- (Counts const& lhs, Counts const& rhs)
{
Counts result;
result.default_ctor = lhs.default_ctor - rhs.default_ctor;
result.copy_ctor = lhs.copy_ctor - rhs.copy_ctor;
result.copy_assign = lhs.copy_assign - rhs.copy_assign;
#if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS
result.move_ctor = lhs.move_ctor - rhs.move_ctor;
result.move_assign = lhs.move_assign - rhs.move_assign;
#endif
return result;
}
String toString () const
{
return String()
+ "default_ctor(" + String::fromNumber (default_ctor) + ") "
+ ", copy_ctor(" + String::fromNumber (copy_ctor) + ")"
+ ", copy_assign(" + String::fromNumber (copy_assign) + ")"
#if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS
+ ", move_ctor(" + String::fromNumber (move_ctor) + ")"
+ ", move_assign(" + String::fromNumber (move_assign) + ")";
#endif
}
count_type default_ctor;
count_type copy_ctor;
count_type copy_assign;
#if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS
count_type move_ctor;
count_type move_assign;
#endif
};
//------------------------------------------------------------------------------
/** Counts the number of element operations performed in a scope. */
class ScopedCounts : public Uncopyable
{
public:
ScopedCounts (Counts const& counts)
: m_start (counts)
, m_counts (counts)
{
}
Counts get () const
{
return m_counts - m_start;
}
private:
Counts const m_start;
Counts const& m_counts;
};
//------------------------------------------------------------------------------
/* Base for element configurations. */
class ElementConfigBase : public Uncopyable
{
public:
typedef std::size_t IdType;
};
/** Provides the element-specific configuration members. */
template <class Params>
class ElementConfig : public ElementConfigBase
{
public:
static Counts& getCounts ()
{
static Counts counts;
return counts;
}
};
//------------------------------------------------------------------------------
/** Base for elements used in container unit tests. */
class ElementBase
{
public:
};
/** An object placed into a container for unit testing. */
template <class Config>
class Element : public ElementBase
{
public:
typedef typename Config::IdType IdType;
Element ()
: m_id (0)
, m_msg (String::empty)
{
++Config::getCounts ().default_ctor;
}
explicit Element (IdType id)
: m_id (id)
, m_msg (String::fromNumber (id))
{
}
Element (Element const& other)
: m_id (other.m_id)
, m_msg (other.m_msg)
{
++Config::getCounts ().copy_ctor;
}
Element& operator= (Element const& other)
{
m_id = other.m_id;
m_msg = other.m_msg;
++Config::getCounts ().copy_assign;
}
#if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS
Element (Element&& other)
: m_id (other.m_id)
, m_msg (other.m_msg)
{
other.m_msg = String::empty;
++Config::getCounts ().move_ctor;
}
Element& operator= (Element&& other)
{
m_id = other.m_id;
m_msg = other.m_msg;
other.m_msg = String::empty;
++Config::getCounts ().move_assign;
}
#endif
IdType id () const
{
return m_id;
}
String msg () const
{
return m_msg;
}
private:
IdType m_id;
String m_msg;
};
//------------------------------------------------------------------------------
/** Base for test state parameters. */
class StateBase : public Uncopyable
{
public:
typedef int64 SeedType;
};
/** Provides configuration-specific test state parameters. */
template <class Params>
class State : public StateBase
{
public:
static Random& random ()
{
static Random generator (Params::seedValue);
return generator;
}
};
//------------------------------------------------------------------------------
class ConfigBase
{
};
template <template <typename, class> class Container,
class Params>
class Config
: public State <Params>
, public ElementConfig <Params>
{
public:
typedef Config ConfigType;
typedef Params ParamsType;
typedef State <Params> StateType;
typedef ElementConfig <Params> ElementConfigType;
typedef Element <ElementConfigType> ElementType;
typedef Container <
ElementType,
std::allocator <char> > ContainerType;
typedef StateBase::SeedType SeedType;
// default seed
static SeedType const seedValue = 69;
};
//------------------------------------------------------------------------------
/** A generic container test. */
template <class Params>
class Test : public Params
{
public:
typedef typename Params::StateType StateType;
typedef typename Params::ElementConfigType ElementConfigType;
typedef typename Params::ContainerType ContainerType;
void doInsert ()
{
m_container.reserve (Params::elementCount);
for (typename ContainerType::size_type i = 0;
i < Params::elementCount; ++i)
{
m_container.push_back (typename Params::ElementType ());
}
}
private:
typename Params::ContainerType m_container;
};
//------------------------------------------------------------------------------
class DynamicListTests : public UnitTest
{
public:
struct T
struct Params : Config <DynamicList, Params>
{
T ()
{
}
explicit T (String what)
: msg (what)
{
}
T& operator= (T const& other)
{
msg = other.msg;
return *this;
}
String msg;
static SeedType const seedValue = 42;
static ContainerType::size_type const elementCount = 100 * 1000;
};
enum
{
numberToAssign = 1000 * 1000,
numberToReserve = 1000 * 1000,
numberToMutate = 12139
};
void testAssign ()
{
String s;
s << "assign (" << String::fromNumber <int> (numberToAssign) << ")";
beginTestCase (s);
pass ();
}
typedef Test <Params> TestType;
void runTest ()
{
testAssign ();
TestType test;
beginTestCase ("insert");
{
ScopedCounts counts (TestType::getCounts ());
test.doInsert ();
this->logMessage (counts.get ().toString ());
}
pass ();
}
DynamicListTests () : UnitTest ("DynamicList", "beast")
@@ -67,4 +321,6 @@ public:
}
};
static DynamicListTests DynamicListTests;
static DynamicListTests dynamicListTests;
}

View File

@@ -23,87 +23,109 @@
template <typename, typename>
class DynamicList;
namespace detail
{
template <typename I>
template <class Container, bool IsConst>
class DynamicListIterator
: public std::iterator <std::bidirectional_iterator_tag,
typename I::size_type>
: public std::iterator <
std::bidirectional_iterator_tag,
typename Container::value_type,
typename Container::difference_type,
typename mpl::IfConst <IsConst,
typename Container::const_pointer,
typename Container::pointer>::type,
typename mpl::IfConst <IsConst,
typename Container::const_reference,
typename Container::reference>::type>
{
private:
typedef typename mpl::IfConst <IsConst,
typename List <typename Container::Item>::const_iterator,
typename List <typename Container::Item>::iterator>::type iterator_type;
typedef typename mpl::IfConst <IsConst,
typename Container::const_pointer,
typename Container::pointer>::type pointer;
typedef typename mpl::IfConst <IsConst,
typename Container::const_reference,
typename Container::reference>::type reference;
public:
typedef typename I::value_type ItemType; // this will be <Item>
typedef typename ItemType::value_type T; // this is the original T
DynamicListIterator ()
{
}
typedef typename copyconst <ItemType, T>::type
value_type;
typedef value_type* pointer;
typedef value_type& reference;
typedef typename I::size_type size_type;
DynamicListIterator (I iter = I ()) noexcept
DynamicListIterator (iterator_type iter)
: m_iter (iter)
{
}
#if 1
template <typename J>
DynamicListIterator (DynamicListIterator <J> const& other) noexcept
DynamicListIterator (DynamicListIterator const& other)
: m_iter (other.m_iter)
{
}
template <typename J>
DynamicListIterator& operator= (DynamicListIterator <J> const& other) noexcept
template <bool OtherIsConst>
DynamicListIterator (DynamicListIterator <Container, OtherIsConst> const& other)
: m_iter (other.m_iter)
{
}
DynamicListIterator& operator= (DynamicListIterator const& other)
{
m_iter = other.m_iter;
return *this;
}
#endif
template <typename J>
bool operator== (DynamicListIterator <J> const& other) const noexcept
template <bool OtherIsConst>
DynamicListIterator& operator= (DynamicListIterator <
Container, OtherIsConst> const& other)
{
m_iter = other.m_iter;
return *this;
}
template <bool OtherIsConst>
bool operator== (DynamicListIterator <Container, OtherIsConst> const& other) const
{
return m_iter == other.m_iter;
}
template <typename J>
bool operator != (DynamicListIterator <J> const& other) const noexcept
template <bool OtherIsConst>
bool operator!= (DynamicListIterator <Container, OtherIsConst> const& other) const
{
return ! this->operator== (other);
return ! ((*this) == other);
}
reference operator* () const noexcept
reference operator* () const
{
return dereference ();
}
pointer operator-> () const noexcept
pointer operator-> () const
{
return &dereference ();
}
DynamicListIterator& operator++ () noexcept
DynamicListIterator& operator++ ()
{
increment ();
return *this;
}
DynamicListIterator operator++ (int) noexcept
DynamicListIterator operator++ (int)
{
DynamicListIterator const result (*this);
increment ();
return result;
}
DynamicListIterator& operator-- () noexcept
DynamicListIterator& operator-- ()
{
decrement ();
return *this;
}
DynamicListIterator operator-- (int) noexcept
DynamicListIterator operator-- (int)
{
DynamicListIterator const result (*this);
decrement ();
@@ -114,28 +136,24 @@ private:
template <typename, typename>
friend class DynamicList;
typedef typename I::value_type Item;
reference dereference () const noexcept
reference dereference () const
{
return *(m_iter->get ());
}
void increment () noexcept
void increment ()
{
++m_iter;
}
void decrement () noexcept
void decrement ()
{
--m_iter;
}
I m_iter;
iterator_type m_iter;
};
}
//------------------------------------------------------------------------------
/** A list that uses a very small number of dynamic allocations.
@@ -155,7 +173,7 @@ private:
Destructible
*/
template <typename T,
typename Allocator = std::allocator <char> >
class Allocator = std::allocator <char> >
class DynamicList
{
private:
@@ -175,34 +193,15 @@ public:
typedef T& reference;
typedef T const* const_pointer;
typedef T const& const_reference;
typedef DynamicList <
T,
Allocator> container_type;
private:
struct Item : List <Item>::Node
{
typedef T value_type;
T* get () noexcept
{
return reinterpret_cast <T*> (&storage [0]);
}
T const* get () const noexcept
{
return reinterpret_cast <T const*> (&storage [0]);
}
private:
// Lets hope this is padded correctly
uint8 storage [sizeof (T)];
};
typedef DynamicListIterator <container_type, false> iterator;
typedef DynamicListIterator <container_type, true> const_iterator;
public:
typedef detail::DynamicListIterator <
typename List <Item>::iterator> iterator;
typedef detail::DynamicListIterator <
typename List <Item>::const_iterator> const_iterator;
explicit DynamicList (
size_type blocksize = defaultBlocksize,
Allocator const& allocator = Allocator ())
@@ -418,6 +417,28 @@ public:
}
private:
template <class, bool>
friend class DynamicListIterator;
struct Item : List <Item>::Node
{
typedef T value_type;
T* get () noexcept
{
return reinterpret_cast <T*> (&storage [0]);
}
T const* get () const noexcept
{
return reinterpret_cast <T const*> (&storage [0]);
}
private:
// Lets hope this is padded correctly
uint8 storage [sizeof (T)];
};
Item* alloc () noexcept
{
Item* item;