From 5893d0c776ea775fdfb982a799d3bd17b26602df Mon Sep 17 00:00:00 2001 From: Eberhard Graether Date: Fri, 1 Aug 2014 02:10:42 +0200 Subject: [PATCH] test: added StorageTestSuite This change adds the StorageTestSuite that checks whether the ParserClient callbacks cause the right things to be saved. In order to allow for easier data retrieval the ParserClient callbacks now return the Id of the inserted Token, which can then be used to retrieve the Token pointer. --- bin/test/data/log/test_log.txt | 39 +++ src/lib/data/Storage.cpp | 116 ++++-- src/lib/data/Storage.h | 36 +- src/lib/data/parser/ParserClient.h | 34 +- src/test/CMakeLists.txt | 1 + src/test/CxxParserTestSuite.h | 50 ++- src/test/StorageTestSuite.h | 545 +++++++++++++++++++++++++++++ src/test/TextAccessTestSuite.h | 3 - 8 files changed, 742 insertions(+), 82 deletions(-) create mode 100644 src/test/StorageTestSuite.h diff --git a/bin/test/data/log/test_log.txt b/bin/test/data/log/test_log.txt index 57a99372..ae097708 100644 --- a/bin/test/data/log/test_log.txt +++ b/bin/test/data/log/test_log.txt @@ -19,6 +19,45 @@ ConfigManager.cpp ERROR: value Int is not present in config. ConfigManager.cpp ERROR: value Float is not present in config. ConfigManager.cpp ERROR: value String is not present in config. ConfigManager.cpp ERROR: value NewBool is not present in config. +Storage.cpp INFO: typedef: type -> int +Storage.cpp INFO: class: Class +Storage.cpp INFO: struct: Struct +Storage.cpp INFO: global: Global +Storage.cpp INFO: global: Global +Storage.cpp INFO: field: m_field +Storage.cpp ERROR: Field is not a member of anything. +Storage.cpp ERROR: Field needs to have access type [public, protected, private] but has none. +Storage.cpp INFO: field: Struct::m_field +Storage.cpp INFO: function: isTrue +Storage.cpp INFO: method: isMethod +Storage.cpp ERROR: Method is not a member of anything. +Storage.cpp ERROR: Method needs to have access type [public, protected, private] but has none. +Storage.cpp INFO: method: isMethod +Storage.cpp ERROR: Method is not a member of anything. +Storage.cpp ERROR: Method needs to have access type [public, protected, private] but has none. +Storage.cpp INFO: method: Class::isMethod +Storage.cpp INFO: namespace: utility +Storage.cpp INFO: enum: Category +Storage.cpp INFO: enum: Class::Category +Storage.cpp INFO: enum field: VALUE +Storage.cpp INFO: class: ClassA +Storage.cpp INFO: class: ClassB +Storage.cpp INFO: inheritance: ClassB : ClassA +Storage.cpp INFO: function: isTrue +Storage.cpp INFO: function: func +Storage.cpp INFO: call: isTrue -> func +Storage.cpp INFO: global: global +Storage.cpp INFO: function: isTrue +Storage.cpp INFO: call: global -> isTrue +Storage.cpp INFO: function: isTrue +Storage.cpp INFO: field: Foo::m_field +Storage.cpp INFO: field usage: isTrue -> Foo::m_field +Storage.cpp INFO: function: isTrue +Storage.cpp INFO: global: global +Storage.cpp INFO: global usage: isTrue -> global +Storage.cpp INFO: function: isTrue +Storage.cpp INFO: struct: Struct +Storage.cpp INFO: type usage: isTrue -> Struct TextAccess.cpp WARNING: Index 'firstLine' has to be lower or equal index 'lastLine', is 3 > 2 TextAccess.cpp WARNING: Tried to access index 10. Maximum index is 8 TextAccess.cpp WARNING: Tried to access index 10. Maximum index is 8 diff --git a/src/lib/data/Storage.cpp b/src/lib/data/Storage.cpp index a5f4d5df..26ca60fe 100644 --- a/src/lib/data/Storage.cpp +++ b/src/lib/data/Storage.cpp @@ -39,7 +39,7 @@ void Storage::logLocations() const } -void Storage::onTypedefParsed( +Id Storage::onTypedefParsed( const ParseLocation& location, const std::string& fullName, const ParseTypeUsage& underlyingType, AccessType access ){ log("typedef", fullName + " -> " + underlyingType.dataType.getFullTypeName(), location); @@ -48,31 +48,37 @@ void Storage::onTypedefParsed( addAccess(node, access); addTokenLocation(node, location); addTypeEdge(node, Edge::EDGE_TYPEDEF_OF, underlyingType); + + return node->getId(); } -void Storage::onClassParsed( - const ParseLocation& location, const std::string& fullName, AccessType access, const ParseLocation& scopeLocation) -{ +Id Storage::onClassParsed( + const ParseLocation& location, const std::string& fullName, AccessType access, const ParseLocation& scopeLocation +){ log("class", fullName, location); Node* node = m_graph.createNodeHierarchy(Node::NODE_CLASS, fullName); addAccess(node, access); addTokenLocation(node, location); addTokenLocation(node, scopeLocation, true); + + return node->getId(); } -void Storage::onStructParsed( - const ParseLocation& location, const std::string& fullName, AccessType access, const ParseLocation& scopeLocation) -{ +Id Storage::onStructParsed( + const ParseLocation& location, const std::string& fullName, AccessType access, const ParseLocation& scopeLocation +){ log("struct", fullName, location); Node* node = m_graph.createNodeHierarchy(Node::NODE_STRUCT, fullName); addAccess(node, access); addTokenLocation(node, location); addTokenLocation(node, scopeLocation, true); + + return node->getId(); } -void Storage::onGlobalVariableParsed(const ParseLocation& location, const ParseVariable& variable) +Id Storage::onGlobalVariableParsed(const ParseLocation& location, const ParseVariable& variable) { log("global", variable.fullName, location); @@ -85,14 +91,21 @@ void Storage::onGlobalVariableParsed(const ParseLocation& location, const ParseV addTypeEdge(node, Edge::EDGE_TYPE_OF, variable.type); addTokenLocation(node, location); + + return node->getId(); } -void Storage::onFieldParsed(const ParseLocation& location, const ParseVariable& variable, AccessType access) +Id Storage::onFieldParsed(const ParseLocation& location, const ParseVariable& variable, AccessType access) { log("field", variable.fullName, location); Node* node = m_graph.createNodeHierarchy(Node::NODE_FIELD, variable.fullName); + if (!node->getMemberEdge()) + { + LOG_ERROR("Field is not a member of anything."); + } + if (variable.isStatic) { node->addComponentStatic(std::make_shared()); @@ -101,15 +114,16 @@ void Storage::onFieldParsed(const ParseLocation& location, const ParseVariable& if (access == ACCESS_NONE) { LOG_ERROR("Field needs to have access type [public, protected, private] but has none."); - return; } addAccess(node, access); addTypeEdge(node, Edge::EDGE_TYPE_OF, variable.type); addTokenLocation(node, location); + + return node->getId(); } -void Storage::onFunctionParsed( +Id Storage::onFunctionParsed( const ParseLocation& location, const ParseFunction& function, const ParseLocation& scopeLocation ){ log("function", function.fullName, location); @@ -126,9 +140,11 @@ void Storage::onFunctionParsed( { addTypeEdge(node, Edge::EDGE_PARAMETER_TYPE_OF, parameter); } + + return node->getId(); } -void Storage::onMethodParsed( +Id Storage::onMethodParsed( const ParseLocation& location, const ParseFunction& method, AccessType access, AbstractionType abstraction, const ParseLocation& scopeLocation ){ @@ -138,6 +154,11 @@ void Storage::onMethodParsed( Node::NODE_METHOD, method.fullName, ParserClient::functionSignatureStr(method) ); + if (!node->getMemberEdge()) + { + LOG_ERROR("Method is not a member of anything."); + } + if (method.isConst) { node->addComponentConst(std::make_shared()); @@ -151,7 +172,6 @@ void Storage::onMethodParsed( if (access == ACCESS_NONE) { LOG_ERROR("Method needs to have access type [public, protected, private] but has none."); - return; } addAccess(node, access); @@ -163,40 +183,48 @@ void Storage::onMethodParsed( { addTypeEdge(node, Edge::EDGE_PARAMETER_TYPE_OF, parameter); } + + return node->getId(); } -void Storage::onNamespaceParsed( - const ParseLocation& location, const std::string& fullName, const ParseLocation& scopeLocation) -{ +Id Storage::onNamespaceParsed( + const ParseLocation& location, const std::string& fullName, const ParseLocation& scopeLocation +){ log("namespace", fullName, location); Node* node = m_graph.createNodeHierarchy(Node::NODE_NAMESPACE, fullName); addTokenLocation(node, location); addTokenLocation(node, scopeLocation, true); + + return node->getId(); } -void Storage::onEnumParsed( - const ParseLocation& location, const std::string& fullName, AccessType access, const ParseLocation& scopeLocation) -{ +Id Storage::onEnumParsed( + const ParseLocation& location, const std::string& fullName, AccessType access, const ParseLocation& scopeLocation +){ log("enum", fullName, location); Node* node = m_graph.createNodeHierarchy(Node::NODE_ENUM, fullName); addAccess(node, access); addTokenLocation(node, location); addTokenLocation(node, scopeLocation, true); + + return node->getId(); } -void Storage::onEnumFieldParsed(const ParseLocation& location, const std::string& fullName) +Id Storage::onEnumFieldParsed(const ParseLocation& location, const std::string& fullName) { log("enum field", fullName, location); Node* node = m_graph.createNodeHierarchy(Node::NODE_FIELD, fullName); addTokenLocation(node, location); + + return node->getId(); } -void Storage::onInheritanceParsed( - const ParseLocation& location, const std::string& fullName, const std::string& baseName, AccessType access) -{ +Id Storage::onInheritanceParsed( + const ParseLocation& location, const std::string& fullName, const std::string& baseName, AccessType access +){ log("inheritance", fullName + " : " + baseName, location); Node* node = m_graph.createNodeHierarchy(fullName); @@ -206,9 +234,11 @@ void Storage::onInheritanceParsed( edge->addComponentAccess(std::make_shared(convertAccessType(access))); addTokenLocation(edge, location); + + return edge->getId(); } -void Storage::onCallParsed(const ParseLocation& location, const ParseFunction& caller, const ParseFunction& callee) +Id Storage::onCallParsed(const ParseLocation& location, const ParseFunction& caller, const ParseFunction& callee) { log("call", caller.fullName + " -> " + callee.fullName, location); @@ -220,9 +250,11 @@ void Storage::onCallParsed(const ParseLocation& location, const ParseFunction& c Edge* edge = m_graph.createEdge(Edge::EDGE_CALL, callerNode, calleeNode); addTokenLocation(edge, location); + + return edge->getId(); } -void Storage::onCallParsed(const ParseLocation& location, const ParseVariable& caller, const ParseFunction& callee) +Id Storage::onCallParsed(const ParseLocation& location, const ParseVariable& caller, const ParseFunction& callee) { log("call", caller.fullName + " -> " + callee.fullName, location); @@ -234,9 +266,11 @@ void Storage::onCallParsed(const ParseLocation& location, const ParseVariable& c Edge* edge = m_graph.createEdge(Edge::EDGE_CALL, callerNode, calleeNode); addTokenLocation(edge, location); + + return edge->getId(); } -void Storage::onFieldUsageParsed(const ParseLocation& location, const ParseFunction& user, const std::string& usedName) +Id Storage::onFieldUsageParsed(const ParseLocation& location, const ParseFunction& user, const std::string& usedName) { log("field usage", user.fullName + " -> " + usedName, location); @@ -246,9 +280,11 @@ void Storage::onFieldUsageParsed(const ParseLocation& location, const ParseFunct Edge* edge = m_graph.createEdge(Edge::EDGE_USAGE, userNode, usedNode); addTokenLocation(edge, location); + + return edge->getId(); } -void Storage::onGlobalVariableUsageParsed( +Id Storage::onGlobalVariableUsageParsed( const ParseLocation& location, const ParseFunction& user, const std::string& usedName ){ log("global usage", user.fullName + " -> " + usedName, location); @@ -259,15 +295,19 @@ void Storage::onGlobalVariableUsageParsed( Edge* edge = m_graph.createEdge(Edge::EDGE_USAGE, userNode, usedNode); addTokenLocation(edge, location); + + return edge->getId(); } -void Storage::onTypeUsageParsed(const ParseTypeUsage& type, const ParseFunction& function) +Id Storage::onTypeUsageParsed(const ParseTypeUsage& type, const ParseFunction& function) { log("type usage", function.fullName + " -> " + type.dataType.getRawTypeName(), type.location); Node* functionNode = m_graph.createNodeHierarchyWithDistinctSignature(function.fullName, ParserClient::functionSignatureStr(function)); - addTypeEdge(functionNode, Edge::EDGE_TYPE_USAGE, type); + Edge* edge = addTypeEdge(functionNode, Edge::EDGE_TYPE_USAGE, type); + + return edge->getId(); } Id Storage::getIdForNodeWithName(const std::string& fullName) const @@ -571,6 +611,24 @@ TokenLocationFile Storage::getTokenLocationsForLinesInFile( return ret; } +Token* Storage::getTokenWithId(Id tokenId) const +{ + return m_graph.getTokenById(tokenId); +} + +std::vector Storage::getTokenLocationsForId(Id tokenId) const +{ + const std::vector& locationIds = getTokenWithId(tokenId)->getLocationIds(); + + std::vector result; + for (Id locationId : locationIds) + { + result.push_back(m_locationCollection.findTokenLocationById(locationId)); + } + + return result; +} + TokenComponentAccess::AccessType Storage::convertAccessType(ParserClient::AccessType access) const { switch (access) diff --git a/src/lib/data/Storage.h b/src/lib/data/Storage.h index 5269f060..f4575a9c 100644 --- a/src/lib/data/Storage.h +++ b/src/lib/data/Storage.h @@ -26,41 +26,41 @@ public: void logLocations() const; // ParserClient implementation - virtual void onTypedefParsed( + virtual Id onTypedefParsed( const ParseLocation& location, const std::string& fullName, const ParseTypeUsage& underlyingType, AccessType access); - virtual void onClassParsed( + virtual Id onClassParsed( const ParseLocation& location, const std::string& fullName, AccessType access, const ParseLocation& scopeLocation); - virtual void onStructParsed( + virtual Id onStructParsed( const ParseLocation& location, const std::string& fullName, AccessType access, const ParseLocation& scopeLocation); - virtual void onGlobalVariableParsed(const ParseLocation& location, const ParseVariable& variable); - virtual void onFieldParsed(const ParseLocation& location, const ParseVariable& variable, AccessType access); + virtual Id onGlobalVariableParsed(const ParseLocation& location, const ParseVariable& variable); + virtual Id onFieldParsed(const ParseLocation& location, const ParseVariable& variable, AccessType access); - virtual void onFunctionParsed( + virtual Id onFunctionParsed( const ParseLocation& location, const ParseFunction& function, const ParseLocation& scopeLocation); - virtual void onMethodParsed( + virtual Id onMethodParsed( const ParseLocation& location, const ParseFunction& method, AccessType access, AbstractionType abstraction, const ParseLocation& scopeLocation); - virtual void onNamespaceParsed( + virtual Id onNamespaceParsed( const ParseLocation& location, const std::string& fullName, const ParseLocation& scopeLocation); - virtual void onEnumParsed( + virtual Id onEnumParsed( const ParseLocation& location, const std::string& fullName, AccessType access, const ParseLocation& scopeLocation); - virtual void onEnumFieldParsed(const ParseLocation& location, const std::string& fullName); + virtual Id onEnumFieldParsed(const ParseLocation& location, const std::string& fullName); - virtual void onInheritanceParsed( + virtual Id onInheritanceParsed( const ParseLocation& location, const std::string& fullName, const std::string& baseName, AccessType access); - virtual void onCallParsed( + virtual Id onCallParsed( const ParseLocation& location, const ParseFunction& caller, const ParseFunction& callee); - virtual void onCallParsed( + virtual Id onCallParsed( const ParseLocation& location, const ParseVariable& caller, const ParseFunction& callee); - virtual void onFieldUsageParsed( + virtual Id onFieldUsageParsed( const ParseLocation& location, const ParseFunction& user, const std::string& usedName); - virtual void onGlobalVariableUsageParsed( + virtual Id onGlobalVariableUsageParsed( const ParseLocation& location, const ParseFunction& user, const std::string& usedName); - virtual void onTypeUsageParsed(const ParseTypeUsage& type, const ParseFunction& function); + virtual Id onTypeUsageParsed(const ParseTypeUsage& type, const ParseFunction& function); // GraphAccess implementation virtual Id getIdForNodeWithName(const std::string& fullName) const; @@ -90,6 +90,10 @@ public: const std::string& filePath, uint firstLineNumber, uint lastLineNumber ) const; +protected: + Token* getTokenWithId(Id tokenId) const; + std::vector getTokenLocationsForId(Id tokenId) const; + private: TokenComponentAccess::AccessType convertAccessType(ParserClient::AccessType access) const; TokenComponentAccess* addAccess(Node* node, ParserClient::AccessType access); diff --git a/src/lib/data/parser/ParserClient.h b/src/lib/data/parser/ParserClient.h index 7e4b5e4d..00fb0eb2 100644 --- a/src/lib/data/parser/ParserClient.h +++ b/src/lib/data/parser/ParserClient.h @@ -4,6 +4,8 @@ #include #include +#include "utility/types.h" + struct ParseFunction; struct ParseLocation; struct ParseTypeUsage; @@ -42,44 +44,44 @@ public: ParserClient(); virtual ~ParserClient(); - virtual void onTypedefParsed( + virtual Id onTypedefParsed( const ParseLocation& location, const std::string& fullName, const ParseTypeUsage& underlyingType, AccessType access) = 0; - virtual void onClassParsed( + virtual Id onClassParsed( const ParseLocation& location, const std::string& fullName, AccessType access, const ParseLocation& scopeLocation) = 0; - virtual void onStructParsed( + virtual Id onStructParsed( const ParseLocation& location, const std::string& fullName, AccessType access, const ParseLocation& scopeLocation) = 0; - virtual void onGlobalVariableParsed(const ParseLocation& location, const ParseVariable& variable) = 0; - virtual void onFieldParsed(const ParseLocation& location, const ParseVariable& variable, AccessType access) = 0; + virtual Id onGlobalVariableParsed(const ParseLocation& location, const ParseVariable& variable) = 0; + virtual Id onFieldParsed(const ParseLocation& location, const ParseVariable& variable, AccessType access) = 0; - virtual void onFunctionParsed( + virtual Id onFunctionParsed( const ParseLocation& location, const ParseFunction& function, const ParseLocation& scopeLocation) = 0; - virtual void onMethodParsed( + virtual Id onMethodParsed( const ParseLocation& location, const ParseFunction& method, AccessType access, AbstractionType abstraction, const ParseLocation& scopeLocation) = 0; - virtual void onNamespaceParsed( + virtual Id onNamespaceParsed( const ParseLocation& location, const std::string& fullName, const ParseLocation& scopeLocation) = 0; - virtual void onEnumParsed( + virtual Id onEnumParsed( const ParseLocation& location, const std::string& fullName, AccessType access, const ParseLocation& scopeLocation) = 0; - virtual void onEnumFieldParsed(const ParseLocation& location, const std::string& fullName) = 0; + virtual Id onEnumFieldParsed(const ParseLocation& location, const std::string& fullName) = 0; - virtual void onInheritanceParsed( + virtual Id onInheritanceParsed( const ParseLocation& location, const std::string& fullName, const std::string& baseName, AccessType access) = 0; - virtual void onCallParsed( + virtual Id onCallParsed( const ParseLocation& location, const ParseFunction& caller, const ParseFunction& callee) = 0; - virtual void onCallParsed( + virtual Id onCallParsed( const ParseLocation& location, const ParseVariable& caller, const ParseFunction& callee) = 0; - virtual void onFieldUsageParsed( + virtual Id onFieldUsageParsed( const ParseLocation& location, const ParseFunction& user, const std::string& usedName) = 0; - virtual void onGlobalVariableUsageParsed( + virtual Id onGlobalVariableUsageParsed( const ParseLocation& location, const ParseFunction& user, const std::string& usedName) = 0; - virtual void onTypeUsageParsed(const ParseTypeUsage& type, const ParseFunction& function) = 0; + virtual Id onTypeUsageParsed(const ParseTypeUsage& type, const ParseFunction& function) = 0; }; #endif // PARSER_CLIENT_H diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index ee118fac..c751f0ab 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -9,6 +9,7 @@ add_files( LogManagerTestSuite.h MessageQueueTestSuite.h SettingsTestSuite.h + StorageTestSuite.h TestSuiteFixture.cpp TestSuiteFixture.h TextAccessTestSuite.h diff --git a/src/test/CxxParserTestSuite.h b/src/test/CxxParserTestSuite.h index 8663dff6..3d36c2ca 100644 --- a/src/test/CxxParserTestSuite.h +++ b/src/test/CxxParserTestSuite.h @@ -1,7 +1,5 @@ #include "cxxtest/TestSuite.h" -#include - #include "data/parser/cxx/CxxParser.h" #include "data/parser/ParseFunction.h" #include "data/parser/ParseLocation.h" @@ -992,40 +990,45 @@ private: class TestParserClient: public ParserClient { public: - virtual void onTypedefParsed( + virtual Id onTypedefParsed( const ParseLocation& location, const std::string& fullName, const ParseTypeUsage& underlyingType, AccessType access ) { std::string str = addAccessPrefix(underlyingType.dataType.getFullTypeName() + " -> " + fullName, access); typedefs.push_back(addLocationSuffix(str, location)); + return 0; } - virtual void onClassParsed( + virtual Id onClassParsed( const ParseLocation& location, const std::string& fullName, AccessType access, const ParseLocation& scopeLocation) { classes.push_back(addLocationSuffix(addAccessPrefix(fullName, access), location, scopeLocation)); + return 0; } - virtual void onStructParsed( + virtual Id onStructParsed( const ParseLocation& location, const std::string& fullName, AccessType access, const ParseLocation& scopeLocation) { structs.push_back(addLocationSuffix(addAccessPrefix(fullName, access), location, scopeLocation)); + return 0; } - virtual void onGlobalVariableParsed(const ParseLocation& location, const ParseVariable& variable) + virtual Id onGlobalVariableParsed(const ParseLocation& location, const ParseVariable& variable) { globalVariables.push_back(addLocationSuffix(variableStr(variable), location)); + return 0; } - virtual void onFieldParsed(const ParseLocation& location, const ParseVariable& variable, AccessType access) + virtual Id onFieldParsed(const ParseLocation& location, const ParseVariable& variable, AccessType access) { fields.push_back(addLocationSuffix(addAccessPrefix(variableStr(variable), access), location)); + return 0; } - virtual void onFunctionParsed( + virtual Id onFunctionParsed( const ParseLocation& location, const ParseFunction& function, const ParseLocation& scopeLocation ){ functions.push_back(addLocationSuffix(functionStr(function), location, scopeLocation)); @@ -1035,9 +1038,10 @@ private: { addTypeUse(parameter); } + return 0; } - virtual void onMethodParsed( + virtual Id onMethodParsed( const ParseLocation& location, const ParseFunction& method, AccessType access, AbstractionType abstraction, const ParseLocation& scopeLocation ){ @@ -1052,60 +1056,70 @@ private: { addTypeUse(parameter); } + return 0; } - virtual void onNamespaceParsed( + virtual Id onNamespaceParsed( const ParseLocation& location, const std::string& fullName, const ParseLocation& scopeLocation) { namespaces.push_back(addLocationSuffix(fullName, location, scopeLocation)); + return 0; } - virtual void onEnumParsed( + virtual Id onEnumParsed( const ParseLocation& location, const std::string& fullName, AccessType access, const ParseLocation& scopeLocation) { enums.push_back(addLocationSuffix(addAccessPrefix(fullName, access), location, scopeLocation)); + return 0; } - virtual void onEnumFieldParsed(const ParseLocation& location, const std::string& fullName) + virtual Id onEnumFieldParsed(const ParseLocation& location, const std::string& fullName) { enumFields.push_back(addLocationSuffix(fullName, location)); + return 0; } - virtual void onInheritanceParsed( + virtual Id onInheritanceParsed( const ParseLocation& location, const std::string& fullName, const std::string& baseName, AccessType access) { std::string str = fullName + " : " + addAccessPrefix(baseName, access); inheritances.push_back(addLocationSuffix(str, location)); + return 0; } - virtual void onCallParsed( + virtual Id onCallParsed( const ParseLocation& location, const ParseFunction& caller, const ParseFunction& callee) { calls.push_back(addLocationSuffix(functionStr(caller) + " -> " + functionStr(callee), location)); + return 0; } - virtual void onCallParsed( + virtual Id onCallParsed( const ParseLocation& location, const ParseVariable& caller, const ParseFunction& callee) { calls.push_back(addLocationSuffix(caller.fullName + " -> " + functionStr(callee), location)); + return 0; } - virtual void onFieldUsageParsed( + virtual Id onFieldUsageParsed( const ParseLocation& location, const ParseFunction& user, const std::string& usedName) { usages.push_back(addLocationSuffix(functionStr(user) + " -> " + usedName, location)); + return 0; } - virtual void onGlobalVariableUsageParsed( + virtual Id onGlobalVariableUsageParsed( const ParseLocation& location, const ParseFunction& user, const std::string& usedName) { usages.push_back(addLocationSuffix(functionStr(user) + " -> " + usedName, location)); + return 0; } - virtual void onTypeUsageParsed(const ParseTypeUsage& type, const ParseFunction& function) + virtual Id onTypeUsageParsed(const ParseTypeUsage& type, const ParseFunction& function) { addTypeUse(type, function); + return 0; } std::vector typedefs; diff --git a/src/test/StorageTestSuite.h b/src/test/StorageTestSuite.h new file mode 100644 index 00000000..425e0573 --- /dev/null +++ b/src/test/StorageTestSuite.h @@ -0,0 +1,545 @@ +#include "cxxtest/TestSuite.h" + +#include "data/graph/token_component/TokenComponentAccess.h" +#include "data/graph/token_component/TokenComponentSignature.h" +#include "data/graph/token_component/TokenComponentStatic.h" +#include "data/location/TokenLocation.h" +#include "data/parser/ParseFunction.h" +#include "data/parser/ParseLocation.h" +#include "data/parser/ParseTypeUsage.h" +#include "data/parser/ParseVariable.h" +#include "data/Storage.h" +#include "data/type/DataType.h" + +class StorageTestSuite: public CxxTest::TestSuite +{ +public: + void test_storage_saves_typedef() + { + TestStorage storage; + Id id = storage.onTypedefParsed(validLocation(1), "type", typeUsage("int"), ParserClient::ACCESS_NONE); + + Node* node = storage.getNodeWithId(id); + TS_ASSERT(node); + TS_ASSERT_EQUALS(node->getFullName(), "type"); + TS_ASSERT_EQUALS(node->getType(), Node::NODE_TYPEDEF); + + Edge* typeEdge = node->findEdgeOfType(Edge::EDGE_TYPEDEF_OF); + TS_ASSERT(typeEdge); + TS_ASSERT_EQUALS(typeEdge->getTo()->getFullName(), "int"); + + std::vector locations = storage.getLocationsForId(id); + TS_ASSERT_EQUALS(locations.size(), 1); + TS_ASSERT(isValidLocation(locations[0], 1)); + } + + void test_storage_saves_class() + { + TestStorage storage; + Id id = storage.onClassParsed(validLocation(1), "Class", ParserClient::ACCESS_NONE, validLocation(2)); + + Node* node = storage.getNodeWithId(id); + TS_ASSERT(node); + TS_ASSERT_EQUALS(node->getFullName(), "Class"); + TS_ASSERT_EQUALS(node->getType(), Node::NODE_CLASS); + + std::vector locations = storage.getLocationsForId(id); + TS_ASSERT_EQUALS(locations.size(), 2); + TS_ASSERT(isValidLocation(locations[0], 1)); + TS_ASSERT(isValidLocation(locations[1], 2)); + TS_ASSERT_EQUALS(locations[1]->getType(), TokenLocation::LOCATION_SCOPE); + } + + void test_storage_saves_struct() + { + TestStorage storage; + Id id = storage.onStructParsed(validLocation(1), "Struct", ParserClient::ACCESS_NONE, validLocation(2)); + + Node* node = storage.getNodeWithId(id); + TS_ASSERT(node); + TS_ASSERT_EQUALS(node->getFullName(), "Struct"); + TS_ASSERT_EQUALS(node->getType(), Node::NODE_STRUCT); + + std::vector locations = storage.getLocationsForId(id); + TS_ASSERT_EQUALS(locations.size(), 2); + TS_ASSERT(isValidLocation(locations[0], 1)); + TS_ASSERT(isValidLocation(locations[1], 2)); + TS_ASSERT_EQUALS(locations[1]->getType(), TokenLocation::LOCATION_SCOPE); + } + + void test_storage_saves_global_variable() + { + TestStorage storage; + Id id = storage.onGlobalVariableParsed(validLocation(42), ParseVariable(typeUsage("char"), "Global", false)); + + Node* node = storage.getNodeWithId(id); + TS_ASSERT(node); + TS_ASSERT_EQUALS(node->getFullName(), "Global"); + TS_ASSERT_EQUALS(node->getType(), Node::NODE_GLOBAL_VARIABLE); + TS_ASSERT(!node->getComponent()); + + Edge* typeEdge = node->findEdgeOfType(Edge::EDGE_TYPE_OF); + TS_ASSERT(typeEdge); + TS_ASSERT_EQUALS(typeEdge->getTo()->getFullName(), "char"); + + std::vector locations = storage.getLocationsForId(id); + TS_ASSERT_EQUALS(locations.size(), 1); + TS_ASSERT(isValidLocation(locations[0], 42)); + } + + void test_storage_saves_global_variable_static() + { + TestStorage storage; + Id id = storage.onGlobalVariableParsed(validLocation(7), ParseVariable(typeUsage("char"), "Global", true)); + + Node* node = storage.getNodeWithId(id); + TS_ASSERT(node); + TS_ASSERT_EQUALS(node->getFullName(), "Global"); + TS_ASSERT_EQUALS(node->getType(), Node::NODE_GLOBAL_VARIABLE); + TS_ASSERT(node->getComponent()); + + std::vector locations = storage.getLocationsForId(id); + TS_ASSERT_EQUALS(locations.size(), 1); + TS_ASSERT(isValidLocation(locations[0], 7)); + } + + void test_storage_saves_field() + { + TestStorage storage; + Id id = storage.onFieldParsed( + validLocation(3), ParseVariable(typeUsage("bool"), "m_field", false), ParserClient::ACCESS_NONE + ); + + Node* node = storage.getNodeWithId(id); + TS_ASSERT(node); + TS_ASSERT_EQUALS(node->getFullName(), "m_field"); + TS_ASSERT_EQUALS(node->getType(), Node::NODE_FIELD); + + Edge* typeEdge = node->findEdgeOfType(Edge::EDGE_TYPE_OF); + TS_ASSERT(typeEdge); + TS_ASSERT_EQUALS(typeEdge->getTo()->getFullName(), "bool"); + + std::vector locations = storage.getLocationsForId(id); + TS_ASSERT_EQUALS(locations.size(), 1); + TS_ASSERT(isValidLocation(locations[0], 3)); + } + + void test_storage_saves_field_as_member() + { + TestStorage storage; + Id id = storage.onFieldParsed( + validLocation(11), ParseVariable(typeUsage("bool"), "Struct::m_field", false), ParserClient::ACCESS_PUBLIC + ); + + Node* node = storage.getNodeWithId(id); + TS_ASSERT(node); + TS_ASSERT_EQUALS(node->getName(), "m_field"); + TS_ASSERT_EQUALS(node->getFullName(), "Struct::m_field"); + TS_ASSERT_EQUALS(node->getType(), Node::NODE_FIELD); + + Edge* memberEdge = node->getMemberEdge(); + TS_ASSERT(memberEdge); + TS_ASSERT_EQUALS(memberEdge->getType(), Edge::EDGE_MEMBER); + + TS_ASSERT(memberEdge->getComponent()); + TS_ASSERT_EQUALS( + memberEdge->getComponent()->getAccess(), TokenComponentAccess::ACCESS_PUBLIC + ); + + TS_ASSERT_EQUALS(memberEdge->getFrom()->getFullName(), "Struct"); + TS_ASSERT_EQUALS(memberEdge->getFrom()->getType(), Node::NODE_UNDEFINED); + + Edge* typeEdge = node->findEdgeOfType(Edge::EDGE_TYPE_OF); + TS_ASSERT(typeEdge); + TS_ASSERT_EQUALS(typeEdge->getTo()->getFullName(), "bool"); + + std::vector locations = storage.getLocationsForId(id); + TS_ASSERT_EQUALS(locations.size(), 1); + TS_ASSERT(isValidLocation(locations[0], 11)); + } + + void test_storage_saves_function() + { + TestStorage storage; + Id id = storage.onFunctionParsed( + validLocation(14), ParseFunction(typeUsage("bool"), "isTrue", parameters("char")), validLocation(41) + ); + + Node* node = storage.getNodeWithId(id); + TS_ASSERT(node); + TS_ASSERT_EQUALS(node->getFullName(), "isTrue"); + TS_ASSERT_EQUALS(node->getType(), Node::NODE_FUNCTION); + + Edge* returnEdge = node->findEdgeOfType(Edge::EDGE_RETURN_TYPE_OF); + TS_ASSERT(returnEdge); + TS_ASSERT_EQUALS(returnEdge->getTo()->getFullName(), "bool"); + + Edge* paramEdge = node->findEdgeOfType(Edge::EDGE_PARAMETER_TYPE_OF); + TS_ASSERT(paramEdge); + TS_ASSERT_EQUALS(paramEdge->getTo()->getFullName(), "char"); + + TS_ASSERT(node->getComponent()); + TS_ASSERT_EQUALS(node->getComponent()->getSignature(), "isTrue(char)"); + + std::vector locations = storage.getLocationsForId(id); + TS_ASSERT_EQUALS(locations.size(), 2); + TS_ASSERT(isValidLocation(locations[0], 14)); + TS_ASSERT(isValidLocation(locations[1], 41)); + TS_ASSERT_EQUALS(locations[1]->getType(), TokenLocation::LOCATION_SCOPE); + } + + void test_storage_saves_method() + { + TestStorage storage; + Id id = storage.onMethodParsed( + validLocation(9), + ParseFunction(typeUsage("void"), "isMethod", parameters("bool")), + ParserClient::ACCESS_NONE, + ParserClient::ABSTRACTION_NONE, + validLocation(4) + ); + + Node* node = storage.getNodeWithId(id); + TS_ASSERT(node); + TS_ASSERT_EQUALS(node->getFullName(), "isMethod"); + TS_ASSERT_EQUALS(node->getType(), Node::NODE_METHOD); + + Edge* returnEdge = node->findEdgeOfType(Edge::EDGE_RETURN_TYPE_OF); + TS_ASSERT(returnEdge); + TS_ASSERT_EQUALS(returnEdge->getTo()->getFullName(), "void"); + + Edge* paramEdge = node->findEdgeOfType(Edge::EDGE_PARAMETER_TYPE_OF); + TS_ASSERT(paramEdge); + TS_ASSERT_EQUALS(paramEdge->getTo()->getFullName(), "bool"); + + TS_ASSERT(node->getComponent()); + TS_ASSERT_EQUALS(node->getComponent()->getSignature(), "isMethod(bool)"); + + std::vector locations = storage.getLocationsForId(id); + TS_ASSERT_EQUALS(locations.size(), 2); + TS_ASSERT(isValidLocation(locations[0], 9)); + TS_ASSERT(isValidLocation(locations[1], 4)); + TS_ASSERT_EQUALS(locations[1]->getType(), TokenLocation::LOCATION_SCOPE); + } + + void test_storage_saves_method_static() + { + TestStorage storage; + Id id = storage.onMethodParsed( + validLocation(1), + ParseFunction(typeUsage("void"), "isMethod", parameters("bool"), true), + ParserClient::ACCESS_NONE, + ParserClient::ABSTRACTION_NONE, + validLocation(4) + ); + + Node* node = storage.getNodeWithId(id); + TS_ASSERT(node); + TS_ASSERT_EQUALS(node->getFullName(), "isMethod"); + TS_ASSERT_EQUALS(node->getType(), Node::NODE_METHOD); + TS_ASSERT(node->getComponent()); + } + + void test_storage_saves_method_as_member() + { + TestStorage storage; + Id id = storage.onMethodParsed( + validLocation(1), + ParseFunction(typeUsage("void"), "Class::isMethod", parameters("bool")), + ParserClient::ACCESS_PROTECTED, + ParserClient::ABSTRACTION_VIRTUAL, + validLocation(4) + ); + + Node* node = storage.getNodeWithId(id); + TS_ASSERT(node); + TS_ASSERT_EQUALS(node->getName(), "isMethod"); + TS_ASSERT_EQUALS(node->getFullName(), "Class::isMethod"); + TS_ASSERT_EQUALS(node->getType(), Node::NODE_METHOD); + + Edge* memberEdge = node->getMemberEdge(); + TS_ASSERT(memberEdge); + TS_ASSERT_EQUALS(memberEdge->getType(), Edge::EDGE_MEMBER); + + TS_ASSERT(memberEdge->getComponent()); + TS_ASSERT_EQUALS( + memberEdge->getComponent()->getAccess(), TokenComponentAccess::ACCESS_PROTECTED + ); + + TS_ASSERT_EQUALS(memberEdge->getFrom()->getFullName(), "Class"); + TS_ASSERT_EQUALS(memberEdge->getFrom()->getType(), Node::NODE_UNDEFINED); + } + + void test_storage_saves_namespace() + { + TestStorage storage; + Id id = storage.onNamespaceParsed(validLocation(1), "utility", validLocation(2)); + + Node* node = storage.getNodeWithId(id); + TS_ASSERT(node); + TS_ASSERT_EQUALS(node->getFullName(), "utility"); + TS_ASSERT_EQUALS(node->getType(), Node::NODE_NAMESPACE); + + std::vector locations = storage.getLocationsForId(id); + TS_ASSERT_EQUALS(locations.size(), 2); + TS_ASSERT(isValidLocation(locations[0], 1)); + TS_ASSERT(isValidLocation(locations[1], 2)); + TS_ASSERT_EQUALS(locations[1]->getType(), TokenLocation::LOCATION_SCOPE); + } + + void test_storage_saves_enum() + { + TestStorage storage; + Id id = storage.onEnumParsed(validLocation(17), "Category", ParserClient::ACCESS_NONE, validLocation(23)); + + Node* node = storage.getNodeWithId(id); + TS_ASSERT(node); + TS_ASSERT_EQUALS(node->getFullName(), "Category"); + TS_ASSERT_EQUALS(node->getType(), Node::NODE_ENUM); + + std::vector locations = storage.getLocationsForId(id); + TS_ASSERT_EQUALS(locations.size(), 2); + TS_ASSERT(isValidLocation(locations[0], 17)); + TS_ASSERT(isValidLocation(locations[1], 23)); + TS_ASSERT_EQUALS(locations[1]->getType(), TokenLocation::LOCATION_SCOPE); + } + + void test_storage_saves_enum_as_member() + { + TestStorage storage; + Id id = + storage.onEnumParsed(validLocation(1), "Class::Category", ParserClient::ACCESS_PRIVATE, validLocation(2)); + + Node* node = storage.getNodeWithId(id); + TS_ASSERT(node); + TS_ASSERT_EQUALS(node->getFullName(), "Class::Category"); + TS_ASSERT_EQUALS(node->getType(), Node::NODE_ENUM); + + Edge* memberEdge = node->getMemberEdge(); + TS_ASSERT(memberEdge); + TS_ASSERT_EQUALS(memberEdge->getType(), Edge::EDGE_MEMBER); + + TS_ASSERT(memberEdge->getComponent()); + TS_ASSERT_EQUALS( + memberEdge->getComponent()->getAccess(), TokenComponentAccess::ACCESS_PRIVATE + ); + + TS_ASSERT_EQUALS(memberEdge->getFrom()->getFullName(), "Class"); + TS_ASSERT_EQUALS(memberEdge->getFrom()->getType(), Node::NODE_UNDEFINED); + } + + void test_storage_saves_enum_field() + { + TestStorage storage; + Id id = storage.onEnumFieldParsed(validLocation(1), "VALUE"); + + Node* node = storage.getNodeWithId(id); + TS_ASSERT(node); + TS_ASSERT_EQUALS(node->getFullName(), "VALUE"); + TS_ASSERT_EQUALS(node->getType(), Node::NODE_FIELD); + + std::vector locations = storage.getLocationsForId(id); + TS_ASSERT_EQUALS(locations.size(), 1); + TS_ASSERT(isValidLocation(locations[0], 1)); + } + + void test_storage_saves_inheritance() + { + TestStorage storage; + storage.onClassParsed(validLocation(), "ClassA", ParserClient::ACCESS_NONE, validLocation()); + storage.onClassParsed(validLocation(), "ClassB", ParserClient::ACCESS_NONE, validLocation()); + Id id = storage.onInheritanceParsed(validLocation(5), "ClassB", "ClassA", ParserClient::ACCESS_PUBLIC); + + Edge* edge = storage.getEdgeWithId(id); + TS_ASSERT(edge); + TS_ASSERT_EQUALS(edge->getType(), Edge::EDGE_INHERITANCE); + + TS_ASSERT(edge->getComponent()); + TS_ASSERT_EQUALS(edge->getComponent()->getAccess(), TokenComponentAccess::ACCESS_PUBLIC); + + TS_ASSERT_EQUALS(edge->getFrom()->getFullName(), "ClassB"); + TS_ASSERT_EQUALS(edge->getTo()->getFullName(), "ClassA"); + + std::vector locations = storage.getLocationsForId(id); + TS_ASSERT_EQUALS(locations.size(), 1); + TS_ASSERT(isValidLocation(locations[0], 5)); + } + + void test_storage_saves_call() + { + TestStorage storage; + storage.onFunctionParsed( + validLocation(), ParseFunction(typeUsage("bool"), "isTrue", parameters("char")), validLocation() + ); + storage.onFunctionParsed( + validLocation(), ParseFunction(typeUsage("void"), "func", parameters("bool")), validLocation() + ); + Id id = storage.onCallParsed( + validLocation(9), + ParseFunction(typeUsage("bool"), "isTrue", parameters("char")), + ParseFunction(typeUsage("void"), "func", parameters("bool")) + ); + + Edge* edge = storage.getEdgeWithId(id); + TS_ASSERT(edge); + TS_ASSERT_EQUALS(edge->getType(), Edge::EDGE_CALL); + + TS_ASSERT_EQUALS(edge->getFrom()->getFullName(), "isTrue"); + TS_ASSERT_EQUALS(edge->getTo()->getFullName(), "func"); + + std::vector locations = storage.getLocationsForId(id); + TS_ASSERT_EQUALS(locations.size(), 1); + TS_ASSERT(isValidLocation(locations[0], 9)); + } + + void test_storage_saves_call_in_global_variable_declaration() + { + TestStorage storage; + storage.onGlobalVariableParsed(validLocation(), ParseVariable(typeUsage("bool"), "global", false)); + storage.onFunctionParsed( + validLocation(), ParseFunction(typeUsage("bool"), "isTrue", parameters("char")), validLocation() + ); + + Id id = storage.onCallParsed( + validLocation(7), + ParseVariable(typeUsage("bool"), "global", false), + ParseFunction(typeUsage("bool"), "isTrue", parameters("char")) + ); + + Edge* edge = storage.getEdgeWithId(id); + TS_ASSERT(edge); + TS_ASSERT_EQUALS(edge->getType(), Edge::EDGE_CALL); + + TS_ASSERT_EQUALS(edge->getFrom()->getFullName(), "global"); + TS_ASSERT_EQUALS(edge->getTo()->getFullName(), "isTrue"); + + std::vector locations = storage.getLocationsForId(id); + TS_ASSERT_EQUALS(locations.size(), 1); + TS_ASSERT(isValidLocation(locations[0], 7)); + } + + void test_storage_saves_field_usage() + { + TestStorage storage; + storage.onFunctionParsed( + validLocation(), ParseFunction(typeUsage("bool"), "isTrue", parameters("char")), validLocation() + ); + storage.onFieldParsed( + validLocation(), ParseVariable(typeUsage("bool"), "Foo::m_field", false), ParserClient::ACCESS_PRIVATE + ); + + Id id = storage.onFieldUsageParsed( + validLocation(7), + ParseFunction(typeUsage("bool"), "isTrue", parameters("char")), + "Foo::m_field" + ); + + Edge* edge = storage.getEdgeWithId(id); + TS_ASSERT(edge); + TS_ASSERT_EQUALS(edge->getType(), Edge::EDGE_USAGE); + + TS_ASSERT_EQUALS(edge->getFrom()->getFullName(), "isTrue"); + TS_ASSERT_EQUALS(edge->getTo()->getFullName(), "Foo::m_field"); + + std::vector locations = storage.getLocationsForId(id); + TS_ASSERT_EQUALS(locations.size(), 1); + TS_ASSERT(isValidLocation(locations[0], 7)); + } + + void test_storage_saves_global_variable_usage() + { + TestStorage storage; + storage.onFunctionParsed( + validLocation(), ParseFunction(typeUsage("bool"), "isTrue", parameters("char")), validLocation() + ); + storage.onGlobalVariableParsed(validLocation(), ParseVariable(typeUsage("bool"), "global", false)); + + Id id = storage.onGlobalVariableUsageParsed( + validLocation(7), + ParseFunction(typeUsage("bool"), "isTrue", parameters("char")), + "global" + ); + + Edge* edge = storage.getEdgeWithId(id); + TS_ASSERT(edge); + TS_ASSERT_EQUALS(edge->getType(), Edge::EDGE_USAGE); + + TS_ASSERT_EQUALS(edge->getFrom()->getFullName(), "isTrue"); + TS_ASSERT_EQUALS(edge->getTo()->getFullName(), "global"); + + std::vector locations = storage.getLocationsForId(id); + TS_ASSERT_EQUALS(locations.size(), 1); + TS_ASSERT(isValidLocation(locations[0], 7)); + } + + void test_storage_saves_type_usage() + { + TestStorage storage; + storage.onFunctionParsed( + validLocation(), ParseFunction(typeUsage("bool"), "isTrue", parameters("char")), validLocation() + ); + storage.onStructParsed(validLocation(), "Struct", ParserClient::ACCESS_NONE, validLocation()); + + Id id = storage.onTypeUsageParsed( + typeUsage("Struct"), + ParseFunction(typeUsage("bool"), "isTrue", parameters("char")) + ); + + Edge* edge = storage.getEdgeWithId(id); + TS_ASSERT(edge); + TS_ASSERT_EQUALS(edge->getType(), Edge::EDGE_TYPE_USAGE); + + TS_ASSERT_EQUALS(edge->getFrom()->getFullName(), "isTrue"); + TS_ASSERT_EQUALS(edge->getTo()->getFullName(), "Struct"); + + std::vector locations = storage.getLocationsForId(id); + TS_ASSERT_EQUALS(locations.size(), 1); + TS_ASSERT(isValidLocation(locations[0], 0)); + } + +private: + class TestStorage + : public Storage + { + public: + Node* getNodeWithId(Id id) const + { + return dynamic_cast(getTokenWithId(id)); + } + + Edge* getEdgeWithId(Id id) const + { + return dynamic_cast(getTokenWithId(id)); + } + + std::vector getLocationsForId(Id id) const + { + return getTokenLocationsForId(id); + } + }; + + ParseLocation validLocation(Id locationId = 0) const + { + return ParseLocation("file.cpp", 1, locationId, 1, locationId); + } + + bool isValidLocation(TokenLocation* location, Id locationId) const + { + return + location->getFilePath() == "file.cpp" && + location->getLineNumber() == 1 && + location->getColumnNumber() == locationId; + } + + ParseTypeUsage typeUsage(const std::string& typeName) const + { + return ParseTypeUsage(validLocation(), DataType(typeName)); + } + + std::vector parameters(const std::string& param) const + { + std::vector params; + params.push_back(typeUsage(param)); + return params; + } +}; diff --git a/src/test/TextAccessTestSuite.h b/src/test/TextAccessTestSuite.h index 1205f424..1e9eb539 100644 --- a/src/test/TextAccessTestSuite.h +++ b/src/test/TextAccessTestSuite.h @@ -1,8 +1,5 @@ #include "cxxtest/TestSuite.h" -#include -#include - #include "utility/text/TextAccess.h" class TextAccessTestSuite : public CxxTest::TestSuite