From 99e34ed4ce76afade130619f62d3df4b183932ff Mon Sep 17 00:00:00 2001 From: saq10002 Date: Fri, 10 Oct 2014 19:21:28 -0400 Subject: [PATCH] Separeted tests from singly/doubly linked lists. Signed-off-by: unknown --- YASI_12/YASI_12.vcxproj | 2 + YASI_12/YASI_12.vcxproj.filters | 6 + YASI_12/ds.doublylinkedlist.h | 743 +--------------------------- YASI_12/ds.doublylinkedlist.test.h | 750 +++++++++++++++++++++++++++++ YASI_12/ds.iterator.test.h | 5 + YASI_12/ds.singlylinkedlist.h | 524 +------------------- YASI_12/ds.singlylinkedlist.test.h | 534 ++++++++++++++++++++ YASI_12/main.cpp | 3 +- YASI_12/utils.test.h | 5 +- 9 files changed, 1313 insertions(+), 1259 deletions(-) create mode 100644 YASI_12/ds.doublylinkedlist.test.h create mode 100644 YASI_12/ds.singlylinkedlist.test.h diff --git a/YASI_12/YASI_12.vcxproj b/YASI_12/YASI_12.vcxproj index ad1e614..5d673ee 100644 --- a/YASI_12/YASI_12.vcxproj +++ b/YASI_12/YASI_12.vcxproj @@ -85,6 +85,7 @@ + @@ -100,6 +101,7 @@ + diff --git a/YASI_12/YASI_12.vcxproj.filters b/YASI_12/YASI_12.vcxproj.filters index c1f9f23..2377fdd 100644 --- a/YASI_12/YASI_12.vcxproj.filters +++ b/YASI_12/YASI_12.vcxproj.filters @@ -149,5 +149,11 @@ Header Files\Common + + Header Files\Data Structures\List + + + Header Files + \ No newline at end of file diff --git a/YASI_12/ds.doublylinkedlist.h b/YASI_12/ds.doublylinkedlist.h index 0e6270b..baccdd6 100644 --- a/YASI_12/ds.doublylinkedlist.h +++ b/YASI_12/ds.doublylinkedlist.h @@ -5,6 +5,10 @@ #include using namespace std; +/******** enable-disable testing *******/ +#include "test.this.module.h" + + namespace yasi{ namespace ds{ @@ -47,7 +51,8 @@ namespace ds{ class DoublyLinkedList :public virtual IDoublyLinkedList < E, Node, Iter >, // implements interface public virtual SinglyLinkedList { // inherits singly-linked list ////////// enable testing //////////////// - friend class DoublyLinkedListTest; + FRIEND_TEST_CLASS(DoublyLinkedListTest); + typedef SinglyLinkedList base; protected: @@ -252,742 +257,6 @@ namespace ds{ } - // test - class DoublyLinkedListTest : public yasi::Test { - typedef DoublyLinkedList >::node_t node_t; - typedef DoublyLinkedList > IntList; - typedef IntList::iterator IntIterator; - protected: - template - void checkListElements(DoublyLinkedList >* pList, const E* srcArr, const int n){ - E* pElems = new E[n]; - int numElems; - DoublyLinkedList >& list = *pList; - list.elements(&pElems); - ASSERT_EQ(true, arrcmp(srcArr, pElems, n)) << "arrays are not the same" << endl - << "actual: " << arrToString(srcArr, n) << endl - << "expected: " << arrToString(pElems, n); - DELETE_ARR_SAFE(pElems); - } - public: - virtual void fromArray(){ - IntList list; - int srcArr[] = { 10, 20, 30, 40 }; - int n = ARR_LENGTH(srcArr); - - list.fromArray(srcArr, n); // build list - ASSERT_NE(0, (int)list.head()) << "head is NULL"; - ASSERT_EQ(4, (int)list.size()) << "size is not 4"; - int j = n - 1; - - for (IntIterator it = list.begin(); it != list.end(); it++){ - ASSERT_EQ(srcArr[j], *it) << "element mismatch at item " << n - j - 1 << " in list"; - j--; - } - } - virtual void elements(){ - IntList list; - int srcArr[] = { 10, 20, 30, 40 }; - int n = ARR_LENGTH(srcArr); - - list.fromArray(srcArr, n); // build list - //ASSERT_NE(0, (int)list.head()) << "list head is NULL"; - ASSERT_EQ(n, list.size()) << "list size should have been " << n; - // since the elements are given in reverse order - int* pRev = new int[n]; - arrrev(srcArr, n, &pRev); - ASSERT_NE(0, (int)pRev) << "array reverse failed"; - { - SCOPED_TRACE("elements"); - checkListElements(&list, pRev, n); - } - DELETE_ARR_SAFE(pRev); - } - - void relements(){ - IntList list; - int srcArr[] = { 10, 20, 30, 40 }; - const int n = ARR_LENGTH(srcArr); - - list.fromArray(srcArr, n); // build list - ASSERT_EQ(n, list.size()) << "list size should have been " << n; - - int* pRelems = new int[n]; - list.relements(&pRelems); - // pRelems should be in the same order as srcArr - ASSERT_EQ(true, arrcmp(srcArr, pRelems, n)) << "arrays are not the same" << endl - << "actual: " << arrToString(pRelems, n) << endl - << "expected: " << arrToString(srcArr, n); - DELETE_ARR_SAFE(pRelems); - } - - void toString(){ - int srcArr[] = { 1, 2, 3, 4 }; - const string expected = "4->3->2->1->"; - IntList list(srcArr, ARR_LENGTH(srcArr)); - string actual = list.toString(); - ASSERT_EQ(expected, actual) << "toString() is wrong"; - } - - void addFront(){ - IntList list; - ASSERT_EQ(0, list.size()) << "size should be zero"; - ASSERT_EQ(0, (int)list.head()) << "head should be NULL"; - - node_t *n1, *n2, *n3; - - // add head - { - SCOPED_TRACE("add #1"); - n1 = list.addFront(4); // new node is at head - // list: 4 - ASSERT_NE(0, (int)list.head()) << "head is NULL"; - ASSERT_NE(0, (int)list.tail()) << "tail is NULL"; - ASSERT_EQ(list.head(), list.tail()) << "head != tail"; - - ASSERT_EQ(list.head(), n1) << "addFront() does not return correct node"; - ASSERT_NE(0, (int)n1) << "head is NULL although list has items"; - ASSERT_EQ(list.end().pNode, n1->next()) << "head's next should be end()"; - ASSERT_EQ(list.end().pNode, n1->prev()) << "head's prev should be end()"; - ASSERT_EQ(1, list.size()) << "size should have been 1"; - ASSERT_EQ(false, list.empty()) << "non-empty list is showing empty"; - ASSERT_EQ(4, n1->element) << "head-element should have been 4"; - - // iterators - ASSERT_EQ(list.head(), list.begin().pNode) << "head() not equal to begin().pNode"; - ASSERT_EQ(list.tail(), list.begin().pNode) << "tail() not equal to begin().pNode"; - ASSERT_NE(list.begin(), list.end()) << "begin() and end() same for non-empty list"; - ASSERT_EQ(list.end(), ++list.begin()) << "++begin() and end() not same"; - ASSERT_EQ(list.begin(), --list.end()) << "--end() and begin() not same"; - ASSERT_NE(list.end(), list.begin()++) << "begin()++ and end() same"; - ASSERT_NE(list.begin(), list.end()--) << "end()-- and begin() same"; - ASSERT_EQ(list.head(), (list.begin()++).pNode) << "begin()++.pNode not head()"; - ASSERT_EQ(list.tail(), (--list.end()).pNode) << "--end().pNode not tail()"; - ASSERT_EQ(list.end().pNode, (++list.begin()).pNode) << "begin++.pNode should be end()"; - ASSERT_EQ(list.begin().pNode, (--list.end()).pNode) << "--end.pNode should be begin()"; - ASSERT_EQ(4, *list.begin()) << "begin()-element should have been 4"; - ASSERT_EQ(4, *(--list.end())) << "--end()-element should have been 4"; - } - - // add 2nd element - { - SCOPED_TRACE("add #2"); - n2 = list.addFront(5); // new node is at head - - // list: 5->4 - ASSERT_NE(0, (int)list.head()) << "head is NULL although list has items"; - ASSERT_EQ(list.head(), n2) << "n2 should be head"; - ASSERT_EQ(list.tail(), n1) << "n1 should be tail"; - - ASSERT_NE(list.end().pNode, list.head()->next()) << "head->next is end() although list has 2 items"; - ASSERT_EQ(n1, list.head()->next()) << "head->next hsould be n1"; - ASSERT_EQ(list.head(), n1->prev()) << "n1->prev should be head"; - - ASSERT_EQ(list.end().pNode, list.tail()->next()) << "tail->next should be end()"; - ASSERT_EQ(list.end().pNode, n1->prev()->prev()) << "n1->perv->prev should be end()"; - ASSERT_EQ(5, list.head()->element) << "head element should have been 5"; - ASSERT_EQ(2, list.size()) << "size should have been 2"; - ASSERT_EQ(false, list.empty()) << "non-empty list is showing empty"; - - ASSERT_EQ(5, list.head()->element) << "head-element should have been 5"; - ASSERT_EQ(4, list.head()->next()->element) << "head->next element should have been 4"; - - - // iterators - ASSERT_EQ(list.head(), list.begin().pNode) << "head() not equal to begin().pNode"; - ASSERT_EQ(list.tail(), (--(list.end())).pNode) << "tail() not equal to --end().pNode"; - ASSERT_NE(list.begin(), list.end()) << "begin() and end() same for non-empty list"; - ASSERT_EQ(list.end(), ++(++(list.begin()))) << "++++begin() not end()"; - ASSERT_EQ(list.begin(), --(--(list.end()))) << "----end() not begin()"; - ASSERT_EQ(n2, (list.begin()++).pNode) << "begin++.pNode should be n2"; - ASSERT_EQ(n1, (++(list.begin())).pNode) << "++begin.pNode should be n1"; - ASSERT_EQ(n2, (--(--list.end())).pNode) << "----end.pNode should be n2"; - ASSERT_EQ(n1, (--(list.end())).pNode) << "--end.pNode should be n1"; - ASSERT_EQ(5, *(list.begin())) << "begin()-element should have been 5"; - ASSERT_EQ(4, *(++(list.begin()))) << "++begin()-element should have been 4"; - ASSERT_EQ(5, *(list.begin()++)) << "begin()-element should have been 5"; - ASSERT_EQ(4, *(--list.end())) << "--end()-element should have been 4"; - ASSERT_EQ(5, *(--(--list.end()))) << "----end()-element should have been 5"; - } - - // add more elements - { - SCOPED_TRACE("add #3"); - n3 = list.addFront(6); // new node is at head - - // list: 6->5->4 - ASSERT_NE(0, (int)list.head()) << "head is NULL although list has items"; - ASSERT_NE(0, (int)list.head()->next()) << "head->next is NULL"; - ASSERT_NE(0, (int)list.head()->next()->next()) << "head->next->next is NULL"; - - ASSERT_EQ(n3, list.head()) << "n3 should be head"; - ASSERT_EQ(n1, list.tail()) << "n1 should be tail"; - ASSERT_EQ(n2, list.head()->next()) << "n2 should be head->next"; - ASSERT_EQ(n2, list.tail()->prev()) << "n2 should be tail->prev"; - ASSERT_EQ(n3, n2->prev()) << "n3 should be n2->prev"; - ASSERT_EQ(list.tail(), n2->next()) << "n2->next should be tail"; - ASSERT_EQ(list.end().pNode, list.tail()->next()) << "tail->next should be end()"; - ASSERT_EQ(list.end().pNode, list.head()->prev()) << "head->prev should be end()"; - - ASSERT_EQ(6, list.head()->element) << "head element should have been 6"; - ASSERT_EQ(5, list.head()->next()->element) << "head->next element should have been 5"; - ASSERT_EQ(4, list.head()->next()->next()->element) << "head->next->next element should have been 4"; - ASSERT_EQ(3, list.size()) << "size should have been 3"; - ASSERT_EQ(false, list.empty()) << "non-empty list is showing empty"; - - // iterators - ASSERT_EQ(list.head(), list.begin().pNode) << "head() not equal to begin().pNode"; - ASSERT_NE(list.begin(), list.end()) << "begin() and end() same for non-empty list"; - ASSERT_EQ(n3, (list.begin()).pNode) << "begin.pNode should be n3"; - ASSERT_EQ(n3, ((list.begin())++).pNode) << "begin++.pNode should be n3"; - ASSERT_EQ(n3, ((list.begin())--).pNode) << "begin--.pNode should be n3"; - ASSERT_EQ(n2, (++(list.begin())).pNode) << "++begin.pNode should be n2"; - ASSERT_EQ(n1, (++(++(list.begin()))).pNode) << "++++begin.pNode should be pNode"; - ASSERT_EQ(list.end(), (++(++(++list.begin())))) << "++++++begin() not end()"; - - ASSERT_EQ(n3, (--(--(--list.end()))).pNode) << "------end.pNode should be n3"; - ASSERT_EQ(n2, (--(--list.end())).pNode) << "----end.pNode should be n2"; - ASSERT_EQ(n1, (--list.end()).pNode) << "--end.pNode should be pNode"; - ASSERT_EQ(list.begin(), --(--(--list.end()))) << "------end should be begin"; - ASSERT_EQ(6, *(list.begin())) << "begin()-element should have been 6"; - ASSERT_EQ(6, *(list.begin()++)) << "begin()++-element should have been 6"; - ASSERT_EQ(6, *(list.begin()--)) << "begin()-- element should have been 6"; - ASSERT_EQ(5, *(++(list.begin()))) << "++begin()-element should have been 5"; - ASSERT_EQ(4, *(++(++(list.begin())))) << "++++begin()-element should have been 4"; - ASSERT_EQ(4, *(--list.end())) << "--end()-element should have been 4"; - ASSERT_EQ(5, *(--(--list.end()))) << "----end()-element should have been 5"; - ASSERT_EQ(6, *(--(--(--list.end())))) << "------end()-element should have been 6"; - } - - } - - void addBack(){ - IntList list; - ASSERT_EQ(0, list.size()) << "size should be zero"; - ASSERT_EQ(0, (int)list.head()) << "head should be NULL"; - ASSERT_EQ(0, (int)list.tail()) << "head should be NULL"; - - node_t *n1, *n2, *n3; - - // add head - { - SCOPED_TRACE("add #1"); - n1 = list.addBack(4); // new node is at head - // list: 4 - ASSERT_NE(0, (int)list.head()) << "head is NULL"; - ASSERT_NE(0, (int)list.tail()) << "tail is NULL"; - ASSERT_EQ(list.head(), list.tail()) << "head != tail"; - - ASSERT_EQ(list.head(), n1) << "head() not n1"; - ASSERT_EQ(list.tail(), n1) << "tail() not n1"; - ASSERT_NE(0, (int)n1) << "head is NULL although list has items"; - ASSERT_EQ(list.end().pNode, n1->next()) << "head's next should be end()"; - ASSERT_EQ(list.end().pNode, n1->prev()) << "head's prev should be end()"; - ASSERT_EQ(1, list.size()) << "size should have been 1"; - ASSERT_EQ(false, list.empty()) << "non-empty list is showing empty"; - ASSERT_EQ(4, n1->element) << "head-element should have been 4"; - - // iterators - ASSERT_EQ(list.head(), list.begin().pNode) << "head() not equal to begin().pNode"; - ASSERT_EQ(list.tail(), list.begin().pNode) << "tail() not equal to begin().pNode"; - ASSERT_NE(list.begin(), list.end()) << "begin() and end() same for non-empty list"; - ASSERT_EQ(list.end(), ++list.begin()) << "++begin() and end() not same"; - ASSERT_EQ(list.begin(), --list.end()) << "--end() and begin() not same"; - ASSERT_NE(list.end(), list.begin()++) << "begin()++ and end() same"; - ASSERT_NE(list.begin(), list.end()--) << "end()-- and begin() same"; - ASSERT_EQ(list.head(), (list.begin()++).pNode) << "begin()++.pNode not head()"; - ASSERT_EQ(list.tail(), (--list.end()).pNode) << "--end().pNode not tail()"; - ASSERT_EQ(list.end().pNode, (++list.begin()).pNode) << "begin++.pNode should be end()"; - ASSERT_EQ(list.begin().pNode, (--list.end()).pNode) << "--end.pNode should be begin()"; - ASSERT_EQ(4, *list.begin()) << "begin()-element should have been 4"; - ASSERT_EQ(4, *(--list.end())) << "--end()-element should have been 4"; - } - - // add 2nd element - { - SCOPED_TRACE("add #2"); - n2 = list.addBack(5); // new node is at head - - // list: 4->5 - ASSERT_NE(0, (int)list.head()) << "head is NULL although list has items"; - ASSERT_EQ(list.head(), n1) << "n1 should be head"; - ASSERT_EQ(list.tail(), n2) << "n2 should be tail"; - ASSERT_EQ(list.tail(), list.head()->next()) << "head->next should be tail"; - - - ASSERT_NE(list.end().pNode, list.head()->next()) << "head->next is end()"; - ASSERT_EQ(n2, list.head()->next()) << "head->next should be n2"; - ASSERT_EQ(list.head(), n2->prev()) << "n2->prev should be head"; - - ASSERT_EQ(list.end().pNode, list.tail()->next()) << "tail->next should be end()"; - ASSERT_EQ(list.end().pNode, n2->prev()->prev()) << "n2->perv->prev should be end()"; - ASSERT_EQ(4, list.head()->element) << "head element should have been 4"; - ASSERT_EQ(5, list.tail()->element) << "tail element should have been 5"; - ASSERT_EQ(2, list.size()) << "size should have been 2"; - ASSERT_EQ(false, list.empty()) << "non-empty list is showing empty"; - - // iterators - ASSERT_EQ(list.head(), list.begin().pNode) << "head() not equal to begin().pNode"; - ASSERT_EQ(list.tail(), (--(list.end())).pNode) << "tail() not equal to --end().pNode"; - ASSERT_NE(list.begin(), list.end()) << "begin() and end() same for non-empty list"; - ASSERT_EQ(list.end(), ++(++(list.begin()))) << "++++begin() not end()"; - ASSERT_EQ(list.begin(), --(--(list.end()))) << "----end() not begin()"; - ASSERT_EQ(n1, (list.begin()++).pNode) << "begin++.pNode should be n1"; - ASSERT_EQ(n2, (++(list.begin())).pNode) << "++begin.pNode should be n2"; - ASSERT_EQ(n1, (--(--list.end())).pNode) << "----end.pNode should be n1"; - ASSERT_EQ(n2, (--(list.end())).pNode) << "--end.pNode should be n2"; - ASSERT_EQ(4, *(list.begin())) << "begin()-element should have been 4"; - ASSERT_EQ(5, *(++(list.begin()))) << "++begin() element should have been 5"; - ASSERT_EQ(4, *(list.begin()++)) << "begin()++ element should have been 4"; - ASSERT_EQ(5, *(--list.end())) << "--end()-element should have been 5"; - ASSERT_EQ(4, *(--(--list.end()))) << "----end()-element should have been 4"; - } - - // add more elements - { - SCOPED_TRACE("add #3"); - n3 = list.addBack(6); // new node is at head - - // list: 4->5->6 - ASSERT_NE(0, (int)list.head()) << "head is NULL although list has items"; - ASSERT_NE(list.end().pNode, list.head()->next()) << "head->next is end()"; - ASSERT_NE(list.end().pNode, list.head()->next()->next()) << "head->next->next is end()"; - - ASSERT_EQ(n3, list.tail()) << "n3 should be tail"; - ASSERT_EQ(n1, list.head()) << "n1 should be head"; - ASSERT_EQ(n2, list.head()->next()) << "n2 should be head->next"; - ASSERT_EQ(n2, list.tail()->prev()) << "n2 should be tail->prev"; - ASSERT_EQ(n3, n2->next()) << "n3 should be n2->next"; - ASSERT_EQ(list.head(), n2->prev()) << "n2->prev should be head"; - ASSERT_EQ(list.end().pNode, list.tail()->next()) << "tail->next should be end()"; - ASSERT_EQ(list.end().pNode, list.head()->prev()) << "head->prev should be end()"; - - ASSERT_EQ(4, list.head()->element) << "head element should have been 4"; - ASSERT_EQ(5, list.head()->next()->element) << "head->next element should have been 5"; - ASSERT_EQ(6, list.head()->next()->next()->element) << "head->next->next element should have been 6"; - ASSERT_EQ(3, list.size()) << "size should have been 3"; - ASSERT_EQ(false, list.empty()) << "non-empty list is showing empty"; - - // iterators - ASSERT_EQ(list.head(), list.begin().pNode) << "head() not equal to begin().pNode"; - ASSERT_NE(list.begin(), list.end()) << "begin() and end() same for non-empty list"; - ASSERT_EQ(n1, (list.begin()).pNode) << "begin.pNode should be n1"; - ASSERT_EQ(n1, ((list.begin())++).pNode) << "begin++.pNode should be n1"; - ASSERT_EQ(n1, ((list.begin())--).pNode) << "begin--.pNode should be n1"; - ASSERT_EQ(n2, (++(list.begin())).pNode) << "++begin.pNode should be n2"; - ASSERT_EQ(n3, (++(++(list.begin()))).pNode) << "++++begin.pNode should be n3"; - ASSERT_EQ(list.end(), (++(++(++list.begin())))) << "++++++begin() not end()"; - - ASSERT_EQ(n1, (--(--(--list.end()))).pNode) << "------end.pNode should be n1"; - ASSERT_EQ(n2, (--(--list.end())).pNode) << "----end.pNode should be n2"; - ASSERT_EQ(n3, (--list.end()).pNode) << "--end.pNode should be n3"; - ASSERT_EQ(list.begin(), --(--(--list.end()))) << "------end should be begin"; - ASSERT_EQ(4, *(list.begin())) << "begin()-element should have been 4"; - ASSERT_EQ(4, *(list.begin()++)) << "begin()++-element should have been 4"; - ASSERT_EQ(4, *(list.begin()--)) << "begin()-- element should have been 4"; - ASSERT_EQ(5, *(++(list.begin()))) << "++begin()-element should have been 5"; - ASSERT_EQ(6, *(++(++(list.begin())))) << "++++begin()-element should have been 6"; - ASSERT_EQ(6, *(--list.end())) << "--end()-element should have been 6"; - ASSERT_EQ(5, *(--(--list.end()))) << "----end()-element should have been 5"; - ASSERT_EQ(4, *(--(--(--list.end())))) << "------end()-element should have been 4"; - } - - } - - void insert(){ - IntList list; - node_t* n[] = { - list.addBack(0), - list.addBack(1), - list.addBack(2), - list.addBack(3) - }; - // list: 0--1--2--3 - - // insert before 0 - { - SCOPED_TRACE("insert before 0"); - node_t* n_1 = list.insert(n[0], -1); // insert -1 before 0 - ASSERT_EQ(5, list.size()) << "size not 5"; - ASSERT_EQ(-1, *list.begin()) << "begin() element not -1"; - ASSERT_EQ(n_1, list.begin().pNode) << "begin() node not n_1"; - } - // list: (-1)--0--1--2--3 - - // insert after 3 - { - SCOPED_TRACE("insert after 3"); - node_t* n4 = list.insert(n[3]->next(), 4); // insert 4 after 3 - ASSERT_EQ(6, list.size()) << "size not 6"; - ASSERT_EQ(4, *--list.end()) << "--end() element not 4"; - ASSERT_EQ(n4, (--list.end()).pNode) << "--end() node not n4"; - } - // list: (-1)--0--1--2--3--4 - - // insert before 2 - { - SCOPED_TRACE("insert before 2"); - node_t* n10 = list.insert(n[2], 10); // insert 10 before 2 - ASSERT_EQ(7, list.size()) << "size not 7"; - ASSERT_EQ(10, * ++ ++ ++ list.begin()) << "n10 element not 10 from begin"; - ASSERT_EQ(n10, (-- -- -- -- list.end()).pNode) << "node not n10 from end"; - } - // list: (-1)--0--1--10--2--3--4 - - } - - void addBefore(){ - IntList list; - ASSERT_EQ(0, list.size()) << "size should be zero"; - ASSERT_EQ(0, (int)list.head()) << "head should be NULL"; - - // add before NULL - node_t* pNode = list.addBefore(5, NULL); // should fail - ASSERT_EQ(NULL, pNode) << "added before NULL"; - - // one-item list - node_t* n0 = list.addFront(0); - ASSERT_EQ(0, n0->element) << "wrong element"; - node_t* n1 = list.addBefore(1, n0); - // list: 1->0 - ASSERT_EQ(n1, list.head()) << "n1 should be head"; - ASSERT_EQ(n0, list.tail()) << "n0 should be tail"; - ASSERT_EQ(1, list.head()->element) << "wrong head element"; - ASSERT_EQ(0, list.tail()->element) << "wrong tail element"; - ASSERT_EQ(n0, n1->next()) << "n1->next should be n0"; - ASSERT_EQ(n1, n0->prev()) << "n0->prev should be n1"; - ASSERT_EQ(2, list.size()) << "size should be 2"; - ASSERT_EQ(list.end().pNode, n1->prev()) << "n1->prev should be end()"; - ASSERT_EQ(list.end().pNode, n0->next()) << "n0->next should be end()"; - - // add more items - const int testSize = 5; - node_t* n[testSize]; - n[0] = n0; - n[1] = n1; - for (int i = 2; i < testSize; i++){ - n[i] = list.addBefore(i, n[i - 1]); - } - // list: 4->3->2->1->0 - ASSERT_EQ(5, list.size()) << "size should be 5"; - ASSERT_EQ(n[4], list.head()) << "4 should be at head"; - ASSERT_EQ(n[3], list.head()->next()) << "3 should be 4->next"; - ASSERT_EQ(n[2], list.head()->next()->next()) << "2 should be 3->next"; - ASSERT_EQ(n[1], list.head()->next()->next()->next()) << "1 should be 2->next"; - ASSERT_EQ(n[0], list.head()->next()->next()->next()->next()) << "0 should be 1->next"; - ASSERT_EQ(list.end().pNode, list.head()->next()->next()->next()->next()->next()) << "tail->next should be end()"; - - ASSERT_EQ(n[0], list.tail()) << "0 should be at tail"; - ASSERT_EQ(n[1], list.tail()->prev()) << "1 should be 0->prev"; - ASSERT_EQ(n[2], list.tail()->prev()->prev()) << "2 should be 1->prev"; - ASSERT_EQ(n[3], list.tail()->prev()->prev()->prev()) << "3 should be 2->prev"; - ASSERT_EQ(n[4], list.tail()->prev()->prev()->prev()->prev()) << "4 should be 3->prev"; - ASSERT_EQ(list.end().pNode, list.tail()->prev()->prev()->prev()->prev()->prev()) << "head->prev should be end()"; - - ASSERT_EQ(4, list.head()->element) << "4 should be at head"; - ASSERT_EQ(3, list.head()->next()->element) << "3 should be 4->next"; - ASSERT_EQ(2, list.head()->next()->next()->element) << "2 should be 3->next"; - ASSERT_EQ(1, list.head()->next()->next()->next()->element) << "1 should be 2->next"; - ASSERT_EQ(0, list.head()->next()->next()->next()->next()->element) << "0 should be 1->next"; - - // add in the middle - node_t* n10 = list.addBefore(10, n[2]); - // list: 4->3->10->2->1->0 - ASSERT_EQ(6, list.size()) << "size should be 6"; - ASSERT_EQ(n[4], list.head()) << "4 should be at head"; - ASSERT_EQ(n[3], list.head()->next()) << "3 should be 4->next"; - ASSERT_EQ(n10, list.head()->next()->next()) << "10 should be 3->next"; - ASSERT_EQ(n[2], list.head()->next()->next()->next()) << "2 should be 10->next"; - ASSERT_EQ(n[1], list.head()->next()->next()->next()->next()) << "1 should be 10->next"; - ASSERT_EQ(n[0], list.head()->next()->next()->next()->next()->next()) << "0 should be 1->next"; - ASSERT_EQ(list.end().pNode, list.head()->next()->next()->next()->next()->next()->next()) << "tail->next should be end()"; - - ASSERT_EQ(n[0], list.tail()) << "0 should be at tail"; - ASSERT_EQ(n[1], list.tail()->prev()) << "1 should be 0->prev"; - ASSERT_EQ(n[2], list.tail()->prev()->prev()) << "2 should be 1->prev"; - ASSERT_EQ(n10, list.tail()->prev()->prev()->prev()) << "10 should be 2->prev"; - ASSERT_EQ(n[3], list.tail()->prev()->prev()->prev()->prev()) << "3 should be 10->prev"; - ASSERT_EQ(n[4], list.tail()->prev()->prev()->prev()->prev()->prev()) << "4 should be 3->prev"; - ASSERT_EQ(list.end().pNode, list.tail()->prev()->prev()->prev()->prev()->prev()->prev()) << "head->prev should be end()"; - - ASSERT_EQ(4, list.head()->element) << "4 should be at head"; - ASSERT_EQ(3, list.head()->next()->element) << "3 should be 4->next"; - ASSERT_EQ(10, list.head()->next()->next()->element) << "10 should be 3->next"; - ASSERT_EQ(2, list.head()->next()->next()->next()->element) << "2 should be 10->next"; - ASSERT_EQ(1, list.head()->next()->next()->next()->next()->element) << "1 should be 10->next"; - ASSERT_EQ(0, list.head()->next()->next()->next()->next()->next()->element) << "0 should be 1->next"; - - } - void addAfter(){ - IntList list; - ASSERT_EQ(0, list.size()) << "size should be zero"; - ASSERT_EQ(0, (int)list.head()) << "head should be NULL"; - - // add before NULL - node_t* pNode = list.addBefore(5, NULL); // should fail - ASSERT_EQ(NULL, pNode) << "added before NULL"; - - // one-item list - node_t* n4 = list.addFront(4); - ASSERT_EQ(4, n4->element) << "wrong element"; - node_t* n3 = list.addAfter(3, n4); - // list: 4->3 - ASSERT_EQ(n4, list.head()) << "n1 should be head"; - ASSERT_EQ(n3, list.tail()) << "n0 should be tail"; - ASSERT_EQ(4, list.head()->element) << "wrong head element"; - ASSERT_EQ(3, list.tail()->element) << "wrong tail element"; - ASSERT_EQ(n3, n4->next()) << "n4->next should be n3"; - ASSERT_EQ(n4, n3->prev()) << "n3->prev should be n4"; - ASSERT_EQ(2, list.size()) << "size should be 2"; - ASSERT_EQ(list.end().pNode, n4->prev()) << "n4->prev should be end()"; - ASSERT_EQ(list.end().pNode, n3->next()) << "n3->next should be end()"; - - // add more items - const int testSize = 5; - node_t* n[testSize]; - n[4] = n4; - n[3] = n3; - for (int i = 2; i >= 0; i--){ - n[i] = list.addAfter(i, n[i + 1]); - } - // list: 4->3->2->1->0 - ASSERT_EQ(5, list.size()) << "size should be 5"; - ASSERT_EQ(n[4], list.head()) << "4 should be at head"; - ASSERT_EQ(n[3], list.head()->next()) << "3 should be 4->next"; - ASSERT_EQ(n[2], list.head()->next()->next()) << "2 should be 3->next"; - ASSERT_EQ(n[1], list.head()->next()->next()->next()) << "1 should be 2->next"; - ASSERT_EQ(n[0], list.head()->next()->next()->next()->next()) << "0 should be 1->next"; - ASSERT_EQ(list.end().pNode, list.head()->next()->next()->next()->next()->next()) << "tail->next should be end()"; - - ASSERT_EQ(n[0], list.tail()) << "0 should be at tail"; - ASSERT_EQ(n[1], list.tail()->prev()) << "1 should be 0->prev"; - ASSERT_EQ(n[2], list.tail()->prev()->prev()) << "2 should be 1->prev"; - ASSERT_EQ(n[3], list.tail()->prev()->prev()->prev()) << "3 should be 2->prev"; - ASSERT_EQ(n[4], list.tail()->prev()->prev()->prev()->prev()) << "4 should be 3->prev"; - ASSERT_EQ(list.end().pNode, list.tail()->prev()->prev()->prev()->prev()->prev()) << "head->prev should be end()"; - - ASSERT_EQ(4, list.head()->element) << "4 should be at head"; - ASSERT_EQ(3, list.head()->next()->element) << "3 should be 4->next"; - ASSERT_EQ(2, list.head()->next()->next()->element) << "2 should be 3->next"; - ASSERT_EQ(1, list.head()->next()->next()->next()->element) << "1 should be 2->next"; - ASSERT_EQ(0, list.head()->next()->next()->next()->next()->element) << "0 should be 1->next"; - - // add in the middle - node_t* n10 = list.addAfter(10, n[3]); - // list: 4->3->10->2->1->0 - ASSERT_EQ(6, list.size()) << "size should be 6"; - ASSERT_EQ(n[4], list.head()) << "4 should be at head"; - ASSERT_EQ(n[3], list.head()->next()) << "3 should be 4->next"; - ASSERT_EQ(n10, list.head()->next()->next()) << "10 should be 3->next"; - ASSERT_EQ(n[2], list.head()->next()->next()->next()) << "2 should be 10->next"; - ASSERT_EQ(n[1], list.head()->next()->next()->next()->next()) << "1 should be 10->next"; - ASSERT_EQ(n[0], list.head()->next()->next()->next()->next()->next()) << "0 should be 1->next"; - ASSERT_EQ(list.end().pNode, list.head()->next()->next()->next()->next()->next()->next()) << "tail->next should be end()"; - - ASSERT_EQ(n[0], list.tail()) << "0 should be at tail"; - ASSERT_EQ(n[1], list.tail()->prev()) << "1 should be 0->prev"; - ASSERT_EQ(n[2], list.tail()->prev()->prev()) << "2 should be 1->prev"; - ASSERT_EQ(n10, list.tail()->prev()->prev()->prev()) << "10 should be 2->prev"; - ASSERT_EQ(n[3], list.tail()->prev()->prev()->prev()->prev()) << "3 should be 10->prev"; - ASSERT_EQ(n[4], list.tail()->prev()->prev()->prev()->prev()->prev()) << "4 should be 3->prev"; - ASSERT_EQ(list.end().pNode, list.tail()->prev()->prev()->prev()->prev()->prev()->prev()) << "head->prev should be end()"; - - ASSERT_EQ(4, list.head()->element) << "4 should be at head"; - ASSERT_EQ(3, list.head()->next()->element) << "3 should be 4->next"; - ASSERT_EQ(10, list.head()->next()->next()->element) << "10 should be 3->next"; - ASSERT_EQ(2, list.head()->next()->next()->next()->element) << "2 should be 10->next"; - ASSERT_EQ(1, list.head()->next()->next()->next()->next()->element) << "1 should be 10->next"; - ASSERT_EQ(0, list.head()->next()->next()->next()->next()->next()->element) << "0 should be 1->next"; - - } - - - void remove(){ - int e; - bool ok; - node_t *n1, *n2, *n3, *n4, *n5; - IntList list; - ASSERT_EQ(0, list.size()) << "size should be zero"; - ASSERT_EQ(0, (int)list.head()) << "head should be NULL"; - - { - SCOPED_TRACE("removing from empty list"); - ok = list.remove(list.head(), e); // should fail - ASSERT_EQ(false, ok) << "remove() succeeded on empty list"; - } - - { - SCOPED_TRACE("removing the only node"); - n1 = list.addFront(1); - ok = list.remove(n1, e); - ASSERT_EQ(true, ok) << "remove failed"; - ASSERT_EQ(1, e) << "wrong element in removed node"; - ASSERT_EQ(0, list.size()) << "size should be zero"; - ASSERT_EQ(true, list.empty()) << "list should be empty"; - - // reinsert a node - list.addFront(1); - ASSERT_EQ(1, list.size()) << "size should be 1"; - ASSERT_EQ(false, list.empty()) << "list should be non-empty"; - } - - { - // list: 1 - SCOPED_TRACE("remove the second node of a size-2 list"); - n1 = list.addFront(2); // list: 2->1 - ok = list.remove(n1, e); // list: 1 - ASSERT_EQ(true, ok) << "remove failed"; - ASSERT_EQ(2, e) << "wrong element in removed node"; - ASSERT_EQ(1, list.size()) << "size should be zero"; - ASSERT_EQ(false, list.empty()) << "list should be empty"; - ASSERT_EQ(1, list.head()->element) << "head-element should be 1"; - } - - { - // list: 1 - SCOPED_TRACE("remove the last node of a size-3 list"); - n1 = list.head(); // list: 1 - n2 = list.addFront(2); // list: 2->1 - n3 = list.addFront(3); // list: 3->2->1 - - ok = list.remove(n1, e); // remove 1; list: 3->2 - ASSERT_EQ(true, ok) << "remove failed"; - ASSERT_EQ(1, e) << "wrong element in removed node"; - ASSERT_EQ(2, list.size()) << "size should be 2"; - ASSERT_EQ(false, list.empty()) << "list should not be empty"; - - ASSERT_EQ(n3, list.head()) << "wrong pointer at list head"; - ASSERT_EQ(n2, list.tail()) << "wrong pointer at list tail"; - ASSERT_EQ(n2, list.head()->next()) << "wrong pointer at list head->next"; - ASSERT_EQ(n3, list.tail()->prev()) << "wrong pointer at list tail->prev"; - ASSERT_EQ(3, list.head()->element) << "head-element should be 1"; - ASSERT_EQ(2, list.head()->next()->element) << "head-element should be 2"; - - } - - { - // list: 3->2 - SCOPED_TRACE("remove a middle node"); - n3 = list.head(); // list: 3->2 - n2 = n3->next(); // - n4 = list.addFront(4); // list: 4->3->2 - n5 = list.addFront(5); // list: 5->4->3->2 - - - // try to remove 4 - ok = list.remove(n4, e); // remove 4; list: 5->3->2 - ASSERT_EQ(true, ok) << "remove failed"; - ASSERT_EQ(4, e) << "removed element should be 4"; - ASSERT_EQ(3, list.size()) << "size should be 3"; - ASSERT_EQ(false, list.empty()) << "list should not be empty"; - - ASSERT_EQ(n5, list.head()) << "wrong pointer at list head"; - ASSERT_EQ(n3, list.head()->next()) << "wrong pointer at list head->next"; - ASSERT_EQ(n2, list.head()->next()->next()) << "wrong pointer at list head->next->next"; - ASSERT_EQ(list.end().pNode, n2->next()) << "last->next should be end()"; - - ASSERT_EQ(n2, list.tail()) << "wrong pointer at list tail"; - ASSERT_EQ(n3, list.tail()->prev()) << "wrong pointer at list tail->prev"; - ASSERT_EQ(n5, list.tail()->prev()->prev()) << "wrong pointer at list tail->prev->prev"; - ASSERT_EQ(list.end().pNode, n5->prev()) << "head->prev should be end()"; - - ASSERT_EQ(5, list.head()->element) << "head-element should be 5"; - ASSERT_EQ(3, list.head()->next()->element) << "head-element should be 3"; - ASSERT_EQ(2, list.head()->next()->next()->element) << "head-element should be 2"; - - // now try to remove 3 - // list: 5->3->2 - ok = list.remove(n3, e); // remove 3; list: 5->2 - ASSERT_EQ(true, ok) << "remove failed"; - ASSERT_EQ(3, e) << "removed element should be 3"; - ASSERT_EQ(2, list.size()) << "size should be 2"; - ASSERT_EQ(false, list.empty()) << "list should not be empty"; - - ASSERT_EQ(n5, list.head()) << "wrong pointer at list head"; - ASSERT_EQ(n2, list.head()->next()) << "wrong pointer at list head->next"; - ASSERT_EQ(list.end().pNode, list.head()->next()->next()) << "last->next should be end()"; - ASSERT_EQ(n2, list.tail()) << "wrong pointer at list tail"; - ASSERT_EQ(n5, list.tail()->prev()) << "wrong pointer at list tail->prev"; - ASSERT_EQ(list.end().pNode, list.tail()->prev()->prev()) << "head->prev should be end()"; - - ASSERT_EQ(5, list.head()->element) << "head-element should be 5"; - ASSERT_EQ(2, list.head()->next()->element) << "head-next element should be 2"; - } - } - void head(){ - int e; - //IntList list = * static_cast(createList()); - IntList list; - node_t* pNode = list.head(); - ASSERT_EQ(0, (int)pNode) << "head must be null at the beginning"; - - list.addFront(4); - pNode = list.head(); - ASSERT_NE(0, (int)pNode) << "head is NULL although list has items"; - ASSERT_EQ(list.end().pNode, pNode->next()) << "head's next should be end()"; - ASSERT_EQ(list.head(), list.tail()) << "tail should be = head"; - ASSERT_EQ(1, list.size()) << "size should have been 1"; - ASSERT_EQ(false, list.empty()) << "non-empty list is showing empty"; - ASSERT_EQ(4, pNode->element) << "head-element should have been 4"; - - list.remove(pNode, e); - pNode = list.head(); - ASSERT_EQ(0, (int)pNode) << "head should have been null"; - } - - void tail(){ - int e; - IntList list; - node_t* pNode = list.tail(); - ASSERT_EQ(0, (int)pNode) << "tail must be null at the beginning"; - - list.addFront(4); - pNode = list.tail(); - ASSERT_NE(0, (int)pNode) << "tail is NULL although list has items"; - ASSERT_EQ(list.end().pNode, pNode->next()) << "tail's next should be end()"; - ASSERT_EQ(list.end().pNode, pNode->prev()) << "tail's prev should be end()"; - ASSERT_EQ(list.head(), list.tail()) << "tail should be = head"; - ASSERT_EQ(1, list.size()) << "size should have been 1"; - ASSERT_EQ(false, list.empty()) << "non-empty list is showing empty"; - ASSERT_EQ(4, pNode->element) << "tail-element should have been 4"; - - list.remove(pNode, e); - pNode = list.tail(); - ASSERT_EQ(0, (int)pNode) << "tail should have been null"; - } - - void clear(){ - IntList list; - int srcArr[] = { 10, 20, 30, 40 }; - int n = ARR_LENGTH(srcArr); - - list.fromArray(srcArr, n); // build list - //ASSERT_NE(0, (int)list.head()) << "list head is NULL"; - ASSERT_EQ(n, list.size()) << "list size should have been " << n; - - list.clear(); - ASSERT_EQ(0, list.size()) << "size not zero after clear"; - ASSERT_EQ(true, list.empty()) << "size not zero after clear"; - ASSERT_EQ(NULL, list.head()) << "head not NULL after clear"; - ASSERT_EQ(NULL, list.tail()) << "tail not NULL after clear"; - } - - }; - - ADD_TEST_F(DoublyLinkedListTest, insert); - ADD_TEST_F(DoublyLinkedListTest, addFront); - ADD_TEST_F(DoublyLinkedListTest, addBack); - ADD_TEST_F(DoublyLinkedListTest, addBefore); - ADD_TEST_F(DoublyLinkedListTest, addAfter); - ADD_TEST_F(DoublyLinkedListTest, remove); - ADD_TEST_F(DoublyLinkedListTest, head); - ADD_TEST_F(DoublyLinkedListTest, tail); - - ADD_TEST_F(DoublyLinkedListTest, fromArray); - ADD_TEST_F(DoublyLinkedListTest, elements); - ADD_TEST_F(DoublyLinkedListTest, relements); - ADD_TEST_F(DoublyLinkedListTest, clear); - ADD_TEST_F(DoublyLinkedListTest, toString); } // namespace ds diff --git a/YASI_12/ds.doublylinkedlist.test.h b/YASI_12/ds.doublylinkedlist.test.h new file mode 100644 index 0000000..c5737d9 --- /dev/null +++ b/YASI_12/ds.doublylinkedlist.test.h @@ -0,0 +1,750 @@ +#pragma once + +#if YASI_TEST_THIS_MODULE != 1 +#define YASI_TEST_THIS_MODULE 1 +#endif + +#include "ds.doublylinkedlist.h" +using namespace std; + +namespace yasi{ + namespace ds{ + + // test + class DoublyLinkedListTest : public yasi::Test { + typedef DoublyLinkedList >::node_t node_t; + typedef DoublyLinkedList > IntList; + typedef IntList::iterator IntIterator; + protected: + template + void checkListElements(DoublyLinkedList >* pList, const E* srcArr, const int n){ + E* pElems = new E[n]; + int numElems; + DoublyLinkedList >& list = *pList; + list.elements(&pElems); + ASSERT_EQ(true, arrcmp(srcArr, pElems, n)) << "arrays are not the same" << endl + << "actual: " << arrToString(srcArr, n) << endl + << "expected: " << arrToString(pElems, n); + DELETE_ARR_SAFE(pElems); + } + public: + virtual void fromArray(){ + IntList list; + int srcArr[] = { 10, 20, 30, 40 }; + int n = ARR_LENGTH(srcArr); + + list.fromArray(srcArr, n); // build list + ASSERT_NE(0, (int)list.head()) << "head is NULL"; + ASSERT_EQ(4, (int)list.size()) << "size is not 4"; + int j = n - 1; + + for (IntIterator it = list.begin(); it != list.end(); it++){ + ASSERT_EQ(srcArr[j], *it) << "element mismatch at item " << n - j - 1 << " in list"; + j--; + } + } + virtual void elements(){ + IntList list; + int srcArr[] = { 10, 20, 30, 40 }; + int n = ARR_LENGTH(srcArr); + + list.fromArray(srcArr, n); // build list + //ASSERT_NE(0, (int)list.head()) << "list head is NULL"; + ASSERT_EQ(n, list.size()) << "list size should have been " << n; + // since the elements are given in reverse order + int* pRev = new int[n]; + arrrev(srcArr, n, &pRev); + ASSERT_NE(0, (int)pRev) << "array reverse failed"; + { + SCOPED_TRACE("elements"); + checkListElements(&list, pRev, n); + } + DELETE_ARR_SAFE(pRev); + } + + void relements(){ + IntList list; + int srcArr[] = { 10, 20, 30, 40 }; + const int n = ARR_LENGTH(srcArr); + + list.fromArray(srcArr, n); // build list + ASSERT_EQ(n, list.size()) << "list size should have been " << n; + + int* pRelems = new int[n]; + list.relements(&pRelems); + // pRelems should be in the same order as srcArr + ASSERT_EQ(true, arrcmp(srcArr, pRelems, n)) << "arrays are not the same" << endl + << "actual: " << arrToString(pRelems, n) << endl + << "expected: " << arrToString(srcArr, n); + DELETE_ARR_SAFE(pRelems); + } + + void toString(){ + int srcArr[] = { 1, 2, 3, 4 }; + const string expected = "4->3->2->1->"; + IntList list(srcArr, ARR_LENGTH(srcArr)); + string actual = list.toString(); + ASSERT_EQ(expected, actual) << "toString() is wrong"; + } + + void addFront(){ + IntList list; + ASSERT_EQ(0, list.size()) << "size should be zero"; + ASSERT_EQ(0, (int)list.head()) << "head should be NULL"; + + node_t *n1, *n2, *n3; + + // add head + { + SCOPED_TRACE("add #1"); + n1 = list.addFront(4); // new node is at head + // list: 4 + ASSERT_NE(0, (int)list.head()) << "head is NULL"; + ASSERT_NE(0, (int)list.tail()) << "tail is NULL"; + ASSERT_EQ(list.head(), list.tail()) << "head != tail"; + + ASSERT_EQ(list.head(), n1) << "addFront() does not return correct node"; + ASSERT_NE(0, (int)n1) << "head is NULL although list has items"; + ASSERT_EQ(list.end().pNode, n1->next()) << "head's next should be end()"; + ASSERT_EQ(list.end().pNode, n1->prev()) << "head's prev should be end()"; + ASSERT_EQ(1, list.size()) << "size should have been 1"; + ASSERT_EQ(false, list.empty()) << "non-empty list is showing empty"; + ASSERT_EQ(4, n1->element) << "head-element should have been 4"; + + // iterators + ASSERT_EQ(list.head(), list.begin().pNode) << "head() not equal to begin().pNode"; + ASSERT_EQ(list.tail(), list.begin().pNode) << "tail() not equal to begin().pNode"; + ASSERT_NE(list.begin(), list.end()) << "begin() and end() same for non-empty list"; + ASSERT_EQ(list.end(), ++list.begin()) << "++begin() and end() not same"; + ASSERT_EQ(list.begin(), --list.end()) << "--end() and begin() not same"; + ASSERT_NE(list.end(), list.begin()++) << "begin()++ and end() same"; + ASSERT_NE(list.begin(), list.end()--) << "end()-- and begin() same"; + ASSERT_EQ(list.head(), (list.begin()++).pNode) << "begin()++.pNode not head()"; + ASSERT_EQ(list.tail(), (--list.end()).pNode) << "--end().pNode not tail()"; + ASSERT_EQ(list.end().pNode, (++list.begin()).pNode) << "begin++.pNode should be end()"; + ASSERT_EQ(list.begin().pNode, (--list.end()).pNode) << "--end.pNode should be begin()"; + ASSERT_EQ(4, *list.begin()) << "begin()-element should have been 4"; + ASSERT_EQ(4, *(--list.end())) << "--end()-element should have been 4"; + } + + // add 2nd element + { + SCOPED_TRACE("add #2"); + n2 = list.addFront(5); // new node is at head + + // list: 5->4 + ASSERT_NE(0, (int)list.head()) << "head is NULL although list has items"; + ASSERT_EQ(list.head(), n2) << "n2 should be head"; + ASSERT_EQ(list.tail(), n1) << "n1 should be tail"; + + ASSERT_NE(list.end().pNode, list.head()->next()) << "head->next is end() although list has 2 items"; + ASSERT_EQ(n1, list.head()->next()) << "head->next hsould be n1"; + ASSERT_EQ(list.head(), n1->prev()) << "n1->prev should be head"; + + ASSERT_EQ(list.end().pNode, list.tail()->next()) << "tail->next should be end()"; + ASSERT_EQ(list.end().pNode, n1->prev()->prev()) << "n1->perv->prev should be end()"; + ASSERT_EQ(5, list.head()->element) << "head element should have been 5"; + ASSERT_EQ(2, list.size()) << "size should have been 2"; + ASSERT_EQ(false, list.empty()) << "non-empty list is showing empty"; + + ASSERT_EQ(5, list.head()->element) << "head-element should have been 5"; + ASSERT_EQ(4, list.head()->next()->element) << "head->next element should have been 4"; + + + // iterators + ASSERT_EQ(list.head(), list.begin().pNode) << "head() not equal to begin().pNode"; + ASSERT_EQ(list.tail(), (--(list.end())).pNode) << "tail() not equal to --end().pNode"; + ASSERT_NE(list.begin(), list.end()) << "begin() and end() same for non-empty list"; + ASSERT_EQ(list.end(), ++(++(list.begin()))) << "++++begin() not end()"; + ASSERT_EQ(list.begin(), --(--(list.end()))) << "----end() not begin()"; + ASSERT_EQ(n2, (list.begin()++).pNode) << "begin++.pNode should be n2"; + ASSERT_EQ(n1, (++(list.begin())).pNode) << "++begin.pNode should be n1"; + ASSERT_EQ(n2, (--(--list.end())).pNode) << "----end.pNode should be n2"; + ASSERT_EQ(n1, (--(list.end())).pNode) << "--end.pNode should be n1"; + ASSERT_EQ(5, *(list.begin())) << "begin()-element should have been 5"; + ASSERT_EQ(4, *(++(list.begin()))) << "++begin()-element should have been 4"; + ASSERT_EQ(5, *(list.begin()++)) << "begin()-element should have been 5"; + ASSERT_EQ(4, *(--list.end())) << "--end()-element should have been 4"; + ASSERT_EQ(5, *(--(--list.end()))) << "----end()-element should have been 5"; + } + + // add more elements + { + SCOPED_TRACE("add #3"); + n3 = list.addFront(6); // new node is at head + + // list: 6->5->4 + ASSERT_NE(0, (int)list.head()) << "head is NULL although list has items"; + ASSERT_NE(0, (int)list.head()->next()) << "head->next is NULL"; + ASSERT_NE(0, (int)list.head()->next()->next()) << "head->next->next is NULL"; + + ASSERT_EQ(n3, list.head()) << "n3 should be head"; + ASSERT_EQ(n1, list.tail()) << "n1 should be tail"; + ASSERT_EQ(n2, list.head()->next()) << "n2 should be head->next"; + ASSERT_EQ(n2, list.tail()->prev()) << "n2 should be tail->prev"; + ASSERT_EQ(n3, n2->prev()) << "n3 should be n2->prev"; + ASSERT_EQ(list.tail(), n2->next()) << "n2->next should be tail"; + ASSERT_EQ(list.end().pNode, list.tail()->next()) << "tail->next should be end()"; + ASSERT_EQ(list.end().pNode, list.head()->prev()) << "head->prev should be end()"; + + ASSERT_EQ(6, list.head()->element) << "head element should have been 6"; + ASSERT_EQ(5, list.head()->next()->element) << "head->next element should have been 5"; + ASSERT_EQ(4, list.head()->next()->next()->element) << "head->next->next element should have been 4"; + ASSERT_EQ(3, list.size()) << "size should have been 3"; + ASSERT_EQ(false, list.empty()) << "non-empty list is showing empty"; + + // iterators + ASSERT_EQ(list.head(), list.begin().pNode) << "head() not equal to begin().pNode"; + ASSERT_NE(list.begin(), list.end()) << "begin() and end() same for non-empty list"; + ASSERT_EQ(n3, (list.begin()).pNode) << "begin.pNode should be n3"; + ASSERT_EQ(n3, ((list.begin())++).pNode) << "begin++.pNode should be n3"; + ASSERT_EQ(n3, ((list.begin())--).pNode) << "begin--.pNode should be n3"; + ASSERT_EQ(n2, (++(list.begin())).pNode) << "++begin.pNode should be n2"; + ASSERT_EQ(n1, (++(++(list.begin()))).pNode) << "++++begin.pNode should be pNode"; + ASSERT_EQ(list.end(), (++(++(++list.begin())))) << "++++++begin() not end()"; + + ASSERT_EQ(n3, (--(--(--list.end()))).pNode) << "------end.pNode should be n3"; + ASSERT_EQ(n2, (--(--list.end())).pNode) << "----end.pNode should be n2"; + ASSERT_EQ(n1, (--list.end()).pNode) << "--end.pNode should be pNode"; + ASSERT_EQ(list.begin(), --(--(--list.end()))) << "------end should be begin"; + ASSERT_EQ(6, *(list.begin())) << "begin()-element should have been 6"; + ASSERT_EQ(6, *(list.begin()++)) << "begin()++-element should have been 6"; + ASSERT_EQ(6, *(list.begin()--)) << "begin()-- element should have been 6"; + ASSERT_EQ(5, *(++(list.begin()))) << "++begin()-element should have been 5"; + ASSERT_EQ(4, *(++(++(list.begin())))) << "++++begin()-element should have been 4"; + ASSERT_EQ(4, *(--list.end())) << "--end()-element should have been 4"; + ASSERT_EQ(5, *(--(--list.end()))) << "----end()-element should have been 5"; + ASSERT_EQ(6, *(--(--(--list.end())))) << "------end()-element should have been 6"; + } + + } + + void addBack(){ + IntList list; + ASSERT_EQ(0, list.size()) << "size should be zero"; + ASSERT_EQ(0, (int)list.head()) << "head should be NULL"; + ASSERT_EQ(0, (int)list.tail()) << "head should be NULL"; + + node_t *n1, *n2, *n3; + + // add head + { + SCOPED_TRACE("add #1"); + n1 = list.addBack(4); // new node is at head + // list: 4 + ASSERT_NE(0, (int)list.head()) << "head is NULL"; + ASSERT_NE(0, (int)list.tail()) << "tail is NULL"; + ASSERT_EQ(list.head(), list.tail()) << "head != tail"; + + ASSERT_EQ(list.head(), n1) << "head() not n1"; + ASSERT_EQ(list.tail(), n1) << "tail() not n1"; + ASSERT_NE(0, (int)n1) << "head is NULL although list has items"; + ASSERT_EQ(list.end().pNode, n1->next()) << "head's next should be end()"; + ASSERT_EQ(list.end().pNode, n1->prev()) << "head's prev should be end()"; + ASSERT_EQ(1, list.size()) << "size should have been 1"; + ASSERT_EQ(false, list.empty()) << "non-empty list is showing empty"; + ASSERT_EQ(4, n1->element) << "head-element should have been 4"; + + // iterators + ASSERT_EQ(list.head(), list.begin().pNode) << "head() not equal to begin().pNode"; + ASSERT_EQ(list.tail(), list.begin().pNode) << "tail() not equal to begin().pNode"; + ASSERT_NE(list.begin(), list.end()) << "begin() and end() same for non-empty list"; + ASSERT_EQ(list.end(), ++list.begin()) << "++begin() and end() not same"; + ASSERT_EQ(list.begin(), --list.end()) << "--end() and begin() not same"; + ASSERT_NE(list.end(), list.begin()++) << "begin()++ and end() same"; + ASSERT_NE(list.begin(), list.end()--) << "end()-- and begin() same"; + ASSERT_EQ(list.head(), (list.begin()++).pNode) << "begin()++.pNode not head()"; + ASSERT_EQ(list.tail(), (--list.end()).pNode) << "--end().pNode not tail()"; + ASSERT_EQ(list.end().pNode, (++list.begin()).pNode) << "begin++.pNode should be end()"; + ASSERT_EQ(list.begin().pNode, (--list.end()).pNode) << "--end.pNode should be begin()"; + ASSERT_EQ(4, *list.begin()) << "begin()-element should have been 4"; + ASSERT_EQ(4, *(--list.end())) << "--end()-element should have been 4"; + } + + // add 2nd element + { + SCOPED_TRACE("add #2"); + n2 = list.addBack(5); // new node is at head + + // list: 4->5 + ASSERT_NE(0, (int)list.head()) << "head is NULL although list has items"; + ASSERT_EQ(list.head(), n1) << "n1 should be head"; + ASSERT_EQ(list.tail(), n2) << "n2 should be tail"; + ASSERT_EQ(list.tail(), list.head()->next()) << "head->next should be tail"; + + + ASSERT_NE(list.end().pNode, list.head()->next()) << "head->next is end()"; + ASSERT_EQ(n2, list.head()->next()) << "head->next should be n2"; + ASSERT_EQ(list.head(), n2->prev()) << "n2->prev should be head"; + + ASSERT_EQ(list.end().pNode, list.tail()->next()) << "tail->next should be end()"; + ASSERT_EQ(list.end().pNode, n2->prev()->prev()) << "n2->perv->prev should be end()"; + ASSERT_EQ(4, list.head()->element) << "head element should have been 4"; + ASSERT_EQ(5, list.tail()->element) << "tail element should have been 5"; + ASSERT_EQ(2, list.size()) << "size should have been 2"; + ASSERT_EQ(false, list.empty()) << "non-empty list is showing empty"; + + // iterators + ASSERT_EQ(list.head(), list.begin().pNode) << "head() not equal to begin().pNode"; + ASSERT_EQ(list.tail(), (--(list.end())).pNode) << "tail() not equal to --end().pNode"; + ASSERT_NE(list.begin(), list.end()) << "begin() and end() same for non-empty list"; + ASSERT_EQ(list.end(), ++(++(list.begin()))) << "++++begin() not end()"; + ASSERT_EQ(list.begin(), --(--(list.end()))) << "----end() not begin()"; + ASSERT_EQ(n1, (list.begin()++).pNode) << "begin++.pNode should be n1"; + ASSERT_EQ(n2, (++(list.begin())).pNode) << "++begin.pNode should be n2"; + ASSERT_EQ(n1, (--(--list.end())).pNode) << "----end.pNode should be n1"; + ASSERT_EQ(n2, (--(list.end())).pNode) << "--end.pNode should be n2"; + ASSERT_EQ(4, *(list.begin())) << "begin()-element should have been 4"; + ASSERT_EQ(5, *(++(list.begin()))) << "++begin() element should have been 5"; + ASSERT_EQ(4, *(list.begin()++)) << "begin()++ element should have been 4"; + ASSERT_EQ(5, *(--list.end())) << "--end()-element should have been 5"; + ASSERT_EQ(4, *(--(--list.end()))) << "----end()-element should have been 4"; + } + + // add more elements + { + SCOPED_TRACE("add #3"); + n3 = list.addBack(6); // new node is at head + + // list: 4->5->6 + ASSERT_NE(0, (int)list.head()) << "head is NULL although list has items"; + ASSERT_NE(list.end().pNode, list.head()->next()) << "head->next is end()"; + ASSERT_NE(list.end().pNode, list.head()->next()->next()) << "head->next->next is end()"; + + ASSERT_EQ(n3, list.tail()) << "n3 should be tail"; + ASSERT_EQ(n1, list.head()) << "n1 should be head"; + ASSERT_EQ(n2, list.head()->next()) << "n2 should be head->next"; + ASSERT_EQ(n2, list.tail()->prev()) << "n2 should be tail->prev"; + ASSERT_EQ(n3, n2->next()) << "n3 should be n2->next"; + ASSERT_EQ(list.head(), n2->prev()) << "n2->prev should be head"; + ASSERT_EQ(list.end().pNode, list.tail()->next()) << "tail->next should be end()"; + ASSERT_EQ(list.end().pNode, list.head()->prev()) << "head->prev should be end()"; + + ASSERT_EQ(4, list.head()->element) << "head element should have been 4"; + ASSERT_EQ(5, list.head()->next()->element) << "head->next element should have been 5"; + ASSERT_EQ(6, list.head()->next()->next()->element) << "head->next->next element should have been 6"; + ASSERT_EQ(3, list.size()) << "size should have been 3"; + ASSERT_EQ(false, list.empty()) << "non-empty list is showing empty"; + + // iterators + ASSERT_EQ(list.head(), list.begin().pNode) << "head() not equal to begin().pNode"; + ASSERT_NE(list.begin(), list.end()) << "begin() and end() same for non-empty list"; + ASSERT_EQ(n1, (list.begin()).pNode) << "begin.pNode should be n1"; + ASSERT_EQ(n1, ((list.begin())++).pNode) << "begin++.pNode should be n1"; + ASSERT_EQ(n1, ((list.begin())--).pNode) << "begin--.pNode should be n1"; + ASSERT_EQ(n2, (++(list.begin())).pNode) << "++begin.pNode should be n2"; + ASSERT_EQ(n3, (++(++(list.begin()))).pNode) << "++++begin.pNode should be n3"; + ASSERT_EQ(list.end(), (++(++(++list.begin())))) << "++++++begin() not end()"; + + ASSERT_EQ(n1, (--(--(--list.end()))).pNode) << "------end.pNode should be n1"; + ASSERT_EQ(n2, (--(--list.end())).pNode) << "----end.pNode should be n2"; + ASSERT_EQ(n3, (--list.end()).pNode) << "--end.pNode should be n3"; + ASSERT_EQ(list.begin(), --(--(--list.end()))) << "------end should be begin"; + ASSERT_EQ(4, *(list.begin())) << "begin()-element should have been 4"; + ASSERT_EQ(4, *(list.begin()++)) << "begin()++-element should have been 4"; + ASSERT_EQ(4, *(list.begin()--)) << "begin()-- element should have been 4"; + ASSERT_EQ(5, *(++(list.begin()))) << "++begin()-element should have been 5"; + ASSERT_EQ(6, *(++(++(list.begin())))) << "++++begin()-element should have been 6"; + ASSERT_EQ(6, *(--list.end())) << "--end()-element should have been 6"; + ASSERT_EQ(5, *(--(--list.end()))) << "----end()-element should have been 5"; + ASSERT_EQ(4, *(--(--(--list.end())))) << "------end()-element should have been 4"; + } + + } + + void insert(){ + IntList list; + node_t* n[] = { + list.addBack(0), + list.addBack(1), + list.addBack(2), + list.addBack(3) + }; + // list: 0--1--2--3 + + // insert before 0 + { + SCOPED_TRACE("insert before 0"); + node_t* n_1 = list.insert(n[0], -1); // insert -1 before 0 + ASSERT_EQ(5, list.size()) << "size not 5"; + ASSERT_EQ(-1, *list.begin()) << "begin() element not -1"; + ASSERT_EQ(n_1, list.begin().pNode) << "begin() node not n_1"; + } + // list: (-1)--0--1--2--3 + + // insert after 3 + { + SCOPED_TRACE("insert after 3"); + node_t* n4 = list.insert(n[3]->next(), 4); // insert 4 after 3 + ASSERT_EQ(6, list.size()) << "size not 6"; + ASSERT_EQ(4, *--list.end()) << "--end() element not 4"; + ASSERT_EQ(n4, (--list.end()).pNode) << "--end() node not n4"; + } + // list: (-1)--0--1--2--3--4 + + // insert before 2 + { + SCOPED_TRACE("insert before 2"); + node_t* n10 = list.insert(n[2], 10); // insert 10 before 2 + ASSERT_EQ(7, list.size()) << "size not 7"; + ASSERT_EQ(10, *++ ++ ++list.begin()) << "n10 element not 10 from begin"; + ASSERT_EQ(n10, (-- -- -- --list.end()).pNode) << "node not n10 from end"; + } + // list: (-1)--0--1--10--2--3--4 + + } + + void addBefore(){ + IntList list; + ASSERT_EQ(0, list.size()) << "size should be zero"; + ASSERT_EQ(0, (int)list.head()) << "head should be NULL"; + + // add before NULL + node_t* pNode = list.addBefore(5, NULL); // should fail + ASSERT_EQ(NULL, pNode) << "added before NULL"; + + // one-item list + node_t* n0 = list.addFront(0); + ASSERT_EQ(0, n0->element) << "wrong element"; + node_t* n1 = list.addBefore(1, n0); + // list: 1->0 + ASSERT_EQ(n1, list.head()) << "n1 should be head"; + ASSERT_EQ(n0, list.tail()) << "n0 should be tail"; + ASSERT_EQ(1, list.head()->element) << "wrong head element"; + ASSERT_EQ(0, list.tail()->element) << "wrong tail element"; + ASSERT_EQ(n0, n1->next()) << "n1->next should be n0"; + ASSERT_EQ(n1, n0->prev()) << "n0->prev should be n1"; + ASSERT_EQ(2, list.size()) << "size should be 2"; + ASSERT_EQ(list.end().pNode, n1->prev()) << "n1->prev should be end()"; + ASSERT_EQ(list.end().pNode, n0->next()) << "n0->next should be end()"; + + // add more items + const int testSize = 5; + node_t* n[testSize]; + n[0] = n0; + n[1] = n1; + for (int i = 2; i < testSize; i++){ + n[i] = list.addBefore(i, n[i - 1]); + } + // list: 4->3->2->1->0 + ASSERT_EQ(5, list.size()) << "size should be 5"; + ASSERT_EQ(n[4], list.head()) << "4 should be at head"; + ASSERT_EQ(n[3], list.head()->next()) << "3 should be 4->next"; + ASSERT_EQ(n[2], list.head()->next()->next()) << "2 should be 3->next"; + ASSERT_EQ(n[1], list.head()->next()->next()->next()) << "1 should be 2->next"; + ASSERT_EQ(n[0], list.head()->next()->next()->next()->next()) << "0 should be 1->next"; + ASSERT_EQ(list.end().pNode, list.head()->next()->next()->next()->next()->next()) << "tail->next should be end()"; + + ASSERT_EQ(n[0], list.tail()) << "0 should be at tail"; + ASSERT_EQ(n[1], list.tail()->prev()) << "1 should be 0->prev"; + ASSERT_EQ(n[2], list.tail()->prev()->prev()) << "2 should be 1->prev"; + ASSERT_EQ(n[3], list.tail()->prev()->prev()->prev()) << "3 should be 2->prev"; + ASSERT_EQ(n[4], list.tail()->prev()->prev()->prev()->prev()) << "4 should be 3->prev"; + ASSERT_EQ(list.end().pNode, list.tail()->prev()->prev()->prev()->prev()->prev()) << "head->prev should be end()"; + + ASSERT_EQ(4, list.head()->element) << "4 should be at head"; + ASSERT_EQ(3, list.head()->next()->element) << "3 should be 4->next"; + ASSERT_EQ(2, list.head()->next()->next()->element) << "2 should be 3->next"; + ASSERT_EQ(1, list.head()->next()->next()->next()->element) << "1 should be 2->next"; + ASSERT_EQ(0, list.head()->next()->next()->next()->next()->element) << "0 should be 1->next"; + + // add in the middle + node_t* n10 = list.addBefore(10, n[2]); + // list: 4->3->10->2->1->0 + ASSERT_EQ(6, list.size()) << "size should be 6"; + ASSERT_EQ(n[4], list.head()) << "4 should be at head"; + ASSERT_EQ(n[3], list.head()->next()) << "3 should be 4->next"; + ASSERT_EQ(n10, list.head()->next()->next()) << "10 should be 3->next"; + ASSERT_EQ(n[2], list.head()->next()->next()->next()) << "2 should be 10->next"; + ASSERT_EQ(n[1], list.head()->next()->next()->next()->next()) << "1 should be 10->next"; + ASSERT_EQ(n[0], list.head()->next()->next()->next()->next()->next()) << "0 should be 1->next"; + ASSERT_EQ(list.end().pNode, list.head()->next()->next()->next()->next()->next()->next()) << "tail->next should be end()"; + + ASSERT_EQ(n[0], list.tail()) << "0 should be at tail"; + ASSERT_EQ(n[1], list.tail()->prev()) << "1 should be 0->prev"; + ASSERT_EQ(n[2], list.tail()->prev()->prev()) << "2 should be 1->prev"; + ASSERT_EQ(n10, list.tail()->prev()->prev()->prev()) << "10 should be 2->prev"; + ASSERT_EQ(n[3], list.tail()->prev()->prev()->prev()->prev()) << "3 should be 10->prev"; + ASSERT_EQ(n[4], list.tail()->prev()->prev()->prev()->prev()->prev()) << "4 should be 3->prev"; + ASSERT_EQ(list.end().pNode, list.tail()->prev()->prev()->prev()->prev()->prev()->prev()) << "head->prev should be end()"; + + ASSERT_EQ(4, list.head()->element) << "4 should be at head"; + ASSERT_EQ(3, list.head()->next()->element) << "3 should be 4->next"; + ASSERT_EQ(10, list.head()->next()->next()->element) << "10 should be 3->next"; + ASSERT_EQ(2, list.head()->next()->next()->next()->element) << "2 should be 10->next"; + ASSERT_EQ(1, list.head()->next()->next()->next()->next()->element) << "1 should be 10->next"; + ASSERT_EQ(0, list.head()->next()->next()->next()->next()->next()->element) << "0 should be 1->next"; + + } + void addAfter(){ + IntList list; + ASSERT_EQ(0, list.size()) << "size should be zero"; + ASSERT_EQ(0, (int)list.head()) << "head should be NULL"; + + // add before NULL + node_t* pNode = list.addBefore(5, NULL); // should fail + ASSERT_EQ(NULL, pNode) << "added before NULL"; + + // one-item list + node_t* n4 = list.addFront(4); + ASSERT_EQ(4, n4->element) << "wrong element"; + node_t* n3 = list.addAfter(3, n4); + // list: 4->3 + ASSERT_EQ(n4, list.head()) << "n1 should be head"; + ASSERT_EQ(n3, list.tail()) << "n0 should be tail"; + ASSERT_EQ(4, list.head()->element) << "wrong head element"; + ASSERT_EQ(3, list.tail()->element) << "wrong tail element"; + ASSERT_EQ(n3, n4->next()) << "n4->next should be n3"; + ASSERT_EQ(n4, n3->prev()) << "n3->prev should be n4"; + ASSERT_EQ(2, list.size()) << "size should be 2"; + ASSERT_EQ(list.end().pNode, n4->prev()) << "n4->prev should be end()"; + ASSERT_EQ(list.end().pNode, n3->next()) << "n3->next should be end()"; + + // add more items + const int testSize = 5; + node_t* n[testSize]; + n[4] = n4; + n[3] = n3; + for (int i = 2; i >= 0; i--){ + n[i] = list.addAfter(i, n[i + 1]); + } + // list: 4->3->2->1->0 + ASSERT_EQ(5, list.size()) << "size should be 5"; + ASSERT_EQ(n[4], list.head()) << "4 should be at head"; + ASSERT_EQ(n[3], list.head()->next()) << "3 should be 4->next"; + ASSERT_EQ(n[2], list.head()->next()->next()) << "2 should be 3->next"; + ASSERT_EQ(n[1], list.head()->next()->next()->next()) << "1 should be 2->next"; + ASSERT_EQ(n[0], list.head()->next()->next()->next()->next()) << "0 should be 1->next"; + ASSERT_EQ(list.end().pNode, list.head()->next()->next()->next()->next()->next()) << "tail->next should be end()"; + + ASSERT_EQ(n[0], list.tail()) << "0 should be at tail"; + ASSERT_EQ(n[1], list.tail()->prev()) << "1 should be 0->prev"; + ASSERT_EQ(n[2], list.tail()->prev()->prev()) << "2 should be 1->prev"; + ASSERT_EQ(n[3], list.tail()->prev()->prev()->prev()) << "3 should be 2->prev"; + ASSERT_EQ(n[4], list.tail()->prev()->prev()->prev()->prev()) << "4 should be 3->prev"; + ASSERT_EQ(list.end().pNode, list.tail()->prev()->prev()->prev()->prev()->prev()) << "head->prev should be end()"; + + ASSERT_EQ(4, list.head()->element) << "4 should be at head"; + ASSERT_EQ(3, list.head()->next()->element) << "3 should be 4->next"; + ASSERT_EQ(2, list.head()->next()->next()->element) << "2 should be 3->next"; + ASSERT_EQ(1, list.head()->next()->next()->next()->element) << "1 should be 2->next"; + ASSERT_EQ(0, list.head()->next()->next()->next()->next()->element) << "0 should be 1->next"; + + // add in the middle + node_t* n10 = list.addAfter(10, n[3]); + // list: 4->3->10->2->1->0 + ASSERT_EQ(6, list.size()) << "size should be 6"; + ASSERT_EQ(n[4], list.head()) << "4 should be at head"; + ASSERT_EQ(n[3], list.head()->next()) << "3 should be 4->next"; + ASSERT_EQ(n10, list.head()->next()->next()) << "10 should be 3->next"; + ASSERT_EQ(n[2], list.head()->next()->next()->next()) << "2 should be 10->next"; + ASSERT_EQ(n[1], list.head()->next()->next()->next()->next()) << "1 should be 10->next"; + ASSERT_EQ(n[0], list.head()->next()->next()->next()->next()->next()) << "0 should be 1->next"; + ASSERT_EQ(list.end().pNode, list.head()->next()->next()->next()->next()->next()->next()) << "tail->next should be end()"; + + ASSERT_EQ(n[0], list.tail()) << "0 should be at tail"; + ASSERT_EQ(n[1], list.tail()->prev()) << "1 should be 0->prev"; + ASSERT_EQ(n[2], list.tail()->prev()->prev()) << "2 should be 1->prev"; + ASSERT_EQ(n10, list.tail()->prev()->prev()->prev()) << "10 should be 2->prev"; + ASSERT_EQ(n[3], list.tail()->prev()->prev()->prev()->prev()) << "3 should be 10->prev"; + ASSERT_EQ(n[4], list.tail()->prev()->prev()->prev()->prev()->prev()) << "4 should be 3->prev"; + ASSERT_EQ(list.end().pNode, list.tail()->prev()->prev()->prev()->prev()->prev()->prev()) << "head->prev should be end()"; + + ASSERT_EQ(4, list.head()->element) << "4 should be at head"; + ASSERT_EQ(3, list.head()->next()->element) << "3 should be 4->next"; + ASSERT_EQ(10, list.head()->next()->next()->element) << "10 should be 3->next"; + ASSERT_EQ(2, list.head()->next()->next()->next()->element) << "2 should be 10->next"; + ASSERT_EQ(1, list.head()->next()->next()->next()->next()->element) << "1 should be 10->next"; + ASSERT_EQ(0, list.head()->next()->next()->next()->next()->next()->element) << "0 should be 1->next"; + + } + + + void remove(){ + int e; + bool ok; + node_t *n1, *n2, *n3, *n4, *n5; + IntList list; + ASSERT_EQ(0, list.size()) << "size should be zero"; + ASSERT_EQ(0, (int)list.head()) << "head should be NULL"; + + { + SCOPED_TRACE("removing from empty list"); + ok = list.remove(list.head(), e); // should fail + ASSERT_EQ(false, ok) << "remove() succeeded on empty list"; + } + + { + SCOPED_TRACE("removing the only node"); + n1 = list.addFront(1); + ok = list.remove(n1, e); + ASSERT_EQ(true, ok) << "remove failed"; + ASSERT_EQ(1, e) << "wrong element in removed node"; + ASSERT_EQ(0, list.size()) << "size should be zero"; + ASSERT_EQ(true, list.empty()) << "list should be empty"; + + // reinsert a node + list.addFront(1); + ASSERT_EQ(1, list.size()) << "size should be 1"; + ASSERT_EQ(false, list.empty()) << "list should be non-empty"; + } + + { + // list: 1 + SCOPED_TRACE("remove the second node of a size-2 list"); + n1 = list.addFront(2); // list: 2->1 + ok = list.remove(n1, e); // list: 1 + ASSERT_EQ(true, ok) << "remove failed"; + ASSERT_EQ(2, e) << "wrong element in removed node"; + ASSERT_EQ(1, list.size()) << "size should be zero"; + ASSERT_EQ(false, list.empty()) << "list should be empty"; + ASSERT_EQ(1, list.head()->element) << "head-element should be 1"; + } + + { + // list: 1 + SCOPED_TRACE("remove the last node of a size-3 list"); + n1 = list.head(); // list: 1 + n2 = list.addFront(2); // list: 2->1 + n3 = list.addFront(3); // list: 3->2->1 + + ok = list.remove(n1, e); // remove 1; list: 3->2 + ASSERT_EQ(true, ok) << "remove failed"; + ASSERT_EQ(1, e) << "wrong element in removed node"; + ASSERT_EQ(2, list.size()) << "size should be 2"; + ASSERT_EQ(false, list.empty()) << "list should not be empty"; + + ASSERT_EQ(n3, list.head()) << "wrong pointer at list head"; + ASSERT_EQ(n2, list.tail()) << "wrong pointer at list tail"; + ASSERT_EQ(n2, list.head()->next()) << "wrong pointer at list head->next"; + ASSERT_EQ(n3, list.tail()->prev()) << "wrong pointer at list tail->prev"; + ASSERT_EQ(3, list.head()->element) << "head-element should be 1"; + ASSERT_EQ(2, list.head()->next()->element) << "head-element should be 2"; + + } + + { + // list: 3->2 + SCOPED_TRACE("remove a middle node"); + n3 = list.head(); // list: 3->2 + n2 = n3->next(); // + n4 = list.addFront(4); // list: 4->3->2 + n5 = list.addFront(5); // list: 5->4->3->2 + + + // try to remove 4 + ok = list.remove(n4, e); // remove 4; list: 5->3->2 + ASSERT_EQ(true, ok) << "remove failed"; + ASSERT_EQ(4, e) << "removed element should be 4"; + ASSERT_EQ(3, list.size()) << "size should be 3"; + ASSERT_EQ(false, list.empty()) << "list should not be empty"; + + ASSERT_EQ(n5, list.head()) << "wrong pointer at list head"; + ASSERT_EQ(n3, list.head()->next()) << "wrong pointer at list head->next"; + ASSERT_EQ(n2, list.head()->next()->next()) << "wrong pointer at list head->next->next"; + ASSERT_EQ(list.end().pNode, n2->next()) << "last->next should be end()"; + + ASSERT_EQ(n2, list.tail()) << "wrong pointer at list tail"; + ASSERT_EQ(n3, list.tail()->prev()) << "wrong pointer at list tail->prev"; + ASSERT_EQ(n5, list.tail()->prev()->prev()) << "wrong pointer at list tail->prev->prev"; + ASSERT_EQ(list.end().pNode, n5->prev()) << "head->prev should be end()"; + + ASSERT_EQ(5, list.head()->element) << "head-element should be 5"; + ASSERT_EQ(3, list.head()->next()->element) << "head-element should be 3"; + ASSERT_EQ(2, list.head()->next()->next()->element) << "head-element should be 2"; + + // now try to remove 3 + // list: 5->3->2 + ok = list.remove(n3, e); // remove 3; list: 5->2 + ASSERT_EQ(true, ok) << "remove failed"; + ASSERT_EQ(3, e) << "removed element should be 3"; + ASSERT_EQ(2, list.size()) << "size should be 2"; + ASSERT_EQ(false, list.empty()) << "list should not be empty"; + + ASSERT_EQ(n5, list.head()) << "wrong pointer at list head"; + ASSERT_EQ(n2, list.head()->next()) << "wrong pointer at list head->next"; + ASSERT_EQ(list.end().pNode, list.head()->next()->next()) << "last->next should be end()"; + ASSERT_EQ(n2, list.tail()) << "wrong pointer at list tail"; + ASSERT_EQ(n5, list.tail()->prev()) << "wrong pointer at list tail->prev"; + ASSERT_EQ(list.end().pNode, list.tail()->prev()->prev()) << "head->prev should be end()"; + + ASSERT_EQ(5, list.head()->element) << "head-element should be 5"; + ASSERT_EQ(2, list.head()->next()->element) << "head-next element should be 2"; + } + } + void head(){ + int e; + //IntList list = * static_cast(createList()); + IntList list; + node_t* pNode = list.head(); + ASSERT_EQ(0, (int)pNode) << "head must be null at the beginning"; + + list.addFront(4); + pNode = list.head(); + ASSERT_NE(0, (int)pNode) << "head is NULL although list has items"; + ASSERT_EQ(list.end().pNode, pNode->next()) << "head's next should be end()"; + ASSERT_EQ(list.head(), list.tail()) << "tail should be = head"; + ASSERT_EQ(1, list.size()) << "size should have been 1"; + ASSERT_EQ(false, list.empty()) << "non-empty list is showing empty"; + ASSERT_EQ(4, pNode->element) << "head-element should have been 4"; + + list.remove(pNode, e); + pNode = list.head(); + ASSERT_EQ(0, (int)pNode) << "head should have been null"; + } + + void tail(){ + int e; + IntList list; + node_t* pNode = list.tail(); + ASSERT_EQ(0, (int)pNode) << "tail must be null at the beginning"; + + list.addFront(4); + pNode = list.tail(); + ASSERT_NE(0, (int)pNode) << "tail is NULL although list has items"; + ASSERT_EQ(list.end().pNode, pNode->next()) << "tail's next should be end()"; + ASSERT_EQ(list.end().pNode, pNode->prev()) << "tail's prev should be end()"; + ASSERT_EQ(list.head(), list.tail()) << "tail should be = head"; + ASSERT_EQ(1, list.size()) << "size should have been 1"; + ASSERT_EQ(false, list.empty()) << "non-empty list is showing empty"; + ASSERT_EQ(4, pNode->element) << "tail-element should have been 4"; + + list.remove(pNode, e); + pNode = list.tail(); + ASSERT_EQ(0, (int)pNode) << "tail should have been null"; + } + + void clear(){ + IntList list; + int srcArr[] = { 10, 20, 30, 40 }; + int n = ARR_LENGTH(srcArr); + + list.fromArray(srcArr, n); // build list + //ASSERT_NE(0, (int)list.head()) << "list head is NULL"; + ASSERT_EQ(n, list.size()) << "list size should have been " << n; + + list.clear(); + ASSERT_EQ(0, list.size()) << "size not zero after clear"; + ASSERT_EQ(true, list.empty()) << "size not zero after clear"; + ASSERT_EQ(NULL, list.head()) << "head not NULL after clear"; + ASSERT_EQ(NULL, list.tail()) << "tail not NULL after clear"; + } + + }; + + ADD_TEST_F(DoublyLinkedListTest, insert); + ADD_TEST_F(DoublyLinkedListTest, addFront); + ADD_TEST_F(DoublyLinkedListTest, addBack); + ADD_TEST_F(DoublyLinkedListTest, addBefore); + ADD_TEST_F(DoublyLinkedListTest, addAfter); + ADD_TEST_F(DoublyLinkedListTest, remove); + ADD_TEST_F(DoublyLinkedListTest, head); + ADD_TEST_F(DoublyLinkedListTest, tail); + + ADD_TEST_F(DoublyLinkedListTest, fromArray); + ADD_TEST_F(DoublyLinkedListTest, elements); + ADD_TEST_F(DoublyLinkedListTest, relements); + ADD_TEST_F(DoublyLinkedListTest, clear); + ADD_TEST_F(DoublyLinkedListTest, toString); + } +} \ No newline at end of file diff --git a/YASI_12/ds.iterator.test.h b/YASI_12/ds.iterator.test.h index fafe2e5..5b2f4ee 100644 --- a/YASI_12/ds.iterator.test.h +++ b/YASI_12/ds.iterator.test.h @@ -1,4 +1,9 @@ #pragma once + +#if YASI_TEST_THIS_MODULE != 1 +#define YASI_TEST_THIS_MODULE 1 +#endif + #include "ds.iterator.h" using namespace std; diff --git a/YASI_12/ds.singlylinkedlist.h b/YASI_12/ds.singlylinkedlist.h index 857ae37..b6de2d3 100644 --- a/YASI_12/ds.singlylinkedlist.h +++ b/YASI_12/ds.singlylinkedlist.h @@ -7,6 +7,9 @@ #include using namespace std; +/******** enable-disable testing *******/ +#include "test.this.module.h" + namespace yasi{ namespace ds{ @@ -53,7 +56,7 @@ class SLLIterator : public ForwardNodeIterator >{ template, class Iter = SLLIterator > class SinglyLinkedList : public virtual ISinglyLinkedList < E, Node, Iter > { ///////////////// enable testing//////////////// - friend class SinglyLinkedListTest; + FRIEND_TEST_CLASS(SinglyLinkedListTest); protected: // typedefs @@ -288,524 +291,5 @@ std::ostream& operator<< (std::ostream& out, const SinglyLinkedList >::node_t node_t; - typedef SinglyLinkedList > IntList; - typedef IntList::iterator IntIterator; - - - -public: - template - void checkListElements(SinglyLinkedList >* pList, const E* srcArr, const int n){ - E* pElems = new int[n]; - int numElems; - SinglyLinkedList >& list = *pList; - list.elements(&pElems); - ASSERT_EQ(true, arrcmp(srcArr, pElems, n)) << "arrays are not the same" << endl - << "actual: " << arrToString(srcArr, n) << endl - << "expected: " << arrToString(pElems, n); - DELETE_ARR_SAFE(pElems); - } - - - void head(){ - int e; - //IntList list = * static_cast(createList()); - IntList list; - node_t* pNode = list.head(); - ASSERT_EQ(0, (int)pNode) << "head must be null at the beginning"; - - list.addFront(4); - pNode = list.head(); - ASSERT_NE(0, (int)pNode) << "head is NULL although list has items"; - ASSERT_EQ(list.end().pNode, pNode->next()) << "head's next should be end()"; - ASSERT_EQ(1, list.size()) << "size should have been 1"; - ASSERT_EQ(false, list.empty()) << "non-empty list is showing empty"; - ASSERT_EQ(4, pNode->element) << "head-element should have been 4"; - - list.remove(pNode, e); - pNode = list.head(); - ASSERT_EQ(0, (int)pNode) << "head should have been null"; - } - - void clear(){ - int e, temp; - bool ok; - node_t *n1, *n2, *n3, *n4, *n5; - IntList list; - ASSERT_EQ(0, list.size()) << "size should be zero"; - ASSERT_EQ(0, (int)list.head()) << "head should be NULL"; - - { - SCOPED_TRACE("clear empty list"); - list.clear(); - ASSERT_EQ(0, list.size()) << "size should be zero"; - ASSERT_EQ(0, (int)list.head()) << "head should be NULL"; - } - - { - SCOPED_TRACE("clear list with the only node"); - n1 = list.addFront(1); - list.clear(); - ASSERT_EQ(0, list.size()) << "size should be zero"; - ASSERT_EQ(true, list.empty()) << "list should be empty"; - ASSERT_EQ(NULL, (int)list.head()) << "head not NULL"; - - } - - { - // list: 1 - SCOPED_TRACE("clear list with several nodes"); - list.addFront(temp = 2); - list.addFront(temp = 3); - list.addFront(temp = 4); - list.addFront(temp = 5); - list.clear(); - ASSERT_EQ(0, list.size()) << "size should be zero"; - ASSERT_EQ(true, list.empty()) << "list should be empty"; - ASSERT_EQ(NULL, (int)list.head()) << "head not NULL"; - } - - } - - void addBefore(){ - IntList list; - ASSERT_EQ(0, list.size()) << "size should be zero"; - ASSERT_EQ(0, (int)list.head()) << "head should be NULL"; - ASSERT_EQ(list.begin(), list.end()) << "begin != end"; - ASSERT_EQ(list.begin().pNode, list.end().pNode) << "begin.pNode != end.pNode"; - ASSERT_EQ(list.pHorizon, list.end().pNode) << "pHorizon != end.pNode"; - - // add before NULL - node_t* pNode = list.addBefore(5, NULL); // should fail - ASSERT_EQ(NULL, (int) pNode) << "added before NULL"; - - // one-item list - node_t* n0 = list.addFront(0); - ASSERT_EQ(0, n0->element) << "wrong element"; - node_t* n1 = list.addBefore(1, n0); - // list: 1->0 - ASSERT_EQ(n1, list.head()) << "node is not at head"; - ASSERT_EQ(1, list.head()->element) << "wrong element"; - ASSERT_EQ(n0, n1->next()) << "n1->next should be n0"; - ASSERT_EQ(2, list.size()) << "size should be 2"; - - // add more items - const int testSize = 5; - node_t* n[testSize]; - n[0] = n0; - n[1] = n1; - for (int i = 2; i < testSize; i++){ - n[i] = list.addBefore(i, n[i-1]); - } - // list: 4->3->2->1->0 - ASSERT_EQ(5, list.size()) << "size should be 5"; - ASSERT_EQ(n[4], list.head()) << "4 should be at head"; - ASSERT_EQ(n[3], list.head()->next()) << "3 should be 4->next"; - ASSERT_EQ(n[2], list.head()->next()->next()) << "2 should be 3->next"; - ASSERT_EQ(n[1], list.head()->next()->next()->next()) << "1 should be 2->next"; - ASSERT_EQ(n[0], list.head()->next()->next()->next()->next()) << "0 should be 1->next"; - ASSERT_EQ(list.end().pNode, list.head()->next()->next()->next()->next()->next()) << "tail->next should be end()"; - - ASSERT_EQ(4, list.head()->element) << "4 should be at head"; - ASSERT_EQ(3, list.head()->next()->element) << "3 should be 4->next"; - ASSERT_EQ(2, list.head()->next()->next()->element) << "2 should be 3->next"; - ASSERT_EQ(1, list.head()->next()->next()->next()->element) << "1 should be 2->next"; - ASSERT_EQ(0, list.head()->next()->next()->next()->next()->element) << "0 should be 1->next"; - - // add in the middle - node_t* n10 = list.addBefore(10, n[2]); - // list: 4->3->10->2->1->0 - ASSERT_EQ(6, list.size()) << "size should be 6"; - ASSERT_EQ(n[4], list.head()) << "4 should be at head"; - ASSERT_EQ(n[3], list.head()->next()) << "3 should be 4->next"; - ASSERT_EQ(n10, list.head()->next()->next()) << "10 should be 3->next"; - ASSERT_EQ(n[2], list.head()->next()->next()->next()) << "2 should be 10->next"; - ASSERT_EQ(n[1], list.head()->next()->next()->next()->next()) << "1 should be 10->next"; - ASSERT_EQ(n[0], list.head()->next()->next()->next()->next()->next()) << "0 should be 1->next"; - ASSERT_EQ(list.end().pNode, list.head()->next()->next()->next()->next()->next()->next()) << "tail->next should be end()"; - - ASSERT_EQ(4, list.head()->element) << "4 should be at head"; - ASSERT_EQ(3, list.head()->next()->element) << "3 should be 4->next"; - ASSERT_EQ(10, list.head()->next()->next()->element) << "10 should be 3->next"; - ASSERT_EQ(2, list.head()->next()->next()->next()->element) << "2 should be 10->next"; - ASSERT_EQ(1, list.head()->next()->next()->next()->next()->element) << "1 should be 10->next"; - ASSERT_EQ(0, list.head()->next()->next()->next()->next()->next()->element) << "0 should be 1->next"; - - } - void addAfter(){ - IntList list; - ASSERT_EQ(0, list.size()) << "size should be zero"; - ASSERT_EQ(0, (int)list.head()) << "head should be NULL"; - - // add after NULL - node_t* pNode = list.addAfter(5, NULL); // should fail - ASSERT_EQ(NULL, pNode) << "added after NULL"; - - // one-item list - node_t* n0 = list.addFront(0); - ASSERT_EQ(0, n0->element) << "wrong element"; - node_t* n1 = list.addAfter(1, n0); - // list: 0->1 - ASSERT_EQ(n0, list.head()) << "node is not at head"; - ASSERT_EQ(0, list.head()->element) << "wrong element"; - ASSERT_EQ(n1, n0->next()) << "n0->next should be n1"; - ASSERT_EQ(2, list.size()) << "size should be 2"; - - // add more items - const int testSize = 5; - node_t* n[testSize]; - n[0] = n0; - n[1] = n1; - for (int i = 2; i < testSize; i++){ - n[i] = list.addAfter(i, n[i - 1]); - } - // list: 0->1->2->3->4 - ASSERT_EQ(5, list.size()) << "size should be 5"; - ASSERT_EQ(n[0], list.head()) << "0 should be at head"; - ASSERT_EQ(n[1], list.head()->next()) << "1 should be 4->next"; - ASSERT_EQ(n[2], list.head()->next()->next()) << "2 should be 3->next"; - ASSERT_EQ(n[3], list.head()->next()->next()->next()) << "3 should be 2->next"; - ASSERT_EQ(n[4], list.head()->next()->next()->next()->next()) << "4 should be 1->next"; - ASSERT_EQ(list.end().pNode, list.head()->next()->next()->next()->next()->next()) << "tail->next should be end()"; - - ASSERT_EQ(0, list.head()->element) << "0 should be at head"; - ASSERT_EQ(1, list.head()->next()->element) << "1 should be 4->next"; - ASSERT_EQ(2, list.head()->next()->next()->element) << "2 should be 3->next"; - ASSERT_EQ(3, list.head()->next()->next()->next()->element) << "3 should be 2->next"; - ASSERT_EQ(4, list.head()->next()->next()->next()->next()->element) << "4 should be 1->next"; - - { - SCOPED_TRACE("add in the middle"); - node_t* n10 = list.addAfter(10, n[2]); - // list: 0->1->2->10->3->4 - ASSERT_EQ(6, list.size()) << "size should be 6"; - ASSERT_EQ(n[0], list.head()) << "0 should be at head"; - ASSERT_EQ(n[1], list.head()->next()) << "1 should be 0->next"; - ASSERT_EQ(n[2], list.head()->next()->next()) << "2 should be 1->next"; - ASSERT_EQ(n10, list.head()->next()->next()->next()) << "10 should be 2->next"; - ASSERT_EQ(n[3], list.head()->next()->next()->next()->next()) << "3 should be 10->next"; - ASSERT_EQ(n[4], list.head()->next()->next()->next()->next()->next()) << "4 should be 3->next"; - ASSERT_EQ(list.end().pNode, list.head()->next()->next()->next()->next()->next()->next()) << "tail->next should be end()"; - - ASSERT_EQ(0, list.head()->element) << "0 should be at head"; - ASSERT_EQ(1, list.head()->next()->element) << "1 should be 0->next"; - ASSERT_EQ(2, list.head()->next()->next()->element) << "2 should be 2->next"; - ASSERT_EQ(10, list.head()->next()->next()->next()->element) << "10 should be 2->next"; - ASSERT_EQ(3, list.head()->next()->next()->next()->next()->element) << "3 should be 10->next"; - ASSERT_EQ(4, list.head()->next()->next()->next()->next()->next()->element) << "4 should be 3->next"; - } - } - - void addFront(){ - - IntList list; - ASSERT_EQ(0, list.size()) << "size should be zero"; - ASSERT_EQ(0, (int)list.head()) << "head should be NULL"; - ASSERT_EQ(list.begin(), list.end()) << "begin() and end() not same for empty list"; - - //node_t *pNode, *pNext, *pNext2; - - //// add head - //{ - // SCOPED_TRACE("add #1"); - // pNode = list.addFront(4); // new node is at head - // ASSERT_EQ(list.head(), pNode) << "addFront() does not return correct node"; - // ASSERT_NE(0, (int)pNode) << "head is NULL although list has items"; - // ASSERT_EQ(list.end().pNode, pNode->next()) << "head's next should be end()"; - // ASSERT_EQ(1, list.size()) << "size should have been 1"; - // ASSERT_EQ(false, list.empty()) << "non-empty list is showing empty"; - // ASSERT_EQ(4, pNode->element) << "head-element should have been 4"; - // - // // iterators - // ASSERT_EQ(list.head(), list.begin().pNode) << "head() not equal to begin().pNode"; - // ASSERT_NE(list.begin(), list.end()) << "begin() and end() same for non-empty list"; - // ASSERT_EQ(list.end(), ++list.begin()) << "++begin() and end() not same"; - // ASSERT_NE(list.end(), list.begin()++) << "begin()++ and end() same"; - // ASSERT_EQ(list.head(), (list.begin()++).pNode) << "begin()++.pNode not head()"; - // ASSERT_EQ(list.end().pNode, (++list.begin()).pNode) << "begin++.pNode should be end()"; - // ASSERT_EQ(4, *list.begin()) << "begin()-element should have been 4"; - //} - - //// add 2nd element - //{ - // SCOPED_TRACE("add #2"); - // pNext = list.addFront(5); // new node is at head - - // ASSERT_NE(0, (int)list.head()) << "head is NULL although list has items"; - // ASSERT_EQ(list.head(), pNext) << "addFront() does not return correct node"; - - // ASSERT_NE(list.end().pNode, list.head()->next()) << "head->next is end() although list has 2 items"; - // ASSERT_EQ(list.head()->next(), pNode) << "addFront() did not put the new node at head"; - - // ASSERT_EQ(5, list.head()->element) << "head element should have been 5"; - // ASSERT_EQ(list.end().pNode, list.head()->next()->next()) << "head->next->next should be end()"; - // ASSERT_EQ(2, list.size()) << "size should have been 2"; - // ASSERT_EQ(false, list.empty()) << "non-empty list is showing empty"; - - // ASSERT_EQ(5, list.head()->element) << "head-element should have been 5"; - // ASSERT_EQ(4, list.head()->next()->element) << "head->next element should have been 4"; - - // // iterators - // ASSERT_EQ(list.head(), list.begin().pNode) << "head() not equal to begin().pNode"; - // ASSERT_NE(list.begin(), list.end()) << "begin() and end() same for non-empty list"; - // ASSERT_EQ(list.end(), ++ (++(list.begin()))) << "++++begin() not end()"; - // ASSERT_EQ(pNext, (list.begin()++).pNode) << "begin++.pNode should be pNext"; - // ASSERT_EQ(pNode, (++list.begin()).pNode) << "++begin.pNode should be pNode"; - // ASSERT_EQ(5, *(list.begin())) << "begin()-element should have been 5"; - // ASSERT_EQ(4, *(++(list.begin()))) << "begin()-element should have been 4"; - // ASSERT_EQ(5, *(list.begin()++)) << "begin()-element should have been 5"; - //} - - //// add more elements - //{ - // SCOPED_TRACE("add #3"); - // pNext2 = list.addFront(6); // new node is at head - - // ASSERT_EQ(pNext2, list.head()) << "addFront() does not return correct node"; - // ASSERT_EQ(pNext, list.head()->next()) << "addFront() did not put the new node at head"; - // ASSERT_EQ(pNode, list.head()->next()->next()) << "addFront() did not put the new node at head"; - // ASSERT_EQ(list.end().pNode, list.head()->next()->next()->next()) << "last->next should be end()"; - - // ASSERT_NE(0, (int)list.head()) << "head is NULL although list has items"; - // ASSERT_NE(0, (int)list.head()->next()) << "head->next is NULL"; - // ASSERT_NE(0, (int)list.head()->next()->next()) << "head->next->next is NULL"; - - // ASSERT_EQ(6, list.head()->element) << "head element should have been 6"; - // ASSERT_EQ(5, list.head()->next()->element) << "head->next element should have been 5"; - // ASSERT_EQ(4, list.head()->next()->next()->element) << "head->next->next element should have been 4"; - // ASSERT_EQ(3, list.size()) << "size should have been 3"; - // ASSERT_EQ(false, list.empty()) << "non-empty list is showing empty"; - - // // iterators - // ASSERT_EQ(list.head(), list.begin().pNode) << "head() not equal to begin().pNode"; - // ASSERT_NE(list.begin(), list.end()) << "begin() and end() same for non-empty list"; - // ASSERT_EQ(pNext2, (list.begin()).pNode) << "begin.pNode should be pNext2"; - // ASSERT_EQ(pNext2, ((list.begin())++).pNode) << "begin++.pNode should be pNext2"; - // ASSERT_EQ(pNext, (++(list.begin())).pNode) << "++begin.pNode should be pNext"; - // ASSERT_EQ(pNode, (++(++(list.begin()))).pNode) << "++++begin.pNode should be pNode"; - // ASSERT_EQ(list.end(), (++(++( ++list.begin())))) << "++++++begin() not end()"; - // ASSERT_EQ(6, *(list.begin())) << "begin()-element should have been 6"; - // ASSERT_EQ(6, *(list.begin()++)) << "begin()++-element should have been 6"; - // ASSERT_EQ(5, *(++(list.begin()))) << "++begin()-element should have been 5"; - // ASSERT_EQ(4, *(++(++(list.begin())))) << "++++begin()-element should have been 4"; - //} - - - } - - void remove(){ - int e; - bool ok; - node_t *n1, *n2, *n3, *n4, *n5; - IntList list; - ASSERT_EQ(0, list.size()) << "size should be zero"; - ASSERT_EQ(0, (int)list.head()) << "head should be NULL"; - - { - SCOPED_TRACE("removing from empty list"); - ok = list.remove(list.head(), e); // should fail - ASSERT_EQ(false, ok) << "remove() succeeded on empty list"; - } - - { - SCOPED_TRACE("removing the only node"); - n1 = list.addFront(1); - ok = list.remove(n1, e); - ASSERT_EQ(true, ok) << "remove failed"; - ASSERT_EQ(1, e) << "wrong element in removed node"; - ASSERT_EQ(0, list.size()) << "size should be zero"; - ASSERT_EQ(true, list.empty()) << "list should be empty"; - - // reinsert a node - list.addFront(1); - ASSERT_EQ(1, list.size()) << "size should be 1"; - ASSERT_EQ(false, list.empty()) << "list should be non-empty"; - } - - { - // list: 1 - SCOPED_TRACE("remove the first node of a size-2 list"); - n1 = list.addFront(2); // list: 2->1 - ok = list.remove(n1, e); // list: 1 - ASSERT_EQ(true, ok) << "remove failed"; - ASSERT_EQ(2, e) << "wrong element in removed node"; - ASSERT_EQ(1, list.size()) << "size should be zero"; - ASSERT_EQ(false, list.empty()) << "list should be empty"; - ASSERT_EQ(1, list.head()->element) << "head-element should be 1"; - ASSERT_EQ(list.end().pNode, list.head()->next()) << "head-next should be end()"; - } - - { - // list: 1 - SCOPED_TRACE("remove the second node of a size-2 list"); - n1 = list.addFront(2); // list: 2->1 - ok = list.remove(n1, e); // list: 1 - ASSERT_EQ(true, ok) << "remove failed"; - ASSERT_EQ(2, e) << "wrong element in removed node"; - ASSERT_EQ(1, list.size()) << "size should be zero"; - ASSERT_EQ(false, list.empty()) << "list should be empty"; - ASSERT_EQ(1, list.head()->element) << "head-element should be 1"; - } - - { - // list: 1 - SCOPED_TRACE("remove the last node of a size-3 list"); - n1 = list.head(); // list: 1 - n2 = list.addFront(2); // list: 2->1 - n3 = list.addFront(3); // list: 3->2->1 - - ok = list.remove(n1, e); // remove 1; list: 3->2 - ASSERT_EQ(true, ok) << "remove failed"; - ASSERT_EQ(1, e) << "wrong element in removed node"; - ASSERT_EQ(2, list.size()) << "size should be 2"; - ASSERT_EQ(false, list.empty()) << "list should not be empty"; - - ASSERT_EQ(n3, list.head()) << "wrong pointer at list head"; - ASSERT_EQ(n2, list.head()->next()) << "wrong pointer at list head->next"; - ASSERT_EQ(3, list.head()->element) << "head-element should be 1"; - ASSERT_EQ(2, list.head()->next()->element) << "head-element should be 2"; - - } - - { - // list: 3->2 - SCOPED_TRACE("remove a middle node"); - n3 = list.head(); // list: 3->2 - n2 = n3->next(); // - n4 = list.addFront(4); // list: 4->3->2 - n5 = list.addFront(5); // list: 5->4->3->2 - - - // try to remove 4 - ok = list.remove(n4, e); // remove 4; list: 5->3->2 - ASSERT_EQ(true, ok) << "remove failed"; - ASSERT_EQ(4, e) << "removed element should be 4"; - ASSERT_EQ(3, list.size()) << "size should be 3"; - ASSERT_EQ(false, list.empty()) << "list should not be empty"; - - ASSERT_EQ(n5, list.head()) << "wrong pointer at list head"; - ASSERT_EQ(n3, list.head()->next()) << "wrong pointer at list head->next"; - ASSERT_EQ(n2, list.head()->next()->next()) << "wrong pointer at list head->next->next"; - ASSERT_EQ(list.end().pNode, n2->next()) << "last->next should be end()"; - ASSERT_EQ(5, list.head()->element) << "head-element should be 5"; - ASSERT_EQ(3, list.head()->next()->element) << "head-element should be 3"; - ASSERT_EQ(2, list.head()->next()->next()->element) << "head-element should be 2"; - - // now try to remove 3 - // list: 5->3->2 - ok = list.remove(n3, e); // remove 3; list: 5->2 - ASSERT_EQ(true, ok) << "remove failed"; - ASSERT_EQ(3, e) << "removed element should be 3"; - ASSERT_EQ(2, list.size()) << "size should be 2"; - ASSERT_EQ(false, list.empty()) << "list should not be empty"; - - ASSERT_EQ(n5, list.head()) << "wrong pointer at list head"; - ASSERT_EQ(n2, list.head()->next()) << "wrong pointer at list head->next"; - ASSERT_EQ(list.end().pNode, list.head()->next()->next()) << "last->next should be end()"; - ASSERT_EQ(5, list.head()->element) << "head-element should be 5"; - ASSERT_EQ(2, list.head()->next()->element) << "head-next element should be 2"; - } - } - - void fromArray(){ - IntList list; - int srcArr[] = { 10, 20, 30, 40 }; - int n = ARR_LENGTH(srcArr); - - list.fromArray(srcArr, n); // build list - ASSERT_NE(0, (int)list.head()) << "head is NULL"; - ASSERT_EQ(4, (int)list.size()) << "size is not 4"; - int j = n - 1; - - for (IntIterator it = list.begin(); it != list.end(); it++ ){ - ASSERT_EQ(srcArr[j], *it) << "element mismatch at item " << n - j - 1 << " in list"; - j--; - } - } - - void elements(){ - IntList list; - int srcArr[] = {10, 20, 30, 40}; - int n = ARR_LENGTH(srcArr); - - list.fromArray(srcArr, n); // build list - //ASSERT_NE(0, (int)list.head()) << "list head is NULL"; - ASSERT_EQ(n, list.size()) << "list size should have been " << n; - // since the elements are given in reverse order - int* pRev = new int[n]; - arrrev(srcArr, n, &pRev); - ASSERT_NE(0, (int)pRev) << "array reverse failed"; - { - SCOPED_TRACE("elements"); - checkListElements(&list, pRev, n); - } - DELETE_ARR_SAFE(pRev); - } - - void relements(){ - IntList list; - int srcArr[] = { 10, 20, 30, 40 }; - const int n = ARR_LENGTH(srcArr); - - list.fromArray(srcArr, n); // build list - ASSERT_EQ(n, list.size()) << "list size should have been " << n; - - int* pRelems = new int[n]; - list.relements( &pRelems); - // pRelems should be in the same order as srcArr - ASSERT_EQ(true, arrcmp(srcArr, pRelems, n)) << "arrays are not the same" << endl - << "actual: " << arrToString(pRelems, n) << endl - << "expected: " << arrToString(srcArr, n); - DELETE_ARR_SAFE(pRelems); - } - - void toString(){ - int srcArr[] = { 1, 2, 3, 4 }; - const string expected = "4->3->2->1->"; - IntList list(srcArr, ARR_LENGTH(srcArr)); - string actual = list.toString(); - ASSERT_EQ(expected, actual) << "toString() is wrong"; - } - - void before(){ - node_t *n1, *n2, *n3, *n4; - IntList list; - ASSERT_EQ(0, list.size()) << "size should be zero"; - ASSERT_EQ(0, (int)list.head()) << "head should be NULL"; - - // test empty list - n1 = list.before(list.head()); // should be NULL - ASSERT_EQ(NULL, n1) << "n1 should be NULL"; - - // test within list - n1 = list.addFront(1); - n2 = list.addFront(2); - n3 = list.addFront(3); - n4 = list.addFront(4); // list: 4->3->2->1 - - ASSERT_EQ(list.end().pNode, list.before(n4)) << "before(4) not end()"; - ASSERT_EQ(n4, list.before(n3)) << "before(3) not 4"; - ASSERT_EQ(n3, list.before(n2)) << "before(2) not 3"; - ASSERT_EQ(n2, list.before(n1)) << "before(1) not 2"; - - } - -}; - - -ADD_TEST_F(SinglyLinkedListTest, addFront); -ADD_TEST_F(SinglyLinkedListTest, addBefore); -ADD_TEST_F(SinglyLinkedListTest, addAfter); -ADD_TEST_F(SinglyLinkedListTest, before); -ADD_TEST_F(SinglyLinkedListTest, remove); -ADD_TEST_F(SinglyLinkedListTest, head); -ADD_TEST_F(SinglyLinkedListTest, fromArray); -ADD_TEST_F(SinglyLinkedListTest, elements); -ADD_TEST_F(SinglyLinkedListTest, relements); -ADD_TEST_F(SinglyLinkedListTest, toString); -ADD_TEST_F(SinglyLinkedListTest, clear); - } // namespace ds } // namespace yasi \ No newline at end of file diff --git a/YASI_12/ds.singlylinkedlist.test.h b/YASI_12/ds.singlylinkedlist.test.h new file mode 100644 index 0000000..9981790 --- /dev/null +++ b/YASI_12/ds.singlylinkedlist.test.h @@ -0,0 +1,534 @@ +#pragma once +#include "common.h" + +#if YASI_TEST_THIS_MODULE != 1 +#define YASI_TEST_THIS_MODULE 1 +#endif + +#include "ds.singlylinkedlist.h" +using namespace std; + +namespace yasi{ + namespace ds{ + class SinglyLinkedListTest : public yasi::Test{ + typedef SinglyLinkedList >::node_t node_t; + typedef SinglyLinkedList > IntList; + typedef IntList::iterator IntIterator; + + + + public: + template + void checkListElements(SinglyLinkedList >* pList, const E* srcArr, const int n){ + E* pElems = new int[n]; + int numElems; + SinglyLinkedList >& list = *pList; + list.elements(&pElems); + ASSERT_EQ(true, arrcmp(srcArr, pElems, n)) << "arrays are not the same" << endl + << "actual: " << arrToString(srcArr, n) << endl + << "expected: " << arrToString(pElems, n); + DELETE_ARR_SAFE(pElems); + } + + + void head(){ + int e; + //IntList list = * static_cast(createList()); + IntList list; + node_t* pNode = list.head(); + ASSERT_EQ(0, (int)pNode) << "head must be null at the beginning"; + + list.addFront(4); + pNode = list.head(); + ASSERT_NE(0, (int)pNode) << "head is NULL although list has items"; + ASSERT_EQ(list.end().pNode, pNode->next()) << "head's next should be end()"; + ASSERT_EQ(1, list.size()) << "size should have been 1"; + ASSERT_EQ(false, list.empty()) << "non-empty list is showing empty"; + ASSERT_EQ(4, pNode->element) << "head-element should have been 4"; + + list.remove(pNode, e); + pNode = list.head(); + ASSERT_EQ(0, (int)pNode) << "head should have been null"; + } + + void clear(){ + int e, temp; + bool ok; + node_t *n1, *n2, *n3, *n4, *n5; + IntList list; + ASSERT_EQ(0, list.size()) << "size should be zero"; + ASSERT_EQ(0, (int)list.head()) << "head should be NULL"; + + { + SCOPED_TRACE("clear empty list"); + list.clear(); + ASSERT_EQ(0, list.size()) << "size should be zero"; + ASSERT_EQ(0, (int)list.head()) << "head should be NULL"; + } + + { + SCOPED_TRACE("clear list with the only node"); + n1 = list.addFront(1); + list.clear(); + ASSERT_EQ(0, list.size()) << "size should be zero"; + ASSERT_EQ(true, list.empty()) << "list should be empty"; + ASSERT_EQ(NULL, (int)list.head()) << "head not NULL"; + + } + + { + // list: 1 + SCOPED_TRACE("clear list with several nodes"); + list.addFront(temp = 2); + list.addFront(temp = 3); + list.addFront(temp = 4); + list.addFront(temp = 5); + list.clear(); + ASSERT_EQ(0, list.size()) << "size should be zero"; + ASSERT_EQ(true, list.empty()) << "list should be empty"; + ASSERT_EQ(NULL, (int)list.head()) << "head not NULL"; + } + + } + + void addBefore(){ + IntList list; + ASSERT_EQ(0, list.size()) << "size should be zero"; + ASSERT_EQ(0, (int)list.head()) << "head should be NULL"; + ASSERT_EQ(list.begin(), list.end()) << "begin != end"; + ASSERT_EQ(list.begin().pNode, list.end().pNode) << "begin.pNode != end.pNode"; + ASSERT_EQ(list.pHorizon, list.end().pNode) << "pHorizon != end.pNode"; + + // add before NULL + node_t* pNode = list.addBefore(5, NULL); // should fail + ASSERT_EQ(NULL, (int)pNode) << "added before NULL"; + + // one-item list + node_t* n0 = list.addFront(0); + ASSERT_EQ(0, n0->element) << "wrong element"; + node_t* n1 = list.addBefore(1, n0); + // list: 1->0 + ASSERT_EQ(n1, list.head()) << "node is not at head"; + ASSERT_EQ(1, list.head()->element) << "wrong element"; + ASSERT_EQ(n0, n1->next()) << "n1->next should be n0"; + ASSERT_EQ(2, list.size()) << "size should be 2"; + + // add more items + const int testSize = 5; + node_t* n[testSize]; + n[0] = n0; + n[1] = n1; + for (int i = 2; i < testSize; i++){ + n[i] = list.addBefore(i, n[i - 1]); + } + // list: 4->3->2->1->0 + ASSERT_EQ(5, list.size()) << "size should be 5"; + ASSERT_EQ(n[4], list.head()) << "4 should be at head"; + ASSERT_EQ(n[3], list.head()->next()) << "3 should be 4->next"; + ASSERT_EQ(n[2], list.head()->next()->next()) << "2 should be 3->next"; + ASSERT_EQ(n[1], list.head()->next()->next()->next()) << "1 should be 2->next"; + ASSERT_EQ(n[0], list.head()->next()->next()->next()->next()) << "0 should be 1->next"; + ASSERT_EQ(list.end().pNode, list.head()->next()->next()->next()->next()->next()) << "tail->next should be end()"; + + ASSERT_EQ(4, list.head()->element) << "4 should be at head"; + ASSERT_EQ(3, list.head()->next()->element) << "3 should be 4->next"; + ASSERT_EQ(2, list.head()->next()->next()->element) << "2 should be 3->next"; + ASSERT_EQ(1, list.head()->next()->next()->next()->element) << "1 should be 2->next"; + ASSERT_EQ(0, list.head()->next()->next()->next()->next()->element) << "0 should be 1->next"; + + // add in the middle + node_t* n10 = list.addBefore(10, n[2]); + // list: 4->3->10->2->1->0 + ASSERT_EQ(6, list.size()) << "size should be 6"; + ASSERT_EQ(n[4], list.head()) << "4 should be at head"; + ASSERT_EQ(n[3], list.head()->next()) << "3 should be 4->next"; + ASSERT_EQ(n10, list.head()->next()->next()) << "10 should be 3->next"; + ASSERT_EQ(n[2], list.head()->next()->next()->next()) << "2 should be 10->next"; + ASSERT_EQ(n[1], list.head()->next()->next()->next()->next()) << "1 should be 10->next"; + ASSERT_EQ(n[0], list.head()->next()->next()->next()->next()->next()) << "0 should be 1->next"; + ASSERT_EQ(list.end().pNode, list.head()->next()->next()->next()->next()->next()->next()) << "tail->next should be end()"; + + ASSERT_EQ(4, list.head()->element) << "4 should be at head"; + ASSERT_EQ(3, list.head()->next()->element) << "3 should be 4->next"; + ASSERT_EQ(10, list.head()->next()->next()->element) << "10 should be 3->next"; + ASSERT_EQ(2, list.head()->next()->next()->next()->element) << "2 should be 10->next"; + ASSERT_EQ(1, list.head()->next()->next()->next()->next()->element) << "1 should be 10->next"; + ASSERT_EQ(0, list.head()->next()->next()->next()->next()->next()->element) << "0 should be 1->next"; + + } + void addAfter(){ + IntList list; + ASSERT_EQ(0, list.size()) << "size should be zero"; + ASSERT_EQ(0, (int)list.head()) << "head should be NULL"; + + // add after NULL + node_t* pNode = list.addAfter(5, NULL); // should fail + ASSERT_EQ(NULL, pNode) << "added after NULL"; + + // one-item list + node_t* n0 = list.addFront(0); + ASSERT_EQ(0, n0->element) << "wrong element"; + node_t* n1 = list.addAfter(1, n0); + // list: 0->1 + ASSERT_EQ(n0, list.head()) << "node is not at head"; + ASSERT_EQ(0, list.head()->element) << "wrong element"; + ASSERT_EQ(n1, n0->next()) << "n0->next should be n1"; + ASSERT_EQ(2, list.size()) << "size should be 2"; + + // add more items + const int testSize = 5; + node_t* n[testSize]; + n[0] = n0; + n[1] = n1; + for (int i = 2; i < testSize; i++){ + n[i] = list.addAfter(i, n[i - 1]); + } + // list: 0->1->2->3->4 + ASSERT_EQ(5, list.size()) << "size should be 5"; + ASSERT_EQ(n[0], list.head()) << "0 should be at head"; + ASSERT_EQ(n[1], list.head()->next()) << "1 should be 4->next"; + ASSERT_EQ(n[2], list.head()->next()->next()) << "2 should be 3->next"; + ASSERT_EQ(n[3], list.head()->next()->next()->next()) << "3 should be 2->next"; + ASSERT_EQ(n[4], list.head()->next()->next()->next()->next()) << "4 should be 1->next"; + ASSERT_EQ(list.end().pNode, list.head()->next()->next()->next()->next()->next()) << "tail->next should be end()"; + + ASSERT_EQ(0, list.head()->element) << "0 should be at head"; + ASSERT_EQ(1, list.head()->next()->element) << "1 should be 4->next"; + ASSERT_EQ(2, list.head()->next()->next()->element) << "2 should be 3->next"; + ASSERT_EQ(3, list.head()->next()->next()->next()->element) << "3 should be 2->next"; + ASSERT_EQ(4, list.head()->next()->next()->next()->next()->element) << "4 should be 1->next"; + + { + SCOPED_TRACE("add in the middle"); + node_t* n10 = list.addAfter(10, n[2]); + // list: 0->1->2->10->3->4 + ASSERT_EQ(6, list.size()) << "size should be 6"; + ASSERT_EQ(n[0], list.head()) << "0 should be at head"; + ASSERT_EQ(n[1], list.head()->next()) << "1 should be 0->next"; + ASSERT_EQ(n[2], list.head()->next()->next()) << "2 should be 1->next"; + ASSERT_EQ(n10, list.head()->next()->next()->next()) << "10 should be 2->next"; + ASSERT_EQ(n[3], list.head()->next()->next()->next()->next()) << "3 should be 10->next"; + ASSERT_EQ(n[4], list.head()->next()->next()->next()->next()->next()) << "4 should be 3->next"; + ASSERT_EQ(list.end().pNode, list.head()->next()->next()->next()->next()->next()->next()) << "tail->next should be end()"; + + ASSERT_EQ(0, list.head()->element) << "0 should be at head"; + ASSERT_EQ(1, list.head()->next()->element) << "1 should be 0->next"; + ASSERT_EQ(2, list.head()->next()->next()->element) << "2 should be 2->next"; + ASSERT_EQ(10, list.head()->next()->next()->next()->element) << "10 should be 2->next"; + ASSERT_EQ(3, list.head()->next()->next()->next()->next()->element) << "3 should be 10->next"; + ASSERT_EQ(4, list.head()->next()->next()->next()->next()->next()->element) << "4 should be 3->next"; + } + } + + void addFront(){ + + IntList list; + ASSERT_EQ(0, list.size()) << "size should be zero"; + ASSERT_EQ(0, (int)list.head()) << "head should be NULL"; + ASSERT_EQ(list.begin(), list.end()) << "begin() and end() not same for empty list"; + + //node_t *pNode, *pNext, *pNext2; + + //// add head + //{ + // SCOPED_TRACE("add #1"); + // pNode = list.addFront(4); // new node is at head + // ASSERT_EQ(list.head(), pNode) << "addFront() does not return correct node"; + // ASSERT_NE(0, (int)pNode) << "head is NULL although list has items"; + // ASSERT_EQ(list.end().pNode, pNode->next()) << "head's next should be end()"; + // ASSERT_EQ(1, list.size()) << "size should have been 1"; + // ASSERT_EQ(false, list.empty()) << "non-empty list is showing empty"; + // ASSERT_EQ(4, pNode->element) << "head-element should have been 4"; + // + // // iterators + // ASSERT_EQ(list.head(), list.begin().pNode) << "head() not equal to begin().pNode"; + // ASSERT_NE(list.begin(), list.end()) << "begin() and end() same for non-empty list"; + // ASSERT_EQ(list.end(), ++list.begin()) << "++begin() and end() not same"; + // ASSERT_NE(list.end(), list.begin()++) << "begin()++ and end() same"; + // ASSERT_EQ(list.head(), (list.begin()++).pNode) << "begin()++.pNode not head()"; + // ASSERT_EQ(list.end().pNode, (++list.begin()).pNode) << "begin++.pNode should be end()"; + // ASSERT_EQ(4, *list.begin()) << "begin()-element should have been 4"; + //} + + //// add 2nd element + //{ + // SCOPED_TRACE("add #2"); + // pNext = list.addFront(5); // new node is at head + + // ASSERT_NE(0, (int)list.head()) << "head is NULL although list has items"; + // ASSERT_EQ(list.head(), pNext) << "addFront() does not return correct node"; + + // ASSERT_NE(list.end().pNode, list.head()->next()) << "head->next is end() although list has 2 items"; + // ASSERT_EQ(list.head()->next(), pNode) << "addFront() did not put the new node at head"; + + // ASSERT_EQ(5, list.head()->element) << "head element should have been 5"; + // ASSERT_EQ(list.end().pNode, list.head()->next()->next()) << "head->next->next should be end()"; + // ASSERT_EQ(2, list.size()) << "size should have been 2"; + // ASSERT_EQ(false, list.empty()) << "non-empty list is showing empty"; + + // ASSERT_EQ(5, list.head()->element) << "head-element should have been 5"; + // ASSERT_EQ(4, list.head()->next()->element) << "head->next element should have been 4"; + + // // iterators + // ASSERT_EQ(list.head(), list.begin().pNode) << "head() not equal to begin().pNode"; + // ASSERT_NE(list.begin(), list.end()) << "begin() and end() same for non-empty list"; + // ASSERT_EQ(list.end(), ++ (++(list.begin()))) << "++++begin() not end()"; + // ASSERT_EQ(pNext, (list.begin()++).pNode) << "begin++.pNode should be pNext"; + // ASSERT_EQ(pNode, (++list.begin()).pNode) << "++begin.pNode should be pNode"; + // ASSERT_EQ(5, *(list.begin())) << "begin()-element should have been 5"; + // ASSERT_EQ(4, *(++(list.begin()))) << "begin()-element should have been 4"; + // ASSERT_EQ(5, *(list.begin()++)) << "begin()-element should have been 5"; + //} + + //// add more elements + //{ + // SCOPED_TRACE("add #3"); + // pNext2 = list.addFront(6); // new node is at head + + // ASSERT_EQ(pNext2, list.head()) << "addFront() does not return correct node"; + // ASSERT_EQ(pNext, list.head()->next()) << "addFront() did not put the new node at head"; + // ASSERT_EQ(pNode, list.head()->next()->next()) << "addFront() did not put the new node at head"; + // ASSERT_EQ(list.end().pNode, list.head()->next()->next()->next()) << "last->next should be end()"; + + // ASSERT_NE(0, (int)list.head()) << "head is NULL although list has items"; + // ASSERT_NE(0, (int)list.head()->next()) << "head->next is NULL"; + // ASSERT_NE(0, (int)list.head()->next()->next()) << "head->next->next is NULL"; + + // ASSERT_EQ(6, list.head()->element) << "head element should have been 6"; + // ASSERT_EQ(5, list.head()->next()->element) << "head->next element should have been 5"; + // ASSERT_EQ(4, list.head()->next()->next()->element) << "head->next->next element should have been 4"; + // ASSERT_EQ(3, list.size()) << "size should have been 3"; + // ASSERT_EQ(false, list.empty()) << "non-empty list is showing empty"; + + // // iterators + // ASSERT_EQ(list.head(), list.begin().pNode) << "head() not equal to begin().pNode"; + // ASSERT_NE(list.begin(), list.end()) << "begin() and end() same for non-empty list"; + // ASSERT_EQ(pNext2, (list.begin()).pNode) << "begin.pNode should be pNext2"; + // ASSERT_EQ(pNext2, ((list.begin())++).pNode) << "begin++.pNode should be pNext2"; + // ASSERT_EQ(pNext, (++(list.begin())).pNode) << "++begin.pNode should be pNext"; + // ASSERT_EQ(pNode, (++(++(list.begin()))).pNode) << "++++begin.pNode should be pNode"; + // ASSERT_EQ(list.end(), (++(++( ++list.begin())))) << "++++++begin() not end()"; + // ASSERT_EQ(6, *(list.begin())) << "begin()-element should have been 6"; + // ASSERT_EQ(6, *(list.begin()++)) << "begin()++-element should have been 6"; + // ASSERT_EQ(5, *(++(list.begin()))) << "++begin()-element should have been 5"; + // ASSERT_EQ(4, *(++(++(list.begin())))) << "++++begin()-element should have been 4"; + //} + + + } + + void remove(){ + int e; + bool ok; + node_t *n1, *n2, *n3, *n4, *n5; + IntList list; + ASSERT_EQ(0, list.size()) << "size should be zero"; + ASSERT_EQ(0, (int)list.head()) << "head should be NULL"; + + { + SCOPED_TRACE("removing from empty list"); + ok = list.remove(list.head(), e); // should fail + ASSERT_EQ(false, ok) << "remove() succeeded on empty list"; + } + + { + SCOPED_TRACE("removing the only node"); + n1 = list.addFront(1); + ok = list.remove(n1, e); + ASSERT_EQ(true, ok) << "remove failed"; + ASSERT_EQ(1, e) << "wrong element in removed node"; + ASSERT_EQ(0, list.size()) << "size should be zero"; + ASSERT_EQ(true, list.empty()) << "list should be empty"; + + // reinsert a node + list.addFront(1); + ASSERT_EQ(1, list.size()) << "size should be 1"; + ASSERT_EQ(false, list.empty()) << "list should be non-empty"; + } + + { + // list: 1 + SCOPED_TRACE("remove the first node of a size-2 list"); + n1 = list.addFront(2); // list: 2->1 + ok = list.remove(n1, e); // list: 1 + ASSERT_EQ(true, ok) << "remove failed"; + ASSERT_EQ(2, e) << "wrong element in removed node"; + ASSERT_EQ(1, list.size()) << "size should be zero"; + ASSERT_EQ(false, list.empty()) << "list should be empty"; + ASSERT_EQ(1, list.head()->element) << "head-element should be 1"; + ASSERT_EQ(list.end().pNode, list.head()->next()) << "head-next should be end()"; + } + + { + // list: 1 + SCOPED_TRACE("remove the second node of a size-2 list"); + n1 = list.addFront(2); // list: 2->1 + ok = list.remove(n1, e); // list: 1 + ASSERT_EQ(true, ok) << "remove failed"; + ASSERT_EQ(2, e) << "wrong element in removed node"; + ASSERT_EQ(1, list.size()) << "size should be zero"; + ASSERT_EQ(false, list.empty()) << "list should be empty"; + ASSERT_EQ(1, list.head()->element) << "head-element should be 1"; + } + + { + // list: 1 + SCOPED_TRACE("remove the last node of a size-3 list"); + n1 = list.head(); // list: 1 + n2 = list.addFront(2); // list: 2->1 + n3 = list.addFront(3); // list: 3->2->1 + + ok = list.remove(n1, e); // remove 1; list: 3->2 + ASSERT_EQ(true, ok) << "remove failed"; + ASSERT_EQ(1, e) << "wrong element in removed node"; + ASSERT_EQ(2, list.size()) << "size should be 2"; + ASSERT_EQ(false, list.empty()) << "list should not be empty"; + + ASSERT_EQ(n3, list.head()) << "wrong pointer at list head"; + ASSERT_EQ(n2, list.head()->next()) << "wrong pointer at list head->next"; + ASSERT_EQ(3, list.head()->element) << "head-element should be 1"; + ASSERT_EQ(2, list.head()->next()->element) << "head-element should be 2"; + + } + + { + // list: 3->2 + SCOPED_TRACE("remove a middle node"); + n3 = list.head(); // list: 3->2 + n2 = n3->next(); // + n4 = list.addFront(4); // list: 4->3->2 + n5 = list.addFront(5); // list: 5->4->3->2 + + + // try to remove 4 + ok = list.remove(n4, e); // remove 4; list: 5->3->2 + ASSERT_EQ(true, ok) << "remove failed"; + ASSERT_EQ(4, e) << "removed element should be 4"; + ASSERT_EQ(3, list.size()) << "size should be 3"; + ASSERT_EQ(false, list.empty()) << "list should not be empty"; + + ASSERT_EQ(n5, list.head()) << "wrong pointer at list head"; + ASSERT_EQ(n3, list.head()->next()) << "wrong pointer at list head->next"; + ASSERT_EQ(n2, list.head()->next()->next()) << "wrong pointer at list head->next->next"; + ASSERT_EQ(list.end().pNode, n2->next()) << "last->next should be end()"; + ASSERT_EQ(5, list.head()->element) << "head-element should be 5"; + ASSERT_EQ(3, list.head()->next()->element) << "head-element should be 3"; + ASSERT_EQ(2, list.head()->next()->next()->element) << "head-element should be 2"; + + // now try to remove 3 + // list: 5->3->2 + ok = list.remove(n3, e); // remove 3; list: 5->2 + ASSERT_EQ(true, ok) << "remove failed"; + ASSERT_EQ(3, e) << "removed element should be 3"; + ASSERT_EQ(2, list.size()) << "size should be 2"; + ASSERT_EQ(false, list.empty()) << "list should not be empty"; + + ASSERT_EQ(n5, list.head()) << "wrong pointer at list head"; + ASSERT_EQ(n2, list.head()->next()) << "wrong pointer at list head->next"; + ASSERT_EQ(list.end().pNode, list.head()->next()->next()) << "last->next should be end()"; + ASSERT_EQ(5, list.head()->element) << "head-element should be 5"; + ASSERT_EQ(2, list.head()->next()->element) << "head-next element should be 2"; + } + } + + void fromArray(){ + IntList list; + int srcArr[] = { 10, 20, 30, 40 }; + int n = ARR_LENGTH(srcArr); + + list.fromArray(srcArr, n); // build list + ASSERT_NE(0, (int)list.head()) << "head is NULL"; + ASSERT_EQ(4, (int)list.size()) << "size is not 4"; + int j = n - 1; + + for (IntIterator it = list.begin(); it != list.end(); it++){ + ASSERT_EQ(srcArr[j], *it) << "element mismatch at item " << n - j - 1 << " in list"; + j--; + } + } + + void elements(){ + IntList list; + int srcArr[] = { 10, 20, 30, 40 }; + int n = ARR_LENGTH(srcArr); + + list.fromArray(srcArr, n); // build list + //ASSERT_NE(0, (int)list.head()) << "list head is NULL"; + ASSERT_EQ(n, list.size()) << "list size should have been " << n; + // since the elements are given in reverse order + int* pRev = new int[n]; + arrrev(srcArr, n, &pRev); + ASSERT_NE(0, (int)pRev) << "array reverse failed"; + { + SCOPED_TRACE("elements"); + checkListElements(&list, pRev, n); + } + DELETE_ARR_SAFE(pRev); + } + + void relements(){ + IntList list; + int srcArr[] = { 10, 20, 30, 40 }; + const int n = ARR_LENGTH(srcArr); + + list.fromArray(srcArr, n); // build list + ASSERT_EQ(n, list.size()) << "list size should have been " << n; + + int* pRelems = new int[n]; + list.relements(&pRelems); + // pRelems should be in the same order as srcArr + ASSERT_EQ(true, arrcmp(srcArr, pRelems, n)) << "arrays are not the same" << endl + << "actual: " << arrToString(pRelems, n) << endl + << "expected: " << arrToString(srcArr, n); + DELETE_ARR_SAFE(pRelems); + } + + void toString(){ + int srcArr[] = { 1, 2, 3, 4 }; + const string expected = "4->3->2->1->"; + IntList list(srcArr, ARR_LENGTH(srcArr)); + string actual = list.toString(); + ASSERT_EQ(expected, actual) << "toString() is wrong"; + } + + void before(){ + node_t *n1, *n2, *n3, *n4; + IntList list; + ASSERT_EQ(0, list.size()) << "size should be zero"; + ASSERT_EQ(0, (int)list.head()) << "head should be NULL"; + + // test empty list + n1 = list.before(list.head()); // should be NULL + ASSERT_EQ(NULL, n1) << "n1 should be NULL"; + + // test within list + n1 = list.addFront(1); + n2 = list.addFront(2); + n3 = list.addFront(3); + n4 = list.addFront(4); // list: 4->3->2->1 + + ASSERT_EQ(list.end().pNode, list.before(n4)) << "before(4) not end()"; + ASSERT_EQ(n4, list.before(n3)) << "before(3) not 4"; + ASSERT_EQ(n3, list.before(n2)) << "before(2) not 3"; + ASSERT_EQ(n2, list.before(n1)) << "before(1) not 2"; + + } + + }; + + + ADD_TEST_F(SinglyLinkedListTest, addFront); + ADD_TEST_F(SinglyLinkedListTest, addBefore); + ADD_TEST_F(SinglyLinkedListTest, addAfter); + ADD_TEST_F(SinglyLinkedListTest, before); + ADD_TEST_F(SinglyLinkedListTest, remove); + ADD_TEST_F(SinglyLinkedListTest, head); + ADD_TEST_F(SinglyLinkedListTest, fromArray); + ADD_TEST_F(SinglyLinkedListTest, elements); + ADD_TEST_F(SinglyLinkedListTest, relements); + ADD_TEST_F(SinglyLinkedListTest, toString); + ADD_TEST_F(SinglyLinkedListTest, clear); + + + } +} \ No newline at end of file diff --git a/YASI_12/main.cpp b/YASI_12/main.cpp index 86828c6..14941fc 100644 --- a/YASI_12/main.cpp +++ b/YASI_12/main.cpp @@ -27,9 +27,10 @@ using namespace yasi; using namespace std; /*------------- Testing ---------------*/ -#define YASI_TEST_THIS_MODULE 1 #include "utils.test.h" #include "ds.iterator.test.h" +#include "ds.singlylinkedlist.test.h" +#include "ds.doublylinkedlist.test.h" int testAll(int* argc, char** argv){ diff --git a/YASI_12/utils.test.h b/YASI_12/utils.test.h index 405290e..1168ecb 100644 --- a/YASI_12/utils.test.h +++ b/YASI_12/utils.test.h @@ -1,5 +1,8 @@ #pragma once -#include "common.h" + +#if YASI_TEST_THIS_MODULE != 1 +#define YASI_TEST_THIS_MODULE 1 +#endif #include "utils.h" ////////////////////////////////