From d25d8e6b160e4bae5c1bff3be8b61ba7465bbf27 Mon Sep 17 00:00:00 2001 From: Michael Pfeiffer Date: Sat, 4 Sep 2004 10:00:13 +0000 Subject: [PATCH] Test for class _PointerList_. Someone should convert it to a CppUnit test and integrate it in the build system. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@8840 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../support/pointerlist/PointerListTest.cpp | 511 ++++++++++++++++++ .../support/pointerlist/PointerListTest.h | 68 +++ 2 files changed, 579 insertions(+) create mode 100644 src/tests/kits/support/pointerlist/PointerListTest.cpp create mode 100644 src/tests/kits/support/pointerlist/PointerListTest.h diff --git a/src/tests/kits/support/pointerlist/PointerListTest.cpp b/src/tests/kits/support/pointerlist/PointerListTest.cpp new file mode 100644 index 0000000000..5d60d731b8 --- /dev/null +++ b/src/tests/kits/support/pointerlist/PointerListTest.cpp @@ -0,0 +1,511 @@ +/* +** Copyright 2004, Michael Pfeiffer (laplace@users.sourceforge.net). +** Distributed under the terms of the Haiku License. +** +*/ + +#include "ObjectList.h" +#include +#include +#include + +#include "PointerListTest.h" + +AssertStatistics *AssertStatistics::fStatistics = NULL; + +AssertStatistics::AssertStatistics() +{ + fAssertions = 0; + fPassed = 0; + fFailed = 0; +} + +AssertStatistics* AssertStatistics::GetInstance() +{ + if (fStatistics == NULL) { + fStatistics = new AssertStatistics(); + } + return fStatistics; +} + +void AssertStatistics::Print() +{ + fprintf(stderr, "Assert Statistics:\n"); + fprintf(stderr, "Assertions: %d\n", fAssertions); + fprintf(stderr, "Passed: %d\n", fPassed); + fprintf(stderr, "Failed: %d\n", fFailed); +} + +#undef assert +#define assert(expr) \ + if (!(expr)) {\ + fprintf(stderr, "FAILED [%d] ("#expr")\n", __LINE__); \ + AssertStatistics::GetInstance()->AssertFailed(); \ + }\ + else {\ + AssertStatistics::GetInstance()->AssertPassed(); \ + } + + +int Item::Compare(const void* a, const void* b) +{ + Item* itemA = (Item*)a; + Item* itemB = (Item*)b; + if (itemA == itemB) return 0; + if (itemA == NULL) return -1; + if (itemB == NULL) return 1; + return itemA->Value() - itemB->Value(); +} + +int Item::fNextID = 0; +int Item::fInstances = 0; + +class PointerListTest +{ +public: + Item* CreateItem(); + void Initialize(_PointerList_& list, int size); + void Print(const _PointerList_& list); + void MakeEmpty(_PointerList_& list); + bool Equals(const _PointerList_& list1, const _PointerList_& list2); + bool IsSorted(const _PointerList_& list, int32 n); + bool IsSorted(const _PointerList_& list) { return IsSorted(list, list.CountItems()); } + bool IsHSorted(const _PointerList_& list) { return IsSorted(list, list.CountItems()-1); } + int IndexOf(const _PointerList_& list, int value); + Item* ItemFor(const _PointerList_& list, int value); + + void CreationTest(); + void OwningTest(); + void SortTest(); + void SortTestWithState(); + void EachElementTest(); + void BinarySearchTest(); + void BinarySearchIndexTest(); + void NullTest(); + void Run(); +}; + +#define MAX_ID 10000 +#define NOT_USED_ID -1 +#define NOT_USED_ID_HIGH (MAX_ID+1) + +// Create an Item with a random value +Item* PointerListTest::CreateItem() +{ + return new Item(rand() % (MAX_ID+1)); +} + +// Add size number of new items to the list. +void PointerListTest::Initialize(_PointerList_& list, int size) +{ + for (int32 i = 0; i < size; i ++) { + list.AddItem(CreateItem()); + } +} + +// Print the list to stderr +void PointerListTest::Print(const _PointerList_& list) +{ + const int32 n = list.CountItems(); + for (int32 i = 0; i < n; i ++) { + Item* item = (Item*)list.ItemAt(i); + if (i > 0) { + fprintf(stderr, ", "); + } + if (item != NULL) { + item->Print(); + } else { + fprintf(stderr, "NULL"); + } + } + fprintf(stderr, "\n"); +} + +// delete the Items in the list +void PointerListTest::MakeEmpty(_PointerList_& list) +{ + const int32 n = list.CountItems(); + for (int32 i = 0; i < n; i ++) { + Item* item = (Item*)list.ItemAt(i); + if (item != NULL) { + delete item; + } + } + list.MakeEmpty(); +} + +// contain the lists the same items or values +bool PointerListTest::Equals(const _PointerList_& list1, const _PointerList_& list2) +{ + const int32 n = list1.CountItems(); + + if (n != list2.CountItems()) return false; + + for (int32 i = 0; i < n; i ++) { + Item* item1 = (Item*)list1.ItemAt(i); + Item* item2 = (Item*)list2.ItemAt(i); + if (item1 == item2) continue; + if (item1 == NULL || !item1->Equals(item2)) return false; + } + + return true; +} + +// is the list sorted +bool PointerListTest::IsSorted(const _PointerList_& list, int32 n) +{ + int prevValue = -1; // item values are >= 0 + for (int32 i = 0; i < n; i ++) { + Item* item = (Item*)list.ItemAt(i); + assert(item != NULL); + int value = item->Value(); + if (value < prevValue) { + return false; + } + prevValue = value; + } + return true; +} + +int PointerListTest::IndexOf(const _PointerList_& list, int value) +{ + int n = list.CountItems(); + for (int32 i = 0; i < n; i ++) { + Item* item = (Item*)list.ItemAt(i); + if (item != NULL && item->Value() == value) { + return i; + } + } + return -1; +} + +Item* PointerListTest::ItemFor(const _PointerList_& list, int value) +{ + int32 index = IndexOf(list, value); + if (index >= 0) { + list.ItemAt(index); + } + return NULL; +} + + + +void PointerListTest::CreationTest() +{ + _PointerList_ list; + int numberOfInstances = Item::GetNumberOfInstances(); + assert(list.Owning() == false); + + assert(list.CountItems() == 0); + Initialize(list, 10); + + assert(list.CountItems() == 10); + + int newInstances = Item::GetNumberOfInstances() - numberOfInstances; + assert(newInstances == 10); + + numberOfInstances = Item::GetNumberOfInstances(); + MakeEmpty(list); + int deletedInstances = numberOfInstances - Item::GetNumberOfInstances(); + assert(deletedInstances == 10); +} + +void PointerListTest::OwningTest() +{ + _PointerList_ list(10, true); + assert(list.CountItems() == 0); + assert(list.Owning() == true); + + int numberOfInstances = Item::GetNumberOfInstances(); + Initialize(list, 10); + assert(list.CountItems() == 10); + assert(Item::GetNumberOfInstances() - numberOfInstances == 10); + + _PointerList_* clone = new _PointerList_(list); + assert(Item::GetNumberOfInstances() - numberOfInstances == 10); + assert(clone->Owning() == true); + + MakeEmpty(list); + assert(Item::GetNumberOfInstances() - numberOfInstances == 0); + + delete clone; + assert(Item::GetNumberOfInstances() - numberOfInstances == 0); +} + +void PointerListTest::SortTest() +{ + for (int i = 0; i < 10; i ++) { + _PointerList_ list; + Initialize(list, i); + + _PointerList_ clone(list); + assert(Equals(list, clone)); + assert(clone.Owning() == false); + + list.SortItems(Item::Compare); + assert(IsSorted(list)); + + int lastItem = clone.CountItems()-1; + bool hasItems = clone.CountItems() > 0; + Item* item = NULL; + if (hasItems) { + item = (Item*)clone.ItemAt(0); + } + + // HSortItems seems to put the first item at the end of the list + // and sort the rest. + clone.HSortItems(Item::Compare); + assert(IsHSorted(clone)); + assert(!hasItems || item == (Item*)clone.ItemAt(lastItem)); + + MakeEmpty(list); + } +} + +static void* gData = NULL; + +int Compare(const void* a, const void* b, void* data) +{ + // check data has the expected value + assert(gData == data); + return Item::Compare(a, b); +} +#define FROM 10000 +#define TO 10000 +void PointerListTest::SortTestWithState() +{ + gData = (void*)0x4711; + + for (int i = FROM; i < (TO+1); i ++) { + BStopWatch* watch = new BStopWatch("Initialize"); + _PointerList_ list; + Initialize(list, i); + delete watch; + + watch = new BStopWatch("Clone"); + _PointerList_ clone(list); + delete watch; + assert(Equals(list, clone)); + assert(clone.Owning() == false); + + watch = new BStopWatch("SortItems"); + list.SortItems(::Compare, gData); + delete watch; + assert(IsSorted(list)); + + watch = new BStopWatch("SortItems (sorted list)"); + list.SortItems(::Compare, gData); + delete watch; + assert(IsSorted(list)); + + int lastItem = clone.CountItems()-1; + bool hasItems = clone.CountItems() > 0; + Item* item = NULL; + if (hasItems) { + item = (Item*)clone.ItemAt(0); + } + + // HSortItems seems to put the first item at the end of the list + // and sort the rest. + watch = new BStopWatch("HSortItems"); + clone.HSortItems(Compare, gData); + delete watch; + assert(IsHSorted(clone)); + assert(!hasItems || item == (Item*)clone.ItemAt(lastItem)); + + watch = new BStopWatch("MakeEmpty"); + MakeEmpty(list); + delete watch; + } +} + +void* CopyTo(void* item, void* data) +{ + _PointerList_* list = (_PointerList_*)data; + list->AddItem(item); + return NULL; +} + +void* FirstItem(void* item, void* data) +{ + return item; +} + +void PointerListTest::EachElementTest() +{ + _PointerList_ list; + Initialize(list, 10); + assert(list.CountItems() == 10); + + _PointerList_ clone; + list.EachElement(CopyTo, &clone); + assert(clone.CountItems() == list.CountItems()); + + void* item = list.EachElement(FirstItem, NULL); + assert (item == list.ItemAt(0)); + + MakeEmpty(list); +} + +void PointerListTest::BinarySearchTest() +{ + _PointerList_ list; + Initialize(list, 10); + list.SortItems(Item::Compare); + assert(IsSorted(list)); + + gData = (void*)0x4711; + + Item notInListLow(NOT_USED_ID); + Item notInListHigh(NOT_USED_ID_HIGH); + + for (int32 i = 0; i < 10; i ++) { + Item* item = (Item*)list.ItemAt(i); + assert(item != NULL); + + Item* found = (Item*)list.BinarySearch(item, Item::Compare); + assert(item->Equals(found)); + + found = (Item*)list.BinarySearch(item, ::Compare, gData); + assert(item->Equals(found)); + + found = (Item*)list.BinarySearch(¬InListLow, Item::Compare); + assert(found == NULL); + + found = (Item*)list.BinarySearch(¬InListLow, ::Compare, gData); + assert(found == NULL); + + found = (Item*)list.BinarySearch(¬InListHigh, Item::Compare); + assert(found == NULL); + + found = (Item*)list.BinarySearch(¬InListHigh, ::Compare, gData); + assert(found == NULL); + } + + MakeEmpty(list); +} + +class Value +{ +public: + Value(int value) : value(value) {}; + int value; +}; + +static int ValuePredicate(const void* _item, void* _value) +{ + Item* item = (Item*)_item; + Value* value = (Value*)_value; + return item->Value() - value->value; +} + +void PointerListTest::BinarySearchIndexTest() +{ + _PointerList_ list; + Initialize(list, 10); + list.SortItems(Item::Compare); + assert(IsSorted(list)); + + Item notInListLow(NOT_USED_ID); + Item notInListHigh(NOT_USED_ID_HIGH); + gData = (void*)0x4711; + + for (int32 i = 0; i < 10; i ++) { + Item* item = (Item*)list.ItemAt(i); + assert(item != NULL); + Value value(item->Value()); + + int index = IndexOf(list, item->Value()); + int searchIndex; + searchIndex = list.BinarySearchIndex(item, Item::Compare); + assert(index == searchIndex); + + searchIndex = list.BinarySearchIndex(item, ::Compare, gData); + assert(index == searchIndex); + + searchIndex = list.BinarySearchIndexByPredicate(&value, ValuePredicate); + assert(index == searchIndex); + + // notInListLow + searchIndex = list.BinarySearchIndex(¬InListLow, Item::Compare); + assert(searchIndex == -1); + + searchIndex = list.BinarySearchIndex(¬InListLow, ::Compare, gData); + assert(searchIndex == -1); + + value.value = notInListLow.Value(); + searchIndex = list.BinarySearchIndexByPredicate(&value, ValuePredicate); + assert(searchIndex == -1); + + // notInListHigh + searchIndex = list.BinarySearchIndex(¬InListHigh, Item::Compare); + assert(searchIndex == -(list.CountItems()+1)); + + searchIndex = list.BinarySearchIndex(¬InListHigh, ::Compare, gData); + assert(searchIndex == -(list.CountItems()+1)); + + value.value = notInListHigh.Value(); + searchIndex = list.BinarySearchIndexByPredicate(&value, ValuePredicate); + assert(searchIndex == -(list.CountItems()+1)); + } + + MakeEmpty(list); + + for (int i = 0; i < 3; i ++) { + list.AddItem(new Item(2 * i)); + } + Item notInList(3); + assert(IndexOf(list, 3) == -1); + + int index = list.BinarySearchIndex(¬InList, Item::Compare); + assert (index == -3); + + index = list.BinarySearchIndex(¬InList, ::Compare, gData); + assert (index == -3); + + Value value(notInList.Value()); + index = list.BinarySearchIndexByPredicate(&value, ValuePredicate); + assert (index == -3); + + MakeEmpty(list); +} + +void PointerListTest::NullTest() +{ + _PointerList_ list; + Initialize(list, 10); + // R5 crashes + // list.EachElement(NULL, NULL); + // list.SortItems(NULL); + // list.SortItems(NULL, NULL); + // list.HSortItems(NULL); + // list.HSortItems(NULL, NULL); + // list.BinarySearch(NULL, NULL); + // list.BinarySearch(NULL, NULL, NULL); + // list.BinarySearchIndex(NULL, NULL); + // list.BinarySearchIndex(NULL, NULL, NULL); + // list.BinarySearchIndexByPredicate(NULL, NULL); + assert(!list.ReplaceItem(-1, NULL)); + assert(!list.ReplaceItem(100, NULL)); +} + +void PointerListTest::Run() +{ + CreationTest(); + OwningTest(); + SortTest(); + SortTestWithState(); + EachElementTest(); + BinarySearchTest(); + BinarySearchIndexTest(); + NullTest(); +} + +int main(int argc, char* argv[]) +{ + // initialize srand with constant to get reproducable results + srand(0); + PointerListTest test; + test.Run(); + AssertStatistics::GetInstance()->Print(); +} \ No newline at end of file diff --git a/src/tests/kits/support/pointerlist/PointerListTest.h b/src/tests/kits/support/pointerlist/PointerListTest.h new file mode 100644 index 0000000000..4ca5ae911b --- /dev/null +++ b/src/tests/kits/support/pointerlist/PointerListTest.h @@ -0,0 +1,68 @@ +/* +** Copyright 2004, Michael Pfeiffer (laplace@users.sourceforge.net). +** Distributed under the terms of the Haiku License. +** +*/ + +#ifndef _TEST_H +#define _TEST_H + +#include + +class AssertStatistics { +private: + AssertStatistics(); + +public: + static AssertStatistics* GetInstance(); + + void AssertFailed() { fAssertions++; fFailed++; } + void AssertPassed() { fAssertions++; fPassed++; } + + void Print(); + + int fAssertions; + int fPassed; + int fFailed; + static AssertStatistics* fStatistics; +}; + +class Item +{ +public: + Item() { Init(); } + Item(const Item& item) : fValue(item.fValue) { Init(); }; + Item(int value) : fValue(value) { Init(); }; + virtual ~Item() { fInstances --; } + + int Value() { return fValue; } + + bool Equals(Item* item) { + return item != NULL && fValue == item->fValue; + } + + static int GetNumberOfInstances() { return fInstances; } + + void Print() { + fprintf(stderr, "[%d] %d", fID, fValue); + // fprintf(stderr, "id: %d; value: %d", fID, fValue); + } + + static int Compare(const void* a, const void* b); + +private: + void Init() { + fID = fNextID ++; + fInstances ++; + } + + int fID; // unique id for each created Item + int fValue; // the value of the item + + + static int fNextID; + static int fInstances; +}; + + +#endif