Skip to content

Commit

Permalink
Add tests for different node data types and methods for setting node …
Browse files Browse the repository at this point in the history
…data (#290)

* Remove static_cast of 0 to template type T in best_first_search

* Add setter for data attribute and pass data with move in constructor

* Use std::move when copying node data

* Add tests for edges with non-native node data types

* Add methods for changing the data of nodes

* Add tests for new setNodeData methods

* Fix in the first overload of setNodeData

* Add move constructor for Node class

* Fix move constructor

---------

Co-authored-by: sbaldu <simone.balducci@gmail.com>
  • Loading branch information
sbaldu and sbaldu authored May 16, 2023
1 parent 8fe01ef commit 6cd335f
Show file tree
Hide file tree
Showing 8 changed files with 344 additions and 8 deletions.
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));
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

0 comments on commit 6cd335f

Please sign in to comment.