testing: Moved tests from tests.cpp to testmemleak.cpp (forwhile, switch)

This commit is contained in:
Daniel Marjamäki 2008-08-22 06:30:06 +00:00
parent 794cdfd2ee
commit c618971609
5 changed files with 618 additions and 599 deletions

View File

@ -251,20 +251,16 @@ static TOKEN *getcode(const TOKEN *tok, const char varname[])
} }
else else
{ {
if (Match(tok, "if")) if (Match(tok, "if") ||
addtoken("if"); Match(tok, "else") ||
if (Match(tok, "else")) Match(tok, "switch") ||
addtoken("else"); Match(tok, "case") ||
if (Match(tok, "switch")) Match(tok, "default"))
addtoken("switch"); addtoken(tok->str);
} }
// Loops.. // Loops..
if ( Match(tok, "for") ) if (Match(tok, "for") || Match(tok, "while") || Match(tok, "do") )
addtoken("loop");
if ( Match(tok, "while") )
addtoken("loop");
if ( Match(tok, "do") )
addtoken("loop"); addtoken("loop");
// continue / break.. // continue / break..

View File

@ -1,250 +1,250 @@
/* /*
* Copyright (c) 2003-2004 Pau Arum<EFBFBD> & David Garc<EFBFBD>a * Copyright (c) 2003-2004 Pau Arum<EFBFBD> & David Garc<EFBFBD>a
* *
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* *
*/ */
#include "MiniCppUnit.h" #include "MiniCppUnit.h"
#include <cmath> #include <cmath>
#ifdef _MSC_VER #if defined(_MSC_VER) || defined(__BORLANDC__)
#include <float.h> #include <float.h>
namespace std namespace std
{ {
template <typename T> template <typename T>
inline bool isnan(T x) { inline bool isnan(T x) {
return _isnan(x) != 0; return _isnan(x) != 0;
} }
template <typename T> template <typename T>
inline bool isinf(T x) { inline bool isinf(T x) {
return _finite(x) == 0; return _finite(x) == 0;
} }
} }
#endif #endif
TestsListener& TestsListener::theInstance() TestsListener& TestsListener::theInstance()
{ {
static TestsListener instancia; static TestsListener instancia;
return instancia; return instancia;
} }
std::stringstream& TestsListener::errorsLog() std::stringstream& TestsListener::errorsLog()
{ {
if (_currentTestName) if (_currentTestName)
_log << "\n" << errmsgTag_nameOfTest() << (*_currentTestName) << "\n"; _log << "\n" << errmsgTag_nameOfTest() << (*_currentTestName) << "\n";
return _log; return _log;
} }
std::string TestsListener::logString() std::string TestsListener::logString()
{ {
std::string aRetornar = _log.str(); std::string aRetornar = _log.str();
_log.str(""); _log.str("");
return aRetornar; return aRetornar;
} }
void TestsListener::currentTestName( std::string& name) void TestsListener::currentTestName( std::string& name)
{ {
_currentTestName = &name; _currentTestName = &name;
} }
void TestsListener::testHasRun() void TestsListener::testHasRun()
{ {
std::cout << "."; std::cout << ".";
theInstance()._executed++; theInstance()._executed++;
} }
void TestsListener::testHasFailed() void TestsListener::testHasFailed()
{ {
std::cout << "F"; std::cout << "F";
theInstance()._failed++; theInstance()._failed++;
throw TestFailedException(); throw TestFailedException();
} }
void TestsListener::testHasThrown() void TestsListener::testHasThrown()
{ {
std::cout << "E"; std::cout << "E";
theInstance()._exceptions++; theInstance()._exceptions++;
} }
std::string TestsListener::summary() std::string TestsListener::summary()
{ {
std::ostringstream os; std::ostringstream os;
os << "\nSummary:\n" os << "\nSummary:\n"
<< Assert::bold() << "\tExecuted Tests: " << Assert::bold() << "\tExecuted Tests: "
<< _executed << Assert::normal() << std::endl << _executed << Assert::normal() << std::endl
<< Assert::green() << "\tPassed Tests: " << Assert::green() << "\tPassed Tests: "
<< (_executed-_failed-_exceptions) << (_executed-_failed-_exceptions)
<< Assert::normal() << std::endl; << Assert::normal() << std::endl;
if (_failed > 0) if (_failed > 0)
{ {
os << Assert::red() << "\tFailed Tests: " os << Assert::red() << "\tFailed Tests: "
<< _failed << Assert::normal() << std::endl; << _failed << Assert::normal() << std::endl;
} }
if (_exceptions > 0) if (_exceptions > 0)
{ {
os << Assert::yellow() << "\tUnexpected exceptions: " os << Assert::yellow() << "\tUnexpected exceptions: "
<< _exceptions << Assert::normal() << std::endl; << _exceptions << Assert::normal() << std::endl;
} }
os << std::endl; os << std::endl;
return os.str(); return os.str();
} }
bool TestsListener::allTestsPassed() bool TestsListener::allTestsPassed()
{ {
return !theInstance()._exceptions && !theInstance()._failed; return !theInstance()._exceptions && !theInstance()._failed;
} }
void Assert::assertTrue(char* strExpression, bool expression, void Assert::assertTrue(char* strExpression, bool expression,
const char* file, int linia) const char* file, int linia)
{ {
if (!expression) if (!expression)
{ {
TestsListener::theInstance().errorsLog() << "\n" TestsListener::theInstance().errorsLog() << "\n"
<< errmsgTag_testFailedIn() << file << errmsgTag_testFailedIn() << file
<< errmsgTag_inLine() << linia << "\n" << errmsgTag_inLine() << linia << "\n"
<< errmsgTag_failedExpression() << errmsgTag_failedExpression()
<< bold() << strExpression << normal() << "\n"; << bold() << strExpression << normal() << "\n";
TestsListener::theInstance().testHasFailed(); TestsListener::theInstance().testHasFailed();
} }
} }
void Assert::assertTrueMissatge(char* strExpression, bool expression, void Assert::assertTrueMissatge(char* strExpression, bool expression,
const char* missatge, const char* file, int linia) const char* missatge, const char* file, int linia)
{ {
if (!expression) if (!expression)
{ {
TestsListener::theInstance().errorsLog() << "\n" TestsListener::theInstance().errorsLog() << "\n"
<< errmsgTag_testFailedIn() << file << errmsgTag_testFailedIn() << file
<< errmsgTag_inLine() << linia << "\n" << errmsgTag_inLine() << linia << "\n"
<< errmsgTag_failedExpression() << errmsgTag_failedExpression()
<< bold() << strExpression << "\n" << bold() << strExpression << "\n"
<< missatge<< normal() << "\n"; << missatge<< normal() << "\n";
TestsListener::theInstance().testHasFailed(); TestsListener::theInstance().testHasFailed();
} }
} }
void Assert::assertEquals( const char * expected, const char * result, void Assert::assertEquals( const char * expected, const char * result,
const char* file, int linia ) const char* file, int linia )
{ {
assertEquals(std::string(expected), std::string(result), assertEquals(std::string(expected), std::string(result),
file, linia); file, linia);
} }
void Assert::assertEquals( const bool& expected, const bool& result, void Assert::assertEquals( const bool& expected, const bool& result,
const char* file, int linia ) const char* file, int linia )
{ {
assertEquals( assertEquals(
(expected?"true":"false"), (expected?"true":"false"),
(result?"true":"false"), (result?"true":"false"),
file, linia); file, linia);
} }
// floating point numbers comparisons taken // floating point numbers comparisons taken
// from c/c++ users journal. dec 04 pag 10 // from c/c++ users journal. dec 04 pag 10
bool isNaN(double x) bool isNaN(double x)
{ {
bool b1 = (x < 0.0); bool b1 = (x < 0.0);
bool b2 = (x >= 0.0); bool b2 = (x >= 0.0);
return !(b1 || b2); return !(b1 || b2);
} }
double scaledEpsilon(const double& expected, const double& fuzzyEpsilon ) double scaledEpsilon(const double& expected, const double& fuzzyEpsilon )
{ {
const double aa = fabs(expected)+1; const double aa = std::fabs(expected)+1;
return (std::isinf(aa))? fuzzyEpsilon: fuzzyEpsilon * aa; return (std::isinf(aa))? fuzzyEpsilon: fuzzyEpsilon * aa;
} }
bool fuzzyEquals(double expected, double result, double fuzzyEpsilon) bool fuzzyEquals(double expected, double result, double fuzzyEpsilon)
{ {
return (expected==result) || ( fabs(expected-result) <= scaledEpsilon(expected, fuzzyEpsilon) ); return (expected==result) || ( std::fabs(expected-result) <= scaledEpsilon(expected, fuzzyEpsilon) );
} }
void Assert::assertEquals( const double& expected, const double& result, void Assert::assertEquals( const double& expected, const double& result,
const char* file, int linia ) const char* file, int linia )
{ {
const double fuzzyEpsilon = 0.000001; const double fuzzyEpsilon = 0.000001;
assertEqualsEpsilon( expected, result, fuzzyEpsilon, file, linia ); assertEqualsEpsilon( expected, result, fuzzyEpsilon, file, linia );
} }
void Assert::assertEquals( const float& expected, const float& result, void Assert::assertEquals( const float& expected, const float& result,
const char* file, int linia ) const char* file, int linia )
{ {
assertEquals((double)expected, (double)result, file, linia); assertEquals((double)expected, (double)result, file, linia);
} }
void Assert::assertEquals( const long double& expected, const long double& result, void Assert::assertEquals( const long double& expected, const long double& result,
const char* file, int linia ) const char* file, int linia )
{ {
assertEquals((double)expected, (double)result, file, linia); assertEquals((double)expected, (double)result, file, linia);
} }
void Assert::assertEqualsEpsilon( const double& expected, const double& result, const double& epsilon, void Assert::assertEqualsEpsilon( const double& expected, const double& result, const double& epsilon,
const char* file, int linia ) const char* file, int linia )
{ {
if (isNaN(expected) && isNaN(result) ) return; if (isNaN(expected) && isNaN(result) ) return;
if (!isNaN(expected) && !isNaN(result) && fuzzyEquals(expected, result, epsilon) ) return; if (!isNaN(expected) && !isNaN(result) && fuzzyEquals(expected, result, epsilon) ) return;
TestsListener::theInstance().errorsLog() TestsListener::theInstance().errorsLog()
<< errmsgTag_testFailedIn() << file << errmsgTag_testFailedIn() << file
<< errmsgTag_inLine() << linia << "\n" << errmsgTag_inLine() << linia << "\n"
<< errmsgTag_expected() << errmsgTag_expected()
<< bold() << expected << normal() << " " << bold() << expected << normal() << " "
<< errmsgTag_butWas() << errmsgTag_butWas()
<< bold() << result << normal() << "\n"; << bold() << result << normal() << "\n";
TestsListener::theInstance().testHasFailed(); TestsListener::theInstance().testHasFailed();
} }
int Assert::notEqualIndex( const std::string & one, const std::string & other ) int Assert::notEqualIndex( const std::string & one, const std::string & other )
{ {
int end = std::min(one.length(), other.length()); int end = std::min(one.length(), other.length());
for ( int index = 0; index < end; index++ ) for ( int index = 0; index < end; index++ )
if (one[index] != other[index] ) if (one[index] != other[index] )
return index; return index;
return end; return end;
} }
/** /**
* we overload the assert with string doing colored diffs * we overload the assert with string doing colored diffs
* *
* MS Visual6 doesn't allow string by reference :-( * MS Visual6 doesn't allow string by reference :-(
*/ */
void Assert::assertEquals( const std::string expected, const std::string result, void Assert::assertEquals( const std::string expected, const std::string result,
const char* file, int linia ) const char* file, int linia )
{ {
if(expected == result) if(expected == result)
return; return;
int indexDiferent = notEqualIndex(expected, result); int indexDiferent = notEqualIndex(expected, result);
TestsListener::theInstance().errorsLog() TestsListener::theInstance().errorsLog()
<< file << ", line: " << linia << "\n" << file << ", line: " << linia << "\n"
<< errmsgTag_expected() << "\n" << blue() << errmsgTag_expected() << "\n" << blue()
<< expected.substr(0,indexDiferent) << expected.substr(0,indexDiferent)
<< green() << expected.substr(indexDiferent) << green() << expected.substr(indexDiferent)
<< normal() << "\n" << normal() << "\n"
<< errmsgTag_butWas() << blue() << "\n" << errmsgTag_butWas() << blue() << "\n"
<< result.substr(0,indexDiferent) << result.substr(0,indexDiferent)
<< red() << result.substr(indexDiferent) << red() << result.substr(indexDiferent)
<< normal() << std::endl; << normal() << std::endl;
TestsListener::theInstance().testHasFailed(); TestsListener::theInstance().testHasFailed();
} }
void Assert::fail(const char* motiu, const char* file, int linia) void Assert::fail(const char* motiu, const char* file, int linia)
{ {
TestsListener::theInstance().errorsLog() << TestsListener::theInstance().errorsLog() <<
file << errmsgTag_inLine() << linia << "\n" << file << errmsgTag_inLine() << linia << "\n" <<
"Reason: " << motiu << "\n"; "Reason: " << motiu << "\n";
TestsListener::theInstance().testHasFailed(); TestsListener::theInstance().testHasFailed();
} }

