diff --git a/bin/test/data/log/test_log.txt b/bin/test/data/log/test_log.txt index ae097708..148d0610 100644 --- a/bin/test/data/log/test_log.txt +++ b/bin/test/data/log/test_log.txt @@ -4,6 +4,36 @@ Node.cpp WARNING: Cannot change NodeType after it was already set from namespace Edge.cpp ERROR: Nodes are not plain copies. Graph.cpp ERROR: Can't remove member edge, without removing the child node. Edge.cpp ERROR: Edge call can't go from Node undefined to Node undefined +Storage.cpp INFO: class: A +Storage.cpp INFO: method: A::A +Storage.cpp INFO: global usage: A::A -> A::count +Storage.cpp INFO: method: A::getCount +Storage.cpp INFO: global usage: A::getCount -> A::count +Storage.cpp INFO: method: A::process +Storage.cpp INFO: field: A::count +Storage.cpp INFO: class: B +Storage.cpp INFO: inheritance: B : A +Storage.cpp INFO: method: B::process +Storage.cpp INFO: type usage: B::process -> int +Storage.cpp INFO: function: main +Storage.cpp INFO: type usage: main -> B +Storage.cpp INFO: call: main -> B::B +Storage.cpp INFO: call: main -> A::getCount +Storage.cpp INFO: class: A +Storage.cpp INFO: method: A::A +Storage.cpp INFO: global usage: A::A -> A::count +Storage.cpp INFO: method: A::getCount +Storage.cpp INFO: global usage: A::getCount -> A::count +Storage.cpp INFO: method: A::process +Storage.cpp INFO: field: A::count +Storage.cpp INFO: class: B +Storage.cpp INFO: inheritance: B : A +Storage.cpp INFO: method: B::process +Storage.cpp INFO: type usage: B::process -> int +Storage.cpp INFO: function: main +Storage.cpp INFO: type usage: main -> B +Storage.cpp INFO: call: main -> B::B +Storage.cpp INFO: call: main -> A::getCount Settings.cpp WARNING: File for Settings not found. ConfigManager.cpp ERROR: value Bool is not present in config. ConfigManager.cpp ERROR: value Int is not present in config. diff --git a/src/lib/Project.cpp b/src/lib/Project.cpp index dc0f1d65..d09f89f4 100644 --- a/src/lib/Project.cpp +++ b/src/lib/Project.cpp @@ -57,7 +57,7 @@ void Project::parseCode() extensions.push_back(".h"); extensions.push_back(".hpp"); - CxxParser parser(m_storage); + CxxParser parser(m_storage.get()); parser.parseFiles( FileSystem::getSourceFilesFromDirectory(ProjectSettings::getInstance()->getSourcePath(), extensions) ); diff --git a/src/lib/data/Storage.cpp b/src/lib/data/Storage.cpp index 67699429..38be2ce2 100644 --- a/src/lib/data/Storage.cpp +++ b/src/lib/data/Storage.cpp @@ -628,6 +628,11 @@ TokenLocationFile Storage::getTokenLocationsForLinesInFile( return ret; } +const Graph& Storage::getGraph() const +{ + return m_graph; +} + Token* Storage::getTokenWithId(Id tokenId) const { return m_graph.getTokenById(tokenId); diff --git a/src/lib/data/Storage.h b/src/lib/data/Storage.h index ccfba144..a107fb2b 100644 --- a/src/lib/data/Storage.h +++ b/src/lib/data/Storage.h @@ -94,6 +94,7 @@ public: ) const; protected: + const Graph& getGraph() const; Token* getTokenWithId(Id tokenId) const; std::vector getTokenLocationsForId(Id tokenId) const; diff --git a/src/lib/data/graph/Edge.cpp b/src/lib/data/graph/Edge.cpp index 7d11ccf2..bd068466 100644 --- a/src/lib/data/graph/Edge.cpp +++ b/src/lib/data/graph/Edge.cpp @@ -118,13 +118,13 @@ std::string Edge::getTypeString(EdgeType type) const case EDGE_MEMBER: return "child"; case EDGE_TYPE_OF: - return "type use"; + return "type_use"; case EDGE_RETURN_TYPE_OF: - return "return type"; + return "return_type"; case EDGE_PARAMETER_TYPE_OF: - return "parameter type"; + return "parameter_type"; case EDGE_TYPE_USAGE: - return "type usage"; + return "type_usage"; case EDGE_INHERITANCE: return "inheritance"; case EDGE_CALL: diff --git a/src/lib/data/graph/FilterableGraph.cpp b/src/lib/data/graph/FilterableGraph.cpp index 326416f7..c90b42a5 100644 --- a/src/lib/data/graph/FilterableGraph.cpp +++ b/src/lib/data/graph/FilterableGraph.cpp @@ -30,3 +30,24 @@ void FilterableGraph::print(std::ostream& ostream) const } ); } + +void FilterableGraph::printBasic(std::ostream& ostream) const +{ + ostream << getNodeCount() << " nodes:"; + forEachNode( + [&ostream](Node* n) + { + ostream << ' ' << n->getTypeString() << ':' << n->getFullName(); + } + ); + ostream << '\n'; + + ostream << getEdgeCount() << " edges:"; + forEachEdge( + [&ostream](Edge* e) + { + ostream << ' ' << e->getName(); + } + ); + ostream << '\n'; +} diff --git a/src/lib/data/graph/FilterableGraph.h b/src/lib/data/graph/FilterableGraph.h index 473a0984..01f06577 100644 --- a/src/lib/data/graph/FilterableGraph.h +++ b/src/lib/data/graph/FilterableGraph.h @@ -30,6 +30,7 @@ public: virtual size_t getEdgeCount() const = 0; void print(std::ostream& ostream) const; + void printBasic(std::ostream& ostream) const; }; #endif // FILTERABLE_GRAPH_H diff --git a/src/lib/data/graph/Graph.cpp b/src/lib/data/graph/Graph.cpp index 4aa9bc1f..f04ab877 100644 --- a/src/lib/data/graph/Graph.cpp +++ b/src/lib/data/graph/Graph.cpp @@ -14,6 +14,28 @@ Graph::~Graph() m_nodes.clear(); } +Graph& Graph::operator=(const Graph& other) +{ + if (&other != this) + { + other.forEachNode( + [this](Node* node) + { + addNodeAsPlainCopy(node); + } + ); + + other.forEachEdge( + [this](Edge* edge) + { + addEdgeAsPlainCopy(edge); + } + ); + } + + return *this; +} + void Graph::copy(const FilterableGraph* other) { clear(); diff --git a/src/lib/data/graph/Graph.h b/src/lib/data/graph/Graph.h index 79176e8c..299d3381 100644 --- a/src/lib/data/graph/Graph.h +++ b/src/lib/data/graph/Graph.h @@ -15,6 +15,7 @@ class Graph public: Graph(); virtual ~Graph(); + Graph& operator=(const Graph& other); // FilterableGraph implementation virtual void copy(const FilterableGraph* other); @@ -71,8 +72,6 @@ private: Edge* insertEdge(Edge::EdgeType type, Node* from, Node* to); void removeEdgeInternal(Edge* edge); - const std::string m_delimiter; - std::map> m_nodes; std::map> m_edges; }; diff --git a/src/lib/data/graph/Node.cpp b/src/lib/data/graph/Node.cpp index 1d52af43..1446fff8 100644 --- a/src/lib/data/graph/Node.cpp +++ b/src/lib/data/graph/Node.cpp @@ -268,7 +268,7 @@ std::string Node::getTypeString(NodeType type) const case NODE_UNDEFINED: return "undefined"; case NODE_UNDEFINED_FUNCTION: - return "undefined function"; + return "undefined_function"; case NODE_CLASS: return "class"; case NODE_STRUCT: diff --git a/src/lib/data/graph/filter/GraphFilterImplementations.h b/src/lib/data/graph/filter/GraphFilterImplementations.h index 8011fed3..f85cc557 100644 --- a/src/lib/data/graph/filter/GraphFilterImplementations.h +++ b/src/lib/data/graph/filter/GraphFilterImplementations.h @@ -56,22 +56,22 @@ class GraphFilterCommandNodeType : public GraphFilter { public: - GraphFilterCommandNodeType(Node::NodeType type) - : m_type(type) + GraphFilterCommandNodeType(Node::NodeTypeMask mask) + : m_mask(mask) { } protected: virtual void visitNode(Node* node) { - if (node->getType() == m_type) + if (node->isType(m_mask)) { addNode(node); } } private: - const Node::NodeType m_type; + const Node::NodeTypeMask m_mask; }; class GraphFilterCommandConst @@ -254,7 +254,6 @@ private: const bool m_super; }; - class GraphFilterToken : public GraphFilter { diff --git a/src/lib/data/parser/Parser.cpp b/src/lib/data/parser/Parser.cpp index 64e9b83a..d030de48 100644 --- a/src/lib/data/parser/Parser.cpp +++ b/src/lib/data/parser/Parser.cpp @@ -1,6 +1,6 @@ #include "data/parser/Parser.h" -Parser::Parser(std::shared_ptr client) +Parser::Parser(ParserClient* client) : m_client(client) { } diff --git a/src/lib/data/parser/Parser.h b/src/lib/data/parser/Parser.h index afa2b969..0843d310 100644 --- a/src/lib/data/parser/Parser.h +++ b/src/lib/data/parser/Parser.h @@ -12,14 +12,14 @@ class TextAccess; class Parser { public: - Parser(std::shared_ptr client); + Parser(ParserClient* client); virtual ~Parser(); virtual void parseFiles(const std::vector& filePaths) = 0; virtual void parseFile(std::shared_ptr textAccess) = 0; protected: - std::shared_ptr m_client; + ParserClient* m_client; }; #endif // PARSER_H diff --git a/src/lib/data/parser/cxx/ASTAction.cpp b/src/lib/data/parser/cxx/ASTAction.cpp index ce971bbf..3778bc13 100644 --- a/src/lib/data/parser/cxx/ASTAction.cpp +++ b/src/lib/data/parser/cxx/ASTAction.cpp @@ -1,6 +1,6 @@ #include "data/parser/cxx/ASTAction.h" -ASTAction::ASTAction(std::shared_ptr client) +ASTAction::ASTAction(ParserClient* client) : m_client(client) { } diff --git a/src/lib/data/parser/cxx/ASTAction.h b/src/lib/data/parser/cxx/ASTAction.h index 578f001a..abef9f57 100644 --- a/src/lib/data/parser/cxx/ASTAction.h +++ b/src/lib/data/parser/cxx/ASTAction.h @@ -9,13 +9,13 @@ class ASTAction : public clang::ASTFrontendAction { public: - explicit ASTAction(std::shared_ptr client); + explicit ASTAction(ParserClient* client); virtual ~ASTAction(); virtual clang::ASTConsumer* CreateASTConsumer(clang::CompilerInstance& compiler, llvm::StringRef inFile); private: - std::shared_ptr m_client; + ParserClient* m_client; }; #endif // AST_ACTION_H diff --git a/src/lib/data/parser/cxx/ASTActionFactory.cpp b/src/lib/data/parser/cxx/ASTActionFactory.cpp index 0afabf7e..1e921fc4 100644 --- a/src/lib/data/parser/cxx/ASTActionFactory.cpp +++ b/src/lib/data/parser/cxx/ASTActionFactory.cpp @@ -1,6 +1,6 @@ #include "data/parser/cxx/ASTActionFactory.h" -ASTActionFactory::ASTActionFactory(std::shared_ptr client) +ASTActionFactory::ASTActionFactory(ParserClient* client) : m_client(client) { } diff --git a/src/lib/data/parser/cxx/ASTActionFactory.h b/src/lib/data/parser/cxx/ASTActionFactory.h index 2b279020..321cb125 100644 --- a/src/lib/data/parser/cxx/ASTActionFactory.h +++ b/src/lib/data/parser/cxx/ASTActionFactory.h @@ -8,13 +8,13 @@ class ASTActionFactory : public clang::tooling::FrontendActionFactory { public: - explicit ASTActionFactory(std::shared_ptr client); + explicit ASTActionFactory(ParserClient* client); virtual ~ASTActionFactory(); virtual clang::FrontendAction* create(); private: - std::shared_ptr m_client; + ParserClient* m_client; }; #endif // AST_ACTION_FACTORY diff --git a/src/lib/data/parser/cxx/ASTConsumer.cpp b/src/lib/data/parser/cxx/ASTConsumer.cpp index 79316379..74591c8c 100644 --- a/src/lib/data/parser/cxx/ASTConsumer.cpp +++ b/src/lib/data/parser/cxx/ASTConsumer.cpp @@ -1,6 +1,6 @@ #include "data/parser/cxx/ASTConsumer.h" -ASTConsumer::ASTConsumer(clang::ASTContext* context, std::shared_ptr client) +ASTConsumer::ASTConsumer(clang::ASTContext* context, ParserClient* client) : m_visitor(context, client) { } diff --git a/src/lib/data/parser/cxx/ASTConsumer.h b/src/lib/data/parser/cxx/ASTConsumer.h index afda1602..5d5cbc85 100644 --- a/src/lib/data/parser/cxx/ASTConsumer.h +++ b/src/lib/data/parser/cxx/ASTConsumer.h @@ -9,7 +9,7 @@ class ASTConsumer : public clang::ASTConsumer { public: - explicit ASTConsumer(clang::ASTContext* context, std::shared_ptr client); + explicit ASTConsumer(clang::ASTContext* context, ParserClient* client); virtual ~ASTConsumer(); virtual void HandleTranslationUnit(clang::ASTContext& context); diff --git a/src/lib/data/parser/cxx/ASTVisitor.cpp b/src/lib/data/parser/cxx/ASTVisitor.cpp index 4ece8ce0..fe6e5fad 100644 --- a/src/lib/data/parser/cxx/ASTVisitor.cpp +++ b/src/lib/data/parser/cxx/ASTVisitor.cpp @@ -8,7 +8,7 @@ #include "data/parser/ParseVariable.h" #include "data/type/DataType.h" -ASTVisitor::ASTVisitor(clang::ASTContext* context, std::shared_ptr client) +ASTVisitor::ASTVisitor(clang::ASTContext* context, ParserClient* client) : m_context(context) , m_client(client) { diff --git a/src/lib/data/parser/cxx/ASTVisitor.h b/src/lib/data/parser/cxx/ASTVisitor.h index 26a583f3..2e3fe692 100644 --- a/src/lib/data/parser/cxx/ASTVisitor.h +++ b/src/lib/data/parser/cxx/ASTVisitor.h @@ -1,8 +1,6 @@ #ifndef AST_VISITOR_H #define AST_VISITOR_H -#include - #include "clang/AST/ASTContext.h" #include "clang/AST/RecursiveASTVisitor.h" @@ -14,7 +12,7 @@ class ASTVisitor , public ASTBodyVisitorClient { public: - ASTVisitor(clang::ASTContext* context, std::shared_ptr client); + ASTVisitor(clang::ASTContext* context, ParserClient* client); virtual ~ASTVisitor(); // Left for debugging purposes. Uncomment to see a colored ast-dump of the parsed file. @@ -66,7 +64,7 @@ private: ParseFunction getParseFunction(clang::FunctionDecl* declaration) const; clang::ASTContext* m_context; - std::shared_ptr m_client; + ParserClient* m_client; }; #endif // AST_VISITOR_H diff --git a/src/lib/data/parser/cxx/CxxParser.cpp b/src/lib/data/parser/cxx/CxxParser.cpp index b0800c9b..5ecc6df3 100644 --- a/src/lib/data/parser/cxx/CxxParser.cpp +++ b/src/lib/data/parser/cxx/CxxParser.cpp @@ -4,7 +4,7 @@ #include "utility/logging/logging.h" #include "utility/text/TextAccess.h" -CxxParser::CxxParser(std::shared_ptr client) +CxxParser::CxxParser(ParserClient* client) : Parser(client) { } diff --git a/src/lib/data/parser/cxx/CxxParser.h b/src/lib/data/parser/cxx/CxxParser.h index d785ddb1..08228c90 100644 --- a/src/lib/data/parser/cxx/CxxParser.h +++ b/src/lib/data/parser/cxx/CxxParser.h @@ -6,7 +6,7 @@ class CxxParser: public Parser { public: - CxxParser(std::shared_ptr client); + CxxParser(ParserClient* client); ~CxxParser(); virtual void parseFiles(const std::vector& filePaths); diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index dcec1d40..d887a25c 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -4,11 +4,16 @@ add_files( TestSuiteFixture.cpp TestSuiteFixture.h + utilityTest.cpp + utilityTest.h + ConfigManagerTestSuite.h CxxParserTestSuite.h DataTypeTestSuite.h FileSystemTestSuite.h GraphTestSuite.h + GraphFilterTestSuite.h + GraphFilterConductorTestSuite.h LogManagerTestSuite.h MessageQueueTestSuite.h QueryTreeTestSuite.h diff --git a/src/test/CxxParserTestSuite.h b/src/test/CxxParserTestSuite.h index 19d5cf12..77921730 100644 --- a/src/test/CxxParserTestSuite.h +++ b/src/test/CxxParserTestSuite.h @@ -975,29 +975,29 @@ public: void test_cxx_parser_parses_multiple_files() { - std::shared_ptr client = std::make_shared(); - CxxParser parser(client); + TestParserClient client; + CxxParser parser(&client); std::vector filePaths; filePaths.push_back("data/CxxParserTestSuite/header.h"); filePaths.push_back("data/CxxParserTestSuite/code.cpp"); parser.parseFiles(filePaths); - TS_ASSERT_EQUALS(client->typedefs.size(), 1); - TS_ASSERT_EQUALS(client->classes.size(), 4); - TS_ASSERT_EQUALS(client->enums.size(), 1); - TS_ASSERT_EQUALS(client->enumFields.size(), 2); - TS_ASSERT_EQUALS(client->functions.size(), 2); - TS_ASSERT_EQUALS(client->fields.size(), 4); - TS_ASSERT_EQUALS(client->globalVariables.size(), 2); - TS_ASSERT_EQUALS(client->methods.size(), 5); - TS_ASSERT_EQUALS(client->namespaces.size(), 2); - TS_ASSERT_EQUALS(client->structs.size(), 1); + TS_ASSERT_EQUALS(client.typedefs.size(), 1); + TS_ASSERT_EQUALS(client.classes.size(), 4); + TS_ASSERT_EQUALS(client.enums.size(), 1); + TS_ASSERT_EQUALS(client.enumFields.size(), 2); + TS_ASSERT_EQUALS(client.functions.size(), 2); + TS_ASSERT_EQUALS(client.fields.size(), 4); + TS_ASSERT_EQUALS(client.globalVariables.size(), 2); + TS_ASSERT_EQUALS(client.methods.size(), 5); + TS_ASSERT_EQUALS(client.namespaces.size(), 2); + TS_ASSERT_EQUALS(client.structs.size(), 1); - TS_ASSERT_EQUALS(client->inheritances.size(), 1); - TS_ASSERT_EQUALS(client->calls.size(), 2); - TS_ASSERT_EQUALS(client->usages.size(), 3); - TS_ASSERT_EQUALS(client->typeUses.size(), 8); + TS_ASSERT_EQUALS(client.inheritances.size(), 1); + TS_ASSERT_EQUALS(client.calls.size(), 2); + TS_ASSERT_EQUALS(client.usages.size(), 3); + TS_ASSERT_EQUALS(client.typeUses.size(), 8); } private: @@ -1175,7 +1175,7 @@ private: std::shared_ptr parseCode(std::string code) const { std::shared_ptr client = std::make_shared(); - CxxParser parser(client); + CxxParser parser(client.get()); parser.parseFile(TextAccess::createFromString(code)); return client; } diff --git a/src/test/GraphFilterConductorTestSuite.h b/src/test/GraphFilterConductorTestSuite.h new file mode 100644 index 00000000..374067fb --- /dev/null +++ b/src/test/GraphFilterConductorTestSuite.h @@ -0,0 +1,153 @@ +#include "cxxtest/TestSuite.h" + +#include "data/graph/filter/GraphFilterConductor.h" +#include "data/query/QueryTree.h" +#include "utilityTest.h" + +class GraphFilterConductorTestSuite : public CxxTest::TestSuite +{ +public: + void test_token_query() + { + TS_ASSERT_EQUALS( + printedFilteredTestGraph("\"main\""), + + "1 nodes: function:main\n" + "0 edges:\n" + ); + } + + void test_command_query() + { + TS_ASSERT_EQUALS( + printedFilteredTestGraph("method"), + + "4 nodes: method:A method:getCount method:process method:process\n" + "0 edges:\n" + ); + + TS_ASSERT_EQUALS( + printedFilteredTestGraph("class"), + + "2 nodes: class:A class:B\n" + "0 edges:\n" + ); + } + + void test_operator_not() + { + TS_ASSERT_EQUALS( + printedFilteredTestGraph("!method"), + + "7 nodes: " + "class:A field:A::count undefined:int undefined: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" + ); + } + + void test_operator_sub() + { + TS_ASSERT_EQUALS( + printedFilteredTestGraph("class.base"), + + "1 nodes: class:A\n" + "0 edges:\n" + ); + } + + void test_operator_has() + { + TS_ASSERT_EQUALS( + printedFilteredTestGraph("\"A\":field"), + + "1 nodes: field:count\n" + "0 edges:\n" + ); + } + + void test_operator_or() + { + TS_ASSERT_EQUALS( + printedFilteredTestGraph("(static|const)"), + + "4 nodes: field:count method:getCount method:process method:process\n" + "0 edges:\n" + ); + } + + void test_operator_group() + { + TS_ASSERT_EQUALS( + printedFilteredTestGraph("(static|const).public"), + + "1 nodes: method:getCount\n" + "0 edges:\n" + ); + } + +private: + std::string printedFilteredTestGraph(std::string query) + { + QueryTree tree(query); + GraphFilterConductor conductor; + + createTestGraph(); + Graph result; + + conductor.filter(&tree, &m_graph, &result); + + std::stringstream ss; + result.printBasic(ss); + return ss.str(); + } + + void createTestGraph() + { + if (m_graph.getNodeCount()) + { + return; + } + + m_graph = utility::getGraphForCxxCode( + "class A\n" + "{\n" + "public:\n" + " A() {\n" + " count++;\n" + " }\n" + "\n" + " static int getCount()\n" + " {\n" + " return count;\n" + " }\n" + "\n" + "protected:\n" + " virtual void process() const = 0;\n" + "\n" + "private:\n" + " static int count;\n" + "};\n" + "\n" + "class B\n" + " : public A\n" + "{\n" + "protected:\n" + " virtual void process() const\n" + " {\n" + " int number = 42;\n" + " }\n" + "};\n" + "\n" + "int main()\n" + "{\n" + " B b;\n" + "\n" + " return A::getCount();\n" + "}\n" + ); + } + + Graph m_graph; +}; diff --git a/src/test/GraphFilterTestSuite.h b/src/test/GraphFilterTestSuite.h new file mode 100644 index 00000000..fa1ad9ed --- /dev/null +++ b/src/test/GraphFilterTestSuite.h @@ -0,0 +1,232 @@ +#include "cxxtest/TestSuite.h" + +#include "data/graph/filter/GraphFilter.h" +#include "data/graph/filter/GraphFilterImplementations.h" +#include "utilityTest.h" + +class GraphFilterTestSuite : public CxxTest::TestSuite +{ +public: + void test_empty_GraphFilter() + { + GraphFilter filter; + + TS_ASSERT_EQUALS( + printedFilteredTestGraph(&filter), + + "0 nodes:\n" + "0 edges:\n" + ); + } + + void test_GraphFilterCommandMember() + { + GraphFilterCommandMember filter; + + TS_ASSERT_EQUALS( + printedFilteredTestGraph(&filter), + + "6 nodes: method:A field:count method:getCount method:process method:process undefined_function:B\n" + "0 edges:\n" + ); + } + + void test_GraphFilterCommandParent() + { + GraphFilterCommandParent filter; + + TS_ASSERT_EQUALS( + printedFilteredTestGraph(&filter), + + "2 nodes: class:A class:B\n" + "0 edges:\n" + ); + } + + void test_GraphFilterCommandNodeType() + { + GraphFilterCommandNodeType filter(Node::NODE_FUNCTION | Node::NODE_METHOD); + + TS_ASSERT_EQUALS( + printedFilteredTestGraph(&filter), + + "5 nodes: method:A method:getCount method:process method:process function:main\n" + "0 edges:\n" + ); + } + + void test_GraphFilterCommandConst() + { + GraphFilterCommandConst filter; + + TS_ASSERT_EQUALS( + printedFilteredTestGraph(&filter), + + "2 nodes: method:process method:process\n" + "0 edges:\n" + ); + } + + void test_GraphFilterCommandStatic() + { + GraphFilterCommandStatic filter; + + TS_ASSERT_EQUALS( + printedFilteredTestGraph(&filter), + + "2 nodes: field:count method:getCount\n" + "0 edges:\n" + ); + } + + void test_GraphFilterCommandAccessType() + { + GraphFilterCommandAccessType filter(TokenComponentAccess::ACCESS_PROTECTED); + + TS_ASSERT_EQUALS( + printedFilteredTestGraph(&filter), + + "2 nodes: method:process method:process\n" + "0 edges:\n" + ); + } + + void test_GraphFilterCommandAbstractionType() + { + GraphFilterCommandAbstractionType filter(TokenComponentAbstraction::ABSTRACTION_PURE_VIRTUAL); + + TS_ASSERT_EQUALS( + printedFilteredTestGraph(&filter), + + "1 nodes: method:process\n" + "0 edges:\n" + ); + } + + void test_GraphFilterCommandCall() + { + GraphFilterCommandCall filter(true); + + TS_ASSERT_EQUALS( + printedFilteredTestGraph(&filter), + + "1 nodes: function:main\n" + "0 edges:\n" + ); + + GraphFilterCommandCall filter2(false); + + TS_ASSERT_EQUALS( + printedFilteredTestGraph(&filter2), + + "2 nodes: method:getCount undefined_function:B\n" + "0 edges:\n" + ); + } + + void test_GraphFilterCommandUsage() + { + GraphFilterCommandUsage filter; + + TS_ASSERT_EQUALS( + printedFilteredTestGraph(&filter), + + "6 nodes: method:A field:count method:getCount method:process method:process function:main\n" + "0 edges:\n" + ); + } + + void test_GraphFilterCommandInheritance() + { + GraphFilterCommandInheritance filter(true); + + TS_ASSERT_EQUALS( + printedFilteredTestGraph(&filter), + + "1 nodes: class:A\n" + "0 edges:\n" + ); + + GraphFilterCommandInheritance filter2(false); + + TS_ASSERT_EQUALS( + printedFilteredTestGraph(&filter2), + + "1 nodes: class:B\n" + "0 edges:\n" + ); + } + + void test_GraphFilterToken() + { + GraphFilterToken filter("main"); + + TS_ASSERT_EQUALS( + printedFilteredTestGraph(&filter), + + "1 nodes: function:main\n" + "0 edges:\n" + ); + } + +private: + std::string printedFilteredTestGraph(GraphFilter* filter) + { + createTestGraph(); + Graph result; + + filter->apply(&m_graph, &result); + + std::stringstream ss; + result.printBasic(ss); + return ss.str(); + } + + void createTestGraph() + { + if (m_graph.getNodeCount()) + { + return; + } + + m_graph = utility::getGraphForCxxCode( + "class A\n" + "{\n" + "public:\n" + " A() {\n" + " count++;\n" + " }\n" + "\n" + " static int getCount()\n" + " {\n" + " return count;\n" + " }\n" + "\n" + "protected:\n" + " virtual void process() const = 0;\n" + "\n" + "private:\n" + " static int count;\n" + "};\n" + "\n" + "class B\n" + " : public A\n" + "{\n" + "protected:\n" + " virtual void process() const\n" + " {\n" + " int number = 42;\n" + " }\n" + "};\n" + "\n" + "int main()\n" + "{\n" + " B b;\n" + "\n" + " return A::getCount();\n" + "}\n" + ); + } + + Graph m_graph; +}; diff --git a/src/test/utilityTest.cpp b/src/test/utilityTest.cpp new file mode 100644 index 00000000..d8d01c9a --- /dev/null +++ b/src/test/utilityTest.cpp @@ -0,0 +1,27 @@ +#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(); +} diff --git a/src/test/utilityTest.h b/src/test/utilityTest.h new file mode 100644 index 00000000..f6e5d9fd --- /dev/null +++ b/src/test/utilityTest.h @@ -0,0 +1,13 @@ +#ifndef UTILITY_TEST_H +#define UTILITY_TEST_H + +#include + +class Graph; + +namespace utility +{ + Graph getGraphForCxxCode(std::string code); +} + +#endif // UTILITY_TEST_H