#include "ZUnitTest.hpp"

#include <ZSTL/ZArrayAlgo.hpp>

static const char* test_Append();
static const char* test_Append_Region();
static const char* test_Apply();
static const char* test_Apply_Region();
static const char* test_Concatenate();
static const char* test_Concatenate_Region();
static const char* test_Contains();
static const char* test_Contains_Region();
static const char* test_ContainsSub();
static const char* test_ContainsSub_Region();
static const char* test_Copy();
static const char* test_Copy_Region();
static const char* test_Count();
static const char* test_Count_Region();
static const char* test_Equal();
static const char* test_Equal_In_Region();
static const char* test_Fill();
static const char* test_Fill_Region();
static const char* test_Find();
static const char* test_Find_Region();
static const char* test_FindAll();
static const char* test_FindAll_Region();
static const char* test_FindAllOf();
static const char* test_FindAllOf_Region();
static const char* test_FindIf();
static const char* test_FindIf_In_Region();
static const char* test_FindFirst();
static const char* test_FindFirst_In_Region();
static const char* test_FindFirstOf();
static const char* test_FindFirstOf_In_Region();
static const char* test_FindFirstNot();
static const char* test_FindFirstNot_In_Region();
static const char* test_FindFirstNotOf();
static const char* test_FindFirstNotOf_In_Region();
static const char* test_FindLast();
static const char* test_FindLast_In_Region();
static const char* test_FindLastOf();
static const char* test_FindLastOf_In_Region();
static const char* test_FindLastNot();
static const char* test_FindLastNot_In_Region();
static const char* test_FindLastNotOf();
static const char* test_FindLastNotOf_In_Region();
static const char* test_FindSub();
static const char* test_FindSub_In_Region();
static const char* test_FoldLeft();
static const char* test_FoldLeft_Region();
static const char* test_FoldRight();
static const char* test_FoldRight_Region();
static const char* test_Generate();
static const char* test_Generate_In_Region();
static const char* test_Max();
static const char* test_Max_In_Region();
static const char* test_Max_Comparator();
static const char* test_Max_Comparator_In_Region();
static const char* test_Min();
static const char* test_Min_In_Region();
static const char* test_Min_Comparator();
static const char* test_Min_Comparator_In_Region();
static const char* test_Remove();
static const char* test_Remove_In_Region();
static const char* test_RemoveAll();
static const char* test_RemoveAll_In_Region();
static const char* test_RemoveIf();
static const char* test_RemoveIf_In_Region();
static const char* test_RemoveUpTo();
static const char* test_RemoveUpTo_In_Region();
static const char* test_Replace();
static const char* test_Replace_In_Region();
static const char* test_ReplaceIf();
static const char* test_ReplaceIf_In_Region();
static const char* test_Reverse();
static const char* test_Reverse_Region();
static const char* test_Rotate();
static const char* test_Rotate_Region();
static const char* test_SetIntersection();
static const char* test_SetIntersection_In_Region();
static const char* test_SetUnion();
static const char* test_SetUnion_In_Region();
static const char* test_Slice();
static const char* test_Sort();
static const char* test_Sort_Region();
static const char* test_Sort_Comparator();
static const char* test_Sort_Comparator_Algorithm();
static const char* test_Sort_Comparator_Algorithm_Region();
static const char* test_Split();
static const char* test_Split_Count();
static const char* test_Split_Count_Region();
static const char* test_Sum();
static const char* test_Sum_Region();
static const char* test_SwapElements();
static const char* test_Map();
static const char* test_Map_Region();
static const char* test_Unique();
static const char* test_Unique_In_Region();

//List of unit tests
ZUnitTest ZArrayAlgoUnitTests[] =
{
	{ "ZArrayAlgo: Append",											test_Append },
	{ "ZArrayAlgo: Append region",									test_Append_Region },
	{ "ZArrayAlgo: Apply",											test_Apply} ,
	{ "ZArrayAlgo: Apply to region",								test_Apply_Region} ,
	{ "ZArrayAlgo: Concatenate",									test_Concatenate },
	{ "ZArrayAlgo: Concatenate region",								test_Concatenate_Region },
	{ "ZArrayAlgo: Contains",										test_Contains },
	{ "ZArrayAlgo: Contains region",								test_Contains_Region },
	{ "ZArrayAlgo: ContainsSub",									test_ContainsSub },
	{ "ZArrayAlgo: ContainsSub region",								test_ContainsSub_Region },
	{ "ZArrayAlgo: Copy",											test_Copy },
	{ "ZArrayAlgo: Copy region",									test_Copy_Region },
	{ "ZArrayAlgo: Count",											test_Count },
	{ "ZArrayAlgo: Count region",									test_Count_Region },
	{ "ZArrayAlgo: Equal",											test_Equal },
	{ "ZArrayAlgo: Equal in region",								test_Equal_In_Region },
	{ "ZArrayAlgo: Fill",											test_Fill },
	{ "ZArrayAlgo: Fill region",									test_Fill_Region },
	{ "ZArrayAlgo: Find ",											test_Find },
	{ "ZArrayAlgo: Find in region",									test_Find_Region },
	{ "ZArrayAlgo: FindAll ",										test_FindAll },
	{ "ZArrayAlgo: FindAll region ",								test_FindAll_Region },
	{ "ZArrayAlgo: FindAllOf ",										test_FindAllOf },
	{ "ZArrayAlgo: FindAllOf region ",								test_FindAllOf_Region },
	{ "ZArrayAlgo: FindIf",											test_FindIf },
	{ "ZArrayAlgo: FindIf in region",								test_FindIf_In_Region },
	{ "ZArrayAlgo: FindFirst",										test_FindFirst },
	{ "ZArrayAlgo: FindFirst in region",							test_FindFirst_In_Region },
	{ "ZArrayAlgo: FindFirstOf",									test_FindFirstOf },
	{ "ZArrayAlgo: FindFirstOf in region",							test_FindFirstOf_In_Region },
	{ "ZArrayAlgo: FindFirstNot",									test_FindFirstNot },
	{ "ZArrayAlgo: FindFirstNot in region",							test_FindFirstNot_In_Region },
	{ "ZArrayAlgo: FindFirstNotOf",									test_FindFirstNotOf },
	{ "ZArrayAlgo: FindFirstNotOf in region",						test_FindFirstNotOf_In_Region },
	{ "ZArrayAlgo: FindLast",										test_FindLast},
	{ "ZArrayAlgo: FindLast in region",								test_FindLast_In_Region},
	{ "ZArrayAlgo: FindLastOf",										test_FindLastOf} ,
	{ "ZArrayAlgo: FindLastOf in region",							test_FindLastOf_In_Region} ,
	{ "ZArrayAlgo: FindLastNot",									test_FindLastNot},
	{ "ZArrayAlgo: FindLastNot in region",							test_FindLastNot_In_Region} ,
	{ "ZArrayAlgo: FindLastNotOf",									test_FindLastNotOf},
	{ "ZArrayAlgo: FindLastNotOf in region",						test_FindLastNotOf_In_Region} ,
	{ "ZArrayAlgo: FindSub",										test_FindSub },
	{ "ZArrayAlgo: FindSub in region",								test_FindSub_In_Region },
	{ "ZArrayAlgo: FoldLeft",										test_FoldLeft },
	{ "ZArrayAlgo: FoldLeft region",								test_FoldLeft_Region },
	{ "ZArrayAlgo: FoldRight",										test_FoldRight },
	{ "ZArrayAlgo: FoldRight region",								test_FoldRight_Region },
	{ "ZArrayAlgo: Generate",										test_Generate},
	{ "ZArrayAlgo: Generate in region",								test_Generate_In_Region} ,
	{ "ZArrayAlgo: Map",											test_Map} ,
	{ "ZArrayAlgo: Map region",										test_Map_Region} ,
	{ "ZArrayAlgo: Max",											test_Max} ,
	{ "ZArrayAlgo: Max in region",									test_Max_In_Region} ,
	{ "ZArrayAlgo: Max with comparator",							test_Max_Comparator} ,
	{ "ZArrayAlgo: Max with comparator in region",					test_Max_Comparator_In_Region} ,
	{ "ZArrayAlgo: Min",											test_Min} ,
	{ "ZArrayAlgo: Min in region",									test_Min_In_Region} ,
	{ "ZArrayAlgo: Min comparator",									test_Min_Comparator} ,
	{ "ZArrayAlgo: Min comparator in region",						test_Min_Comparator_In_Region} ,
	{ "ZArrayAlgo: Remove",											test_Remove} ,
	{ "ZArrayAlgo: Remove in region",								test_Remove_In_Region} ,
	{ "ZArrayAlgo: RemoveAll",										test_RemoveAll} ,
	{ "ZArrayAlgo: RemoveAll in region",							test_RemoveAll_In_Region} ,
	{ "ZArrayAlgo: RemoveIf",										test_RemoveIf} ,
	{ "ZArrayAlgo: RemoveIf in region",								test_RemoveIf_In_Region} ,
	{ "ZArrayAlgo: RemoveUpTo",										test_RemoveUpTo} ,
	{ "ZArrayAlgo: RemoveUpTo in region",							test_RemoveUpTo_In_Region} ,
	{ "ZArrayAlgo: Replace",										test_Replace} ,
	{ "ZArrayAlgo: Replace in region",								test_Replace_In_Region} ,
	{ "ZArrayAlgo: ReplaceIf",										test_ReplaceIf} ,
	{ "ZArrayAlgo: ReplaceIf in region",							test_ReplaceIf_In_Region} ,
	{ "ZArrayAlgo: Reverse",										test_Reverse} ,
	{ "ZArrayAlgo: Reverse region",									test_Reverse_Region} ,
	{ "ZArrayAlgo: Rotate",											test_Rotate} ,
	{ "ZArrayAlgo: Rotate region",									test_Rotate_Region} ,
	{ "ZArrayAlgo: SetIntersection",								test_SetIntersection} ,
	{ "ZArrayAlgo: SetIntersection in region",						test_SetIntersection_In_Region} ,
	{ "ZArrayAlgo: SetUnion",										test_SetUnion} ,
	{ "ZArrayAlgo: SetUnion in region",								test_SetUnion_In_Region} ,
	{ "ZArrayAlgo: Slice",											test_Slice },
	{ "ZArrayAlgo: Sort",											test_Sort} ,
	{ "ZArrayAlgo: Sort region",									test_Sort_Region} ,
	{ "ZArrayAlgo: Sort given comparator",							test_Sort_Comparator} ,
	{ "ZArrayAlgo: Sort given comparator and algorithm",			test_Sort_Comparator_Algorithm} ,
	{ "ZArrayAlgo: Sort given comparator and algorithm in region",	test_Sort_Comparator_Algorithm_Region},
	{ "ZArrayAlgo: Split",											test_Split },
	{ "ZArrayAlgo: Split with count",								test_Split_Count },
	{ "ZArrayAlgo: Split with count in region",						test_Split_Count_Region },
	{ "ZArrayAlgo: Sum",											test_Sum },
	{ "ZArrayAlgo: Sum region",										test_Sum_Region },
	{ "ZArrayAlgo: SwapElements",									test_SwapElements} ,
	{ "ZArrayAlgo: Unique",											test_Unique} ,
	{ "ZArrayAlgo: Unique given comparator in region",				test_Unique_In_Region}
};

//Now declare the ZUnitTestBlock associated with this.
DECLARE_ZTESTBLOCK(ZArrayAlgo);

/*************************************************************************/

class ArrayValueTestClass
{
public:
	int val;

	ArrayValueTestClass() : val( 0 ) {}
	ArrayValueTestClass(int v) : val(v) {}

	ArrayValueTestClass operator + (const ArrayValueTestClass& _other)
	{
		return ArrayValueTestClass(val + _other.val);
	}
};

struct IfTestFunctor {
	bool operator () (const int& val) { return val > 3; }
};

/*************************************************************************/