View File

@ -1,4 +1,4 @@
/* /*
* Copyright (c) 2003-2004 Pau Arum<EFBFBD> & David Garc<EFBFBD>a * Copyright (c) 2003-2004 Pau Arum<EFBFBD> & David Garc<EFBFBD>a
* *
* *
@ -163,7 +163,7 @@ class Assert
static const char * errmsgTag_butWas() { return "But was: "; } static const char * errmsgTag_butWas() { return "But was: "; }
public: public:
#ifdef _MSC_VER #if defined(_MSC_VER) || defined(__BORLANDC__)
static const char * blue() { return ""; } static const char * blue() { return ""; }
static const char * green() { return ""; } static const char * green() { return ""; }
static const char * red() { return ""; } static const char * red() { return ""; }

View File

@ -1,253 +1,359 @@
#include "tokenize.h" #include "tokenize.h"
#include "CheckMemoryLeak.h" #include "CheckMemoryLeak.h"
#include "MiniCppUnit.h" #include "MiniCppUnit.h"
#include <sstream> #include <sstream>
extern std::ostringstream errout; extern std::ostringstream errout;
extern bool ShowAll; extern bool ShowAll;
class TestMemleak : public TestFixture<TestMemleak> class TestMemleak : public TestFixture<TestMemleak>
{ {
private: private:
void check( const char code[] ) void check( const char code[] )
{ {
// Tokenize.. // Tokenize..
tokens = tokens_back = NULL; tokens = tokens_back = NULL;
std::istringstream istr(code); std::istringstream istr(code);
TokenizeCode( istr ); TokenizeCode( istr );
SimplifyTokenList(); SimplifyTokenList();
// Clear the error buffer.. // Clear the error buffer..
errout.str(""); errout.str("");
// Check for memory leaks.. // Check for memory leaks..
ShowAll = false; ShowAll = false;
CheckMemoryLeak(); CheckMemoryLeak();
} }
public: public:
TEST_FIXTURE( TestMemleak ) TEST_FIXTURE( TestMemleak )
{ {
TEST_CASE( simple1 ); TEST_CASE( simple1 );
TEST_CASE( simple2 ); TEST_CASE( simple2 );
TEST_CASE( simple3 ); TEST_CASE( simple3 );
TEST_CASE( simple4 ); TEST_CASE( simple4 );
TEST_CASE( simple5 ); TEST_CASE( simple5 );
TEST_CASE( simple6 ); TEST_CASE( simple6 );
TEST_CASE( simple7 ); TEST_CASE( simple7 );
TEST_CASE( ifelse1 ); TEST_CASE( ifelse1 );
TEST_CASE( ifelse2 ); TEST_CASE( ifelse2 );
TEST_CASE( ifelse3 ); TEST_CASE( ifelse3 );
TEST_CASE( ifelse4 ); TEST_CASE( ifelse4 );
TEST_CASE( ifelse5 ); TEST_CASE( ifelse5 );
}
TEST_CASE( forwhile1 );
void simple1() TEST_CASE( forwhile2 );
{
check( "void f()\n"
"{\n" TEST_CASE( switch1 );
" int *a = new int[10];\n" // TODO: TEST_CASE( switch2 );
"}\n" );
ASSERT_EQUALS( std::string("[test.cpp:4]: Memory leak: a\n"), errout.str() ); TEST_CASE( mismatch1 );
}
}
void simple2()
{ void simple1()
check( "Fred *NewFred()\n" {
"{\n" check( "void f()\n"
" Fred *f = new Fred;\n" "{\n"
" return f;\n" " int *a = new int[10];\n"
"}\n" ); "}\n" );
ASSERT_EQUALS( std::string(""), errout.str() ); ASSERT_EQUALS( std::string("[test.cpp:4]: Memory leak: a\n"), errout.str() );
} }
void simple3() void simple2()
{ {
check( "static char *f()\n" check( "Fred *NewFred()\n"
"{\n" "{\n"
" char *s = new char[100];\n" " Fred *f = new Fred;\n"
" return (char *)s;\n" " return f;\n"
"}\n" ); "}\n" );
ASSERT_EQUALS( std::string(""), errout.str() ); ASSERT_EQUALS( std::string(""), errout.str() );
} }
void simple3()
void simple4() {
{ check( "static char *f()\n"
check( "static char *f()\n" "{\n"
"{\n" " char *s = new char[100];\n"
" char *s = new char[100];\n" " return (char *)s;\n"
" return 0;\n" "}\n" );
"}\n" ); ASSERT_EQUALS( std::string(""), errout.str() );
ASSERT_EQUALS( std::string("[test.cpp:4]: Memory leak: s\n"), errout.str() ); }
}
void simple4()
void simple5() {
{ check( "static char *f()\n"
check( "static char *f()\n" "{\n"
"{\n" " char *s = new char[100];\n"
" struct *str = new strlist;\n" " return 0;\n"
" return &str->s;\n" "}\n" );
"}\n" ); ASSERT_EQUALS( std::string("[test.cpp:4]: Memory leak: s\n"), errout.str() );
ASSERT_EQUALS( std::string(""), errout.str() ); }
}
void simple5()
void simple6() {
{ check( "static char *f()\n"
check( "static void f()\n" "{\n"
"{\n" " struct *str = new strlist;\n"
" char *str = strdup(\"hello\");\n" " return &str->s;\n"
" char *str2 = (char *)str;\n" "}\n" );
" free(str2);\n" ASSERT_EQUALS( std::string(""), errout.str() );
"}\n" ); }
ASSERT_EQUALS( std::string(""), errout.str() );
}
void simple6()
{
void simple7() check( "static void f()\n"
{ "{\n"
// A garbage collector may delete f automaticly " char *str = strdup(\"hello\");\n"
check( "class Fred;\n" " char *str2 = (char *)str;\n"
"void foo()\n" " free(str2);\n"
"{\n" "}\n" );
" Fred *f = new Fred;\n" ASSERT_EQUALS( std::string(""), errout.str() );
"}\n" ); }
ASSERT_EQUALS( std::string(""), errout.str() );
}
void simple7()
{
// A garbage collector may delete f automaticly
check( "class Fred;\n"
"void foo()\n"
void ifelse1() "{\n"
{ " Fred *f = new Fred;\n"
check( "void f()\n" "}\n" );
"{\n" ASSERT_EQUALS( std::string(""), errout.str() );
" int *a = new int[10];\n" }
" if (a)\n"
" {\n"
" delete [] a;\n"
" }\n"
"}\n" );
ASSERT_EQUALS( std::string(""), errout.str() ); void ifelse1()
} {
check( "void f()\n"
"{\n"
void ifelse2() " int *a = new int[10];\n"
{ " if (a)\n"
check( "void f()\n" " {\n"
"{\n" " delete [] a;\n"
" char *str = strdup(\"hello\");\n" " }\n"
" if (somecondition)\n" "}\n" );
" {\n" ASSERT_EQUALS( std::string(""), errout.str() );
" return;\n" }
" }\n"
" free(str);\n"
"}\n" ); void ifelse2()
ASSERT_EQUALS( std::string("[test.cpp:6]: Memory leak: str\n"), errout.str() ); {
} check( "void f()\n"
"{\n"
" char *str = strdup(\"hello\");\n"
void ifelse3() " if (somecondition)\n"
{ " {\n"
check( "void f()\n" " return;\n"
"{\n" " }\n"
" char *str = strdup(\"hello\");\n" " free(str);\n"
" if (a==b)\n" "}\n" );
" {\n" ASSERT_EQUALS( std::string("[test.cpp:6]: Memory leak: str\n"), errout.str() );
" free(str);\n" }
" return;\n"
" }\n"
"}\n" ); void ifelse3()
ASSERT_EQUALS( std::string("[test.cpp:9]: Memory leak: str\n"), errout.str() ); {
} check( "void f()\n"
"{\n"
" char *str = strdup(\"hello\");\n"
void ifelse4() " if (a==b)\n"
{ " {\n"
check( "void f()\n" " free(str);\n"
"{\n" " return;\n"
" char *str = new char[10];\n" " }\n"
" if (a==b)\n" "}\n" );
" {\n" ASSERT_EQUALS( std::string("[test.cpp:9]: Memory leak: str\n"), errout.str() );
" delete [] str;\n" }
" return;\n"
" }\n"
" delete [] str;\n" void ifelse4()
"}\n" ); {
ASSERT_EQUALS( std::string(""), errout.str() ); check( "void f()\n"
} "{\n"
" char *str = new char[10];\n"
" if (a==b)\n"
void ifelse5() " {\n"
{ " delete [] str;\n"
check( "void f()\n" " return;\n"
"{\n" " }\n"
" char *str;\n" " delete [] str;\n"
" if (somecondition)\n" "}\n" );
" {\n" ASSERT_EQUALS( std::string(""), errout.str() );
" str = new char[100];\n" }
" }\n"
" else\n"
" {\n" void ifelse5()
" return;\n" {
" }\n" check( "void f()\n"
" delete [] str;\n" "{\n"
"}\n" ); " char *str;\n"
ASSERT_EQUALS( std::string(""), errout.str() ); " if (somecondition)\n"
} " {\n"
" str = new char[100];\n"
" }\n"
void ifelse6() " else\n"
{ " {\n"
check( "static char *f()\n" " return;\n"
"{\n" " }\n"
" char *s = new char[100];\n" " delete [] str;\n"
" if ( a == b )\n" "}\n" );
" {\n" ASSERT_EQUALS( std::string(""), errout.str() );
" return s;\n" }
" }\n"
" return NULL;\n"
"}\n" ); void ifelse6()
ASSERT_EQUALS( std::string("[test.cpp:8]: Memory leak: s\n"), errout.str() ); {
} check( "static char *f()\n"
"{\n"
" char *s = new char[100];\n"
void ifelse7() " if ( a == b )\n"
{ " {\n"
check( "static char *f()\n" " return s;\n"
"{\n" " }\n"
" char *s;\n" " return NULL;\n"
" if ( abc )\n" "}\n" );
" {\n" ASSERT_EQUALS( std::string("[test.cpp:8]: Memory leak: s\n"), errout.str() );
" s = new char[10];\n" }
" }\n"
" return s;\n"
"}\n" ); void ifelse7()
ASSERT_EQUALS( std::string(""), errout.str() ); {
} check( "static char *f()\n"
"{\n"
" char *s;\n"
void ifelse8() " if ( abc )\n"
{ " {\n"
check( "static char *f()\n" " s = new char[10];\n"
"{\n" " }\n"
" char *s = new char[10];\n" " return s;\n"
" if ( s )\n" "}\n" );
" {\n" ASSERT_EQUALS( std::string(""), errout.str() );
" return s;\n" }
" }\n"
" return 0;\n"
"}\n" ); void ifelse8()
ASSERT_EQUALS( std::string(""), errout.str() ); {
} check( "static char *f()\n"
}; "{\n"
" char *s = new char[10];\n"
REGISTER_FIXTURE( TestMemleak ) " if ( s )\n"
" {\n"
" return s;\n"
" }\n"
" return 0;\n"
"}\n" );
ASSERT_EQUALS( std::string(""), errout.str() );
}
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( std::string(""), 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( std::string("[test.cpp:7]: 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( std::string(""), errout.str() );
}
void switch2()
{
check("void f()\n"
"{\n"
" char *str = new char[10];\n"
" switch (abc)\n"
" {\n"
" case 1:\n"
" delete [] str;\n"
" break;\n"
" default:\n"
" break;\n"
" };\n"
"}\n");
ASSERT_EQUALS( std::string("[test.cpp:12]: Memory leak"), errout.str() );
}
void mismatch1()
{
check( "void f()\n"
"{\n"
" int *a = new int[10];\n"
" free(a);\n"
"}\n");
ASSERT_EQUALS( std::string("[test.cpp:4]: Mismatching allocation and deallocation: a\n"), errout.str() );
}
};
REGISTER_FIXTURE( TestMemleak )

View File

@ -455,31 +455,8 @@ static void operator_eq()
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
static void check_(void (chk)(),
const unsigned int line,
const char code[],
const char msg[])
{
ShowAll = false;
check( chk, line, code, msg );
ShowAll = true;
check( chk, line, code, msg );
}
static void memleak_in_function() static void memleak_in_function()
{ {
// There are 2 sections:
// * Simple testcases
// * if else
// * for/while
// * switch
// * mismatching allocation and deallocation
// * garbage collection
// * arrays
// * struct members
// * function calls
//////////////////////////////////////////////// ////////////////////////////////////////////////
@ -487,32 +464,6 @@ static void memleak_in_function()
//////////////////////////////////////////////// ////////////////////////////////////////////////
code = "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";
check_( CheckMemoryLeak, __LINE__, code, "" );
code = "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";
check_( CheckMemoryLeak, __LINE__, code, "[test.cpp:7]: Memory leak: str\n" );
@ -520,40 +471,6 @@ static void memleak_in_function()
////////////////////////////////////////////////
// switch
////////////////////////////////////////////////
code = "void f()\n"
"{\n"
" char *str = new char[10];\n"
" switch (abc)\n"
" {\n"
" case 1:\n"
" break;\n"
" };\n"
" delete [] str;\n"
"}\n";
check_( CheckMemoryLeak, __LINE__, code, "" );
////////////////////////////////////////////////
// mismatching allocation and deallocation
////////////////////////////////////////////////
code = "void f()\n"
"{\n"
" int *a = new int[10];\n"
" free(a);\n"
"}\n";
check_( CheckMemoryLeak, __LINE__, code, "[test.cpp:4]: Mismatching allocation and deallocation: a\n" );