diff --git a/Makefile b/Makefile index 31c448b8d..d27bc1f7e 100644 --- a/Makefile +++ b/Makefile @@ -183,6 +183,7 @@ TESTOBJ = test/options.o \ test/testpostfixoperator.o \ test/testpreprocessor.o \ test/testrunner.o \ + test/testsamples.o \ test/testsimplifytokens.o \ test/testsizeof.o \ test/teststl.o \ @@ -485,6 +486,9 @@ test/testpreprocessor.o: test/testpreprocessor.cpp lib/cxx11emu.h test/testsuite test/testrunner.o: test/testrunner.cpp lib/cxx11emu.h test/testsuite.h lib/errorlogger.h lib/config.h lib/suppressions.h test/redirect.h lib/library.h lib/path.h lib/mathlib.h test/options.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CFG) $(CXXFLAGS) -std=c++0x -c -o test/testrunner.o test/testrunner.cpp +test/testsamples.o: test/testsamples.cpp lib/cxx11emu.h test/testsuite.h lib/errorlogger.h lib/config.h lib/suppressions.h test/redirect.h lib/library.h lib/path.h lib/mathlib.h + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CFG) $(CXXFLAGS) -std=c++0x -c -o test/testsamples.o test/testsamples.cpp + test/testsimplifytokens.o: test/testsimplifytokens.cpp lib/cxx11emu.h test/testsuite.h lib/errorlogger.h lib/config.h lib/suppressions.h test/redirect.h lib/library.h lib/path.h lib/mathlib.h lib/tokenize.h lib/tokenlist.h lib/token.h lib/valueflow.h lib/settings.h lib/standards.h lib/timer.h lib/templatesimplifier.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CFG) $(CXXFLAGS) -std=c++0x -c -o test/testsimplifytokens.o test/testsimplifytokens.cpp diff --git a/samples/AssignmentAddressToInteger/out.txt b/samples/AssignmentAddressToInteger/out.txt new file mode 100644 index 000000000..aa9b1b0a5 --- /dev/null +++ b/samples/AssignmentAddressToInteger/out.txt @@ -0,0 +1 @@ +[samples\AssignmentAddressToInteger\bad.c:3]: (portability) Assigning a pointer to an integer is not portable. diff --git a/samples/arrayIndexOutOfBounds/out.txt b/samples/arrayIndexOutOfBounds/out.txt new file mode 100644 index 000000000..f05a3337a --- /dev/null +++ b/samples/arrayIndexOutOfBounds/out.txt @@ -0,0 +1 @@ +[samples\arrayIndexOutOfBounds\bad.c:6]: (error) Array 'a[2]' accessed at index 2, which is out of bounds. diff --git a/samples/autoVariables/out.txt b/samples/autoVariables/out.txt new file mode 100644 index 000000000..a5f001b2f --- /dev/null +++ b/samples/autoVariables/out.txt @@ -0,0 +1 @@ +[samples\autoVariables\bad.c:4]: (error) Address of local auto-variable assigned to a function parameter. diff --git a/samples/bufferAccessOutOfBounds/out.txt b/samples/bufferAccessOutOfBounds/out.txt new file mode 100644 index 000000000..c87463277 --- /dev/null +++ b/samples/bufferAccessOutOfBounds/out.txt @@ -0,0 +1,2 @@ +[samples\bufferAccessOutOfBounds\bad.c:6]: (error) Buffer is accessed out of bounds: a +[samples\bufferAccessOutOfBounds\bad.c:6]: (error) Array 'a[2]' accessed at index 2, which is out of bounds. diff --git a/samples/erase/out.txt b/samples/erase/out.txt new file mode 100644 index 000000000..d89d1f8ab --- /dev/null +++ b/samples/erase/out.txt @@ -0,0 +1 @@ +[samples\erase\bad.cpp:9] -> [samples\erase\bad.cpp:11]: (error) Iterator 'iter' used after element has been erased. diff --git a/samples/memleak/out.txt b/samples/memleak/out.txt new file mode 100644 index 000000000..7fd408c2f --- /dev/null +++ b/samples/memleak/out.txt @@ -0,0 +1 @@ +[samples\memleak\bad.c:8]: (error) Memory leak: a diff --git a/samples/outOfBounds/out.txt b/samples/outOfBounds/out.txt new file mode 100644 index 000000000..da289e4a1 --- /dev/null +++ b/samples/outOfBounds/out.txt @@ -0,0 +1 @@ +[samples\outOfBounds\bad.c:5]: (error) snprintf size is out of bounds: Supplied size 10 is larger than actual size 5. diff --git a/samples/resourceLeak/out.txt b/samples/resourceLeak/out.txt new file mode 100644 index 000000000..2efee2b22 --- /dev/null +++ b/samples/resourceLeak/out.txt @@ -0,0 +1 @@ +[samples\resourceLeak\bad.c:8]: (error) Resource leak: a diff --git a/samples/syntaxError/out.txt b/samples/syntaxError/out.txt new file mode 100644 index 000000000..5689c3a20 --- /dev/null +++ b/samples/syntaxError/out.txt @@ -0,0 +1 @@ +[samples\syntaxError\bad.c:2]: (error) Invalid number of character ({) when these macros are defined: 'A'. diff --git a/test/redirect.h b/test/redirect.h index bfe240f9d..b7ee4f386 100644 --- a/test/redirect.h +++ b/test/redirect.h @@ -61,6 +61,17 @@ public: _out.str(""); } + /** Return what would be printed to cerr. See also clearErrout() */ + std::string getErrout() const { + return _err.str(); + } + + /** Normally called after getErrout() to prevent same text to be returned + twice. */ + void clearErrout() { + _err.str(""); + } + private: std::ostringstream _out; std::ostringstream _err; @@ -71,5 +82,7 @@ private: #define REDIRECT RedirectOutputError redir; #define GET_REDIRECT_OUTPUT redir.getOutput() #define CLEAR_REDIRECT_OUTPUT redir.clearOutput() +#define GET_REDIRECT_ERROUT redir.getErrout() +#define CLEAR_REDIRECT_ERROUT redir.clearErrout() #endif diff --git a/test/testcppcheck.cpp b/test/testcppcheck.cpp index 4d6c0e8a4..cfe227bea 100644 --- a/test/testcppcheck.cpp +++ b/test/testcppcheck.cpp @@ -17,10 +17,6 @@ */ -// The preprocessor that Cppcheck uses is a bit special. Instead of generating -// the code for a known configuration, it generates the code for each configuration. - - #include "cppcheck.h" #include "cppcheckexecutor.h" #include "testsuite.h" diff --git a/test/testrunner.vcxproj b/test/testrunner.vcxproj index 6952a4844..57b75ed74 100644 --- a/test/testrunner.vcxproj +++ b/test/testrunner.vcxproj @@ -63,6 +63,7 @@ + diff --git a/test/testrunner.vcxproj.filters b/test/testrunner.vcxproj.filters index f9357f425..a7a1a5f9c 100644 --- a/test/testrunner.vcxproj.filters +++ b/test/testrunner.vcxproj.filters @@ -181,6 +181,9 @@ Source Files + + Source Files + diff --git a/test/testsamples.cpp b/test/testsamples.cpp new file mode 100644 index 000000000..21dc851b5 --- /dev/null +++ b/test/testsamples.cpp @@ -0,0 +1,83 @@ +/* +* Cppcheck - A tool for static C/C++ code analysis +* Copyright (C) 2007-2014 Daniel Marjamäki and Cppcheck team. +* +* 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 3 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, see . +*/ + + +#include "filelister.h" +#include "testsuite.h" +#include "cppcheckexecutor.h" +#include +#include +#include + + +class TestSamples : public TestFixture { +public: + TestSamples() : TestFixture("TestSamples") { + } + +private: + + void run() { + TEST_CASE(runSamples); + } + + void runSamples() const { + REDIRECT; + + std::map files; +#ifdef _WIN32 + FileLister::recursiveAddFiles(files, "..\\samples"); +#else + FileLister::recursiveAddFiles(files, "samples"); +#endif + for (std::map::const_iterator i = files.begin(); i != files.end(); ++i) { + CLEAR_REDIRECT_ERROUT; + char* path = new char[i->first.size() + 1]; + strcpy(path, i->first.c_str()); + const char* argv[] = { +#ifdef _WIN32 + ".\\..\\testrunner", +#else + "./testrunner", +#endif + "--enable=style,warning,performance,portability", "--inconclusive", "-rp", "-f", "-q", path + }; + std::string filename = i->first.substr(i->first.find_last_of("/\\")+1); + if (filename == "good.cpp" || filename == "good.c") { + CppCheckExecutor exec; + exec.check(7, argv); + ASSERT_EQUALS_MSG("", GET_REDIRECT_ERROUT, i->first); + } else if (filename == "bad.cpp" || filename == "bad.c") { + CppCheckExecutor exec; + exec.check(7, argv); + std::string expected_filename = Path::getPathFromFilename(i->first) + "out.txt"; + std::ifstream ifs(expected_filename.c_str()); + std::string expected((std::istreambuf_iterator(ifs)), std::istreambuf_iterator()); + std::string actual = GET_REDIRECT_ERROUT; + // We need some uniformization to make this work on Unix and Windows + std::replace(actual.begin(), actual.end(), '/', '\\'); // Uniformize slashes. + while (actual.find("..\\") != std::string::npos) + actual.erase(actual.find("..\\"), 3); // Remove '..\' + ASSERT_EQUALS_MSG(expected, actual, i->first); + } + delete[] path; + } + } +}; + +REGISTER_TEST(TestSamples) diff --git a/test/testthreadexecutor.cpp b/test/testthreadexecutor.cpp index 518a12c08..4c8ef6c43 100644 --- a/test/testthreadexecutor.cpp +++ b/test/testthreadexecutor.cpp @@ -17,10 +17,6 @@ */ -// The preprocessor that Cppcheck uses is a bit special. Instead of generating -// the code for a known configuration, it generates the code for each configuration. - - #include "cppcheck.h" #include "testsuite.h" #include "threadexecutor.h"