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)
|