From c61897160996e8cad6e4d3a9a505b1fb4e16dfeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Fri, 22 Aug 2008 06:30:06 +0000 Subject: [PATCH] testing: Moved tests from tests.cpp to testmemleak.cpp (forwhile, switch) --- CheckMemoryLeak.cpp | 18 +- MiniCppUnit.cpp | 500 ++++++++++++++++++------------------ MiniCppUnit.h | 4 +- testmemleak.cpp | 612 ++++++++++++++++++++++++++------------------ tests.cpp | 83 ------ 5 files changed, 618 insertions(+), 599 deletions(-) diff --git a/CheckMemoryLeak.cpp b/CheckMemoryLeak.cpp index a257694b8..cf94dd9fe 100644 --- a/CheckMemoryLeak.cpp +++ b/CheckMemoryLeak.cpp @@ -251,20 +251,16 @@ static TOKEN *getcode(const TOKEN *tok, const char varname[]) } else { - if (Match(tok, "if")) - addtoken("if"); - if (Match(tok, "else")) - addtoken("else"); - if (Match(tok, "switch")) - addtoken("switch"); + if (Match(tok, "if") || + Match(tok, "else") || + Match(tok, "switch") || + Match(tok, "case") || + Match(tok, "default")) + addtoken(tok->str); } // Loops.. - if ( Match(tok, "for") ) - addtoken("loop"); - if ( Match(tok, "while") ) - addtoken("loop"); - if ( Match(tok, "do") ) + if (Match(tok, "for") || Match(tok, "while") || Match(tok, "do") ) addtoken("loop"); // continue / break.. diff --git a/MiniCppUnit.cpp b/MiniCppUnit.cpp index 4ddcaa1ec..5aa131c5c 100644 --- a/MiniCppUnit.cpp +++ b/MiniCppUnit.cpp @@ -1,250 +1,250 @@ -/* - * Copyright (c) 2003-2004 Pau Arum� & David Garc�a - * - * - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include "MiniCppUnit.h" - -#include - -#ifdef _MSC_VER -#include -namespace std -{ - template - inline bool isnan(T x) { - return _isnan(x) != 0; - } - template - inline bool isinf(T x) { - return _finite(x) == 0; - } -} -#endif - -TestsListener& TestsListener::theInstance() -{ - static TestsListener instancia; - return instancia; -} - -std::stringstream& TestsListener::errorsLog() -{ - if (_currentTestName) - _log << "\n" << errmsgTag_nameOfTest() << (*_currentTestName) << "\n"; - return _log; -} - -std::string TestsListener::logString() -{ - std::string aRetornar = _log.str(); - _log.str(""); - return aRetornar; -} -void TestsListener::currentTestName( std::string& name) -{ - _currentTestName = &name; -} -void TestsListener::testHasRun() -{ - std::cout << "."; - theInstance()._executed++; -} -void TestsListener::testHasFailed() -{ - std::cout << "F"; - theInstance()._failed++; - throw TestFailedException(); -} -void TestsListener::testHasThrown() -{ - std::cout << "E"; - theInstance()._exceptions++; -} -std::string TestsListener::summary() -{ - std::ostringstream os; - os << "\nSummary:\n" - << Assert::bold() << "\tExecuted Tests: " - << _executed << Assert::normal() << std::endl - << Assert::green() << "\tPassed Tests: " - << (_executed-_failed-_exceptions) - << Assert::normal() << std::endl; - if (_failed > 0) - { - os << Assert::red() << "\tFailed Tests: " - << _failed << Assert::normal() << std::endl; - } - if (_exceptions > 0) - { - os << Assert::yellow() << "\tUnexpected exceptions: " - << _exceptions << Assert::normal() << std::endl; - } - os << std::endl; - return os.str(); -} -bool TestsListener::allTestsPassed() -{ - return !theInstance()._exceptions && !theInstance()._failed; -} - - - -void Assert::assertTrue(char* strExpression, bool expression, - const char* file, int linia) -{ - if (!expression) - { - TestsListener::theInstance().errorsLog() << "\n" - << errmsgTag_testFailedIn() << file - << errmsgTag_inLine() << linia << "\n" - << errmsgTag_failedExpression() - << bold() << strExpression << normal() << "\n"; - TestsListener::theInstance().testHasFailed(); - } -} - -void Assert::assertTrueMissatge(char* strExpression, bool expression, - const char* missatge, const char* file, int linia) -{ - if (!expression) - { - TestsListener::theInstance().errorsLog() << "\n" - << errmsgTag_testFailedIn() << file - << errmsgTag_inLine() << linia << "\n" - << errmsgTag_failedExpression() - << bold() << strExpression << "\n" - << missatge<< normal() << "\n"; - TestsListener::theInstance().testHasFailed(); - } -} - - - -void Assert::assertEquals( const char * expected, const char * result, - const char* file, int linia ) -{ - assertEquals(std::string(expected), std::string(result), - file, linia); - -} -void Assert::assertEquals( const bool& expected, const bool& result, - const char* file, int linia ) -{ - assertEquals( - (expected?"true":"false"), - (result?"true":"false"), - file, linia); -} - -// floating point numbers comparisons taken -// from c/c++ users journal. dec 04 pag 10 -bool isNaN(double x) -{ - bool b1 = (x < 0.0); - bool b2 = (x >= 0.0); - return !(b1 || b2); -} - -double scaledEpsilon(const double& expected, const double& fuzzyEpsilon ) -{ - const double aa = fabs(expected)+1; - return (std::isinf(aa))? fuzzyEpsilon: fuzzyEpsilon * aa; -} -bool fuzzyEquals(double expected, double result, double fuzzyEpsilon) -{ - return (expected==result) || ( fabs(expected-result) <= scaledEpsilon(expected, fuzzyEpsilon) ); -} -void Assert::assertEquals( const double& expected, const double& result, - const char* file, int linia ) -{ - const double fuzzyEpsilon = 0.000001; - assertEqualsEpsilon( expected, result, fuzzyEpsilon, file, linia ); -} - -void Assert::assertEquals( const float& expected, const float& result, - const char* file, int linia ) -{ - assertEquals((double)expected, (double)result, file, linia); -} -void Assert::assertEquals( const long double& expected, const long double& result, - const char* file, int linia ) -{ - assertEquals((double)expected, (double)result, file, linia); -} -void Assert::assertEqualsEpsilon( const double& expected, const double& result, const double& epsilon, - const char* file, int linia ) -{ - if (isNaN(expected) && isNaN(result) ) return; - if (!isNaN(expected) && !isNaN(result) && fuzzyEquals(expected, result, epsilon) ) return; - - TestsListener::theInstance().errorsLog() - << errmsgTag_testFailedIn() << file - << errmsgTag_inLine() << linia << "\n" - << errmsgTag_expected() - << bold() << expected << normal() << " " - << errmsgTag_butWas() - << bold() << result << normal() << "\n"; - TestsListener::theInstance().testHasFailed(); -} - -int Assert::notEqualIndex( const std::string & one, const std::string & other ) -{ - int end = std::min(one.length(), other.length()); - for ( int index = 0; index < end; index++ ) - if (one[index] != other[index] ) - return index; - return end; -} - - -/** - * we overload the assert with string doing colored diffs - * - * MS Visual6 doesn't allow string by reference :-( - */ -void Assert::assertEquals( const std::string expected, const std::string result, - const char* file, int linia ) -{ - if(expected == result) - return; - - int indexDiferent = notEqualIndex(expected, result); - TestsListener::theInstance().errorsLog() - << file << ", line: " << linia << "\n" - << errmsgTag_expected() << "\n" << blue() - << expected.substr(0,indexDiferent) - << green() << expected.substr(indexDiferent) - << normal() << "\n" - << errmsgTag_butWas() << blue() << "\n" - << result.substr(0,indexDiferent) - << red() << result.substr(indexDiferent) - << normal() << std::endl; - - TestsListener::theInstance().testHasFailed(); -} -void Assert::fail(const char* motiu, const char* file, int linia) -{ - TestsListener::theInstance().errorsLog() << - file << errmsgTag_inLine() << linia << "\n" << - "Reason: " << motiu << "\n"; - - TestsListener::theInstance().testHasFailed(); -} - - +/* + * Copyright (c) 2003-2004 Pau Arum� & David Garc�a + * + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "MiniCppUnit.h" + +#include + +#if defined(_MSC_VER) || defined(__BORLANDC__) +#include +namespace std +{ + template + inline bool isnan(T x) { + return _isnan(x) != 0; + } + template + inline bool isinf(T x) { + return _finite(x) == 0; + } +} +#endif + +TestsListener& TestsListener::theInstance() +{ + static TestsListener instancia; + return instancia; +} + +std::stringstream& TestsListener::errorsLog() +{ + if (_currentTestName) + _log << "\n" << errmsgTag_nameOfTest() << (*_currentTestName) << "\n"; + return _log; +} + +std::string TestsListener::logString() +{ + std::string aRetornar = _log.str(); + _log.str(""); + return aRetornar; +} +void TestsListener::currentTestName( std::string& name) +{ + _currentTestName = &name; +} +void TestsListener::testHasRun() +{ + std::cout << "."; + theInstance()._executed++; +} +void TestsListener::testHasFailed() +{ + std::cout << "F"; + theInstance()._failed++; + throw TestFailedException(); +} +void TestsListener::testHasThrown() +{ + std::cout << "E"; + theInstance()._exceptions++; +} +std::string TestsListener::summary() +{ + std::ostringstream os; + os << "\nSummary:\n" + << Assert::bold() << "\tExecuted Tests: " + << _executed << Assert::normal() << std::endl + << Assert::green() << "\tPassed Tests: " + << (_executed-_failed-_exceptions) + << Assert::normal() << std::endl; + if (_failed > 0) + { + os << Assert::red() << "\tFailed Tests: " + << _failed << Assert::normal() << std::endl; + } + if (_exceptions > 0) + { + os << Assert::yellow() << "\tUnexpected exceptions: " + << _exceptions << Assert::normal() << std::endl; + } + os << std::endl; + return os.str(); +} +bool TestsListener::allTestsPassed() +{ + return !theInstance()._exceptions && !theInstance()._failed; +} + + + +void Assert::assertTrue(char* strExpression, bool expression, + const char* file, int linia) +{ + if (!expression) + { + TestsListener::theInstance().errorsLog() << "\n" + << errmsgTag_testFailedIn() << file + << errmsgTag_inLine() << linia << "\n" + << errmsgTag_failedExpression() + << bold() << strExpression << normal() << "\n"; + TestsListener::theInstance().testHasFailed(); + } +} + +void Assert::assertTrueMissatge(char* strExpression, bool expression, + const char* missatge, const char* file, int linia) +{ + if (!expression) + { + TestsListener::theInstance().errorsLog() << "\n" + << errmsgTag_testFailedIn() << file + << errmsgTag_inLine() << linia << "\n" + << errmsgTag_failedExpression() + << bold() << strExpression << "\n" + << missatge<< normal() << "\n"; + TestsListener::theInstance().testHasFailed(); + } +} + + + +void Assert::assertEquals( const char * expected, const char * result, + const char* file, int linia ) +{ + assertEquals(std::string(expected), std::string(result), + file, linia); + +} +void Assert::assertEquals( const bool& expected, const bool& result, + const char* file, int linia ) +{ + assertEquals( + (expected?"true":"false"), + (result?"true":"false"), + file, linia); +} + +// floating point numbers comparisons taken +// from c/c++ users journal. dec 04 pag 10 +bool isNaN(double x) +{ + bool b1 = (x < 0.0); + bool b2 = (x >= 0.0); + return !(b1 || b2); +} + +double scaledEpsilon(const double& expected, const double& fuzzyEpsilon ) +{ + const double aa = std::fabs(expected)+1; + return (std::isinf(aa))? fuzzyEpsilon: fuzzyEpsilon * aa; +} +bool fuzzyEquals(double expected, double result, double fuzzyEpsilon) +{ + return (expected==result) || ( std::fabs(expected-result) <= scaledEpsilon(expected, fuzzyEpsilon) ); +} +void Assert::assertEquals( const double& expected, const double& result, + const char* file, int linia ) +{ + const double fuzzyEpsilon = 0.000001; + assertEqualsEpsilon( expected, result, fuzzyEpsilon, file, linia ); +} + +void Assert::assertEquals( const float& expected, const float& result, + const char* file, int linia ) +{ + assertEquals((double)expected, (double)result, file, linia); +} +void Assert::assertEquals( const long double& expected, const long double& result, + const char* file, int linia ) +{ + assertEquals((double)expected, (double)result, file, linia); +} +void Assert::assertEqualsEpsilon( const double& expected, const double& result, const double& epsilon, + const char* file, int linia ) +{ + if (isNaN(expected) && isNaN(result) ) return; + if (!isNaN(expected) && !isNaN(result) && fuzzyEquals(expected, result, epsilon) ) return; + + TestsListener::theInstance().errorsLog() + << errmsgTag_testFailedIn() << file + << errmsgTag_inLine() << linia << "\n" + << errmsgTag_expected() + << bold() << expected << normal() << " " + << errmsgTag_butWas() + << bold() << result << normal() << "\n"; + TestsListener::theInstance().testHasFailed(); +} + +int Assert::notEqualIndex( const std::string & one, const std::string & other ) +{ + int end = std::min(one.length(), other.length()); + for ( int index = 0; index < end; index++ ) + if (one[index] != other[index] ) + return index; + return end; +} + + +/** + * we overload the assert with string doing colored diffs + * + * MS Visual6 doesn't allow string by reference :-( + */ +void Assert::assertEquals( const std::string expected, const std::string result, + const char* file, int linia ) +{ + if(expected == result) + return; + + int indexDiferent = notEqualIndex(expected, result); + TestsListener::theInstance().errorsLog() + << file << ", line: " << linia << "\n" + << errmsgTag_expected() << "\n" << blue() + << expected.substr(0,indexDiferent) + << green() << expected.substr(indexDiferent) + << normal() << "\n" + << errmsgTag_butWas() << blue() << "\n" + << result.substr(0,indexDiferent) + << red() << result.substr(indexDiferent) + << normal() << std::endl; + + TestsListener::theInstance().testHasFailed(); +} +void Assert::fail(const char* motiu, const char* file, int linia) +{ + TestsListener::theInstance().errorsLog() << + file << errmsgTag_inLine() << linia << "\n" << + "Reason: " << motiu << "\n"; + + TestsListener::theInstance().testHasFailed(); +} + + diff --git a/MiniCppUnit.h b/MiniCppUnit.h index 12b2650a8..3e2b781de 100644 --- a/MiniCppUnit.h +++ b/MiniCppUnit.h @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2003-2004 Pau Arum� & David Garc�a * * @@ -163,7 +163,7 @@ class Assert static const char * errmsgTag_butWas() { return "But was: "; } public: -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__BORLANDC__) static const char * blue() { return ""; } static const char * green() { return ""; } static const char * red() { return ""; } diff --git a/testmemleak.cpp b/testmemleak.cpp index 98682dcd9..b1225666e 100644 --- a/testmemleak.cpp +++ b/testmemleak.cpp @@ -1,253 +1,359 @@ - -#include "tokenize.h" -#include "CheckMemoryLeak.h" -#include "MiniCppUnit.h" - -#include - -extern std::ostringstream errout; -extern bool ShowAll; - -class TestMemleak : public TestFixture -{ -private: - void check( const char code[] ) - { - // Tokenize.. - tokens = tokens_back = NULL; - std::istringstream istr(code); - TokenizeCode( istr ); - SimplifyTokenList(); - - // Clear the error buffer.. - errout.str(""); - - // Check for memory leaks.. - ShowAll = false; - CheckMemoryLeak(); - } - -public: - TEST_FIXTURE( TestMemleak ) - { - TEST_CASE( simple1 ); - TEST_CASE( simple2 ); - TEST_CASE( simple3 ); - TEST_CASE( simple4 ); - TEST_CASE( simple5 ); - TEST_CASE( simple6 ); - TEST_CASE( simple7 ); - - TEST_CASE( ifelse1 ); - TEST_CASE( ifelse2 ); - TEST_CASE( ifelse3 ); - TEST_CASE( ifelse4 ); - TEST_CASE( ifelse5 ); - } - - void simple1() - { - check( "void f()\n" - "{\n" - " int *a = new int[10];\n" - "}\n" ); - ASSERT_EQUALS( std::string("[test.cpp:4]: Memory leak: a\n"), errout.str() ); - } - - void simple2() - { - check( "Fred *NewFred()\n" - "{\n" - " Fred *f = new Fred;\n" - " return f;\n" - "}\n" ); - ASSERT_EQUALS( std::string(""), errout.str() ); - } - - void simple3() - { - check( "static char *f()\n" - "{\n" - " char *s = new char[100];\n" - " return (char *)s;\n" - "}\n" ); - ASSERT_EQUALS( std::string(""), errout.str() ); - } - - - void simple4() - { - check( "static char *f()\n" - "{\n" - " char *s = new char[100];\n" - " return 0;\n" - "}\n" ); - ASSERT_EQUALS( std::string("[test.cpp:4]: Memory leak: s\n"), errout.str() ); - } - - - void simple5() - { - check( "static char *f()\n" - "{\n" - " struct *str = new strlist;\n" - " return &str->s;\n" - "}\n" ); - ASSERT_EQUALS( std::string(""), errout.str() ); - } - - - void simple6() - { - check( "static void f()\n" - "{\n" - " char *str = strdup(\"hello\");\n" - " char *str2 = (char *)str;\n" - " free(str2);\n" - "}\n" ); - ASSERT_EQUALS( std::string(""), errout.str() ); - } - - - void simple7() - { - // A garbage collector may delete f automaticly - check( "class Fred;\n" - "void foo()\n" - "{\n" - " Fred *f = new Fred;\n" - "}\n" ); - ASSERT_EQUALS( std::string(""), errout.str() ); - } - - - - - - void ifelse1() - { - check( "void f()\n" - "{\n" - " int *a = new int[10];\n" - " if (a)\n" - " {\n" - " delete [] a;\n" - " }\n" - "}\n" ); - ASSERT_EQUALS( std::string(""), errout.str() ); - } - - - void ifelse2() - { - check( "void f()\n" - "{\n" - " char *str = strdup(\"hello\");\n" - " if (somecondition)\n" - " {\n" - " return;\n" - " }\n" - " free(str);\n" - "}\n" ); - ASSERT_EQUALS( std::string("[test.cpp:6]: Memory leak: str\n"), errout.str() ); - } - - - 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( std::string("[test.cpp:9]: 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( std::string(""), 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( std::string(""), errout.str() ); - } - - - void ifelse6() - { - check( "static char *f()\n" - "{\n" - " char *s = new char[100];\n" - " if ( a == b )\n" - " {\n" - " return s;\n" - " }\n" - " return NULL;\n" - "}\n" ); - ASSERT_EQUALS( std::string("[test.cpp:8]: Memory leak: s\n"), errout.str() ); - } - - - void ifelse7() - { - check( "static char *f()\n" - "{\n" - " char *s;\n" - " if ( abc )\n" - " {\n" - " s = new char[10];\n" - " }\n" - " return s;\n" - "}\n" ); - ASSERT_EQUALS( std::string(""), errout.str() ); - } - - - void ifelse8() - { - check( "static char *f()\n" - "{\n" - " char *s = new char[10];\n" - " if ( s )\n" - " {\n" - " return s;\n" - " }\n" - " return 0;\n" - "}\n" ); - ASSERT_EQUALS( std::string(""), errout.str() ); - } -}; - -REGISTER_FIXTURE( TestMemleak ) - - + +#include "tokenize.h" +#include "CheckMemoryLeak.h" +#include "MiniCppUnit.h" + +#include + +extern std::ostringstream errout; +extern bool ShowAll; + +class TestMemleak : public TestFixture +{ +private: + void check( const char code[] ) + { + // Tokenize.. + tokens = tokens_back = NULL; + std::istringstream istr(code); + TokenizeCode( istr ); + SimplifyTokenList(); + + // Clear the error buffer.. + errout.str(""); + + // Check for memory leaks.. + ShowAll = false; + CheckMemoryLeak(); + } + +public: + TEST_FIXTURE( TestMemleak ) + { + TEST_CASE( simple1 ); + TEST_CASE( simple2 ); + TEST_CASE( simple3 ); + TEST_CASE( simple4 ); + TEST_CASE( simple5 ); + TEST_CASE( simple6 ); + TEST_CASE( simple7 ); + + TEST_CASE( ifelse1 ); + TEST_CASE( ifelse2 ); + TEST_CASE( ifelse3 ); + TEST_CASE( ifelse4 ); + TEST_CASE( ifelse5 ); + + TEST_CASE( forwhile1 ); + TEST_CASE( forwhile2 ); + + + TEST_CASE( switch1 ); + // TODO: TEST_CASE( switch2 ); + + TEST_CASE( mismatch1 ); + + } + + void simple1() + { + check( "void f()\n" + "{\n" + " int *a = new int[10];\n" + "}\n" ); + ASSERT_EQUALS( std::string("[test.cpp:4]: Memory leak: a\n"), errout.str() ); + } + + void simple2() + { + check( "Fred *NewFred()\n" + "{\n" + " Fred *f = new Fred;\n" + " return f;\n" + "}\n" ); + ASSERT_EQUALS( std::string(""), errout.str() ); + } + + void simple3() + { + check( "static char *f()\n" + "{\n" + " char *s = new char[100];\n" + " return (char *)s;\n" + "}\n" ); + ASSERT_EQUALS( std::string(""), errout.str() ); + } + + + void simple4() + { + check( "static char *f()\n" + "{\n" + " char *s = new char[100];\n" + " return 0;\n" + "}\n" ); + ASSERT_EQUALS( std::string("[test.cpp:4]: Memory leak: s\n"), errout.str() ); + } + + + void simple5() + { + check( "static char *f()\n" + "{\n" + " struct *str = new strlist;\n" + " return &str->s;\n" + "}\n" ); + ASSERT_EQUALS( std::string(""), errout.str() ); + } + + + void simple6() + { + check( "static void f()\n" + "{\n" + " char *str = strdup(\"hello\");\n" + " char *str2 = (char *)str;\n" + " free(str2);\n" + "}\n" ); + ASSERT_EQUALS( std::string(""), errout.str() ); + } + + + void simple7() + { + // A garbage collector may delete f automaticly + check( "class Fred;\n" + "void foo()\n" + "{\n" + " Fred *f = new Fred;\n" + "}\n" ); + ASSERT_EQUALS( std::string(""), errout.str() ); + } + + + + + + void ifelse1() + { + check( "void f()\n" + "{\n" + " int *a = new int[10];\n" + " if (a)\n" + " {\n" + " delete [] a;\n" + " }\n" + "}\n" ); + ASSERT_EQUALS( std::string(""), errout.str() ); + } + + + void ifelse2() + { + check( "void f()\n" + "{\n" + " char *str = strdup(\"hello\");\n" + " if (somecondition)\n" + " {\n" + " return;\n" + " }\n" + " free(str);\n" + "}\n" ); + ASSERT_EQUALS( std::string("[test.cpp:6]: Memory leak: str\n"), errout.str() ); + } + + + 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( std::string("[test.cpp:9]: 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( std::string(""), 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( std::string(""), errout.str() ); + } + + + void ifelse6() + { + check( "static char *f()\n" + "{\n" + " char *s = new char[100];\n" + " if ( a == b )\n" + " {\n" + " return s;\n" + " }\n" + " return NULL;\n" + "}\n" ); + ASSERT_EQUALS( std::string("[test.cpp:8]: Memory leak: s\n"), errout.str() ); + } + + + void ifelse7() + { + check( "static char *f()\n" + "{\n" + " char *s;\n" + " if ( abc )\n" + " {\n" + " s = new char[10];\n" + " }\n" + " return s;\n" + "}\n" ); + ASSERT_EQUALS( std::string(""), errout.str() ); + } + + + void ifelse8() + { + check( "static char *f()\n" + "{\n" + " char *s = new char[10];\n" + " 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 ) + + diff --git a/tests.cpp b/tests.cpp index 4f8da6e2c..7eeaf6869 100644 --- a/tests.cpp +++ b/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() { - // 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" ); - - -