static const char* test_Append()
{
	ZArray<int> list;
	ZArray<int> list2;
	ZArray<int> out;

	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list2.PushBack(4);
	list2.PushBack(5);
	list2.PushBack(6);

	ZArrayAlgo::Append(list,list2);

	TASSERT(list.Size() == 6, "Append() created list!\n");
	TASSERT(list.PopFront() == 1, "Append() corrupted list!\n");
	TASSERT(list.PopFront() == 2, "Append() corrupted list!\n");
	TASSERT(list.PopFront() == 3, "Append() corrupted list!\n");
	TASSERT(list.PopFront() == 4, "Append() corrupted list!\n");
	TASSERT(list.PopFront() == 5, "Append() corrupted list!\n");
	TASSERT(list.PopFront() == 6, "Append() corrupted list!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Append_Region()
{
	ZArray<int> list;
	ZArray<int> list2;
	ZArray<int> out;

	list.PushBack(1);
	list.PushBack(2);
	list2.PushBack(3);
	list2.PushBack(4);
	list2.PushBack(5);
	list2.PushBack(6);

	ZArrayAlgo::Append(list,list2,1,3);

	TASSERT(list.Size() == 4, "Append() corrupted list!\n");
	TASSERT(list.PopFront() == 1, "Append() corrupted list!\n");
	TASSERT(list.PopFront() == 2, "Append() corrupted list!\n");
	TASSERT(list.PopFront() == 4, "Append() corrupted list!\n");
	TASSERT(list.PopFront() == 5, "Append() corrupted list!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

struct ApplyTestFunctor{ void operator()(int& _val) const { _val *= -1 ;} };

static const char* test_Apply()
{
	ZArray<int> list;

	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);

	ZArrayAlgo::Apply(list, ApplyTestFunctor());
	TASSERT(list.Size() == 5, "Apply() changed list length!\n");
	TASSERT(list.PopFront() == -1, "Apply() did not apply functor!\n");
	TASSERT(list.PopFront() == -2, "Apply() did not apply functor!\n");
	TASSERT(list.PopFront() == -3, "Apply() did not apply functor!\n");
	TASSERT(list.PopFront() == -4, "Apply() did not apply functor!\n");
	TASSERT(list.PopFront() == -5, "Apply() did not apply functor!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Apply_Region()
{
	ZArray<int> list;

	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);

	ZArrayAlgo::Apply(list, ApplyTestFunctor(), 1, 4);
	TASSERT(list.Size() == 5, "Apply() changed list length!\n");
	TASSERT(list.PopFront() == 1, "Apply() did not apply functor!\n");
	TASSERT(list.PopFront() == -2, "Apply() did not apply functor!\n");
	TASSERT(list.PopFront() == -3, "Apply() did not apply functor!\n");
	TASSERT(list.PopFront() == -4, "Apply() did not apply functor!\n");
	TASSERT(list.PopFront() == 5, "Apply() did not apply functor!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Concatenate()
{
	ZArray<int> list;
	ZArray<int> list2;
	ZArray<int> out;

	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list2.PushBack(4);
	list2.PushBack(5);
	list2.PushBack(6);

	out = ZArrayAlgo::Concatenate(list,list2);

	TASSERT(out.Size() == 6, "Append() created list of incorrect size!\n");
	TASSERT(out.PopFront() == 1, "Append() corrupted list!\n");
	TASSERT(out.PopFront() == 2, "Append() corrupted list!\n");
	TASSERT(out.PopFront() == 3, "Append() corrupted list!\n");
	TASSERT(out.PopFront() == 4, "Append() corrupted list!\n");
	TASSERT(out.PopFront() == 5, "Append() corrupted list!\n");
	TASSERT(out.PopFront() == 6, "Append() corrupted list!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Concatenate_Region()
{
	ZArray<int> list;
	ZArray<int> list2;
	ZArray<int> out;

	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list2.PushBack(5);
	list2.PushBack(6);
	list2.PushBack(7);
	list2.PushBack(8);

	out = ZArrayAlgo::Concatenate(list,1,3,list2,1,3);

	TASSERT(out.Size() == 4, "Append() created list of incorrect size!\n");
	TASSERT(out.PopFront() == 2, "Append() corrupted list!\n");
	TASSERT(out.PopFront() == 3, "Append() corrupted list!\n");
	TASSERT(out.PopFront() == 6, "Append() corrupted list!\n");
	TASSERT(out.PopFront() == 7, "Append() corrupted list!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Contains()
{
	ZArray<int> list;

	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);

	TASSERT( ZArrayAlgo::Contains(list, 2) == true, "Contains() missed an existing element!\n");
	TASSERT( ZArrayAlgo::Contains(list, 5) == false, "Contains() found an nonexisting element!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Contains_Region()
{
	ZArray<int> list;

	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);
	list.PushBack(6);

	TASSERT( ZArrayAlgo::Contains(list, 2, 1, 5) == true, "Contains() missed an existing element inside of range!\n");
	TASSERT( ZArrayAlgo::Contains(list, 6, 1, 5) == false, "Contains() found an existing element outside of range!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_ContainsSub()
{
	ZArray<int> list;

	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);
	list.PushBack(6);

	ZArray<int> list2;

	list2.PushBack(3);
	list2.PushBack(4);
	list2.PushBack(5);

	ZArray<int> list3;

	list3.PushBack(3);
	list3.PushBack(5);

	TASSERT(ZArrayAlgo::ContainsSub(list, list2), "ContainsSub() failed to return true when sub list is contained!");
	TASSERT(!ZArrayAlgo::ContainsSub(list, list3), "ContainsSub() failed to return false when sub list is not contained!");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_ContainsSub_Region()
{
	ZArray<int> list;

	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);
	list.PushBack(6);

	ZArray<int> list2;

	list2.PushBack(3);
	list2.PushBack(4);
	list2.PushBack(5);

	TASSERT(ZArrayAlgo::ContainsSub(list, 2, 5, list2, 0, list2.Size()), "ContainsSub() failed to return true when sub list is contained in region 1!");
	TASSERT(!ZArrayAlgo::ContainsSub(list, 3, 5, list2, 0, list2.Size()), "ContainsSub() failed to return false when sub list is not contained in region!");
	TASSERT(ZArrayAlgo::ContainsSub(list, 3, 5, list2, 1, 3), "ContainsSub() failed to return true when sub list is contained in region 2!");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Copy()
{
	ZArray<int> list;
	ZArray<int> list2;

	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list2.PushBack(5);
	list2.PushBack(6);
	list2.PushBack(7);
	list2.PushBack(8);

	ZArrayAlgo::Copy(list2, list);

	TASSERT( list2.PopFront() == 1, "Copy() failed to copy correct element!\n");
	TASSERT( list2.PopFront() == 2, "Copy() failed to copy correct element!\n");
	TASSERT( list2.PopFront() == 3, "Copy() failed to copy correct element!\n");
	TASSERT( list2.PopFront() == 8, "Copy() overrode out-of-range element!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Copy_Region()
{
	ZArray<int> list;
	ZArray<int> list2;

	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);

	list2.PushBack(5);
	list2.PushBack(6);
	list2.PushBack(7);
	list2.PushBack(8);

	ZArrayAlgo::Copy(list2, 1, 3, list, 2, 4);

	TASSERT( list2.PopFront() == 5, "Copy() failed to copy correct element!\n");
	TASSERT( list2.PopFront() == 3, "Copy() failed to copy correct element!\n");
	TASSERT( list2.PopFront() == 4, "Copy() failed to copy correct element!\n");
	TASSERT( list2.PopFront() == 8, "Copy() failed to copy correct element!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Count()
{
	ZArray<int> list;

	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(2);
	list.PushBack(2);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);

	TASSERT( ZArrayAlgo::Count(list, 2) == 4, "Count() failed to get accurate count of existing element!\n");
	TASSERT( ZArrayAlgo::Count(list, 5) == 0, "Count() failed to get accurate count of nonexisting element!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Count_Region()
{
	ZArray<int> list;

	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(2);
	list.PushBack(2);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);

	TASSERT( ZArrayAlgo::Count(list, 2, 2, 6) == 3, "Count() failed to get accurate count of existing element!\n");
	TASSERT( ZArrayAlgo::Count(list, 1, 2, 6) == 0, "Count() failed to get accurate count of existing element outside of range!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Equal()
{
	ZArray<int> list;
	ZArray<int> list2a;
	ZArray<int> list2b;
	ZArray<int> list3;

	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);

	list2a.PushBack(1);
	list2a.PushBack(2);
	list2a.PushBack(3);
	list2a.PushBack(4);

	list3.PushBack(5);
	list3.PushBack(6);
	list3.PushBack(7);
	list3.PushBack(8);

	TASSERT( ZArrayAlgo::Equal(list, list2a) == true, "Equal() reported nonequailty on identical lists!\n");
	TASSERT( ZArrayAlgo::Equal(list, list3) == false, "Equal() reported equality on different lists!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Equal_In_Region()
{
	ZArray<int> list;
	ZArray<int> list2a;
	ZArray<int> list2b;
	ZArray<int> list3;

	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);

	list2a.PushBack(1);
	list2a.PushBack(2);
	list2a.PushBack(3);
	list2a.PushBack(4);

	list2b.PushBack(0);
	list2b.PushBack(1);
	list2b.PushBack(2);
	list2b.PushBack(3);

	list3.PushBack(5);
	list3.PushBack(6);
	list3.PushBack(7);
	list3.PushBack(8);

	TASSERT( ZArrayAlgo::Equal(list, 1, 4, list2a, 1, 4) == true, "Equal() reported nonequailty on identical sublists!\n");
	TASSERT( ZArrayAlgo::Equal(list, 0, 3, list2b, 1, 4) == true, "Equal() reported nonequailty on identical sublists!\n");
	TASSERT( ZArrayAlgo::Equal(list, 1, 4, list3, 1, 4) == false, "Equal() reported equality on different lists!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Fill()
{
	ZArray<int> list;
	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);

	ZArrayAlgo::Fill(list, 4);

	TASSERT( list.Size() == 3, "Fill() changed size of array!\n");
	TASSERT( list.PopFront() == 4, "Fill() didn't fill array correctly!\n");
	TASSERT( list.PopFront() == 4, "Fill() didn't fill array correctly!\n");
	TASSERT( list.PopFront() == 4, "Fill() didn't fill array correctly!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Fill_Region()
{
	ZArray<int> list;
	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);

	ZArrayAlgo::Fill(list, 6, 1, 4);

	TASSERT( list.Size() == 5, "Fill() changed size of array!\n");
	TASSERT( list.PopFront() == 1, "Fill() didn't fill array correctly!\n");
	TASSERT( list.PopFront() == 6, "Fill() didn't fill array correctly!\n");
	TASSERT( list.PopFront() == 6, "Fill() didn't fill array correctly!\n");
	TASSERT( list.PopFront() == 6, "Fill() didn't fill array correctly!\n");
	TASSERT( list.PopFront() == 5, "Fill() didn't fill array correctly!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Find()
{
	ZArray<int> list;

	list.PushBack(0); // 0
	list.PushBack(1); // 1
	list.PushBack(0); // 2
	list.PushBack(3); // 3
	list.PushBack(3); // 4
	list.PushBack(0); // 5
	list.PushBack(6); // 6
	list.PushBack(3); // 7
	list.PushBack(0); // 8
	list.PushBack(3); // 9
	list.PushBack(3); // 10
	list.PushBack(0); // 11

	TASSERT( ZArrayAlgo::Find(list,42,0) == ZSTL::InvalidPos, "Find() found missing element!\n");
	TASSERT( ZArrayAlgo::Find(list,0,0) == 0, "Find() missed element at front!\n");
	TASSERT( ZArrayAlgo::Find(list,0,4) == 11, "Find() miscounted elements!\n");
	TASSERT( ZArrayAlgo::Find(list,0,23) == ZSTL::InvalidPos, "Find() found excess (nonexistent) element!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Find_Region()
{
	ZArray<int> list;

	list.PushBack(0); // 0
	list.PushBack(1); // 1
	list.PushBack(0); // 2
	list.PushBack(3); // 3
	list.PushBack(3); // 4
	list.PushBack(0); // 5
	list.PushBack(6); // 6
	list.PushBack(3); // 7
	list.PushBack(0); // 8
	list.PushBack(3); // 9
	list.PushBack(3); // 10
	list.PushBack(0); // 11

	TASSERT( ZArrayAlgo::Find(list,42,0,2,10) == ZSTL::InvalidPos, "Find() found missing element!\n");
	TASSERT( ZArrayAlgo::Find(list,0,0,2,10) == 2, "Find() missed element at front!\n");
	TASSERT( ZArrayAlgo::Find(list,0,2,2,10) == 8, "Find() miscounted elements!\n");
	TASSERT( ZArrayAlgo::Find(list,0,23,2,10) == ZSTL::InvalidPos, "Find() found excess (nonexistent) element!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_FindAll()
{ 
	ZArray<int> list;

	list.PushBack(0); // 0
	list.PushBack(1); // 1
	list.PushBack(0); // 2
	list.PushBack(3); // 3
	list.PushBack(3); // 4
	list.PushBack(0); // 5
	list.PushBack(6); // 6
	list.PushBack(3); // 7
	list.PushBack(0); // 8
	list.PushBack(3); // 9
	list.PushBack(3); // 10
	list.PushBack(0); // 11

	ZArray<size_t> inds;
	
	// search for nonexistent value
	inds = ZArrayAlgo::FindAll(list, 10);
	TASSERT(inds.Empty(), "FindAll() found nonexistent elements!\n");

	// search for multiple elements
	inds = ZArrayAlgo::FindAll(list, 3);
	TASSERT(inds.Size() == 5, "FindAll() did not find all elements!\n");
	TASSERT(inds.PopFront() == 3,"FindAll() found element in incorrect position!\n");
	TASSERT(inds.PopFront() == 4,"FindAll() found element in incorrect position!\n");
	TASSERT(inds.PopFront() == 7,"FindAll() found element in incorrect position!\n");
	TASSERT(inds.PopFront() == 9,"FindAll() found element in incorrect position!\n");
	TASSERT(inds.PopFront() == 10,"FindAll() found element in incorrect position!\n");

	// search for existing elements in middle and ends
	inds = ZArrayAlgo::FindAll(list, 0);
	TASSERT(inds.Size() == 5, "FindAll() did not find all elements!\n");
	TASSERT(inds.PopFront() == 0,"FindAll() found element in incorrect position!\n");
	TASSERT(inds.PopFront() == 2,"FindAll() found element in incorrect position!\n");
	TASSERT(inds.PopFront() == 5,"FindAll() found element in incorrect position!\n");
	TASSERT(inds.PopFront() == 8,"FindAll() found element in incorrect position!\n");
	TASSERT(inds.PopFront() == 11,"FindAll() found element in incorrect position!\n");

	return ZTEST_SUCCESS; 
}

/*************************************************************************/

static const char* test_FindAll_Region()
{ 
	ZArray<int> list;

	list.PushBack(0); // 0
	list.PushBack(1); // 1
	list.PushBack(0); // 2
	list.PushBack(3); // 3
	list.PushBack(3); // 4
	list.PushBack(0); // 5
	list.PushBack(6); // 6
	list.PushBack(3); // 7
	list.PushBack(0); // 8
	list.PushBack(3); // 9
	list.PushBack(3); // 10
	list.PushBack(0); // 11

	ZArray<size_t> inds;

	// search for nonexistent value
	inds = ZArrayAlgo::FindAll(list, 10, 3, 9);
	TASSERT(inds.Empty(), "FindAll() found nonexistent elements!\n");

	// search for multiple elements
	inds = ZArrayAlgo::FindAll(list, 3, 3, 9);
	TASSERT(inds.Size() == 3, "FindAll() did not find all elements!\n");
	TASSERT(inds.PopFront() == 3,"FindAll() found element in incorrect position!\n");
	TASSERT(inds.PopFront() == 4,"FindAll() found element in incorrect position!\n");
	TASSERT(inds.PopFront() == 7,"FindAll() found element in incorrect position!\n");

	// search for existing elements in middle and ends
	inds = ZArrayAlgo::FindAll(list, 0, 3, 12);
	TASSERT(inds.Size() == 3, "FindAll() did not find all elements!\n");
	TASSERT(inds.PopFront() == 5,"FindAll() found element in incorrect position!\n");
	TASSERT(inds.PopFront() == 8,"FindAll() found element in incorrect position!\n");
	TASSERT(inds.PopFront() == 11,"FindAll() found element in incorrect position!\n");

	return ZTEST_SUCCESS; 
}

/*************************************************************************/

static const char* test_FindAllOf()
{ 
	ZArray<int> list;

	list.PushBack(0); // 0
	list.PushBack(1); // 1
	list.PushBack(0); // 2
	list.PushBack(3); // 3
	list.PushBack(3); // 4
	list.PushBack(0); // 5
	list.PushBack(6); // 6
	list.PushBack(3); // 7
	list.PushBack(0); // 8
	list.PushBack(3); // 9
	list.PushBack(3); // 10
	list.PushBack(0); // 11

	ZArray<size_t> inds;

	// search for nonexistent value
	const int badvalues[] = {7,9,-3};
	inds = ZArrayAlgo::FindAllOf(list, ZArray<int>(badvalues));
	TASSERT(inds.Empty(), "FindAll() found nonexistent elements!\n");

	// search for existent values
	const int goodvalues[] = {1,6};
	inds = ZArrayAlgo::FindAllOf(list, ZArray<int>(goodvalues));
	TASSERT(inds.Size() == 2, "FindAll() found wrong number of elements!\n");
	TASSERT(inds.PopFront() == 1, "FindAll() found element in wrong position!\n");
	TASSERT(inds.PopFront() == 6, "FindAll() found element in wrong position!\n");

	// search for existent values, including those on ends
	const int goodvalues2[] = {1,3};
	inds = ZArrayAlgo::FindAllOf(list, ZArray<int>(goodvalues2));
	TASSERT(inds.Size() == 6, "FindAll() found wrong number of elements!\n");
	TASSERT(inds.PopFront() == 1, "FindAll() found element in wrong position!\n");
	TASSERT(inds.PopFront() == 3, "FindAll() found element in wrong position!\n");
	TASSERT(inds.PopFront() == 4, "FindAll() found element in wrong position!\n");
	TASSERT(inds.PopFront() == 7, "FindAll() found element in wrong position!\n");
	TASSERT(inds.PopFront() == 9, "FindAll() found element in wrong position!\n");
	TASSERT(inds.PopFront() == 10, "FindAll() found element in wrong position!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_FindAllOf_Region()
{ 
	ZArray<int> list;

	list.PushBack(0); // 0
	list.PushBack(1); // 1
	list.PushBack(0); // 2
	list.PushBack(3); // 3
	list.PushBack(3); // 4
	list.PushBack(5); // 5
	list.PushBack(6); // 6
	list.PushBack(3); // 7
	list.PushBack(0); // 8
	list.PushBack(3); // 9
	list.PushBack(3); // 10
	list.PushBack(0); // 11

	ZArray<size_t> inds;

	// search for nonexistent value
	const int badvals[] = {13,43,14,42};
	inds = ZArrayAlgo::FindAllOf(list, 2, 9, ZArray<int>(badvals), 0, 4);
	TASSERT(inds.Empty(), "FindAll() found nonexistent elements!\n");

	// search for value in empty region
	const int goodvals[] = {1,3,5,6};
	inds = ZArrayAlgo::FindAllOf(list, 0, 1, ZArray<int>(goodvals), 0, 4);
	TASSERT(inds.Empty(), "FindAll() found nonexistent elements in empty region!\n");

	// search for existent values in subregion of target list
	inds = ZArrayAlgo::FindAllOf(list, 2, 9, ZArray<int>(goodvals), 1, 3);
	TASSERT(inds.Size() == 4, "FindAll() found wrong number of elements!\n");
	TASSERT(inds.PopFront() == 3, "FindAll() found element in wrong position!\n");
	TASSERT(inds.PopFront() == 4, "FindAll() found element in wrong position!\n");
	TASSERT(inds.PopFront() == 5, "FindAll() found element in wrong position!\n");
	TASSERT(inds.PopFront() == 7, "FindAll() found element in wrong position!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_FindIf()
{
	ZArray<int> list;
	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);

	ZArray<int> list2;
	list2.PushBack(1);
	list2.PushBack(2);
	list2.PushBack(3);
	list2.PushBack(2);
	list2.PushBack(1);

	TASSERT( ZArrayAlgo::FindIf(list, IfTestFunctor()) == 3, "FindIf() failed to find first element matching functor!\n");
	TASSERT( ZArrayAlgo::FindIf(list2, IfTestFunctor()) == ZSTL::InvalidPos, "FindIf() failed to not find first element matching functor!\n");
	
	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_FindIf_In_Region()
{
	ZArray<int> list;
	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);

	TASSERT( ZArrayAlgo::FindIf(list, IfTestFunctor(), 1, 4) == 3, "FindIf() failed to find first element matching functor in subregion!\n");
	TASSERT( ZArrayAlgo::FindIf(list, IfTestFunctor(), 1, 3) == ZSTL::InvalidPos, "FindIf() found nonconforming element in range!\n");
	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_FindFirst()
{
	ZArray<int> list;
	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);

	TASSERT( ZArrayAlgo::FindFirst(list, 3) == 2, "FindFirst() failed to find first element in correct position!\n");
	TASSERT( ZArrayAlgo::FindFirst(list, 7) == ZSTL::InvalidPos, "FindFirst() found element not in list!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_FindFirst_In_Region()
{
	ZArray<int> list;
	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);
	list.PushBack(6);
	list.PushBack(7);

	TASSERT( ZArrayAlgo::FindFirst(list, 4, 2, 5) == 3, "FindFirst() failed to find first element in correct position in region!\n");
	TASSERT( ZArrayAlgo::FindFirst(list, 4, 4, 7) == ZSTL::InvalidPos, "FindFirst() found element not in region!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_FindFirstOf()
{
	ZArray<int> list;
	
	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);

	ZArray<int> values1;
	ZArray<int> values2;

	values1.PushBack(3);
	values1.PushBack(5);

	values2.PushBack(6);
	values2.PushBack(7);

	TASSERT( ZArrayAlgo::FindFirstOf(list, values1) == 2, "FindFirstOf() failed to find first element in correct position!\n");
	TASSERT( ZArrayAlgo::FindFirstOf(list, values2) == ZSTL::InvalidPos, "FindFirstOf() found element not in list!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_FindFirstOf_In_Region()
{
	ZArray<int> list;

	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);

	ZArray<int> values1;
	ZArray<int> values2;

	values1.PushBack(3);
	values1.PushBack(5);

	values2.PushBack(6);
	values2.PushBack(7);

	TASSERT( ZArrayAlgo::FindFirstOf(list, 3, 5, values1, 0, values1.Size()) == 4, "FindFirstOf() failed to find first element in correct position in region!\n");
	TASSERT( ZArrayAlgo::FindFirstOf(list, 2, 4, values2, 0, values2.Size()) ==ZSTL::InvalidPos, "FindFirstOf() found element not in region!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_FindFirstNot()
{
	ZArray<int> list;
	ZArray<int> list2;

	list.PushBack(3);
	list.PushBack(3);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);

	TASSERT( ZArrayAlgo::FindFirstNot(list, 3) == 3, "FindFirstNotOf() failed to find first element not of given type in correct position!\n");
	
	list2.PushBack(3);
	list2.PushBack(3);
	list2.PushBack(3);
	list2.PushBack(3);
	list2.PushBack(3);

	TASSERT( ZArrayAlgo::FindFirstNot(list2, 3) == ZSTL::InvalidPos, "FindFirstNotOf() failed to find nonexistent nonelement nonoccurence\n");
	
	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_FindFirstNot_In_Region()
{
	ZArray<int> list;
	ZArray<int> list2;

	list.PushBack(3);
	list.PushBack(3);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);

	TASSERT( ZArrayAlgo::FindFirstNot(list, 3, 1, 4) == 3, "FindFirstNotOf() failed to find first element not of given type in correct position!\n");

	list2.PushBack(3);
	list2.PushBack(3);
	list2.PushBack(3);
	list2.PushBack(3);
	list2.PushBack(3);

	TASSERT( ZArrayAlgo::FindFirstNot(list2, 3, 1, 4) == ZSTL::InvalidPos, "FindFirstNotOf() failed to find nonexistent nonelement nonoccurence\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_FindFirstNotOf()
{
	ZArray<int> list;
	ZArray<int> list2;

	list.PushBack(3);
	list.PushBack(3);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);

	ZArray<int> values1;

	values1.PushBack(3);
	values1.PushBack(4);

	TASSERT( ZArrayAlgo::FindFirstNotOf(list, values1) == 4, "FindFirstNotOf() failed to find first element not of given type in correct position!\n");

	list2.PushBack(3);
	list2.PushBack(3);
	list2.PushBack(3);
	list2.PushBack(3);
	list2.PushBack(3);

	TASSERT( ZArrayAlgo::FindFirstNotOf(list2, values1) == ZSTL::InvalidPos, "FindFirstNotOf() failed to find nonexistent nonelement nonoccurence\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_FindFirstNotOf_In_Region()
{
	ZArray<int> list;
	ZArray<int> list2;

	list.PushBack(1);
	list.PushBack(3);
	list.PushBack(3);
	list.PushBack(5);
	list.PushBack(4);

	ZArray<int> values1;

	values1.PushBack(3);
	values1.PushBack(4);

	TASSERT(ZArrayAlgo::FindFirstNotOf(list, 0, 4, values1, 0, values1.Size()) == 0, "FindFirstNotOf() failed to find first element not of given type in correct position in start region!");
	TASSERT(ZArrayAlgo::FindFirstNotOf(list, 1, 4, values1, 0, values1.Size()) == 3, "FindFirstNotOf() failed to find first element not of given type in correct position in end region!");

	list2.PushBack(3);
	list2.PushBack(2);
	list2.PushBack(3);
	list2.PushBack(3);
	list2.PushBack(3);

	TASSERT(ZArrayAlgo::FindFirstNotOf(list2, 2, 4, values1, 0, values1.Size()) == ZSTL::InvalidPos, "FindFirstNotOf() failed to find nonexistent nonelement nonoccurence in region!");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_FindLast()
{
	ZArray<int> list;

	list.PushBack(3);
	list.PushBack(3);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);

	TASSERT( ZArrayAlgo::FindLast(list, 3) == 2, "FindLastOf() failed to find last element not of given type in correct position!\n");
	TASSERT( ZArrayAlgo::FindLast(list, 2) == ZSTL::InvalidPos, "FindLastOf() failed to find nonexistent nonelement nonoccurence\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_FindLast_In_Region()
{
	ZArray<int> list;

	list.PushBack(3);
	list.PushBack(3);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);
	list.PushBack(6);

	TASSERT( ZArrayAlgo::FindLast(list, 3, 1, 4) == 2, "FindLastOf() failed to find last element not of given type in correct position!\n");
	TASSERT( ZArrayAlgo::FindLast(list, 3, 3, 6) == ZSTL::InvalidPos, "FindLastOf() failed to find nonexistent nonelement nonoccurence\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_FindLastOf()
{
	ZArray<int> list;

	list.PushBack(3);
	list.PushBack(3);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);

	ZArray<int> values1;
	ZArray<int> values2;

	values1.PushBack(4);
	values1.PushBack(3);

	values2.PushBack(1);
	values2.PushBack(2);

	TASSERT( ZArrayAlgo::FindLastOf(list, values1) == 3, "FindLastOf() failed to find last element not of given type in correct position!\n");
	TASSERT( ZArrayAlgo::FindLastOf(list, values2) == ZSTL::InvalidPos, "FindLastOf() failed to find nonexistent nonelement nonoccurence\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_FindLastOf_In_Region()
{
	ZArray<int> list;

	list.PushBack(3);
	list.PushBack(3);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);

	ZArray<int> values1;
	ZArray<int> values2;

	values1.PushBack(4);
	values1.PushBack(3);

	values2.PushBack(1);
	values2.PushBack(2);

	TASSERT( ZArrayAlgo::FindLastOf(list, 1, 3, values1, 0, values1.Size()) == 2, "FindLastOf() failed to find last element not of given type in correct position in region!");
	TASSERT( ZArrayAlgo::FindLastOf(list, 2, 4, values2, 0, values2.Size()) == ZSTL::InvalidPos, "FindLastOf() failed to find nonexistent nonelement nonoccurence in region!");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_FindLastNot()
{
	ZArray<int> list;

	list.PushBack(3);
	list.PushBack(3);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);
	list.PushBack(6);
	list.PushBack(3);
	list.PushBack(3);
	list.PushBack(7);
	list.PushBack(8);
	list.PushBack(3);

	TASSERT( ZArrayAlgo::FindLastNot(list, 3) == 9, "FindLastNotOf() returned incorrect position!\n");
	TASSERT( ZArrayAlgo::FindLastNot(list, 11) == 10, "FindLastNotOf() returned incorrect position!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_FindLastNot_In_Region()
{
	ZArray<int> list;

	list.PushBack(3);
	list.PushBack(3);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);
	list.PushBack(6);
	list.PushBack(3);
	list.PushBack(3);
	list.PushBack(7);
	list.PushBack(8);
	list.PushBack(3);

	TASSERT( ZArrayAlgo::FindLastNot(list, 3, 1, 7) == 5, "FindLastNotOf() returned incorrect position!\n");
	TASSERT( ZArrayAlgo::FindLastNot(list, 11, 1, 7) == 6, "FindLastNotOf() returned incorrect position!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_FindLastNotOf()
{
	ZArray<int> list;

	list.PushBack(3);
	list.PushBack(3);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);
	list.PushBack(6);
	list.PushBack(3);
	list.PushBack(3);
	list.PushBack(7);
	list.PushBack(8);
	list.PushBack(3);

	ZArray<int> values1;
	ZArray<int> values2;

	values1.PushBack(4);
	values1.PushBack(3);

	values2.PushBack(1);
	values2.PushBack(2);

	TASSERT( ZArrayAlgo::FindLastNotOf(list, values1) == 9, "FindLastNotOf() returned incorrect position!\n");
	TASSERT( ZArrayAlgo::FindLastNotOf(list, values2) == 10, "FindLastNotOf() returned incorrect position!\n");
	TASSERT( ZArrayAlgo::FindLastNotOf(list, list) == ZSTL::InvalidPos, "FindLastNotOf() returned incorrect position!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_FindLastNotOf_In_Region()
{
	ZArray<int> list;

	list.PushBack(3);
	list.PushBack(3);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);
	list.PushBack(6);
	list.PushBack(3);
	list.PushBack(3);
	list.PushBack(7);
	list.PushBack(8);
	list.PushBack(3);

	ZArray<int> values1;
	ZArray<int> values2;

	values1.PushBack(4);
	values1.PushBack(3);

	values2.PushBack(1);
	values2.PushBack(2);

	TASSERT( ZArrayAlgo::FindLastNotOf(list, 1, 7, values1, 0, values1.Size()) == 5, "FindLastNotOf() returned incorrect position!\n");
	TASSERT( ZArrayAlgo::FindLastNotOf(list, 1, 7, values2, 0, values2.Size()) == 6, "FindLastNotOf() returned incorrect position!\n");
	TASSERT( ZArrayAlgo::FindLastNotOf(list, 1, 7, list, 0, list.Size()) == ZSTL::InvalidPos, "FindLastNotOf() returned incorrect position!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_FindSub()
{
	ZArray<int> list;

	list.PushBack(3);
	list.PushBack(3);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);
	list.PushBack(6);
	list.PushBack(3);
	list.PushBack(3);
	list.PushBack(7);
	list.PushBack(8);
	list.PushBack(3);

	ZArray<int> values1;
	ZArray<int> values2;

	values1.PushBack(4);
	values1.PushBack(5);
	values1.PushBack(6);

	values2.PushBack(3);
	values2.PushBack(3);
	values2.PushBack(8);

	TASSERT( ZArrayAlgo::FindSub(list, values1) == 3, "FindSub() returned incorrect position!");
	TASSERT( ZArrayAlgo::FindSub(list, values2) == ZSTL::InvalidPos, "FindSub() failed to return invalid position with invalid sub array!");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_FindSub_In_Region()
{
	ZArray<int> list;

	list.PushBack(3);
	list.PushBack(3);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);
	list.PushBack(6);
	list.PushBack(3);
	list.PushBack(3);
	list.PushBack(7);
	list.PushBack(8);
	list.PushBack(3);

	ZArray<int> values1;
	ZArray<int> values2;

	values1.PushBack(4);
	values1.PushBack(5);
	values1.PushBack(6);

	values2.PushBack(3);
	values2.PushBack(3);
	values2.PushBack(8);

	TASSERT( ZArrayAlgo::FindSub(list, 2, 6, values1, 0, values1.Size()) == 3, "FindSub() returned incorrect position in region!");
	TASSERT( ZArrayAlgo::FindSub(list, 2, 4, values1, 0, values1.Size()) == ZSTL::InvalidPos, "FindSub() returned valid position in region with invalid sub-array region!");
	TASSERT( ZArrayAlgo::FindSub(list, 2, 8, values1, 1, values1.Size()) == 4, "FindSub() returned incorrect position in region!");
	TASSERT( ZArrayAlgo::FindSub(list, 2, list.Size(), values2, 1, values2.Size()) == ZSTL::InvalidPos, "FindSub() failed to return invalid position with invalid sub array!");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

class FoldLeftTestFunctor
{
public:
	FoldLeftTestFunctor() {}
	~FoldLeftTestFunctor() {}

	int operator () (const ArrayValueTestClass& _lhs, const ArrayValueTestClass& _rhs) const
	{
		if (_rhs.val > 3)
			return _lhs.val + _rhs.val;
		else
			return _lhs.val;
	}
};

static const char* test_FoldLeft()
{
	ZArray<int> list;
	int ans;

	ZArray<ArrayValueTestClass> list2;
	ArrayValueTestClass ans2;

	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);

	ans = ZArrayAlgo::FoldLeft(list, FoldLeftTestFunctor(), 10); //only add values greater than 3
	TASSERT (ans == 19, "FoldLeft() failed to accumulate correctly!\n");

	list2.PushBack(1);
	list2.PushBack(2);
	list2.PushBack(3);
	list2.PushBack(4);
	list2.PushBack(5);

	ans2 = ZArrayAlgo::FoldLeft(list2, FoldLeftTestFunctor(), ArrayValueTestClass(10)); //only add values greater than 3
	TASSERT (ans2.val == 19, "FoldLeft() failed to accumulate correctly!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_FoldLeft_Region()
{
	ZArray<int> list;
	int ans;

	ZArray<ArrayValueTestClass> list2;
	ArrayValueTestClass ans2;

	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);

	ans = ZArrayAlgo::FoldLeft(list, FoldLeftTestFunctor(), 10, 1, 4); //only add values greater than 3
	TASSERT (ans == 14, "FoldLeft() failed to accumulate correctly in region!\n");

	list2.PushBack(1);
	list2.PushBack(2);
	list2.PushBack(3);
	list2.PushBack(4);
	list2.PushBack(5);

	ans2 = ZArrayAlgo::FoldLeft(list2, FoldLeftTestFunctor(), ArrayValueTestClass(10), 1, 4); //only add values greater than 3
	TASSERT (ans2.val == 14, "FoldLeft() failed to accumulate correctly!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

class FoldRightTestFunctor
{
public:
	FoldRightTestFunctor() {}
	~FoldRightTestFunctor() {}

	int operator () (const int& _lhs, const int& _rhs) const
	{
		return _lhs - _rhs;
	}
};

static const char* test_FoldRight()
{
	ZArray<int> list;
	int ans;

	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);

	ans = ZArrayAlgo::FoldLeft(list, FoldRightTestFunctor(), 10);
	TASSERT(ans == -5, "FoldLeft() with subtraction operator returned incorrect value!");

	ans = ZArrayAlgo::FoldRight(list, FoldRightTestFunctor(), 10);
	TASSERT (ans == -7, "FoldRight() with subtraction operator returned incorrect value!");
	
	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_FoldRight_Region()
{
	ZArray<int> list;
	int ans;

	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);

	ans = ZArrayAlgo::FoldLeft(list, FoldRightTestFunctor(), 10, 0, 4);
	TASSERT(ans == 0, "FoldLeft() with subtraction operator returned incorrect value in region!");

	ans = ZArrayAlgo::FoldRight(list, FoldRightTestFunctor(), 10, 1, 5);
	TASSERT (ans == 8, "FoldRight() with subtraction operator returned incorrect value in region!");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

struct GenerateTestFunctor
{
	int operator () ( size_t _index, size_t _count )
	{
		return ((int)_count) - ((int)_index);
	}
};

static const char* test_Generate()
{
	ZArray<int> list;
	list.Resize(5);
	ZArrayAlgo::Generate(list, GenerateTestFunctor());

	TASSERT( list.Size() == 5, "Generate() changed size of list!\n");
	TASSERT( list.PopFront() == 5, "Generate() producted incorrect list!\n");
	TASSERT( list.PopFront() == 4, "Generate() producted incorrect list!\n");
	TASSERT( list.PopFront() == 3, "Generate() producted incorrect list!\n");
	TASSERT( list.PopFront() == 2, "Generate() producted incorrect list!\n");
	TASSERT( list.PopFront() == 1, "Generate() producted incorrect list!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Generate_In_Region()
{
	ZArray<int> list;
	list.PushBack(9);
	list.PushBack(9);
	list.PushBack(9);
	list.PushBack(9);
	list.PushBack(9);
	ZArrayAlgo::Generate(list, GenerateTestFunctor(), 1, 4);

	TASSERT( list.Size() == 5, "Generate() changed size of list!\n");
	TASSERT( list.PopFront() == 9, "Generate() producted incorrect list!\n");
	TASSERT( list.PopFront() == 3, "Generate() producted incorrect list!\n");
	TASSERT( list.PopFront() == 2, "Generate() producted incorrect list!\n");
	TASSERT( list.PopFront() == 1, "Generate() producted incorrect list!\n");
	TASSERT( list.PopFront() == 9, "Generate() producted incorrect list!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

struct MapTestFunctor { void operator() (int& _val) const { _val *= -1; } };

static const char* test_Map()
{
	ZArray<int> list;
	ZArray<int> out;
	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);

	out = ZArrayAlgo::Map(list, MapTestFunctor());
	
	TASSERT( list.Size() == 5, "Map() changed input array size!\n");
	TASSERT( list.PopFront() == 1, "Map() changed input array!\n");
	TASSERT( list.PopFront() == 2, "Map() changed input array!\n");
	TASSERT( list.PopFront() == 3, "Map() changed input array!\n");
	TASSERT( list.PopFront() == 4, "Map() changed input array!\n");
	TASSERT( list.PopFront() == 5, "Map() changed input array!\n");

	TASSERT( out.Size() == 5, "Map() returned range of incorrect size!\n");
	TASSERT( out.PopFront() == -1, "Map() returned incorrect range!\n");
	TASSERT( out.PopFront() == -2, "Map() returned incorrect range!\n");
	TASSERT( out.PopFront() == -3, "Map() returned incorrect range!\n");
	TASSERT( out.PopFront() == -4, "Map() returned incorrect range!\n");
	TASSERT( out.PopFront() == -5, "Map() returned incorrect range!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Map_Region()
{
	ZArray<int> list;
	ZArray<int> out;
	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);

	out = ZArrayAlgo::Map(list, MapTestFunctor(), 1, 4);

	TASSERT( list.Size() == 5, "Map() changed input array size!\n");
	TASSERT( list.PopFront() == 1, "Map() changed input array!\n");
	TASSERT( list.PopFront() == 2, "Map() changed input array!\n");
	TASSERT( list.PopFront() == 3, "Map() changed input array!\n");
	TASSERT( list.PopFront() == 4, "Map() changed input array!\n");
	TASSERT( list.PopFront() == 5, "Map() changed input array!\n");

	TASSERT( out.Size() == 3, "Map() returned range of incorrect size!\n");
	TASSERT( out.PopFront() == -2, "Map() returned incorrect range!\n");
	TASSERT( out.PopFront() == -3, "Map() returned incorrect range!\n");
	TASSERT( out.PopFront() == -4, "Map() returned incorrect range!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Max()
{
	ZArray<int> list;
	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(5);
	list.PushBack(4);
	list.PushBack(2);
	list.PushBack(7);
	list.PushBack(3);
	list.PushBack(0);
	list.PushBack(5);

	ZArray<int> list2;
	list2.PushBack(1);
	list2.PushBack(2);
	list2.PushBack(5);
	list2.PushBack(5);
	list2.PushBack(5);
	list2.PushBack(4);
	list2.PushBack(2);

	TASSERT( ZArrayAlgo::Max(list) == 5, "Max() failed to find max at expected place!\n");
	TASSERT( ZArrayAlgo::Max(list2) == 2, "Max() failed to find max at expected place for multiple max values!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Max_In_Region()
{
	ZArray<int> list;
	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(5);
	list.PushBack(4);
	list.PushBack(2);
	list.PushBack(7);
	list.PushBack(3);
	list.PushBack(0);
	list.PushBack(5);

	ZArray<int> list2;
	list2.PushBack(1);
	list2.PushBack(2);
	list2.PushBack(5);
	list2.PushBack(5);
	list2.PushBack(5);
	list2.PushBack(4);
	list2.PushBack(2);

	TASSERT( ZArrayAlgo::Max(list, 3, 8 ) == 5, "Max() failed to find max at expected place!\n");
	TASSERT( ZArrayAlgo::Max(list2, 1, 6) == 2, "Max() failed to find max at expected place for multiple max values!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/
struct TestComparatorFunctor
{
	//operator overload which returns 1 if a < b, 0 if a == b, and -1 if a > b
	//this basically means that this comparator returns the reverse of usual
	int operator () (const int& _a, const int& _b) const
	{
		if (_a < _b)
		{
			return 1;
		}
		else if (_b < _a)
		{
			return -1;
		}
		else
		{
			return 0;
		}
	}
};
static const char* test_Max_Comparator()
{
	ZArray<int> list;
	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(5);
	list.PushBack(4);
	list.PushBack(2);
	list.PushBack(7);
	list.PushBack(3);
	list.PushBack(0);
	list.PushBack(5);

	ZArray<int> list2;
	list2.PushBack(4);
	list2.PushBack(1);
	list2.PushBack(2);
	list2.PushBack(1);
	list2.PushBack(1);
	list2.PushBack(1);
	list2.PushBack(4);
	list2.PushBack(2);

	TASSERT( ZArrayAlgo::Max(list, TestComparatorFunctor()) == 7, "Max() failed to find max at expected place!\n");
	TASSERT( ZArrayAlgo::Max(list2, TestComparatorFunctor()) == 1, "Max() failed to find max at expected place for multiple max values!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Max_Comparator_In_Region()
{
	ZArray<int> list;
	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(5);
	list.PushBack(4);
	list.PushBack(2);
	list.PushBack(7);
	list.PushBack(3);
	list.PushBack(0);
	list.PushBack(5);

	ZArray<int> list2;
	list2.PushBack(4);
	list2.PushBack(1);
	list2.PushBack(2);
	list2.PushBack(1);
	list2.PushBack(1);
	list2.PushBack(1);
	list2.PushBack(4);
	list2.PushBack(2);

	TASSERT( ZArrayAlgo::Max(list, TestComparatorFunctor(), 0, 4) == 0, "Max() failed to find max at expected place in region!");
	TASSERT( ZArrayAlgo::Max(list2, TestComparatorFunctor(), 4, 6) == 4, "Max() failed to find max at expected place for multiple max values in region!");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Min()
{
	ZArray<int> list;
	list.PushBack(2);
	list.PushBack(7);
	list.PushBack(5);
	list.PushBack(1);
	list.PushBack(4);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(0);
	list.PushBack(5);

	ZArray<int> list2;
	list2.PushBack(3);
	list2.PushBack(2);
	list2.PushBack(3);
	list2.PushBack(2);
	list2.PushBack(1);
	list2.PushBack(1);
	list2.PushBack(1);
	list2.PushBack(4);
	list2.PushBack(2);

	TASSERT( ZArrayAlgo::Min(list) == 7, "Min() failed to find min at expected place!\n");
	TASSERT( ZArrayAlgo::Min(list2) == 4, "Min() failed to find min at expected place for multiple max values!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Min_In_Region()
{
	ZArray<int> list;
	list.PushBack(2);
	list.PushBack(7);
	list.PushBack(5);
	list.PushBack(1);
	list.PushBack(4);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(0);
	list.PushBack(5);

	ZArray<int> list2;
	list2.PushBack(3);
	list2.PushBack(2);
	list2.PushBack(3);
	list2.PushBack(2);
	list2.PushBack(1);
	list2.PushBack(1);
	list2.PushBack(1);
	list2.PushBack(4);
	list2.PushBack(2);

	TASSERT( ZArrayAlgo::Min(list, 1, 6) == 3, "Min() failed to find min at expected place!\n");
	TASSERT( ZArrayAlgo::Min(list2, 3, 7) == 4, "Min() failed to find min at expected place for multiple max values!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Min_Comparator()
{
	ZArray<int> list;
	list.PushBack(2);
	list.PushBack(7);
	list.PushBack(5);
	list.PushBack(1);
	list.PushBack(4);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(0);
	list.PushBack(5);

	ZArray<int> list2;
	list2.PushBack(3);
	list2.PushBack(2);
	list2.PushBack(3);
	list2.PushBack(2);
	list2.PushBack(1);
	list2.PushBack(1);
	list2.PushBack(1);
	list2.PushBack(4);
	list2.PushBack(2);

	TASSERT( ZArrayAlgo::Min(list, TestComparatorFunctor()) == 1, "Min() failed to find min at expected place!\n");
	TASSERT( ZArrayAlgo::Min(list2, TestComparatorFunctor()) == 7, "Min() failed to find min at expected place for multiple max values!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Min_Comparator_In_Region()
{
	ZArray<int> list;
	list.PushBack(2);
	list.PushBack(7);
	list.PushBack(5);
	list.PushBack(1);
	list.PushBack(4);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(0);
	list.PushBack(5);

	ZArray<int> list2;
	list2.PushBack(3);
	list2.PushBack(2);
	list2.PushBack(3);
	list2.PushBack(2);
	list2.PushBack(4);
	list2.PushBack(4);
	list2.PushBack(4);
	list2.PushBack(4);
	list2.PushBack(2);

	TASSERT( ZArrayAlgo::Min(list, TestComparatorFunctor(), 2, 6) == 2, "Min() failed to find min at expected place in region!");
	TASSERT( ZArrayAlgo::Min(list2, TestComparatorFunctor(), 0, 4) == 0, "Min() failed to find min at expected place for multiple max values in region!");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Remove()
{
	ZArray<int> list;

	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(2);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);

	TASSERT(ZArrayAlgo::Remove(list, 8) == ZSTL::InvalidPos, "Remove() did not take out element at correct position!\n");
	TASSERT(list.Size() == 7, "Remove() did not change list size correctly!\n");
	TASSERT(ZArrayAlgo::Remove(list, 2) == 1, "Remove() did not take out element at correct position!\n");
	TASSERT(list.Size() == 6, "Remove() did not change list size correctly!\n");
	TASSERT(ZArrayAlgo::Remove(list, 5) == 5, "Remove() did not take out element at correct position!\n");
	TASSERT(list.Size() == 5, "Remove() did not change list size correctly!\n");
	TASSERT(ZArrayAlgo::Remove(list, 1) == 0, "Remove() did not take out element at correct position!\n");
	TASSERT(list.Size() == 4, "Remove() did not change list size correctly!\n");

	TASSERT( list.PopFront() == 2, "Remove() created incorrect list!\n");
	TASSERT( list.PopFront() == 2, "Remove() created incorrect list!\n");
	TASSERT( list.PopFront() == 3, "Remove() created incorrect list!\n");
	TASSERT( list.PopFront() == 4, "Remove() created incorrect list!\n");
	TASSERT( list.Empty(), "Remove() created incorrectly sized list!\n");
	
	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Remove_In_Region()
{
	ZArray<int> list;

	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(2);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);

	TASSERT(ZArrayAlgo::Remove(list, 8, 1, 6 ) == ZSTL::InvalidPos, "Remove() did not take out element at correct position!\n");
	TASSERT(list.Size() == 7, "Remove() did not change list size correctly!\n");
	TASSERT(ZArrayAlgo::Remove(list, 2, 1, 6 ) == 1, "Remove() did not take out element at correct position!\n");
	TASSERT(list.Size() == 6, "Remove() did not change list size correctly!\n");
	TASSERT(ZArrayAlgo::Remove(list, 5, 1, 6 ) == 5, "Remove() did not take out element at correct position!\n");
	TASSERT(list.Size() == 5, "Remove() did not change list size correctly!\n");
	TASSERT(ZArrayAlgo::Remove(list, 1, 1, 5 ) == ZSTL::InvalidPos, "Remove() took out an element at the wrong place!\n");
	TASSERT(list.Size() == 5, "Remove() changed list size correctly!\n");

	TASSERT( list.PopFront() == 1, "Remove() created incorrect list!\n");
	TASSERT( list.PopFront() == 2, "Remove() created incorrect list!\n");
	TASSERT( list.PopFront() == 2, "Remove() created incorrect list!\n");
	TASSERT( list.PopFront() == 3, "Remove() created incorrect list!\n");
	TASSERT( list.PopFront() == 4, "Remove() created incorrect list!\n");
	TASSERT( list.Empty(), "Remove() created incorrectly sized list!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_RemoveAll()
{
	ZArray<int> list;

	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(2);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);

	TASSERT( ZArrayAlgo::RemoveAll(list, 2) == 3, "RemoveAll() claims wrong number of removals!\n");
	TASSERT( list.Size() == 4, "RemoveAll() failed to remove all elements of supplied value!\n");
	TASSERT( list.PopFront() == 1, "RemoveAll() corrupted list!\n");
	TASSERT( list.PopFront() == 3, "RemoveAll() corrupted list!\n");
	TASSERT( list.PopFront() == 4, "RemoveAll() corrupted list!\n");
	TASSERT( list.PopFront() == 5, "RemoveAll() corrupted list!\n");
	TASSERT( list.Empty(), "RemoveAll() corrupted list!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_RemoveAll_In_Region()
{
	ZArray<int> list;

	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(2);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);

	TASSERT( ZArrayAlgo::RemoveAll(list, 2, 2,7 ) == 2, "RemoveAll() claims wrong number of removals!\n");
	TASSERT( list.Size() == 5, "RemoveAll() failed to remove all elements of supplied value!\n");
	TASSERT( list.PopFront() == 1, "RemoveAll() corrupted list!\n");
	TASSERT( list.PopFront() == 2, "RemoveAll() corrupted list!\n");
	TASSERT( list.PopFront() == 3, "RemoveAll() corrupted list!\n");
	TASSERT( list.PopFront() == 4, "RemoveAll() corrupted list!\n");
	TASSERT( list.PopFront() == 5, "RemoveAll() corrupted list!\n");
	TASSERT( list.Empty(), "RemoveAll() corrupted list!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/
// returns true if given odd number
struct RemoveIfTestFunctor{ bool operator()(int _val) { return (_val%2) == 1;}};

static const char* test_RemoveIf()
{
	ZArray<int> list;

	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(2);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);

	TASSERT( ZArrayAlgo::RemoveIf(list,RemoveIfTestFunctor()) == 3, "RemoveIf() claims wrong number of removals!\n");
	TASSERT( list.Size() == 4, "RemoveIf() failed to remove all elements of supplied value!\n");
	TASSERT( list.PopFront() == 2, "RemoveIf() corrupted list!\n");
	TASSERT( list.PopFront() == 2, "RemoveIf() corrupted list!\n");
	TASSERT( list.PopFront() == 2, "RemoveIf() corrupted list!\n");
	TASSERT( list.PopFront() == 4, "RemoveIf() corrupted list!\n");
	TASSERT( list.Empty(), "RemoveIf() corrupted list!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_RemoveIf_In_Region()
{
	ZArray<int> list;

	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(2);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);

	TASSERT( ZArrayAlgo::RemoveIf(list,RemoveIfTestFunctor(), 1, 5) == 1, "RemoveIf() claims wrong number of removals!\n");
	TASSERT( list.Size() == 6, "RemoveIf() failed to remove all elements of supplied value!\n");
	TASSERT( list.PopFront() == 1, "RemoveIf() corrupted list!\n");
	TASSERT( list.PopFront() == 2, "RemoveIf() corrupted list!\n");
	TASSERT( list.PopFront() == 2, "RemoveIf() corrupted list!\n");
	TASSERT( list.PopFront() == 2, "RemoveIf() corrupted list!\n");
	TASSERT( list.PopFront() == 4, "RemoveIf() corrupted list!\n");
	TASSERT( list.PopFront() == 5, "RemoveIf() corrupted list!\n");
	TASSERT( list.Empty(), "RemoveIf() corrupted list!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_RemoveUpTo()
{
	ZArray<int> list;

	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(2);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);

	TASSERT( ZArrayAlgo::RemoveUpTo(list, 2, 2) == 2, "RemoveUpTo() claims incorrect number of removals!\n");
	TASSERT( list.Size() == 5, "RemoveUpTo() resized list to incorrect size!\n");
	TASSERT( list.At(0) == 1, "RemoveUpTo() corrupted list!\n");
	TASSERT( list.At(1) == 2, "RemoveUpTo() corrupted list!\n");
	TASSERT( list.At(2) == 3, "RemoveUpTo() corrupted list!\n");
	TASSERT( list.At(3) == 4, "RemoveUpTo() corrupted list!\n");
	TASSERT( list.At(4) == 5, "RemoveUpTo() corrupted list!\n");

	TASSERT( ZArrayAlgo::RemoveUpTo(list, 3, 12) == 1, "RemoveUpTo() claims incorrect number of removals!\n");
	TASSERT( list.Size() == 4, "RemoveUpTo() resized list to incorrect size!\n");
	TASSERT( list.At(0) == 1, "RemoveUpTo() corrupted list!\n");
	TASSERT( list.At(1) == 2, "RemoveUpTo() corrupted list!\n");
	TASSERT( list.At(2) == 4, "RemoveUpTo() corrupted list!\n");
	TASSERT( list.At(3) == 5, "RemoveUpTo() corrupted list!\n");

	TASSERT( ZArrayAlgo::RemoveUpTo(list, 1337, 12) == 0, "RemoveUpTo() claims incorrect number of removals!\n");
	TASSERT( list.Size() == 4, "RemoveUpTo() resized list to incorrect size!\n");
	TASSERT( list.At(0) == 1, "RemoveUpTo() corrupted list!\n");
	TASSERT( list.At(1) == 2, "RemoveUpTo() corrupted list!\n");
	TASSERT( list.At(2) == 4, "RemoveUpTo() corrupted list!\n");
	TASSERT( list.At(3) == 5, "RemoveUpTo() corrupted list!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_RemoveUpTo_In_Region()
{
	ZArray<int> list;

	list.PushBack(2);
	list.PushBack(2);
	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(2);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);

	TASSERT( ZArrayAlgo::RemoveUpTo(list, 2, 2, 2, 9) == 2, "RemoveUpTo() claims incorrect number of removals!\n");
	TASSERT( list.Size() == 7, "RemoveUpTo() resized list to incorrect size!\n");
	TASSERT( list.At(0) == 2, "RemoveUpTo() corrupted list!\n");
	TASSERT( list.At(1) == 2, "RemoveUpTo() corrupted list!\n");
	TASSERT( list.At(2) == 1, "RemoveUpTo() corrupted list!\n");
	TASSERT( list.At(3) == 2, "RemoveUpTo() corrupted list!\n");
	TASSERT( list.At(4) == 3, "RemoveUpTo() corrupted list!\n");
	TASSERT( list.At(5) == 4, "RemoveUpTo() corrupted list!\n");
	TASSERT( list.At(6) == 5, "RemoveUpTo() corrupted list!\n");

	TASSERT( ZArrayAlgo::RemoveUpTo(list, 3, 12, 2, 7) == 1, "RemoveUpTo() claims incorrect number of removals!\n");
	TASSERT( list.Size() == 6, "RemoveUpTo() resized list to incorrect size!\n");
	TASSERT( list.At(0) == 2, "RemoveUpTo() corrupted list!\n");
	TASSERT( list.At(1) == 2, "RemoveUpTo() corrupted list!\n");
	TASSERT( list.At(2) == 1, "RemoveUpTo() corrupted list!\n");
	TASSERT( list.At(3) == 2, "RemoveUpTo() corrupted list!\n");
	TASSERT( list.At(4) == 4, "RemoveUpTo() corrupted list!\n");
	TASSERT( list.At(5) == 5, "RemoveUpTo() corrupted list!\n");

	TASSERT( ZArrayAlgo::RemoveUpTo(list, 1337, 12, 2, 6) == 0, "RemoveUpTo() claims incorrect number of removals!\n");
	TASSERT( list.Size() == 6, "RemoveUpTo() resized list to incorrect size!\n");
	TASSERT( list.At(0) == 2, "RemoveUpTo() corrupted list!\n");
	TASSERT( list.At(1) == 2, "RemoveUpTo() corrupted list!\n");
	TASSERT( list.At(2) == 1, "RemoveUpTo() corrupted list!\n");
	TASSERT( list.At(3) == 2, "RemoveUpTo() corrupted list!\n");
	TASSERT( list.At(4) == 4, "RemoveUpTo() corrupted list!\n");
	TASSERT( list.At(5) == 5, "RemoveUpTo() corrupted list!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Replace()
{
	ZArray<int> list;

	list.PushBack(2);
	list.PushBack(2);
	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(2);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);

	TASSERT( ZArrayAlgo::Replace(list, 2, 42) == 5, "Replace() claims wrong number of replacements!\n");
	TASSERT( list.Size() == 9, "Replace() changed size of list!\n");
	TASSERT( list.PopFront() == 42, "Replace() did not replace element correctly!\n");
	TASSERT( list.PopFront() == 42, "Replace() did not replace element correctly!\n");
	TASSERT( list.PopFront() == 1, "Replace() did not replace element correctly!\n");
	TASSERT( list.PopFront() == 42, "Replace() did not replace element correctly!\n");
	TASSERT( list.PopFront() == 42, "Replace() did not replace element correctly!\n");
	TASSERT( list.PopFront() == 42, "Replace() did not replace element correctly!\n");
	TASSERT( list.PopFront() == 3, "Replace() did not replace element correctly!\n");
	TASSERT( list.PopFront() == 4, "Replace() did not replace element correctly!\n");
	TASSERT( list.PopFront() == 5, "Replace() did not replace element correctly!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Replace_In_Region()
{
	ZArray<int> list;

	list.PushBack(2);
	list.PushBack(2);
	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(2);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);

	TASSERT( ZArrayAlgo::Replace(list, 2, 42, 2, 9) == 3, "Replace() claims wrong number of replacements!\n");
	TASSERT( list.Size() == 9, "Replace() changed size of list!\n");
	TASSERT( list.PopFront() == 2, "Replace() did not replace element correctly!\n");
	TASSERT( list.PopFront() == 2, "Replace() did not replace element correctly!\n");
	TASSERT( list.PopFront() == 1, "Replace() did not replace element correctly!\n");
	TASSERT( list.PopFront() == 42, "Replace() did not replace element correctly!\n");
	TASSERT( list.PopFront() == 42, "Replace() did not replace element correctly!\n");
	TASSERT( list.PopFront() == 42, "Replace() did not replace element correctly!\n");
	TASSERT( list.PopFront() == 3, "Replace() did not replace element correctly!\n");
	TASSERT( list.PopFront() == 4, "Replace() did not replace element correctly!\n");
	TASSERT( list.PopFront() == 5, "Replace() did not replace element correctly!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

// returns true if given odd number
struct ReplaceIfTestFunctor{ bool operator ()(int _val){ return (_val%2) == 1;} };

static const char* test_ReplaceIf()
{
	ZArray<int> list;

	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);
	list.PushBack(6);

	TASSERT( ZArrayAlgo::ReplaceIf(list, ReplaceIfTestFunctor(), 42) == 3, "ReplaceIf() claims wrong number of replacements!\n");
	TASSERT( list.Size() == 6, "ReplaceIf() changed size of list!\n");
	TASSERT( list.PopFront() == 42, "ReplaceIf() corrupted list!\n");
	TASSERT( list.PopFront() == 2, "ReplaceIf() corrupted list!\n");
	TASSERT( list.PopFront() == 42, "ReplaceIf() corrupted list!\n");
	TASSERT( list.PopFront() == 4, "ReplaceIf() corrupted list!\n");
	TASSERT( list.PopFront() == 42, "ReplaceIf() corrupted list!\n");
	TASSERT( list.PopFront() == 6, "ReplaceIf() corrupted list!\n");
	
	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_ReplaceIf_In_Region()
{
	ZArray<int> list;

	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);
	list.PushBack(6);

	TASSERT( ZArrayAlgo::ReplaceIf(list, ReplaceIfTestFunctor(), 42, 1, 3) == 1, "ReplaceIf() claims wrong number of replacements!\n");
	TASSERT( list.Size() == 6, "ReplaceIf() changed size of list!\n");
	TASSERT( list.PopFront() == 1, "ReplaceIf() corrupted list!\n");
	TASSERT( list.PopFront() == 2, "ReplaceIf() corrupted list!\n");
	TASSERT( list.PopFront() == 42, "ReplaceIf() corrupted list!\n");
	TASSERT( list.PopFront() == 4, "ReplaceIf() corrupted list!\n");
	TASSERT( list.PopFront() == 5, "ReplaceIf() corrupted list!\n");
	TASSERT( list.PopFront() == 6, "ReplaceIf() corrupted list!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Reverse()
{
	ZArray<int> list;

	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);
	list.PushBack(6);

	ZArrayAlgo::Reverse(list);
	TASSERT( list.Size() == 6, "Reverse() changed size of list!\n");
	TASSERT( list.PopFront() == 6, "Reverse() corrupted list!\n");
	TASSERT( list.PopFront() == 5, "Reverse() corrupted list!\n");
	TASSERT( list.PopFront() == 4, "Reverse() corrupted list!\n");
	TASSERT( list.PopFront() == 3, "Reverse() corrupted list!\n");
	TASSERT( list.PopFront() == 2, "Reverse() corrupted list!\n");
	TASSERT( list.PopFront() == 1, "Reverse() corrupted list!\n");
	
	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Reverse_Region()
{
	ZArray<int> list;

	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);
	list.PushBack(6);

	// test reverse on same element
	ZArrayAlgo::Reverse(list,0,0);
	ZArrayAlgo::Reverse(list,3,3);
	TASSERT( list.Size() == 6, "Reverse() changed size of list!\n");
	TASSERT( list.At(0) == 1, "Reverse() corrupted list!\n");
	TASSERT( list.At(1) == 2, "Reverse() corrupted list!\n");
	TASSERT( list.At(2) == 3, "Reverse() corrupted list!\n");
	TASSERT( list.At(3) == 4, "Reverse() corrupted list!\n");
	TASSERT( list.At(4) == 5, "Reverse() corrupted list!\n");
	TASSERT( list.At(5) == 6, "Reverse() corrupted list!\n");

	// okay, real test
	ZArrayAlgo::Reverse(list,2,5);
	TASSERT( list.Size() == 6, "Reverse() changed size of list!\n");
	TASSERT( list.PopFront() == 1, "Reverse() corrupted list!\n");
	TASSERT( list.PopFront() == 2, "Reverse() corrupted list!\n");
	TASSERT( list.PopFront() == 5, "Reverse() corrupted list!\n");
	TASSERT( list.PopFront() == 4, "Reverse() corrupted list!\n");
	TASSERT( list.PopFront() == 3, "Reverse() corrupted list!\n");
	TASSERT( list.PopFront() == 6, "Reverse() corrupted list!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Rotate()
{
	ZArray<int> list;
	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);
	list.PushBack(6);

	// test rotate at front
	ZArrayAlgo::Rotate(list, 0);
	TASSERT( list.Size() == 6, "Rotate() changed length of array!\n");
	TASSERT( list.PopFront() == 1, "Rotate() misordered list!\n");
	TASSERT( list.PopFront() == 2, "Rotate() misordered list!\n");
	TASSERT( list.PopFront() == 3, "Rotate() misordered list!\n");
	TASSERT( list.PopFront() == 4, "Rotate() misordered list!\n");
	TASSERT( list.PopFront() == 5, "Rotate() misordered list!\n");
	TASSERT( list.PopFront() == 6, "Rotate() misordered list!\n");
	
	// test rotate at middle
	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);
	list.PushBack(6);
	ZArrayAlgo::Rotate(list, 3);
	TASSERT( list.Size() == 6, "Rotate() changed length of array!\n");
	TASSERT( list.PopFront() == 4, "Rotate() misordered list!\n");
	TASSERT( list.PopFront() == 5, "Rotate() misordered list!\n");
	TASSERT( list.PopFront() == 6, "Rotate() misordered list!\n");
	TASSERT( list.PopFront() == 1, "Rotate() misordered list!\n");
	TASSERT( list.PopFront() == 2, "Rotate() misordered list!\n");
	TASSERT( list.PopFront() == 3, "Rotate() misordered list!\n");

	// test pivot back
	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);
	list.PushBack(6);
	ZArrayAlgo::Rotate(list, 5);
	TASSERT( list.Size() == 6, "Rotate() changed length of array!\n");
	TASSERT( list.PopFront() == 6, "Rotate() misordered list!\n");
	TASSERT( list.PopFront() == 1, "Rotate() misordered list!\n");
	TASSERT( list.PopFront() == 2, "Rotate() misordered list!\n");
	TASSERT( list.PopFront() == 3, "Rotate() misordered list!\n");
	TASSERT( list.PopFront() == 4, "Rotate() misordered list!\n");
	TASSERT( list.PopFront() == 5, "Rotate() misordered list!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Rotate_Region()
{
	ZArray<int> list;
	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);
	list.PushBack(6);

	// test rotate at front
	ZArrayAlgo::Rotate(list, 1, 0, 3);
	TASSERT( list.Size() == 6, "Rotate() changed length of array!\n");
	TASSERT( list.PopFront() == 2, "Rotate() misordered list!\n");
	TASSERT( list.PopFront() == 3, "Rotate() misordered list!\n");
	TASSERT( list.PopFront() == 1, "Rotate() misordered list!\n");
	TASSERT( list.PopFront() == 4, "Rotate() misordered list!\n");
	TASSERT( list.PopFront() == 5, "Rotate() misordered list!\n");
	TASSERT( list.PopFront() == 6, "Rotate() misordered list!\n");

	// test rotate at middle
	list.PushBack(1); //0
	list.PushBack(2); //1
	list.PushBack(3); //2 =
	list.PushBack(4); //3 | <
	list.PushBack(5); //4 = 
	list.PushBack(6); //5
	ZArrayAlgo::Rotate(list, 3, 2, 5);
	TASSERT( list.Size() == 6, "Rotate() changed length of array!\n");
	TASSERT( list.PopFront() == 1, "Rotate() misordered list!\n");
	TASSERT( list.PopFront() == 2, "Rotate() misordered list!\n");
	TASSERT( list.PopFront() == 4, "Rotate() misordered list!\n");
	TASSERT( list.PopFront() == 5, "Rotate() misordered list!\n");
	TASSERT( list.PopFront() == 3, "Rotate() misordered list!\n");
	TASSERT( list.PopFront() == 6, "Rotate() misordered list!\n");

	// test pivot back
	list.PushBack(1); //0
	list.PushBack(2); //1
	list.PushBack(3); //2
	list.PushBack(4); //3 =
	list.PushBack(5); //4 | 
	list.PushBack(6); //5 = <
	ZArrayAlgo::Rotate(list, 5, 3, 6);
	TASSERT( list.Size() == 6, "Rotate() changed length of array!\n");
	TASSERT( list.PopFront() == 1, "Rotate() misordered list!\n");
	TASSERT( list.PopFront() == 2, "Rotate() misordered list!\n");
	TASSERT( list.PopFront() == 3, "Rotate() misordered list!\n");
	TASSERT( list.PopFront() == 6, "Rotate() misordered list!\n");
	TASSERT( list.PopFront() == 4, "Rotate() misordered list!\n");
	TASSERT( list.PopFront() == 5, "Rotate() misordered list!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_SetIntersection()
{
	ZArray<int> list;
	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);

	ZArray<int> list2;
	list2.PushBack(2);
	list2.PushBack(3);
	list2.PushBack(4);
	list2.PushBack(5);

	ZArray<int> intersection = ZArrayAlgo::SetIntersection(list, list2);
	TASSERT( intersection.Size() == 3, "SetIntersection() created wrong size intersection set\n");
	TASSERT( intersection.PopFront() == 2, "SetIntersection() produced wrong value!\n");
	TASSERT( intersection.PopFront() == 3, "SetIntersection() produced wrong value!\n");
	TASSERT( intersection.PopFront() == 4, "SetIntersection() produced wrong value!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_SetIntersection_In_Region()
{
	ZArray<int> list;
	list.PushBack(1); // 0
	list.PushBack(2); // 1 =
	list.PushBack(3); // 2 |
	list.PushBack(4); // 3 |
	list.PushBack(5); // 4 |
	list.PushBack(6); // 5 =
	list.PushBack(7); // 6

	ZArray<int> list2;
	list2.PushBack(1); // 0
	list2.PushBack(2); // 1
	list2.PushBack(3); // 2
	list2.PushBack(4); // 3 =
	list2.PushBack(5); // 4 |
	list2.PushBack(6); // 5 |
	list2.PushBack(7); // 6 =

	ZArray<int> intersection = ZArrayAlgo::SetIntersection(list, 1, 6, list2, 3, 7);
	TASSERT( intersection.Size() == 3, "SetIntersection() created wrong size intersection set\n");
	TASSERT( intersection.PopFront() == 4, "SetIntersection() produced wrong value!\n");
	TASSERT( intersection.PopFront() == 5, "SetIntersection() produced wrong value!\n");
	TASSERT( intersection.PopFront() == 6, "SetIntersection() produced wrong value!\n");
	
	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_SetUnion()
{
	ZArray<int> list;
	list.PushBack(1); // 0
	list.PushBack(2); // 1 =
	list.PushBack(3); // 2 |
	list.PushBack(4); // 3 |
	list.PushBack(5); // 4 |

	ZArray<int> list2;
	list2.PushBack(1); // 0
	list2.PushBack(2); // 1
	list2.PushBack(3); // 2

	ZArray<int> list3;
	list3.PushBack(3); // 0
	list3.PushBack(4); // 1
	list3.PushBack(5); // 2

	ZArray<int> same = ZArrayAlgo::SetUnion(list,list2);
	TASSERT(same.Size() == 5, "SetUnion() created wrong sized list!\n");
	TASSERT(same.PopFront() == 1, "SetUnion() created wrong list!\n");
	TASSERT(same.PopFront() == 2, "SetUnion() created wrong list!\n");
	TASSERT(same.PopFront() == 3, "SetUnion() created wrong list!\n");
	TASSERT(same.PopFront() == 4, "SetUnion() created wrong list!\n");
	TASSERT(same.PopFront() == 5, "SetUnion() created wrong list!\n");

	ZArray<int> diff = ZArrayAlgo::SetUnion(list2,list3);
	TASSERT(diff.Size() == 5, "SetUnion() created wrong sized list!\n");
	TASSERT(diff.PopFront() == 1, "SetUnion() created wrong list!\n");
	TASSERT(diff.PopFront() == 2, "SetUnion() created wrong list!\n");
	TASSERT(diff.PopFront() == 3, "SetUnion() created wrong list!\n");
	TASSERT(diff.PopFront() == 4, "SetUnion() created wrong list!\n");
	TASSERT(diff.PopFront() == 5, "SetUnion() created wrong list!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_SetUnion_In_Region()
{
	ZArray<int> list;
	list.PushBack(1); // 0
	list.PushBack(2); // 1 =
	list.PushBack(3); // 2 |
	list.PushBack(4); // 3 |
	list.PushBack(5); // 4 =
	list.PushBack(6); // 5 
	list.PushBack(7); // 6

	ZArray<int> list2;
	list2.PushBack(1); // 0
	list2.PushBack(2); // 1
	list2.PushBack(3); // 2
	list2.PushBack(4); // 3 =
	list2.PushBack(5); // 4 |
	list2.PushBack(6); // 5 |
	list2.PushBack(7); // 6 =

	ZArray<int> diff = ZArrayAlgo::SetUnion(list,1,4,list2,3,6);
	TASSERT(diff.Size() == 5, "SetUnion() created wrong sized list!\n");
	TASSERT(diff.PopFront() == 2, "SetUnion() created wrong list!\n");
	TASSERT(diff.PopFront() == 3, "SetUnion() created wrong list!\n");
	TASSERT(diff.PopFront() == 4, "SetUnion() created wrong list!\n");
	TASSERT(diff.PopFront() == 5, "SetUnion() created wrong list!\n");
	TASSERT(diff.PopFront() == 6, "SetUnion() created wrong list!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Slice()
{
	ZArray<int> list;
	ZArray<int> list2;

	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);

	list2 = ZArrayAlgo::Slice(list,1,3);

	TASSERT( list.Size() == 3, "Slice() removed the wrong number of elements!\n");
	TASSERT( list.PopFront() == 1, "Slice() produced incorrect mutated list!\n");
	TASSERT( list.PopFront() == 4, "Slice() produced incorrect mutated list!\n");
	TASSERT( list.PopFront() == 5, "Slice() produced incorrect mutated list!\n");

	TASSERT( list2.PopFront() == 2, "Slice() produced incorrect excise list!\n");
	TASSERT( list2.PopFront() == 3, "Slice() produced incorrect excise list!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Sort()
{
	ZArray<int> list;

	list.PushBack(4);
	list.PushBack(1);
	list.PushBack(3);
	list.PushBack(6);
	list.PushBack(7);
	list.PushBack(2);
	list.PushBack(5);

	ZArrayAlgo::Sort(list);
	TASSERT(list.Size() == 7, "Sort() changed array size!\n");
	TASSERT(list.PopFront() == 1, "Sort() didn't sort list properly!\n");
	TASSERT(list.PopFront() == 2, "Sort() didn't sort list properly!\n");
	TASSERT(list.PopFront() == 3, "Sort() didn't sort list properly!\n");
	TASSERT(list.PopFront() == 4, "Sort() didn't sort list properly!\n");
	TASSERT(list.PopFront() == 5, "Sort() didn't sort list properly!\n");
	TASSERT(list.PopFront() == 6, "Sort() didn't sort list properly!\n");
	TASSERT(list.PopFront() == 7, "Sort() didn't sort list properly!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Sort_Region()
{
	ZArray<int> list;

	list.PushBack(4);
	list.PushBack(1);
	list.PushBack(3);
	list.PushBack(6);
	list.PushBack(7);
	list.PushBack(2);
	list.PushBack(5);

	ZArrayAlgo::Sort(list,2,6);
	TASSERT(list.Size() == 7, "Sort() changed array size!\n");
	TASSERT(list.PopFront() == 4, "Sort() didn't sort list properly!\n");
	TASSERT(list.PopFront() == 1, "Sort() didn't sort list properly!\n");
	TASSERT(list.PopFront() == 2, "Sort() didn't sort list properly!\n");
	TASSERT(list.PopFront() == 3, "Sort() didn't sort list properly!\n");
	TASSERT(list.PopFront() == 6, "Sort() didn't sort list properly!\n");
	TASSERT(list.PopFront() == 7, "Sort() didn't sort list properly!\n");
	TASSERT(list.PopFront() == 5, "Sort() didn't sort list properly!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

// reverse from normal
struct SortComparatorTestFunctor
{
	int operator () (const int& _a, const int& _b) const
	{
		if (_a < _b)
		{
			return 1;
		}
		else if (_b < _a)
		{
			return -1;
		}
		else
		{
			return 0;
		}
	}
};

static const char* test_Sort_Comparator()
{
	ZArray<int> list;

	list.PushBack(4);
	list.PushBack(1);
	list.PushBack(3);
	list.PushBack(6);
	list.PushBack(7);
	list.PushBack(2);
	list.PushBack(5);

	ZArrayAlgo::Sort(list,SortComparatorTestFunctor());
	TASSERT(list.Size() == 7, "Sort() changed array size!\n");
	TASSERT(list.PopFront() == 7, "Sort() didn't sort list properly!\n");
	TASSERT(list.PopFront() == 6, "Sort() didn't sort list properly!\n");
	TASSERT(list.PopFront() == 5, "Sort() didn't sort list properly!\n");
	TASSERT(list.PopFront() == 4, "Sort() didn't sort list properly!\n");
	TASSERT(list.PopFront() == 3, "Sort() didn't sort list properly!\n");
	TASSERT(list.PopFront() == 2, "Sort() didn't sort list properly!\n");
	TASSERT(list.PopFront() == 1, "Sort() didn't sort list properly!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

// ye olde bubble sorte
struct SortAlgorithmTestFunctor
{
	//Functor operator () override
	template <typename CF>
	void operator () (CF& _comparator, int* _array, size_t _size)
	{
		if (_size == 0)
			return;

		bool keepGoing;
		size_t i;
		int temp;

		do 
		{
			keepGoing  = false;
			for (i = 1; i < _size; i++)
			{
				if ( _comparator(_array[i-1], _array[i]) > 0)
				{
					temp = _array[i];
					_array[i] = _array[i-1];
					_array[i-1] = temp;
					keepGoing = true;
				}
			}
		} while (keepGoing);
	}
};

static const char* test_Sort_Comparator_Algorithm()
{
	ZArray<int> list;

	list.PushBack(4);
	list.PushBack(1);
	list.PushBack(3);
	list.PushBack(6);
	list.PushBack(7);
	list.PushBack(2);
	list.PushBack(5);

	ZArrayAlgo::Sort(list, SortComparatorTestFunctor(), SortAlgorithmTestFunctor(), 0, list.Size());
	TASSERT(list.Size() == 7, "Sort() changed array size!\n");
	TASSERT(list.PopFront() == 7, "Sort() didn't sort list properly!\n");
	TASSERT(list.PopFront() == 6, "Sort() didn't sort list properly!\n");
	TASSERT(list.PopFront() == 5, "Sort() didn't sort list properly!\n");
	TASSERT(list.PopFront() == 4, "Sort() didn't sort list properly!\n");
	TASSERT(list.PopFront() == 3, "Sort() didn't sort list properly!\n");
	TASSERT(list.PopFront() == 2, "Sort() didn't sort list properly!\n");
	TASSERT(list.PopFront() == 1, "Sort() didn't sort list properly!\n");
	
	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Sort_Comparator_Algorithm_Region()
{
	ZArray<int> list;

	list.PushBack(4);
	list.PushBack(1);
	list.PushBack(3);
	list.PushBack(6);
	list.PushBack(7);
	list.PushBack(2);
	list.PushBack(5);

	ZArrayAlgo::Sort(list,SortComparatorTestFunctor(), SortAlgorithmTestFunctor(),2,5);
	TASSERT(list.Size() == 7, "Sort() changed array size!\n");
	TASSERT(list.PopFront() == 4, "Sort() didn't sort list properly!\n");
	TASSERT(list.PopFront() == 1, "Sort() didn't sort list properly!\n");
	TASSERT(list.PopFront() == 7, "Sort() didn't sort list properly!\n");
	TASSERT(list.PopFront() == 6, "Sort() didn't sort list properly!\n");
	TASSERT(list.PopFront() == 3, "Sort() didn't sort list properly!\n");
	TASSERT(list.PopFront() == 2, "Sort() didn't sort list properly!\n");
	TASSERT(list.PopFront() == 5, "Sort() didn't sort list properly!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Split() 
{ 
	ZArray<int> list;

	list.PushBack(4);
	list.PushBack(1);
	list.PushBack(3);
	list.PushBack(6);
	list.PushBack(7);
	list.PushBack(2);
	list.PushBack(5);

	ZArray<int> values;

	values.PushBack(4);

	ZArray< ZArray<int> > out = ZArrayAlgo::Split(list, values);

	TASSERT( out.Size() == 1, "Split() 1 did not create an array with the correct number of sections!");
	TASSERT( out[0].Size() == 6, "Split() 1 did not create correct size section!");
	TASSERT( out[0].Front() == 1, "Split() 1 did not create correct front element!");
	TASSERT( out[0].Back() == 5, "Split() 1 did not create correct back element!");

	values.PushBack(6);

	out = ZArrayAlgo::Split(list, values);

	TASSERT( out.Size() == 2, "Split() 2 did not create an array with the correct number of sections!");
	TASSERT( out[0].Size() == 2, "Split() 2 did not create correct size section 1!");
	TASSERT( out[0].Front() == 1, "Split() 2 did not create correct front element on section 1!");
	TASSERT( out[0].Back() == 3, "Split() 2 did not create correct back element on section 1!");
	TASSERT( out[1].Size() == 3, "Split() 2 did not create correct size section 2!");
	TASSERT( out[1].Front() == 7, "Split() 2 did not create correct front element on section 2!");
	TASSERT( out[1].Back() == 5, "Split() 2 did not create correct back element on section 2!");

	values.PushBack(5);

	out = ZArrayAlgo::Split(list, values);

	TASSERT( out.Size() == 2, "Split() 3 did not create an array with the correct number of sections!");
	TASSERT( out[0].Size() == 2, "Split() 3 did not create correct size section 1!");
	TASSERT( out[0].Front() == 1, "Split() 3 did not create correct front element on section 1!");
	TASSERT( out[0].Back() == 3, "Split() 3 did not create correct back element on section 1!");
	TASSERT( out[1].Size() == 2, "Split() 3 did not create correct size section 2!");
	TASSERT( out[1].Front() == 7, "Split() 3 did not create correct front element on section 2!");
	TASSERT( out[1].Back() == 2, "Split() 3 did not create correct back element on section 2!");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Split_Count() 
{ 
	ZArray<int> list;

	list.PushBack(4);
	list.PushBack(1);
	list.PushBack(3);
	list.PushBack(6);
	list.PushBack(7);
	list.PushBack(2);
	list.PushBack(5);
	list.PushBack(1);
	list.PushBack(7);

	ZArray<int> values;

	values.PushBack(1);

	ZArray< ZArray<int> > out = ZArrayAlgo::Split(list, values, 1);

	//Should create [ [4], [3, 6, 7, 2, 5, 1, 7] ]

	TASSERT( out.Size() == 2, "Split() 1 did not create an array with the correct number of sections!");
	TASSERT( out[0].Size() == 1, "Split() 1 did not create correct size section 1!");
	TASSERT( out[0].Front() == 4, "Split() 1 did not create correct front element for section 1!");
	TASSERT( out[0].Back() == 4, "Split() 1 did not create correct back element for section 1!");
	TASSERT( out[1].Size() == 7, "Split() 1 did not create correct size section 2!");
	TASSERT( out[1].Front() == 3, "Split() 1 did not create correct front element for section 2!");
	TASSERT( out[1].Back() == 7, "Split() 1 did not create correct back element for section 2!");

	values.PushBack(6);

	out = ZArrayAlgo::Split(list, values, 2);

	//Should create [ [4], [3], [7, 2, 5, 1, 7] ]

	TASSERT( out.Size() == 3, "Split() 2 did not create an array with the correct number of sections!");
	TASSERT( out[0].Size() == 1, "Split() 2 did not create correct size section 1!");
	TASSERT( out[0].Front() == 4, "Split() 2 did not create correct front element for section 1!");
	TASSERT( out[0].Back() == 4, "Split() 2 did not create correct back element for section 1!");
	TASSERT( out[1].Size() == 1, "Split() 2 did not create correct size section 2!");
	TASSERT( out[1].Front() == 3, "Split() 2 did not create correct front element for section 2!");
	TASSERT( out[1].Back() == 3, "Split() 2 did not create correct back element for section 2!");
	TASSERT( out[2].Size() == 5, "Split() 2 did not create correct size section 3!");
	TASSERT( out[2].Front() == 7, "Split() 2 did not create correct front element for section 3!");
	TASSERT( out[2].Back() == 7, "Split() 2 did not create correct back element for section 3!");

	values.PushBack(5);

	out = ZArrayAlgo::Split(list, values, 15);

	//Should create [ [4], [3], [7, 2], [7] ]

	TASSERT( out.Size() == 4, "Split() 3 did not create an array with the correct number of sections!");
	TASSERT( out[0].Size() == 1, "Split() 3 did not create correct size section 1!");
	TASSERT( out[0].Front() == 4, "Split() 3 did not create correct front element for section 1!");
	TASSERT( out[0].Back() == 4, "Split() 3 did not create correct back element for section 1!");
	TASSERT( out[1].Size() == 1, "Split() 3 did not create correct size section 2!");
	TASSERT( out[1].Front() == 3, "Split() 3 did not create correct front element for section 2!");
	TASSERT( out[1].Back() == 3, "Split() 3 did not create correct back element for section 2!");
	TASSERT( out[2].Size() == 2, "Split() 3 did not create correct size section 3!");
	TASSERT( out[2].Front() == 7, "Split() 3 did not create correct front element for section 3!");
	TASSERT( out[2].Back() == 2, "Split() 3 did not create correct back element for section 3!");
	TASSERT( out[3].Size() == 1, "Split() 3 did not create correct size section 4!");
	TASSERT( out[3].Front() == 7, "Split() 3 did not create correct front element for section 4!");
	TASSERT( out[3].Back() == 7, "Split() 3 did not create correct back element for section 4!");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Split_Count_Region() 
{
	ZArray<int> list;

	list.PushBack(4);
	list.PushBack(1);
	list.PushBack(3);
	list.PushBack(6);
	list.PushBack(7);
	list.PushBack(2);
	list.PushBack(5);
	list.PushBack(1);
	list.PushBack(7);

	ZArray<int> values;

	values.PushBack(1);

	ZArray< ZArray<int> > out = ZArrayAlgo::Split(list, values, 1, 4, list.Size());

	//Should create [ [7, 2, 5], [7] ]

	TASSERT( out.Size() == 2, "Split() 1 did not create an array with the correct number of sections!");
	TASSERT( out[0].Size() == 3, "Split() 1 did not create correct size section 1!");
	TASSERT( out[0].Front() == 7, "Split() 1 did not create correct front element for section 1!");
	TASSERT( out[0].Back() == 5, "Split() 1 did not create correct back element for section 1!");
	TASSERT( out[1].Size() == 1, "Split() 1 did not create correct size section 2!");
	TASSERT( out[1].Front() == 7, "Split() 1 did not create correct front element for section 2!");
	TASSERT( out[1].Back() == 7, "Split() 1 did not create correct back element for section 2!");

	values.PushBack(6);

	out = ZArrayAlgo::Split(list, values, 2, 4, list.Size());

	//Should create [ [7, 2, 5], [7] ]

	TASSERT( out.Size() == 2, "Split() 2 did not create an array with the correct number of sections!");
	TASSERT( out[0].Size() == 3, "Split() 2 did not create correct size section 1!");
	TASSERT( out[0].Front() == 7, "Split() 2 did not create correct front element for section 1!");
	TASSERT( out[0].Back() == 5, "Split() 2 did not create correct back element for section 1!");
	TASSERT( out[1].Size() == 1, "Split() 2 did not create correct size section 2!");
	TASSERT( out[1].Front() == 7, "Split() 2 did not create correct front element for section 2!");
	TASSERT( out[1].Back() == 7, "Split() 2 did not create correct back element for section 2!");

	values.PushBack(5);

	out = ZArrayAlgo::Split(list, values, 15, 1, list.Size());

	//Should create [ [3], [7, 2], [7] ]

	TASSERT( out.Size() == 3, "Split() 3 did not create an array with the correct number of sections!");
	TASSERT( out[0].Size() == 1, "Split() 3 did not create correct size section 1!");
	TASSERT( out[0].Front() == 3, "Split() 3 did not create correct front element for section 1!");
	TASSERT( out[0].Back() == 3, "Split() 3 did not create correct back element for section 1!");
	TASSERT( out[1].Size() == 2, "Split() 3 did not create correct size section 2!");
	TASSERT( out[1].Front() == 7, "Split() 3 did not create correct front element for section 2!");
	TASSERT( out[1].Back() == 2, "Split() 3 did not create correct back element for section 2!");
	TASSERT( out[2].Size() == 1, "Split() 3 did not create correct size section 3!");
	TASSERT( out[2].Front() == 7, "Split() 3 did not create correct front element for section 3!");
	TASSERT( out[2].Back() == 7, "Split() 3 did not create correct back element for section 3!");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Sum()
{
	ZArray<int> list;
	ZArray<ArrayValueTestClass> list2;
	int ans;
	ArrayValueTestClass ans2;

	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);

	ans = ZArrayAlgo::Sum(list, 10);
	TASSERT (ans == 25, "Accumulate() failed to accumulate correctly on primitive list!\n");

	list2.PushBack(1);
	list2.PushBack(2);
	list2.PushBack(3);
	list2.PushBack(4);
	list2.PushBack(5);

	ans2 = ZArrayAlgo::Sum(list2, ArrayValueTestClass(10));
	TASSERT (ans2.val == 25, "Accumulate() failed to accumulate correctly on overridden list!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Sum_Region()
{
	ZArray<int> list;
	ZArray<ArrayValueTestClass> list2;
	int ans;
	ArrayValueTestClass ans2;

	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);

	ans = ZArrayAlgo::Sum(list, 10, 1, 4);
	TASSERT (ans == 19, "Accumulate() failed to accumulate correctly on primitive list!\n");

	list2.PushBack(1);
	list2.PushBack(2);
	list2.PushBack(3);
	list2.PushBack(4);
	list2.PushBack(5);

	ans2 = ZArrayAlgo::Sum(list2, ArrayValueTestClass(10), 1, 4);
	TASSERT (ans2.val == 19, "Accumulate() failed to accumulate correctly on overridden list!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_SwapElements()
{
	ZArray<int> list;
	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);

	ZArrayAlgo::SwapElements(list, 1,2);
	TASSERT( list.Size() == 3, "SwapElements changed list size!\n");
	TASSERT( list.PopFront() == 1, "SwapElements corrupted list!\n");
	TASSERT( list.PopFront() == 3, "SwapElements failed to swap elements in list!\n");
	TASSERT( list.PopFront() == 2, "SwapElements failed to swap elements in list!\n");

	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	ZArrayAlgo::SwapElements(list, 1,1);
	TASSERT( list.Size() == 3, "SwapElements changed list size!\n");
	TASSERT( list.PopFront() == 1, "SwapElements corrupted list!\n");
	TASSERT( list.PopFront() == 2, "SwapElements failed to swap elements in list!\n");
	TASSERT( list.PopFront() == 3, "SwapElements failed to swap elements in list!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Unique()
{
	ZArray<int> list;
	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);

	TASSERT( ZArrayAlgo::Unique(list) == 0, "Unique() claims removals on unique list!\n");
	TASSERT( list.Size() == 3, "Unique() changed length of list!\n");
	
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);

	TASSERT( ZArrayAlgo::Unique(list) == 4, "Unique() claims wrong number of removals on nonunique list!\n");
	TASSERT( list.Size() == 5, "Unique() changed length of list to wrong value!\n");
	TASSERT( list.PopFront() == 1, "Unique() put wrong value into list!\n");
	TASSERT( list.PopFront() == 2, "Unique() put wrong value into list!\n");
	TASSERT( list.PopFront() == 3, "Unique() put wrong value into list!\n");
	TASSERT( list.PopFront() == 4, "Unique() put wrong value into list!\n");
	TASSERT( list.PopFront() == 5, "Unique() put wrong value into list!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/

static const char* test_Unique_In_Region()
{
	ZArray<int> list;
	list.PushBack(1);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(2);
	list.PushBack(3);
	list.PushBack(4);
	list.PushBack(5);

	TASSERT( ZArrayAlgo::Unique(list, 1, 4) == 1, "Unique() claims wrong number of removals on nonunique list!\n");
	TASSERT( list.Size() == 8, "Unique() changed length of list to wrong value!\n");
	TASSERT( list.PopFront() == 1, "Unique() put wrong value into list!\n");
	TASSERT( list.PopFront() == 2, "Unique() put wrong value into list!\n");
	TASSERT( list.PopFront() == 3, "Unique() put wrong value into list!\n");
	TASSERT( list.PopFront() == 3, "Unique() put wrong value into list!\n");
	TASSERT( list.PopFront() == 2, "Unique() put wrong value into list!\n");
	TASSERT( list.PopFront() == 3, "Unique() put wrong value into list!\n");
	TASSERT( list.PopFront() == 4, "Unique() put wrong value into list!\n");
	TASSERT( list.PopFront() == 5, "Unique() put wrong value into list!\n");

	return ZTEST_SUCCESS;
}

/*************************************************************************/
