Refactoring the unit tests of TestMemleakInFunction

This commit is contained in:
Daniel Marjamäki 2009-08-25 22:18:22 +02:00
parent 8dcb846627
commit d67e3fcc49
1 changed files with 123 additions and 274 deletions

View File

@ -124,7 +124,9 @@ private:
TEST_CASE(testgetcode); TEST_CASE(testgetcode);
// Todo: check that call_func works correctly.. // Todo: check that call_func works correctly..
// Todo: check that simplifycode works correctly..
// Check that simplifycode works correctly..
TEST_CASE(simplifycode);
// Check that errors are found.. // Check that errors are found..
TEST_CASE(findleak); TEST_CASE(findleak);
@ -133,16 +135,12 @@ private:
TEST_CASE(simple7); TEST_CASE(simple7);
TEST_CASE(simple9); // Bug 2435468 - member function "free" TEST_CASE(simple9); // Bug 2435468 - member function "free"
TEST_CASE(simple11); TEST_CASE(simple11);
TEST_CASE(simple12);
TEST_CASE(new_nothrow); TEST_CASE(new_nothrow);
TEST_CASE(staticvar); TEST_CASE(staticvar);
TEST_CASE(alloc_alloc_1); TEST_CASE(alloc_alloc_1);
TEST_CASE(ifelse3);
TEST_CASE(ifelse4);
TEST_CASE(ifelse5);
TEST_CASE(ifelse6); TEST_CASE(ifelse6);
TEST_CASE(ifelse7); TEST_CASE(ifelse7);
TEST_CASE(ifelse8); TEST_CASE(ifelse8);
@ -150,36 +148,25 @@ private:
TEST_CASE(ifelse10); TEST_CASE(ifelse10);
TEST_CASE(if1); TEST_CASE(if1);
TEST_CASE(if2);
TEST_CASE(if3); TEST_CASE(if3);
TEST_CASE(if4); TEST_CASE(if4);
TEST_CASE(if5); TEST_CASE(if5);
TEST_CASE(if6); // Bug 2432631
TEST_CASE(if7); // Bug 2401436 TEST_CASE(if7); // Bug 2401436
TEST_CASE(if8); // Bug 2458532 TEST_CASE(if8); // Bug 2458532
TEST_CASE(if9); // if (realloc) TEST_CASE(if9); // if (realloc)
TEST_CASE(if10); // else if (realloc) TEST_CASE(if10); // else if (realloc)
TEST_CASE(if11); TEST_CASE(if11);
TEST_CASE(forwhile1);
TEST_CASE(forwhile2);
TEST_CASE(forwhile3);
TEST_CASE(forwhile4);
TEST_CASE(forwhile5); TEST_CASE(forwhile5);
TEST_CASE(forwhile6); TEST_CASE(forwhile6);
TEST_CASE(forwhile7);
TEST_CASE(forwhile8); // Bug 2429936 TEST_CASE(forwhile8); // Bug 2429936
TEST_CASE(forwhile9); TEST_CASE(forwhile9);
TEST_CASE(forwhile10); TEST_CASE(forwhile10);
TEST_CASE(forwhile11); TEST_CASE(forwhile11);
TEST_CASE(dowhile1);
TEST_CASE(switch1);
TEST_CASE(switch2); TEST_CASE(switch2);
TEST_CASE(switch3); TEST_CASE(switch3);
TEST_CASE(ret1);
TEST_CASE(ret2); TEST_CASE(ret2);
TEST_CASE(ret3); TEST_CASE(ret3);
TEST_CASE(ret4); TEST_CASE(ret4);
@ -266,9 +253,7 @@ private:
TEST_CASE(assign_pclose); TEST_CASE(assign_pclose);
// Using the function "exit" // Using the function "exit"
TEST_CASE(exit1);
TEST_CASE(exit2); TEST_CASE(exit2);
TEST_CASE(exit3);
TEST_CASE(exit4); TEST_CASE(exit4);
TEST_CASE(exit5); TEST_CASE(exit5);
TEST_CASE(stdstring); TEST_CASE(stdstring);
@ -356,11 +341,16 @@ private:
ASSERT_EQUALS(";;if{}", getcode("char *s; if (a && s) { }", "s")); ASSERT_EQUALS(";;if{}", getcode("char *s; if (a && s) { }", "s"));
ASSERT_EQUALS(";;if(!var){}", getcode("char *s; if (a && !s) { }", "s")); ASSERT_EQUALS(";;if(!var){}", getcode("char *s; if (a && !s) { }", "s"));
// switch..
ASSERT_EQUALS(";;switch{case;break;};", getcode("char *s; switch(a){case 1: break;};", "s"));
// loop.. // loop..
ASSERT_EQUALS(";;loop{}", getcode("char *s; while (a) { }", "s")); ASSERT_EQUALS(";;loop{}", getcode("char *s; while (a) { }", "s"));
ASSERT_EQUALS(";;loopcallfunc{}", getcode("char *s; while (a()) { }", "s")); ASSERT_EQUALS(";;loopcallfunc{}", getcode("char *s; while (a()) { }", "s"));
ASSERT_EQUALS(";;loop{}", getcode("char *s; while (s) { }", "s")); ASSERT_EQUALS(";;loop{}", getcode("char *s; while (s) { }", "s"));
ASSERT_EQUALS(";;loop{}", getcode("char *s; for (a;b;c) { }", "s")); ASSERT_EQUALS(";;loop{}", getcode("char *s; for (a;b;c) { }", "s"));
ASSERT_EQUALS(";;loop{alloc;}", getcode("char *s; for (a;b;c) { s=malloc(10); }", "s"));
ASSERT_EQUALS(";;do{}loop;", getcode("char *s; do { } while (a);", "s"));
// use.. // use..
ASSERT_EQUALS(";;use;", getcode("char *s; DeleteString(s);", "s")); ASSERT_EQUALS(";;use;", getcode("char *s; DeleteString(s);", "s"));
@ -376,8 +366,109 @@ private:
// exit.. // exit..
ASSERT_EQUALS(";;exit;", getcode("char *s; exit(0);", "s")); ASSERT_EQUALS(";;exit;", getcode("char *s; exit(0);", "s"));
ASSERT_EQUALS(";;if{exit;}", getcode("char *s; if (a) { exit(0); }", "s"));
} }
std::string simplifycode(const char code[], bool all = false) const
{
// Tokenize..
Tokenizer tokenizer;
std::istringstream istr(code);
tokenizer.tokenize(istr, "test.cpp");
// replace "if ( ! var )" => "if(!var)"
for (Token *tok = tokenizer._tokens; tok; tok = tok->next())
{
if (Token::simpleMatch(tok, "if ( var )"))
{
Token::eraseTokens(tok, tok->tokAt(4));
tok->str("if(var)");
}
else if (Token::simpleMatch(tok, "if ( ! var )"))
{
Token::eraseTokens(tok, tok->tokAt(5));
tok->str("if(!var)");
}
}
Settings settings;
settings._showAll = all;
CheckMemoryLeakInFunction checkMemoryLeak(&tokenizer, &settings, NULL);
all = false;
checkMemoryLeak.simplifycode(tokenizer._tokens, all);
std::ostringstream ret;
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next())
ret << (tok->previous() ? " " : "") << tok->str();
return ret.str();
}
// Test that the CheckMemoryLeaksInFunction::simplifycode works
void simplifycode()
{
ASSERT_EQUALS(";", simplifycode("; ; ; ;"));
ASSERT_EQUALS(";", simplifycode("; if ;"));
ASSERT_EQUALS("alloc ;", simplifycode("alloc ; if ; if(var) ; ifv ; if(!var) ;"));
ASSERT_EQUALS("alloc ;", simplifycode("alloc ; if ; else ;"));
// if, else..
ASSERT_EQUALS("; alloc ; if break ; dealloc ;", simplifycode("; alloc ; if { break; } dealloc ;"));
ASSERT_EQUALS("; alloc ; if continue ; dealloc ;", simplifycode("; alloc ; if { continue; } dealloc ;"));
ASSERT_EQUALS("; alloc ;", simplifycode("; alloc; if { return use; }"));
ASSERT_EQUALS("; alloc ; dealloc ;", simplifycode("; alloc; if(!var) { return; } dealloc;"));
ASSERT_EQUALS("; alloc ;", simplifycode("; if { alloc; } else { return; }"));
ASSERT_EQUALS("; alloc ; dealloc ;", simplifycode("; alloc ; if(!var) { alloc ; } dealloc ;"));
{
const char code[] = "; alloc ; if { dealloc ; return ; }";
ASSERT_EQUALS(code, simplifycode(code));
ASSERT_EQUALS("; alloc ;", simplifycode(code, true));
}
// switch..
ASSERT_EQUALS("; alloc ; dealloc ;", simplifycode(";alloc;switch{case;break;};dealloc;"));
// loops..
ASSERT_EQUALS(";", simplifycode("; loop { if { break; } }"));
ASSERT_EQUALS("; loop alloc ;", simplifycode("; loop { alloc ; }"));
ASSERT_EQUALS("; alloc ; alloc ;", simplifycode("; alloc ; do { alloc ; } loop ;"));
// return..
// exit..
ASSERT_EQUALS(";", simplifycode("; if { alloc; exit; }"));
ASSERT_EQUALS("; alloc ;", simplifycode("; alloc ; if { use; exit; }"));
// Todo..
ASSERT_EQUALS("; alloc ; if(!var) exit ;", simplifycode("; alloc ; if(!var) { exit; }"));
TODO_ASSERT_EQUALS("; alloc ;", simplifycode("; alloc ; if(!var) { exit; }"));
TODO_ASSERT_EQUALS(";", simplifycode("; alloc ; if(var) { exit; }"));
TODO_ASSERT_EQUALS(";", simplifycode("; alloc ; ifv { exit; }", false));
TODO_ASSERT_EQUALS("; alloc ;", simplifycode("; alloc ; ifv { exit; }", true));
ASSERT_EQUALS("; alloc ; if { dealloc ; return ; }", simplifycode("; alloc; if { dealloc; return; }"));
TODO_ASSERT_EQUALS("; alloc ;", simplifycode("; alloc; if { dealloc; return; }"));
ASSERT_EQUALS("; alloc ; if return ; return ;", simplifycode(";alloc;if{return;}return;"));
TODO_ASSERT_EQUALS("; alloc ; return ;", simplifycode(";alloc;if{return;}return;"));
{
const char code[] = "; alloc ; if { dealloc ; return ; } dealloc ;";
ASSERT_EQUALS(code, simplifycode(code));
TODO_ASSERT_EQUALS("; alloc ; dealloc ;", simplifycode(code));
}
}
// is there a leak in given code? if so, return the linenr // is there a leak in given code? if so, return the linenr
int dofindleak(const char code[], bool all = false) const int dofindleak(const char code[], bool all = false) const
{ {
@ -431,16 +522,30 @@ private:
ASSERT_EQUALS(-1, dofindleak("alloc; if { dealloc ; alloc; } dealloc;")); ASSERT_EQUALS(-1, dofindleak("alloc; if { dealloc ; alloc; } dealloc;"));
ASSERT_EQUALS(-1, dofindleak("alloc;\n if(!var)\n { callfunc;\n return;\n }\n use;")); ASSERT_EQUALS(-1, dofindleak("alloc;\n if(!var)\n { callfunc;\n return;\n }\n use;"));
ASSERT_EQUALS(-1, dofindleak("alloc; if { return use; } dealloc;"));
ASSERT_EQUALS(-1, dofindleak("alloc; if { dealloc; return; } dealloc;"));
// assign.. // assign..
ASSERT_EQUALS(2, dofindleak("alloc;\n assign;\n dealloc;")); ASSERT_EQUALS(2, dofindleak("alloc;\n assign;\n dealloc;"));
ASSERT_EQUALS(-1, dofindleak("alloc;\n if(!var) assign;\n dealloc;")); ASSERT_EQUALS(-1, dofindleak("alloc;\n if(!var) assign;\n dealloc;"));
// loop..
ASSERT_EQUALS(1, dofindleak("; loop { alloc ; if break; dealloc ; }"));
ASSERT_EQUALS(1, dofindleak("; loop { alloc ; if continue; dealloc ; }"));
ASSERT_EQUALS(1, dofindleak("; loop alloc ;"));
ASSERT_EQUALS(1, dofindleak("; loop alloc ; dealloc ;"));
// Todo.. // Todo..
ASSERT_EQUALS(-1, dofindleak("; alloc;\n if { dealloc; }\n ;")); ASSERT_EQUALS(-1, dofindleak("; alloc;\n if { dealloc; }\n ;"));
TODO_ASSERT_EQUALS(3, dofindleak("; alloc;\n if { dealloc; }\n ;")); TODO_ASSERT_EQUALS(3, dofindleak("; alloc;\n if { dealloc; }\n ;"));
ASSERT_EQUALS(-1, dofindleak("alloc;\n if assign;\n dealloc;")); ASSERT_EQUALS(-1, dofindleak("alloc;\n if assign;\n dealloc;"));
TODO_ASSERT_EQUALS(2, dofindleak("alloc;\n if assign;\n dealloc;")); TODO_ASSERT_EQUALS(2, dofindleak("alloc;\n if assign;\n dealloc;"));
ASSERT_EQUALS(-1, dofindleak("alloc; if { return use; }"));
TODO_ASSERT_EQUALS(1, dofindleak("alloc; if { return use; }"));
ASSERT_EQUALS(-1, dofindleak("alloc; if { dealloc; return; }"));
TODO_ASSERT_EQUALS(1, dofindleak("alloc; if { dealloc; return; }"));
} }
@ -500,17 +605,6 @@ private:
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void simple12()
{
check("void f()\n"
"{\n"
" char *s;\n"
" foo(s);\n"
" s = malloc(100);\n"
"}\n");
ASSERT_EQUALS("[test.cpp:6]: (error) Memory leak: s\n", errout.str());
}
void new_nothrow() void new_nothrow()
@ -591,66 +685,6 @@ private:
void ifelse3()
{
check("void f()\n"
"{\n"
" char *str = strdup(\"hello\");\n"
" if (a==b)\n"
" {\n"
" free(str);\n"
" return;\n"
" }\n"
"}\n");
ASSERT_EQUALS("", errout.str());
check("void f()\n"
"{\n"
" char *str = strdup(\"hello\");\n"
" if (a==b)\n"
" {\n"
" free(str);\n"
" return;\n"
" }\n"
"}\n", true);
ASSERT_EQUALS("[test.cpp:9]: (possible error) Memory leak: str\n", errout.str());
}
void ifelse4()
{
check("void f()\n"
"{\n"
" char *str = new char[10];\n"
" if (a==b)\n"
" {\n"
" delete [] str;\n"
" return;\n"
" }\n"
" delete [] str;\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
void ifelse5()
{
check("void f()\n"
"{\n"
" char *str;\n"
" if (somecondition)\n"
" {\n"
" str = new char[100];\n"
" }\n"
" else\n"
" {\n"
" return;\n"
" }\n"
" delete [] str;\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
void ifelse6() void ifelse6()
{ {
@ -744,19 +778,6 @@ private:
ASSERT_EQUALS("[test.cpp:6]: (error) Memory leak: p\n", errout.str()); ASSERT_EQUALS("[test.cpp:6]: (error) Memory leak: p\n", errout.str());
} }
void if2()
{
check("void f()\n"
"{\n"
" struct smp_alt_module *smp;\n"
" smp = kzalloc(sizeof(*smp), GFP_KERNEL);\n"
" if (NULL == smp)\n"
" return;\n"
" kfree( smp );\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
void if3() void if3()
{ {
check("void f()\n" check("void f()\n"
@ -794,22 +815,6 @@ private:
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void if6()
{
check("void f()\n"
"{\n"
" FILE *a = 0;\n"
" a = fopen(\"test.txt\", \"rw\");\n"
" if( a == 0 )\n"
" {\n"
" a = fopen(\"test.txt\", \"r\");\n"
" }\n"
"\n"
" fclose( a );\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
void if7() void if7()
{ {
check("void f( bool b )\n" check("void f( bool b )\n"
@ -893,73 +898,6 @@ private:
void forwhile1()
{
check("void f()\n"
"{\n"
" char *str = strdup(\"hello\");\n"
" while (condition)\n"
" {\n"
" if (condition)\n"
" {\n"
" break;\n"
" }\n"
" }\n"
" free(str);\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
void forwhile2()
{
check("void f()\n"
"{\n"
" for (int i = 0; i < j; i++)\n"
" {\n"
" char *str = strdup(\"hello\");\n"
" if (condition)\n"
" continue;\n"
" free(str);\n"
" }\n"
"}\n");
ASSERT_EQUALS("[test.cpp:7]: (error) Memory leak: str\n", errout.str());
}
void forwhile3()
{
check("void f()\n"
"{\n"
" char *str = 0;\n"
" for (int i = 0; i < 10; i++)\n"
" {\n"
" str = strdup(\"hello\");\n"
" }\n"
" free(str);\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Memory leak: str\n", errout.str());
}
void forwhile4()
{
check("void f()\n"
"{\n"
" char *str = 0;\n"
" for (int i = 0; i < 10; i++)\n"
" {\n"
" str = strdup(\"hello\");\n"
" if (str) { }\n"
" }\n"
" free(str);\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Memory leak: str\n", errout.str());
}
void forwhile5() void forwhile5()
{ {
check("void f(const char **a)\n" check("void f(const char **a)\n"
@ -989,22 +927,6 @@ private:
} }
void forwhile7()
{
check("void f()\n"
"{\n"
" for (int i = 0; i < j; i++)\n"
" {\n"
" char *str = strdup(\"hello\");\n"
" if (condition)\n"
" break;\n"
" free(str);\n"
" }\n"
"}\n");
ASSERT_EQUALS("[test.cpp:7]: (error) Memory leak: str\n", errout.str());
}
void forwhile8() void forwhile8()
{ {
check("char *f()\n" check("char *f()\n"
@ -1085,38 +1007,6 @@ private:
void dowhile1()
{
check("void f()\n"
"{\n"
" char *str = strdup(\"abc\");\n"
" do\n"
" {\n"
" str = strdup(\"def\");\n"
" }\n"
" while (!str);\n"
" return str;\n"
"}\n");
ASSERT_EQUALS("[test.cpp:6]: (error) Memory leak: str\n", errout.str());
}
void switch1()
{
check("void f()\n"
"{\n"
" char *str = new char[10];\n"
" switch (abc)\n"
" {\n"
" case 1:\n"
" break;\n"
" };\n"
" delete [] str;\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
void switch2() void switch2()
{ {
const std::string code("void f()\n" const std::string code("void f()\n"
@ -1158,18 +1048,6 @@ private:
void ret1()
{
check("char *f( char **str )\n"
"{\n"
" char *ret = malloc( 10 );\n"
" return *str = ret;\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
void ret2() void ret2()
{ {
check("void foo()\n" check("void foo()\n"
@ -2152,22 +2030,6 @@ private:
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void exit1()
{
// Ticket #297
check("void f()\n"
"{\n"
" char *out = new char[100];\n"
" if (c())\n"
" {\n"
" delete [] out;\n"
" exit(0);\n"
" }\n"
" delete [] out;\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
void exit2() void exit2()
{ {
check("void f()\n" check("void f()\n"
@ -2186,19 +2048,6 @@ private:
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void exit3()
{
check("void f()\n"
"{\n"
" char *p = malloc(100);\n"
" if (p)\n"
" {\n"
" exit(0);\n"
" }\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
void exit4() void exit4()
{ {
check("void f()\n" check("void f()\n"