417 lines
13 KiB
C++
417 lines
13 KiB
C++
#include "ZUnitTest.hpp"
|
|
|
|
#include <ZSTL/ZList.hpp>
|
|
#include <ZSTL/ZListAlgo.hpp>
|
|
|
|
static const char* test_Constructors_PushBack_Size_Empty();
|
|
static const char* test_Begin_End_At_Iterator();
|
|
static const char* test_Allocator_Front_Back_Clear();
|
|
static const char* test_Copy_Equals();
|
|
static const char* test_PushFront_PopBack_PopFront();
|
|
static const char* test_Insert_Erase();
|
|
static const char* test_Swap_Splice_SwapNodes();
|
|
|
|
//List of unit tests
|
|
ZUnitTest ZListUnitTests[] =
|
|
{
|
|
{ "ZList: Constructors, PushBack, Size, Empty", test_Constructors_PushBack_Size_Empty },
|
|
{ "ZList: Begin, End, At, Iterator", test_Begin_End_At_Iterator },
|
|
{ "ZList: Allocator, Front, Back, Clear", test_Allocator_Front_Back_Clear },
|
|
{ "ZList: Copy, Equals", test_Copy_Equals },
|
|
{ "ZList: PushFront, PopBack, PopFront", test_PushFront_PopBack_PopFront },
|
|
{ "ZList: Insert, Erase", test_Insert_Erase },
|
|
{ "ZList: Swap, Splice, SwapNodes", test_Swap_Splice_SwapNodes }
|
|
};
|
|
|
|
//Now declare the ZUnitTestBlock associated with this.
|
|
DECLARE_ZTESTBLOCK(ZList);
|
|
|
|
/*************************************************************************/
|
|
|
|
static const char* test_Constructors_PushBack_Size_Empty()
|
|
{
|
|
//Test our default list constructor with default allocator
|
|
ZList<int> list1;
|
|
|
|
//Should start empty
|
|
TASSERT(list1.Size() == 0, "Size() returns non-zero value but should be empty!");
|
|
TASSERT(list1.Empty() == true, "Empty() returns false on newly created list!");
|
|
|
|
//Fill in with 5 elements
|
|
for(int i = 0; i < 5; i++)
|
|
{
|
|
list1.PushBack(i);
|
|
|
|
TASSERT(list1.Size() == (size_t)(i + 1), "Size() returns incorrect value after PushBack()!");
|
|
TASSERT(list1.Empty() == false, "Empty() returns true on list with elements!");
|
|
}
|
|
|
|
return ZTEST_SUCCESS;
|
|
}
|
|
|
|
/*************************************************************************/
|
|
|
|
static const char* test_Begin_End_At_Iterator()
|
|
{
|
|
int i;
|
|
|
|
ZList<int> list1;
|
|
ZList<int>::Iterator itr1;
|
|
ZListIterator<int> itr2;
|
|
|
|
itr1 = list1.Begin();
|
|
|
|
TASSERT(itr1.HasNext() == false, "Iterator HasNext() returns true on empty list iterator!");
|
|
TASSERT(itr1.HasPrev() == false, "Iterator HasPrev() returns true on empty list iterator!");
|
|
TASSERT(itr1.HasCurrent() == false, "Iterator HasCurrent() returns false on empty list iterator!");
|
|
|
|
for(int i = 0; i < 5; i++)
|
|
list1.PushBack(i); //These calls will invalidate the iterator, or, rather, have it point to 'End'
|
|
|
|
itr1 = list1.Begin();
|
|
|
|
TASSERT(itr1.HasNext() == true, "Iterator HasNext() returns false when elements remain!");
|
|
TASSERT(itr1.HasPrev() == false, "Iterator HasPrevious() returns true at list Begin()!");
|
|
|
|
//Check going forwards
|
|
for (itr1 = list1.Begin(), i = 0; i < 5; itr1++, i++)
|
|
{
|
|
TASSERT(itr1.HasCurrent() == true, "Iterator HasCurrent() returns false when elements should exist!");
|
|
TASSERT(itr1.Get() == i, "Iterator Get() does not return correct value when iterating list!");
|
|
TASSERT((*itr1) == i, "Iterator operator * does not return correct value when iterating list!");
|
|
|
|
TASSERT(itr1 == list1.At(i), "At() returns incorrect iterator when forward iterating!");
|
|
}
|
|
|
|
//Should be at end
|
|
TASSERT(list1.End() == itr1, "Iterator should be at end after forward iteration but == End() returns false!");
|
|
TASSERT(itr1.HasNext() == false, "Iterator HasNext() should return false at End() but returns true!");
|
|
TASSERT(itr1.HasPrev() == true, "Iterator HasPrev() should return true at End() but returns false!");
|
|
TASSERT(itr1.HasCurrent() == false, "Iterator HasCurrent() should return false at End() but returns true!");
|
|
|
|
for (i = 4; i >= 0; i--)
|
|
{
|
|
itr1--;
|
|
|
|
TASSERT(itr1.Get() == i, "Iterator Get() does not return correct value when reverse iterating list!");
|
|
TASSERT((*itr1) == i, "Iterator operator * does not return correct value when reverse iterating list!");
|
|
|
|
TASSERT(itr1 == list1.At(i), "At() returns incorrect iterator when reverse iterating!");
|
|
}
|
|
|
|
//Should be at the beginning now
|
|
TASSERT(itr1 == list1.Begin(), "Iterator should be at start after reverse iteration but == Begin() returns false!");
|
|
|
|
for (i = 0; i < 5; i++)
|
|
{
|
|
itr1 = list1.At(i);
|
|
|
|
TASSERT((*itr1) == i, "Iterator operator * returns incorrect value after iterator assignment!");
|
|
}
|
|
|
|
return ZTEST_SUCCESS;
|
|
}
|
|
|
|
/*************************************************************************/
|
|
|
|
//Allocator that counts current number of node allocations
|
|
template <typename T>
|
|
class ZListTestAllocator : public ZListAllocator<T>
|
|
{
|
|
public:
|
|
//Current number of allocated nodes
|
|
int Count;
|
|
|
|
ZListTestAllocator() : Count(0) { }
|
|
|
|
ZListNode<T>* Allocate()
|
|
{
|
|
Count++;
|
|
|
|
return new (std::nothrow) ZListNode<T>();
|
|
}
|
|
|
|
void Deallocate( ZListNode<T>* _node )
|
|
{
|
|
Count--;
|
|
|
|
delete _node;
|
|
}
|
|
};
|
|
|
|
static const char* test_Allocator_Front_Back_Clear()
|
|
{
|
|
ZList<int, ZListTestAllocator<int> > list1;
|
|
ZList<int>::Iterator itr;
|
|
|
|
for (int i = 0; i < 5; i++)
|
|
{
|
|
list1.PushBack(i);
|
|
|
|
TASSERT(list1.Allocator().Count == i + 1, "Allocator() returns incorrect count for number of allocated nodes!");
|
|
}
|
|
|
|
TASSERT(list1.Front() == 0, "Front() returns incorrect value!");
|
|
TASSERT(list1.Back() == 4, "Back() returns incorrect value!");
|
|
|
|
list1.Clear();
|
|
|
|
TASSERT(list1.Empty(), "Empty() returns false after call to Clear()!");
|
|
TASSERT(list1.Allocator().Count == 0, "Clear() failed to deallocate nodes!");;
|
|
|
|
for (int i = 0; i < 5; i++)
|
|
list1.PushBack(i);
|
|
|
|
itr = list1.At(2);
|
|
|
|
list1.Clear(itr);
|
|
|
|
TASSERT(list1.Size() == 2, "Size() returns incorrect value after call to Clear()!");
|
|
|
|
itr = list1.End();
|
|
|
|
list1.Clear(itr);
|
|
|
|
TASSERT(list1.Size() == 2, "Size() returns incorrect value after call to Clear(End())!");
|
|
|
|
return ZTEST_SUCCESS;
|
|
}
|
|
|
|
/*************************************************************************/
|
|
|
|
static const char* test_Copy_Equals()
|
|
{
|
|
ZList<int, ZListTestAllocator<int> > list1;
|
|
ZList<int, ZListTestAllocator<int> > list2;
|
|
|
|
ZList<int>::Iterator itr;
|
|
|
|
TASSERT(list1.Equals(list2) == true, "Equals() returns false when empty list is compared to empty list!");
|
|
|
|
for (int i = 0; i < 5; i++)
|
|
list1.PushBack(i);
|
|
|
|
TASSERT(list1.Equals(list2) == false, "Equals() returns true when empty list is compared to non-empty list!");
|
|
|
|
list2.Copy(list1);
|
|
|
|
TASSERT(list1.Size() == list2.Size(), "Size() of list1 does not equal Size() of list2 after Copy!");
|
|
TASSERT(list1.Equals(list2) == true, "Equals(list1, list2) returns false after Copy!");
|
|
TASSERT(list2.Equals(list1) == true, "Equals(list2, list1) returns false after Copy!");
|
|
|
|
itr = list2.At(3);
|
|
|
|
list2.Clear(itr);
|
|
|
|
TASSERT(list1.Equals(list2) == false, "Equals(list1, list2) returns true after Clear()!");
|
|
TASSERT(list2.Equals(list1) == false, "Equals(list2, list1) returns true after Clear()!");
|
|
|
|
ZList<int, ZListTestAllocator<int> > list3(list2.Begin(), list2.End());
|
|
ZList<int, ZListTestAllocator<int> > list4(list2.Begin(), --itr);
|
|
|
|
TASSERT(list3.Back() == 2, "Back() returns incorrect value on list3 after sub-list constructor!");
|
|
TASSERT(list4.Back() == 1, "Back() returns incorrect value on list4 after sub-list constructor!");
|
|
TASSERT(list3.Equals(list4) == false, "Equals(list3, list4) returns true after sub-list constructor!");
|
|
|
|
return ZTEST_SUCCESS;
|
|
}
|
|
|
|
/*************************************************************************/
|
|
|
|
static const char* test_PushFront_PopBack_PopFront()
|
|
{
|
|
int i;
|
|
|
|
ZList<int, ZListTestAllocator<int> > list1;
|
|
|
|
for (i = 0; i < 5; i++)
|
|
{
|
|
list1.PushBack(i);
|
|
|
|
TASSERT(list1.Allocator().Count == i + 1, "Allocator() returns incorrect count for number of allocated nodes after PushBack()!");
|
|
TASSERT(list1.Back() == i, "Back() returns incorrect value after PushBack()!");
|
|
}
|
|
|
|
TASSERT(list1.Size() == 5, "Size() returns incorrect value after after PushBack()!");
|
|
|
|
for (i = 5; i > 0; i--)
|
|
{
|
|
int j = list1.PopBack();
|
|
|
|
TASSERT(j == i - 1, "PopBack() returns incorrect value!");
|
|
|
|
TASSERT(list1.Allocator().Count == i - 1, "Allocator() returns incorrect count for number of allocated nodes after PopBack()!");
|
|
TASSERT(list1.Size() == (size_t)(i - 1), "Size() returns incorrect value after PopBack()!");
|
|
}
|
|
|
|
list1.Clear();
|
|
|
|
for (i = 0; i < 5; i++)
|
|
{
|
|
list1.PushFront(i);
|
|
|
|
TASSERT(list1.Allocator().Count == i + 1, "Allocator() returns incorrect count for number of allocated nodes!");
|
|
TASSERT(list1.Front() == i, "Front() returns wrong value after calls to PushFront()!");
|
|
}
|
|
|
|
TASSERT(list1.Size() == 5, "Size() returns incorrect value after after PushFront()!");
|
|
|
|
for (i = 5; i > 0; i--)
|
|
{
|
|
int j = list1.PopFront();
|
|
|
|
TASSERT(j == i - 1, "PopFront() returns incorrect value!");
|
|
|
|
TASSERT(list1.Allocator().Count == i - 1, "Allocator() returns incorrect count for number of allocated nodes!");
|
|
TASSERT(list1.Size() == (size_t)(i - 1), "Size() returns incorrect value after PopFront()!");
|
|
}
|
|
|
|
return ZTEST_SUCCESS;
|
|
}
|
|
|
|
/*************************************************************************/
|
|
|
|
static const char* test_Insert_Erase()
|
|
{
|
|
ZList<int, ZListTestAllocator<int> > list1;
|
|
ZList<int, ZListTestAllocator<int> > list2;
|
|
|
|
ZList<int>::Iterator itr1;
|
|
ZList<int>::Iterator itr2;
|
|
|
|
for (int i = 0; i < 5; i++)
|
|
list1.PushBack(i);
|
|
|
|
itr1 = list1.Begin();
|
|
|
|
list1.Insert(itr1, 10);
|
|
|
|
TASSERT((*itr1) == 0, "Iterator operator * returns incorrect value after Insert()!");
|
|
TASSERT(list1.Begin().Get() == 10, "Iterator Get() returns incorrect value after Insert()!");
|
|
TASSERT(list1.Size() == 6, "Size() returns incorrect value after Insert()!")
|
|
|
|
itr2 = list1.End();
|
|
|
|
list1.Insert(itr2, 20);
|
|
|
|
TASSERT(list1.Back() == 20, "Back() returns incorrect value after Insert()!");
|
|
TASSERT(itr2 == list1.End(), "Iterator does not equal End after Insert()!");
|
|
TASSERT(list1.Size() == 7, "Size() returns incorrect value after Insert(End())!");
|
|
|
|
itr1 = list1.Begin();
|
|
|
|
int j = list1.Erase(itr1);
|
|
|
|
TASSERT(j == 10, "Erase(itr1) returns incorrect value!");
|
|
TASSERT(list1.Front() == 0, "Front() returns incorrect value after Erase()!");
|
|
TASSERT(list1.Size() == 6, "Size() returns incorrect value after Erase(Begin())!");
|
|
|
|
itr2 = list1.End() - 1;
|
|
|
|
j = list1.Erase(itr2);
|
|
|
|
TASSERT(j == 20, "Erase(itr2) returns incorrect value!");
|
|
TASSERT(list1.Back() == 4, "Back() returns incorrect value after Erase()!");
|
|
TASSERT(list1.Size() == 5, "Size() returns incorrect value after Erase(End() - 1))!");
|
|
|
|
itr1 = list1.Begin();
|
|
itr2 = list1.At(2); //0, 1, 2
|
|
|
|
list2.Insert(list2.Begin(), itr1, itr2);
|
|
|
|
TASSERT(list2.Front() == 0 && list2.Back() == 1, "Front() and Back() do not return correct values after Insert(Begin(), itr1, itr2)!");
|
|
|
|
itr1 = list2.Begin();
|
|
itr2 = list2.End();
|
|
|
|
list1.Insert(list1.At(2), itr1, itr2);
|
|
|
|
TASSERT(list1.Size() == 7, "Size() returns incorrect value after Insert(At(2), itr1, itr2)!");
|
|
|
|
TASSERT(list1.Front() == 0, "Front() returns incorrect value after Insert(At(2), itr1, itr2)!");
|
|
TASSERT(list1.Back() == 4, "Back() returns incorrect value after Insert(At(2), itr1, itr2)");
|
|
|
|
TASSERT(*list1.At(2) == 0, "At(2) dereference contains invalid value after Insert(At(2), itr1, itr2)!");
|
|
TASSERT(*list1.At(3) == 1, "At(3) dereference contains invalid value after Insert(At(2), itr1, itr2)!");
|
|
|
|
itr1 = list1.At(2);
|
|
itr2 = list1.At(4);
|
|
|
|
list1.Erase(itr1, itr2);
|
|
|
|
TASSERT(list1.Size() == 5, "Size() returns incorrect value after Erase(itr1, itr2)!");
|
|
|
|
itr1 = list1.Begin();
|
|
|
|
for (int i = 0; itr1 != list1.End(); itr1++, i++)
|
|
{
|
|
TASSERT((*itr1) == i, "Iterator operator * returns incorrect value after Erase(itr1, itr2)!");
|
|
}
|
|
|
|
return ZTEST_SUCCESS;
|
|
}
|
|
|
|
/*************************************************************************/
|
|
|
|
static const char* test_Swap_Splice_SwapNodes()
|
|
{
|
|
int i;
|
|
|
|
ZList<int> list1;
|
|
ZList<int> list2;
|
|
|
|
ZList<int>::Iterator itr1;
|
|
ZList<int>::Iterator itr2;
|
|
|
|
for (int i = 0; i < 5; i++)
|
|
list1.PushBack(i);
|
|
|
|
for (int i = 5; i < 10; i++)
|
|
list2.PushBack(i);
|
|
|
|
list1.Swap(list2);
|
|
|
|
for (i = 5, itr1 = list1.Begin(); itr1 != list1.End(); i++, itr1++)
|
|
{
|
|
TASSERT((*itr1) == i, "Iterator operator * returns incorrect value on list1 after Swap()!");
|
|
}
|
|
|
|
for (i = 0, itr2 = list2.Begin(); itr2 != list2.End(); i++, itr2++)
|
|
{
|
|
TASSERT((*itr2) == i, "Iterator operator * returns incorrect value on list2 after Swap()!");
|
|
}
|
|
|
|
itr1 = list1.Begin();
|
|
itr2 = list1.End();
|
|
|
|
list2.Splice(list2.End(), list1, itr1, itr2);
|
|
|
|
TASSERT(list2.Size() == 10, "Size() returns incorrect value after Splice()!");
|
|
TASSERT(list1.Empty(), "Empty() returns false after Splice()!");
|
|
|
|
for (i = 0, itr2 = list2.Begin(); itr2 != list2.End(); i++, itr2++)
|
|
{
|
|
TASSERT((*itr2) == i, "Iterator operator * returns incorrect value on list2 after Splice()!");
|
|
}
|
|
|
|
itr1 = list2.At(3);
|
|
itr2 = list2.At(6);
|
|
|
|
list1.Splice(list1.Begin(), list2, itr1, itr2);
|
|
|
|
TASSERT(list2.Size() == 7, "Size() returns incorrect value for list2 after Splice(At(3), At(6))!");
|
|
TASSERT(list1.Size() == 3, "Size() returns incorrect value for list1 after Splice(At(3), At(6))!");
|
|
|
|
for (i = 3, itr1 = list1.Begin(); itr1 != list1.End(); i++, itr1++)
|
|
{
|
|
TASSERT((*itr1) == i, "Iterator operator * returns incorrect value on list1 after Splice()!");
|
|
}
|
|
|
|
list1.SwapNodes(list1.Begin(), list1.End() - 1);
|
|
|
|
TASSERT(list1.Front() == 5, "Front() returns invalid value after call to SwapNodes()!");
|
|
TASSERT(list1.Back() == 3, "Back() returns invalid value after call to SwapNodes()!");
|
|
|
|
return ZTEST_SUCCESS;
|
|
}
|