diff --git a/Makefile b/Makefile
index 5a0db2b18..0e2f27822 100644
--- a/Makefile
+++ b/Makefile
@@ -105,6 +105,7 @@ TESTOBJ = test/options.o \
test/testsimplifytokens.o \
test/teststl.o \
test/testsuite.o \
+ test/testsuppressions.o \
test/testsymboldatabase.o \
test/testthreadexecutor.o \
test/testtoken.o \
@@ -333,6 +334,9 @@ test/teststl.o: test/teststl.cpp lib/tokenize.h lib/checkstl.h lib/check.h lib/t
test/testsuite.o: test/testsuite.cpp test/testsuite.h lib/errorlogger.h lib/settings.h test/redirect.h test/options.h
$(CXX) $(CPPFLAGS) $(CXXFLAGS) ${INCLUDE_FOR_TEST} -c -o test/testsuite.o test/testsuite.cpp
+test/testsuppressions.o: test/testsuppressions.cpp lib/cppcheck.h lib/settings.h lib/errorlogger.h lib/checkunusedfunctions.h lib/check.h lib/token.h lib/tokenize.h test/testsuite.h test/redirect.h
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) ${INCLUDE_FOR_TEST} -c -o test/testsuppressions.o test/testsuppressions.cpp
+
test/testsymboldatabase.o: test/testsymboldatabase.cpp test/testsuite.h lib/errorlogger.h lib/settings.h test/redirect.h test/testutils.h lib/tokenize.h lib/token.h lib/symboldatabase.h
$(CXX) $(CPPFLAGS) $(CXXFLAGS) ${INCLUDE_FOR_TEST} -c -o test/testsymboldatabase.o test/testsymboldatabase.cpp
diff --git a/test/test.pro b/test/test.pro
index 504da8341..b9f38e02f 100644
--- a/test/test.pro
+++ b/test/test.pro
@@ -59,6 +59,7 @@ SOURCES += options.cpp \
testsimplifytokens.cpp \
teststl.cpp \
testsuite.cpp \
+ testsuppressions.cpp \
testsymboldatabase.cpp \
testthreadexecutor.cpp \
testtoken.cpp \
diff --git a/test/testsuppressions.cpp b/test/testsuppressions.cpp
new file mode 100644
index 000000000..2570321db
--- /dev/null
+++ b/test/testsuppressions.cpp
@@ -0,0 +1,262 @@
+/*
+ * Cppcheck - A tool for static C/C++ code analysis
+ * Copyright (C) 2007-2011 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 "cppcheck.h"
+#include "settings.h"
+#include "testsuite.h"
+#include "cppcheckexecutor.h"
+#include "threadexecutor.h"
+
+#include
+
+extern std::ostringstream errout;
+
+class TestSuppressions : public TestFixture
+{
+public:
+ TestSuppressions() : TestFixture("TestSuppressions")
+ { }
+
+private:
+
+ void run()
+ {
+ TEST_CASE(suppressionsSettings);
+ TEST_CASE(suppressionsMultiFile);
+ }
+
+ // Check the suppression
+ void checkSuppression(const char code[], const std::string &suppression = "")
+ {
+ // Clear the error log
+ errout.str("");
+
+ Settings settings;
+ settings._inlineSuppressions = true;
+ if (!suppression.empty())
+ {
+ std::string r = settings.nomsg.addSuppressionLine(suppression);
+ ASSERT_EQUALS("", r);
+ }
+
+ CppCheck cppCheck(*this, true);
+ cppCheck.settings(settings);
+ cppCheck.check("test.cpp", code);
+
+ reportUnmatchedSuppressions(cppCheck.settings().nomsg.getUnmatchedGlobalSuppressions());
+ }
+
+ void checkSuppressionThreads(const char code[], const std::string &suppression = "")
+ {
+ errout.str("");
+ output.str("");
+ if (!ThreadExecutor::isEnabled())
+ {
+ // Skip this check on systems which don't use this feature
+ return;
+ }
+
+ std::vector filenames;
+ std::map filesizes;
+ filenames.push_back("test.cpp");
+
+ Settings settings;
+ settings._jobs = 1;
+ settings._inlineSuppressions = true;
+ if (!suppression.empty())
+ {
+ std::string r = settings.nomsg.addSuppressionLine(suppression);
+ ASSERT_EQUALS("", r);
+ }
+ ThreadExecutor executor(filenames, filesizes, settings, *this);
+ for (unsigned int i = 0; i < filenames.size(); ++i)
+ executor.addFileContent(filenames[i], code);
+
+ executor.check();
+
+ reportUnmatchedSuppressions(settings.nomsg.getUnmatchedGlobalSuppressions());
+ }
+
+ // Check the suppression for multiple files
+ void checkSuppression(const char *names[], const char *codes[], const std::string &suppression = "")
+ {
+ // Clear the error log
+ errout.str("");
+
+ Settings settings;
+ settings._inlineSuppressions = true;
+ if (!suppression.empty())
+ settings.nomsg.addSuppressionLine(suppression);
+
+ CppCheck cppCheck(*this, true);
+ cppCheck.settings(settings);
+ for (int i = 0; names[i] != NULL; ++i)
+ cppCheck.check(names[i], codes[i]);
+
+ reportUnmatchedSuppressions(cppCheck.settings().nomsg.getUnmatchedGlobalSuppressions());
+ }
+
+ void runChecks(void (TestSuppressions::*check)(const char[], const std::string &))
+ {
+ // check to make sure the appropriate error is present
+ (this->*check)("void f() {\n"
+ " int a;\n"
+ " a++;\n"
+ "}\n",
+ "");
+ ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: a\n", errout.str());
+
+ // suppress uninitvar globally
+ (this->*check)("void f() {\n"
+ " int a;\n"
+ " a++;\n"
+ "}\n",
+ "uninitvar");
+ ASSERT_EQUALS("", errout.str());
+
+ // suppress uninitvar globally, without error present
+ (this->*check)("void f() {\n"
+ " int a;\n"
+ " b++;\n"
+ "}\n",
+ "uninitvar");
+ ASSERT_EQUALS("[*]: (information) Unmatched suppression: uninitvar\n", errout.str());
+
+ // suppress uninitvar for this file only
+ (this->*check)("void f() {\n"
+ " int a;\n"
+ " a++;\n"
+ "}\n",
+ "uninitvar:test.cpp");
+ ASSERT_EQUALS("", errout.str());
+
+ // suppress uninitvar for this file only, without error present
+ (this->*check)("void f() {\n"
+ " int a;\n"
+ " b++;\n"
+ "}\n",
+ "uninitvar:test.cpp");
+ ASSERT_EQUALS("[test.cpp]: (information) Unmatched suppression: uninitvar\n", errout.str());
+
+ // suppress all for this file only
+ (this->*check)("void f() {\n"
+ " int a;\n"
+ " a++;\n"
+ "}\n",
+ "*:test.cpp");
+ ASSERT_EQUALS("", errout.str());
+
+ // suppress all for this file only, without error present
+ (this->*check)("void f() {\n"
+ " int a;\n"
+ " b++;\n"
+ "}\n",
+ "*:test.cpp");
+ ASSERT_EQUALS("[test.cpp]: (information) Unmatched suppression: *\n", errout.str());
+
+ // suppress uninitvar for this file and line
+ (this->*check)("void f() {\n"
+ " int a;\n"
+ " a++;\n"
+ "}\n",
+ "uninitvar:test.cpp:3");
+ ASSERT_EQUALS("", errout.str());
+
+ // suppress uninitvar for this file and line, without error present
+ (this->*check)("void f() {\n"
+ " int a;\n"
+ " b++;\n"
+ "}\n",
+ "uninitvar:test.cpp:3");
+ ASSERT_EQUALS("[test.cpp:3]: (information) Unmatched suppression: uninitvar\n", errout.str());
+
+ // suppress uninitvar inline
+ (this->*check)("void f() {\n"
+ " int a;\n"
+ " // cppcheck-suppress uninitvar\n"
+ " a++;\n"
+ "}\n",
+ "");
+ ASSERT_EQUALS("", errout.str());
+
+ // suppress uninitvar inline
+ (this->*check)("void f() {\n"
+ " int a;\n"
+ " // cppcheck-suppress uninitvar\n"
+ "\n"
+ " a++;\n"
+ "}\n",
+ "");
+ ASSERT_EQUALS("", errout.str());
+
+ // suppress uninitvar inline
+ (this->*check)("void f() {\n"
+ " int a;\n"
+ " /* cppcheck-suppress uninitvar */\n"
+ " a++;\n"
+ "}\n",
+ "");
+ ASSERT_EQUALS("", errout.str());
+
+ // suppress uninitvar inline
+ (this->*check)("void f() {\n"
+ " int a;\n"
+ " /* cppcheck-suppress uninitvar */\n"
+ "\n"
+ " a++;\n"
+ "}\n",
+ "");
+ ASSERT_EQUALS("", errout.str());
+
+ // suppress uninitvar inline, without error present
+ (this->*check)("void f() {\n"
+ " int a;\n"
+ " // cppcheck-suppress uninitvar\n"
+ " b++;\n"
+ "}\n",
+ "");
+ ASSERT_EQUALS("[test.cpp:4]: (information) Unmatched suppression: uninitvar\n", errout.str());
+ }
+
+ void suppressionsSettings()
+ {
+ runChecks(&TestSuppressions::checkSuppression);
+ runChecks(&TestSuppressions::checkSuppressionThreads);
+ }
+
+ void suppressionsMultiFile()
+ {
+ const char *names[] = {"abc.cpp", "xyz.cpp", NULL};
+ const char *codes[] =
+ {
+ "void f() {\n"
+ "}\n",
+ "void f() {\n"
+ " int a;\n"
+ " a++;\n"
+ "}\n",
+ };
+
+ // suppress uninitvar for this file and line
+ checkSuppression(names, codes, "uninitvar:xyz.cpp:3");
+ ASSERT_EQUALS("", errout.str());
+ }
+
+};
+
+REGISTER_TEST(TestSuppressions)