testing: Moved tests from tests.cpp to testmemleak.cpp (forwhile, switch)
This commit is contained in:
parent
794cdfd2ee
commit
c618971609
|
@ -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..
|
||||||
|
|
500
MiniCppUnit.cpp
500
MiniCppUnit.cpp
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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 ""; }
|
||||||
|
|
612
testmemleak.cpp
612
testmemleak.cpp
|
@ -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 )
|
||||||
|
|
||||||
|
|
||||||
|
|
83
tests.cpp
83
tests.cpp
|
@ -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" );
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue