mirror of https://github.com/coolaj86/fizzbuzz
AJ ONeal
14 years ago
20 changed files with 5410 additions and 0 deletions
@ -0,0 +1,256 @@ |
|||
#include "BST.h" |
|||
|
|||
//! BSTNode implements a binary search tree node
|
|||
|
|||
//! Constructor
|
|||
BSTNode::BSTNode(const std::string & v) : |
|||
value(v), left(NULL), right(NULL) |
|||
{ |
|||
// Sounds good to me
|
|||
return; |
|||
} |
|||
|
|||
//! Copy Constructor DEEP COPY and does not free memory
|
|||
BSTNode::BSTNode(const BSTNode & other): |
|||
value(other.value), left(NULL), right(NULL) |
|||
{ |
|||
// Recurse me! Yay!
|
|||
value = other.value; |
|||
if (other.left) |
|||
left = new BSTNode(*(other.left)); |
|||
if (other.right) |
|||
right = new BSTNode(*(other.right)); |
|||
return; |
|||
} |
|||
|
|||
//! Delete Destructor frees memory
|
|||
BSTNode::~BSTNode() |
|||
{ |
|||
Clear(); |
|||
return; |
|||
} |
|||
|
|||
void BSTNode::Clear() |
|||
{ |
|||
if (left) { |
|||
delete left; |
|||
left = NULL; |
|||
} |
|||
if (right) { |
|||
delete right; |
|||
right = NULL; |
|||
} |
|||
return; |
|||
} |
|||
|
|||
void BSTNode::Copy(const BSTNode & other) |
|||
{ |
|||
// Recurse me! Yay!
|
|||
value = other.value; |
|||
if (other.left) |
|||
left = new BSTNode(*(other.left)); |
|||
if (other.right) |
|||
right = new BSTNode(*(other.right)); |
|||
return; |
|||
} |
|||
|
|||
//! Insert string into tree with sort by comparison
|
|||
BSTNode * BSTNode::Insert(const std::string & v) |
|||
{ |
|||
if (NULL == &v || Find(v)) |
|||
return NULL; |
|||
|
|||
// Greater to the right
|
|||
if (0 < value.compare(v)) |
|||
if (NULL == right) |
|||
return right = new BSTNode(v); |
|||
else |
|||
return right->Insert(v); |
|||
// Lesser to the left
|
|||
else if (0 > value.compare(v)) |
|||
if (NULL == left) |
|||
return left = new BSTNode(v); |
|||
else |
|||
return left->Insert(v); |
|||
// Same??? Can't happen
|
|||
else |
|||
return NULL; |
|||
} |
|||
|
|||
//! Find string in tree with sort by comparison
|
|||
BSTNode * BSTNode::Find(const std::string & v) |
|||
{ |
|||
// Equal means this
|
|||
if (0 == value.compare(v)) |
|||
return this; |
|||
|
|||
// Greater to the right
|
|||
else if (0 < value.compare(v) && NULL != right) |
|||
return right->Find(v); |
|||
|
|||
// Lesser to the left
|
|||
else if (0 > value.compare(v) && NULL != left) |
|||
return left->Find(v); |
|||
|
|||
// Nothing matches
|
|||
return NULL; |
|||
} |
|||
|
|||
//! Read-only public methods for use by clients of the BST class
|
|||
const std::string & BSTNode::GetValue() |
|||
{ |
|||
return value; |
|||
} |
|||
|
|||
BSTNode * BSTNode::GetLeft()const |
|||
{ |
|||
return left; |
|||
} |
|||
|
|||
BSTNode * BSTNode::GetRight()const |
|||
{ |
|||
return right; |
|||
} |
|||
|
|||
//! Assignment operator makes a DEEP COPY and does not free memory
|
|||
BSTNode & BSTNode::operator=(const BSTNode & other) |
|||
{ |
|||
if (this == &other) |
|||
return *this; |
|||
|
|||
Clear(); |
|||
Copy(other); |
|||
|
|||
return *this; |
|||
} |
|||
|
|||
|
|||
//! BST implements a binary search tree
|
|||
|
|||
//! No-arg constructor. Initializes an empty BST
|
|||
BST::BST() : |
|||
root(NULL), size(0) |
|||
{ |
|||
// Empty as can be
|
|||
return; |
|||
} |
|||
|
|||
|
|||
//! Copy constructor. Makes a complete copy of its argument
|
|||
BST::BST(const BST & other) |
|||
{ |
|||
Copy(other); |
|||
return; |
|||
} |
|||
|
|||
//! Copy method. Makes a complete copy of its argument
|
|||
void BST::Copy(const BST & other) |
|||
{ |
|||
if (this == &other) |
|||
return; |
|||
|
|||
size = other.GetSize(); |
|||
if(other.root) |
|||
root = (new BSTNode(*(other.root))); |
|||
else |
|||
root=NULL; |
|||
|
|||
return; |
|||
} |
|||
|
|||
//! Destructor
|
|||
BST::~BST() |
|||
{ |
|||
Clear(); |
|||
return; |
|||
} |
|||
|
|||
|
|||
//! Assignment operator. Makes a complete copy of its argument
|
|||
//! @return Reference to oneself
|
|||
BST & BST::operator=(const BST & other) |
|||
{ |
|||
if (this == &other) |
|||
return *this; |
|||
|
|||
Clear(); |
|||
Copy(other); |
|||
return *this; |
|||
} |
|||
|
|||
|
|||
//! @return a pointer to the root node of the tree, or NULL if the tree is empty.
|
|||
//! @note This is useful for BST clients that need to traverse the tree.)
|
|||
BSTNode * BST::GetRoot()const |
|||
{ |
|||
return root; |
|||
} |
|||
|
|||
|
|||
//! @return true if the BST is empty, or false if the BST is not empty
|
|||
bool BST::IsEmpty() const |
|||
{ |
|||
return (NULL == root); |
|||
} |
|||
|
|||
|
|||
//! Removes all values from the BST
|
|||
void BST::Clear() |
|||
{ |
|||
size = 0; |
|||
if (root) |
|||
delete root; |
|||
root = NULL; |
|||
return; |
|||
} |
|||
|
|||
|
|||
//! @return the number of values in the BST
|
|||
int BST::GetSize() const |
|||
{ |
|||
return size; |
|||
} |
|||
|
|||
|
|||
//! Inserts value v into the BST
|
|||
//!
|
|||
//! @param v The new value being inserted
|
|||
//!
|
|||
//! @return a pointer to the newly inserted node, or NULL if v was already
|
|||
//! in the tree (i.e., NULL is used to indicate a duplicate insertion)
|
|||
BSTNode * BST::Insert(const std::string & v) |
|||
{ |
|||
if (Find(v)) |
|||
return NULL; |
|||
|
|||
++size; |
|||
if (root) |
|||
return root->Insert(v); |
|||
else |
|||
return root = new BSTNode(v); |
|||
} |
|||
|
|||
|
|||
//! Searches the tree for value v
|
|||
//!
|
|||
//! @param v The new value being searched for
|
|||
//!
|
|||
//! @return a pointer to the node containing v, or NULL if v is not in the tree
|
|||
BSTNode * BST::Find(const std::string & v) const |
|||
{ |
|||
if (NULL == root) |
|||
return NULL; |
|||
else |
|||
return root->Find(v); |
|||
} |
|||
|
|||
|
|||
//! @NOTE: YOU ARE NOT REQUIRED TO IMPLEMENT THE Remove METHOD BELOW
|
|||
//! (BUT YOU CAN IF YOU WANT TO)
|
|||
//!
|
|||
//! Removes value v from the tree
|
|||
//!
|
|||
//! @param v The value being removed from the tree
|
|||
//!
|
|||
//! @return true if v was removed from the tree, or false if v was not in the tree
|
|||
//bool Remove(const std::string & v);
|
@ -0,0 +1,122 @@ |
|||
#ifndef CS240_BST_H |
|||
#define CS240_BST_H |
|||
|
|||
#include <string> |
|||
|
|||
|
|||
//! BSTNode implements a binary search tree node
|
|||
class BSTNode { |
|||
friend class BST; //!< BST can access private members of BSTNode
|
|||
|
|||
public: |
|||
|
|||
//! Constructor
|
|||
BSTNode(const std::string &); |
|||
|
|||
//! Copy Constructor SHALLOW COPY and does not free memory
|
|||
BSTNode(const BSTNode &); |
|||
|
|||
//! Delete Destructor calls Clear
|
|||
~BSTNode(); |
|||
|
|||
//! Clear recursively deletes nodes
|
|||
void Clear(); |
|||
|
|||
//! Copy recursively copies a node
|
|||
void Copy(const BSTNode &); |
|||
|
|||
//! Insert sorts on string comparison
|
|||
BSTNode * Insert(const std::string &); |
|||
|
|||
//! Find does string comparison to find if node exists
|
|||
BSTNode * Find(const std::string &); |
|||
|
|||
//! Read-only public methods for use by clients of the BST class
|
|||
const std::string & GetValue(); |
|||
|
|||
BSTNode * GetLeft() const; |
|||
BSTNode * GetRight() const; |
|||
|
|||
//! Assignment operator makes a SHALLOW COPY and does not free memory
|
|||
//!Feel free to change this function(IE, to a deep copy).
|
|||
BSTNode & operator=(const BSTNode &); |
|||
|
|||
private: |
|||
std::string value; //!< value stored in the node
|
|||
BSTNode * left; //!< pointer to the node's left child
|
|||
BSTNode * right; //!< pointer to the node's right child
|
|||
}; |
|||
|
|||
|
|||
//! BST implements a binary search tree
|
|||
class BST { |
|||
|
|||
public: |
|||
|
|||
//! No-arg constructor. Initializes an empty BST
|
|||
BST(); |
|||
|
|||
|
|||
//! Copy constructor. Makes a complete copy of its argument
|
|||
BST(const BST &); |
|||
|
|||
|
|||
//! Destructor
|
|||
~BST(); |
|||
|
|||
//! Copy makes DEEP Copy
|
|||
void Copy(const BST &); |
|||
|
|||
//! Assignment operator. Makes a complete copy of its argument
|
|||
//! @return Reference to oneself
|
|||
BST& operator =(const BST &); |
|||
|
|||
|
|||
//! @return a pointer to the root node of the tree, or NULL if the tree is empty.
|
|||
//! @note This is useful for BST clients that need to traverse the tree.)
|
|||
BSTNode * GetRoot()const; |
|||
|
|||
//! @return true if the BST is empty, or false if the BST is not empty
|
|||
bool IsEmpty() const; |
|||
|
|||
//! Removes all values from the BST
|
|||
void Clear(); |
|||
|
|||
//! @return the number of values in the BST
|
|||
int GetSize() const; |
|||
|
|||
|
|||
//! Inserts value v into the BST
|
|||
//!
|
|||
//! @param v The new value being inserted
|
|||
//!
|
|||
//! @return a pointer to the newly inserted node, or NULL if v was already
|
|||
//! in the tree (i.e., NULL is used to indicate a duplicate insertion)
|
|||
BSTNode * Insert(const std::string &); |
|||
|
|||
|
|||
//! Searches the tree for value v
|
|||
//!
|
|||
//! @param v The new value being searched for
|
|||
//!
|
|||
//! @return a pointer to the node containing v, or NULL if v is not in the tree
|
|||
BSTNode * Find(const std::string &) const; |
|||
|
|||
|
|||
//! @NOTE: YOU ARE NOT REQUIRED TO IMPLEMENT THE Remove METHOD BELOW
|
|||
//! (BUT YOU CAN IF YOU WANT TO)
|
|||
//!
|
|||
//! Removes value v from the tree
|
|||
//!
|
|||
//! @param v The value being removed from the tree
|
|||
//!
|
|||
//! @return true if v was removed from the tree, or false if v was not in the tree
|
|||
//bool Remove(const std::string & v);
|
|||
|
|||
private: |
|||
BSTNode * root; |
|||
int size; |
|||
}; |
|||
|
|||
|
|||
#endif |
@ -0,0 +1,272 @@ |
|||
#include "LinkedList.h" |
|||
|
|||
//! LLNode implements a doubly-linked list node
|
|||
//! Constructor
|
|||
LLNode::LLNode(const std::string & v, LLNode * p, LLNode * n) : |
|||
value(v), prev(p), next(n) |
|||
{ |
|||
// Good enough
|
|||
return; |
|||
} |
|||
|
|||
//! Copy Constructor SHALLOW COPY and does not free memory
|
|||
//!Feel free to change this function(IE, to a deep copy).
|
|||
LLNode::LLNode(const LLNode & other) |
|||
{ |
|||
if (this == &other) |
|||
return; |
|||
|
|||
// It makes sense (in my mind) for this to be shallow and disconnected
|
|||
value = other.value; |
|||
prev = NULL; //other.prev;
|
|||
next = NULL; //other.next;
|
|||
} |
|||
|
|||
//! Read-only public methods for use by clients of the LinkedList class
|
|||
const std::string & LLNode::GetValue() const |
|||
{ |
|||
return value; |
|||
} |
|||
|
|||
|
|||
LLNode * LLNode::GetPrevious() const |
|||
{ |
|||
return prev; |
|||
} |
|||
|
|||
|
|||
LLNode * LLNode::GetNext() const |
|||
{ |
|||
return next; |
|||
} |
|||
|
|||
//! Assignment operator makes a SHALLOW COPY and does not free memory
|
|||
//!Feel free to change this function(IE, to a deep copy).
|
|||
LLNode & LLNode::operator=(const LLNode & other) |
|||
{ |
|||
if(this != &other) |
|||
{ |
|||
value = other.value; |
|||
prev = other.prev; |
|||
next = other.next; |
|||
} |
|||
return *this; |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
//! LinkedList implements a doubly-linked list
|
|||
|
|||
//! No-arg constructor. Initializes an empty linked list
|
|||
LinkedList::LinkedList() |
|||
{ |
|||
length = 0; |
|||
head = NULL; |
|||
return; |
|||
} |
|||
|
|||
|
|||
//! Copy constructor. Makes a complete copy of its argument
|
|||
LinkedList::LinkedList(const LinkedList & other) |
|||
{ |
|||
Copy(other); |
|||
return; |
|||
} |
|||
|
|||
//! Copy make a DEEP copy. Makes a complete copy of its argument
|
|||
void LinkedList::Copy(const LinkedList & other) |
|||
{ |
|||
if (this == &other) |
|||
return; |
|||
if (NULL == other.head) { |
|||
head = NULL; |
|||
return; |
|||
} |
|||
|
|||
LLNode * tmpCopy = NULL; |
|||
LLNode * oHead = NULL; |
|||
|
|||
length = other.GetSize(); |
|||
oHead = other.head; |
|||
|
|||
head = new LLNode(*oHead); |
|||
oHead = oHead->next; |
|||
tmpCopy = head; |
|||
while (oHead != NULL) { |
|||
tmpCopy->next = new LLNode(*oHead); |
|||
tmpCopy->next->prev = tmpCopy; |
|||
tmpCopy = tmpCopy->next; |
|||
oHead = oHead->next; |
|||
} |
|||
} |
|||
|
|||
//! Destructor
|
|||
LinkedList::~LinkedList() |
|||
{ |
|||
Clear(); |
|||
} |
|||
|
|||
//! Assignment operator. Makes a complete copy of its argument
|
|||
//! @return A reference to oneself
|
|||
LinkedList& LinkedList::operator =(const LinkedList & other) |
|||
{ |
|||
if (this == &other) |
|||
return *this; |
|||
|
|||
Clear(); |
|||
Copy(other); |
|||
return *this; |
|||
} |
|||
|
|||
|
|||
//! @return true if the list is empty, or false if the list is not empty
|
|||
bool LinkedList::IsEmpty() const |
|||
{ |
|||
return (0 == length); |
|||
} |
|||
|
|||
|
|||
//! Removes all values from the list
|
|||
void LinkedList::Clear() { |
|||
LLNode * tmpCopy = NULL; |
|||
if (NULL == head) |
|||
return; |
|||
|
|||
///*
|
|||
while (NULL != head) { |
|||
tmpCopy = head; |
|||
head = head->next; |
|||
delete tmpCopy; |
|||
}//*/
|
|||
|
|||
length = 0; |
|||
head = NULL; |
|||
return; |
|||
} |
|||
|
|||
|
|||
//! @return the number of values in the list
|
|||
int LinkedList::GetSize() const |
|||
{ |
|||
return length; |
|||
} |
|||
|
|||
|
|||
|
|||
//! @return a pointer to the first node in the list, or NULL if the list is empty
|
|||
LLNode * LinkedList::GetFirst()const |
|||
{ |
|||
return head; |
|||
} |
|||
|
|||
|
|||
|
|||
//! @returns a pointer to the last node in the list, or NULL if the list is empty
|
|||
LLNode * LinkedList::GetLast()const |
|||
{ |
|||
if (IsEmpty()) |
|||
return NULL; |
|||
|
|||
LLNode * tail; |
|||
tail = head; |
|||
while (NULL != tail->next) { |
|||
tail = tail->next; |
|||
} |
|||
return tail; |
|||
} |
|||
|
|||
|
|||
//! Inserts value v into the list after node n
|
|||
//!
|
|||
//! @param v The new value being inserted
|
|||
//! @param n A node that is already in the list after which the new node should
|
|||
//! be inserted.
|
|||
//! If n is NULL, the new node should be inserted at the beginning of the list.
|
|||
//!
|
|||
//! @return a pointer to the newly inserted node
|
|||
LLNode * LinkedList::Insert(const std::string & v, LLNode * n) |
|||
{ |
|||
if (NULL == &v || Find(v, NULL)) |
|||
return NULL; |
|||
|
|||
++length; |
|||
|
|||
LLNode * tmpCopy; |
|||
|
|||
if (NULL == n) { |
|||
tmpCopy = new LLNode(v, NULL, NULL); |
|||
if (NULL != head) |
|||
head->prev = tmpCopy; |
|||
tmpCopy->next = head; |
|||
return head = tmpCopy; |
|||
} |
|||
|
|||
tmpCopy = new LLNode(v, n, n->next); |
|||
if (NULL != n->next) |
|||
n->next->prev = tmpCopy; |
|||
tmpCopy->prev = n; |
|||
tmpCopy->next = n->next; |
|||
n->next = tmpCopy; |
|||
|
|||
return tmpCopy; |
|||
} |
|||
|
|||
|
|||
//! Searches for the first occurrence of value v that appears in the list
|
|||
//! after node n
|
|||
//!
|
|||
//! @param v The value being searched for
|
|||
//! @param n The node in the list after which the search should begin.
|
|||
//! If n is NULL, the list should be searched from the beginning.
|
|||
//!
|
|||
//! @return a pointer to the node containing v, or NULL if v is not found
|
|||
LLNode * LinkedList::Find(const std::string & v, LLNode * n) const |
|||
{ |
|||
LLNode * result; |
|||
if (NULL != n) |
|||
result = n->next; |
|||
else |
|||
result = head; |
|||
|
|||
while (NULL != result) { |
|||
if (0 == result->value.compare(v)) |
|||
return result; |
|||
result = result->next; |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
|
|||
//! Removes node n from the list
|
|||
//!
|
|||
//! @param n The node being removed from the list
|
|||
void LinkedList::Remove(LLNode * n) |
|||
{ |
|||
if (NULL == n) |
|||
return; |
|||
|
|||
--length; |
|||
|
|||
if (NULL != n->prev) |
|||
n->prev->next = n->next; |
|||
else { |
|||
head = n->next; // Could be NULL
|
|||
if (NULL != head) |
|||
head->prev = NULL; |
|||
} |
|||
if (NULL != n->next) |
|||
n->next->prev = n->prev; |
|||
|
|||
delete n; |
|||
n = NULL; |
|||
|
|||
return; |
|||
} |
|||
|
@ -0,0 +1,118 @@ |
|||
#ifndef CS240_LINKED_LIST_H |
|||
#define CS240_LINKED_LIST_H |
|||
|
|||
#include <string> |
|||
|
|||
//! LLNode implements a doubly-linked list node
|
|||
class LLNode { |
|||
friend class LinkedList; //!< LinkedList can access private members of LLNode
|
|||
public: |
|||
|
|||
//! Constructor
|
|||
LLNode(const std::string &, LLNode *, LLNode *); |
|||
|
|||
//! Copy Constructor SHALLOW COPY and does not free memory
|
|||
//!Feel free to change this function(IE, to a deep copy).
|
|||
LLNode(const LLNode &); |
|||
|
|||
//! Read-only public methods for use by clients of the LinkedList class
|
|||
const std::string & GetValue() const; |
|||
|
|||
|
|||
LLNode * GetPrevious() const; |
|||
|
|||
|
|||
LLNode * GetNext() const; |
|||
|
|||
//! Assignment operator makes a SHALLOW COPY and does not free memory
|
|||
//!Feel free to change this function(IE, to a deep copy).
|
|||
LLNode & operator=(const LLNode &); |
|||
|
|||
private: |
|||
std::string value; //!< value stored in the node
|
|||
LLNode * prev; //!< pointer to previous node in the list
|
|||
LLNode * next; //!< pointer to next node in the list
|
|||
}; |
|||
|
|||
|
|||
//! LinkedList implements a doubly-linked list
|
|||
class LinkedList |
|||
{ |
|||
public: |
|||
|
|||
//! No-arg constructor. Initializes an empty linked list
|
|||
LinkedList(); |
|||
|
|||
|
|||
//! Copy constructor. Makes a complete copy of its argument
|
|||
LinkedList(const LinkedList & other); |
|||
|
|||
|
|||
//! Destructor
|
|||
~LinkedList(); |
|||
|
|||
//! Copy make a DEEP copy. Makes a complete copy of its argument
|
|||
void Copy(const LinkedList &); |
|||
|
|||
//! Assignment operator. Makes a complete copy of its argument
|
|||
//! @return A reference to oneself
|
|||
LinkedList& operator =(const LinkedList & other); |
|||
|
|||
|
|||
//! @return true if the list is empty, or false if the list is not empty
|
|||
bool IsEmpty() const; |
|||
|
|||
|
|||
//! Removes all values from the list
|
|||
void Clear(); |
|||
|
|||
|
|||
//! @return the number of values in the list
|
|||
int GetSize() const; |
|||
|
|||
|
|||
|
|||
//! @return a pointer to the first node in the list, or NULL if the list is empty
|
|||
LLNode * GetFirst() const; |
|||
|
|||
|
|||
|
|||
//! @returns a pointer to the last node in the list, or NULL if the list is empty
|
|||
LLNode * GetLast() const; |
|||
|
|||
|
|||
//! Inserts value v into the list after node n
|
|||
//!
|
|||
//! @param v The new value being inserted
|
|||
//! @param n A node that is already in the list after which the new node should
|
|||
//! be inserted.
|
|||
//! If n is NULL, the new node should be inserted at the beginning of the list.
|
|||
//!
|
|||
//! @return a pointer to the newly inserted node
|
|||
LLNode * Insert(const std::string & v, LLNode * n); |
|||
|
|||
|
|||
//! Searches for the first occurrence of value v that appears in the list
|
|||
//! after node n
|
|||
//!
|
|||
//! @param v The value being searched for
|
|||
//! @param n The node in the list after which the search should begin.
|
|||
//! If n is NULL, the list should be searched from the beginning.
|
|||
//!
|
|||
//! @return a pointer to the node containing v, or NULL if v is not found
|
|||
LLNode * Find(const std::string & v, LLNode * n) const; |
|||
|
|||
|
|||
//! Removes node n from the list
|
|||
//!
|
|||
//! @param n The node being removed from the list
|
|||
void Remove(LLNode * n); |
|||
|
|||
private: |
|||
int length; |
|||
LLNode * head; |
|||
}; |
|||
|
|||
|
|||
#endif |
|||
|
@ -0,0 +1,14 @@ |
|||
all: test |
|||
|
|||
bst: obj/BST.o |
|||
obj/BST.o: BST.h BST.cpp |
|||
g++ -c -o obj/BST.o BST.cpp |
|||
|
|||
ll: obj/LinkedList.o LinkedList.h LinkedList.cpp |
|||
g++ -c -o obj/LinkedList.o LinkedList.cpp |
|||
|
|||
test: bst ll colexp passoff |
|||
./colexp part2 |
|||
|
|||
clean: |
|||
rm *.o obj/*.o -rf |
@ -0,0 +1,12 @@ |
|||
About |
|||
==== |
|||
|
|||
I wrote `LinkedList.cpp` and `BST.cpp`. Parts of the `*.h` were provided by BYU as the documentation for the project. |
|||
|
|||
The test program was created by BYU, but I don't see a copyright so I assume I'm safe to include it. |
|||
|
|||
Build on Ubuntu 10.04 |
|||
==== |
|||
|
|||
sudo apt-get install libboost-all-dev valgrind |
|||
make |
@ -0,0 +1,3 @@ |
|||
#!/usr/bin/env sh |
|||
echo "Running the Collections Test Passoff" |
|||
make -f ./passoff/Makefile $@ |
@ -0,0 +1,153 @@ |
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> |
|||
<html><head> |
|||
|
|||
|
|||
|
|||
<meta name="generator" content="HTML Tidy for Linux/x86 (vers 6 November 2007), see www.w3.org"><title>Collections Part I and II</title> |
|||
|
|||
|
|||
<meta http-equiv="content-type" content="text/html; charset=us-ascii"> |
|||
<meta http-equiv="content-style-type" content="text/css"> |
|||
<link rel="stylesheet" type="text/css" media="screen,projection" href="collections_files/style.css"></head><body> |
|||
<div class="box"> |
|||
<h1>Computer Science 240 :: Advanced Programming</h1> |
|||
</div> |
|||
|
|||
<div class="main"> |
|||
<div class="center"> |
|||
<h2>Collections</h2> |
|||
</div> |
|||
<hr> |
|||
|
|||
<p><b>NOTE: This project is divided into two parts (Part I and |
|||
Part II). For the Programming Exam you only need to complete |
|||
Part I. Part II will be completed after the Programming |
|||
Exam.</b></p> |
|||
|
|||
<h3>Overview</h3> |
|||
|
|||
<p>Most non-trivial programs use data structures to store and |
|||
access information. Common examples are lists, stacks, queues, |
|||
trees, etc. Data structures are also called "collections" |
|||
because they are used to manage groups (or collections) of |
|||
objects. For this assignment you will write two collection |
|||
classes in C++. You will write a class named |
|||
<tt>LinkedList</tt> that implements a doubly-linked list and a |
|||
class named <tt>BST</tt> that implements a binary search tree. |
|||
Unlike the previous projects, you will not be asked to deliver |
|||
a complete running program. Rather, the deliverables for this |
|||
project are just the <tt>LinkedList</tt> and <tt>BST</tt> |
|||
classes. To pass off your project, we will take your classes |
|||
and compile and link them with a test program that will |
|||
exercise your code and verify that it works. It is your |
|||
responsibility to test your code and make sure that it works |
|||
before passing off.</p> |
|||
|
|||
<h3>Project Files</h3> |
|||
|
|||
<p>Header files for the <tt>LinkedList</tt> and <tt>BST</tt> |
|||
classes are provided at the following links:</p> |
|||
|
|||
<p><a href="http://students.cs.byu.edu/%7Ecs240ta/winter2008/projects/collections/LinkedList.h">LinkedList.h</a></p> |
|||
|
|||
<p><a href="http://students.cs.byu.edu/%7Ecs240ta/winter2008/projects/collections/BST.h">BST.h</a></p> |
|||
|
|||
<p>Your task is to implement all of the methods on the |
|||
<span style="font-family: "Courier New";">LinkedList</span> and |
|||
<span style="font-family: "Courier New";">BST</span> classes |
|||
according to the comments in the header files. You should place |
|||
your <span style="font-family: "Courier New";">LinkedList</span> |
|||
and <span style="font-family: "Courier New";">BST</span> |
|||
implementations in files named <span style="font-family: "Courier New";">LinkedList.cpp</span> and |
|||
<span style="font-family: "Courier New";">BST.cpp</span>, |
|||
respectively. You should not modify the public interfaces of |
|||
the classes. If you do, the test program that will be used to |
|||
pass off your code will not compile. You may (and probably |
|||
should) modify the <span style="font-family: "Courier New";">.h</span> files to add private |
|||
method and variable declarations, but your method bodies should |
|||
go in the <span style="font-family: "Courier New";">.cpp</span> |
|||
files.</p> |
|||
|
|||
<p>The test program will assume that your files are named |
|||
<span style="font-family: "Courier New";">LinkedList.h</span>, |
|||
<span style="font-family: "Courier New";">LinkedList.cpp</span>, |
|||
<span style="font-family: "Courier New";">BST.h</span>, and |
|||
<span style="font-family: "Courier New";">BST.cpp</span> Since |
|||
Linux file names are case sensitive, capitalization does |
|||
matter.</p> |
|||
|
|||
<h3>Restrictions</h3> |
|||
|
|||
<p>For this project you <u>are</u> allowed to use the C++ |
|||
string class defined in the <span style="font-family: "Courier New";"><string></span> header file |
|||
(in fact, you must use it to make your code work).</p> |
|||
|
|||
<p>You <u>are not</u> allowed to use the classes and functions |
|||
from the Standard Template Library (vector, list, map, set, |
|||
etc.). Specifically, the following header files may not be |
|||
used:</p> |
|||
|
|||
<ul> |
|||
<li><algorithm></li> |
|||
|
|||
<li><deque></li> |
|||
|
|||
<li><list></li> |
|||
|
|||
<li><map></li> |
|||
|
|||
<li><queue></li> |
|||
|
|||
<li><set></li> |
|||
|
|||
<li><stack></li> |
|||
|
|||
<li><vector></li> |
|||
</ul> |
|||
|
|||
<h3>Part I</h3> |
|||
|
|||
<p>Implement all of the methods on the <span style="font-family: "Courier New";">LinkedList</span> and <span style="font-family: "Courier New";">BST</span> classes.</p> |
|||
|
|||
<p>For Part I your code will not be tested for memory |
|||
management errors. That will come in Part II.</p> |
|||
|
|||
<h3>Part II</h3> |
|||
|
|||
<p>Ensure that your code does not contain any memory management |
|||
errors, as described in the <i>Memory Management Errors</i> |
|||
section of the Project I specification. The TAs will use |
|||
<span style="font-family: "Courier New";">valgrind</span> to |
|||
check your code for memory-related errors when you pass off. |
|||
You should run <span style="font-family: "Courier New";">valgrind</span> on your code and |
|||
fix any reported bugs before attempting to pass off.</p> |
|||
|
|||
<p>Not all memory errors are your fault and there are cases of false positives. We offer a <a href="http://students.cs.byu.edu/%7Ecs240ta/util_docs/string.supp">file</a> to suppress these for you.</p> |
|||
</div> |
|||
<div class="menu"> |
|||
<div class="nav"> |
|||
<div>Main Menu</div> |
|||
<dl> |
|||
<dd><a href="http://students.cs.byu.edu/%7Ecs240ta/winter2008/">Home Page</a></dd> |
|||
</dl><dl> |
|||
<dt><a>Class Information</a></dt> |
|||
<dd><a href="http://students.cs.byu.edu/%7Ecs240ta/winter2008/info/policies.php">Policies</a></dd> |
|||
<dd><a href="http://students.cs.byu.edu/%7Ecs240ta/winter2008/info/schedule.php">Schedule</a></dd> |
|||
<dd><a href="http://students.cs.byu.edu/%7Ecs240ta/winter2008/projects/">Projects</a></dd> |
|||
<dd><a href="http://students.cs.byu.edu/%7Ecs240ta/winter2008/tutorials/">Tutorials</a></dd> |
|||
<dd><a href="http://students.cs.byu.edu/%7Ecs240ta/winter2008/TA/">TA Schedule</a></dd> |
|||
</dl><dl> |
|||
<dt><a>Help</a></dt> |
|||
<dd><a href="http://gotapi.com/ccpp" target="_blank">C++ API</a></dd> |
|||
<dd><a href="http://boost.org/libs/libraries.htm" target="_blank">Boost API</a></dd> |
|||
<dd><a href="http://students.cs.byu.edu/%7Ecs240ta/winter2008/tutorials/boost.php">Boost?</a></dd> |
|||
<dd><a href="http://students.cs.byu.edu/%7Ecs240ta/util_docs/" target="_blank">CS 240 Utils API</a></dd> |
|||
<dd><a href="http://students.cs.byu.edu/%7Ecs240ta/winter2008/resources/">Resources</a></dd> |
|||
</dl><dl> |
|||
<dt><a>Contact</a></dt> |
|||
<dd><a href="http://blackboard.byu.edu/">CS 240 TA's</a></dd> |
|||
<dd><a href="mailto:rodham@cs.byu.edu">Dr. Ken Rodham</a></dd> |
|||
<dd><a href="mailto:egbert@cs.byu.edu">Dr. Parris Egbert</a></dd> |
|||
</dl> |
|||
</div> |
|||
</div></body></html> |
@ -0,0 +1,522 @@ |
|||
@charset "iso-8859-1"; |
|||
body { |
|||
margin: 2ex; |
|||
color: #000; |
|||
font-family: tahoma, verdana, sans, arial, helvetica, sans-serif; |
|||
background: #e8e8e8; |
|||
max-width: 120ex; |
|||
} |
|||
.box { |
|||
font-size: 90%; |
|||
background: #7f97b0 url(../images/hr.png) repeat-x; |
|||
margin-left: 26ex; |
|||
|
|||
color: white; |
|||
border-color: black; |
|||
border-style: solid; |
|||
border-width: 1px 1px 1px 1px; |
|||
height: 5ex; |
|||
} |
|||
.box h1 { |
|||
font-weight: normal; |
|||
font-size: 150%; |
|||
float: left; |
|||
margin: 0px 1ex; |
|||
padding: .5ex 0ex 0ex 0ex; |
|||
letter-spacing: 1px; |
|||
} |
|||
.box div { |
|||
font-weight: normal; |
|||
font-size: 108%; |
|||
height: 3.5ex; |
|||
text-align: right; |
|||
padding: 1.2ex 1ex 0ex 0ex; |
|||
white-space: nowrap; |
|||
} |
|||
.hr_1 { |
|||
font-size: 90%; |
|||
background: url(../images/hr_3.png) #446 repeat-x; |
|||
color: inherit; |
|||
margin-left: 26ex; |
|||
margin-top: -1px; |
|||
height: 2ex; |
|||
border-color: #000; |
|||
border-width: 1px 1px 1px 1px; |
|||
border-style: solid; |
|||
} |
|||
.nav div.hr_2 { |
|||
border-top-width: 0; |
|||
font-size: 90%; |
|||
background: url(../images/hr_3.png) #446 repeat-x; |
|||
color: inherit; |
|||
margin: 0ex 0ex 2ex; |
|||
height: 2ex; |
|||
} |
|||
|
|||
.menu { |
|||
background: #fff url(../images/back.png) repeat-y; |
|||
color: inherit; |
|||
left: 2ex; |
|||
padding-bottom: 0.5ex; |
|||
width: 22ex; |
|||
border: black 1px solid; |
|||
position: absolute; |
|||
top: 6.6ex; |
|||
} |
|||
|
|||
[class="menu"]{ |
|||
position: fixed; |
|||
} |
|||
|
|||
.nav { |
|||
margin: 0; |
|||
text-align: center; |
|||
} |
|||
|
|||
.nav span { |
|||
display: none |
|||
} |
|||
|
|||
.nav div { |
|||
font-weight: bold; |
|||
font-size: 90%; |
|||
background: url(../images/hr_2.png) #7f97b0 repeat-x; |
|||
margin: 0ex 0px 0.5ex; |
|||
color: #fff; |
|||
text-align: center; |
|||
border-style: solid; |
|||
border-color: #000; |
|||
border-width: 0px 0px 1px; |
|||
} |
|||
|
|||
.nav a { |
|||
padding-right: 5px; |
|||
display: block; |
|||
padding-left: 5px; |
|||
font-size: 80%; |
|||
text-align: left; |
|||
text-decoration: none; |
|||
color: #000; |
|||
background: transparent; |
|||
} |
|||
|
|||
.menu .nav a:link, .menu .nav a:visited { |
|||
padding-right: 5px; |
|||
display: block; |
|||
padding-left: 5px; |
|||
font-size: 80%; |
|||
text-align: left; |
|||
text-decoration: none; |
|||
color: #339; |
|||
background: transparent; |
|||
} |
|||
|
|||
.nav dt { |
|||
font-weight: bold; |
|||
padding-right: 5px; |
|||
display: block; |
|||
padding-left: 5px; |
|||
font-size: 80%; |
|||
text-align: left; |
|||
text-decoration: none; |
|||
color: #339; |
|||
background: transparent; |
|||
} |
|||
|
|||
.nav dd { |
|||
margin-left: 0px; |
|||
padding-left: 0px; |
|||
} |
|||
|
|||
.nav dl { |
|||
margin-top: 0px; |
|||
margin-bottom: 0.5ex; |
|||
} |
|||
|
|||
.menu .nav a:hover { |
|||
background: url(../images/menuhover.png) repeat-y; |
|||
text-decoration: none; |
|||
color: #339; |
|||
} |
|||
|
|||
.nav dd a:before { |
|||
content: " "; |
|||
} |
|||
|
|||
.nav dl.links dd a:before { |
|||
content: ""; |
|||
} |
|||
|
|||
.nav a.indent { |
|||
margin-left: 0; |
|||
} |
|||
|
|||
.nav a.indent:before { |
|||
content: " "; |
|||
} |
|||
|
|||
.nav span.menuspace { |
|||
display: block; |
|||
border-width: 0; |
|||
height: .4em; |
|||
} |
|||
|
|||
.nav a.selected { |
|||
background: url(../images/menuhover.png) repeat-y; |
|||
color: #000; |
|||
} |
|||
|
|||
.main { |
|||
font-size: 90%; |
|||
min-height: 61ex; |
|||
background: #fff; |
|||
color: inherit; |
|||
margin: 0ex 0ex 0ex 26ex; |
|||
border-color: black; |
|||
border-style: solid; |
|||
padding: 1ex 2ex 0ex; |
|||
border-width: 0px 1px 1px 1px; |
|||
} |
|||
|
|||
/*.main ul li a:before { |
|||
content: " "; |
|||
}*/ |
|||
|
|||
.main ul li p a:before { |
|||
content: ""; |
|||
} |
|||
|
|||
img { |
|||
border-width: 0; |
|||
vertical-align: bottom; |
|||
} |
|||
|
|||
img.screenshot { |
|||
margin: 0.5em 0em 0.5em 0em; |
|||
} |
|||
|
|||
img.down { |
|||
width: 18px; |
|||
height: 18px; |
|||
} |
|||
|
|||
div.logo { |
|||
float: right; |
|||
margin: 15px 0px 0px 10px; |
|||
} |
|||
|
|||
div.screenshot-right, div.screenshot-left { |
|||
border: 1px solid #caccd3; |
|||
background: #f2f2f8; |
|||
color: black; |
|||
padding: 3px; |
|||
text-align: center; |
|||
} |
|||
|
|||
div.screenshot-right { |
|||
float: right; |
|||
margin: 0px 0px 0px 10px; |
|||
} |
|||
|
|||
div.screenshot-left { |
|||
float: left; |
|||
margin: 0px 10px 5px 0px; |
|||
} |
|||
|
|||
div.right { |
|||
float: right; |
|||
margin: 0px 0px 0px 10px; |
|||
} |
|||
|
|||
div.center { |
|||
text-align: center; |
|||
} |
|||
|
|||
|
|||
p.justify { |
|||
text-align: justify; |
|||
} |
|||
|
|||
div.screenshot-left p, div.screenshot-right p { |
|||
margin-top: 2px; |
|||
margin-bottom: 0px; |
|||
font-size: 80%; |
|||
text-align: center; |
|||
} |
|||
|
|||
div.logo { |
|||
margin-top: -2em; |
|||
} |
|||
|
|||
a:link, a:visited, a:active { |
|||
color: #833; |
|||
/*text-decoration: none;*/ |
|||
background: transparent; |
|||
} |
|||
|
|||
a:hover { |
|||
color: #c00; |
|||
background: transparent; |
|||
text-decoration: underline; |
|||
} |
|||
|
|||
a.blue { |
|||
color: #00f; |
|||
background: transparent; |
|||
text-decoration: underline; |
|||
} |
|||
|
|||
hr { |
|||
border: 0px; |
|||
border-top: 2px solid #ccccff; |
|||
height: 0; |
|||
clear: both; |
|||
} |
|||
|
|||
h2.headline { |
|||
font-size: 130%; |
|||
margin-bottom: 0.25em; |
|||
color: #009; |
|||
background: transparent; |
|||
} |
|||
|
|||
p { |
|||
line-height: 1.3em; |
|||
margin-bottom: 1em; |
|||
margin-top: 0em; |
|||
} |
|||
|
|||
p a, ul.disc a { |
|||
font-weight: bold; |
|||
} |
|||
|
|||
h2 { |
|||
font-weight: normal; |
|||
font-size: 150%; |
|||
color: #7c98a6; |
|||
background: transparent; |
|||
} |
|||
|
|||
h3 { |
|||
font-weight: normal; |
|||
font-size: 110%; |
|||
margin-bottom: 0.5em; |
|||
border-bottom: 1px solid #cccccc; |
|||
color: #009; |
|||
background: transparent; |
|||
text-align: left; |
|||
} |
|||
|
|||
.clear { |
|||
clear: both; |
|||
} |
|||
|
|||
h4 { |
|||
font-size: 100%; |
|||
margin-bottom: 1ex; |
|||
color: #337; |
|||
background: transparent; |
|||
text-align: left; |
|||
} |
|||
|
|||
h5 { |
|||
margin-bottom: 0.25em; |
|||
} |
|||
|
|||
div.indent { |
|||
margin-left: 3ex; |
|||
} |
|||
|
|||
ol { |
|||
margin-left: 0px; |
|||
padding-left: 25px; |
|||
} |
|||
|
|||
ul { |
|||
padding-left: 25px; |
|||
margin-left: 0px; |
|||
|
|||
font-size: inherit; |
|||
} |
|||
|
|||
ul.disc { |
|||
list-style-type: disc; |
|||
} |
|||
|
|||
.strike { |
|||
text-decoration: line-through; |
|||
} |
|||
|
|||
div.rightside { |
|||
background: #f7f6fb; |
|||
color: inherit; |
|||
float: right; |
|||
padding: 1ex; |
|||
margin-top: 3ex; |
|||
width: 30%; |
|||
border: #9999cc 1px solid; |
|||
font-size: 90%; |
|||
} |
|||
|
|||
div.rightside h3 { |
|||
margin-top: 0; |
|||
} |
|||
|
|||
div.rightside:first-child p { |
|||
margin-bottom: 0; |
|||
text-align: justify; |
|||
} |
|||
|
|||
table { |
|||
background-color: #666699; |
|||
border: gray 0px solid; |
|||
border-spacing: 1px; |
|||
color: inherit; |
|||
margin-bottom: 1em; |
|||
} |
|||
|
|||
td { |
|||
padding-right: 12px; |
|||
padding-left: 6px; |
|||
font-size: 90%; |
|||
background-color: #fff; |
|||
vertical-align: top; |
|||
color: #000; |
|||
} |
|||
|
|||
th { |
|||
font-weight: bold; |
|||
background-color: #666; |
|||
text-align: left; |
|||
color: #fff; |
|||
} |
|||
|
|||
.code, kbd, pre, tt, var { |
|||
font-family: "courier new", "courier", monospace; |
|||
} |
|||
|
|||
.keyword { |
|||
font-style: italic; |
|||
color: #009; |
|||
} |
|||
|
|||
em { |
|||
font-weight: bold; |
|||
font-style: normal; |
|||
color: #C00; |
|||
} |
|||
|
|||
pre, .code { |
|||
background: #f5f8fb; |
|||
font-weight: bold; |
|||
color: black; |
|||
border: 1px dashed #e5e8eb; |
|||
text-align: left; |
|||
padding: 0.5ex; |
|||
display: block; |
|||
margin: 1em 0em 1em 0em; |
|||
} |
|||
|
|||
fieldset { |
|||
font-size: 90%; |
|||
border: 1px solid gray; |
|||
} |
|||
|
|||
fieldset.left { |
|||
width: 47%; |
|||
} |
|||
|
|||
fieldset.right { |
|||
float: right; |
|||
width: 47%; |
|||
} |
|||
|
|||
abbr, span.credits { |
|||
border-bottom: 1px dashed #6666cc; |
|||
cursor: help; |
|||
} |
|||
|
|||
li.newsection { |
|||
margin-top: 1ex; |
|||
|
|||
} |
|||
|
|||
div.downloadinfo { |
|||
margin-bottom: 1em; |
|||
background: #f7f6fb; |
|||
color: inherit; |
|||
float: right; |
|||
padding: 1ex; |
|||
width: 37%; |
|||
border: #9999cc 1px solid; |
|||
} |
|||
|
|||
div.downloadinfo p { |
|||
text-align: justify; |
|||
margin-top: 0ex; |
|||
margin-bottom: 0.6ex; |
|||
} |
|||
|
|||
div.news { |
|||
border-left: 0.8ex #e2e1e6 solid; |
|||
border-bottom: 1px #d6d5da solid; |
|||
border-top: 1px #e2e1e6 solid; |
|||
border-right: 1px #d2d1d6 solid; |
|||
|
|||
padding-left: 1ex; |
|||
padding-right: 1ex; |
|||
margin-bottom: 1ex; |
|||
margin-top: 2ex; |
|||
padding-top: 0px; |
|||
padding-bottom: 2ex; |
|||
background: #ffffff; |
|||
color: inherit; |
|||
} |
|||
|
|||
div.news h4 { |
|||
margin-top: 1ex; |
|||
} |
|||
|
|||
div.news div.category1 { |
|||
float: right; |
|||
font-size: 80%; |
|||
background: #f8f7fc; |
|||
color: #666699; |
|||
|
|||
margin-top: -1ex; |
|||
padding: 0px 2px 1px 2px; |
|||
border-width: 1px; |
|||
border-style: solid; |
|||
border-color: #eeedf2; |
|||
} |
|||
|
|||
div.news p.info { |
|||
float:left; |
|||
border-top: 1px solid #e2e1e6; |
|||
font-size: 80%; |
|||
width: 42ex; |
|||
color: #333366; |
|||
background: transparent; |
|||
margin-top: -1ex; |
|||
padding-top: 0px; |
|||
} |
|||
|
|||
div.news p.info a:link, div.news p.info a:visited { |
|||
color: #333366; |
|||
background: transparent; |
|||
font-weight: normal; |
|||
} |
|||
|
|||
p.newsarchive { |
|||
text-align: right; font-size: 80%; margin-top: -1ex; padding-top: 0px; |
|||
} |
|||
|
|||
div.downloadicon { |
|||
background: transparent url("../images/download.png") no-repeat top right; |
|||
min-height: 200px; |
|||
} |
|||
|
|||
div.optionsicon { |
|||
background: transparent url("../images/options.png") no-repeat top right; |
|||
min-height: 200px; |
|||
} |
@ -0,0 +1,17 @@ |
|||
#include "BST.h" |
|||
#include <cstdlib> |
|||
#include <iostream> |
|||
#include <stdlib.h> |
|||
#include <string> |
|||
#include <cstring> |
|||
|
|||
int main(int argc, char * argv[]) { |
|||
std::string str; |
|||
str.append("AJ"); |
|||
std::cout << "okay" << std::endl; |
|||
BST * bst = new BST(); |
|||
bst->Insert(str); |
|||
std::cout << bst->GetRoot()->GetValue() << std::endl; |
|||
BST * bstCopy = new BST(*bst); |
|||
std::cout << bstCopy->GetRoot()->GetValue() << std::endl; |
|||
} |
@ -0,0 +1,65 @@ |
|||
SUPPRESIONS=./passoff/coll.supp |
|||
PASSOFF_DIR=./passoff |
|||
STUDENT_DIR = . |
|||
|
|||
CC = g++ |
|||
CFLAGS = -I./ -Wall -Winit-self -Wmissing-include-dirs -Wextra -Wfloat-equal -c -ggdb |
|||
LFLAGS = -o |
|||
LIB = -lboost_program_options -lboost_filesystem -lboost_iostreams |
|||
|
|||
TESTR_BIN = $(STUDENT_DIR)/test_runner |
|||
TESTR_SRC = $(PASSOFF_DIR)/test_runner.cpp $(PASSOFF_DIR)/test_ll.cpp $(PASSOFF_DIR)/test_bst.cpp |
|||
TESTR_OBJ = $(foreach obj, $(TESTR_SRC:.cpp=.o), $(addprefix $(STUDENT_DIR)/,$(shell basename $(obj)))) |
|||
|
|||
STUDENT_SRC = $(STUDENT_DIR)/LinkedList.cpp $(STUDENT_DIR)/BST.cpp |
|||
STUDENT_OBJ = $(STUDENT_SRC:.cpp=.o) |
|||
|
|||
all: help |
|||
|
|||
help: |
|||
@ echo -e "Accepted Targets" |
|||
@ echo -e "\tpart1 - Test with no memory check, auto-cleans" |
|||
@ echo -e "\tpart2 - Test with memory check, auto-cleans" |
|||
@ echo -e "" |
|||
@ echo -e "\tnomem - Test with no memory check" |
|||
@ echo -e "\tmem - Test with memory check" |
|||
@ echo -e "\tdebug - Run the test with gdb" |
|||
@ echo -e "\t$(TESTR_BIN) - Compile the executable" |
|||
@ echo -e "\tclean - Clean the build" |
|||
|
|||
part1: nomem clean |
|||
|
|||
part2: mem clean |
|||
|
|||
mem: $(TESTR_BIN) |
|||
- time valgrind --tool=memcheck --leak-check=yes --show-reachable=yes --suppressions=$(SUPPRESIONS) $(TESTR_BIN) |
|||
|
|||
|
|||
nomem: $(TESTR_BIN) |
|||
- time $(TESTR_BIN) |
|||
|
|||
debug: $(TESTR_BIN) |
|||
gdb $(TESTR_BIN) |
|||
|
|||
|
|||
clean: |
|||
rm -f $(TESTR_BIN) |
|||
rm -f $(STUDENT_OBJ) |
|||
rm -f $(TESTR_OBJ) |
|||
|
|||
$(TESTR_BIN): $(TESTR_OBJ) $(STUDENT_OBJ) |
|||
$(CC) $(TESTR_OBJ) $(STUDENT_OBJ) $(LIB) $(LFLAGS) $(TESTR_BIN) |
|||
|
|||
#Makefile Debugging
|
|||
#Target to print any variable, can be added to the dependencies of any other target
|
|||
#Userfule flags for make, -d, -p, -n
|
|||
print-%: ; @$(error $* is $($*) ($(value $*)) (from $(origin $*))) |
|||
|
|||
#Support
|
|||
%.o: $(PASSOFF_DIR)/%.cpp |
|||
$(CC) $(CFLAGS) $< $(LFLAGS) $@ |
|||
|
|||
%.o: %.cpp |
|||
$(CC) $(CFLAGS) $< $(LFLAGS) $@ |
|||
|
|||
# DO NOT DELETE THIS LINE --
|
@ -0,0 +1,661 @@ |
|||
{ |
|||
Dynamic Linker Bug |
|||
Memcheck:Cond |
|||
fun:_dl_relocate_object |
|||
fun:dl_main |
|||
fun:_dl_sysdep_start |
|||
fun:_dl_start |
|||
obj:/lib/ld-2.6.so |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:strlen |
|||
fun:_ZNSsC1EPKcRKSaIcE |
|||
fun:_Z11generateKeyv |
|||
fun:_Z14TestLinkedListb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZStneIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
fun:_Z14TestLinkedListb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZStneIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
fun:_Z14TestLinkedListb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZStneIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
fun:_Z12CompareListsRK10LinkedListRSt4listISsSaISsEE |
|||
fun:_Z14TestLinkedListb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZStneIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
fun:_Z12CompareListsRK10LinkedListRSt4listISsSaISsEE |
|||
fun:_Z14TestLinkedListb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZStneIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
fun:_Z12CompareListsRK10LinkedListRSt4listISsSaISsEE |
|||
fun:_Z14TestLinkedListb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZStneIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
fun:_Z12CompareListsRK10LinkedListRSt4listISsSaISsEE |
|||
fun:_Z14TestLinkedListb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZStneIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
fun:_Z12CompareListsRK10LinkedListRSt4listISsSaISsEE |
|||
fun:_Z14TestLinkedListb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZSteqIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
fun:_ZNK10LinkedList4FindERKSsP6LLNode |
|||
fun:_Z14TestLinkedListb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZStneIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
fun:_Z14TestLinkedListb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZSteqIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
fun:_ZNK10LinkedList4FindERKSsP6LLNode |
|||
fun:_Z14TestLinkedListb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:strlen |
|||
fun:_ZNSsC1EPKcRKSaIcE |
|||
fun:_Z11generateKeyv |
|||
fun:_Z14TestLinkedListb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZSteqIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
fun:_ZNK10LinkedList4FindERKSsP6LLNode |
|||
fun:_Z14TestLinkedListb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZSteqIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
fun:_ZSt6__findISt14_List_iteratorISsESsET_S2_S2_RKT0_St18input_iterator_tag |
|||
fun:_ZSt4findISt14_List_iteratorISsESsET_S2_S2_RKT0_ |
|||
fun:_Z14TestLinkedListb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZStneIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
fun:_Z14TestLinkedListb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZSteqIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
fun:_ZNK10LinkedList4FindERKSsP6LLNode |
|||
fun:_Z14TestLinkedListb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:strlen |
|||
fun:_ZNSsC1EPKcRKSaIcE |
|||
fun:_Z11generateKeyv |
|||
fun:_Z7TestBSTb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZStneIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
fun:_Z7TestBSTb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZSteqIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZSteqIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZStneIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
fun:_Z7TestBSTb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:strlen |
|||
fun:_ZNSsC1EPKcRKSaIcE |
|||
fun:_Z11generateKeyv |
|||
fun:_Z7TestBSTb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZStneIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:strlen |
|||
fun:_ZNSsC1EPKcRKSaIcE |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZStltIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZStltIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:strlen |
|||
fun:_ZNSsC1EPKcRKSaIcE |
|||
fun:_Z11generateKeyv |
|||
fun:_Z14TestLinkedListb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZStneIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
fun:_Z14TestLinkedListb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZStneIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
fun:_Z14TestLinkedListb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZStneIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
fun:_Z12CompareListsRK10LinkedListRSt4listISsSaISsEE |
|||
fun:_Z14TestLinkedListb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZStneIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
fun:_Z12CompareListsRK10LinkedListRSt4listISsSaISsEE |
|||
fun:_Z14TestLinkedListb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZStneIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
fun:_Z12CompareListsRK10LinkedListRSt4listISsSaISsEE |
|||
fun:_Z14TestLinkedListb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZStneIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
fun:_Z12CompareListsRK10LinkedListRSt4listISsSaISsEE |
|||
fun:_Z14TestLinkedListb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZStneIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZNK10LinkedList4FindERKSsP6LLNode |
|||
fun:_Z14TestLinkedListb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZStneIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
fun:_Z14TestLinkedListb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZNK10LinkedList4FindERKSsP6LLNode |
|||
fun:_Z14TestLinkedListb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:strlen |
|||
fun:_ZNSsC1EPKcRKSaIcE |
|||
fun:_Z11generateKeyv |
|||
fun:_Z14TestLinkedListb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZSteqIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZStneIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
fun:_Z14TestLinkedListb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZNK10LinkedList4FindERKSsP6LLNode |
|||
fun:_Z14TestLinkedListb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:strlen |
|||
fun:_ZNSsC1EPKcRKSaIcE |
|||
fun:_Z11generateKeyv |
|||
fun:_Z7TestBSTb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZStneIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
fun:_Z7TestBSTb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZStneIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
fun:_Z7TestBSTb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:strlen |
|||
fun:_ZNSsC1EPKcRKSaIcE |
|||
fun:_Z11generateKeyv |
|||
fun:_Z7TestBSTb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZStneIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:strlen |
|||
fun:_ZNSsC1EPKcRKSaIcE |
|||
fun:_Z11generateKeyv |
|||
fun:_Z7TestBSTb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZStltIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:strlen |
|||
fun:_ZNSsC1EPKcRKSaIcE |
|||
fun:_Z11generateKeyv |
|||
fun:_Z14TestLinkedListb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZStneIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
fun:_Z14TestLinkedListb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZStneIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
fun:_Z14TestLinkedListb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZStneIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
fun:_Z12CompareListsRK10LinkedListRSt4listISsSaISsEE |
|||
fun:_Z14TestLinkedListb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZStneIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
fun:_Z12CompareListsRK10LinkedListRSt4listISsSaISsEE |
|||
fun:_Z14TestLinkedListb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZStneIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
fun:_Z12CompareListsRK10LinkedListRSt4listISsSaISsEE |
|||
fun:_Z14TestLinkedListb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZStneIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
fun:_Z12CompareListsRK10LinkedListRSt4listISsSaISsEE |
|||
fun:_Z14TestLinkedListb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZStneIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
fun:_Z12CompareListsRK10LinkedListRSt4listISsSaISsEE |
|||
fun:_Z14TestLinkedListb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZSteqIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZStneIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
fun:_Z14TestLinkedListb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZSteqIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:strlen |
|||
fun:_ZNSsC1EPKcRKSaIcE |
|||
fun:_Z11generateKeyv |
|||
fun:_Z14TestLinkedListb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZSteqIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZSteqIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
fun:_ZSt6__findISt14_List_iteratorISsESsET_S2_S2_RKT0_St18input_iterator_tag |
|||
fun:_ZSt4findISt14_List_iteratorISsESsET_S2_S2_RKT0_ |
|||
fun:_Z14TestLinkedListb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZStneIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
fun:_Z14TestLinkedListb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:_ZNKSs7compareERKSs |
|||
fun:_ZSteqIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:strlen |
|||
fun:_ZNSsC1EPKcRKSaIcE |
|||
fun:_Z11generateKeyv |
|||
fun:_Z7TestBSTb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:strlen |
|||
fun:_ZNSsC1EPKcRKSaIcE |
|||
fun:_Z11generateKeyv |
|||
fun:_Z7TestBSTb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:strlen |
|||
fun:_ZNSsC1EPKcRKSaIcE |
|||
fun:_Z11generateKeyv |
|||
fun:_Z7TestBSTb |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:bcmp |
|||
fun:_ZNSt11char_traitsIcE7compareEPKcS2_j |
|||
fun:_ZSteqIcEN9__gnu_cxx11__enable_ifIXsrSt9__is_charIT_E7__valueEbE6__typeERKSbIS3_St11char_traitsIS3_ESaIS3_EESC_ |
|||
fun:_ZStneIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_ |
|||
fun:_ZN3tut12_GLOBAL__N_113ensure_equalsISsSsEEvPKcRKT0_RKT_ |
|||
fun:_ZN7BSTTest7initBSTER3BST |
|||
fun:_ZN3tut11test_objectI7BSTTestE4testILi2EEEvv |
|||
fun:_ZN3tut10test_groupI7BSTTestLi50EE13run_test_seh_EMNS_11test_objectIS1_EEFvvERNS2_11safe_holderIS4_EERSs |
|||
fun:_ZN3tut10test_groupI7BSTTestLi50EE9run_test_ERKSt17_Rb_tree_iteratorISt4pairIKiMNS_11test_objectIS1_EEFvvEEERNS2_11safe_holderIS7_EE |
|||
fun:_ZN3tut10test_groupI7BSTTestLi50EE8run_nextEv |
|||
fun:_ZNK3tut11test_runner23run_all_tests_in_group_ESt23_Rb_tree_const_iteratorISt4pairIKSsPNS_10group_baseEEE |
|||
fun:_ZNK3tut11test_runner9run_testsEv |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:bcmp |
|||
fun:_ZNSt11char_traitsIcE7compareEPKcS2_j |
|||
fun:_ZSteqIcEN9__gnu_cxx11__enable_ifIXsrSt9__is_charIT_E7__valueEbE6__typeERKSbIS3_St11char_traitsIS3_ESaIS3_EESC_ |
|||
fun:_ZNK10LinkedList4FindERKSsP6LLNode |
|||
fun:_ZN3tut11test_objectI14LinkedListTestE4testILi8EEEvv |
|||
fun:_ZN3tut10test_groupI14LinkedListTestLi50EE13run_test_seh_EMNS_11test_objectIS1_EEFvvERNS2_11safe_holderIS4_EERSs |
|||
fun:_ZN3tut10test_groupI14LinkedListTestLi50EE9run_test_ERKSt17_Rb_tree_iteratorISt4pairIKiMNS_11test_objectIS1_EEFvvEEERNS2_11safe_holderIS7_EE |
|||
fun:_ZN3tut10test_groupI14LinkedListTestLi50EE8run_nextEv |
|||
fun:_ZNK3tut11test_runner23run_all_tests_in_group_ESt23_Rb_tree_const_iteratorISt4pairIKSsPNS_10group_baseEEE |
|||
fun:_ZNK3tut11test_runner9run_testsEv |
|||
fun:_Z3runRKSsi |
|||
fun:main |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:bcmp |
|||
fun:_ZNSt11char_traitsIcE7compareEPKcS2_j |
|||
fun:_ZSteqIcEN9__gnu_cxx11__enable_ifIXsrSt9__is_charIT_E7__valueEbE6__typeERKSbIS3_St11char_traitsIS3_ESaIS3_EESC_ |
|||
fun:_ZSt6__findISt14_List_iteratorISsESsET_S2_S2_RKT0_St18input_iterator_tag |
|||
fun:_ZSt4findISt14_List_iteratorISsESsET_S2_S2_RKT0_ |
|||
fun:_ZN3tut11test_objectI14LinkedListTestE4testILi9EEEvv |
|||
fun:_ZN3tut10test_groupI14LinkedListTestLi50EE13run_test_seh_EMNS_11test_objectIS1_EEFvvERNS2_11safe_holderIS4_EERSs |
|||
fun:_ZN3tut10test_groupI14LinkedListTestLi50EE9run_test_ERKSt17_Rb_tree_iteratorISt4pairIKiMNS_11test_objectIS1_EEFvvEEERNS2_11safe_holderIS7_EE |
|||
fun:_ZN3tut10test_groupI14LinkedListTestLi50EE8run_nextEv |
|||
fun:_ZNK3tut11test_runner23run_all_tests_in_group_ESt23_Rb_tree_const_iteratorISt4pairIKSsPNS_10group_baseEEE |
|||
fun:_ZNK3tut11test_runner9run_testsEv |
|||
fun:_Z3runRKSsi |
|||
} |
|||
{ |
|||
<insert a suppression name here> |
|||
Memcheck:Cond |
|||
fun:bcmp |
|||
fun:_ZNSt11char_traitsIcE7compareEPKcS2_j |
|||
fun:_ZSteqIcEN9__gnu_cxx11__enable_ifIXsrSt9__is_charIT_E7__valueEbE6__typeERKSbIS3_St11char_traitsIS3_ESaIS3_EESC_ |
|||
fun:_ZN3tut11test_objectI14LinkedListTestE4testILi9EEEvv |
|||
fun:_ZN3tut10test_groupI14LinkedListTestLi50EE13run_test_seh_EMNS_11test_objectIS1_EEFvvERNS2_11safe_holderIS4_EERSs |
|||
fun:_ZN3tut10test_groupI14LinkedListTestLi50EE9run_test_ERKSt17_Rb_tree_iteratorISt4pairIKiMNS_11test_objectIS1_EEFvvEEERNS2_11safe_holderIS7_EE |
|||
fun:_ZN3tut10test_groupI14LinkedListTestLi50EE8run_nextEv |
|||
fun:_ZNK3tut11test_runner23run_all_tests_in_group_ESt23_Rb_tree_const_iteratorISt4pairIKSsPNS_10group_baseEEE |
|||
fun:_ZNK3tut11test_runner9run_testsEv |
|||
fun:_Z3runRKSsi |
|||
fun:main |
|||
} |
@ -0,0 +1,368 @@ |
|||
#include <string> |
|||
#include <iostream> |
|||
#include <set> |
|||
#include <list> |
|||
#include <algorithm> |
|||
#include <vector> |
|||
#include <time.h> |
|||
|
|||
#include "tut/tut.hpp" |
|||
#include "BST.h" |
|||
|
|||
#define NULL_NODE (static_cast<BSTNode*>(NULL)) |
|||
|
|||
using namespace std; |
|||
|
|||
bool gDoRemove = false; |
|||
extern std::string gCurrentTest; |
|||
|
|||
string generateKey(); |
|||
void CheckSubTreeOrder(BSTNode * bNode, bool isLeftLess); |
|||
void CheckBSTOrder(BST & bst); |
|||
void CompareSubTrees(BSTNode* subTree1, BSTNode* subTree2); |
|||
void CompareTrees(BST & bst1, BST & bst2); |
|||
|
|||
struct BSTTest |
|||
{ |
|||
public: |
|||
BSTTest() : BSTTestSize(6379) |
|||
{ |
|||
} |
|||
|
|||
void initBST(BST& bst) |
|||
{ |
|||
for(int i = 0; i < BSTTestSize; ++i) |
|||
{ |
|||
string key = generateKey(); |
|||
if(chosen.find(key) != chosen.end()) |
|||
{ |
|||
--i; |
|||
} |
|||
else |
|||
{ |
|||
chosen.insert(key); |
|||
BSTNode * curNode = bst.Insert(key); |
|||
tut::ensure("Insert() - Return NULL when the value was not in the tree", curNode != NULL); |
|||
tut::ensure_equals("Insert() - Returned a value which was different from the one entered", curNode->GetValue(), key); |
|||
tut::ensure_equals("Insert() - The size of the BST is not the size of the elements inserted", bst.GetSize(), (int)chosen.size()); |
|||
|
|||
curNode = bst.Insert(key); |
|||
tut::ensure_equals("Instert() - Did not return NULL when the value was in the tree", curNode, NULL_NODE); |
|||
tut::ensure_equals("Insert() - Size incremented on duplicate insertion", bst.GetSize(), (int)chosen.size()); |
|||
} |
|||
} |
|||
} |
|||
|
|||
std::string generateKey() |
|||
{ |
|||
char key[9]; |
|||
int digit = '9'-'0'+1; |
|||
int upCase = 'Z'-'A'+digit+1; |
|||
int top = 'z'-'a'+upCase+1; |
|||
for(int i = 0; i < 9; i++){ |
|||
int val = rand()%top; |
|||
if(val < digit){ |
|||
key[i] = val + '0'; |
|||
} |
|||
else if(val < upCase){ |
|||
key[i] = val - digit + 'A'; |
|||
} |
|||
else{ |
|||
key[i] = val - upCase + 'a'; |
|||
} |
|||
}//end for i
|
|||
string result(key); |
|||
return result; |
|||
} |
|||
|
|||
const int BSTTestSize; |
|||
set<string> chosen; |
|||
}; |
|||
|
|||
|
|||
void CheckSubTreeOrder(BSTNode * bNode, bool isLeftLess){ |
|||
if(bNode != NULL){ |
|||
string val = bNode->GetValue(); |
|||
BSTNode * lNode = bNode->GetLeft(); |
|||
BSTNode * rNode = bNode->GetRight(); |
|||
if(isLeftLess){ |
|||
if(lNode != NULL){ |
|||
tut::ensure("The left node had a greater value when it should have been less", lNode->GetValue() <= val); |
|||
CheckSubTreeOrder(lNode, isLeftLess); |
|||
} |
|||
if(rNode != NULL){ |
|||
tut::ensure("The right node had a lesser value when it should have been less", rNode->GetValue() >= val); |
|||
CheckSubTreeOrder(rNode, isLeftLess); |
|||
} |
|||
} |
|||
else{ |
|||
if(lNode != NULL){ |
|||
tut::ensure("The left node had a lesser value when it should have been less", lNode->GetValue() >= val); |
|||
CheckSubTreeOrder(lNode, isLeftLess); |
|||
} |
|||
if(rNode != NULL){ |
|||
tut::ensure("The right node had a greater value when it should have been less", rNode->GetValue() <= val); |
|||
CheckSubTreeOrder(rNode, isLeftLess); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
void CheckBSTOrder(BST & bst){ |
|||
BSTNode * bNode = bst.GetRoot(); |
|||
if(bNode != NULL){ |
|||
bool isLeftLess = true; |
|||
BSTNode * left = bNode->GetLeft(); |
|||
if(left != NULL){ |
|||
if(left->GetValue() > bNode->GetValue()){ |
|||
isLeftLess = false; |
|||
} |
|||
} |
|||
else{ |
|||
BSTNode * right = bNode->GetRight(); |
|||
if(right != NULL){ |
|||
if(right->GetValue() < bNode->GetValue()){ |
|||
isLeftLess = false; |
|||
} |
|||
} |
|||
} |
|||
CheckSubTreeOrder(bNode->GetLeft(), isLeftLess); |
|||
CheckSubTreeOrder(bNode->GetRight(), isLeftLess); |
|||
} |
|||
} |
|||
|
|||
void CompareSubTrees(BSTNode* subTree1, BSTNode* subTree2){ |
|||
tut::ensure_not("SubTrees are not equal", (subTree1 && !subTree2) || (subTree2 && !subTree1)); |
|||
if(subTree1 != NULL){ |
|||
tut::ensure_not("Nodes point to the same memory", subTree1 == subTree2 || subTree1 == subTree2); |
|||
tut::ensure_equals("Node values are not equal", subTree1->GetValue(), subTree2->GetValue()); |
|||
CompareSubTrees(subTree1->GetLeft(),subTree2->GetLeft()); |
|||
CompareSubTrees(subTree1->GetRight(),subTree2->GetRight()); |
|||
} |
|||
} |
|||
|
|||
void CompareTrees(BST & bst1, BST & bst2){ |
|||
tut::ensure_equals("Sizes of the two trees are not equal", bst1.GetSize(), bst2.GetSize()); |
|||
CompareSubTrees(bst1.GetRoot(), bst2.GetRoot()); |
|||
} |
|||
|
|||
namespace tut |
|||
{ |
|||
namespace |
|||
{ |
|||
typedef tut::test_group<BSTTest> tGroup; |
|||
typedef tGroup::object tObject; |
|||
tGroup group("BST"); |
|||
} |
|||
|
|||
template<> |
|||
template<> |
|||
void tObject::test<1> () |
|||
{ |
|||
set_test_name("Default Constructor"); |
|||
gCurrentTest = get_test_name(); |
|||
BST bst; |
|||
|
|||
// Root should be NULL
|
|||
tut::ensure_equals("Default Constructor - Root is not NULL", bst.GetRoot(), NULL_NODE); |
|||
|
|||
// Size should be 0
|
|||
tut::ensure_equals("Default Constructor - Size is not 0", bst.GetSize(), 0); |
|||
tut::ensure("Default Constructor - Says it's not empty", bst.IsEmpty()); |
|||
} |
|||
|
|||
template<> |
|||
template<> |
|||
void tObject::test<2> () |
|||
{ |
|||
set_test_name("Insert"); |
|||
gCurrentTest = get_test_name(); |
|||
BST bst; |
|||
initBST(bst); |
|||
|
|||
CheckBSTOrder(bst); |
|||
} |
|||
|
|||
template<> |
|||
template<> |
|||
void tObject::test<3> () |
|||
{ |
|||
set_test_name("GetSize"); |
|||
gCurrentTest = get_test_name(); |
|||
BST bst; |
|||
initBST(bst); |
|||
tut::ensure_equals("GetSize() - The size of the BST is not the size of the elements inserted", bst.GetSize(), static_cast<int>(chosen.size())); |
|||
} |
|||
|
|||
template<> |
|||
template<> |
|||
void tObject::test<4> () |
|||
{ |
|||
set_test_name("Find"); |
|||
gCurrentTest = get_test_name(); |
|||
BST bst; |
|||
initBST(bst); |
|||
|
|||
set<string>::iterator iter; |
|||
for(iter = chosen.begin(); iter != chosen.end(); iter++){ |
|||
BSTNode * curNode = bst.Find(*iter); |
|||
tut::ensure("Find() - Node not found when it should have been", curNode != NULL); |
|||
tut::ensure_equals("Find() - Returned a node with the wrong value", curNode->GetValue(), *iter); |
|||
} |
|||
|
|||
for(int i = 0; i < BSTTestSize; i++){ |
|||
string key = generateKey(); |
|||
if(chosen.find(key) == chosen.end()){ |
|||
BSTNode * curNode = bst.Find(key); |
|||
tut::ensure("Find() - Returned a node when the value was not in the tree", curNode == NULL); |
|||
} |
|||
else{ |
|||
--i; |
|||
} |
|||
} |
|||
} |
|||
|
|||
template<> |
|||
template<> |
|||
void tObject::test<5> () |
|||
{ |
|||
set_test_name("Copy Constructor"); |
|||
gCurrentTest = get_test_name(); |
|||
BST bst; |
|||
BST emptyCopyBst(bst); |
|||
initBST(bst); |
|||
|
|||
BST fullCopyBst(bst); |
|||
CompareTrees(bst,fullCopyBst); |
|||
} |
|||
|
|||
template<> |
|||
template<> |
|||
void tObject::test<6> () |
|||
{ |
|||
set_test_name("Assignment Operator"); |
|||
gCurrentTest = get_test_name(); |
|||
BST bst; |
|||
|
|||
//Assign empty to empty
|
|||
BST emptyBst; |
|||
emptyBst = bst; |
|||
CompareTrees(bst,emptyBst); |
|||
|
|||
//Return type check
|
|||
tut::ensure ("Assignment Operator: Testing return value", &emptyBst == &(emptyBst = bst)); |
|||
|
|||
//Assign empty to full
|
|||
initBST(bst); |
|||
BST fullBst; |
|||
fullBst = bst; |
|||
CompareTrees(bst,fullBst); |
|||
|
|||
//Assign to self
|
|||
fullBst = fullBst; |
|||
|
|||
//Assign full to empty
|
|||
BST& nowEmpty = fullBst; |
|||
nowEmpty = emptyBst; |
|||
CompareTrees(emptyBst, nowEmpty); |
|||
} |
|||
|
|||
template<> |
|||
template<> |
|||
void tObject::test<7> () |
|||
{ |
|||
set_test_name("Clear"); |
|||
gCurrentTest = get_test_name(); |
|||
BST bst; |
|||
initBST(bst); |
|||
|
|||
BST bst2(bst); |
|||
|
|||
BST bst3; |
|||
bst3 = bst; |
|||
|
|||
bst.Clear(); |
|||
CompareTrees(bst3, bst2); |
|||
bst3.Clear(); |
|||
|
|||
BSTNode* curNode = bst.GetRoot(); |
|||
tut::ensure_equals("GetRoot() - Returned a node after the tree was cleared", curNode, NULL_NODE); |
|||
} |
|||
|
|||
template<> |
|||
template<> |
|||
void tObject::test<8> () |
|||
{ |
|||
set_test_name ("IsEmpty"); |
|||
gCurrentTest = get_test_name(); |
|||
BST bst; |
|||
initBST(bst); |
|||
|
|||
BST bst2(bst); |
|||
bst = bst2; |
|||
BST bst3; |
|||
bst3 = bst; |
|||
bst.Clear(); |
|||
bst3.Clear(); |
|||
|
|||
tut::ensure_not("IsEmpty() - The Tree is not empty", bst2.IsEmpty()); |
|||
bst = bst2; //for the remove stage
|
|||
bst2.Clear(); |
|||
tut::ensure("IsEmpty() - The Tree is Empty", bst2.IsEmpty()); |
|||
tut::ensure_equals("GetSize() - The Tree returned a non 0 size after it was cleared", bst2.GetSize(), 0); |
|||
} |
|||
|
|||
#if TEST_BST_REMOVE |
|||
template<> |
|||
template<> |
|||
void tObject::test<9> () |
|||
{ |
|||
set_test_name ("Remove"); |
|||
gCurrentTest = get_test_name(); |
|||
if(!gDoRemove) |
|||
return; |
|||
|
|||
set<string>::iterator iter; |
|||
BSTNode * curNode; |
|||
|
|||
BST bst; |
|||
initBST(bst); |
|||
|
|||
BST bst2(bst); |
|||
bst = bst2; |
|||
BST bst3; |
|||
bst3 = bst; |
|||
bst.Clear(); |
|||
bst3.Clear(); |
|||
|
|||
bst = bst2; |
|||
bst2.Clear(); |
|||
|
|||
for(int i = 0; i < BSTTestSize; i++){ |
|||
string key = generateKey(); |
|||
if(chosen.find(key) == chosen.end()){ |
|||
ensure_not("Remove() - Returned true when the value was not in the tree", bst.Remove(key)); |
|||
} |
|||
else{ |
|||
--i; |
|||
} |
|||
} |
|||
|
|||
BSTNode * root = bst.GetRoot(); |
|||
chosen.erase(root->GetValue()); |
|||
bst.Remove(root->GetValue()); |
|||
root = NULL; |
|||
|
|||
vector<string> randomv(chosen.begin(), chosen.end()); |
|||
random_shuffle(randomv.begin(), randomv.end()); |
|||
|
|||
for(vector<string>::iterator vIter = randomv.begin(); vIter != randomv.end(); vIter++){ |
|||
ensure("Remove() - Returned false whe nthe value was in the tree", bst.Remove(*vIter)); |
|||
ensure_not("Remove() - Returned true when the value was not in the tree", bst.Remove(*vIter)); |
|||
|
|||
} |
|||
ensure_equals("Remove() - Size of tree is not 0 after removing all values", bst.GetSize(), 0); |
|||
ensure_equals("GetRoot() - Did not return NULL after removing all values", bst.GetRoot(), NULL_NODE); |
|||
} |
|||
#endif |
|||
} |
@ -0,0 +1,407 @@ |
|||
#include <string> |
|||
#include <iostream> |
|||
#include <set> |
|||
#include <list> |
|||
#include <algorithm> |
|||
#include <vector> |
|||
#include <time.h> |
|||
|
|||
#include "tut/tut.hpp" |
|||
#include "LinkedList.h" |
|||
|
|||
#define NULL_NODE (static_cast<LLNode*>(NULL)) |
|||
|
|||
using namespace std; |
|||
|
|||
bool gDoSmall = true; |
|||
extern std::string gCurrentTest; |
|||
|
|||
string generateKey(); |
|||
void CompareLists(const LinkedList & aList, list<string> & master); |
|||
|
|||
struct LinkedListTest |
|||
{ |
|||
public: |
|||
LinkedListTest() : LLTestSize((gDoSmall) ? 2827 : 8239) |
|||
{ |
|||
for(int i = 0; i < LLTestSize; ++i) |
|||
{ |
|||
string key = generateKey(); |
|||
if(chosen.find(key) != chosen.end()) |
|||
{ |
|||
--i; |
|||
} |
|||
else |
|||
{ |
|||
master.push_back(key); |
|||
chosen.insert(key); |
|||
} |
|||
} |
|||
} |
|||
|
|||
void initList (LinkedList& aList) |
|||
{ |
|||
list<string>::iterator iter; |
|||
for(iter = master.begin(); iter != master.end(); ++iter) |
|||
{ |
|||
LLNode* curNode = aList.Insert(*iter, NULL); |
|||
tut::ensure ("Insert() - The returned node is NULL", curNode != NULL_NODE); |
|||
tut::ensure_equals ("Insert() - The returned node had the wrong value", curNode->GetValue(), *iter); |
|||
} |
|||
} |
|||
|
|||
void sortedInitList (LinkedList& aList) |
|||
{ |
|||
aList.Clear(); |
|||
int count = 0; |
|||
|
|||
list<string>::iterator iter; |
|||
for(iter = master.begin(); iter != master.end(); ++iter) |
|||
{ |
|||
LLNode* curNode = aList.GetLast(); |
|||
while(curNode != NULL && 0 < curNode->GetValue().compare(*iter)) |
|||
{ |
|||
curNode = curNode->GetPrevious(); |
|||
} |
|||
aList.Insert(*iter, curNode); |
|||
|
|||
tut::ensure_equals("Insert() - Size != number of elements inserted", aList.GetSize(), ++count); |
|||
} |
|||
} |
|||
|
|||
string generateKey() |
|||
{ |
|||
static const int kKeyLength = 9; |
|||
char key[kKeyLength]; |
|||
for (int i = 0; i < kKeyLength; ++i) |
|||
key[i] = '\0'; |
|||
|
|||
int digit = '9'-'0'+1; |
|||
int upCase = 'Z'-'A'+digit+1; |
|||
int top = 'z'-'a'+upCase+1; |
|||
for(int i = 0; i < kKeyLength; ++i) |
|||
{ |
|||
int val = rand()%top; |
|||
if(val < digit) |
|||
{ |
|||
key[i] = val + '0'; |
|||
} |
|||
else if(val < upCase) |
|||
{ |
|||
key[i] = val - digit + 'A'; |
|||
} |
|||
else |
|||
{ |
|||
key[i] = val - upCase + 'a'; |
|||
} |
|||
} |
|||
string result(key); |
|||
return result; |
|||
} |
|||
|
|||
const int LLTestSize; |
|||
|
|||
set<string> chosen; |
|||
list<string> master; |
|||
}; |
|||
|
|||
void CompareLists(const LinkedList & aList, list<string> & master){ |
|||
const LLNode * curNode = aList.GetFirst(); |
|||
|
|||
list<string>::iterator iter; |
|||
for(iter = master.begin(); iter != master.end() && curNode != NULL; iter++, curNode = curNode->GetNext()) |
|||
{ |
|||
tut::ensure_equals("GetValue() - The values are not the order which they should be", curNode->GetValue(), *iter); |
|||
} |
|||
|
|||
tut::ensure_equals("GetNext() - The list is longer than it should be", curNode, NULL_NODE); |
|||
tut::ensure("GetNext() - The list is shorter than it should be", iter == master.end()); |
|||
} |
|||
|
|||
namespace tut |
|||
{ |
|||
namespace |
|||
{ |
|||
typedef tut::test_group<LinkedListTest> tGroup; |
|||
typedef tGroup::object tObject; |
|||
tGroup group("LinkedList"); |
|||
} |
|||
|
|||
template<> |
|||
template<> |
|||
void tObject::test<1> () |
|||
{ |
|||
set_test_name ("Default Constructor"); |
|||
gCurrentTest = get_test_name(); |
|||
|
|||
LinkedList aList; |
|||
tut::ensure_equals("Default Constructor - List size != 0", aList.GetSize(), 0); |
|||
tut::ensure_equals("Default Constructor - first != NULL", aList.GetFirst(), NULL_NODE); |
|||
tut::ensure_equals("Default Constructor - last != NULL", aList.GetLast(), NULL_NODE); |
|||
} |
|||
|
|||
template<> |
|||
template<> |
|||
void tObject::test<2> () |
|||
{ |
|||
set_test_name ("Clear"); |
|||
gCurrentTest = get_test_name(); |
|||
|
|||
LinkedList aList; |
|||
aList.Clear(); |
|||
|
|||
aList.Insert("To Remove", NULL); |
|||
aList.Clear(); |
|||
|
|||
tut::ensure_equals("Clear() - size != 0", aList.GetSize(), 0); |
|||
tut::ensure_equals("Clear() - first != NULL", aList.GetFirst(), NULL_NODE); |
|||
tut::ensure_equals("Clear() - last != NULL", aList.GetLast(), NULL_NODE); |
|||
} |
|||
|
|||
template<> |
|||
template<> |
|||
void tObject::test<3> () |
|||
{ |
|||
set_test_name ("Basic Insert Tests"); |
|||
gCurrentTest = get_test_name(); |
|||
|
|||
LinkedList aList; |
|||
initList(aList); |
|||
master.reverse(); |
|||
|
|||
tut::ensure_equals("Insert() - List size != number of strings inserted", aList.GetSize(), static_cast<int>(master.size())); |
|||
|
|||
tut::ensure("GetLast() - List was empty", aList.GetLast() != NULL); |
|||
tut::ensure_equals("GetLast() - Returned the wrong value", aList.GetLast()->GetValue(), master.back()); |
|||
tut::ensure_equals("GetLast() - The returned node had a next", aList.GetLast()->GetNext(), NULL_NODE); |
|||
|
|||
tut::ensure("GetFirst() - List was empty", aList.GetFirst() != NULL); |
|||
tut::ensure_equals("GetFirst() - Returned the wrong value", aList.GetFirst()->GetValue(), master.front()); |
|||
tut::ensure_equals("GetFirst() - The returned node had a next", aList.GetFirst()->GetPrevious(), NULL_NODE); |
|||
} |
|||
|
|||
template<> |
|||
template<> |
|||
void tObject::test<4> () |
|||
{ |
|||
set_test_name ("Insert"); |
|||
gCurrentTest = get_test_name(); |
|||
|
|||
master.reverse(); |
|||
|
|||
LinkedList aList; |
|||
aList.Clear(); |
|||
|
|||
int count = 0; |
|||
list<string>::iterator iter; |
|||
for(iter = master.begin(); iter != master.end(); iter++) |
|||
{ |
|||
LLNode* curNode = aList.GetLast(); |
|||
while(curNode != NULL && curNode->GetValue().compare(*iter) > 0) |
|||
{ |
|||
curNode = curNode->GetPrevious(); |
|||
} |
|||
aList.Insert(*iter, curNode); |
|||
|
|||
ensure_equals("Size != number of elements inserted", aList.GetSize(), ++count); |
|||
} |
|||
|
|||
sortedInitList(aList); |
|||
list<string> sorted(master.begin(), master.end()); |
|||
sorted.sort(); |
|||
|
|||
tut::ensure_equals("Insert() - Size != Number of strings inserted", aList.GetSize(), static_cast<int>(sorted.size())); |
|||
|
|||
CompareLists(aList, sorted); |
|||
} |
|||
|
|||
template<> |
|||
template<> |
|||
void tObject::test<5> () |
|||
{ |
|||
set_test_name ("Copy Constructor"); |
|||
gCurrentTest = get_test_name(); |
|||
|
|||
LinkedList aList; |
|||
LinkedList emptyCopy(aList); |
|||
|
|||
initList(aList); |
|||
master.reverse(); |
|||
sortedInitList(aList); |
|||
|
|||
list<string> sorted(master.begin(), master.end()); |
|||
sorted.sort(); |
|||
|
|||
LinkedList fullCopyList(aList); |
|||
|
|||
tut::ensure_equals("Copy Constructor - Size != size of original list", aList.GetSize(), fullCopyList.GetSize()); |
|||
|
|||
aList.Clear(); |
|||
CompareLists(fullCopyList, sorted); |
|||
} |
|||
|
|||
template<> |
|||
template<> |
|||
void tObject::test<6> () |
|||
{ |
|||
set_test_name ("Assignment Operator"); |
|||
gCurrentTest = get_test_name(); |
|||
|
|||
LinkedList aList; |
|||
|
|||
//Assign an empty to an empty
|
|||
LinkedList emptyList; |
|||
emptyList = aList; |
|||
|
|||
//Return type check
|
|||
tut::ensure ("Assignment Operator: Testing return value", &emptyList == &(emptyList = aList)); |
|||
|
|||
//Assign full to an empty
|
|||
initList(aList); |
|||
master.reverse(); |
|||
sortedInitList(aList); |
|||
|
|||
list<string> sorted(master.begin(), master.end()); |
|||
sorted.sort(); |
|||
|
|||
LinkedList fullList; |
|||
fullList = aList; |
|||
tut::ensure_equals("Assignment Operator - Size != size of original list when going from empty to full", fullList.GetSize(), aList.GetSize()); |
|||
|
|||
aList.Clear(); |
|||
CompareLists(fullList, sorted); |
|||
|
|||
//Self assignment
|
|||
fullList = fullList; |
|||
tut::ensure_equals("Assignment Operator - Size != size of original list on self assignment", fullList.GetSize(), sorted.size()); |
|||
CompareLists(fullList, sorted); |
|||
|
|||
//Assign full to empty
|
|||
LinkedList& nowEmpty = fullList; |
|||
nowEmpty = aList; |
|||
tut::ensure_equals("Assignment Operator - Size != size of original list when going from full to empty", nowEmpty.GetSize(), aList.GetSize()); |
|||
} |
|||
|
|||
template<> |
|||
template<> |
|||
void tObject::test<7> () |
|||
{ |
|||
set_test_name ("IsEmpty"); |
|||
gCurrentTest = get_test_name(); |
|||
|
|||
LinkedList aList; |
|||
initList(aList); |
|||
master.reverse(); |
|||
sortedInitList(aList); |
|||
|
|||
list<string> sorted(master.begin(), master.end()); |
|||
sorted.sort(); |
|||
|
|||
LinkedList cList; |
|||
cList = aList; |
|||
|
|||
tut::ensure_equals("Assignment Operator - Size != size of original list", cList.GetSize(), aList.GetSize()); |
|||
|
|||
aList.Clear(); |
|||
|
|||
CompareLists(cList, sorted); |
|||
|
|||
tut::ensure_not("IsEmpty() - returned true when list was not empty", cList.IsEmpty()); |
|||
tut::ensure("IsEmpty() - returned false when list was empty", aList.IsEmpty()); |
|||
} |
|||
|
|||
template<> |
|||
template<> |
|||
void tObject::test<8> () |
|||
{ |
|||
set_test_name ("Find"); |
|||
gCurrentTest = get_test_name(); |
|||
|
|||
LinkedList aList; |
|||
initList(aList); |
|||
master.reverse(); |
|||
|
|||
list<string> sorted(master.begin(), master.end()); |
|||
sorted.sort(); |
|||
|
|||
list<string>::iterator iter; |
|||
for(iter = master.begin(); iter != master.end(); iter++){ |
|||
LLNode* curNode = aList.Find(*iter, NULL); |
|||
|
|||
tut::ensure("Find() - Find returned NULL when it shouldn't have", curNode != NULL); |
|||
tut::ensure_equals("Find() - Find returned the wrong value", curNode->GetValue(), *iter); |
|||
}//end for iter
|
|||
|
|||
LLNode* curNode = NULL; |
|||
curNode = aList.Find(master.back(), aList.GetLast()); |
|||
|
|||
tut::ensure_equals("Find() - Find is starting its search on the node given, not the node after the one given", curNode, NULL_NODE); |
|||
|
|||
curNode = aList.GetFirst(); |
|||
int attempt = -1; |
|||
while(curNode != NULL){ |
|||
tut::ensure_equals("Find() - Find is returning a value when it should be returning NULL", aList.Find(curNode->GetValue(), curNode), NULL_NODE); |
|||
curNode = curNode->GetNext(); |
|||
tut::ensure("GetNext() - Infinite loop hit", attempt++ <= LLTestSize); |
|||
} |
|||
|
|||
iter = master.begin(); |
|||
iter++; |
|||
curNode = aList.Find(*iter, NULL); |
|||
tut::ensure("Find() - Returned NULL when it should not have", curNode != NULL); |
|||
curNode = aList.Find(master.front(), curNode); |
|||
tut::ensure_equals("Find() - Did not return NULL when the item was in the list, but before the search point", curNode, NULL_NODE); |
|||
|
|||
string key = generateKey(); |
|||
while(chosen.find(key) != chosen.end()){ |
|||
key = generateKey(); |
|||
} |
|||
curNode = aList.Find(key, NULL); |
|||
tut::ensure_equals("Find() - Find is returning a value when the value is not in the list", curNode, NULL_NODE); |
|||
} |
|||
|
|||
template<> |
|||
template<> |
|||
void tObject::test<9> () |
|||
{ |
|||
set_test_name ("Remove"); |
|||
gCurrentTest = get_test_name(); |
|||
|
|||
LinkedList aList; |
|||
initList(aList); |
|||
|
|||
master.reverse(); |
|||
list<string> sorted(master.begin(), master.end()); |
|||
sorted.sort(); |
|||
|
|||
for(int i = 0; i < LLTestSize/2; i++) |
|||
{ |
|||
ensure_not("Internal Error", master.empty()); |
|||
master.pop_back(); |
|||
aList.Remove(aList.GetLast()); |
|||
ensure_equals("GetSize() Did not return the correct size after a remove", aList.GetSize(), static_cast<int>(master.size())); |
|||
} |
|||
|
|||
for(set<string>::iterator setIter = chosen.begin(); setIter != chosen.end(); ++setIter) |
|||
{ |
|||
LLNode* curNode = aList.Find(*setIter, NULL); |
|||
list<string>::iterator iter = find(master.begin(), master.end(), *setIter); |
|||
ensure("Find() - Returned a value which was removed", iter != master.end() || curNode == NULL); |
|||
ensure("Find() - Returned NULL when the value was in the list", iter == master.end() || curNode != NULL); |
|||
ensure("Find() - Find returned the wrong value", curNode == NULL || curNode->GetValue() == *setIter); |
|||
} |
|||
|
|||
master.sort(); |
|||
list<string>::iterator iter; |
|||
for(iter = master.begin(); iter != master.end(); ++iter) |
|||
{ |
|||
aList.Remove(aList.Find(*iter,0)); |
|||
} |
|||
|
|||
ensure_equals("Remove() - List did not return a size of 0 when the list was empty", aList.GetSize(), 0); |
|||
ensure("Remove() - List should be empty", aList.IsEmpty()); |
|||
ensure_equals("Remove() - List should have no first node", aList.GetFirst(), NULL_NODE); |
|||
ensure_equals("Remove() - List should have no last node", aList.GetLast(), NULL_NODE); |
|||
} |
|||
} |
|||
|
@ -0,0 +1,111 @@ |
|||
#include <csignal> |
|||
#include <boost/program_options.hpp> |
|||
#include <boost/cstdlib.hpp> |
|||
#include "tut/tut.hpp" |
|||
#include "tut/tut_reporter.hpp" |
|||
|
|||
///@file
|
|||
///All tests are auto-included through linking thanks to the TUT Unit Test frame-work
|
|||
///@see tut
|
|||
|
|||
namespace tut |
|||
{ |
|||
test_runner_singleton gRunner; |
|||
} |
|||
|
|||
namespace |
|||
{ |
|||
const std::string gTestGroupDefault = "all"; |
|||
const int gTestDefault = -1; |
|||
} |
|||
|
|||
std::string gCurrentTest = ""; |
|||
|
|||
|
|||
void segfault_handler(int num) |
|||
{ |
|||
std::cout << "Died during the test \"" << gCurrentTest << "\"" << std::endl; |
|||
exit(-1); |
|||
} |
|||
|
|||
|
|||
namespace po = boost::program_options; |
|||
|
|||
void print_tests () |
|||
{ |
|||
std::cout << "CS 240 Collections Pass Off" << std::endl; |
|||
std::cout << std::endl << "Tests: " << std::endl; |
|||
|
|||
tut::groupnames names = tut::runner.get().list_groups(); |
|||
tut::groupnames::iterator nameItr = names.begin(); |
|||
for (; nameItr != names.end(); ++nameItr) |
|||
std::cout << "\t\"" << *nameItr << "\"" << std::endl; |
|||
} |
|||
|
|||
bool run (const std::string &testGroup, int test) |
|||
{ |
|||
std::cout << "CS 240 Collections Pass Off" << std::endl; |
|||
tut::reporter reportPresenter; |
|||
tut::runner.get().set_callback(&reportPresenter); |
|||
|
|||
if (testGroup == gTestGroupDefault) |
|||
tut::runner.get().run_tests (); |
|||
else if (test == gTestDefault) |
|||
tut::runner.get().run_tests (testGroup); |
|||
else |
|||
tut::runner.get().run_test (testGroup, test); |
|||
|
|||
std::cout << std::endl << "Finished" << std::endl; |
|||
|
|||
return true; |
|||
} |
|||
|
|||
|
|||
int main(int argc, char* argv[]) |
|||
{ |
|||
bool success = true; |
|||
|
|||
try |
|||
{ |
|||
std::string testGroup; |
|||
int test; |
|||
|
|||
po::options_description optionList ("Allowed options"); |
|||
optionList.add_options() |
|||
("test,t", po::value<std::string>(&testGroup)->default_value(gTestGroupDefault), "Selects which test group to run") |
|||
("number,n", po::value<int>(&test)->default_value(gTestDefault), "Select a test within a group") |
|||
("list-tests,l", "List available tests") |
|||
("disable-seg,d", "Disable the seg-fault handler to make debugging easier") |
|||
("help,h", "Prints this message") |
|||
; |
|||
|
|||
po::positional_options_description positionalOptions; |
|||
positionalOptions.add("test", -1); |
|||
|
|||
po::variables_map parsedOptions; |
|||
po::store (po::command_line_parser (argc, argv).options(optionList).positional(positionalOptions).run(), parsedOptions); |
|||
po::notify (parsedOptions); |
|||
|
|||
if (parsedOptions.count("disable-seg") == 0) |
|||
std::signal(SIGSEGV, segfault_handler); |
|||
|
|||
if (0 < parsedOptions.count("help")) |
|||
{ |
|||
std::cout << "CS 240 Collections Pass Off" << std::endl; |
|||
std::cout << optionList << std::endl; |
|||
} |
|||
else if (0 < parsedOptions.count("list-tests")) |
|||
print_tests(); |
|||
else |
|||
success = run(testGroup, test); |
|||
|
|||
} |
|||
catch (std::exception &e) |
|||
{ |
|||
std::cerr << e.what() << std::endl; |
|||
std::cerr << "Abborting" << std::endl; |
|||
success = false;; |
|||
} |
|||
|
|||
return success? boost::exit_success : boost::exit_failure; |
|||
} |
@ -0,0 +1,509 @@ |
|||
Documentation TUT How-To minimum steps to make TUT work for you |
|||
|
|||
What is TUT |
|||
|
|||
TUT is a pure C++ unit test framework. Its name - TUT - stands for |
|||
Template Unit Tests. |
|||
|
|||
Features |
|||
|
|||
TUT provides all features required for unit testing: |
|||
|
|||
* Similar tests can be grouped together into test groups. Each |
|||
test group has its unique name and is located in a separate |
|||
compilation unit. One group can contain almost unlimited number |
|||
of tests (actually, the limit is the compiler template |
|||
recursion depth). |
|||
* User can run all the tests (regression), or just some selected |
|||
groups or even some tests in these groups. |
|||
* TUT provides special template functions to check the condition |
|||
validity at run-time and to force test failure if required. |
|||
Since C++ doesn't provide a facility for obtaining stack trace |
|||
of the throwed exception and TUT avoids macros, those functions |
|||
accept string marker to allow users easely determine the source |
|||
of exception. |
|||
* TUT contains callback that can be implemented by the calling code |
|||
to integrate with an IDE, for example. Callbacks tell listener |
|||
when a new test run started, when test runner switches to the |
|||
next tests group, when a test was completed (and what result it |
|||
has), and when test run was finished. The callbacks allow users |
|||
to produce their own visualization format for test process and results. |
|||
* Being a template library, it doesn't need compilation; just |
|||
include the <tut.h> header into the test modules. |
|||
|
|||
TUT tests organization |
|||
|
|||
Test application |
|||
|
|||
C++ produces executable code, so tests have to be compiled into a single |
|||
binary called test application. The application can be built in automated |
|||
mode to perform nightly tests. They also can be built manually when a |
|||
developer hunts for bugs. |
|||
|
|||
The test application contains tests, organized into test groups. |
|||
|
|||
Test groups |
|||
|
|||
The functionality of a tested application can be divided into a few separate |
|||
function blocks (e.g. User Rights, Export, Processing, ...). It is natural |
|||
to group together tests for each block. TUT invokes this test group. Each |
|||
test group has a unique human-readable name and normally is located in a |
|||
separate file. |
|||
|
|||
Tests |
|||
|
|||
Each single test usually checks only one specific element of functionality. |
|||
For example, for a container a test could check whether size() call |
|||
returns zero after the successful call to the clear() method. |
|||
|
|||
Writing simple test |
|||
|
|||
Preamble |
|||
|
|||
You are going to create a new class for your application. You decided to |
|||
write tests for the class to be sure it works while you are developing or, |
|||
possibly, enhancing it. Let's consider your class is shared pointer: |
|||
std::auto_ptr-alike type that shares the same object among instances. |
|||
|
|||
Prior to test writing, you should decide what to test. Maximalist's |
|||
approach requires to write so many tests that altering any single |
|||
line of your production code will break at least one of them. |
|||
Minimalist's approach allows one to write tests only for the most |
|||
general or the most complex use cases. The truth lies somewhere in |
|||
between, but only you, developer, know where. You should prepare |
|||
common successful and unsuccessful scenarios, and the scenarios for |
|||
testing any other functionality you believe might be broken in some way. |
|||
|
|||
For our shared_ptr we obviosly should test constructors, assignment operators, referencing and passing ownership. |
|||
|
|||
Skeleton |
|||
|
|||
If you don't have any implemented class to test yet, it would be good to |
|||
implement it as a set of stubs for a first time. Thus you'll get an |
|||
interface, and be able to write your tests. Yes, that's correct: you |
|||
should write your tests before writing code! First of all, writing tests |
|||
often helps to understand oddities in the current interface, and fix it. |
|||
Secondly, with the stubs all your tests will fail, so you'll be sure |
|||
they do their job. |
|||
|
|||
Creating Test Group |
|||
|
|||
Since we're writing unit tests, it would be a good idea to group the |
|||
tests for our class in one place to be able to run them separately. |
|||
It's also natural in C++ to place all the grouped tests into one |
|||
compilation unit (i.e. source file). So, to begin, we should create |
|||
a new file. Let's call it test_shared_ptr.cpp. (Final variant of the |
|||
test group can be found in examples/shared_ptr subdirectory of the |
|||
distribution package) |
|||
|
|||
// test_shared_ptr.cpp |
|||
#include <tut.h> |
|||
|
|||
namespace tut |
|||
{ |
|||
}; |
|||
|
|||
|
|||
As you see, you need to include TUT header file (as expected) and |
|||
use namespace tut for tests. You may also use anonymous namespace if |
|||
your compiler allows it (you will need to instantiate methods from |
|||
tut namespace and some compilers refuse to place such instantiations |
|||
into the anonymous namespace). |
|||
|
|||
A test group in TUT framework is described by the special template |
|||
test_group<T>. The template parameter T is a type that will hold all |
|||
test-specific data during the test execution. Actually, the data |
|||
stored in T are member data of the test. Test object is inherited |
|||
from T, so any test can refer to the data in T as its member data. |
|||
|
|||
For simple test groups (where all data are stored in test local |
|||
variables) type T is an empty struct. |
|||
|
|||
#include <tut.h> |
|||
|
|||
namespace tut |
|||
{ |
|||
struct shared_ptr_data |
|||
{ |
|||
}; |
|||
} |
|||
|
|||
But when tests have complex or repeating creation phase, you may put |
|||
data members into the T and provide constructor (and, if required, |
|||
destructor) for it. For each test, a new instance of T will be |
|||
created. To prepare your test for execution TUT will use default |
|||
constructor. Similarly, after the test has been finished, TUT |
|||
calls the destructor to clean up T. I.e.: |
|||
|
|||
#include <tut.h> |
|||
|
|||
namespace tut |
|||
{ |
|||
struct complex_data |
|||
{ |
|||
connection* con; |
|||
complex_data(){ con = db_pool.get_connection(); } |
|||
~complex_data(){ db_pool.release_connection(con); } |
|||
}; |
|||
|
|||
// each test from now will have con data member initialized |
|||
// by constructor: |
|||
... |
|||
con->commit(); |
|||
... |
|||
|
|||
|
|||
What will happen if the constructor throws an exception? TUT will treat |
|||
it as if test itself failed with exception, so this test will |
|||
not be executed. You'll see an exception mark near the test, and |
|||
if the constructor throwed something printable, a certain message will appear. |
|||
|
|||
Exception in destructor is threated a bit different. Reaching destruction |
|||
phase means that the test is passed, so TUT marks test with warning |
|||
status meaning that test itself was OK, but something bad has happend |
|||
after the test. |
|||
|
|||
Well, all we have written so far is just a type declaration. To work |
|||
with a group we have to have an object, so we must create the test group |
|||
object. Since we need only one test group object for each unit, we can |
|||
(and should, actually) make this object static. To prevent name clash with |
|||
other test group objects in the namespace tut, we should provide a |
|||
descriptive name, or, alternatively, we may put it into the anonymous |
|||
namespace. The former is more correct, but a descriptive name usually works |
|||
well too, unless you're too terse in giving names to objects. |
|||
|
|||
#include <tut.h> |
|||
|
|||
namespace tut |
|||
{ |
|||
struct shared_ptr_data |
|||
{ |
|||
|
|||
}; |
|||
|
|||
typedef test_group<shared_ptr_data> tg; |
|||
tg shared_ptr_group("shared_ptr"); |
|||
}; |
|||
|
|||
As you see, any test group accepts a single parameter - its human-readable |
|||
name. This name is used to identify the group when a programmer wants to |
|||
execute all tests or a single test within the group. So this name shall |
|||
also be descriptive enough to avoid clashes. Since we're writing tests |
|||
for a specific unit, it's enough to name it after the unit name. |
|||
|
|||
Test group constructor will be called at unspecified moment at the test |
|||
application startup. The constructor performs self-registration; it calls |
|||
tut::runner and asks it to store the test group object name and location. |
|||
Any other test group in the system undergoes the same processing, i.e. |
|||
each test group object registers itself. Thus, test runner can iterate |
|||
all test groups or execute any test group by its name. |
|||
|
|||
Newly created group has no tests associated with it. To be more precise, |
|||
it has predefined set of dummy tests. By default, there are 50 tests in a |
|||
group, including dummy ones. To create a test group with higher volume |
|||
(e.g. when tests are generated by a script and their number is higher) |
|||
we must provide a higher border of test group size when it is instantiated: |
|||
|
|||
#include <tut.h> |
|||
|
|||
namespace tut |
|||
{ |
|||
struct huge_test_data |
|||
{ |
|||
}; |
|||
|
|||
// test group with maximum 500 tests |
|||
typedef test_group<huge_test_data,500> testgroup; |
|||
testgroup huge_test_testgroup("huge group"); |
|||
}; |
|||
|
|||
|
|||
Note also, that your compiler will possibly need a command-line switch |
|||
or pragma to enlarge recursive instantiation depth. For g++, for |
|||
example, you should specify at least --ftemplate-depth-501 to increase |
|||
the depth. For more information see your compiler documentation. |
|||
|
|||
Creating Tests |
|||
|
|||
Now it's time to fill our test group with content. |
|||
|
|||
In TUT, all tests have unique numbers inside the test group. Some |
|||
people believe that textual names better describe failed tests in |
|||
reports. I agree; but in reality C++ templates work good with numbers |
|||
because they are compile-time constants and refuse to do the same |
|||
with strings, since strings are in fact addresses of character |
|||
buffers, i.e. run-time data. |
|||
|
|||
As I mentioned above, our test group already has a few dummy tests; |
|||
and we can replace any of them with something real just by writing |
|||
our own version: |
|||
|
|||
#include <tut.h> |
|||
|
|||
namespace tut |
|||
{ |
|||
struct shared_ptr_data{}; |
|||
|
|||
typedef test_group<shared_ptr_data> testgroup; |
|||
typedef testgroup::object testobject; |
|||
testgroup shared_ptr_testgroup("shared_ptr"); |
|||
|
|||
template<> |
|||
template<> |
|||
void testobject::test<1>() |
|||
{ |
|||
// do nothing test |
|||
} |
|||
}; |
|||
|
|||
|
|||
So far this test does nothing, but it's enough to illustrate the concept. |
|||
|
|||
All tests in the group belong to the type test_group<T>::object. This |
|||
class is directly inherited from our test data structure. In our case, it is |
|||
|
|||
class object : public shared_ptr_data { ... } |
|||
|
|||
This allows to access members of the data structure directly, since at |
|||
the same time they are members of the object type. We also typedef the |
|||
type with testobject for brevity. |
|||
|
|||
We mark our test with number 1. Previously, test group had a dummy test |
|||
with the same number, but now, since we've defined our own version, it |
|||
replaces the dummy test as more specialized one. It's how C++ template |
|||
ordering works. |
|||
|
|||
The test we've written always succeeds. Successful test returns with no |
|||
exceptions. Unsuccessful one either throws an exception, or fails at |
|||
fail() or ensure() methods (which anyway just throw the exception when failed). |
|||
|
|||
First real test |
|||
|
|||
Well, now we know enough to write the first real working test. This test |
|||
will create shared_ptr instances and check their state. We will define a |
|||
small structure (keepee) to use it as shared_ptr stored object type. |
|||
|
|||
#include <tut.h> |
|||
#include <shared_ptr.h> |
|||
|
|||
namespace tut |
|||
{ |
|||
struct shared_ptr_data |
|||
{ |
|||
struct keepee{ int data; }; |
|||
}; |
|||
|
|||
typedef test_group<shared_ptr_data> testgroup; |
|||
typedef testgroup::object testobject; |
|||
testgroup shared_ptr_testgroup("shared_ptr"); |
|||
|
|||
/** |
|||
* Checks default constructor. |
|||
*/ |
|||
template<> |
|||
template<> |
|||
void testobject::test<1>() |
|||
{ |
|||
shared_ptr<keepee> def; |
|||
ensure("null",def.get() == 0); |
|||
} |
|||
}; |
|||
|
|||
|
|||
That's all! The first line creates shared_ptr. If constructor throws |
|||
an exception, test will fail (exceptions, including '...', are catched |
|||
by the TUT framework). If the first line succeeds, we must check |
|||
whether the kept object is null one. To do this, we use test object |
|||
member function ensure(), which throws std::logic_error with a given |
|||
message if its second argument is not true. Finally, if destructor of |
|||
shared_ptr fails with exception, TUT also will report this test as failed. |
|||
|
|||
It's equally easy to write a test for the scenario where we expect to get |
|||
an exception: let's consider our class should throw an exception if it |
|||
has no stored object, and the operator -> is called. |
|||
|
|||
/** |
|||
* Checks operator -> throws instead of returning null. |
|||
*/ |
|||
template<> |
|||
template<> |
|||
void testobject::test<2>() |
|||
{ |
|||
try |
|||
{ |
|||
shared_ptr<keepee> sp; |
|||
sp->data = 0; |
|||
fail("exception expected"); |
|||
} |
|||
catch( const std::runtime_error& ex ) |
|||
{ |
|||
// ok |
|||
} |
|||
} |
|||
|
|||
|
|||
Here we expect the std::runtime_error. If operator doesn't throw it, |
|||
we'll force the test to fail using another member function: fail(). It |
|||
just throws std::logic_error with a given message. If operator throws |
|||
anything else, our test will fail too, since we intercept only |
|||
std::runtime_error, and any other exception means the test has failed. |
|||
|
|||
NB: our second test has number 2 in its name; it can, actually, be any |
|||
in range 1..Max; the only requirement is not to write tests with the |
|||
same numbers. If you did, compiler will force you to fix them anyway. |
|||
|
|||
And finally, one more test to demonstrate how to use the |
|||
ensure_equals template member function: |
|||
|
|||
/** |
|||
* Checks keepee counting. |
|||
*/ |
|||
template<> |
|||
template<> |
|||
void testobject::test<3>() |
|||
{ |
|||
shared_ptr<keepee> sp1(new keepee()); |
|||
shared_ptr<keepee> sp2(sp1); |
|||
ensure_equals("second copy at sp1",sp1.count(),2); |
|||
ensure_equals("second copy at sp2",sp2.count(),2); |
|||
} |
|||
|
|||
|
|||
The test checks if the shared_ptr correctly counts references during |
|||
copy construction. What's interesting here is the template member |
|||
ensure_equals. It has an additional functionality comparing with similar |
|||
call ensure("second_copy",sp1.count()==2); it uses operator == to check |
|||
the equality of the two passed parameters and, what's more important, it |
|||
uses std::stream to format the passed parameters into a human-readable |
|||
message (smth like: "second copy: expected 2, got 1"). It means that |
|||
ensure_equals cannot be used with the types that don't have operator <<; |
|||
but for those having the operator it provides much more informational message. |
|||
|
|||
In contrast to JUnit assertEquals, where the expected value goes before |
|||
the actual one, ensure_equals() accepts the expected after the actual |
|||
value. I believe it's more natural to read ensure_equals("msg", count, 5) |
|||
as "ensure that count equals to 5" rather than JUnit's |
|||
"assert that 5 is the value of the count". |
|||
|
|||
Running tests |
|||
|
|||
Tests are already written, but an attempt to run them will be unsuccessful. |
|||
We need a few other bits to complete the test application. |
|||
|
|||
First of all, we need a main() method, simply because it must be in all |
|||
applications. Secondly, we need a test runner singleton. Remember I said |
|||
each test group should register itself in singleton? So, we need that |
|||
singleton. And, finally, we need a kind of a callback handler to visualize |
|||
our test results. |
|||
|
|||
The design of TUT doesn't strictly set a way the tests are visualized; |
|||
instead, it provides an opportunity to get the test results by means of |
|||
callbacks. Moreover it allows user to output the results in any format he |
|||
prefers. Of course, there is a "reference implementation" in the |
|||
example/subdirectory of the project. |
|||
|
|||
Test runner singleton is defined in tut.h, so all we need to activate it |
|||
is to declare an object of the type tut::test_runner_singleton in the main |
|||
module with a special name tut::runner. |
|||
|
|||
Now, with the test_runner we can run tests. Singleton has method get() |
|||
returning a reference to an instance of the test_runner class, which in |
|||
turn has methods run_tests() to run all tests in all groups, |
|||
run_tests(const std::string& groupname) to run all tests in a given group |
|||
and run_test(const std::string& grp,int n) to run one test in the specified group. |
|||
|
|||
// main.cpp |
|||
#include <tut.h> |
|||
|
|||
namespace tut |
|||
{ |
|||
test_runner_singleton runner; |
|||
} |
|||
|
|||
int main() |
|||
{ |
|||
// run all tests in all groups |
|||
runner.get().run_tests(); |
|||
|
|||
// run all tests in group "shared_ptr" |
|||
runner.get().run_tests("shared_ptr"); |
|||
|
|||
// run test number 5 in group "shared_ptr" |
|||
runner.get().run_test("shared_ptr",5); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
It's up to user to handle command-line arguments or GUI messages and map those |
|||
arguments/messages to actual calls to test runner. Again, as you see, TUT |
|||
doesn't restrict user here. |
|||
|
|||
But, the last question is still unanswered: how do we get our test results? |
|||
The answer lies inside tut::callback interface. User shall create its subclass, |
|||
and write up to three simple methods. He also can omit any method since they |
|||
have default no-op implementation. Each corresponding method is called in the |
|||
following cases: |
|||
|
|||
* a new test run started; |
|||
* test finished; |
|||
* test run finished. |
|||
|
|||
Here is a minimal implementation: |
|||
|
|||
class visualizator : public tut::callback |
|||
{ |
|||
public: |
|||
void run_started(){ } |
|||
|
|||
void test_completed(const tut::test_result& tr) |
|||
{ |
|||
// ... show test result here ... |
|||
} |
|||
|
|||
void run_completed(){ } |
|||
}; |
|||
|
|||
The most important is the test_completed() method; its parameter has type |
|||
test_result, and contains everything about the finished test, from its group |
|||
name and number to the exception message, if any. Member result is an enum |
|||
that contains status of the test: ok, fail or ex. Take a look at the |
|||
examples/basic/main.cpp for more complete visualizator. |
|||
|
|||
Visualizator should be passed to the test_runner before run. Knowing that, |
|||
we are ready to write the final version of our main module: |
|||
|
|||
// main.cpp |
|||
#include <tut.h> |
|||
|
|||
namespace tut |
|||
{ |
|||
test_runner_singleton runner; |
|||
} |
|||
|
|||
class callback : public tut::callback |
|||
{ |
|||
public: |
|||
void run_started(){ std::cout << "\nbegin"; } |
|||
|
|||
void test_completed(const tut::test_result& tr) |
|||
{ |
|||
std::cout << tr.test_pos << "=" << tr.result << std::flush; |
|||
} |
|||
|
|||
void run_completed(){ std::cout << "\nend"; } |
|||
}; |
|||
|
|||
int main() |
|||
{ |
|||
callback clbk; |
|||
runner.get().set_callback(&clbk); |
|||
|
|||
// run all tests in all groups |
|||
runner.get().run_tests(); |
|||
return 0; |
|||
} |
|||
|
|||
That's it. You are now ready to link and run our test application. Do it as often as possible; |
|||
once a day is a definite must. I hope, TUT will help you to make your application more |
|||
robust and relieve your testing pain. Feel free to send your questions, suggestions and |
|||
critical opinions to me; I'll do my best to address them asap. |
File diff suppressed because it is too large
@ -0,0 +1,226 @@ |
|||
#ifndef TUT_REPORTER |
|||
#define TUT_REPORTER |
|||
|
|||
#include "tut.hpp" |
|||
|
|||
/**
|
|||
* Template Unit Tests Framework for C++. |
|||
* http://tut.dozen.ru
|
|||
* |
|||
* @author Vladimir Dyuzhev, Vladimir.Dyuzhev@gmail.com |
|||
*/ |
|||
namespace |
|||
{ |
|||
|
|||
std::ostream& operator<<(std::ostream& os, const tut::test_result& tr) |
|||
{ |
|||
switch(tr.result) |
|||
{ |
|||
case tut::test_result::ok: |
|||
os << "\t" << tr.test << " " << tr.name << "...ok" << std::endl; |
|||
break; |
|||
case tut::test_result::fail: |
|||
os << "\t" << tr.test << " " << tr.name<< "...failed" << std::endl; |
|||
break; |
|||
case tut::test_result::ex_ctor: |
|||
os << "\t" << tr.test << " " << tr.name<< "...exception in setup" << std::endl; |
|||
break; |
|||
case tut::test_result::ex: |
|||
os << "\t" << tr.test << " " << tr.name<< "...exception" << std::endl; |
|||
break; |
|||
case tut::test_result::warn: |
|||
os << "\t" << tr.test << " " << tr.name<< "...warning" << std::endl; |
|||
break; |
|||
case tut::test_result::term: |
|||
os << "\t" << tr.test << " " << tr.name<< "...terminated" << std::endl; |
|||
break; |
|||
} |
|||
|
|||
return os; |
|||
} |
|||
|
|||
} // end of namespace
|
|||
|
|||
namespace tut |
|||
{ |
|||
|
|||
/**
|
|||
* Default TUT callback handler. |
|||
*/ |
|||
class reporter : public tut::callback |
|||
{ |
|||
std::string current_group; |
|||
typedef std::vector<tut::test_result> not_passed_list; |
|||
not_passed_list not_passed; |
|||
std::ostream& os; |
|||
|
|||
public: |
|||
|
|||
int ok_count; |
|||
int exceptions_count; |
|||
int failures_count; |
|||
int terminations_count; |
|||
int warnings_count; |
|||
|
|||
reporter() |
|||
: os(std::cout) |
|||
{ |
|||
init(); |
|||
} |
|||
|
|||
reporter(std::ostream& out) |
|||
: os(out) |
|||
{ |
|||
init(); |
|||
} |
|||
|
|||
void run_started() |
|||
{ |
|||
init(); |
|||
} |
|||
|
|||
void test_completed(const tut::test_result& tr) |
|||
{ |
|||
if (tr.group != current_group) |
|||
{ |
|||
os << std::endl << tr.group << ": " << std::endl; |
|||
current_group = tr.group; |
|||
} |
|||
|
|||
os << tr << std::flush; |
|||
if (tr.result == tut::test_result::ok) |
|||
{ |
|||
ok_count++; |
|||
} |
|||
else if (tr.result == tut::test_result::ex) |
|||
{ |
|||
exceptions_count++; |
|||
} |
|||
else if (tr.result == tut::test_result::ex_ctor) |
|||
{ |
|||
exceptions_count++; |
|||
} |
|||
else if (tr.result == tut::test_result::fail) |
|||
{ |
|||
failures_count++; |
|||
} |
|||
else if (tr.result == tut::test_result::warn) |
|||
{ |
|||
warnings_count++; |
|||
} |
|||
else |
|||
{ |
|||
terminations_count++; |
|||
} |
|||
|
|||
if (tr.result != tut::test_result::ok) |
|||
{ |
|||
not_passed.push_back(tr); |
|||
} |
|||
} |
|||
|
|||
void run_completed() |
|||
{ |
|||
os << std::endl; |
|||
|
|||
if (not_passed.size() > 0) |
|||
{ |
|||
not_passed_list::const_iterator i = not_passed.begin(); |
|||
while (i != not_passed.end()) |
|||
{ |
|||
tut::test_result tr = *i; |
|||
|
|||
os << std::endl; |
|||
|
|||
os << "---> " << "group: " << tr.group |
|||
<< ", test: test<" << tr.test << ">" |
|||
<< (!tr.name.empty() ? (std::string(" : ") + tr.name) : std::string()) |
|||
<< std::endl; |
|||
|
|||
os << " problem: "; |
|||
switch(tr.result) |
|||
{ |
|||
case test_result::fail: |
|||
os << "assertion failed" << std::endl; |
|||
break; |
|||
case test_result::ex: |
|||
case test_result::ex_ctor: |
|||
os << "unexpected exception" << std::endl; |
|||
if( tr.exception_typeid != "" ) |
|||
{ |
|||
os << " exception typeid: " |
|||
<< tr.exception_typeid << std::endl; |
|||
} |
|||
break; |
|||
case test_result::term: |
|||
os << "would be terminated" << std::endl; |
|||
break; |
|||
case test_result::warn: |
|||
os << "test passed, but cleanup code (destructor) raised" |
|||
" an exception" << std::endl; |
|||
break; |
|||
default: |
|||
break; |
|||
} |
|||
|
|||
if (!tr.message.empty()) |
|||
{ |
|||
if (tr.result == test_result::fail) |
|||
{ |
|||
os << " failed assertion: \"" << tr.message << "\"" |
|||
<< std::endl; |
|||
} |
|||
else |
|||
{ |
|||
os << " message: \"" << tr.message << "\"" |
|||
<< std::endl; |
|||
} |
|||
} |
|||
|
|||
++i; |
|||
} |
|||
} |
|||
|
|||
os << std::endl; |
|||
|
|||
os << "tests summary:" << std::endl; |
|||
if (terminations_count > 0) |
|||
{ |
|||
os << " terminations:" << terminations_count << std::endl; |
|||
} |
|||
if (exceptions_count > 0) |
|||
{ |
|||
os << " exceptions:" << exceptions_count << std::endl; |
|||
} |
|||
if (failures_count > 0) |
|||
{ |
|||
os << " failures:" << failures_count << std::endl; |
|||
} |
|||
if (warnings_count > 0) |
|||
{ |
|||
os << " warnings:" << warnings_count << std::endl; |
|||
} |
|||
os << " ok:" << ok_count << std::endl; |
|||
} |
|||
|
|||
bool all_ok() const |
|||
{ |
|||
return not_passed.empty(); |
|||
} |
|||
|
|||
private: |
|||
|
|||
void init() |
|||
{ |
|||
ok_count = 0; |
|||
exceptions_count = 0; |
|||
failures_count = 0; |
|||
terminations_count = 0; |
|||
warnings_count = 0; |
|||
not_passed.clear(); |
|||
} |
|||
}; |
|||
|
|||
} |
|||
|
|||
#endif |
@ -0,0 +1,394 @@ |
|||
#ifndef TUT_RESTARTABLE_H_GUARD |
|||
#define TUT_RESTARTABLE_H_GUARD |
|||
|
|||
#include "tut.hpp" |
|||
#include <fstream> |
|||
#include <iostream> |
|||
#include <stdexcept> |
|||
|
|||
/**
|
|||
* Template Unit Tests Framework for C++. |
|||
* http://tut.dozen.ru
|
|||
* |
|||
* Optional restartable wrapper for test_runner. Allows to restart test runs |
|||
* finished due to abnormal test application termination (such as segmentation |
|||
* fault or math error). |
|||
* |
|||
* @author Vladimir Dyuzhev, Vladimir.Dyuzhev@gmail.com |
|||
*/ |
|||
|
|||
namespace tut |
|||
{ |
|||
|
|||
namespace util |
|||
{ |
|||
|
|||
/**
|
|||
* Escapes non-alphabetical characters in string. |
|||
*/ |
|||
std::string escape(const std::string& orig) |
|||
{ |
|||
std::string rc; |
|||
std::string::const_iterator i,e; |
|||
i = orig.begin(); |
|||
e = orig.end(); |
|||
|
|||
while (i != e) |
|||
{ |
|||
if ((*i >= 'a' && *i <= 'z') || |
|||
(*i >= 'A' && *i <= 'Z') || |
|||
(*i >= '0' && *i <= '9') ) |
|||
{ |
|||
rc += *i; |
|||
} |
|||
else |
|||
{ |
|||
rc += '\\'; |
|||
rc += ('a'+(((unsigned int)*i) >> 4)); |
|||
rc += ('a'+(((unsigned int)*i) & 0xF)); |
|||
} |
|||
|
|||
++i; |
|||
} |
|||
return rc; |
|||
} |
|||
|
|||
/**
|
|||
* Un-escapes string. |
|||
*/ |
|||
std::string unescape(const std::string& orig) |
|||
{ |
|||
std::string rc; |
|||
std::string::const_iterator i,e; |
|||
i = orig.begin(); |
|||
e = orig.end(); |
|||
|
|||
while (i != e) |
|||
{ |
|||
if (*i != '\\') |
|||
{ |
|||
rc += *i; |
|||
} |
|||
else |
|||
{ |
|||
++i; |
|||
if (i == e) |
|||
{ |
|||
throw std::invalid_argument("unexpected end of string"); |
|||
} |
|||
unsigned int c1 = *i; |
|||
++i; |
|||
if (i == e) |
|||
{ |
|||
throw std::invalid_argument("unexpected end of string"); |
|||
} |
|||
unsigned int c2 = *i; |
|||
rc += (((c1 - 'a') << 4) + (c2 - 'a')); |
|||
} |
|||
|
|||
++i; |
|||
} |
|||
return rc; |
|||
} |
|||
|
|||
/**
|
|||
* Serialize test_result avoiding interfering with operator <<. |
|||
*/ |
|||
void serialize(std::ostream& os, const tut::test_result& tr) |
|||
{ |
|||
os << escape(tr.group) << std::endl; |
|||
os << tr.test << ' '; |
|||
switch(tr.result) |
|||
{ |
|||
case test_result::ok: |
|||
os << 0; |
|||
break; |
|||
case test_result::fail: |
|||
os << 1; |
|||
break; |
|||
case test_result::ex: |
|||
os << 2; |
|||
break; |
|||
case test_result::warn: |
|||
os << 3; |
|||
break; |
|||
case test_result::term: |
|||
os << 4; |
|||
break; |
|||
default: |
|||
throw std::logic_error("operator << : bad result_type"); |
|||
} |
|||
os << ' ' << escape(tr.message) << std::endl; |
|||
} |
|||
|
|||
/**
|
|||
* deserialization for test_result |
|||
*/ |
|||
void deserialize(std::istream& is, tut::test_result& tr) |
|||
{ |
|||
std::getline(is,tr.group); |
|||
if (is.eof()) |
|||
{ |
|||
throw tut::no_more_tests(); |
|||
} |
|||
tr.group = unescape(tr.group); |
|||
|
|||
tr.test = -1; |
|||
is >> tr.test; |
|||
if (tr.test < 0) |
|||
{ |
|||
throw std::logic_error("operator >> : bad test number"); |
|||
} |
|||
|
|||
int n = -1; |
|||
is >> n; |
|||
switch(n) |
|||
{ |
|||
case 0: |
|||
tr.result = test_result::ok; |
|||
break; |
|||
case 1: |
|||
tr.result = test_result::fail; |
|||
break; |
|||
case 2: |
|||
tr.result = test_result::ex; |
|||
break; |
|||
case 3: |
|||
tr.result = test_result::warn; |
|||
break; |
|||
case 4: |
|||
tr.result = test_result::term; |
|||
break; |
|||
default: |
|||
throw std::logic_error("operator >> : bad result_type"); |
|||
} |
|||
|
|||
is.ignore(1); // space
|
|||
std::getline(is,tr.message); |
|||
tr.message = unescape(tr.message); |
|||
if (!is.good()) |
|||
{ |
|||
throw std::logic_error("malformed test result"); |
|||
} |
|||
} |
|||
}; |
|||
|
|||
/**
|
|||
* Restartable test runner wrapper. |
|||
*/ |
|||
class restartable_wrapper |
|||
{ |
|||
test_runner& runner_; |
|||
callback* callback_; |
|||
|
|||
std::string dir_; |
|||
std::string log_; // log file: last test being executed
|
|||
std::string jrn_; // journal file: results of all executed tests
|
|||
|
|||
public: |
|||
/**
|
|||
* Default constructor. |
|||
* @param dir Directory where to search/put log and journal files |
|||
*/ |
|||
restartable_wrapper(const std::string& dir = ".") |
|||
: runner_(runner.get()), |
|||
callback_(0), |
|||
dir_(dir) |
|||
{ |
|||
// dozen: it works, but it would be better to use system path separator
|
|||
jrn_ = dir_ + '/' + "journal.tut"; |
|||
log_ = dir_ + '/' + "log.tut"; |
|||
} |
|||
|
|||
/**
|
|||
* Stores another group for getting by name. |
|||
*/ |
|||
void register_group(const std::string& name, group_base* gr) |
|||
{ |
|||
runner_.register_group(name,gr); |
|||
} |
|||
|
|||
/**
|
|||
* Stores callback object. |
|||
*/ |
|||
void set_callback(callback* cb) |
|||
{ |
|||
callback_ = cb; |
|||
} |
|||
|
|||
/**
|
|||
* Returns callback object. |
|||
*/ |
|||
callback& get_callback() const |
|||
{ |
|||
return runner_.get_callback(); |
|||
} |
|||
|
|||
/**
|
|||
* Returns list of known test groups. |
|||
*/ |
|||
groupnames list_groups() const |
|||
{ |
|||
return runner_.list_groups(); |
|||
} |
|||
|
|||
/**
|
|||
* Runs all tests in all groups. |
|||
*/ |
|||
void run_tests() const |
|||
{ |
|||
// where last run was failed
|
|||
std::string fail_group; |
|||
int fail_test; |
|||
read_log_(fail_group,fail_test); |
|||
bool fail_group_reached = (fail_group == ""); |
|||
|
|||
// iterate over groups
|
|||
tut::groupnames gn = list_groups(); |
|||
tut::groupnames::const_iterator gni,gne; |
|||
gni = gn.begin(); |
|||
gne = gn.end(); |
|||
while (gni != gne) |
|||
{ |
|||
// skip all groups before one that failed
|
|||
if (!fail_group_reached) |
|||
{ |
|||
if (*gni != fail_group) |
|||
{ |
|||
++gni; |
|||
continue; |
|||
} |
|||
fail_group_reached = true; |
|||
} |
|||
|
|||
// first or restarted run
|
|||
int test = (*gni == fail_group && fail_test >= 0) ? fail_test + 1 : 1; |
|||
while(true) |
|||
{ |
|||
// last executed test pos
|
|||
register_execution_(*gni,test); |
|||
|
|||
try |
|||
{ |
|||
tut::test_result tr = runner_.run_test(*gni,test); |
|||
register_test_(tr); |
|||
} |
|||
catch (const tut::beyond_last_test&) |
|||
{ |
|||
break; |
|||
} |
|||
catch(const tut::no_such_test&) |
|||
{ |
|||
// it's ok
|
|||
} |
|||
|
|||
++test; |
|||
} |
|||
|
|||
++gni; |
|||
} |
|||
|
|||
// show final results to user
|
|||
invoke_callback_(); |
|||
|
|||
// truncate files as mark of successful finish
|
|||
truncate_(); |
|||
} |
|||
|
|||
private: |
|||
/**
|
|||
* Shows results from journal file. |
|||
*/ |
|||
void invoke_callback_() const |
|||
{ |
|||
runner_.set_callback(callback_); |
|||
runner_.get_callback().run_started(); |
|||
|
|||
std::string current_group; |
|||
std::ifstream ijournal(jrn_.c_str()); |
|||
while (ijournal.good()) |
|||
{ |
|||
// read next test result
|
|||
try |
|||
{ |
|||
tut::test_result tr; |
|||
util::deserialize(ijournal,tr); |
|||
runner_.get_callback().test_completed(tr); |
|||
} |
|||
catch (const no_more_tests&) |
|||
{ |
|||
break; |
|||
} |
|||
} |
|||
|
|||
runner_.get_callback().run_completed(); |
|||
} |
|||
|
|||
/**
|
|||
* Register test into journal. |
|||
*/ |
|||
void register_test_(const test_result& tr) const |
|||
{ |
|||
std::ofstream ojournal(jrn_.c_str(), std::ios::app); |
|||
util::serialize(ojournal, tr); |
|||
ojournal << std::flush; |
|||
if (!ojournal.good()) |
|||
{ |
|||
throw std::runtime_error("unable to register test result in file " |
|||
+ jrn_); |
|||
} |
|||
} |
|||
|
|||
/**
|
|||
* Mark the fact test going to be executed |
|||
*/ |
|||
void register_execution_(const std::string& grp, int test) const |
|||
{ |
|||
// last executed test pos
|
|||
std::ofstream olog(log_.c_str()); |
|||
olog << util::escape(grp) << std::endl << test << std::endl << std::flush; |
|||
if (!olog.good()) |
|||
{ |
|||
throw std::runtime_error("unable to register execution in file " |
|||
+ log_); |
|||
} |
|||
} |
|||
|
|||
/**
|
|||
* Truncate tests. |
|||
*/ |
|||
void truncate_() const |
|||
{ |
|||
std::ofstream olog(log_.c_str()); |
|||
std::ofstream ojournal(jrn_.c_str()); |
|||
} |
|||
|
|||
/**
|
|||
* Read log file |
|||
*/ |
|||
void read_log_(std::string& fail_group, int& fail_test) const |
|||
{ |
|||
// read failure point, if any
|
|||
std::ifstream ilog(log_.c_str()); |
|||
std::getline(ilog,fail_group); |
|||
fail_group = util::unescape(fail_group); |
|||
ilog >> fail_test; |
|||
if (!ilog.good()) |
|||
{ |
|||
fail_group = ""; |
|||
fail_test = -1; |
|||
truncate_(); |
|||
} |
|||
else |
|||
{ |
|||
// test was terminated...
|
|||
tut::test_result tr(fail_group, fail_test, "", tut::test_result::term); |
|||
register_test_(tr); |
|||
} |
|||
} |
|||
}; |
|||
|
|||
} |
|||
|
|||
#endif |
|||
|
Binary file not shown.
Loading…
Reference in new issue