data: added SearchIndex for fuzzy name search and rewrote name handling in the Storage
This change stores each Token name in the separate singleton class Dictionary. The Dictionary gives each saved word an Id and thereby avoids duplicated names. E.g if the constructor method "Graph::Graph" is stored then the word "Graph" only appears once in memory. The class SearchIndex is now responsible for the name hierarchy and is instantiated by the Storage. The SearchIndex builds the name hierarchy using SearchNodes, each holding a Dictionary string reference of the name it holds. E.g if the names "math::ceil" and "math::floor" are added to the SearchIndex then 3 nodes get created, the SearchNode "math" will hold the two childs "ceil" and "floor". The hierarchical graph creation functionality got split off from Graph into the new subclass StorageGraph. The StorageGraph creates nodes with a passed SearchNode pointer of the name it represents in the SearchIndex. Thereby the StorageGraph reuses the hierarchical information in the SearchIndex and can create nodes much quicker by avoiding node searches and name comparisions. The name information is now stored in the Nodes via the TokenComponentName class, which is subclassed into TokenComponentNameReferenced and TokenComponentNameCached. The StorageClass creates nodes with the component TokenComponentNameReferenced, which holds a pointer to the SearchNode instance holding the name. This allows for retrieving the full name of the node, without using other Nodes int the Graph, which might not be present. If the Node is copied then the component changes to a TokenComponentNameCached, which holds the full name as a string, so the memory in the Storage doesn't have to be accessed anymore. TokenComponentSignature is now only holding an Id of the signature string saved in the Dictionary, which speeds up the signature comparison. A follow-up will change saving the whole signature as string to reusing the wordIds it is consisting of. Lastly the SearchIndex holds basic fuzzy search functionality. A passed query gets compared down the SearchNode hierarchy as long as matches for each letter are found. Matches must contain all letters of the query. The search is case-insensitive. If letters are found in front positions, next to each other or written in uppercase they are weighed higher in the match ranking. The character ':' is also interpreted and found, although the '::' delimiter is not stored. E.g. the query "m:l" used on the example above will return both "math::floor" and "math::ceil", but "floor" is ranked higher because the 'l' appears closer to the start.
This commit is contained in:
@@ -4,12 +4,13 @@ add_files(
|
||||
TestSuiteFixture.cpp
|
||||
TestSuiteFixture.h
|
||||
|
||||
utilityTest.cpp
|
||||
utilityTest.h
|
||||
TestStorage.cpp
|
||||
TestStorage.h
|
||||
|
||||
ConfigManagerTestSuite.h
|
||||
CxxParserTestSuite.h
|
||||
DataTypeTestSuite.h
|
||||
DictionaryTestSuite.h
|
||||
FileSystemTestSuite.h
|
||||
GraphTestSuite.h
|
||||
GraphFilterTestSuite.h
|
||||
@@ -19,6 +20,7 @@ add_files(
|
||||
QueryTreeTestSuite.h
|
||||
SettingsTestSuite.h
|
||||
StorageTestSuite.h
|
||||
StorageGraphTestSuite.h
|
||||
TextAccessTestSuite.h
|
||||
TokenLocationCollectionTestSuite.h
|
||||
UtilityStringTestSuite.h
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
#include "cxxtest/TestSuite.h"
|
||||
|
||||
#include "utility/text/Dictionary.h"
|
||||
|
||||
class DictionaryTestSuite: public CxxTest::TestSuite
|
||||
{
|
||||
public:
|
||||
void test_get_instance()
|
||||
{
|
||||
TS_ASSERT(Dictionary::getInstance());
|
||||
}
|
||||
|
||||
void test_does_not_find_unsaved_word()
|
||||
{
|
||||
TS_ASSERT_EQUALS("", Dictionary::getInstance()->getWord(12));
|
||||
}
|
||||
|
||||
void test_can_save_word_and_retrieve_it_with_id()
|
||||
{
|
||||
Id id = Dictionary::getInstance()->getWordId("hello world!");
|
||||
|
||||
TS_ASSERT_LESS_THAN(0, id);
|
||||
TS_ASSERT_EQUALS("hello world!", Dictionary::getInstance()->getWord(id));
|
||||
}
|
||||
|
||||
void test_can_save_multiple_words_and_retrieve_it_with_id()
|
||||
{
|
||||
std::deque<Id> ids = Dictionary::getInstance()->getWordIds("hello world!", " ");
|
||||
|
||||
TS_ASSERT_EQUALS(2, ids.size());
|
||||
TS_ASSERT_EQUALS("hello", Dictionary::getInstance()->getWord(ids.front()));
|
||||
TS_ASSERT_EQUALS("world!", Dictionary::getInstance()->getWord(ids.back()));
|
||||
TS_ASSERT_EQUALS("hello world!", Dictionary::getInstance()->getWord(ids, " "));
|
||||
}
|
||||
|
||||
void test_next_word_gets_different_id()
|
||||
{
|
||||
Id id = Dictionary::getInstance()->getWordId("hello world!");
|
||||
Id id2 = Dictionary::getInstance()->getWordId("foobar");
|
||||
|
||||
TS_ASSERT_LESS_THAN(0, id);
|
||||
TS_ASSERT_LESS_THAN(0, id2);
|
||||
TS_ASSERT_LESS_THAN(id, id2);
|
||||
|
||||
TS_ASSERT_EQUALS("hello world!", Dictionary::getInstance()->getWord(id));
|
||||
TS_ASSERT_EQUALS("foobar", Dictionary::getInstance()->getWord(id2));
|
||||
}
|
||||
};
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include "data/graph/filter/GraphFilterConductor.h"
|
||||
#include "data/query/QueryTree.h"
|
||||
#include "utilityTest.h"
|
||||
#include "TestStorage.h"
|
||||
|
||||
class GraphFilterConductorTestSuite : public CxxTest::TestSuite
|
||||
{
|
||||
@@ -22,7 +22,7 @@ public:
|
||||
TS_ASSERT_EQUALS(
|
||||
printedFilteredTestGraph("method"),
|
||||
|
||||
"4 nodes: method:A method:getCount method:process method:process\n"
|
||||
"4 nodes: method:A::A method:A::getCount method:A::process method:B::process\n"
|
||||
"0 edges:\n"
|
||||
);
|
||||
|
||||
@@ -40,7 +40,8 @@ public:
|
||||
printedFilteredTestGraph("!method"),
|
||||
|
||||
"7 nodes: "
|
||||
"class:A field:A::count undefined:int undefined:void class:B function:main undefined_function:B::B\n"
|
||||
"class:A field:A::count undefined_type:int undefined_type:void class:B function:main "
|
||||
"undefined_function:B::B\n"
|
||||
"7 edges: "
|
||||
"child:A->A::count type_use:A::count->int inheritance:B->A return_type:main->int type_usage:main->B "
|
||||
"child:B->B::B call:main->B::B\n"
|
||||
@@ -62,7 +63,7 @@ public:
|
||||
TS_ASSERT_EQUALS(
|
||||
printedFilteredTestGraph("\"A\":field"),
|
||||
|
||||
"1 nodes: field:count\n"
|
||||
"1 nodes: field:A::count\n"
|
||||
"0 edges:\n"
|
||||
);
|
||||
}
|
||||
@@ -72,7 +73,7 @@ public:
|
||||
TS_ASSERT_EQUALS(
|
||||
printedFilteredTestGraph("(static|const)"),
|
||||
|
||||
"4 nodes: field:count method:getCount method:process method:process\n"
|
||||
"4 nodes: field:A::count method:A::getCount method:A::process method:B::process\n"
|
||||
"0 edges:\n"
|
||||
);
|
||||
}
|
||||
@@ -82,7 +83,7 @@ public:
|
||||
TS_ASSERT_EQUALS(
|
||||
printedFilteredTestGraph("(static|const).public"),
|
||||
|
||||
"1 nodes: method:getCount\n"
|
||||
"1 nodes: method:A::getCount\n"
|
||||
"0 edges:\n"
|
||||
);
|
||||
}
|
||||
@@ -93,24 +94,24 @@ private:
|
||||
QueryTree tree(query);
|
||||
GraphFilterConductor conductor;
|
||||
|
||||
createTestGraph();
|
||||
createTestStorage();
|
||||
Graph result;
|
||||
|
||||
conductor.filter(&tree, &m_graph, &result);
|
||||
conductor.filter(&tree, &m_storage.getGraph(), &result);
|
||||
|
||||
std::stringstream ss;
|
||||
result.printBasic(ss);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
void createTestGraph()
|
||||
void createTestStorage()
|
||||
{
|
||||
if (m_graph.getNodeCount())
|
||||
if (m_storage.getGraph().getNodeCount())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_graph = utility::getGraphForCxxCode(
|
||||
m_storage.parseCxxCode(
|
||||
"class A\n"
|
||||
"{\n"
|
||||
"public:\n"
|
||||
@@ -149,5 +150,5 @@ private:
|
||||
);
|
||||
}
|
||||
|
||||
Graph m_graph;
|
||||
TestStorage m_storage;
|
||||
};
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include "data/graph/filter/GraphFilter.h"
|
||||
#include "data/graph/filter/GraphFilterImplementations.h"
|
||||
#include "utilityTest.h"
|
||||
#include "TestStorage.h"
|
||||
|
||||
class GraphFilterTestSuite : public CxxTest::TestSuite
|
||||
{
|
||||
@@ -26,7 +26,9 @@ public:
|
||||
TS_ASSERT_EQUALS(
|
||||
printedFilteredTestGraph(&filter),
|
||||
|
||||
"6 nodes: method:A field:count method:getCount method:process method:process undefined_function:B\n"
|
||||
"6 nodes: "
|
||||
"method:A::A field:A::count method:A::getCount method:A::process method:B::process "
|
||||
"undefined_function:B::B\n"
|
||||
"0 edges:\n"
|
||||
);
|
||||
}
|
||||
@@ -50,7 +52,7 @@ public:
|
||||
TS_ASSERT_EQUALS(
|
||||
printedFilteredTestGraph(&filter),
|
||||
|
||||
"5 nodes: method:A method:getCount method:process method:process function:main\n"
|
||||
"5 nodes: method:A::A method:A::getCount method:A::process method:B::process function:main\n"
|
||||
"0 edges:\n"
|
||||
);
|
||||
}
|
||||
@@ -62,7 +64,7 @@ public:
|
||||
TS_ASSERT_EQUALS(
|
||||
printedFilteredTestGraph(&filter),
|
||||
|
||||
"2 nodes: method:process method:process\n"
|
||||
"2 nodes: method:A::process method:B::process\n"
|
||||
"0 edges:\n"
|
||||
);
|
||||
}
|
||||
@@ -74,7 +76,7 @@ public:
|
||||
TS_ASSERT_EQUALS(
|
||||
printedFilteredTestGraph(&filter),
|
||||
|
||||
"2 nodes: field:count method:getCount\n"
|
||||
"2 nodes: field:A::count method:A::getCount\n"
|
||||
"0 edges:\n"
|
||||
);
|
||||
}
|
||||
@@ -86,7 +88,7 @@ public:
|
||||
TS_ASSERT_EQUALS(
|
||||
printedFilteredTestGraph(&filter),
|
||||
|
||||
"2 nodes: method:process method:process\n"
|
||||
"2 nodes: method:A::process method:B::process\n"
|
||||
"0 edges:\n"
|
||||
);
|
||||
}
|
||||
@@ -98,7 +100,7 @@ public:
|
||||
TS_ASSERT_EQUALS(
|
||||
printedFilteredTestGraph(&filter),
|
||||
|
||||
"1 nodes: method:process\n"
|
||||
"1 nodes: method:A::process\n"
|
||||
"0 edges:\n"
|
||||
);
|
||||
}
|
||||
@@ -119,7 +121,7 @@ public:
|
||||
TS_ASSERT_EQUALS(
|
||||
printedFilteredTestGraph(&filter2),
|
||||
|
||||
"2 nodes: method:getCount undefined_function:B\n"
|
||||
"2 nodes: method:A::getCount undefined_function:B::B\n"
|
||||
"0 edges:\n"
|
||||
);
|
||||
}
|
||||
@@ -131,7 +133,7 @@ public:
|
||||
TS_ASSERT_EQUALS(
|
||||
printedFilteredTestGraph(&filter),
|
||||
|
||||
"6 nodes: method:A field:count method:getCount method:process method:process function:main\n"
|
||||
"6 nodes: method:A::A field:A::count method:A::getCount method:A::process method:B::process function:main\n"
|
||||
"0 edges:\n"
|
||||
);
|
||||
}
|
||||
@@ -172,24 +174,24 @@ public:
|
||||
private:
|
||||
std::string printedFilteredTestGraph(GraphFilter* filter)
|
||||
{
|
||||
createTestGraph();
|
||||
createTestStorage();
|
||||
Graph result;
|
||||
|
||||
filter->apply(&m_graph, &result);
|
||||
filter->apply(&m_storage.getGraph(), &result);
|
||||
|
||||
std::stringstream ss;
|
||||
result.printBasic(ss);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
void createTestGraph()
|
||||
void createTestStorage()
|
||||
{
|
||||
if (m_graph.getNodeCount())
|
||||
if (m_storage.getGraph().getNodeCount())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_graph = utility::getGraphForCxxCode(
|
||||
m_storage.parseCxxCode(
|
||||
"class A\n"
|
||||
"{\n"
|
||||
"public:\n"
|
||||
@@ -228,5 +230,5 @@ private:
|
||||
);
|
||||
}
|
||||
|
||||
Graph m_graph;
|
||||
TestStorage m_storage;
|
||||
};
|
||||
|
||||
+26
-279
@@ -246,289 +246,51 @@ public:
|
||||
|
||||
void test_graph_saves_nodes()
|
||||
{
|
||||
TestGraph graph;
|
||||
Node* a = graph.createNodeHierarchy("A");
|
||||
Node* b = graph.createNodeHierarchy("B");
|
||||
Graph graph;
|
||||
Node a(Node::NODE_UNDEFINED, "A");
|
||||
Node b(Node::NODE_UNDEFINED, "B");
|
||||
|
||||
graph.addNode(&a);
|
||||
graph.addNode(&b);
|
||||
|
||||
TS_ASSERT_EQUALS(2, graph.getNodeCount());
|
||||
TS_ASSERT_EQUALS(0, graph.getEdgeCount());
|
||||
|
||||
TS_ASSERT_EQUALS(a, graph.getNode("A"));
|
||||
TS_ASSERT_EQUALS("A", graph.getNode("A")->getName());
|
||||
TS_ASSERT(graph.getNodeById(a.getId()));
|
||||
TS_ASSERT_EQUALS("A", graph.getNodeById(a.getId())->getName());
|
||||
|
||||
TS_ASSERT_EQUALS(b, graph.getNode("B"));
|
||||
TS_ASSERT_EQUALS("B", graph.getNode("B")->getName());
|
||||
TS_ASSERT(graph.getNodeById(b.getId()));
|
||||
TS_ASSERT_EQUALS("B", graph.getNodeById(b.getId())->getName());
|
||||
|
||||
TS_ASSERT(!graph.getNode("C"));
|
||||
TS_ASSERT(!graph.getNodeById(0));
|
||||
}
|
||||
|
||||
void test_graph_saves_edges()
|
||||
{
|
||||
TestGraph graph;
|
||||
Node* a = graph.createNodeHierarchy("A");
|
||||
Node* b = graph.createNodeHierarchy("B");
|
||||
Edge* e = graph.createEdge(Edge::EDGE_TYPE_OF, a, b);
|
||||
Graph graph;
|
||||
|
||||
TS_ASSERT_EQUALS(e, graph.getEdge(Edge::EDGE_TYPE_OF, a, b));
|
||||
TS_ASSERT(!graph.getEdge(Edge::EDGE_CALL, a, b));
|
||||
}
|
||||
Node a(Node::NODE_FUNCTION, "A");
|
||||
Node b(Node::NODE_FUNCTION, "B");
|
||||
|
||||
void test_graph_finds_nodes_and_edges_by_id()
|
||||
{
|
||||
TestGraph graph;
|
||||
Node* a = graph.createNodeHierarchy("A");
|
||||
Node* b = graph.createNodeHierarchy("B");
|
||||
Edge* e = graph.createEdge(Edge::EDGE_TYPE_OF, a, b);
|
||||
Edge e(Edge::EDGE_CALL, &a, &b);
|
||||
|
||||
TS_ASSERT(!graph.getEdgeById(a->getId()));
|
||||
TS_ASSERT_EQUALS(a, graph.getNodeById(a->getId()));
|
||||
TS_ASSERT_EQUALS(a, graph.getTokenById(a->getId()));
|
||||
graph.addEdge(&e);
|
||||
|
||||
TS_ASSERT(!graph.getNodeById(e->getId()));
|
||||
TS_ASSERT_EQUALS(e, graph.getEdgeById(e->getId()));
|
||||
TS_ASSERT_EQUALS(e, graph.getTokenById(e->getId()));
|
||||
}
|
||||
TS_ASSERT_EQUALS(0, graph.getNodeCount());
|
||||
TS_ASSERT_EQUALS(0, graph.getEdgeCount());
|
||||
|
||||
void test_graph_creates_child_edges()
|
||||
{
|
||||
TestGraph graph;
|
||||
Node* a = graph.createNodeHierarchy("A");
|
||||
Node* ab = graph.createNodeHierarchy("A::B");
|
||||
TS_ASSERT(!graph.getEdgeById(e.getId()));
|
||||
|
||||
graph.addNode(&a);
|
||||
graph.addNode(&b);
|
||||
|
||||
graph.addEdge(&e);
|
||||
|
||||
TS_ASSERT_EQUALS(2, graph.getNodeCount());
|
||||
TS_ASSERT_EQUALS(1, graph.getEdgeCount());
|
||||
|
||||
TS_ASSERT(ab->getMemberEdge());
|
||||
TS_ASSERT(graph.getEdge(Edge::EDGE_MEMBER, a, ab));
|
||||
TS_ASSERT_EQUALS(ab->getMemberEdge(), graph.getEdge(Edge::EDGE_MEMBER, a, ab));
|
||||
TS_ASSERT_EQUALS(ab->getMemberEdge()->getFrom(), a);
|
||||
TS_ASSERT_EQUALS(ab->getMemberEdge()->getTo(), ab);
|
||||
TS_ASSERT_EQUALS(ab->getParentNode(), a);
|
||||
}
|
||||
|
||||
void test_graph_removes_nodes()
|
||||
{
|
||||
TestGraph graph;
|
||||
Node* a = graph.createNodeHierarchy("A");
|
||||
Node* b = graph.createNodeHierarchy("B");
|
||||
graph.createNodeHierarchy("A::C");
|
||||
graph.createNodeHierarchy("A::C::D");
|
||||
graph.createEdge(Edge::EDGE_TYPE_OF, a, b);
|
||||
|
||||
graph.removeNode(a);
|
||||
|
||||
TS_ASSERT_EQUALS(1, graph.getNodeCount());
|
||||
TS_ASSERT_EQUALS(0, graph.getEdgeCount());
|
||||
|
||||
TS_ASSERT(!graph.getNode("A"));
|
||||
TS_ASSERT(!graph.getNode("A::C"));
|
||||
TS_ASSERT(graph.getNode("B"));
|
||||
}
|
||||
|
||||
void test_graph_removes_edge()
|
||||
{
|
||||
TestGraph graph;
|
||||
Node* a = graph.createNodeHierarchy("A");
|
||||
Node* b = graph.createNodeHierarchy("B");
|
||||
Edge* e = graph.createEdge(Edge::EDGE_TYPE_OF, a, b);
|
||||
|
||||
graph.removeEdge(e);
|
||||
|
||||
TS_ASSERT_EQUALS(2, graph.getNodeCount());
|
||||
TS_ASSERT_EQUALS(0, graph.getEdgeCount());
|
||||
|
||||
TS_ASSERT(graph.getNode("A"));
|
||||
TS_ASSERT(graph.getNode("B"));
|
||||
}
|
||||
|
||||
void test_graph_can_not_remove_member_edge()
|
||||
{
|
||||
TestGraph graph;
|
||||
Node* a = graph.createNodeHierarchy("A");
|
||||
Node* b = graph.createNodeHierarchy("B");
|
||||
Node* c = graph.createNodeHierarchy("A::C");
|
||||
graph.createEdge(Edge::EDGE_TYPE_OF, a, b);
|
||||
|
||||
graph.removeEdge(c->getMemberEdge());
|
||||
|
||||
TS_ASSERT_EQUALS(3, graph.getNodeCount());
|
||||
TS_ASSERT_EQUALS(2, graph.getEdgeCount());
|
||||
|
||||
TS_ASSERT(graph.getNode("A"));
|
||||
TS_ASSERT(graph.getNode("B"));
|
||||
TS_ASSERT(graph.getNode("A::C"));
|
||||
}
|
||||
|
||||
void test_node_in_graph_finds_child_node()
|
||||
{
|
||||
TestGraph graph;
|
||||
Node* a = graph.createNodeHierarchy("A");
|
||||
Node* b = graph.createNodeHierarchy("A::B");
|
||||
Node* c = graph.createNodeHierarchy("A::C");
|
||||
|
||||
Node* x = a->findChildNode(
|
||||
[](Node* n)
|
||||
{
|
||||
return n->getName() == "C";
|
||||
}
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(x, c);
|
||||
TS_ASSERT_DIFFERS(x, b);
|
||||
}
|
||||
|
||||
void test_node_has_name_and_full_name()
|
||||
{
|
||||
TestGraph graph;
|
||||
Node* n = graph.createNodeHierarchy("A::B::C");
|
||||
|
||||
TS_ASSERT_EQUALS(n->getName(), "C");
|
||||
TS_ASSERT_EQUALS(n->getFullName(), "A::B::C");
|
||||
}
|
||||
|
||||
void test_edge_has_name()
|
||||
{
|
||||
TestGraph graph;
|
||||
Node* a = graph.createNodeHierarchy(Node::NODE_FUNCTION, "A");
|
||||
Node* b = graph.createNodeHierarchy(Node::NODE_FUNCTION, "B");
|
||||
Edge* e = graph.createEdge(Edge::EDGE_CALL, a, b);
|
||||
|
||||
TS_ASSERT_EQUALS(e->getName(), "call:A->B");
|
||||
}
|
||||
|
||||
void test_graph_saves_nodes_with_distinct_signatures()
|
||||
{
|
||||
TestGraph graph;
|
||||
Node* a1 = graph.createNodeHierarchyWithDistinctSignature(Node::NODE_FUNCTION, "A", "A1");
|
||||
Node* a2 = graph.createNodeHierarchyWithDistinctSignature(Node::NODE_FUNCTION, "A", "A2");
|
||||
Node* a3 = graph.createNodeHierarchyWithDistinctSignature(Node::NODE_FUNCTION, "A", "A2");
|
||||
|
||||
TS_ASSERT_DIFFERS(a1, a2);
|
||||
TS_ASSERT_EQUALS(a2, a3);
|
||||
|
||||
Node* c1 = graph.createNodeHierarchyWithDistinctSignature(Node::NODE_METHOD, "B::C", "C1");
|
||||
Node* c2 = graph.createNodeHierarchyWithDistinctSignature(Node::NODE_METHOD, "B::C", "C2");
|
||||
Node* c3 = graph.createNodeHierarchyWithDistinctSignature(Node::NODE_METHOD, "B::C", "C2");
|
||||
|
||||
TS_ASSERT_DIFFERS(c1, c2);
|
||||
TS_ASSERT_EQUALS(c2, c3);
|
||||
}
|
||||
|
||||
void test_graph_saves_nodes_as_undefined_function_when_using_signatures()
|
||||
{
|
||||
TestGraph graph;
|
||||
Node* a1 = graph.createNodeHierarchyWithDistinctSignature("A", "A1");
|
||||
Node* a2 = graph.createNodeHierarchyWithDistinctSignature("A", "A2");
|
||||
|
||||
TS_ASSERT_DIFFERS(a1, a2);
|
||||
TS_ASSERT_EQUALS(a1->getType(), Node::NODE_UNDEFINED_FUNCTION);
|
||||
TS_ASSERT_EQUALS(a2->getType(), Node::NODE_UNDEFINED_FUNCTION);
|
||||
}
|
||||
|
||||
void test_graph_creates_multiple_nodes_as_undefined_nodes()
|
||||
{
|
||||
TestGraph graph;
|
||||
Node* abc = graph.createNodeHierarchy("A::B::C");
|
||||
|
||||
TS_ASSERT_EQUALS(3, graph.getNodeCount());
|
||||
TS_ASSERT_EQUALS(2, graph.getEdgeCount());
|
||||
|
||||
TS_ASSERT_EQUALS("A", graph.getNode("A")->getName());
|
||||
TS_ASSERT_EQUALS(Node::NODE_UNDEFINED, graph.getNode("A")->getType());
|
||||
|
||||
TS_ASSERT_EQUALS("A::B", graph.getNode("A::B")->getFullName());
|
||||
TS_ASSERT_EQUALS(Node::NODE_UNDEFINED, graph.getNode("A::B")->getType());
|
||||
|
||||
TS_ASSERT_EQUALS(abc, graph.getNode("A::B::C"));
|
||||
TS_ASSERT_EQUALS("A::B::C", graph.getNode("A::B::C")->getFullName());
|
||||
TS_ASSERT_EQUALS(Node::NODE_UNDEFINED, graph.getNode("A::B::C")->getType());
|
||||
|
||||
Node* abcde = graph.createNodeHierarchy("A::B::C::D::E");
|
||||
|
||||
TS_ASSERT_EQUALS(5, graph.getNodeCount());
|
||||
TS_ASSERT_EQUALS(4, graph.getEdgeCount());
|
||||
|
||||
TS_ASSERT_EQUALS("A::B::C::D", graph.getNode("A::B::C::D")->getFullName());
|
||||
TS_ASSERT_EQUALS(Node::NODE_UNDEFINED, graph.getNode("A::B::C::D")->getType());
|
||||
|
||||
TS_ASSERT_EQUALS(abcde, graph.getNode("A::B::C::D::E"));
|
||||
TS_ASSERT_EQUALS("A::B::C::D::E", graph.getNode("A::B::C::D::E")->getFullName());
|
||||
TS_ASSERT_EQUALS(Node::NODE_UNDEFINED, graph.getNode("A::B::C::D::E")->getType());
|
||||
}
|
||||
|
||||
void test_visit_each_token_on_graph()
|
||||
{
|
||||
TestGraph graph;
|
||||
Node* a = graph.createNodeHierarchy("A");
|
||||
Node* b = graph.createNodeHierarchy("B");
|
||||
Node* c = graph.createNodeHierarchy("C");
|
||||
Edge* e = graph.createEdge(Edge::EDGE_TYPE_OF, a, b);
|
||||
Edge* f = graph.createEdge(Edge::EDGE_TYPE_OF, b, c);
|
||||
|
||||
unsigned long idSum = a->getId() + b->getId() + c->getId() + e->getId() + f->getId();
|
||||
unsigned long checkSum = 0;
|
||||
|
||||
graph.forEachToken(
|
||||
[&checkSum](Token* t)
|
||||
{
|
||||
checkSum += t->getId();
|
||||
}
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(idSum, checkSum);
|
||||
}
|
||||
|
||||
void test_visit_each_edge_of_type_on_node()
|
||||
{
|
||||
TestGraph graph;
|
||||
Node* a = graph.createNodeHierarchy("A");
|
||||
Node* ab = graph.createNodeHierarchy("A::B");
|
||||
Node* ac = graph.createNodeHierarchy("A::C");
|
||||
|
||||
graph.createEdge(Edge::EDGE_TYPE_OF, a, ab);
|
||||
graph.createEdge(Edge::EDGE_CALL, a, ac);
|
||||
|
||||
unsigned int sum = 0;
|
||||
a->forEachEdgeOfType(Edge::EDGE_MEMBER, [&sum](Edge* e)
|
||||
{
|
||||
TS_ASSERT_EQUALS(Edge::EDGE_MEMBER, e->getType());
|
||||
sum++;
|
||||
});
|
||||
|
||||
TS_ASSERT_EQUALS(sum, 2);
|
||||
}
|
||||
|
||||
void test_creating_plain_copy_of_graph_part()
|
||||
{
|
||||
TestGraph graph;
|
||||
Node* b = graph.createNodeHierarchy("A::B");
|
||||
graph.createNodeHierarchy("A::B::C");
|
||||
Node* d = graph.createNodeHierarchy("D");
|
||||
Node* e = graph.createNodeHierarchy("E");
|
||||
graph.createEdge(Edge::EDGE_TYPE_OF, d, b);
|
||||
graph.createEdge(Edge::EDGE_TYPE_OF, d, e);
|
||||
|
||||
TestGraph plainGraph;
|
||||
Node* x = graph.getNode("A::B");
|
||||
plainGraph.addNodeAsPlainCopy(x);
|
||||
|
||||
x->forEachEdge(
|
||||
[&plainGraph](Edge* e)
|
||||
{
|
||||
plainGraph.addNodeAsPlainCopy(e->getFrom());
|
||||
plainGraph.addNodeAsPlainCopy(e->getTo());
|
||||
plainGraph.addEdgeAsPlainCopy(e);
|
||||
}
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(4, plainGraph.getNodeCount());
|
||||
TS_ASSERT_EQUALS(3, plainGraph.getEdgeCount());
|
||||
|
||||
TS_ASSERT(plainGraph.getNode("A"));
|
||||
TS_ASSERT(plainGraph.getNode("A::B"));
|
||||
TS_ASSERT(plainGraph.getNode("A::B::C"));
|
||||
TS_ASSERT(plainGraph.getNode("D"));
|
||||
TS_ASSERT(!plainGraph.getNode("E"));
|
||||
TS_ASSERT(graph.getEdgeById(e.getId()));
|
||||
TS_ASSERT_EQUALS(Edge::EDGE_CALL, graph.getEdgeById(e.getId())->getType());
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -583,19 +345,4 @@ private:
|
||||
return std::make_shared<Test2Component>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
class TestGraph: public Graph
|
||||
{
|
||||
public:
|
||||
size_t getNodeCount() const
|
||||
{
|
||||
return getNodes().size();
|
||||
}
|
||||
|
||||
size_t getEdgeCount() const
|
||||
{
|
||||
return getEdges().size();
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
@@ -0,0 +1,332 @@
|
||||
#include "cxxtest/TestSuite.h"
|
||||
|
||||
#include "data/graph/StorageGraph.h"
|
||||
#include "data/SearchIndex.h"
|
||||
|
||||
class StorageGraphTestSuite : public CxxTest::TestSuite
|
||||
{
|
||||
public:
|
||||
void test_graph_saves_nodes()
|
||||
{
|
||||
TestStorageGraph graph;
|
||||
Node* a = graph.createNodeHierarchy(Node::NODE_CLASS, "A");
|
||||
Node* b = graph.createNodeHierarchy(Node::NODE_CLASS, "B");
|
||||
|
||||
TS_ASSERT(a);
|
||||
TS_ASSERT(b);
|
||||
|
||||
TS_ASSERT_EQUALS("A", a->getName());
|
||||
TS_ASSERT_EQUALS("B", b->getName());
|
||||
|
||||
TS_ASSERT_EQUALS(2, graph.getNodeCount());
|
||||
TS_ASSERT_EQUALS(0, graph.getEdgeCount());
|
||||
|
||||
TS_ASSERT_EQUALS(a, graph.getNode("A"));
|
||||
TS_ASSERT_EQUALS("A", graph.getNode("A")->getName());
|
||||
|
||||
TS_ASSERT_EQUALS(b, graph.getNode("B"));
|
||||
TS_ASSERT_EQUALS("B", graph.getNode("B")->getName());
|
||||
|
||||
TS_ASSERT(!graph.getNode("C"));
|
||||
}
|
||||
|
||||
void test_graph_saves_edges()
|
||||
{
|
||||
TestStorageGraph graph;
|
||||
Node* a = graph.createNodeHierarchy(Node::NODE_GLOBAL_VARIABLE, "A");
|
||||
Node* b = graph.createNodeHierarchy(Node::NODE_CLASS, "B");
|
||||
Edge* e = graph.createEdge(Edge::EDGE_TYPE_OF, a, b);
|
||||
|
||||
TS_ASSERT_EQUALS(e, graph.getEdge(Edge::EDGE_TYPE_OF, a, b));
|
||||
TS_ASSERT(!graph.getEdge(Edge::EDGE_CALL, a, b));
|
||||
}
|
||||
|
||||
void test_graph_finds_nodes_and_edges_by_id()
|
||||
{
|
||||
TestStorageGraph graph;
|
||||
Node* a = graph.createNodeHierarchy(Node::NODE_GLOBAL_VARIABLE, "A");
|
||||
Node* b = graph.createNodeHierarchy(Node::NODE_CLASS, "B");
|
||||
Edge* e = graph.createEdge(Edge::EDGE_TYPE_OF, a, b);
|
||||
|
||||
TS_ASSERT(!graph.getEdgeById(a->getId()));
|
||||
TS_ASSERT_EQUALS(a, graph.getNodeById(a->getId()));
|
||||
TS_ASSERT_EQUALS(a, graph.getTokenById(a->getId()));
|
||||
|
||||
TS_ASSERT(!graph.getNodeById(e->getId()));
|
||||
TS_ASSERT_EQUALS(e, graph.getEdgeById(e->getId()));
|
||||
TS_ASSERT_EQUALS(e, graph.getTokenById(e->getId()));
|
||||
}
|
||||
|
||||
void test_graph_creates_child_edges()
|
||||
{
|
||||
TestStorageGraph graph;
|
||||
Node* a = graph.createNodeHierarchy(Node::NODE_CLASS, "A");
|
||||
Node* ab = graph.createNodeHierarchy(Node::NODE_CLASS, "A::B");
|
||||
|
||||
TS_ASSERT_EQUALS(2, graph.getNodeCount());
|
||||
TS_ASSERT_EQUALS(1, graph.getEdgeCount());
|
||||
|
||||
TS_ASSERT(ab->getMemberEdge());
|
||||
TS_ASSERT(graph.getEdge(Edge::EDGE_MEMBER, a, ab));
|
||||
TS_ASSERT_EQUALS(ab->getMemberEdge(), graph.getEdge(Edge::EDGE_MEMBER, a, ab));
|
||||
TS_ASSERT_EQUALS(ab->getMemberEdge()->getFrom(), a);
|
||||
TS_ASSERT_EQUALS(ab->getMemberEdge()->getTo(), ab);
|
||||
TS_ASSERT_EQUALS(ab->getParentNode(), a);
|
||||
}
|
||||
|
||||
void test_graph_removes_nodes()
|
||||
{
|
||||
TestStorageGraph graph;
|
||||
Node* a = graph.createNodeHierarchy(Node::NODE_CLASS, "A");
|
||||
Node* b = graph.createNodeHierarchy(Node::NODE_GLOBAL_VARIABLE, "B");
|
||||
graph.createNodeHierarchy(Node::NODE_CLASS, "A::C");
|
||||
graph.createNodeHierarchy(Node::NODE_CLASS, "A::C::D");
|
||||
graph.createEdge(Edge::EDGE_TYPE_OF, b, a);
|
||||
|
||||
graph.removeNode(a);
|
||||
|
||||
TS_ASSERT_EQUALS(1, graph.getNodeCount());
|
||||
TS_ASSERT_EQUALS(0, graph.getEdgeCount());
|
||||
|
||||
TS_ASSERT(!graph.getNode("A"));
|
||||
TS_ASSERT(!graph.getNode("A::C"));
|
||||
TS_ASSERT(graph.getNode("B"));
|
||||
}
|
||||
|
||||
void test_graph_removes_edge()
|
||||
{
|
||||
TestStorageGraph graph;
|
||||
Node* a = graph.createNodeHierarchy(Node::NODE_GLOBAL_VARIABLE, "A");
|
||||
Node* b = graph.createNodeHierarchy(Node::NODE_CLASS, "B");
|
||||
Edge* e = graph.createEdge(Edge::EDGE_TYPE_OF, a, b);
|
||||
|
||||
graph.removeEdge(e);
|
||||
|
||||
TS_ASSERT_EQUALS(2, graph.getNodeCount());
|
||||
TS_ASSERT_EQUALS(0, graph.getEdgeCount());
|
||||
|
||||
TS_ASSERT(graph.getNode("A"));
|
||||
TS_ASSERT(graph.getNode("B"));
|
||||
}
|
||||
|
||||
void test_graph_can_not_remove_member_edge()
|
||||
{
|
||||
TestStorageGraph graph;
|
||||
Node* a = graph.createNodeHierarchy(Node::NODE_CLASS, "A");
|
||||
Node* b = graph.createNodeHierarchy(Node::NODE_GLOBAL_VARIABLE, "B");
|
||||
Node* c = graph.createNodeHierarchy(Node::NODE_CLASS, "A::C");
|
||||
graph.createEdge(Edge::EDGE_TYPE_OF, b, a);
|
||||
|
||||
graph.removeEdge(c->getMemberEdge());
|
||||
|
||||
TS_ASSERT_EQUALS(3, graph.getNodeCount());
|
||||
TS_ASSERT_EQUALS(2, graph.getEdgeCount());
|
||||
|
||||
TS_ASSERT(graph.getNode("A"));
|
||||
TS_ASSERT(graph.getNode("B"));
|
||||
TS_ASSERT(graph.getNode("A::C"));
|
||||
}
|
||||
|
||||
void test_node_in_graph_finds_child_node()
|
||||
{
|
||||
TestStorageGraph graph;
|
||||
Node* a = graph.createNodeHierarchy(Node::NODE_CLASS, "A");
|
||||
Node* b = graph.createNodeHierarchy(Node::NODE_CLASS, "A::B");
|
||||
Node* c = graph.createNodeHierarchy(Node::NODE_CLASS, "A::C");
|
||||
|
||||
Node* x = a->findChildNode(
|
||||
[](Node* n)
|
||||
{
|
||||
return n->getName() == "C";
|
||||
}
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(x, c);
|
||||
TS_ASSERT_DIFFERS(x, b);
|
||||
}
|
||||
|
||||
void test_node_has_name_and_full_name()
|
||||
{
|
||||
TestStorageGraph graph;
|
||||
Node* n = graph.createNodeHierarchy(Node::NODE_CLASS, "A::B::C");
|
||||
|
||||
TS_ASSERT_EQUALS(n->getName(), "C");
|
||||
TS_ASSERT_EQUALS(n->getFullName(), "A::B::C");
|
||||
}
|
||||
|
||||
void test_edge_has_name()
|
||||
{
|
||||
TestStorageGraph graph;
|
||||
Node* a = graph.createNodeHierarchy(Node::NODE_FUNCTION, "A");
|
||||
Node* b = graph.createNodeHierarchy(Node::NODE_FUNCTION, "B");
|
||||
Edge* e = graph.createEdge(Edge::EDGE_CALL, a, b);
|
||||
|
||||
TS_ASSERT_EQUALS(e->getName(), "call:A->B");
|
||||
}
|
||||
|
||||
void test_graph_saves_nodes_with_distinct_signatures()
|
||||
{
|
||||
TestStorageGraph graph;
|
||||
Node* a1 = graph.createNodeHierarchyWithDistinctSignature(Node::NODE_FUNCTION, "A", "A1");
|
||||
Node* a2 = graph.createNodeHierarchyWithDistinctSignature(Node::NODE_FUNCTION, "A", "A2");
|
||||
Node* a3 = graph.createNodeHierarchyWithDistinctSignature(Node::NODE_FUNCTION, "A", "A2");
|
||||
|
||||
TS_ASSERT_DIFFERS(a1, a2);
|
||||
TS_ASSERT_EQUALS(a2, a3);
|
||||
|
||||
Node* c1 = graph.createNodeHierarchyWithDistinctSignature(Node::NODE_METHOD, "B::C", "C1");
|
||||
Node* c2 = graph.createNodeHierarchyWithDistinctSignature(Node::NODE_METHOD, "B::C", "C2");
|
||||
Node* c3 = graph.createNodeHierarchyWithDistinctSignature(Node::NODE_METHOD, "B::C", "C2");
|
||||
|
||||
TS_ASSERT_DIFFERS(c1, c2);
|
||||
TS_ASSERT_EQUALS(c2, c3);
|
||||
}
|
||||
|
||||
void test_graph_creates_multiple_nodes_as_undefined_nodes()
|
||||
{
|
||||
TestStorageGraph graph;
|
||||
Node* abc = graph.createNodeHierarchy(Node::NODE_CLASS, "A::B::C");
|
||||
|
||||
TS_ASSERT_EQUALS(3, graph.getNodeCount());
|
||||
TS_ASSERT_EQUALS(2, graph.getEdgeCount());
|
||||
|
||||
TS_ASSERT_EQUALS("A", graph.getNode("A")->getName());
|
||||
TS_ASSERT_EQUALS(Node::NODE_UNDEFINED, graph.getNode("A")->getType());
|
||||
|
||||
TS_ASSERT_EQUALS("A::B", graph.getNode("A::B")->getFullName());
|
||||
TS_ASSERT_EQUALS(Node::NODE_UNDEFINED, graph.getNode("A::B")->getType());
|
||||
|
||||
TS_ASSERT_EQUALS(abc, graph.getNode("A::B::C"));
|
||||
TS_ASSERT_EQUALS("A::B::C", graph.getNode("A::B::C")->getFullName());
|
||||
TS_ASSERT_EQUALS(Node::NODE_CLASS, graph.getNode("A::B::C")->getType());
|
||||
|
||||
Node* abcde = graph.createNodeHierarchy(Node::NODE_CLASS, "A::B::C::D::E");
|
||||
|
||||
TS_ASSERT_EQUALS(5, graph.getNodeCount());
|
||||
TS_ASSERT_EQUALS(4, graph.getEdgeCount());
|
||||
|
||||
TS_ASSERT_EQUALS("A::B::C::D", graph.getNode("A::B::C::D")->getFullName());
|
||||
TS_ASSERT_EQUALS(Node::NODE_UNDEFINED, graph.getNode("A::B::C::D")->getType());
|
||||
|
||||
TS_ASSERT_EQUALS(abcde, graph.getNode("A::B::C::D::E"));
|
||||
TS_ASSERT_EQUALS("A::B::C::D::E", graph.getNode("A::B::C::D::E")->getFullName());
|
||||
TS_ASSERT_EQUALS(Node::NODE_CLASS, graph.getNode("A::B::C::D::E")->getType());
|
||||
}
|
||||
|
||||
void test_visit_each_token_on_graph()
|
||||
{
|
||||
TestStorageGraph graph;
|
||||
Node* a = graph.createNodeHierarchy(Node::NODE_CLASS, "A");
|
||||
Node* b = graph.createNodeHierarchy(Node::NODE_GLOBAL_VARIABLE, "B");
|
||||
Node* c = graph.createNodeHierarchy(Node::NODE_GLOBAL_VARIABLE, "C");
|
||||
Edge* e = graph.createEdge(Edge::EDGE_TYPE_OF, b, a);
|
||||
Edge* f = graph.createEdge(Edge::EDGE_TYPE_OF, c, a);
|
||||
|
||||
unsigned long idSum = a->getId() + b->getId() + c->getId() + e->getId() + f->getId();
|
||||
unsigned long checkSum = 0;
|
||||
|
||||
graph.forEachToken(
|
||||
[&checkSum](Token* t)
|
||||
{
|
||||
checkSum += t->getId();
|
||||
}
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(idSum, checkSum);
|
||||
}
|
||||
|
||||
void test_visit_each_edge_of_type_on_node()
|
||||
{
|
||||
TestStorageGraph graph;
|
||||
Node* a = graph.createNodeHierarchy(Node::NODE_CLASS, "A");
|
||||
Node* ab = graph.createNodeHierarchy(Node::NODE_FIELD, "A::B");
|
||||
Node* ac = graph.createNodeHierarchy(Node::NODE_METHOD, "A::C");
|
||||
|
||||
graph.createEdge(Edge::EDGE_TYPE_OF, ab, a);
|
||||
graph.createEdge(Edge::EDGE_USAGE, ac, ab);
|
||||
|
||||
unsigned int sum = 0;
|
||||
a->forEachEdgeOfType(Edge::EDGE_MEMBER, [&sum](Edge* e)
|
||||
{
|
||||
TS_ASSERT_EQUALS(Edge::EDGE_MEMBER, e->getType());
|
||||
sum++;
|
||||
});
|
||||
|
||||
TS_ASSERT_EQUALS(sum, 2);
|
||||
}
|
||||
|
||||
void test_creating_plain_copy_of_graph_part()
|
||||
{
|
||||
TestStorageGraph graph;
|
||||
Node* b = graph.createNodeHierarchy(Node::NODE_CLASS, "A::B");
|
||||
Node* c = graph.createNodeHierarchy(Node::NODE_CLASS, "A::B::C");
|
||||
Node* d = graph.createNodeHierarchy(Node::NODE_GLOBAL_VARIABLE, "D");
|
||||
Node* e = graph.createNodeHierarchy(Node::NODE_GLOBAL_VARIABLE, "E");
|
||||
graph.createEdge(Edge::EDGE_TYPE_OF, d, b);
|
||||
graph.createEdge(Edge::EDGE_TYPE_OF, e, c);
|
||||
|
||||
TestStorageGraph plainGraph;
|
||||
Node* x = graph.getNode("A::B");
|
||||
plainGraph.addNodeAsPlainCopy(x);
|
||||
|
||||
x->forEachEdge(
|
||||
[&plainGraph](Edge* e)
|
||||
{
|
||||
plainGraph.addNodeAsPlainCopy(e->getFrom());
|
||||
plainGraph.addNodeAsPlainCopy(e->getTo());
|
||||
plainGraph.addEdgeAsPlainCopy(e);
|
||||
}
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(4, plainGraph.getNodeCount());
|
||||
TS_ASSERT_EQUALS(3, plainGraph.getEdgeCount());
|
||||
|
||||
TS_ASSERT(plainGraph.getNode("A"));
|
||||
TS_ASSERT(plainGraph.getNode("A::B"));
|
||||
TS_ASSERT(plainGraph.getNode("A::B::C"));
|
||||
TS_ASSERT(plainGraph.getNode("D"));
|
||||
TS_ASSERT(!plainGraph.getNode("E"));
|
||||
}
|
||||
|
||||
private:
|
||||
class TestStorageGraph
|
||||
: public StorageGraph
|
||||
{
|
||||
public:
|
||||
Node* createNodeHierarchy(Node::NodeType type, const std::string& name)
|
||||
{
|
||||
SearchIndex::SearchNode* searchNode = m_index.addNode(name);
|
||||
return StorageGraph::createNodeHierarchy(type, searchNode);
|
||||
}
|
||||
|
||||
Node* createNodeHierarchyWithDistinctSignature(
|
||||
Node::NodeType type, const std::string& name, const std::string& signature
|
||||
){
|
||||
SearchIndex::SearchNode* searchNode = m_index.addNode(name);
|
||||
return StorageGraph::createNodeHierarchyWithDistinctSignature(type, searchNode, signature);
|
||||
}
|
||||
|
||||
Node* getNode(const std::string& fullName) const
|
||||
{
|
||||
return findNode(
|
||||
[&fullName](Node* node)
|
||||
{
|
||||
return node->getFullName() == fullName;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
Edge* getEdge(Edge::EdgeType type, Node* from, Node* to) const
|
||||
{
|
||||
return from->findEdgeOfType(type,
|
||||
[to](Edge* edge)
|
||||
{
|
||||
return edge->getTo() == to;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private:
|
||||
SearchIndex m_index;
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,16 @@
|
||||
#include "TestStorage.h"
|
||||
|
||||
#include "utility/text/TextAccess.h"
|
||||
#include "data/parser/cxx/CxxParser.h"
|
||||
|
||||
void TestStorage::parseCxxCode(std::string code)
|
||||
{
|
||||
clear();
|
||||
CxxParser parser(this);
|
||||
parser.parseFile(TextAccess::createFromString(code));
|
||||
}
|
||||
|
||||
const Graph& TestStorage::getGraph() const
|
||||
{
|
||||
return Storage::getGraph();
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef TEST_STORAGE_H
|
||||
#define TEST_STORAGE_H
|
||||
|
||||
#include "data/Storage.h"
|
||||
|
||||
class TestStorage
|
||||
: public Storage
|
||||
{
|
||||
public:
|
||||
void parseCxxCode(std::string code);
|
||||
const Graph& getGraph() const;
|
||||
};
|
||||
|
||||
#endif // TEST_STORAGE_H
|
||||
@@ -1,27 +0,0 @@
|
||||
#include "utilityTest.h"
|
||||
|
||||
#include "data/graph/Graph.h"
|
||||
#include "data/Storage.h"
|
||||
#include "utility/text/TextAccess.h"
|
||||
#include "data/parser/cxx/CxxParser.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
class TestStorage
|
||||
: public Storage
|
||||
{
|
||||
public:
|
||||
const Graph& getGraph() const
|
||||
{
|
||||
return Storage::getGraph();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Graph utility::getGraphForCxxCode(std::string code)
|
||||
{
|
||||
TestStorage storage;
|
||||
CxxParser parser(&storage);
|
||||
parser.parseFile(TextAccess::createFromString(code));
|
||||
return storage.getGraph();
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
#ifndef UTILITY_TEST_H
|
||||
#define UTILITY_TEST_H
|
||||
|
||||
#include <string>
|
||||
|
||||
class Graph;
|
||||
|
||||
namespace utility
|
||||
{
|
||||
Graph getGraphForCxxCode(std::string code);
|
||||
}
|
||||
|
||||
#endif // UTILITY_TEST_H
|
||||
Reference in New Issue
Block a user