LCOV - code coverage report
Current view: top level - test - testsuppressions.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 734 734 100.0 %
Date: 2024-04-28 12:00:40 Functions: 70 70 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Cppcheck - A tool for static C/C++ code analysis
       3             :  * Copyright (C) 2007-2024 Cppcheck team.
       4             :  *
       5             :  * This program is free software: you can redistribute it and/or modify
       6             :  * it under the terms of the GNU General Public License as published by
       7             :  * the Free Software Foundation, either version 3 of the License, or
       8             :  * (at your option) any later version.
       9             :  *
      10             :  * This program is distributed in the hope that it will be useful,
      11             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      12             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13             :  * GNU General Public License for more details.
      14             :  *
      15             :  * You should have received a copy of the GNU General Public License
      16             :  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
      17             :  */
      18             : 
      19             : #include "config.h"
      20             : #include "cppcheck.h"
      21             : #include "cppcheckexecutor.h"
      22             : #include "errortypes.h"
      23             : #include "filesettings.h"
      24             : #include "processexecutor.h"
      25             : #include "settings.h"
      26             : #include "suppressions.h"
      27             : #include "fixture.h"
      28             : #include "helpers.h"
      29             : #include "threadexecutor.h"
      30             : #include "singleexecutor.h"
      31             : 
      32             : #include <cstddef>
      33             : #include <cstring>
      34             : #include <list>
      35             : #include <map>
      36             : #include <memory>
      37             : #include <sstream>
      38             : #include <string>
      39             : #include <utility>
      40             : #include <vector>
      41             : 
      42             : class TestSuppressions : public TestFixture {
      43             : public:
      44           1 :     TestSuppressions() : TestFixture("TestSuppressions") {}
      45             : 
      46             : private:
      47             : 
      48           1 :     void run() override {
      49           1 :         TEST_CASE(suppressionsBadId1);
      50           1 :         TEST_CASE(suppressionsDosFormat);     // Ticket #1836
      51           1 :         TEST_CASE(suppressionsFileNameWithColon);    // Ticket #1919 - filename includes colon
      52           1 :         TEST_CASE(suppressionsGlob);
      53           1 :         TEST_CASE(suppressionsGlobId);
      54           1 :         TEST_CASE(suppressionsFileNameWithExtraPath);
      55           1 :         TEST_CASE(suppressionsSettingsFiles);
      56           1 :         TEST_CASE(suppressionsSettingsFS);
      57           1 :         TEST_CASE(suppressionsSettingsThreadsFiles);
      58           1 :         TEST_CASE(suppressionsSettingsThreadsFS);
      59             : #if !defined(WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
      60           1 :         TEST_CASE(suppressionsSettingsProcessesFiles);
      61           1 :         TEST_CASE(suppressionsSettingsProcessesFS);
      62             : #endif
      63           1 :         TEST_CASE(suppressionsMultiFileFiles);
      64           1 :         TEST_CASE(suppressionsMultiFileFS);
      65           1 :         TEST_CASE(suppressionsPathSeparator);
      66           1 :         TEST_CASE(suppressionsLine0);
      67           1 :         TEST_CASE(suppressionsFileComment);
      68             : 
      69           1 :         TEST_CASE(inlinesuppress);
      70           1 :         TEST_CASE(inlinesuppress_symbolname_Files);
      71           1 :         TEST_CASE(inlinesuppress_symbolname_FS);
      72           1 :         TEST_CASE(inlinesuppress_comment);
      73             : 
      74           1 :         TEST_CASE(multi_inlinesuppress);
      75           1 :         TEST_CASE(multi_inlinesuppress_comment);
      76             : 
      77           1 :         TEST_CASE(globalSuppressions); // Testing that global suppressions work (#8515)
      78             : 
      79           1 :         TEST_CASE(inlinesuppress_unusedFunction); // #4210 - unusedFunction
      80           1 :         TEST_CASE(globalsuppress_unusedFunction); // #4946
      81           1 :         TEST_CASE(suppressionWithRelativePaths); // #4733
      82           1 :         TEST_CASE(suppressingSyntaxErrorsFiles); // #7076
      83           1 :         TEST_CASE(suppressingSyntaxErrorsFS); // #7076
      84           1 :         TEST_CASE(suppressingSyntaxErrorsInlineFiles); // #5917
      85           1 :         TEST_CASE(suppressingSyntaxErrorsInlineFS); // #5917
      86           1 :         TEST_CASE(suppressingSyntaxErrorsWhileFileReadFiles); // PR #1333
      87           1 :         TEST_CASE(suppressingSyntaxErrorsWhileFileReadFS); // PR #1333
      88           1 :         TEST_CASE(symbol);
      89             : 
      90           1 :         TEST_CASE(unusedFunctionFiles);
      91           1 :         TEST_CASE(unusedFunctionFS);
      92             : 
      93           1 :         TEST_CASE(suppressingSyntaxErrorAndExitCodeFiles);
      94           1 :         TEST_CASE(suppressingSyntaxErrorAndExitCodeFS);
      95           1 :         TEST_CASE(suppressingSyntaxErrorAndExitCodeMultiFileFiles);
      96           1 :         TEST_CASE(suppressingSyntaxErrorAndExitCodeMultiFileFS);
      97           1 :         TEST_CASE(suppressLocal);
      98             : 
      99           1 :         TEST_CASE(suppressUnmatchedSuppressions);
     100             : 
     101           1 :         TEST_CASE(suppressionsParseXmlFile);
     102           1 :     }
     103             : 
     104           1 :     void suppressionsBadId1() const {
     105           1 :         SuppressionList suppressions;
     106           2 :         std::istringstream s1("123");
     107           1 :         ASSERT_EQUALS("Failed to add suppression. Invalid id \"123\"", suppressions.parseFile(s1));
     108             : 
     109           2 :         std::istringstream s2("obsoleteFunctionsrand_r");
     110           1 :         ASSERT_EQUALS("", suppressions.parseFile(s2));
     111             :     }
     112             : 
     113           2 :     static SuppressionList::ErrorMessage errorMessage(const std::string &errorId) {
     114           2 :         SuppressionList::ErrorMessage ret;
     115           2 :         ret.errorId = errorId;
     116           2 :         ret.hash = 0;
     117           2 :         ret.lineNumber = 0;
     118           2 :         ret.certainty = Certainty::normal;
     119           2 :         return ret;
     120             :     }
     121             : 
     122          35 :     static SuppressionList::ErrorMessage errorMessage(const std::string &errorId, const std::string &file, int line) {
     123          35 :         SuppressionList::ErrorMessage ret;
     124          35 :         ret.errorId = errorId;
     125          35 :         ret.setFileName(file);
     126          35 :         ret.lineNumber = line;
     127          35 :         return ret;
     128             :     }
     129             : 
     130           1 :     void suppressionsDosFormat() const {
     131           1 :         SuppressionList suppressions;
     132             :         std::istringstream s("abc\r\n"
     133           2 :                              "def\r\n");
     134           1 :         ASSERT_EQUALS("", suppressions.parseFile(s));
     135           1 :         ASSERT_EQUALS(true, suppressions.isSuppressed(errorMessage("abc")));
     136           1 :         ASSERT_EQUALS(true, suppressions.isSuppressed(errorMessage("def")));
     137             :     }
     138             : 
     139           1 :     void suppressionsFileNameWithColon() const {
     140           1 :         SuppressionList suppressions;
     141             :         std::istringstream s("errorid:c:\\foo.cpp\n"
     142           2 :                              "errorid:c:\\bar.cpp:12");
     143           1 :         ASSERT_EQUALS("", suppressions.parseFile(s));
     144           1 :         ASSERT_EQUALS(true, suppressions.isSuppressed(errorMessage("errorid", "c:/foo.cpp", 1111)));
     145           1 :         ASSERT_EQUALS(false, suppressions.isSuppressed(errorMessage("errorid", "c:/bar.cpp", 10)));
     146           1 :         ASSERT_EQUALS(true, suppressions.isSuppressed(errorMessage("errorid", "c:/bar.cpp", 12)));
     147             :     }
     148             : 
     149           1 :     void suppressionsGlob() const {
     150             :         // Check for syntax errors in glob
     151             :         {
     152           1 :             SuppressionList suppressions;
     153           2 :             std::istringstream s("errorid:**.cpp\n");
     154           1 :             ASSERT_EQUALS("Failed to add suppression. Invalid glob pattern '**.cpp'.", suppressions.parseFile(s));
     155             :         }
     156             : 
     157             :         // Check that globbing works
     158             :         {
     159           1 :             SuppressionList suppressions;
     160             :             std::istringstream s("errorid:x*.cpp\n"
     161             :                                  "errorid:y?.cpp\n"
     162           2 :                                  "errorid:test.c*");
     163           1 :             ASSERT_EQUALS("", suppressions.parseFile(s));
     164           1 :             ASSERT_EQUALS(true, suppressions.isSuppressed(errorMessage("errorid", "xyz.cpp", 1)));
     165           1 :             ASSERT_EQUALS(true, suppressions.isSuppressed(errorMessage("errorid", "xyz.cpp.cpp", 1)));
     166           1 :             ASSERT_EQUALS(false, suppressions.isSuppressed(errorMessage("errorid", "abc.cpp", 1)));
     167           1 :             ASSERT_EQUALS(true, suppressions.isSuppressed(errorMessage("errorid", "ya.cpp", 1)));
     168           1 :             ASSERT_EQUALS(false, suppressions.isSuppressed(errorMessage("errorid", "y.cpp", 1)));
     169           1 :             ASSERT_EQUALS(true, suppressions.isSuppressed(errorMessage("errorid", "test.c", 1)));
     170           1 :             ASSERT_EQUALS(true, suppressions.isSuppressed(errorMessage("errorid", "test.cpp", 1)));
     171             :         }
     172             : 
     173             :         // Check that both a filename match and a glob match apply
     174             :         {
     175           1 :             SuppressionList suppressions;
     176             :             std::istringstream s("errorid:x*.cpp\n"
     177             :                                  "errorid:xyz.cpp:1\n"
     178             :                                  "errorid:a*.cpp:1\n"
     179           2 :                                  "errorid:abc.cpp:2");
     180           1 :             ASSERT_EQUALS("", suppressions.parseFile(s));
     181           1 :             ASSERT_EQUALS(true, suppressions.isSuppressed(errorMessage("errorid", "xyz.cpp", 1)));
     182           1 :             ASSERT_EQUALS(true, suppressions.isSuppressed(errorMessage("errorid", "xyz.cpp", 2)));
     183           1 :             ASSERT_EQUALS(true, suppressions.isSuppressed(errorMessage("errorid", "abc.cpp", 1)));
     184           1 :             ASSERT_EQUALS(true, suppressions.isSuppressed(errorMessage("errorid", "abc.cpp", 2)));
     185             :         }
     186             :     }
     187             : 
     188           1 :     void suppressionsGlobId() const {
     189           1 :         SuppressionList suppressions;
     190           2 :         std::istringstream s("a*\n");
     191           1 :         ASSERT_EQUALS("", suppressions.parseFile(s));
     192           1 :         ASSERT_EQUALS(true, suppressions.isSuppressed(errorMessage("abc", "xyz.cpp", 1)));
     193           1 :         ASSERT_EQUALS(false, suppressions.isSuppressed(errorMessage("def", "xyz.cpp", 1)));
     194             :     }
     195             : 
     196           1 :     void suppressionsFileNameWithExtraPath() const {
     197             :         // Ticket #2797
     198           1 :         SuppressionList suppressions;
     199           1 :         ASSERT_EQUALS("", suppressions.addSuppressionLine("errorid:./a.c:123"));
     200           1 :         ASSERT_EQUALS(true, suppressions.isSuppressed(errorMessage("errorid", "a.c", 123)));
     201           1 :         ASSERT_EQUALS(true, suppressions.isSuppressed(errorMessage("errorid", "x/../a.c", 123)));
     202             :     }
     203             : 
     204          63 :     unsigned int checkSuppressionFiles(const char code[], const std::string &suppression = emptyString) {
     205          63 :         return _checkSuppression(code, false, suppression);
     206             :     }
     207             : 
     208           4 :     unsigned int checkSuppressionFS(const char code[], const std::string &suppression = emptyString) {
     209           4 :         return _checkSuppression(code, true, suppression);
     210             :     }
     211             : 
     212             :     // Check the suppression
     213          67 :     unsigned int _checkSuppression(const char code[], bool useFS, const std::string &suppression = emptyString) {
     214         134 :         std::map<std::string, std::string> files;
     215          67 :         files["test.cpp"] = code;
     216             : 
     217         134 :         return _checkSuppression(files, useFS, suppression);
     218             :     }
     219             : 
     220           2 :     unsigned int checkSuppressionFiles(std::map<std::string, std::string> &f, const std::string &suppression = emptyString) {
     221           2 :         return _checkSuppression(f, false, suppression);
     222             :     }
     223             : 
     224           1 :     unsigned int checkSuppressionFS(std::map<std::string, std::string> &f, const std::string &suppression = emptyString) {
     225           1 :         return _checkSuppression(f, true, suppression);
     226             :     }
     227             : 
     228             :     // Check the suppression for multiple files
     229          70 :     unsigned int _checkSuppression(std::map<std::string, std::string> &f, bool useFS, const std::string &suppression = emptyString) {
     230         140 :         std::list<FileSettings> fileSettings;
     231             : 
     232         140 :         std::list<FileWithDetails> filelist;
     233         143 :         for (std::map<std::string, std::string>::const_iterator i = f.cbegin(); i != f.cend(); ++i) {
     234          73 :             filelist.emplace_back(i->first, i->second.size());
     235          73 :             if (useFS) {
     236           6 :                 fileSettings.emplace_back(i->first, i->second.size());
     237             :             }
     238             :         }
     239             : 
     240         140 :         CppCheck cppCheck(*this, true, nullptr);
     241          70 :         Settings& settings = cppCheck.settings();
     242          70 :         settings.jobs = 1;
     243          70 :         settings.quiet = true;
     244          70 :         settings.inlineSuppressions = true;
     245          70 :         settings.severity.enable(Severity::information);
     246          70 :         if (suppression == "unusedFunction")
     247           2 :             settings.checks.setEnabled(Checks::unusedFunction, true);
     248          70 :         if (!suppression.empty()) {
     249          21 :             EXPECT_EQ("", settings.supprs.nomsg.addSuppressionLine(suppression));
     250             :         }
     251             : 
     252         140 :         std::vector<std::unique_ptr<ScopedFile>> scopedfiles;
     253          70 :         scopedfiles.reserve(filelist.size());
     254         143 :         for (std::map<std::string, std::string>::const_iterator i = f.cbegin(); i != f.cend(); ++i)
     255          73 :             scopedfiles.emplace_back(new ScopedFile(i->first, i->second));
     256             : 
     257             :         // clear files list so only fileSettings are used
     258          70 :         if (useFS)
     259           5 :             filelist.clear();
     260             : 
     261          70 :         SingleExecutor executor(cppCheck, filelist, fileSettings, settings, settings.supprs.nomsg, *this);
     262          70 :         const unsigned int exitCode = executor.check();
     263             : 
     264          70 :         CppCheckExecutor::reportSuppressions(settings, settings.supprs.nomsg, false, filelist, fileSettings, *this); // TODO: check result
     265             : 
     266         140 :         return exitCode;
     267             :     }
     268             : 
     269          52 :     unsigned int checkSuppressionThreadsFiles(const char code[], const std::string &suppression = emptyString) {
     270          52 :         return _checkSuppressionThreads(code, false, suppression);
     271             :     }
     272             : 
     273          52 :     unsigned int checkSuppressionThreadsFS(const char code[], const std::string &suppression = emptyString) {
     274          52 :         return _checkSuppressionThreads(code, true, suppression);
     275             :     }
     276             : 
     277         104 :     unsigned int _checkSuppressionThreads(const char code[], bool useFS, const std::string &suppression = emptyString) {
     278         208 :         std::list<FileSettings> fileSettings;
     279             : 
     280         208 :         std::list<FileWithDetails> filelist;
     281         104 :         filelist.emplace_back("test.cpp", strlen(code));
     282         104 :         if (useFS) {
     283          52 :             fileSettings.emplace_back("test.cpp", strlen(code));
     284             :         }
     285             : 
     286         312 :         /*const*/ auto settings = dinit(Settings,
     287             :                                         $.jobs = 2,
     288             :                                             $.quiet = true,
     289             :                                             $.inlineSuppressions = true);
     290         104 :         settings.severity.enable(Severity::information);
     291         104 :         if (!suppression.empty()) {
     292          18 :             EXPECT_EQ("", settings.supprs.nomsg.addSuppressionLine(suppression));
     293             :         }
     294             : 
     295         208 :         std::vector<std::unique_ptr<ScopedFile>> scopedfiles;
     296         104 :         scopedfiles.reserve(filelist.size());
     297         208 :         for (std::list<FileWithDetails>::const_iterator i = filelist.cbegin(); i != filelist.cend(); ++i)
     298         104 :             scopedfiles.emplace_back(new ScopedFile(i->path(), code));
     299             : 
     300             :         // clear files list so only fileSettings are used
     301         104 :         if (useFS)
     302          52 :             filelist.clear();
     303             : 
     304         104 :         ThreadExecutor executor(filelist, fileSettings, settings, settings.supprs.nomsg, *this, CppCheckExecutor::executeCommand);
     305         104 :         const unsigned int exitCode = executor.check();
     306             : 
     307         104 :         CppCheckExecutor::reportSuppressions(settings, settings.supprs.nomsg, false, filelist, fileSettings, *this); // TODO: check result
     308             : 
     309         208 :         return exitCode;
     310             :     }
     311             : 
     312             : #if !defined(WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
     313          52 :     unsigned int checkSuppressionProcessesFiles(const char code[], const std::string &suppression = emptyString) {
     314          52 :         return _checkSuppressionProcesses(code, false, suppression);
     315             :     }
     316             : 
     317          52 :     unsigned int checkSuppressionProcessesFS(const char code[], const std::string &suppression = emptyString) {
     318          52 :         return _checkSuppressionProcesses(code, true, suppression);
     319             :     }
     320             : 
     321         104 :     unsigned int _checkSuppressionProcesses(const char code[], bool useFS, const std::string &suppression = emptyString) {
     322         208 :         std::list<FileSettings> fileSettings;
     323             : 
     324         208 :         std::list<FileWithDetails> filelist;
     325         104 :         filelist.emplace_back("test.cpp", strlen(code));
     326         104 :         if (useFS) {
     327          52 :             fileSettings.emplace_back("test.cpp", strlen(code));
     328             :         }
     329             : 
     330         312 :         /*const*/ auto settings = dinit(Settings,
     331             :                                         $.jobs = 2,
     332             :                                             $.quiet = true,
     333             :                                             $.inlineSuppressions = true);
     334         104 :         settings.severity.enable(Severity::information);
     335         104 :         if (!suppression.empty()) {
     336          18 :             EXPECT_EQ("", settings.supprs.nomsg.addSuppressionLine(suppression));
     337             :         }
     338             : 
     339         208 :         std::vector<std::unique_ptr<ScopedFile>> scopedfiles;
     340         104 :         scopedfiles.reserve(filelist.size());
     341         208 :         for (std::list<FileWithDetails>::const_iterator i = filelist.cbegin(); i != filelist.cend(); ++i)
     342         104 :             scopedfiles.emplace_back(new ScopedFile(i->path(), code));
     343             : 
     344             :         // clear files list so only fileSettings are used
     345         104 :         if (useFS)
     346          52 :             filelist.clear();
     347             : 
     348         104 :         ProcessExecutor executor(filelist, fileSettings, settings, settings.supprs.nomsg, *this, CppCheckExecutor::executeCommand);
     349         104 :         const unsigned int exitCode = executor.check();
     350             : 
     351         104 :         CppCheckExecutor::reportSuppressions(settings, settings.supprs.nomsg, false, filelist, fileSettings, *this); // TODO: check result
     352             : 
     353         208 :         return exitCode;
     354             :     }
     355             : #endif
     356             : 
     357           5 :     void runChecks(unsigned int (TestSuppressions::*check)(const char[], const std::string &)) {
     358             :         // check to make sure the appropriate errors are present
     359           5 :         ASSERT_EQUALS(1, (this->*check)("void f() {\n"
     360             :                                         "    int a;\n"
     361             :                                         "    a++;\n"
     362             :                                         "}\n",
     363             :                                         ""));
     364           5 :         ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: a\n", errout_str());
     365             : 
     366           5 :         ASSERT_EQUALS(1, (this->*check)("void f() {\n"
     367             :                                         "    int a;\n"
     368             :                                         "    a++;\n"
     369             :                                         "    int b;\n"
     370             :                                         "    b++;\n"
     371             :                                         "}\n",
     372             :                                         ""));
     373           5 :         ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: a\n"
     374             :                       "[test.cpp:5]: (error) Uninitialized variable: b\n", errout_str());
     375             : 
     376             :         // suppress uninitvar globally
     377           5 :         ASSERT_EQUALS(0, (this->*check)("void f() {\n"
     378             :                                         "    int a;\n"
     379             :                                         "    a++;\n"
     380             :                                         "}\n",
     381             :                                         "uninitvar"));
     382           5 :         ASSERT_EQUALS("", errout_str());
     383             : 
     384           5 :         (this->*check)("void f() {\n"
     385             :                        "    // cppcheck-suppress-file uninitvar\n"
     386             :                        "    int a;\n"
     387             :                        "    a++;\n"
     388             :                        "}\n",
     389          10 :                        "");
     390           5 :         ASSERT_EQUALS("[test.cpp:2]: (error) File suppression should be at the top of the file\n"
     391             :                       "[test.cpp:4]: (error) Uninitialized variable: a\n", errout_str());
     392             : 
     393           5 :         (this->*check)("void f() {\n"
     394             :                        "    int a;\n"
     395             :                        "    a++;\n"
     396             :                        "}\n"
     397             :                        "// cppcheck-suppress-file uninitvar\n",
     398          10 :                        "");
     399           5 :         ASSERT_EQUALS("[test.cpp:5]: (error) File suppression should be at the top of the file\n"
     400             :                       "[test.cpp:3]: (error) Uninitialized variable: a\n", errout_str());
     401             : 
     402           5 :         ASSERT_EQUALS(0, (this->*check)("// cppcheck-suppress-file uninitvar\n"
     403             :                                         "void f() {\n"
     404             :                                         "    int a;\n"
     405             :                                         "    a++;\n"
     406             :                                         "    int b;\n"
     407             :                                         "    b++;\n"
     408             :                                         "}\n",
     409             :                                         ""));
     410           5 :         ASSERT_EQUALS("", errout_str());
     411             : 
     412           5 :         ASSERT_EQUALS(0, (this->*check)("/* Fake file description\n"
     413             :                                         " * End\n"
     414             :                                         " */\n"
     415             :                                         "\n"
     416             :                                         "// cppcheck-suppress-file uninitvar\n"
     417             :                                         "\n"
     418             :                                         "void f() {\n"
     419             :                                         "    int a;\n"
     420             :                                         "    a++;\n"
     421             :                                         "    int b;\n"
     422             :                                         "    b++;\n"
     423             :                                         "}\n",
     424             :                                         ""));
     425           5 :         ASSERT_EQUALS("", errout_str());
     426             : 
     427           5 :         (this->*check)("// cppcheck-suppress-file uninitvar\n"
     428             :                        "void f() {\n"
     429             :                        "    int a;\n"
     430             :                        "    a++;\n"
     431             :                        "    int b;\n"
     432             :                        "    b++;\n"
     433             :                        "}\n",
     434          10 :                        "");
     435           5 :         ASSERT_EQUALS("", errout_str());
     436             : 
     437             :         // suppress uninitvar globally, without error present
     438           5 :         ASSERT_EQUALS(0, (this->*check)("void f() {\n"
     439             :                                         "    int a;\n"
     440             :                                         "    b++;\n"
     441             :                                         "}\n",
     442             :                                         "uninitvar"));
     443           5 :         ASSERT_EQUALS("(information) Unmatched suppression: uninitvar\n", errout_str());
     444             : 
     445           5 :         (this->*check)("// cppcheck-suppress-file uninitvar\n"
     446             :                        "void f() {\n"
     447             :                        "    int a;\n"
     448             :                        "    b++;\n"
     449             :                        "}\n",
     450          10 :                        "");
     451           5 :         ASSERT_EQUALS("[test.cpp:1]: (information) Unmatched suppression: uninitvar\n", errout_str());
     452             : 
     453             :         // suppress uninitvar for this file only
     454           5 :         ASSERT_EQUALS(0, (this->*check)("void f() {\n"
     455             :                                         "    int a;\n"
     456             :                                         "    a++;\n"
     457             :                                         "}\n",
     458             :                                         "uninitvar:test.cpp"));
     459           5 :         ASSERT_EQUALS("", errout_str());
     460             : 
     461             :         // suppress uninitvar for this file only, without error present
     462           5 :         (this->*check)("void f() {\n"
     463             :                        "    int a;\n"
     464             :                        "    b++;\n"
     465             :                        "}\n",
     466          10 :                        "uninitvar:test.cpp");
     467           5 :         ASSERT_EQUALS("[test.cpp]: (information) Unmatched suppression: uninitvar\n", errout_str());
     468             : 
     469             :         // suppress all for this file only
     470           5 :         ASSERT_EQUALS(0, (this->*check)("void f() {\n"
     471             :                                         "    int a;\n"
     472             :                                         "    a++;\n"
     473             :                                         "}\n",
     474             :                                         "*:test.cpp"));
     475           5 :         ASSERT_EQUALS("", errout_str());
     476             : 
     477             :         // suppress all for this file only, without error present
     478           5 :         (this->*check)("void f() {\n"
     479             :                        "    int a;\n"
     480             :                        "    b++;\n"
     481             :                        "}\n",
     482          10 :                        "*:test.cpp");
     483           5 :         ASSERT_EQUALS("[test.cpp]: (information) Unmatched suppression: *\n", errout_str());
     484             : 
     485             :         // suppress uninitvar for this file and line
     486           5 :         ASSERT_EQUALS(0, (this->*check)("void f() {\n"
     487             :                                         "    int a;\n"
     488             :                                         "    a++;\n"
     489             :                                         "}\n",
     490             :                                         "uninitvar:test.cpp:3"));
     491           5 :         ASSERT_EQUALS("", errout_str());
     492             : 
     493             :         // suppress uninitvar for this file and line, without error present
     494           5 :         (this->*check)("void f() {\n"
     495             :                        "    int a;\n"
     496             :                        "    b++;\n"
     497             :                        "}\n",
     498          10 :                        "uninitvar:test.cpp:3");
     499           5 :         ASSERT_EQUALS("[test.cpp:3]: (information) Unmatched suppression: uninitvar\n", errout_str());
     500             : 
     501             :         // suppress uninitvar inline
     502           5 :         ASSERT_EQUALS(0, (this->*check)("void f() {\n"
     503             :                                         "    int a;\n"
     504             :                                         "    // cppcheck-suppress uninitvar\n"
     505             :                                         "    a++;\n"
     506             :                                         "}\n",
     507             :                                         ""));
     508           5 :         ASSERT_EQUALS("", errout_str());
     509             : 
     510             :         // suppress uninitvar inline
     511           5 :         ASSERT_EQUALS(0, (this->*check)("void f() {\n"
     512             :                                         "    int a;\n"
     513             :                                         "    // cppcheck-suppress uninitvar\n"
     514             :                                         "\n"
     515             :                                         "    a++;\n"
     516             :                                         "}\n",
     517             :                                         ""));
     518           5 :         ASSERT_EQUALS("", errout_str());
     519             : 
     520             :         // suppress uninitvar inline
     521           5 :         ASSERT_EQUALS(0, (this->*check)("void f() {\n"
     522             :                                         "    int a;\n"
     523             :                                         "    a++;// cppcheck-suppress uninitvar\n"
     524             :                                         "}\n",
     525             :                                         ""));
     526           5 :         ASSERT_EQUALS("", errout_str());
     527             : 
     528             :         // suppress uninitvar inline
     529           5 :         ASSERT_EQUALS(0, (this->*check)("void f() {\n"
     530             :                                         "    int a;\n"
     531             :                                         "    /* cppcheck-suppress uninitvar */\n"
     532             :                                         "    a++;\n"
     533             :                                         "}\n",
     534             :                                         ""));
     535           5 :         ASSERT_EQUALS("", errout_str());
     536             : 
     537             :         // suppress uninitvar inline
     538           5 :         ASSERT_EQUALS(0, (this->*check)("void f() {\n"
     539             :                                         "    int a;\n"
     540             :                                         "    /* cppcheck-suppress uninitvar */\n"
     541             :                                         "\n"
     542             :                                         "    a++;\n"
     543             :                                         "}\n",
     544             :                                         ""));
     545           5 :         ASSERT_EQUALS("", errout_str());
     546             : 
     547             :         // suppress uninitvar inline
     548           5 :         ASSERT_EQUALS(0, (this->*check)("void f() {\n"
     549             :                                         "    int a;\n"
     550             :                                         "    a++;/* cppcheck-suppress uninitvar */\n"
     551             :                                         "}\n",
     552             :                                         ""));
     553           5 :         ASSERT_EQUALS("", errout_str());
     554             : 
     555             :         // suppress uninitvar inline
     556           5 :         ASSERT_EQUALS(0, (this->*check)("void f() {\n"
     557             :                                         "    int a;\n"
     558             :                                         "    // cppcheck-suppress[uninitvar]\n"
     559             :                                         "    a++;\n"
     560             :                                         "}\n",
     561             :                                         ""));
     562           5 :         ASSERT_EQUALS("", errout_str());
     563             : 
     564             :         // suppress uninitvar inline
     565           5 :         ASSERT_EQUALS(0, (this->*check)("void f() {\n"
     566             :                                         "    int a;\n"
     567             :                                         "    // cppcheck-suppress[uninitvar]\n"
     568             :                                         "    a++;\n"
     569             :                                         "\n"
     570             :                                         "    a++;\n"
     571             :                                         "}\n",
     572             :                                         ""));
     573           5 :         ASSERT_EQUALS("", errout_str());
     574             : 
     575             :         // suppress uninitvar inline
     576           5 :         ASSERT_EQUALS(0, (this->*check)("void f() {\n"
     577             :                                         "    int a;\n"
     578             :                                         "    a++;// cppcheck-suppress[uninitvar]\n"
     579             :                                         "}\n",
     580             :                                         ""));
     581           5 :         ASSERT_EQUALS("", errout_str());
     582             : 
     583             :         // suppress uninitvar inline
     584           5 :         ASSERT_EQUALS(0, (this->*check)("void f() {\n"
     585             :                                         "    int a;\n"
     586             :                                         "    /* cppcheck-suppress[uninitvar]*/\n"
     587             :                                         "    a++;\n"
     588             :                                         "}\n",
     589             :                                         ""));
     590           5 :         ASSERT_EQUALS("", errout_str());
     591             : 
     592             :         // suppress uninitvar inline
     593           5 :         ASSERT_EQUALS(0, (this->*check)("void f() {\n"
     594             :                                         "    int a;\n"
     595             :                                         "    /* cppcheck-suppress[uninitvar]*/\n"
     596             :                                         "\n"
     597             :                                         "    a++;\n"
     598             :                                         "}\n",
     599             :                                         ""));
     600           5 :         ASSERT_EQUALS("", errout_str());
     601             : 
     602             :         // suppress uninitvar inline
     603           5 :         ASSERT_EQUALS(0, (this->*check)("void f() {\n"
     604             :                                         "    int a;\n"
     605             :                                         "    a++;/* cppcheck-suppress[uninitvar]*/\n"
     606             :                                         "}\n",
     607             :                                         ""));
     608           5 :         ASSERT_EQUALS("", errout_str());
     609             : 
     610             :         // suppress uninitvar inline, with asm before (#6813)
     611           5 :         ASSERT_EQUALS(0, (this->*check)("void f() {\n"
     612             :                                         "    __asm {\n"
     613             :                                         "        foo\n"
     614             :                                         "    }"
     615             :                                         "    int a;\n"
     616             :                                         "    // cppcheck-suppress uninitvar\n"
     617             :                                         "    a++;\n"
     618             :                                         "}",
     619             :                                         ""));
     620           5 :         ASSERT_EQUALS("", errout_str());
     621             : 
     622             :         // suppress uninitvar inline, without error present
     623           5 :         (this->*check)("void f() {\n"
     624             :                        "    int a;\n"
     625             :                        "    // cppcheck-suppress uninitvar\n"
     626             :                        "    b++;\n"
     627             :                        "}\n",
     628          10 :                        "");
     629           5 :         ASSERT_EQUALS("[test.cpp:4]: (information) Unmatched suppression: uninitvar\n", errout_str());
     630             : 
     631             :         // suppress block inline checks
     632           5 :         ASSERT_EQUALS(0, (this->*check)("void f() {\n"
     633             :                                         "    // cppcheck-suppress-begin uninitvar\n"
     634             :                                         "    int a;\n"
     635             :                                         "    a++;\n"
     636             :                                         "    int b;\n"
     637             :                                         "    b++;\n"
     638             :                                         "    // cppcheck-suppress-end uninitvar\n"
     639             :                                         "}\n",
     640             :                                         ""));
     641           5 :         ASSERT_EQUALS("", errout_str());
     642             : 
     643           5 :         ASSERT_EQUALS(1, (this->*check)("void f() {\n"
     644             :                                         "    // cppcheck-suppress-begin uninitvar\n"
     645             :                                         "    int a;\n"
     646             :                                         "    a++;\n"
     647             :                                         "    int b;\n"
     648             :                                         "    b++;\n"
     649             :                                         "}\n",
     650             :                                         ""));
     651           5 :         ASSERT_EQUALS("[test.cpp:2]: (error) Suppress Begin: No matching end\n"
     652             :                       "[test.cpp:4]: (error) Uninitialized variable: a\n"
     653             :                       "[test.cpp:6]: (error) Uninitialized variable: b\n", errout_str());
     654             : 
     655           5 :         ASSERT_EQUALS(1, (this->*check)("void f() {\n"
     656             :                                         "    int a;\n"
     657             :                                         "    a++;\n"
     658             :                                         "    int b;\n"
     659             :                                         "    b++;\n"
     660             :                                         "    // cppcheck-suppress-end uninitvar\n"
     661             :                                         "}\n",
     662             :                                         ""));
     663           5 :         ASSERT_EQUALS("[test.cpp:6]: (error) Suppress End: No matching begin\n"
     664             :                       "[test.cpp:3]: (error) Uninitialized variable: a\n"
     665             :                       "[test.cpp:5]: (error) Uninitialized variable: b\n", errout_str());
     666             : 
     667           5 :         ASSERT_EQUALS(1, (this->*check)("void f() {\n"
     668             :                                         "    int a;\n"
     669             :                                         "    // cppcheck-suppress-begin uninitvar\n"
     670             :                                         "    a++;\n"
     671             :                                         "    // cppcheck-suppress-end uninitvar\n"
     672             :                                         "    int b;\n"
     673             :                                         "    b++;\n"
     674             :                                         "}\n",
     675             :                                         ""));
     676           5 :         ASSERT_EQUALS("[test.cpp:7]: (error) Uninitialized variable: b\n", errout_str());
     677             : 
     678           5 :         ASSERT_EQUALS(1, (this->*check)("void f() {\n"
     679             :                                         "    int a;\n"
     680             :                                         "    // cppcheck-suppress-begin uninitvar\n"
     681             :                                         "    a++;\n"
     682             :                                         "    // cppcheck-suppress-end uninitvar\n"
     683             :                                         "    int b;\n"
     684             :                                         "    b++;\n"
     685             :                                         "}\n",
     686             :                                         ""));
     687           5 :         ASSERT_EQUALS("[test.cpp:7]: (error) Uninitialized variable: b\n", errout_str());
     688             : 
     689           5 :         ASSERT_EQUALS(1, (this->*check)("void f() {\n"
     690             :                                         "    int a;\n"
     691             :                                         "    // cppcheck-suppress-begin[uninitvar]\n"
     692             :                                         "    a++;\n"
     693             :                                         "    // cppcheck-suppress-end[uninitvar]\n"
     694             :                                         "    int b;\n"
     695             :                                         "    b++;\n"
     696             :                                         "}\n",
     697             :                                         ""));
     698           5 :         ASSERT_EQUALS("[test.cpp:7]: (error) Uninitialized variable: b\n", errout_str());
     699             : 
     700           5 :         ASSERT_EQUALS(1, (this->*check)("void f() {\n"
     701             :                                         "    int a;\n"
     702             :                                         "    // cppcheck-suppress-begin [uninitvar]\n"
     703             :                                         "    a++;\n"
     704             :                                         "    // cppcheck-suppress-end [uninitvar]\n"
     705             :                                         "    int b;\n"
     706             :                                         "    b++;\n"
     707             :                                         "}\n",
     708             :                                         ""));
     709           5 :         ASSERT_EQUALS("[test.cpp:7]: (error) Uninitialized variable: b\n", errout_str());
     710             : 
     711           5 :         (this->*check)("void f() {\n"
     712             :                        "    int a;\n"
     713             :                        "    // cppcheck-suppress-begin uninitvar\n"
     714             :                        "    a++;\n"
     715             :                        "    // cppcheck-suppress-end uninitvar\n"
     716             :                        "    int b;\n"
     717             :                        "    // cppcheck-suppress-begin uninitvar\n"
     718             :                        "    b++;\n"
     719             :                        "    // cppcheck-suppress-end uninitvar\n"
     720             :                        "}\n",
     721          10 :                        "");
     722           5 :         ASSERT_EQUALS("", errout_str());
     723             : 
     724           5 :         (this->*check)("void f() {\n"
     725             :                        "    int a;\n"
     726             :                        "    // cppcheck-suppress-begin uninitvar\n"
     727             :                        "    a++;\n"
     728             :                        "    // cppcheck-suppress-end uninitvar\n"
     729             :                        "    // cppcheck-suppress-begin uninitvar\n"
     730             :                        "    int b;\n"
     731             :                        "    b++;\n"
     732             :                        "    // cppcheck-suppress-end uninitvar\n"
     733             :                        "}\n",
     734          10 :                        "");
     735           5 :         ASSERT_EQUALS("", errout_str());
     736             : 
     737           5 :         (this->*check)("void f() {\n"
     738             :                        "    // cppcheck-suppress-begin [uninitvar]\n"
     739             :                        "    int a;\n"
     740             :                        "    // cppcheck-suppress-begin uninitvar\n"
     741             :                        "    a++;\n"
     742             :                        "    // cppcheck-suppress-end uninitvar\n"
     743             :                        "    int b;\n"
     744             :                        "    // cppcheck-suppress-begin uninitvar\n"
     745             :                        "    b++;\n"
     746             :                        "    // cppcheck-suppress-end uninitvar\n"
     747             :                        "    // cppcheck-suppress-end [uninitvar]\n"
     748             :                        "}\n",
     749          10 :                        "");
     750           5 :         ASSERT_EQUALS("", errout_str());
     751             : 
     752           5 :         (this->*check)("void f() {\n"
     753             :                        "    // cppcheck-suppress-begin [uninitvar, syntaxError]\n"
     754             :                        "    int a;\n"
     755             :                        "    // cppcheck-suppress-begin uninitvar\n"
     756             :                        "    a++;\n"
     757             :                        "    // cppcheck-suppress-end uninitvar\n"
     758             :                        "    int b;\n"
     759             :                        "    // cppcheck-suppress-begin uninitvar\n"
     760             :                        "    b++;\n"
     761             :                        "    // cppcheck-suppress-end uninitvar\n"
     762             :                        "    // cppcheck-suppress-end [uninitvar, syntaxError]\n"
     763             :                        "}\n",
     764          10 :                        "");
     765           5 :         ASSERT_EQUALS("[test.cpp:2]: (information) Unmatched suppression: syntaxError\n", errout_str());
     766             : 
     767           5 :         (this->*check)("// cppcheck-suppress-begin [uninitvar, syntaxError]\n"
     768             :                        "void f() {\n"
     769             :                        "    int a;\n"
     770             :                        "    // cppcheck-suppress-begin uninitvar\n"
     771             :                        "    a++;\n"
     772             :                        "    // cppcheck-suppress-end uninitvar\n"
     773             :                        "    int b;\n"
     774             :                        "    // cppcheck-suppress-begin uninitvar\n"
     775             :                        "    b++;\n"
     776             :                        "    // cppcheck-suppress-end uninitvar\n"
     777             :                        "}\n"
     778             :                        "// cppcheck-suppress-end [uninitvar, syntaxError]\n",
     779          10 :                        "");
     780           5 :         ASSERT_EQUALS("[test.cpp:1]: (information) Unmatched suppression: syntaxError\n", errout_str());
     781             : 
     782           5 :         (this->*check)("// cppcheck-suppress-begin [uninitvar, syntaxError]\n"
     783             :                        "void f() {\n"
     784             :                        "    int a;\n"
     785             :                        "    // cppcheck-suppress-begin uninitvar\n"
     786             :                        "    a++;\n"
     787             :                        "    // cppcheck-suppress-end uninitvar\n"
     788             :                        "    int b;\n"
     789             :                        "    // cppcheck-suppress-begin uninitvar\n"
     790             :                        "    b++;\n"
     791             :                        "    // cppcheck-suppress-end uninitvar\n"
     792             :                        "}\n"
     793             :                        "// cppcheck-suppress-end [uninitvar, syntaxError]",
     794          10 :                        "");
     795           5 :         ASSERT_EQUALS("[test.cpp:1]: (information) Unmatched suppression: syntaxError\n", errout_str());
     796             : 
     797             :         // test of multiple suppression types
     798           5 :         (this->*check)("// cppcheck-suppress-file uninitvar\n"
     799             :                        "void f() {\n"
     800             :                        "    int a;\n"
     801             :                        "    // cppcheck-suppress-begin uninitvar\n"
     802             :                        "    // cppcheck-suppress uninitvar\n"
     803             :                        "    a++;\n"
     804             :                        "    // cppcheck-suppress-end uninitvar\n"
     805             :                        "}\n",
     806          10 :                        "");
     807           5 :         ASSERT_EQUALS("", errout_str());
     808             : 
     809           5 :         (this->*check)("void f() {\n"
     810             :                        "    int a;\n"
     811             :                        "    // cppcheck-suppress-begin uninitvar\n"
     812             :                        "    // cppcheck-suppress uninitvar\n"
     813             :                        "    a++;\n"
     814             :                        "    // cppcheck-suppress-end uninitvar\n"
     815             :                        "}\n",
     816          10 :                        "");
     817           5 :         ASSERT_EQUALS("", errout_str());
     818             : 
     819           5 :         (this->*check)("// cppcheck-suppress-file uninitvar\n"
     820             :                        "void f() {\n"
     821             :                        "    int a;\n"
     822             :                        "    // cppcheck-suppress uninitvar\n"
     823             :                        "    a++;\n"
     824             :                        "}\n",
     825          10 :                        "");
     826           5 :         ASSERT_EQUALS("", errout_str());
     827             : 
     828           5 :         (this->*check)("// cppcheck-suppress-file uninitvar\n"
     829             :                        "void f() {\n"
     830             :                        "    int a;\n"
     831             :                        "    // cppcheck-suppress-begin uninitvar\n"
     832             :                        "    a++;\n"
     833             :                        "    // cppcheck-suppress-end uninitvar\n"
     834             :                        "}\n",
     835          10 :                        "");
     836           5 :         ASSERT_EQUALS("", errout_str());
     837             : 
     838           5 :         (this->*check)("// cppcheck-suppress-file uninitvar\n"
     839             :                        "void f() {\n"
     840             :                        "    // cppcheck-suppress uninitvar\n"
     841             :                        "    int a;\n"
     842             :                        "    a++;\n"
     843             :                        "}\n",
     844          10 :                        "");
     845           5 :         ASSERT_EQUALS("[test.cpp:4]: (information) Unmatched suppression: uninitvar\n", errout_str());
     846             : 
     847             :         // #5746 - exitcode
     848           5 :         ASSERT_EQUALS(1U,
     849             :                       (this->*check)("int f() {\n"
     850             :                                      "  int a; return a;\n"
     851             :                                      "}\n",
     852             :                                      ""));
     853           5 :         ASSERT_EQUALS("[test.cpp:2]: (error) Uninitialized variable: a\n", errout_str());
     854             : 
     855           5 :         ASSERT_EQUALS(0U,
     856             :                       (this->*check)("int f() {\n"
     857             :                                      "  int a; return a;\n"
     858             :                                      "}\n",
     859             :                                      "uninitvar"));
     860           5 :         ASSERT_EQUALS("", errout_str());
     861             : 
     862             :         // cppcheck-suppress-macro
     863           5 :         (this->*check)("// cppcheck-suppress-macro zerodiv\n"
     864             :                        "#define DIV(A,B) A/B\n"
     865             :                        "a = DIV(10,0);\n",
     866          10 :                        "");
     867           5 :         ASSERT_EQUALS("", errout_str());
     868             : 
     869           5 :         (this->*check)("// cppcheck-suppress-macro abc\n"
     870             :                        "#define DIV(A,B) A/B\n"
     871             :                        "a = DIV(10,1);\n",
     872          10 :                        "");
     873           5 :         ASSERT_EQUALS("", errout_str()); // <- no unmatched suppression reported for macro suppression
     874             :     }
     875             : 
     876           1 :     void suppressionsSettingsFiles() {
     877           1 :         runChecks(&TestSuppressions::checkSuppressionFiles);
     878           1 :     }
     879             : 
     880           1 :     static void suppressionsSettingsFS() {
     881             :         // TODO
     882             :         // runChecks(&TestSuppressions::checkSuppressionFS);
     883           1 :     }
     884             : 
     885           1 :     void suppressionsSettingsThreadsFiles() {
     886           1 :         runChecks(&TestSuppressions::checkSuppressionThreadsFiles);
     887           1 :     }
     888             : 
     889           1 :     void suppressionsSettingsThreadsFS() {
     890           1 :         runChecks(&TestSuppressions::checkSuppressionThreadsFS);
     891           1 :     }
     892             : 
     893             : #if !defined(WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
     894           1 :     void suppressionsSettingsProcessesFiles() {
     895           1 :         runChecks(&TestSuppressions::checkSuppressionProcessesFiles);
     896           1 :     }
     897             : 
     898           1 :     void suppressionsSettingsProcessesFS() {
     899           1 :         runChecks(&TestSuppressions::checkSuppressionProcessesFS);
     900           1 :     }
     901             : #endif
     902             : 
     903           2 :     void suppressionsMultiFileInternal(unsigned int (TestSuppressions::*check)(std::map<std::string, std::string> &f, const std::string &)) {
     904           2 :         std::map<std::string, std::string> files;
     905           4 :         files["abc.cpp"] = "void f() {\n"
     906           2 :                            "}\n";
     907           4 :         files["xyz.cpp"] = "void f() {\n"
     908             :                            "    int a;\n"
     909             :                            "    a++;\n"
     910           2 :                            "}\n";
     911             : 
     912             :         // suppress uninitvar for this file and line
     913           2 :         ASSERT_EQUALS(0, (this->*check)(files, "uninitvar:xyz.cpp:3"));
     914           2 :         ASSERT_EQUALS("", errout_str());
     915             :     }
     916             : 
     917           1 :     void suppressionsMultiFileFiles() {
     918           1 :         suppressionsMultiFileInternal(&TestSuppressions::checkSuppressionFiles);
     919           1 :     }
     920             : 
     921           1 :     void suppressionsMultiFileFS() {
     922           1 :         suppressionsMultiFileInternal(&TestSuppressions::checkSuppressionFS);
     923           1 :     }
     924             : 
     925           1 :     void suppressionsPathSeparator() const {
     926           3 :         const SuppressionList::Suppression s1("*", "test/foo/*");
     927           1 :         ASSERT_EQUALS(true, s1.isSuppressed(errorMessage("someid", "test/foo/bar.cpp", 142)));
     928             : 
     929           3 :         const SuppressionList::Suppression s2("abc", "include/1.h");
     930           1 :         ASSERT_EQUALS(true, s2.isSuppressed(errorMessage("abc", "include/1.h", 142)));
     931             :     }
     932             : 
     933           1 :     void suppressionsLine0() const {
     934           1 :         SuppressionList suppressions;
     935           1 :         ASSERT_EQUALS("", suppressions.addSuppressionLine("syntaxError:*:0"));
     936           1 :         ASSERT_EQUALS(true, suppressions.isSuppressed(errorMessage("syntaxError", "test.cpp", 0)));
     937             :     }
     938             : 
     939           1 :     void suppressionsFileComment() const {
     940             :         std::istringstream file1("# comment\n"
     941           2 :                                  "abc");
     942           1 :         SuppressionList suppressions1;
     943           1 :         ASSERT_EQUALS("", suppressions1.parseFile(file1));
     944           1 :         ASSERT_EQUALS(true, suppressions1.isSuppressed(errorMessage("abc", "test.cpp", 123)));
     945             : 
     946             :         std::istringstream file2("// comment\n"
     947           2 :                                  "abc");
     948           1 :         SuppressionList suppressions2;
     949           1 :         ASSERT_EQUALS("", suppressions2.parseFile(file2));
     950           1 :         ASSERT_EQUALS(true, suppressions2.isSuppressed(errorMessage("abc", "test.cpp", 123)));
     951             : 
     952           2 :         std::istringstream file3("abc // comment");
     953           1 :         SuppressionList suppressions3;
     954           1 :         ASSERT_EQUALS("", suppressions3.parseFile(file3));
     955           1 :         ASSERT_EQUALS(true, suppressions3.isSuppressed(errorMessage("abc", "test.cpp", 123)));
     956             : 
     957           2 :         std::istringstream file4("abc\t\t # comment");
     958           1 :         SuppressionList suppressions4;
     959           1 :         ASSERT_EQUALS("", suppressions4.parseFile(file4));
     960           1 :         ASSERT_EQUALS(true, suppressions4.isSuppressed(errorMessage("abc", "test.cpp", 123)));
     961             : 
     962           2 :         std::istringstream file5("abc:test.cpp\t\t # comment");
     963           1 :         SuppressionList suppressions5;
     964           1 :         ASSERT_EQUALS("", suppressions5.parseFile(file5));
     965           1 :         ASSERT_EQUALS(true, suppressions5.isSuppressed(errorMessage("abc", "test.cpp", 123)));
     966             : 
     967           2 :         std::istringstream file6("abc:test.cpp:123\t\t # comment with . inside");
     968           1 :         SuppressionList suppressions6;
     969           1 :         ASSERT_EQUALS("", suppressions6.parseFile(file6));
     970           1 :         ASSERT_EQUALS(true, suppressions6.isSuppressed(errorMessage("abc", "test.cpp", 123)));
     971             :     }
     972             : 
     973           1 :     void inlinesuppress() const {
     974           1 :         SuppressionList::Suppression s;
     975           1 :         std::string msg;
     976             : 
     977             :         // Suppress without attribute
     978           1 :         ASSERT_EQUALS(false, s.parseComment("/* some text */", &msg));
     979           1 :         ASSERT_EQUALS(false, s.parseComment("/* cppcheck-suppress */", &msg));
     980           1 :         ASSERT_EQUALS(false, s.parseComment("/* cppcheck-suppress-file  */", &msg));
     981           1 :         ASSERT_EQUALS(false, s.parseComment("/* cppcheck-suppress-begin */", &msg));
     982           1 :         ASSERT_EQUALS(false, s.parseComment("/* cppcheck-suppress-end */", &msg));
     983             : 
     984             :         // Correct suppress
     985           1 :         msg.clear();
     986           1 :         ASSERT_EQUALS(true, s.parseComment("/* cppcheck-suppress id */", &msg));
     987           1 :         ASSERT_EQUALS("", msg);
     988             : 
     989           1 :         msg.clear();
     990           1 :         ASSERT_EQUALS(true, s.parseComment("/* cppcheck-suppress-file id */", &msg));
     991           1 :         ASSERT_EQUALS("", msg);
     992             : 
     993           1 :         msg.clear();
     994           1 :         ASSERT_EQUALS(true, s.parseComment("/* cppcheck-suppress-begin id */", &msg));
     995           1 :         ASSERT_EQUALS("", msg);
     996             : 
     997           1 :         msg.clear();
     998           1 :         ASSERT_EQUALS(true, s.parseComment("/* cppcheck-suppress-end id */", &msg));
     999           1 :         ASSERT_EQUALS("", msg);
    1000             : 
    1001             :         // Bad cppcheck-suppress comment
    1002           1 :         ASSERT_EQUALS(false, s.parseComment("/* cppcheck-suppress-beggin id */", &msg));
    1003             : 
    1004             :         // Bad attribute construction
    1005           1 :         const std::string badSuppressionAttribute = "Bad suppression attribute 'some'. You can write comments in the comment after a ; or //. Valid suppression attributes; symbolName=sym";
    1006             : 
    1007           1 :         ASSERT_EQUALS(true, s.parseComment("/* cppcheck-suppress id some text */", &msg));
    1008           1 :         ASSERT_EQUALS(badSuppressionAttribute, msg);
    1009           1 :         ASSERT_EQUALS(true, s.parseComment("/* cppcheck-suppress-file id some text */", &msg));
    1010           1 :         ASSERT_EQUALS(badSuppressionAttribute, msg);
    1011           1 :         ASSERT_EQUALS(true, s.parseComment("/* cppcheck-suppress-begin id some text */", &msg));
    1012           1 :         ASSERT_EQUALS(badSuppressionAttribute, msg);
    1013           1 :         ASSERT_EQUALS(true, s.parseComment("/* cppcheck-suppress-end id some text */", &msg));
    1014           1 :         ASSERT_EQUALS(badSuppressionAttribute, msg);
    1015             :     }
    1016             : 
    1017           2 :     void inlinesuppress_symbolname_Internal(unsigned int (TestSuppressions::*check)(const char[], const std::string &)) {
    1018           2 :         ASSERT_EQUALS(0, (this->*check)("void f() {\n"
    1019             :                                         "    int a;\n"
    1020             :                                         "    /* cppcheck-suppress uninitvar symbolName=a */\n"
    1021             :                                         "    a++;\n"
    1022             :                                         "}\n",
    1023             :                                         ""));
    1024           2 :         ASSERT_EQUALS("", errout_str());
    1025             : 
    1026           2 :         ASSERT_EQUALS(1, (this->*check)("void f() {\n"
    1027             :                                         "    int a,b;\n"
    1028             :                                         "    /* cppcheck-suppress uninitvar symbolName=b */\n"
    1029             :                                         "    a++; b++;\n"
    1030             :                                         "}\n",
    1031             :                                         ""));
    1032           2 :         ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: a\n", errout_str());
    1033             :     }
    1034             : 
    1035           1 :     void inlinesuppress_symbolname_Files() {
    1036           1 :         inlinesuppress_symbolname_Internal(&TestSuppressions::checkSuppressionFiles);
    1037           1 :     }
    1038             : 
    1039           1 :     void inlinesuppress_symbolname_FS() {
    1040           1 :         inlinesuppress_symbolname_Internal(&TestSuppressions::checkSuppressionFS);
    1041           1 :     }
    1042             : 
    1043           1 :     void inlinesuppress_comment() const {
    1044           1 :         SuppressionList::Suppression s;
    1045           1 :         std::string errMsg;
    1046           1 :         ASSERT_EQUALS(true, s.parseComment("// cppcheck-suppress abc ; some comment", &errMsg));
    1047           1 :         ASSERT_EQUALS("", errMsg);
    1048           1 :         ASSERT_EQUALS(true, s.parseComment("// cppcheck-suppress abc // some comment", &errMsg));
    1049           1 :         ASSERT_EQUALS("", errMsg);
    1050           1 :         ASSERT_EQUALS(true, s.parseComment("// cppcheck-suppress abc -- some comment", &errMsg));
    1051           1 :         ASSERT_EQUALS("", errMsg);
    1052             :     }
    1053             : 
    1054           1 :     void multi_inlinesuppress() const {
    1055           1 :         std::vector<SuppressionList::Suppression> suppressions;
    1056           1 :         std::string errMsg;
    1057             : 
    1058           1 :         errMsg = "";
    1059           1 :         suppressions=SuppressionList::parseMultiSuppressComment("// cppcheck-suppress[errorId]", &errMsg);
    1060           1 :         ASSERT_EQUALS(1, suppressions.size());
    1061           1 :         ASSERT_EQUALS("errorId", suppressions[0].errorId);
    1062           1 :         ASSERT_EQUALS("", suppressions[0].symbolName);
    1063           1 :         ASSERT_EQUALS("", errMsg);
    1064             : 
    1065           1 :         errMsg = "";
    1066           1 :         suppressions=SuppressionList::parseMultiSuppressComment("// cppcheck-suppress-begin[errorId]", &errMsg);
    1067           1 :         ASSERT_EQUALS(1, suppressions.size());
    1068           1 :         ASSERT_EQUALS("errorId", suppressions[0].errorId);
    1069           1 :         ASSERT_EQUALS("", suppressions[0].symbolName);
    1070           1 :         ASSERT_EQUALS("", errMsg);
    1071             : 
    1072           1 :         errMsg = "";
    1073           1 :         suppressions=SuppressionList::parseMultiSuppressComment("// cppcheck-suppress-begin [errorId]", &errMsg);
    1074           1 :         ASSERT_EQUALS(1, suppressions.size());
    1075           1 :         ASSERT_EQUALS("errorId", suppressions[0].errorId);
    1076           1 :         ASSERT_EQUALS("", suppressions[0].symbolName);
    1077           1 :         ASSERT_EQUALS("", errMsg);
    1078             : 
    1079           1 :         errMsg = "";
    1080           1 :         suppressions=SuppressionList::parseMultiSuppressComment("// cppcheck-suppress-end[errorId]", &errMsg);
    1081           1 :         ASSERT_EQUALS(1, suppressions.size());
    1082           1 :         ASSERT_EQUALS("errorId", suppressions[0].errorId);
    1083           1 :         ASSERT_EQUALS("", suppressions[0].symbolName);
    1084           1 :         ASSERT_EQUALS("", errMsg);
    1085             : 
    1086           1 :         errMsg = "";
    1087           1 :         suppressions=SuppressionList::parseMultiSuppressComment("// cppcheck-suppress-end [errorId]", &errMsg);
    1088           1 :         ASSERT_EQUALS(1, suppressions.size());
    1089           1 :         ASSERT_EQUALS("errorId", suppressions[0].errorId);
    1090           1 :         ASSERT_EQUALS("", suppressions[0].symbolName);
    1091           1 :         ASSERT_EQUALS("", errMsg);
    1092             : 
    1093           1 :         errMsg = "";
    1094           1 :         suppressions=SuppressionList::parseMultiSuppressComment("// cppcheck-suppress-file[errorId]", &errMsg);
    1095           1 :         ASSERT_EQUALS(1, suppressions.size());
    1096           1 :         ASSERT_EQUALS("errorId", suppressions[0].errorId);
    1097           1 :         ASSERT_EQUALS("", suppressions[0].symbolName);
    1098           1 :         ASSERT_EQUALS("", errMsg);
    1099             : 
    1100           1 :         errMsg = "";
    1101           1 :         suppressions=SuppressionList::parseMultiSuppressComment("// cppcheck-suppress-file [errorId]", &errMsg);
    1102           1 :         ASSERT_EQUALS(1, suppressions.size());
    1103           1 :         ASSERT_EQUALS("errorId", suppressions[0].errorId);
    1104           1 :         ASSERT_EQUALS("", suppressions[0].symbolName);
    1105           1 :         ASSERT_EQUALS("", errMsg);
    1106             : 
    1107           1 :         errMsg = "";
    1108           1 :         suppressions=SuppressionList::parseMultiSuppressComment("// cppcheck-suppress[errorId symbolName=arr]", &errMsg);
    1109           1 :         ASSERT_EQUALS(1, suppressions.size());
    1110           1 :         ASSERT_EQUALS("errorId", suppressions[0].errorId);
    1111           1 :         ASSERT_EQUALS("arr", suppressions[0].symbolName);
    1112           1 :         ASSERT_EQUALS("", errMsg);
    1113             : 
    1114           1 :         errMsg = "";
    1115           1 :         suppressions=SuppressionList::parseMultiSuppressComment("// cppcheck-suppress[errorId symbolName=]", &errMsg);
    1116           1 :         ASSERT_EQUALS(1, suppressions.size());
    1117           1 :         ASSERT_EQUALS("errorId", suppressions[0].errorId);
    1118           1 :         ASSERT_EQUALS("", suppressions[0].symbolName);
    1119           1 :         ASSERT_EQUALS("", errMsg);
    1120             : 
    1121           1 :         errMsg = "";
    1122           1 :         suppressions=SuppressionList::parseMultiSuppressComment("// cppcheck-suppress[errorId1, errorId2 symbolName=arr]", &errMsg);
    1123           1 :         ASSERT_EQUALS(2, suppressions.size());
    1124           1 :         ASSERT_EQUALS("errorId1", suppressions[0].errorId);
    1125           1 :         ASSERT_EQUALS("", suppressions[0].symbolName);
    1126           1 :         ASSERT_EQUALS("errorId2", suppressions[1].errorId);
    1127           1 :         ASSERT_EQUALS("arr", suppressions[1].symbolName);
    1128           1 :         ASSERT_EQUALS("", errMsg);
    1129             : 
    1130           1 :         errMsg = "";
    1131           1 :         suppressions=SuppressionList::parseMultiSuppressComment("// cppcheck-suppress[]", &errMsg);
    1132           1 :         ASSERT_EQUALS(0, suppressions.size());
    1133           1 :         ASSERT_EQUALS(true, errMsg.empty());
    1134             : 
    1135           1 :         errMsg = "";
    1136           1 :         suppressions=SuppressionList::parseMultiSuppressComment("// cppcheck-suppress[errorId", &errMsg);
    1137           1 :         ASSERT_EQUALS(0, suppressions.size());
    1138           1 :         ASSERT_EQUALS(false, errMsg.empty());
    1139             : 
    1140           1 :         errMsg = "";
    1141           1 :         suppressions=SuppressionList::parseMultiSuppressComment("// cppcheck-suppress errorId", &errMsg);
    1142           1 :         ASSERT_EQUALS(0, suppressions.size());
    1143           1 :         ASSERT_EQUALS(false, errMsg.empty());
    1144             : 
    1145           1 :         errMsg = "";
    1146           1 :         suppressions=SuppressionList::parseMultiSuppressComment("// cppcheck-suppress[errorId1 errorId2 symbolName=arr]", &errMsg);
    1147           1 :         ASSERT_EQUALS(0, suppressions.size());
    1148           1 :         ASSERT_EQUALS(false, errMsg.empty());
    1149             : 
    1150           1 :         errMsg = "";
    1151           1 :         suppressions=SuppressionList::parseMultiSuppressComment("// cppcheck-suppress[errorId1, errorId2 symbol=arr]", &errMsg);
    1152           1 :         ASSERT_EQUALS(0, suppressions.size());
    1153           1 :         ASSERT_EQUALS(false, errMsg.empty());
    1154             : 
    1155           1 :         errMsg = "";
    1156           1 :         suppressions=SuppressionList::parseMultiSuppressComment("// cppcheck-suppress[errorId1, errorId2 symbolName]", &errMsg);
    1157           1 :         ASSERT_EQUALS(0, suppressions.size());
    1158           1 :         ASSERT_EQUALS(false, errMsg.empty());
    1159             :     }
    1160             : 
    1161           1 :     void multi_inlinesuppress_comment() const {
    1162           1 :         std::vector<SuppressionList::Suppression> suppressions;
    1163           1 :         std::string errMsg;
    1164             : 
    1165           1 :         errMsg = "";
    1166           1 :         suppressions=SuppressionList::parseMultiSuppressComment("//cppcheck-suppress[errorId1, errorId2 symbolName=arr]", &errMsg);
    1167           1 :         ASSERT_EQUALS(2, suppressions.size());
    1168           1 :         ASSERT_EQUALS(true, errMsg.empty());
    1169             : 
    1170           1 :         errMsg = "";
    1171           1 :         suppressions=SuppressionList::parseMultiSuppressComment("//cppcheck-suppress[errorId1, errorId2 symbolName=arr] some text", &errMsg);
    1172           1 :         ASSERT_EQUALS(2, suppressions.size());
    1173           1 :         ASSERT_EQUALS(true, errMsg.empty());
    1174             : 
    1175           1 :         errMsg = "";
    1176           1 :         suppressions=SuppressionList::parseMultiSuppressComment("/*cppcheck-suppress[errorId1, errorId2 symbolName=arr]*/", &errMsg);
    1177           1 :         ASSERT_EQUALS(2, suppressions.size());
    1178           1 :         ASSERT_EQUALS(true, errMsg.empty());
    1179             :     }
    1180             : 
    1181           1 :     void globalSuppressions() { // Testing that Cppcheck::useGlobalSuppressions works (#8515)
    1182           1 :         CppCheck cppCheck(*this, false, nullptr); // <- do not "use global suppressions". pretend this is a thread that just checks a file.
    1183           1 :         Settings& settings = cppCheck.settings();
    1184           1 :         settings.quiet = true;
    1185           1 :         ASSERT_EQUALS("", settings.supprs.nomsg.addSuppressionLine("uninitvar"));
    1186           1 :         settings.exitCode = 1;
    1187             : 
    1188           1 :         const char code[] = "int f() { int a; return a; }";
    1189           1 :         ASSERT_EQUALS(0, cppCheck.check("test.c", code)); // <- no unsuppressed error is seen
    1190           1 :         ASSERT_EQUALS("[test.c:1]: (error) Uninitialized variable: a\n", errout_str()); // <- report error so ThreadExecutor can suppress it and make sure the global suppression is matched.
    1191             :     }
    1192             : 
    1193           1 :     void inlinesuppress_unusedFunction() const { // #4210, #4946 - wrong report of "unmatchedSuppression" for "unusedFunction"
    1194           1 :         SuppressionList suppressions;
    1195           3 :         SuppressionList::Suppression suppression("unusedFunction", "test.c", 3);
    1196           1 :         suppression.checked = true; // have to do this because fixes for #5704
    1197           1 :         ASSERT_EQUALS("", suppressions.addSuppression(std::move(suppression)));
    1198           1 :         ASSERT_EQUALS(true, !suppressions.getUnmatchedLocalSuppressions("test.c", true).empty());
    1199           1 :         ASSERT_EQUALS(false, !suppressions.getUnmatchedGlobalSuppressions(true).empty());
    1200           1 :         ASSERT_EQUALS(false, !suppressions.getUnmatchedLocalSuppressions("test.c", false).empty());
    1201           1 :         ASSERT_EQUALS(false, !suppressions.getUnmatchedGlobalSuppressions(false).empty());
    1202             :     }
    1203             : 
    1204           1 :     void globalsuppress_unusedFunction() const { // #4946 - wrong report of "unmatchedSuppression" for "unusedFunction"
    1205           1 :         SuppressionList suppressions;
    1206           1 :         ASSERT_EQUALS("", suppressions.addSuppressionLine("unusedFunction:*"));
    1207           1 :         ASSERT_EQUALS(false, !suppressions.getUnmatchedLocalSuppressions("test.c", true).empty());
    1208           1 :         ASSERT_EQUALS(true, !suppressions.getUnmatchedGlobalSuppressions(true).empty());
    1209           1 :         ASSERT_EQUALS(false, !suppressions.getUnmatchedLocalSuppressions("test.c", false).empty());
    1210           1 :         ASSERT_EQUALS(false, !suppressions.getUnmatchedGlobalSuppressions(false).empty());
    1211             :     }
    1212             : 
    1213           1 :     void suppressionWithRelativePaths() {
    1214           1 :         CppCheck cppCheck(*this, true, nullptr);
    1215           1 :         Settings& settings = cppCheck.settings();
    1216           1 :         settings.quiet = true;
    1217           1 :         settings.severity.enable(Severity::style);
    1218           1 :         settings.inlineSuppressions = true;
    1219           1 :         settings.relativePaths = true;
    1220           1 :         settings.basePaths.emplace_back("/somewhere");
    1221           1 :         const char code[] =
    1222             :             "struct Point\n"
    1223             :             "{\n"
    1224             :             "    // cppcheck-suppress unusedStructMember\n"
    1225             :             "    int x;\n"
    1226             :             "    // cppcheck-suppress unusedStructMember\n"
    1227             :             "    int y;\n"
    1228             :             "};";
    1229           1 :         ASSERT_EQUALS(0, cppCheck.check("/somewhere/test.cpp", code));
    1230           1 :         ASSERT_EQUALS("",errout_str());
    1231             :     }
    1232             : 
    1233           2 :     void suppressingSyntaxErrorsInternal(unsigned int (TestSuppressions::*check)(const char[], const std::string &)) { // syntaxErrors should be suppressible (#7076)
    1234           2 :         const char code[] = "if if\n";
    1235             : 
    1236           2 :         ASSERT_EQUALS(0, (this->*check)(code, "syntaxError:test.cpp:1"));
    1237           2 :         ASSERT_EQUALS("", errout_str());
    1238             :     }
    1239             : 
    1240           1 :     void suppressingSyntaxErrorsFiles() {
    1241           1 :         suppressingSyntaxErrorsInternal(&TestSuppressions::checkSuppressionFiles);
    1242           1 :     }
    1243             : 
    1244           1 :     void suppressingSyntaxErrorsFS() {
    1245           1 :         suppressingSyntaxErrorsInternal(&TestSuppressions::checkSuppressionFiles);
    1246           1 :     }
    1247             : 
    1248           2 :     void suppressingSyntaxErrorsInlineInternal(unsigned int (TestSuppressions::*check)(const char[], const std::string &)) { // syntaxErrors should be suppressible (#5917)
    1249           2 :         const char code[] = "double result(0.0);\n"
    1250             :                             "_asm\n"
    1251             :                             "{\n"
    1252             :                             "   // cppcheck-suppress syntaxError\n"
    1253             :                             "   push  EAX               ; save EAX for callers\n"
    1254             :                             "   mov   EAX,Real10        ; get the address pointed to by Real10\n"
    1255             :                             "   fld   TBYTE PTR [EAX]   ; load an extended real (10 bytes)\n"
    1256             :                             "   fstp  QWORD PTR result  ; store a double (8 bytes)\n"
    1257             :                             "   pop   EAX               ; restore EAX\n"
    1258             :                             "}";
    1259           2 :         ASSERT_EQUALS(0, (this->*check)(code, ""));
    1260           2 :         ASSERT_EQUALS("", errout_str());
    1261             :     }
    1262             : 
    1263           1 :     void suppressingSyntaxErrorsInlineFiles() {
    1264           1 :         suppressingSyntaxErrorsInlineInternal(&TestSuppressions::checkSuppressionFiles);
    1265           1 :     }
    1266             : 
    1267           1 :     void suppressingSyntaxErrorsInlineFS() {
    1268           1 :         suppressingSyntaxErrorsInlineInternal(&TestSuppressions::checkSuppressionFS);
    1269           1 :     }
    1270             : 
    1271           2 :     void suppressingSyntaxErrorsWhileFileReadInternal(unsigned int (TestSuppressions::*check)(const char[], const std::string &)) { // syntaxError while file read should be suppressible (PR #1333)
    1272           2 :         const char code[] = "CONST (genType, KS_CONST) genService[KS_CFG_NR_OF_NVM_BLOCKS] =\n"
    1273             :                             "{\n"
    1274             :                             "[!VAR \"BC\" = \"$BC + 1\"!][!//\n"
    1275             :                             "[!IF \"(as:modconf('Ks')[1]/KsGeneral/KsType = 'KS_CFG_TYPE_KS_MASTER') and\n"
    1276             :                             "      (as:modconf('Ks')[1]/KsGeneral/KsUseShe = 'true')\"!][!//\n"
    1277             :                             "  {\n"
    1278             :                             "      &varNB_GetErrorStatus,\n"
    1279             :                             "      &varNB_WriteBlock,\n"
    1280             :                             "      &varNB_ReadBlock\n"
    1281             :                             "  },\n"
    1282             :                             "[!VAR \"BC\" = \"$BC + 1\"!][!//\n"
    1283             :                             "[!ENDIF!][!//\n"
    1284             :                             "};";
    1285           2 :         ASSERT_EQUALS(0, (this->*check)(code, "syntaxError:test.cpp:4"));
    1286           2 :         ASSERT_EQUALS("", errout_str());
    1287             :     }
    1288             : 
    1289           1 :     void suppressingSyntaxErrorsWhileFileReadFiles() {
    1290           1 :         suppressingSyntaxErrorsWhileFileReadInternal(&TestSuppressions::checkSuppressionFiles);
    1291           1 :     }
    1292             : 
    1293           1 :     void suppressingSyntaxErrorsWhileFileReadFS() {
    1294           1 :         suppressingSyntaxErrorsWhileFileReadInternal(&TestSuppressions::checkSuppressionFiles);
    1295           1 :     }
    1296             : 
    1297           1 :     void symbol() const {
    1298           1 :         SuppressionList::Suppression s;
    1299           1 :         s.errorId = "foo";
    1300           1 :         s.symbolName = "array*";
    1301             : 
    1302           1 :         SuppressionList::ErrorMessage errorMsg;
    1303           1 :         errorMsg.errorId = "foo";
    1304           1 :         errorMsg.setFileName("test.cpp");
    1305           1 :         errorMsg.lineNumber = 123;
    1306           1 :         errorMsg.symbolNames = "";
    1307           1 :         ASSERT_EQUALS(false, s.isSuppressed(errorMsg));
    1308           1 :         errorMsg.symbolNames = "x\n";
    1309           1 :         ASSERT_EQUALS(false, s.isSuppressed(errorMsg));
    1310           1 :         errorMsg.symbolNames = "array1\n";
    1311           1 :         ASSERT_EQUALS(true, s.isSuppressed(errorMsg));
    1312             :         errorMsg.symbolNames = "x\n"
    1313           1 :                                "array2\n";
    1314           1 :         ASSERT_EQUALS(true, s.isSuppressed(errorMsg));
    1315             :         errorMsg.symbolNames = "array3\n"
    1316           1 :                                "x\n";
    1317           1 :         ASSERT_EQUALS(true, s.isSuppressed(errorMsg));
    1318             :     }
    1319             : 
    1320           2 :     void unusedFunctionInternal(unsigned int (TestSuppressions::*check)(const char[], const std::string &)) {
    1321           2 :         ASSERT_EQUALS(0, (this->*check)("void f() {}", "unusedFunction"));
    1322             :     }
    1323             : 
    1324           1 :     void unusedFunctionFiles() {
    1325           1 :         unusedFunctionInternal(&TestSuppressions::checkSuppressionFiles);
    1326           1 :     }
    1327             : 
    1328           1 :     void unusedFunctionFS() {
    1329           1 :         unusedFunctionInternal(&TestSuppressions::checkSuppressionFS);
    1330           1 :     }
    1331             : 
    1332           1 :     void suppressingSyntaxErrorAndExitCodeInternal(unsigned int (TestSuppressions::*check)(const char[], const std::string &)) {
    1333           1 :         const char code[] = "fi if;";
    1334             : 
    1335           1 :         ASSERT_EQUALS(0, (this->*check)(code, "*:test.cpp"));
    1336           1 :         ASSERT_EQUALS("", errout_str());
    1337             : 
    1338             :         // multi error in file, but only suppression one error
    1339           1 :         const char code2[] = "fi fi\n"
    1340             :                              "if if;";
    1341           1 :         ASSERT_EQUALS(1, (this->*check)(code2, "*:test.cpp:1"));  // suppress all error at line 1 of test.cpp
    1342           1 :         ASSERT_EQUALS("[test.cpp:2]: (error) syntax error\n", errout_str());
    1343             : 
    1344             :         // multi error in file, but only suppression one error (2)
    1345           1 :         const char code3[] = "void f(int x, int y){\n"
    1346             :                              "    int a = x/0;\n"
    1347             :                              "    int b = y/0;\n"
    1348             :                              "}\n"
    1349             :                              "f(0, 1);\n";
    1350           1 :         ASSERT_EQUALS(1, (this->*check)(code3, "zerodiv:test.cpp:3"));  // suppress 'zerodiv' at line 3 of test.cpp
    1351           1 :         ASSERT_EQUALS("[test.cpp:2]: (error) Division by zero.\n", errout_str());
    1352             :     }
    1353             : 
    1354           1 :     void suppressingSyntaxErrorAndExitCodeFiles() {
    1355           1 :         suppressingSyntaxErrorAndExitCodeInternal(&TestSuppressions::checkSuppressionFiles);
    1356           1 :     }
    1357             : 
    1358           1 :     static void suppressingSyntaxErrorAndExitCodeFS() {
    1359             :         // TODO
    1360             :         // suppressingSyntaxErrorAndExitCodeInternal(&TestSuppressions::checkSuppressionFS);
    1361           1 :     }
    1362             : 
    1363           1 :     void suppressingSyntaxErrorAndExitCodeMultiFileInternal(unsigned int (TestSuppressions::*check)(std::map<std::string, std::string> &f, const std::string &)) {
    1364             :         // multi files, but only suppression one
    1365           1 :         std::map<std::string, std::string> mfiles;
    1366           1 :         mfiles["test.cpp"] = "fi if;";
    1367           1 :         mfiles["test2.cpp"] = "fi if";
    1368           1 :         ASSERT_EQUALS(1, (this->*check)(mfiles, "*:test.cpp"));
    1369           1 :         ASSERT_EQUALS("[test2.cpp:1]: (error) syntax error\n", errout_str());
    1370             :     }
    1371             : 
    1372           1 :     void suppressingSyntaxErrorAndExitCodeMultiFileFiles() {
    1373           1 :         suppressingSyntaxErrorAndExitCodeMultiFileInternal(&TestSuppressions::checkSuppressionFiles);
    1374           1 :     }
    1375             : 
    1376           1 :     static void suppressingSyntaxErrorAndExitCodeMultiFileFS() {
    1377             :         // TODO
    1378             :         // suppressingSyntaxErrorAndExitCodeMultiFileInternal(&TestSuppressions::checkSuppressionFS);
    1379           1 :     }
    1380             : 
    1381           1 :     void suppressLocal() const {
    1382           1 :         SuppressionList suppressions;
    1383             :         std::istringstream s("errorid:test.cpp\n"
    1384           2 :                              "errorid2");
    1385           1 :         ASSERT_EQUALS("", suppressions.parseFile(s));
    1386           1 :         ASSERT_EQUALS(true, suppressions.isSuppressed(errorMessage("errorid", "test.cpp", 1)));
    1387           1 :         ASSERT_EQUALS(true, suppressions.isSuppressed(errorMessage("errorid", "test.cpp", 1), false));
    1388           1 :         ASSERT_EQUALS(false, suppressions.isSuppressed(errorMessage("errorid", "test2.cpp", 1)));
    1389           1 :         ASSERT_EQUALS(false, suppressions.isSuppressed(errorMessage("errorid", "test2.cpp", 1), false));
    1390           1 :         ASSERT_EQUALS(true, suppressions.isSuppressed(errorMessage("errorid2", "test.cpp", 1)));
    1391           1 :         ASSERT_EQUALS(false, suppressions.isSuppressed(errorMessage("errorid2", "test.cpp", 1), false));
    1392           1 :         ASSERT_EQUALS(true, suppressions.isSuppressed(errorMessage("errorid2", "test2.cpp", 1)));
    1393           1 :         ASSERT_EQUALS(false, suppressions.isSuppressed(errorMessage("errorid2", "test2.cpp", 1), false));
    1394             :     }
    1395             : 
    1396           1 :     void suppressUnmatchedSuppressions() {
    1397           1 :         std::list<SuppressionList::Suppression> suppressions;
    1398             : 
    1399             :         // No unmatched suppression
    1400           1 :         suppressions.clear();
    1401           1 :         ASSERT_EQUALS(false, SuppressionList::reportUnmatchedSuppressions(suppressions, *this));
    1402           1 :         ASSERT_EQUALS("", errout_str());
    1403             : 
    1404             :         // suppress all unmatchedSuppression
    1405           1 :         suppressions.clear();
    1406           1 :         suppressions.emplace_back("abc", "a.c", 10U);
    1407           1 :         suppressions.emplace_back("unmatchedSuppression", "*", SuppressionList::Suppression::NO_LINE);
    1408           1 :         ASSERT_EQUALS(false, SuppressionList::reportUnmatchedSuppressions(suppressions, *this));
    1409           1 :         ASSERT_EQUALS("", errout_str());
    1410             : 
    1411             :         // suppress all unmatchedSuppression (corresponds to "--suppress=unmatchedSuppression")
    1412           1 :         suppressions.clear();
    1413           1 :         suppressions.emplace_back("abc", "a.c", 10U);
    1414           1 :         suppressions.emplace_back("unmatchedSuppression", "", SuppressionList::Suppression::NO_LINE);
    1415           1 :         ASSERT_EQUALS(false, SuppressionList::reportUnmatchedSuppressions(suppressions, *this));
    1416           1 :         ASSERT_EQUALS("", errout_str());
    1417             : 
    1418             :         // suppress all unmatchedSuppression in a.c
    1419           1 :         suppressions.clear();
    1420           1 :         suppressions.emplace_back("abc", "a.c", 10U);
    1421           1 :         suppressions.emplace_back("unmatchedSuppression", "a.c", SuppressionList::Suppression::NO_LINE);
    1422           1 :         ASSERT_EQUALS(false, SuppressionList::reportUnmatchedSuppressions(suppressions, *this));
    1423           1 :         ASSERT_EQUALS("", errout_str());
    1424             : 
    1425             :         // suppress unmatchedSuppression in a.c at line 10
    1426           1 :         suppressions.clear();
    1427           1 :         suppressions.emplace_back("abc", "a.c", 10U);
    1428           1 :         suppressions.emplace_back("unmatchedSuppression", "a.c", 10U);
    1429           1 :         ASSERT_EQUALS(false, SuppressionList::reportUnmatchedSuppressions(suppressions, *this));
    1430           1 :         ASSERT_EQUALS("", errout_str());
    1431             : 
    1432             :         // don't suppress unmatchedSuppression when file is mismatching
    1433           1 :         suppressions.clear();
    1434           1 :         suppressions.emplace_back("abc", "a.c", 10U);
    1435           1 :         suppressions.emplace_back("unmatchedSuppression", "b.c", SuppressionList::Suppression::NO_LINE);
    1436           1 :         ASSERT_EQUALS(true, SuppressionList::reportUnmatchedSuppressions(suppressions, *this));
    1437           1 :         ASSERT_EQUALS("[a.c:10]: (information) Unmatched suppression: abc\n", errout_str());
    1438             : 
    1439             :         // don't suppress unmatchedSuppression when line is mismatching
    1440           1 :         suppressions.clear();
    1441           1 :         suppressions.emplace_back("abc", "a.c", 10U);
    1442           1 :         suppressions.emplace_back("unmatchedSuppression", "a.c", 1U);
    1443           1 :         ASSERT_EQUALS(true, SuppressionList::reportUnmatchedSuppressions(suppressions, *this));
    1444           1 :         ASSERT_EQUALS("[a.c:10]: (information) Unmatched suppression: abc\n", errout_str());
    1445             :     }
    1446             : 
    1447           1 :     void suppressionsParseXmlFile() const {
    1448             :         {
    1449             :             ScopedFile file("suppressparsexml.xml",
    1450             :                             "<suppressions>\n"
    1451             :                             "<suppress>\n"
    1452             :                             "<id>uninitvar</id>\n"
    1453             :                             "<fileName>file.c</fileName>\n"
    1454             :                             "<lineNumber>10</lineNumber>\n"
    1455             :                             "<symbolName>sym</symbolName>\n"
    1456             :                             "</suppress>\n"
    1457           4 :                             "</suppressions>");
    1458             : 
    1459           1 :             SuppressionList supprList;
    1460           1 :             ASSERT_EQUALS("", supprList.parseXmlFile(file.path().c_str()));
    1461           1 :             const auto& supprs = supprList.getSuppressions();
    1462           1 :             ASSERT_EQUALS(1, supprs.size());
    1463           1 :             const auto& suppr = *supprs.cbegin();
    1464           1 :             ASSERT_EQUALS("uninitvar", suppr.errorId);
    1465           1 :             ASSERT_EQUALS("file.c", suppr.fileName);
    1466           1 :             ASSERT_EQUALS(10, suppr.lineNumber);
    1467           1 :             ASSERT_EQUALS("sym", suppr.symbolName);
    1468             :         }
    1469             : 
    1470             :         // no file specified
    1471             :         {
    1472           1 :             SuppressionList supprList;
    1473           1 :             ASSERT_EQUALS("failed to load suppressions XML '' (XML_ERROR_FILE_NOT_FOUND).", supprList.parseXmlFile(""));
    1474             :         }
    1475             : 
    1476             :         // missing file
    1477             :         {
    1478           1 :             SuppressionList supprList;
    1479           1 :             ASSERT_EQUALS("failed to load suppressions XML 'suppressparsexml.xml' (XML_ERROR_FILE_NOT_FOUND).", supprList.parseXmlFile("suppressparsexml.xml"));
    1480             :         }
    1481             : 
    1482             :         // empty file
    1483             :         {
    1484             :             ScopedFile file("suppressparsexml.xml",
    1485           4 :                             "");
    1486             : 
    1487           1 :             SuppressionList supprList;
    1488           1 :             ASSERT_EQUALS("failed to load suppressions XML 'suppressparsexml.xml' (XML_ERROR_EMPTY_DOCUMENT).", supprList.parseXmlFile(file.path().c_str()));
    1489             :         }
    1490             : 
    1491             :         // wrong root node
    1492             :         {
    1493             :             ScopedFile file("suppressparsexml.xml",
    1494           4 :                             "<suppress/>\n");
    1495             : 
    1496           1 :             SuppressionList supprList;
    1497           1 :             ASSERT_EQUALS("", supprList.parseXmlFile(file.path().c_str()));
    1498             :         }
    1499             : 
    1500             :         // no root node
    1501             :         {
    1502             :             ScopedFile file("suppressparsexml.xml",
    1503           4 :                             "<?xml version=\"1.0\"?>\n");
    1504             : 
    1505           1 :             SuppressionList supprList;
    1506           1 :             ASSERT_EQUALS("failed to load suppressions XML 'suppressparsexml.xml' (no root node found).", supprList.parseXmlFile(file.path().c_str()));
    1507             :         }
    1508             : 
    1509             :         // unknown element
    1510             :         {
    1511             :             ScopedFile file("suppressparsexml.xml",
    1512             :                             "<suppressions>\n"
    1513             :                             "<suppress>\n"
    1514             :                             "<eid>uninitvar</eid>\n"
    1515             :                             "</suppress>\n"
    1516           4 :                             "</suppressions>");
    1517             : 
    1518           1 :             SuppressionList supprList;
    1519           1 :             ASSERT_EQUALS("unknown element 'eid' in suppressions XML 'suppressparsexml.xml', expected id/fileName/lineNumber/symbolName/hash.", supprList.parseXmlFile(file.path().c_str()));
    1520             :         }
    1521             :     }
    1522             : };
    1523             : 
    1524             : REGISTER_TEST(TestSuppressions)

Generated by: LCOV version 1.14