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"
////////////////////////////////