Symbol database: better unit testing. ticket: #2468

This commit is contained in:
Robert Reif 2011-01-28 08:33:02 +01:00 committed by Daniel Marjamäki
parent 75695a723e
commit 79862573ba
3 changed files with 226 additions and 0 deletions

View File

@ -1348,6 +1348,42 @@ const Scope *SymbolDatabase::findVariableType(const Scope *start, const Token *t
//---------------------------------------------------------------------------
const Scope *SymbolDatabase::findFunctionScopeByToken(const Token *tok) const
{
std::list<Scope *>::const_iterator scope;
for (scope = scopeList.begin(); scope != scopeList.end(); ++scope)
{
if ((*scope)->type == Scope::eFunction)
{
if ((*scope)->classDef == tok)
return (*scope);
}
}
return 0;
}
//---------------------------------------------------------------------------
const Function *SymbolDatabase::findFunctionByToken(const Token *tok) const
{
std::list<Scope *>::const_iterator scope;
for (scope = scopeList.begin(); scope != scopeList.end(); ++scope)
{
std::list<Function>::const_iterator func;
for (func = (*scope)->functionList.begin(); func != (*scope)->functionList.end(); ++func)
{
if (func->token == tok)
return &*func;
}
}
return 0;
}
//---------------------------------------------------------------------------
Scope * Scope::findInNestedList(const std::string & name)
{
std::list<Scope *>::iterator it;

View File

@ -362,6 +362,10 @@ public:
*/
const Scope *findVariableType(const Scope *start, const Token *type) const;
const Scope *findFunctionScopeByToken(const Token *tok) const;
const Function *findFunctionByToken(const Token *tok) const;
bool argsMatch(const Scope *info, const Token *first, const Token *second, const std::string &path, unsigned int depth) const;
bool isClassOrStruct(const std::string &type) const

View File

@ -20,6 +20,14 @@
#include "testutils.h"
#include "symboldatabase.h"
#define GET_SYMBOL_DB(code) \
errout.str(""); \
Settings settings; \
Tokenizer tokenizer(&settings, this); \
std::istringstream istr(code); \
tokenizer.tokenize(istr, "test.cpp"); \
const SymbolDatabase *db = tokenizer.getSymbolDatabase();
class TestSymbolDatabase: public TestFixture
{
public:
@ -75,6 +83,16 @@ private:
TEST_CASE(canFindMatchingBracketsOuterPair);
TEST_CASE(canFindMatchingBracketsWithTooManyClosing);
TEST_CASE(canFindMatchingBracketsWithTooManyOpening);
TEST_CASE(hasRegularFunction);
TEST_CASE(hasInlineClassFunction);
TEST_CASE(hasMissingInlineClassFunction);
TEST_CASE(hasClassFunction);
TEST_CASE(hasRegularFunctionReturningFunctionPointer);
TEST_CASE(hasInlineClassFunctionReturningFunctionPointer);
TEST_CASE(hasMissingInlineClassFunctionReturningFunctionPointer);
TEST_CASE(hasClassFunctionReturningFunctionPointer);
}
void test_isVariableDeclarationCanHandleNull()
@ -336,6 +354,174 @@ private:
found = si.findClosingBracket(var.tokens()->tokAt(1), t);
ASSERT(!found);
}
void hasRegularFunction()
{
GET_SYMBOL_DB("void func() { }\n")
// 2 scopes: Global and Function
ASSERT(db && db->scopeList.size() == 2 && tokenizer.getFunctionTokenByName("func"));
if (db)
{
const Scope *scope = db->findFunctionScopeByToken(tokenizer.tokens()->tokAt(1));
ASSERT(scope && scope->className == "func");
const Function *function = db->findFunctionByToken(tokenizer.tokens()->tokAt(1));
ASSERT(function && function->token->str() == "func");
ASSERT(function && function->token == tokenizer.tokens()->tokAt(1));
ASSERT(function && function->hasBody);
}
}
void hasInlineClassFunction()
{
GET_SYMBOL_DB("class Fred { void func() { } };\n")
// 3 scopes: Global, Class, and Function
ASSERT(db && db->scopeList.size() == 3 && tokenizer.getFunctionTokenByName("func"));
if (db)
{
const Scope *scope = db->findFunctionScopeByToken(tokenizer.tokens()->tokAt(4));
ASSERT(scope && scope->className == "func");
const Function *function = db->findFunctionByToken(tokenizer.tokens()->tokAt(4));
ASSERT(function && function->token->str() == "func");
ASSERT(function && function->token == tokenizer.tokens()->tokAt(4));
ASSERT(function && function->hasBody && function->isInline);
}
}
void hasMissingInlineClassFunction()
{
GET_SYMBOL_DB("class Fred { void func(); };\n")
// 2 scopes: Global and Class (no Function scope because there is no function implementation)
ASSERT(db && db->scopeList.size() == 2 && !tokenizer.getFunctionTokenByName("func"));
if (db)
{
const Scope *scope = db->findFunctionScopeByToken(tokenizer.tokens()->tokAt(4));
ASSERT(scope == NULL);
const Function *function = db->findFunctionByToken(tokenizer.tokens()->tokAt(4));
ASSERT(function && function->token->str() == "func");
ASSERT(function && function->token == tokenizer.tokens()->tokAt(4));
ASSERT(function && !function->hasBody);
}
}
void hasClassFunction()
{
GET_SYMBOL_DB("class Fred { void func(); }; Fred::func() { }\n")
// 3 scopes: Global, Class, and Function
ASSERT(db && db->scopeList.size() == 3 && tokenizer.getFunctionTokenByName("func"));
if (db)
{
const Scope *scope = db->findFunctionScopeByToken(tokenizer.tokens()->tokAt(12));
ASSERT(scope && scope->className == "func");
const Function *function = db->findFunctionByToken(tokenizer.tokens()->tokAt(12));
ASSERT(function && function->token->str() == "func");
ASSERT(function && function->token == tokenizer.tokens()->tokAt(12));
ASSERT(function && function->hasBody && !function->isInline);
}
}
void hasRegularFunctionReturningFunctionPointer()
{
GET_SYMBOL_DB("void (*func(int f))(char) { }\n")
// 2 scopes: Global and Function
ASSERT(db && db->scopeList.size() == 2 && tokenizer.getFunctionTokenByName("func"));
if (db)
{
const Scope *scope = db->findFunctionScopeByToken(tokenizer.tokens()->tokAt(3));
ASSERT(scope && scope->className == "func");
const Function *function = db->findFunctionByToken(tokenizer.tokens()->tokAt(3));
ASSERT(function && function->token->str() == "func");
ASSERT(function && function->token == tokenizer.tokens()->tokAt(3));
ASSERT(function && function->hasBody && function->retFuncPtr);
}
}
void hasInlineClassFunctionReturningFunctionPointer()
{
GET_SYMBOL_DB("class Fred { void (*func(int f))(char) { } };\n")
// 3 scopes: Global, Class, and Function
ASSERT(db && db->scopeList.size() == 3 && tokenizer.getFunctionTokenByName("func"));
if (db)
{
const Scope *scope = db->findFunctionScopeByToken(tokenizer.tokens()->tokAt(6));
ASSERT(scope && scope->className == "func");
const Function *function = db->findFunctionByToken(tokenizer.tokens()->tokAt(6));
ASSERT(function && function->token->str() == "func");
ASSERT(function && function->token == tokenizer.tokens()->tokAt(6));
ASSERT(function && function->hasBody && function->isInline && function->retFuncPtr);
}
}
void hasMissingInlineClassFunctionReturningFunctionPointer()
{
GET_SYMBOL_DB("class Fred { void (*func(int f))(char); };\n")
// 2 scopes: Global and Class (no Function scope because there is no function implementation)
ASSERT(db && db->scopeList.size() == 2 && !tokenizer.getFunctionTokenByName("func"));
if (db)
{
const Scope *scope = db->findFunctionScopeByToken(tokenizer.tokens()->tokAt(6));
ASSERT(scope == NULL);
const Function *function = db->findFunctionByToken(tokenizer.tokens()->tokAt(6));
ASSERT(function && function->token->str() == "func");
ASSERT(function && function->token == tokenizer.tokens()->tokAt(6));
ASSERT(function && !function->hasBody && function->retFuncPtr);
}
}
void hasClassFunctionReturningFunctionPointer()
{
GET_SYMBOL_DB("class Fred { void (*func(int f))(char); }; void (*Fred::func(int f))(char) { }\n")
// 3 scopes: Global, Class, and Function
ASSERT(db && db->scopeList.size() == 3 && tokenizer.getFunctionTokenByName("func"));
if (db)
{
const Scope *scope = db->findFunctionScopeByToken(tokenizer.tokens()->tokAt(23));
ASSERT(scope && scope->className == "func");
const Function *function = db->findFunctionByToken(tokenizer.tokens()->tokAt(23));
ASSERT(function && function->token->str() == "func");
ASSERT(function && function->token == tokenizer.tokens()->tokAt(23));
ASSERT(function && function->hasBody && !function->isInline && function->retFuncPtr);
}
}
};
REGISTER_TEST(TestSymbolDatabase)