diff --git a/CMakeLists.txt b/CMakeLists.txt index 79b2b51de..439d442df 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.9) # set the project name and version -project(CXXGraph VERSION 0.0.9) +project(CXXGraph VERSION 0.1.0) configure_file(CXXGraphConfig.h.in ${PROJECT_SOURCE_DIR}/include/CXXGraphConfig.h) diff --git a/docs/Doxyfile b/docs/Doxyfile index cb77d9cd7..10457b642 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = "CXXGraph" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 0.0.9 +PROJECT_NUMBER = 0.1.0 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/include/Graph.hpp b/include/Graph.hpp index f2f5efe81..398d1f316 100644 --- a/include/Graph.hpp +++ b/include/Graph.hpp @@ -468,6 +468,7 @@ namespace CXXGRAPH std::list *> edgeSet; void addElementToAdjMatrix(AdjacencyMatrix &adjMatrix, const Node *nodeFrom, const Node *nodeTo, const Edge *edge) const; int writeToStandardFile_csv(const std::string &workingDir, const std::string &OFileName, bool compress, bool writeNodeFeat, bool writeEdgeWeight) const; + int readFromStandardFile_csv(const std::string &workingDir, const std::string &OFileName, bool compress, bool readNodeFeat, bool readEdgeWeight); public: /// Specify the Input/Output format of the Graph for Import/Export functions @@ -483,7 +484,7 @@ namespace CXXGRAPH ~Graph() = default; const std::list *> &getEdgeSet() const; void setEdgeSet(std::list *> &edgeSet); - void addEdge(const Edge &edge); + void addEdge(const Edge *edge); void removeEdge(unsigned long edgeId); const std::list *> getNodeSet() const; const std::optional *> getEdge(unsigned long edgeId) const; @@ -563,6 +564,19 @@ namespace CXXGRAPH * @return 0 if all OK, else return a negative value */ int writeToFile(InputOutputFormat format = InputOutputFormat::STANDARD_CSV, const std::string &workingDir = ".", const std::string &OFileName = "graph", bool compress = false, bool writeNodeFeat = false, bool writeEdgeWeight = false) const; + /** + * \brief + * This function write the graph in an output file + * + * @param format The Input format of the file + * @param workingDir The path to the directory in which is placed the Input file + * @param OFileName The Input File Name ( ) + * @param compress Indicates if the Input is compressed + * @param writeNodeFeat Indicates if import also Node Features + * @param writeEdgeWeight Indicates if import also Edge Weights + * @return 0 if all OK, else return a negative value + */ + int readFromFile(InputOutputFormat format = InputOutputFormat::STANDARD_CSV, const std::string &workingDir = ".", const std::string &OFileName = "graph", bool compress = false, bool readNodeFeat = false, bool readEdgeWeight = false); friend std::ostream &operator<<<>(std::ostream &os, const Graph &graph); friend std::ostream &operator<<<>(std::ostream &os, const AdjacencyMatrix &adj); @@ -573,7 +587,8 @@ namespace CXXGRAPH { for (auto edgeSetIt = edgeSet.begin(); edgeSetIt != edgeSet.end(); ++edgeSetIt) { - if (std::find(this->edgeSet.begin(), this->edgeSet.end(), *edgeSetIt) == this->edgeSet.end()) + if (std::find_if(this->edgeSet.begin(), this->edgeSet.end(), [edgeSetIt](const Edge *edge) + { return (*edge == **edgeSetIt); }) == this->edgeSet.end()) { this->edgeSet.push_back(*edgeSetIt); } @@ -592,7 +607,8 @@ namespace CXXGRAPH this->edgeSet.clear(); for (auto edgeSetIt = edgeSet.begin(); edgeSetIt != edgeSet.end(); ++edgeSetIt) { - if (std::find(this->edgeSet.begin(), this->edgeSet.end(), *edgeSetIt) == this->edgeSet.end()) + if (std::find_if(this->edgeSet.begin(), this->edgeSet.end(), [edgeSetIt](const Edge *edge) + { return (*edge == **edgeSetIt); }) == this->edgeSet.end()) { this->edgeSet.push_back(*edgeSetIt); } @@ -600,11 +616,12 @@ namespace CXXGRAPH } template - void Graph::addEdge(const Edge &edge) + void Graph::addEdge(const Edge *edge) { - if (std::find(edgeSet.begin(), edgeSet.end(), &edge) == edgeSet.end()) + if (std::find_if(edgeSet.begin(), edgeSet.end(), [edge](const Edge *edge_a) + { return (*edge == *edge_a); }) == edgeSet.end()) { - edgeSet.push_back(&edge); + edgeSet.push_back(edge); } } @@ -624,11 +641,13 @@ namespace CXXGRAPH std::list *> nodeSet; for (auto edge : edgeSet) { - if (std::find(nodeSet.begin(), nodeSet.end(), edge->getNodePair().first) == nodeSet.end()) + if (std::find_if(nodeSet.begin(), nodeSet.end(), [edge](const Node *node) + { return (*edge->getNodePair().first == *node); }) == nodeSet.end()) { nodeSet.push_back(edge->getNodePair().first); } - if (std::find(nodeSet.begin(), nodeSet.end(), edge->getNodePair().second) == nodeSet.end()) + if (std::find_if(nodeSet.begin(), nodeSet.end(), [edge](const Node *node) + { return (*edge->getNodePair().second == *node); }) == nodeSet.end()) { nodeSet.push_back(edge->getNodePair().second); } @@ -667,8 +686,13 @@ namespace CXXGRAPH std::ofstream ofileGraph; std::string completePathToFileGraph = workingDir + "/" + OFileName + ".csv"; ofileGraph.open(completePathToFileGraph); + if (!ofileGraph.is_open()) + { + // ERROR File Not Open + return -1; + } auto printOutGraph = [&ofileGraph](const Edge *e) - { ofileGraph << e->getId() << "," << e->getNodePair().first->getId() << "," << e->getNodePair().second->getId() << std::endl; }; + { ofileGraph << e->getId() << "," << e->getNodePair().first->getId() << "," << e->getNodePair().second->getId() << "," << ((e->isDirected().has_value() && e->isDirected().value()) ? 1 : 0) << std::endl; }; std::for_each(edgeSet.cbegin(), edgeSet.cend(), printOutGraph); ofileGraph.close(); @@ -678,6 +702,11 @@ namespace CXXGRAPH std::string completePathToFileNodeFeat = workingDir + "/" + OFileName + "_NodeFeat" ".csv"; ofileNodeFeat.open(completePathToFileNodeFeat); + if (!ofileNodeFeat.is_open()) + { + // ERROR File Not Open + return -1; + } auto printOutNodeFeat = [&ofileNodeFeat](const Node *node) { ofileNodeFeat << node->getId() << "," << node->getData() << std::endl; }; auto nodeSet = getNodeSet(); @@ -691,8 +720,13 @@ namespace CXXGRAPH std::string completePathToFileEdgeWeight = workingDir + "/" + OFileName + "_EdgeWeight" ".csv"; ofileEdgeWeight.open(completePathToFileEdgeWeight); + if (!ofileEdgeWeight.is_open()) + { + // ERROR File Not Open + return -1; + } auto printOutEdgeWeight = [&ofileEdgeWeight](const Edge *e) - { ofileEdgeWeight << e->getId() << "," << (e->isWeighted().has_value() && e->isWeighted().value() ? (dynamic_cast(e))->getWeight() : 0.0) << std::endl; }; + { ofileEdgeWeight << e->getId() << "," << (e->isWeighted().has_value() && e->isWeighted().value() ? (dynamic_cast(e))->getWeight() : 0.0) << "," << (e->isWeighted().has_value() && e->isWeighted().value() ? 1 : 0) << std::endl; }; std::for_each(edgeSet.cbegin(), edgeSet.cend(), printOutEdgeWeight); ofileEdgeWeight.close(); @@ -700,6 +734,168 @@ namespace CXXGRAPH return 0; } + template + int Graph::readFromStandardFile_csv(const std::string &workingDir, const std::string &OFileName, bool compress, bool readNodeFeat, bool readEdgeWeight) + { + std::ifstream ifileGraph; + std::ifstream ifileNodeFeat; + std::ifstream ifileEdgeWeight; + std::map> edgeMap; + std::map edgeDirectedMap; + std::map nodeFeatMap; + std::map edgeWeightMap; + std::string completePathToFileGraph = workingDir + "/" + OFileName + ".csv"; + ifileGraph.open(completePathToFileGraph); + if (!ifileGraph.is_open()) + { + // ERROR File Not Open + return -1; + } + for (;;) + { /* loop continually */ + char comma; + unsigned long edgeId; + unsigned long nodeId1; + unsigned long nodeId2; + bool directed; + ifileGraph >> edgeId >> comma >> nodeId1 >> comma >> nodeId2 >> comma >> directed; + edgeMap[edgeId] = std::pair(nodeId1, nodeId2); + edgeDirectedMap[edgeId] = directed; + std::cout << "Edge Id : " << edgeId << std::endl; + std::cout << "map size : " << edgeMap.size() << std::endl; + if (ifileGraph.fail() || ifileGraph.eof()) + break; + ifileGraph.ignore(128, '\n'); + } + ifileGraph.close(); + + if (readNodeFeat) + { + std::string completePathToFileNodeFeat = workingDir + "/" + OFileName + "_NodeFeat" + ".csv"; + ifileNodeFeat.open(completePathToFileNodeFeat); + if (!ifileNodeFeat.is_open()) + { + // ERROR File Not Open + return -1; + } + for (;;) + { /* loop continually */ + char comma; + unsigned long nodeId; + T nodeFeat; + ifileNodeFeat >> nodeId >> comma >> nodeFeat; + nodeFeatMap[nodeId] = nodeFeat; + if (ifileNodeFeat.fail() || ifileNodeFeat.eof()) + break; + ifileNodeFeat.ignore(128, '\n'); + } + ifileNodeFeat.close(); + } + + if (readEdgeWeight) + { + + std::string completePathToFileEdgeWeight = workingDir + "/" + OFileName + "_EdgeWeight" + ".csv"; + ifileEdgeWeight.open(completePathToFileEdgeWeight); + if (!ifileEdgeWeight.is_open()) + { + // ERROR File Not Open + return -1; + } + for (;;) + { /* loop continually */ + char comma; + unsigned long edgeId; + double weight; + bool weighted; + ifileEdgeWeight >> edgeId >> comma >> weight >> comma >> weighted; + if (weighted) + { + edgeWeightMap[edgeId] = weight; + } + if (ifileEdgeWeight.fail() || ifileEdgeWeight.eof()) + break; + ifileEdgeWeight.ignore(128, '\n'); + } + ifileEdgeWeight.close(); + } + std::map *> nodeMap; + for (auto edgeIt = edgeMap.begin(); edgeIt != edgeMap.end(); ++edgeIt) + { + Node *node1 = nullptr; + Node *node2 = nullptr; + if (nodeMap.find(edgeIt->second.first) == nodeMap.end()) + { + //Create new Node + T feat; + if (nodeFeatMap.find(edgeIt->second.first) != nodeFeatMap.end()) + { + feat = nodeFeatMap.at(edgeIt->second.first); + } + node1 = new Node(edgeIt->second.first, feat); + nodeMap[edgeIt->second.first] = node1; + } + else + { + node1 = nodeMap.at(edgeIt->second.first); + } + if (nodeMap.find(edgeIt->second.second) == nodeMap.end()) + { + //Create new Node + T feat; + if (nodeFeatMap.find(edgeIt->second.second) != nodeFeatMap.end()) + { + feat = nodeFeatMap.at(edgeIt->second.second); + } + node2 = new Node(edgeIt->second.second, feat); + nodeMap[edgeIt->second.second] = node2; + } + else + { + node2 = nodeMap.at(edgeIt->second.second); + } + + if (edgeWeightMap.find(edgeIt->first) != edgeWeightMap.end()) + { + if (edgeDirectedMap.find(edgeIt->first) != edgeDirectedMap.end() && edgeDirectedMap.at(edgeIt->first)) + { + auto edge = new DirectedWeightedEdge(edgeIt->first, *node1, *node2, edgeWeightMap.at(edgeIt->first)); + std::cout << "ADD Edge : " << *edge << std::endl; + addEdge(edge); + std::cout << "EdgeSet size : " << getEdgeSet().size() << std::endl; + } + else + { + auto edge = new UndirectedWeightedEdge(edgeIt->first, *node1, *node2, edgeWeightMap.at(edgeIt->first)); + std::cout << "ADD Edge : " << *edge << std::endl; + addEdge(edge); + std::cout << "EdgeSet size : " << getEdgeSet().size() << std::endl; + } + } + else + { + if (edgeDirectedMap.find(edgeIt->first) != edgeDirectedMap.end() && edgeDirectedMap.at(edgeIt->first)) + { + auto edge = new DirectedEdge(edgeIt->first, *node1, *node2); + std::cout << "ADD Edge : " << *edge << std::endl; + addEdge(edge); + std::cout << "EdgeSet size : " << getEdgeSet().size() << std::endl; + } + else + { + auto edge = new UndirectedEdge(edgeIt->first, *node1, *node2); + std::cout << "ADD Edge : " << *edge << std::endl; + addEdge(edge); + std::cout << "EdgeSet size : " << getEdgeSet().size() << std::endl; + } + } + } + + return 0; + } + template const AdjacencyMatrix Graph::getAdjMatrix() const { @@ -1098,6 +1294,20 @@ namespace CXXGRAPH } } + template + int Graph::readFromFile(InputOutputFormat format, const std::string &workingDir, const std::string &OFileName, bool compress, bool readNodeFeat, bool readEdgeWeight) + { + if (format == InputOutputFormat::STANDARD_CSV) + { + return readFromStandardFile_csv(workingDir, OFileName, compress, readNodeFeat, readEdgeWeight); + } + else + { + //OUTPUT FORMAT NOT RECOGNIZED + return -1; + } + } + //ostream overload template std::ostream &operator<<(std::ostream &os, const Node &node) diff --git a/test/RWOutputTest.cpp b/test/RWOutputTest.cpp index 67139a47d..431ef5ce4 100644 --- a/test/RWOutputTest.cpp +++ b/test/RWOutputTest.cpp @@ -140,4 +140,189 @@ TEST(RWOutputTest, test_7) ASSERT_TRUE(exists_test("test_7.csv")); ASSERT_TRUE(exists_test("test_7_NodeFeat.csv")); ASSERT_FALSE(exists_test("test_7_EdgeWeight.csv")); +} + +TEST(RWOutputTest, test_8) +{ + CXXGRAPH::Node node1(1, 1); + CXXGRAPH::Node node2(2, 2); + CXXGRAPH::Node node3(3, 3); + std::pair *, const CXXGRAPH::Node *> pairNode(&node1, &node2); + CXXGRAPH::DirectedWeightedEdge edge1(1, pairNode, 5); + CXXGRAPH::DirectedEdge edge2(2, node2, node3); + CXXGRAPH::UndirectedWeightedEdge edge3(3, node1, node3, 6); + std::list *> edgeSet; + edgeSet.push_back(&edge1); + edgeSet.push_back(&edge2); + edgeSet.push_back(&edge3); + CXXGRAPH::Graph graph(edgeSet); + int res = graph.writeToFile(CXXGRAPH::Graph::InputOutputFormat::STANDARD_CSV, ".", "test_8"); + ASSERT_EQ(res, 0); + ASSERT_TRUE(exists_test("test_8.csv")); + ASSERT_FALSE(exists_test("test_8_NodeFeat.csv")); + ASSERT_FALSE(exists_test("test_8_EdgeWeight.csv")); + + CXXGRAPH::Graph readGraph; + readGraph.readFromFile(CXXGRAPH::Graph::InputOutputFormat::STANDARD_CSV, ".", "test_8"); + auto readNode = readGraph.getNodeSet(); + auto readEdge = readGraph.getEdgeSet(); + ASSERT_EQ(readEdge.size(), 3); + ASSERT_EQ(readNode.size(), 3); + + for (auto readEdgeIt = readEdge.begin(); readEdgeIt != readEdge.end(); ++readEdgeIt) + { + if ((*readEdgeIt)->getId() == 1) + { + ASSERT_TRUE((*readEdgeIt)->isDirected().has_value() && (*readEdgeIt)->isDirected().value()); + ASSERT_EQ((*readEdgeIt)->getNodePair().first->getId(), node1.getId()); + //ASSERT_EQ((*readEdgeIt)->getNodePair().first->getData(), node1.getData()); + ASSERT_EQ((*readEdgeIt)->getNodePair().second->getId(), node2.getId()); + //ASSERT_EQ((*readEdgeIt)->getNodePair().second->getData(), node2.getData()); + } + else if ((*readEdgeIt)->getId() == 2) + { + ASSERT_TRUE((*readEdgeIt)->isDirected().has_value() && (*readEdgeIt)->isDirected().value()); + ASSERT_EQ((*readEdgeIt)->getNodePair().first->getId(), node2.getId()); + //ASSERT_EQ((*readEdgeIt)->getNodePair().first->getData(), node2.getData()); + ASSERT_EQ((*readEdgeIt)->getNodePair().second->getId(), node3.getId()); + //ASSERT_EQ((*readEdgeIt)->getNodePair().second->getData(), node3.getData()); + } + else if ((*readEdgeIt)->getId() == 3) + { + ASSERT_TRUE((*readEdgeIt)->isDirected().has_value() && !(*readEdgeIt)->isDirected().value()); + ASSERT_EQ((*readEdgeIt)->getNodePair().first->getId(), node1.getId()); + //ASSERT_EQ((*readEdgeIt)->getNodePair().first->getData(), node1.getData()); + ASSERT_EQ((*readEdgeIt)->getNodePair().second->getId(), node3.getId()); + //ASSERT_EQ((*readEdgeIt)->getNodePair().second->getData(), node3.getData()); + } + else + { + ASSERT_TRUE(false); // forced Error + } + } +} + +TEST(RWOutputTest, test_9) +{ + CXXGRAPH::Node node1(1, 1); + CXXGRAPH::Node node2(2, 2); + CXXGRAPH::Node node3(3, 3); + std::pair *, const CXXGRAPH::Node *> pairNode(&node1, &node2); + CXXGRAPH::DirectedWeightedEdge edge1(1, pairNode, 5); + CXXGRAPH::DirectedEdge edge2(2, node2, node3); + CXXGRAPH::UndirectedWeightedEdge edge3(3, node1, node3, 6); + std::list *> edgeSet; + edgeSet.push_back(&edge1); + edgeSet.push_back(&edge2); + edgeSet.push_back(&edge3); + CXXGRAPH::Graph graph(edgeSet); + int res = graph.writeToFile(CXXGRAPH::Graph::InputOutputFormat::STANDARD_CSV, ".", "test_9", false, true); + ASSERT_EQ(res, 0); + ASSERT_TRUE(exists_test("test_9.csv")); + ASSERT_TRUE(exists_test("test_9_NodeFeat.csv")); + ASSERT_FALSE(exists_test("test_9_EdgeWeight.csv")); + + CXXGRAPH::Graph readGraph; + readGraph.readFromFile(CXXGRAPH::Graph::InputOutputFormat::STANDARD_CSV, ".", "test_9", false, true); + auto readNode = readGraph.getNodeSet(); + auto readEdge = readGraph.getEdgeSet(); + ASSERT_EQ(readEdge.size(), 3); + ASSERT_EQ(readNode.size(), 3); + + for (auto readEdgeIt = readEdge.begin(); readEdgeIt != readEdge.end(); ++readEdgeIt) + { + if ((*readEdgeIt)->getId() == 1) + { + ASSERT_TRUE((*readEdgeIt)->isDirected().has_value() && (*readEdgeIt)->isDirected().value()); + ASSERT_EQ((*readEdgeIt)->getNodePair().first->getId(), node1.getId()); + ASSERT_EQ((*readEdgeIt)->getNodePair().first->getData(), node1.getData()); + ASSERT_EQ((*readEdgeIt)->getNodePair().second->getId(), node2.getId()); + ASSERT_EQ((*readEdgeIt)->getNodePair().second->getData(), node2.getData()); + } + else if ((*readEdgeIt)->getId() == 2) + { + ASSERT_TRUE((*readEdgeIt)->isDirected().has_value() && (*readEdgeIt)->isDirected().value()); + ASSERT_EQ((*readEdgeIt)->getNodePair().first->getId(), node2.getId()); + ASSERT_EQ((*readEdgeIt)->getNodePair().first->getData(), node2.getData()); + ASSERT_EQ((*readEdgeIt)->getNodePair().second->getId(), node3.getId()); + ASSERT_EQ((*readEdgeIt)->getNodePair().second->getData(), node3.getData()); + } + else if ((*readEdgeIt)->getId() == 3) + { + ASSERT_TRUE((*readEdgeIt)->isDirected().has_value() && !(*readEdgeIt)->isDirected().value()); + ASSERT_EQ((*readEdgeIt)->getNodePair().first->getId(), node1.getId()); + ASSERT_EQ((*readEdgeIt)->getNodePair().first->getData(), node1.getData()); + ASSERT_EQ((*readEdgeIt)->getNodePair().second->getId(), node3.getId()); + ASSERT_EQ((*readEdgeIt)->getNodePair().second->getData(), node3.getData()); + } + else + { + ASSERT_TRUE(false); // forced Error + } + } +} + +TEST(RWOutputTest, test_10) +{ + CXXGRAPH::Node node1(1, 1); + CXXGRAPH::Node node2(2, 2); + CXXGRAPH::Node node3(3, 3); + std::pair *, const CXXGRAPH::Node *> pairNode(&node1, &node2); + CXXGRAPH::DirectedWeightedEdge edge1(1, pairNode, 5); + CXXGRAPH::DirectedEdge edge2(2, node2, node3); + CXXGRAPH::UndirectedWeightedEdge edge3(3, node1, node3, 6); + std::list *> edgeSet; + edgeSet.push_back(&edge1); + edgeSet.push_back(&edge2); + edgeSet.push_back(&edge3); + CXXGRAPH::Graph graph(edgeSet); + int res = graph.writeToFile(CXXGRAPH::Graph::InputOutputFormat::STANDARD_CSV, ".", "test_10", false, true, true); + ASSERT_EQ(res, 0); + ASSERT_TRUE(exists_test("test_10.csv")); + ASSERT_TRUE(exists_test("test_10_NodeFeat.csv")); + ASSERT_TRUE(exists_test("test_10_EdgeWeight.csv")); + + CXXGRAPH::Graph readGraph; + readGraph.readFromFile(CXXGRAPH::Graph::InputOutputFormat::STANDARD_CSV, ".", "test_10", false, true, true); + auto readNode = readGraph.getNodeSet(); + auto readEdge = readGraph.getEdgeSet(); + ASSERT_EQ(readEdge.size(), 3); + ASSERT_EQ(readNode.size(), 3); + + for (auto readEdgeIt = readEdge.begin(); readEdgeIt != readEdge.end(); ++readEdgeIt) + { + if ((*readEdgeIt)->getId() == 1) + { + ASSERT_TRUE((*readEdgeIt)->isDirected().has_value() && (*readEdgeIt)->isDirected().value()); + ASSERT_TRUE((*readEdgeIt)->isWeighted().has_value() && (*readEdgeIt)->isWeighted().value()); + ASSERT_EQ((dynamic_cast(*readEdgeIt))->getWeight(), 5); + ASSERT_EQ((*readEdgeIt)->getNodePair().first->getId(), node1.getId()); + ASSERT_EQ((*readEdgeIt)->getNodePair().first->getData(), node1.getData()); + ASSERT_EQ((*readEdgeIt)->getNodePair().second->getId(), node2.getId()); + ASSERT_EQ((*readEdgeIt)->getNodePair().second->getData(), node2.getData()); + } + else if ((*readEdgeIt)->getId() == 2) + { + ASSERT_TRUE((*readEdgeIt)->isDirected().has_value() && (*readEdgeIt)->isDirected().value()); + ASSERT_TRUE((*readEdgeIt)->isWeighted().has_value() && !(*readEdgeIt)->isWeighted().value()); + ASSERT_EQ((*readEdgeIt)->getNodePair().first->getId(), node2.getId()); + ASSERT_EQ((*readEdgeIt)->getNodePair().first->getData(), node2.getData()); + ASSERT_EQ((*readEdgeIt)->getNodePair().second->getId(), node3.getId()); + ASSERT_EQ((*readEdgeIt)->getNodePair().second->getData(), node3.getData()); + } + else if ((*readEdgeIt)->getId() == 3) + { + ASSERT_TRUE((*readEdgeIt)->isDirected().has_value() && !(*readEdgeIt)->isDirected().value()); + ASSERT_TRUE((*readEdgeIt)->isWeighted().has_value() && (*readEdgeIt)->isWeighted().value()); + ASSERT_EQ((dynamic_cast(*readEdgeIt))->getWeight(), 6); + ASSERT_EQ((*readEdgeIt)->getNodePair().first->getId(), node1.getId()); + ASSERT_EQ((*readEdgeIt)->getNodePair().first->getData(), node1.getData()); + ASSERT_EQ((*readEdgeIt)->getNodePair().second->getId(), node3.getId()); + ASSERT_EQ((*readEdgeIt)->getNodePair().second->getData(), node3.getData()); + } + else + { + ASSERT_TRUE(false); // forced Error + } + } } \ No newline at end of file