Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tests for different node data types and methods for setting node data #290

Merged
merged 10 commits into from
May 16, 2023
54 changes: 52 additions & 2 deletions include/Graph/Graph.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ template <typename T>
class Graph {
private:
T_EdgeSet<T> edgeSet = {};

// Private non-const getter for the set of nodes
std::set<Node<T> *> nodeSet();

std::optional<std::pair<std::string, char>> getExtenstionAndSeparator(
InputOutputFormat format) const;
void writeGraphToStream(std::ostream &oGraph, std::ostream &oNodeFeat,
Expand Down Expand Up @@ -161,6 +165,23 @@ class Graph {
*
*/
virtual const std::set<const Node<T> *> getNodeSet() const;
/**
* \brief
* Function that sets the data contained in a node
*
* @param nodeUserId The userId string of the node whose data is to be changes
* @param data The new value for the node data
*
*/
virtual void setNodeData(const std::string &nodeUserId, T data);
/**
* \brief
* Function that sets the data contained in every node of the graph
*
* @param dataMap Map of the userId of every node with its new data value
*
*/
virtual void setNodeData(std::map<std::string, T> &dataMap);
/**
* \brief
* Function that return an Edge with specific ID if Exist in the Graph
Expand Down Expand Up @@ -641,6 +662,24 @@ const std::set<const Node<T> *> Graph<T>::getNodeSet() const {
return nodeSet;
}

template <typename T>
void Graph<T>::setNodeData(const std::string &nodeUserId, T data) {
for(auto &nodeSetIt : this->nodeSet()) {
if (nodeSetIt->getUserId() == nodeUserId) {
nodeSetIt->setData(std::move(data));
break;
}
}
}

template <typename T>
void Graph<T>::setNodeData(std::map<std::string, T> &dataMap) {
// Construct the set of all the nodes in the graph
for(auto &nodeSetIt : this->nodeSet()) {
nodeSetIt->setData(std::move(dataMap[nodeSetIt->getUserId()]));
}
}

template <typename T>
const std::optional<const Edge<T> *> Graph<T>::getEdge(
const unsigned long long edgeId) const {
Expand All @@ -653,6 +692,17 @@ const std::optional<const Edge<T> *> Graph<T>::getEdge(
return std::nullopt;
}

template <typename T>
std::set<Node<T> *> Graph<T>::nodeSet() {
std::set<Node<T> *> nodeSet;
for (auto &edgeSetIt : edgeSet) {
nodeSet.insert(const_cast<Node<T> *>(edgeSetIt->getNodePair().first));
ZigRazor marked this conversation as resolved.
Show resolved Hide resolved
nodeSet.insert(const_cast<Node<T> *>(edgeSetIt->getNodePair().second));
}

return nodeSet;
}

template <typename T>
std::optional<std::pair<std::string, char>> Graph<T>::getExtenstionAndSeparator(
InputOutputFormat format) const {
Expand Down Expand Up @@ -909,7 +959,7 @@ void Graph<T>::recreateGraph(
// Create new Node
T feat;
if (nodeFeatMap.find(edgeIt.second.first) != nodeFeatMap.end()) {
feat = nodeFeatMap.at(edgeIt.second.first);
feat = std::move(nodeFeatMap.at(edgeIt.second.first));
}
node1 = new Node<T>(edgeIt.second.first, feat);
nodeMap[edgeIt.second.first] = node1;
Expand All @@ -920,7 +970,7 @@ void Graph<T>::recreateGraph(
// Create new Node
T feat;
if (nodeFeatMap.find(edgeIt.second.second) != nodeFeatMap.end()) {
feat = nodeFeatMap.at(edgeIt.second.second);
feat = std::move(nodeFeatMap.at(edgeIt.second.second));
}
node2 = new Node<T>(edgeIt.second.second, feat);
nodeMap[edgeIt.second.second] = node2;
Expand Down
24 changes: 21 additions & 3 deletions include/Node/Node.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,25 +39,36 @@ class Node {
void setId(const std::string &);

public:
Node(const std::string &, const T &data);
Node(const std::string &, const T& data);
// Move constructor
Node(const std::string &, T&& data) noexcept;
~Node() = default;
const std::size_t &getId() const;
const std::string &getUserId() const;
const T &getData() const;
void setData(T&& new_data);
// operator
bool operator==(const Node<T> &b) const;
bool operator<(const Node<T> &b) const;
friend std::ostream &operator<< <>(std::ostream &os, const Node<T> &node);
};

template <typename T>
Node<T>::Node(const std::string &id, const T &data) {
Node<T>::Node(const std::string& id, const T& data) {
this->userId = id;
// the userid is set as sha512 hash of the user provided id
setId(id);
this->data = data;
}

template <typename T>
Node<T>::Node(const std::string& id, T&& data) noexcept {
this->userId = id;
// the userid is set as sha512 hash of the user provided id
setId(id);
std::swap(this->data, data);
}

template <typename T>
void Node<T>::setId(const std::string &inpId) {
// const unsigned char* userId = reinterpret_cast<const unsigned char
Expand Down Expand Up @@ -99,6 +110,12 @@ const T &Node<T>::getData() const {
return data;
}

template <typename T>
void Node<T>::setData(T&& new_data) {
this->data = std::move(new_data);
}

// The data type T must have an overload of the equality operator
template <typename T>
bool Node<T>::operator==(const Node<T> &b) const {
return (this->id == b.id && this->data == b.data);
Expand All @@ -110,6 +127,7 @@ bool Node<T>::operator<(const Node<T> &b) const {
}

// ostream overload
// The data type T must have an overload of the ostream operator
template <typename T>
std::ostream &operator<<(std::ostream &os, const Node<T> &node) {
os << "Node: {\n"
Expand All @@ -118,4 +136,4 @@ std::ostream &operator<<(std::ostream &os, const Node<T> &node) {
}
} // namespace CXXGraph

#endif // __CXXGRAPH_NODE_H__
#endif // __CXXGRAPH_NODE_H__
46 changes: 46 additions & 0 deletions test/DirectedEdgeTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,52 @@ TEST(DirectedEdgeTest, Constructor_5) {
ASSERT_FALSE(edge.isWeighted().value());
}

TEST(DirectedEdgeTest, Bool_data) {
// First constructor
CXXGraph::Node<bool> node1("1", true);
CXXGraph::Node<bool> node2("2", false);
CXXGraph::DirectedEdge<bool> edge1(1, node1, node2);
ASSERT_EQ(*(edge1.getNodePair().first), node1);
ASSERT_EQ(*(edge1.getNodePair().second), node2);
ASSERT_TRUE(edge1.isDirected().value());
ASSERT_FALSE(edge1.isWeighted().value());

// Second constructor
CXXGraph::Node<bool> node3("3", true);
CXXGraph::Node<bool> node4("4", false);
std::pair<const CXXGraph::Node<bool> *, const CXXGraph::Node<bool> *> pairNode(
&node3, &node4);
CXXGraph::DirectedEdge<bool> edge2(2, pairNode);
ASSERT_EQ(edge2.getNodePair(), pairNode);
ASSERT_EQ(*(edge2.getNodePair().first), node3);
ASSERT_EQ(*(edge2.getNodePair().second), node4);
ASSERT_TRUE(edge2.isDirected().value());
ASSERT_FALSE(edge2.isWeighted().value());
}

TEST(DirectedEdgeTest, String_data) {
// First constructor
CXXGraph::Node<bool> node1("1", "On");
CXXGraph::Node<bool> node2("2", "Off");
CXXGraph::DirectedEdge<bool> edge1(1, node1, node2);
ASSERT_EQ(*(edge1.getNodePair().first), node1);
ASSERT_EQ(*(edge1.getNodePair().second), node2);
ASSERT_TRUE(edge1.isDirected().value());
ASSERT_FALSE(edge1.isWeighted().value());

// Second constructor
CXXGraph::Node<bool> node3("3", "On");
CXXGraph::Node<bool> node4("4", "Off");
std::pair<const CXXGraph::Node<bool> *, const CXXGraph::Node<bool> *> pairNode(
&node3, &node4);
CXXGraph::DirectedEdge<bool> edge2(2, pairNode);
ASSERT_EQ(edge2.getNodePair(), pairNode);
ASSERT_EQ(*(edge2.getNodePair().first), node3);
ASSERT_EQ(*(edge2.getNodePair().second), node4);
ASSERT_TRUE(edge2.isDirected().value());
ASSERT_FALSE(edge2.isWeighted().value());
}

TEST(DirectedEdgeTest, Cast_1) {
CXXGraph::Node<int> node1("1", 1);
CXXGraph::Node<int> node2("2", 2);
Expand Down
46 changes: 46 additions & 0 deletions test/DirectedWeightedEdgeTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,52 @@ TEST(DirectedWeightedEdgeTest, Constructor_7) {
ASSERT_EQ(edge.getWeight(), 0.0);
}

TEST(DirectedWeightedEdgeTest, Bool_data) {
// First constructor
CXXGraph::Node<bool> node1("1", true);
CXXGraph::Node<bool> node2("2", false);
CXXGraph::DirectedWeightedEdge<bool> edge1(1, node1, node2, 8);
ASSERT_EQ(*(edge1.getNodePair().first), node1);
ASSERT_EQ(*(edge1.getNodePair().second), node2);
ASSERT_TRUE(edge1.isDirected().value());
ASSERT_TRUE(edge1.isWeighted().value());

// Second constructor
CXXGraph::Node<bool> node3("3", true);
CXXGraph::Node<bool> node4("4", false);
std::pair<const CXXGraph::Node<bool> *, const CXXGraph::Node<bool> *> pairNode(
&node3, &node4);
CXXGraph::DirectedWeightedEdge<bool> edge2(2, pairNode, 2);
ASSERT_EQ(edge2.getNodePair(), pairNode);
ASSERT_EQ(*(edge2.getNodePair().first), node3);
ASSERT_EQ(*(edge2.getNodePair().second), node4);
ASSERT_TRUE(edge2.isDirected().value());
ASSERT_TRUE(edge2.isWeighted().value());
}

TEST(DirectedWeightedEdgeTest, String_data) {
// First constructor
CXXGraph::Node<bool> node1("1", "On");
CXXGraph::Node<bool> node2("2", "Off");
CXXGraph::DirectedWeightedEdge<bool> edge1(1, node1, node2, 4);
ASSERT_EQ(*(edge1.getNodePair().first), node1);
ASSERT_EQ(*(edge1.getNodePair().second), node2);
ASSERT_TRUE(edge1.isDirected().value());
ASSERT_TRUE(edge1.isWeighted().value());

// Second constructor
CXXGraph::Node<bool> node3("3", "On");
CXXGraph::Node<bool> node4("4", "Off");
std::pair<const CXXGraph::Node<bool> *, const CXXGraph::Node<bool> *> pairNode(
&node3, &node4);
CXXGraph::DirectedWeightedEdge<bool> edge2(2, pairNode, 6);
ASSERT_EQ(edge2.getNodePair(), pairNode);
ASSERT_EQ(*(edge2.getNodePair().first), node3);
ASSERT_EQ(*(edge2.getNodePair().second), node4);
ASSERT_TRUE(edge2.isDirected().value());
ASSERT_TRUE(edge2.isWeighted().value());
}

TEST(DirectedWeightedEdgeTest, Cast_1) {
CXXGraph::Node<int> node1("1", 1);
CXXGraph::Node<int> node2("2", 2);
Expand Down
40 changes: 39 additions & 1 deletion test/EdgeTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,44 @@ TEST(EdgeTest, print_1) {
std::cout << edge << std::endl;
}

TEST(EdgeTest, Bool_data) {
// First constructor
CXXGraph::Node<bool> node1("1", true);
CXXGraph::Node<bool> node2("2", false);
CXXGraph::Edge<bool> edge1(1, node1, node2);
ASSERT_EQ(*(edge1.getNodePair().first), node1);
ASSERT_EQ(*(edge1.getNodePair().second), node2);

// Second constructor
CXXGraph::Node<bool> node3("3", true);
CXXGraph::Node<bool> node4("4", false);
std::pair<const CXXGraph::Node<bool> *, const CXXGraph::Node<bool> *> pairNode(
&node3, &node4);
CXXGraph::Edge<bool> edge2(2, pairNode);
ASSERT_EQ(edge2.getNodePair(), pairNode);
ASSERT_EQ(*(edge2.getNodePair().first), node3);
ASSERT_EQ(*(edge2.getNodePair().second), node4);
}

TEST(EdgeTest, String_data) {
// First constructor
CXXGraph::Node<bool> node1("1", "On");
CXXGraph::Node<bool> node2("2", "Off");
CXXGraph::Edge<bool> edge1(1, node1, node2);
ASSERT_EQ(*(edge1.getNodePair().first), node1);
ASSERT_EQ(*(edge1.getNodePair().second), node2);

// Second constructor
CXXGraph::Node<bool> node3("3", "On");
CXXGraph::Node<bool> node4("4", "Off");
std::pair<const CXXGraph::Node<bool> *, const CXXGraph::Node<bool> *> pairNode(
&node3, &node4);
CXXGraph::Edge<bool> edge2(2, pairNode);
ASSERT_EQ(edge2.getNodePair(), pairNode);
ASSERT_EQ(*(edge2.getNodePair().first), node3);
ASSERT_EQ(*(edge2.getNodePair().second), node4);
}

TEST(EdgeTest, test) {
CXXGraph::Node<int> node1("1", 1);
CXXGraph::Node<int> node2("2", 2);
Expand All @@ -54,4 +92,4 @@ TEST(EdgeTest, test) {
adj = graph.getAdjMatrix();
ASSERT_EQ(adj->size(), 1);
std::cout << *adj << std::endl;
}
}
48 changes: 47 additions & 1 deletion test/GraphTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,4 +179,50 @@ TEST(GraphTest, adj_print_6) {
CXXGraph::Graph<int> graph(edgeSet);
std::cout << "Test Print Adjacency Matrix" << std::endl;
std::cout << *graph.getAdjMatrix() << std::endl;
}
}

TEST(GraphTest, set_data) {
// Create the graph
CXXGraph::Node<int> node1("1", 1);
CXXGraph::Node<int> node2("2", 2);
CXXGraph::Node<int> node3("3", 3);
std::pair<const CXXGraph::Node<int> *, const CXXGraph::Node<int> *> pairNode(
&node1, &node2);
CXXGraph::DirectedEdge<int> edge1(1, pairNode);
CXXGraph::DirectedEdge<int> edge2(2, node2, node3);
CXXGraph::UndirectedEdge<int> edge3(3, node1, node3);
CXXGraph::T_EdgeSet<int> edgeSet;
edgeSet.insert(&edge1);
edgeSet.insert(&edge2);
edgeSet.insert(&edge3);
CXXGraph::Graph<int> graph(edgeSet);


std::map<std::string, int> initial_values;
// Construct map with the initial values of the nodes data
for (const auto& nodeIt : graph.getNodeSet()) {
initial_values[nodeIt->getUserId()] = nodeIt->getData();
}
// Change the data contained in the nodes singularly
std::map<std::string, int> new_values;
for (const auto& nodeIt : graph.getNodeSet()) {
int r = std::rand();
graph.setNodeData(nodeIt->getUserId(), r);
new_values[nodeIt->getUserId()] = r;
}
// Check the final values of the node data
for (const auto& nodeIt : graph.getNodeSet()) {
ASSERT_EQ(nodeIt->getData(), new_values[nodeIt->getUserId()]);
}

// Now set the data of all the nodes at once
std::map<std::string, int> data_values;
for (const auto& nodeIt : graph.getNodeSet()) {
int r = std::rand();
data_values[nodeIt->getUserId()] = r;
}
graph.setNodeData(data_values);
for (const auto& nodeIt : graph.getNodeSet()) {
ASSERT_EQ(nodeIt->getData(), data_values[nodeIt->getUserId()]);
}
}
Loading