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 "cmdlinelogger.h"
20 : #include "cmdlineparser.h"
21 : #include "config.h"
22 : #include "cppcheckexecutor.h"
23 : #include "errorlogger.h"
24 : #include "errortypes.h"
25 : #include "helpers.h"
26 : #include "path.h"
27 : #include "platform.h"
28 : #include "redirect.h"
29 : #include "settings.h"
30 : #include "standards.h"
31 : #include "suppressions.h"
32 : #include "fixture.h"
33 : #include "timer.h"
34 : #include "utils.h"
35 :
36 : #include <cstdio>
37 : #include <list>
38 : #include <memory>
39 : #include <set>
40 : #include <stdexcept>
41 : #include <string>
42 : #include <unordered_set>
43 : #include <vector>
44 :
45 : class TestCmdlineParser : public TestFixture {
46 : public:
47 1 : TestCmdlineParser() : TestFixture("TestCmdlineParser")
48 1 : {}
49 :
50 : private:
51 : class CmdLineLoggerTest : public CmdLineLogger
52 : {
53 : public:
54 252 : CmdLineLoggerTest() = default;
55 :
56 92 : void printMessage(const std::string &message) override
57 : {
58 92 : printInternal("cppcheck: " + message + '\n');
59 92 : }
60 :
61 87 : void printError(const std::string &message) override
62 : {
63 87 : printMessage("error: " + message);
64 87 : }
65 :
66 11 : void printRaw(const std::string &message) override
67 : {
68 11 : printInternal(message + '\n');
69 11 : }
70 :
71 111 : std::string str()
72 : {
73 111 : std::string s;
74 111 : std::swap(buf, s);
75 111 : return s;
76 : }
77 :
78 252 : void destroy()
79 : {
80 252 : if (!buf.empty())
81 0 : throw std::runtime_error("unconsumed messages: " + buf);
82 252 : }
83 :
84 : private:
85 103 : void printInternal(const std::string &message)
86 : {
87 103 : buf += message;
88 103 : }
89 :
90 : std::string buf;
91 : };
92 :
93 : std::unique_ptr<CmdLineLoggerTest> logger;
94 : std::unique_ptr<Settings> settings;
95 : std::unique_ptr<CmdLineParser> parser;
96 :
97 252 : void prepareTestInternal() override {
98 252 : logger.reset(new CmdLineLoggerTest());
99 252 : settings.reset(new Settings());
100 252 : parser.reset(new CmdLineParser(*logger, *settings, settings->supprs));
101 252 : }
102 :
103 252 : void teardownTestInternal() override {
104 252 : logger->destroy();
105 252 : }
106 :
107 8 : void asPremium() {
108 : // set this so we think it is the premium
109 8 : settings->cppcheckCfgProductName = "Cppcheck Premium 0.0.0";
110 8 : }
111 :
112 1 : void run() override {
113 1 : TEST_CASE(nooptions);
114 1 : TEST_CASE(helpshort);
115 1 : TEST_CASE(helpshortExclusive);
116 1 : TEST_CASE(helplong);
117 1 : TEST_CASE(helplongExclusive);
118 1 : TEST_CASE(version);
119 1 : TEST_CASE(versionWithCfg);
120 1 : TEST_CASE(versionExclusive);
121 1 : TEST_CASE(versionWithInvalidCfg);
122 1 : TEST_CASE(checkVersionCorrect);
123 1 : TEST_CASE(checkVersionIncorrect);
124 1 : TEST_CASE(onefile);
125 1 : TEST_CASE(onepath);
126 1 : TEST_CASE(optionwithoutfile);
127 1 : TEST_CASE(verboseshort);
128 1 : TEST_CASE(verboselong);
129 1 : TEST_CASE(debugSimplified);
130 1 : TEST_CASE(debugwarnings);
131 1 : TEST_CASE(forceshort);
132 1 : TEST_CASE(forcelong);
133 1 : TEST_CASE(relativePaths1);
134 1 : TEST_CASE(relativePaths2);
135 1 : TEST_CASE(relativePaths3);
136 1 : TEST_CASE(relativePaths4);
137 1 : TEST_CASE(quietshort);
138 1 : TEST_CASE(quietlong);
139 1 : TEST_CASE(defines_noarg);
140 1 : TEST_CASE(defines_noarg2);
141 1 : TEST_CASE(defines_noarg3);
142 1 : TEST_CASE(defines);
143 1 : TEST_CASE(defines2);
144 1 : TEST_CASE(defines3);
145 1 : TEST_CASE(defines4);
146 1 : TEST_CASE(enforceLanguage1);
147 1 : TEST_CASE(enforceLanguage2);
148 1 : TEST_CASE(enforceLanguage3);
149 1 : TEST_CASE(enforceLanguage4);
150 1 : TEST_CASE(enforceLanguage5);
151 1 : TEST_CASE(enforceLanguage6);
152 1 : TEST_CASE(enforceLanguage7);
153 1 : TEST_CASE(includesnopath);
154 1 : TEST_CASE(includes);
155 1 : TEST_CASE(includesslash);
156 1 : TEST_CASE(includesbackslash);
157 1 : TEST_CASE(includesnospace);
158 1 : TEST_CASE(includes2);
159 1 : TEST_CASE(includesFile);
160 1 : TEST_CASE(includesFileNoFile);
161 1 : TEST_CASE(configExcludesFile);
162 1 : TEST_CASE(configExcludesFileNoFile);
163 1 : TEST_CASE(enabledAll);
164 1 : TEST_CASE(enabledStyle);
165 1 : TEST_CASE(enabledPerformance);
166 1 : TEST_CASE(enabledPortability);
167 1 : TEST_CASE(enabledInformation);
168 1 : TEST_CASE(enabledUnusedFunction);
169 1 : TEST_CASE(enabledMissingInclude);
170 1 : TEST_CASE(disabledMissingIncludeWithInformation);
171 1 : TEST_CASE(enabledMissingIncludeWithInformation);
172 1 : TEST_CASE(enabledMissingIncludeWithInformationReverseOrder);
173 : #ifdef CHECK_INTERNAL
174 : TEST_CASE(enabledInternal);
175 : #endif
176 1 : TEST_CASE(enabledMultiple);
177 1 : TEST_CASE(enabledInvalid);
178 1 : TEST_CASE(enabledError);
179 1 : TEST_CASE(enabledEmpty);
180 1 : TEST_CASE(disableAll);
181 1 : TEST_CASE(disableMultiple);
182 1 : TEST_CASE(disableStylePartial);
183 1 : TEST_CASE(disableInformationPartial);
184 1 : TEST_CASE(disableInformationPartial2);
185 1 : TEST_CASE(disableInvalid);
186 1 : TEST_CASE(disableError);
187 1 : TEST_CASE(disableEmpty);
188 1 : TEST_CASE(inconclusive);
189 1 : TEST_CASE(errorExitcode);
190 1 : TEST_CASE(errorExitcodeMissing);
191 1 : TEST_CASE(errorExitcodeStr);
192 1 : TEST_CASE(exitcodeSuppressionsOld);
193 1 : TEST_CASE(exitcodeSuppressions);
194 1 : TEST_CASE(exitcodeSuppressionsNoFile);
195 1 : TEST_CASE(fileFilterStdin);
196 1 : TEST_CASE(fileList);
197 1 : TEST_CASE(fileListNoFile);
198 1 : TEST_CASE(fileListStdin);
199 1 : TEST_CASE(fileListInvalid);
200 1 : TEST_CASE(inlineSuppr);
201 1 : TEST_CASE(jobs);
202 1 : TEST_CASE(jobs2);
203 1 : TEST_CASE(jobsMissingCount);
204 1 : TEST_CASE(jobsInvalid);
205 1 : TEST_CASE(jobsNoJobs);
206 1 : TEST_CASE(jobsTooBig);
207 1 : TEST_CASE(maxConfigs);
208 1 : TEST_CASE(maxConfigsMissingCount);
209 1 : TEST_CASE(maxConfigsInvalid);
210 1 : TEST_CASE(maxConfigsTooSmall);
211 1 : TEST_CASE(premiumOptions1);
212 1 : TEST_CASE(premiumOptions2);
213 1 : TEST_CASE(premiumOptions3);
214 1 : TEST_CASE(premiumOptions4);
215 1 : TEST_CASE(premiumOptions5);
216 1 : TEST_CASE(premiumOptionsInvalid1);
217 1 : TEST_CASE(premiumOptionsInvalid2);
218 1 : TEST_CASE(premiumSafety);
219 1 : TEST_CASE(reportProgress1);
220 1 : TEST_CASE(reportProgress2);
221 1 : TEST_CASE(reportProgress3);
222 1 : TEST_CASE(reportProgress4);
223 1 : TEST_CASE(reportProgress5);
224 1 : TEST_CASE(stdc99);
225 1 : TEST_CASE(stdcpp11);
226 1 : TEST_CASE(stdunknown1);
227 1 : TEST_CASE(stdunknown2);
228 1 : TEST_CASE(platformWin64);
229 1 : TEST_CASE(platformWin32A);
230 1 : TEST_CASE(platformWin32W);
231 1 : TEST_CASE(platformUnix32);
232 1 : TEST_CASE(platformUnix32Unsigned);
233 1 : TEST_CASE(platformUnix64);
234 1 : TEST_CASE(platformUnix64Unsigned);
235 1 : TEST_CASE(platformNative);
236 1 : TEST_CASE(platformUnspecified);
237 1 : TEST_CASE(platformPlatformFile);
238 1 : TEST_CASE(platformUnknown);
239 1 : TEST_CASE(plistEmpty);
240 1 : TEST_CASE(plistDoesNotExist);
241 1 : TEST_CASE(suppressionsOld);
242 1 : TEST_CASE(suppressions);
243 1 : TEST_CASE(suppressionsNoFile1);
244 1 : TEST_CASE(suppressionsNoFile2);
245 1 : TEST_CASE(suppressionsNoFile3);
246 1 : TEST_CASE(suppressionSingle);
247 1 : TEST_CASE(suppressionSingleFile);
248 1 : TEST_CASE(suppressionTwo);
249 1 : TEST_CASE(suppressionTwoSeparate);
250 1 : TEST_CASE(templates);
251 1 : TEST_CASE(templatesGcc);
252 1 : TEST_CASE(templatesVs);
253 1 : TEST_CASE(templatesEdit);
254 1 : TEST_CASE(templatesCppcheck1);
255 1 : TEST_CASE(templatesDaca2);
256 1 : TEST_CASE(templatesSelfcheck);
257 1 : TEST_CASE(templatesSimple);
258 1 : TEST_CASE(templatesNoPlaceholder);
259 1 : TEST_CASE(templateFormatInvalid);
260 1 : TEST_CASE(templateFormatEmpty);
261 1 : TEST_CASE(templateLocationInvalid);
262 1 : TEST_CASE(templateLocationEmpty);
263 1 : TEST_CASE(xml);
264 1 : TEST_CASE(xmlver2);
265 1 : TEST_CASE(xmlver2both);
266 1 : TEST_CASE(xmlver2both2);
267 1 : TEST_CASE(xmlverunknown);
268 1 : TEST_CASE(xmlverinvalid);
269 1 : TEST_CASE(doc);
270 1 : TEST_CASE(docExclusive);
271 1 : TEST_CASE(showtimeFile);
272 1 : TEST_CASE(showtimeFileTotal);
273 1 : TEST_CASE(showtimeTop5);
274 1 : TEST_CASE(showtimeTop5File);
275 1 : TEST_CASE(showtimeTop5Summary);
276 1 : TEST_CASE(showtimeNone);
277 1 : TEST_CASE(showtimeEmpty);
278 1 : TEST_CASE(showtimeInvalid);
279 1 : TEST_CASE(errorlist);
280 1 : TEST_CASE(errorlistWithCfg);
281 1 : TEST_CASE(errorlistExclusive);
282 1 : TEST_CASE(errorlistWithInvalidCfg);
283 1 : TEST_CASE(ignorepathsnopath);
284 : #if defined(USE_WINDOWS_SEH) || defined(USE_UNIX_SIGNAL_HANDLING)
285 1 : TEST_CASE(exceptionhandling);
286 1 : TEST_CASE(exceptionhandling2);
287 1 : TEST_CASE(exceptionhandling3);
288 1 : TEST_CASE(exceptionhandlingInvalid);
289 1 : TEST_CASE(exceptionhandlingInvalid2);
290 : #else
291 : TEST_CASE(exceptionhandlingNotSupported);
292 : TEST_CASE(exceptionhandlingNotSupported2);
293 : #endif
294 1 : TEST_CASE(clang);
295 1 : TEST_CASE(clang2);
296 1 : TEST_CASE(clangInvalid);
297 1 : TEST_CASE(valueFlowMaxIterations);
298 1 : TEST_CASE(valueFlowMaxIterations2);
299 1 : TEST_CASE(valueFlowMaxIterationsInvalid);
300 1 : TEST_CASE(valueFlowMaxIterationsInvalid2);
301 1 : TEST_CASE(valueFlowMaxIterationsInvalid3);
302 1 : TEST_CASE(checksMaxTime);
303 1 : TEST_CASE(checksMaxTime2);
304 1 : TEST_CASE(checksMaxTimeInvalid);
305 : #ifdef HAS_THREADING_MODEL_FORK
306 1 : TEST_CASE(loadAverage);
307 1 : TEST_CASE(loadAverage2);
308 1 : TEST_CASE(loadAverageInvalid);
309 : #else
310 : TEST_CASE(loadAverageNotSupported);
311 : #endif
312 1 : TEST_CASE(maxCtuDepth);
313 1 : TEST_CASE(maxCtuDepthInvalid);
314 1 : TEST_CASE(performanceValueflowMaxTime);
315 1 : TEST_CASE(performanceValueflowMaxTimeInvalid);
316 1 : TEST_CASE(performanceValueFlowMaxIfCount);
317 1 : TEST_CASE(performanceValueFlowMaxIfCountInvalid);
318 1 : TEST_CASE(templateMaxTime);
319 1 : TEST_CASE(templateMaxTimeInvalid);
320 1 : TEST_CASE(templateMaxTimeInvalid2);
321 1 : TEST_CASE(typedefMaxTime);
322 1 : TEST_CASE(typedefMaxTimeInvalid);
323 1 : TEST_CASE(typedefMaxTimeInvalid2);
324 1 : TEST_CASE(templateMaxTime);
325 1 : TEST_CASE(templateMaxTime);
326 1 : TEST_CASE(project);
327 1 : TEST_CASE(projectMultiple);
328 1 : TEST_CASE(projectAndSource);
329 1 : TEST_CASE(projectEmpty);
330 1 : TEST_CASE(projectMissing);
331 1 : TEST_CASE(projectNoPaths);
332 1 : TEST_CASE(addon);
333 1 : TEST_CASE(addonMissing);
334 : #ifdef HAVE_RULES
335 : TEST_CASE(rule);
336 : TEST_CASE(ruleMissingPattern);
337 : #else
338 1 : TEST_CASE(ruleNotSupported);
339 : #endif
340 : #ifdef HAVE_RULES
341 : TEST_CASE(ruleFileMulti);
342 : TEST_CASE(ruleFileSingle);
343 : TEST_CASE(ruleFileEmpty);
344 : TEST_CASE(ruleFileMissing);
345 : TEST_CASE(ruleFileInvalid);
346 : TEST_CASE(ruleFileNoRoot);
347 : TEST_CASE(ruleFileEmptyElements1);
348 : TEST_CASE(ruleFileEmptyElements2);
349 : TEST_CASE(ruleFileUnknownElement1);
350 : TEST_CASE(ruleFileUnknownElement2);
351 : TEST_CASE(ruleFileMissingTokenList);
352 : TEST_CASE(ruleFileUnknownTokenList);
353 : TEST_CASE(ruleFileMissingId);
354 : TEST_CASE(ruleFileInvalidSeverity1);
355 : TEST_CASE(ruleFileInvalidSeverity2);
356 : #else
357 1 : TEST_CASE(ruleFileNotSupported);
358 : #endif
359 1 : TEST_CASE(signedChar);
360 1 : TEST_CASE(signedChar2);
361 1 : TEST_CASE(unsignedChar);
362 1 : TEST_CASE(unsignedChar2);
363 1 : TEST_CASE(signedCharUnsignedChar);
364 1 : TEST_CASE(library);
365 1 : TEST_CASE(libraryMissing);
366 1 : TEST_CASE(suppressXml);
367 1 : TEST_CASE(suppressXmlEmpty);
368 1 : TEST_CASE(suppressXmlMissing);
369 1 : TEST_CASE(suppressXmlInvalid);
370 1 : TEST_CASE(suppressXmlNoRoot);
371 1 : TEST_CASE(executorDefault);
372 1 : TEST_CASE(executorAuto);
373 1 : TEST_CASE(executorAutoNoJobs);
374 : #if defined(HAS_THREADING_MODEL_THREAD)
375 1 : TEST_CASE(executorThread);
376 1 : TEST_CASE(executorThreadNoJobs);
377 : #else
378 : TEST_CASE(executorThreadNotSupported);
379 : #endif
380 : #if defined(HAS_THREADING_MODEL_FORK)
381 1 : TEST_CASE(executorProcess);
382 1 : TEST_CASE(executorProcessNoJobs);
383 : #else
384 : TEST_CASE(executorProcessNotSupported);
385 : #endif
386 1 : TEST_CASE(checkLevelDefault);
387 1 : TEST_CASE(checkLevelNormal);
388 1 : TEST_CASE(checkLevelExhaustive);
389 1 : TEST_CASE(checkLevelUnknown);
390 :
391 1 : TEST_CASE(ignorepaths1);
392 1 : TEST_CASE(ignorepaths2);
393 1 : TEST_CASE(ignorepaths3);
394 1 : TEST_CASE(ignorepaths4);
395 1 : TEST_CASE(ignorefilepaths1);
396 1 : TEST_CASE(ignorefilepaths2);
397 1 : TEST_CASE(ignorefilepaths3);
398 :
399 1 : TEST_CASE(checkconfig);
400 1 : TEST_CASE(unknownParam);
401 :
402 1 : TEST_CASE(undefs_noarg);
403 1 : TEST_CASE(undefs_noarg2);
404 1 : TEST_CASE(undefs_noarg3);
405 1 : TEST_CASE(undefs);
406 1 : TEST_CASE(undefs2);
407 :
408 1 : TEST_CASE(cppcheckBuildDirExistent);
409 1 : TEST_CASE(cppcheckBuildDirNonExistent);
410 1 : TEST_CASE(cppcheckBuildDirEmpty);
411 :
412 1 : TEST_CASE(invalidCppcheckCfg);
413 1 : }
414 :
415 1 : void nooptions() {
416 1 : REDIRECT;
417 1 : const char * const argv[] = {"cppcheck"};
418 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Exit, parser->parseFromArgs(1, argv));
419 1 : ASSERT(startsWith(logger->str(), "Cppcheck - A tool for static C/C++ code analysis"));
420 : }
421 :
422 1 : void helpshort() {
423 1 : REDIRECT;
424 1 : const char * const argv[] = {"cppcheck", "-h"};
425 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Exit, parser->parseFromArgs(2, argv));
426 1 : ASSERT(startsWith(logger->str(), "Cppcheck - A tool for static C/C++ code analysis"));
427 : }
428 :
429 1 : void helpshortExclusive() {
430 1 : REDIRECT;
431 1 : const char * const argv[] = {"cppcheck", "--library=missing", "-h"};
432 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Exit, parser->parseFromArgs(3, argv));
433 1 : ASSERT(startsWith(logger->str(), "Cppcheck - A tool for static C/C++ code analysis"));
434 : }
435 :
436 1 : void helplong() {
437 1 : REDIRECT;
438 1 : const char * const argv[] = {"cppcheck", "--help"};
439 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Exit, parser->parseFromArgs(2, argv));
440 1 : ASSERT(startsWith(logger->str(), "Cppcheck - A tool for static C/C++ code analysis"));
441 : }
442 :
443 1 : void helplongExclusive() {
444 1 : REDIRECT;
445 1 : const char * const argv[] = {"cppcheck", "--library=missing", "--help"};
446 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Exit, parser->parseFromArgs(3, argv));
447 1 : ASSERT(startsWith(logger->str(), "Cppcheck - A tool for static C/C++ code analysis"));
448 : }
449 :
450 1 : void version() {
451 1 : REDIRECT;
452 1 : const char * const argv[] = {"cppcheck", "--version"};
453 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Exit, parser->parseFromArgs(2, argv));
454 1 : ASSERT(logger->str().compare(0, 11, "Cppcheck 2.") == 0);
455 : }
456 :
457 1 : void versionWithCfg() {
458 1 : REDIRECT;
459 2 : ScopedFile file(Path::join(Path::getPathFromFilename(Path::getCurrentExecutablePath("")), "cppcheck.cfg"),
460 : "{\n"
461 : "\"productName\": \"The Product\""
462 4 : "}\n");
463 1 : const char * const argv[] = {"cppcheck", "--version"};
464 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Exit, parser->parseFromArgs(2, argv));
465 : // TODO: somehow the config is not loaded on some systems
466 1 : (void)logger->str(); //ASSERT_EQUALS("The Product\n", logger->str()); // TODO: include version?
467 : }
468 :
469 : // TODO: test --version with extraVersion
470 :
471 1 : void versionExclusive() {
472 1 : REDIRECT;
473 1 : const char * const argv[] = {"cppcheck", "--library=missing", "--version"};
474 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Exit, parser->parseFromArgs(3, argv));
475 1 : ASSERT(logger->str().compare(0, 11, "Cppcheck 2.") == 0);
476 : }
477 :
478 1 : void versionWithInvalidCfg() {
479 1 : REDIRECT;
480 2 : ScopedFile file(Path::join(Path::getPathFromFilename(Path::getCurrentExecutablePath("")), "cppcheck.cfg"),
481 4 : "{\n");
482 1 : const char * const argv[] = {"cppcheck", "--version"};
483 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv));
484 1 : ASSERT_EQUALS("cppcheck: error: could not load cppcheck.cfg - not a valid JSON - syntax error at line 2 near: \n", logger->str());
485 : }
486 :
487 1 : void checkVersionCorrect() {
488 1 : REDIRECT;
489 1 : const std::string currentVersion = parser->getVersion();
490 1 : const std::string checkVersion = "--check-version=" + currentVersion;
491 1 : const char * const argv[] = {"cppcheck", checkVersion.c_str(), "file.cpp"};
492 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
493 : }
494 :
495 1 : void checkVersionIncorrect() {
496 1 : REDIRECT;
497 1 : const char * const argv[] = {"cppcheck", "--check-version=Cppcheck 2.0", "file.cpp"};
498 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
499 1 : ASSERT_EQUALS("cppcheck: error: --check-version check failed. Aborting.\n", logger->str());
500 : }
501 :
502 1 : void onefile() {
503 1 : REDIRECT;
504 1 : const char * const argv[] = {"cppcheck", "file.cpp"};
505 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(2, argv));
506 1 : ASSERT_EQUALS(1, (int)parser->getPathNames().size());
507 1 : ASSERT_EQUALS("file.cpp", parser->getPathNames().at(0));
508 : }
509 :
510 1 : void onepath() {
511 1 : REDIRECT;
512 1 : const char * const argv[] = {"cppcheck", "src"};
513 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(2, argv));
514 1 : ASSERT_EQUALS(1, (int)parser->getPathNames().size());
515 1 : ASSERT_EQUALS("src", parser->getPathNames().at(0));
516 : }
517 :
518 1 : void optionwithoutfile() {
519 1 : REDIRECT;
520 1 : const char * const argv[] = {"cppcheck", "-v"};
521 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv));
522 1 : ASSERT_EQUALS(0, (int)parser->getPathNames().size());
523 1 : ASSERT_EQUALS("cppcheck: error: no C or C++ source files found.\n", logger->str());
524 : }
525 :
526 1 : void verboseshort() {
527 1 : REDIRECT;
528 1 : const char * const argv[] = {"cppcheck", "-v", "file.cpp"};
529 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
530 1 : ASSERT_EQUALS(true, settings->verbose);
531 : }
532 :
533 1 : void verboselong() {
534 1 : REDIRECT;
535 1 : const char * const argv[] = {"cppcheck", "--verbose", "file.cpp"};
536 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
537 1 : ASSERT_EQUALS(true, settings->verbose);
538 : }
539 :
540 1 : void debugSimplified() {
541 1 : REDIRECT;
542 1 : const char * const argv[] = {"cppcheck", "--debug-simplified", "file.cpp"};
543 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
544 1 : ASSERT_EQUALS(true, settings->debugSimplified);
545 : }
546 :
547 1 : void debugwarnings() {
548 1 : REDIRECT;
549 1 : const char * const argv[] = {"cppcheck", "--debug-warnings", "file.cpp"};
550 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
551 1 : ASSERT_EQUALS(true, settings->debugwarnings);
552 : }
553 :
554 1 : void forceshort() {
555 1 : REDIRECT;
556 1 : const char * const argv[] = {"cppcheck", "-f", "file.cpp"};
557 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
558 1 : ASSERT_EQUALS(true, settings->force);
559 : }
560 :
561 1 : void forcelong() {
562 1 : REDIRECT;
563 1 : const char * const argv[] = {"cppcheck", "--force", "file.cpp"};
564 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
565 1 : ASSERT_EQUALS(true, settings->force);
566 : }
567 :
568 1 : void relativePaths1() {
569 1 : REDIRECT;
570 1 : const char * const argv[] = {"cppcheck", "-rp", "file.cpp"};
571 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
572 1 : ASSERT_EQUALS(true, settings->relativePaths);
573 : }
574 :
575 1 : void relativePaths2() {
576 1 : REDIRECT;
577 1 : const char * const argv[] = {"cppcheck", "--relative-paths", "file.cpp"};
578 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
579 1 : ASSERT_EQUALS(true, settings->relativePaths);
580 : }
581 :
582 1 : void relativePaths3() {
583 1 : REDIRECT;
584 1 : const char * const argv[] = {"cppcheck", "-rp=C:/foo;C:\\bar", "file.cpp"};
585 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
586 1 : ASSERT_EQUALS(true, settings->relativePaths);
587 1 : ASSERT_EQUALS(2, settings->basePaths.size());
588 1 : ASSERT_EQUALS("C:/foo", settings->basePaths[0]);
589 1 : ASSERT_EQUALS("C:/bar", settings->basePaths[1]);
590 : }
591 :
592 1 : void relativePaths4() {
593 1 : REDIRECT;
594 1 : const char * const argv[] = {"cppcheck", "--relative-paths=C:/foo;C:\\bar", "file.cpp"};
595 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
596 1 : ASSERT_EQUALS(true, settings->relativePaths);
597 1 : ASSERT_EQUALS(2, settings->basePaths.size());
598 1 : ASSERT_EQUALS("C:/foo", settings->basePaths[0]);
599 1 : ASSERT_EQUALS("C:/bar", settings->basePaths[1]);
600 : }
601 :
602 1 : void quietshort() {
603 1 : REDIRECT;
604 1 : const char * const argv[] = {"cppcheck", "-q", "file.cpp"};
605 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
606 1 : ASSERT_EQUALS(true, settings->quiet);
607 : }
608 :
609 1 : void quietlong() {
610 1 : REDIRECT;
611 1 : const char * const argv[] = {"cppcheck", "--quiet", "file.cpp"};
612 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
613 1 : ASSERT_EQUALS(true, settings->quiet);
614 : }
615 :
616 1 : void defines_noarg() {
617 1 : REDIRECT;
618 1 : const char * const argv[] = {"cppcheck", "-D"};
619 : // Fails since -D has no param
620 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv));
621 1 : ASSERT_EQUALS("cppcheck: error: argument to '-D' is missing.\n", logger->str());
622 : }
623 :
624 1 : void defines_noarg2() {
625 1 : REDIRECT;
626 1 : const char * const argv[] = {"cppcheck", "-D", "-v", "file.cpp"};
627 : // Fails since -D has no param
628 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(4, argv));
629 1 : ASSERT_EQUALS("cppcheck: error: argument to '-D' is missing.\n", logger->str());
630 : }
631 :
632 1 : void defines_noarg3() {
633 1 : REDIRECT;
634 1 : const char * const argv[] = {"cppcheck", "-D", "--quiet", "file.cpp"};
635 : // Fails since -D has no param
636 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(4, argv));
637 1 : ASSERT_EQUALS("cppcheck: error: argument to '-D' is missing.\n", logger->str());
638 : }
639 :
640 1 : void defines() {
641 1 : REDIRECT;
642 1 : const char * const argv[] = {"cppcheck", "-D_WIN32", "file.cpp"};
643 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
644 1 : ASSERT_EQUALS("_WIN32=1", settings->userDefines);
645 : }
646 :
647 1 : void defines2() {
648 1 : REDIRECT;
649 1 : const char * const argv[] = {"cppcheck", "-D_WIN32", "-DNODEBUG", "file.cpp"};
650 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv));
651 1 : ASSERT_EQUALS("_WIN32=1;NODEBUG=1", settings->userDefines);
652 : }
653 :
654 1 : void defines3() {
655 1 : REDIRECT;
656 1 : const char * const argv[] = {"cppcheck", "-D", "DEBUG", "file.cpp"};
657 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv));
658 1 : ASSERT_EQUALS("DEBUG=1", settings->userDefines);
659 : }
660 :
661 1 : void defines4() {
662 1 : REDIRECT;
663 1 : const char * const argv[] = {"cppcheck", "-DDEBUG=", "file.cpp"}; // #5137 - defining empty macro
664 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
665 1 : ASSERT_EQUALS("DEBUG=", settings->userDefines);
666 : }
667 :
668 1 : void enforceLanguage1() {
669 1 : REDIRECT;
670 1 : const char * const argv[] = {"cppcheck", "file.cpp"};
671 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(2, argv));
672 1 : ASSERT_EQUALS(Standards::Language::None, settings->enforcedLang);
673 : }
674 :
675 1 : void enforceLanguage2() {
676 1 : REDIRECT;
677 1 : const char * const argv[] = {"cppcheck", "-x", "c++", "file.cpp"};
678 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv));
679 1 : ASSERT_EQUALS(Standards::Language::CPP, settings->enforcedLang);
680 : }
681 :
682 1 : void enforceLanguage3() {
683 1 : REDIRECT;
684 1 : const char * const argv[] = {"cppcheck", "-x"};
685 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv));
686 1 : ASSERT_EQUALS("cppcheck: error: no language given to '-x' option.\n", logger->str());
687 : }
688 :
689 1 : void enforceLanguage4() {
690 1 : REDIRECT;
691 1 : const char * const argv[] = {"cppcheck", "-x", "--inconclusive", "file.cpp"};
692 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(4, argv));
693 1 : ASSERT_EQUALS("cppcheck: error: no language given to '-x' option.\n", logger->str());
694 : }
695 :
696 1 : void enforceLanguage5() {
697 1 : REDIRECT;
698 1 : const char * const argv[] = {"cppcheck", "--language=c++", "file.cpp"};
699 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
700 1 : ASSERT_EQUALS(Standards::Language::CPP, settings->enforcedLang);
701 : }
702 :
703 1 : void enforceLanguage6() {
704 1 : REDIRECT;
705 1 : const char * const argv[] = {"cppcheck", "--language=c", "file.cpp"};
706 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
707 1 : ASSERT_EQUALS(Standards::Language::C, settings->enforcedLang);
708 : }
709 :
710 1 : void enforceLanguage7() {
711 1 : REDIRECT;
712 1 : const char * const argv[] = {"cppcheck", "--language=unknownLanguage", "file.cpp"};
713 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
714 1 : ASSERT_EQUALS("cppcheck: error: unknown language 'unknownLanguage' enforced.\n", logger->str());
715 : }
716 :
717 1 : void includesnopath() {
718 1 : REDIRECT;
719 1 : const char * const argv[] = {"cppcheck", "-I"};
720 : // Fails since -I has no param
721 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv));
722 1 : ASSERT_EQUALS("cppcheck: error: argument to '-I' is missing.\n", logger->str());
723 : }
724 :
725 1 : void includes() {
726 1 : REDIRECT;
727 1 : const char * const argv[] = {"cppcheck", "-I", "include", "file.cpp"};
728 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv));
729 1 : ASSERT_EQUALS("include/", settings->includePaths.front());
730 : }
731 :
732 1 : void includesslash() {
733 1 : REDIRECT;
734 1 : const char * const argv[] = {"cppcheck", "-I", "include/", "file.cpp"};
735 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv));
736 1 : ASSERT_EQUALS("include/", settings->includePaths.front());
737 : }
738 :
739 1 : void includesbackslash() {
740 1 : REDIRECT;
741 1 : const char * const argv[] = {"cppcheck", "-I", "include\\", "file.cpp"};
742 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv));
743 1 : ASSERT_EQUALS("include/", settings->includePaths.front());
744 : }
745 :
746 1 : void includesnospace() {
747 1 : REDIRECT;
748 1 : const char * const argv[] = {"cppcheck", "-Iinclude", "file.cpp"};
749 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
750 1 : ASSERT_EQUALS("include/", settings->includePaths.front());
751 : }
752 :
753 1 : void includes2() {
754 1 : REDIRECT;
755 1 : const char * const argv[] = {"cppcheck", "-I", "include/", "-I", "framework/", "file.cpp"};
756 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(6, argv));
757 1 : ASSERT_EQUALS("include/", settings->includePaths.front());
758 1 : settings->includePaths.pop_front();
759 1 : ASSERT_EQUALS("framework/", settings->includePaths.front());
760 : }
761 :
762 1 : void includesFile() {
763 1 : REDIRECT;
764 : ScopedFile file("includes.txt",
765 : "path/sub\n"
766 4 : "path2/sub1\n");
767 1 : const char * const argv[] = {"cppcheck", "--includes-file=includes.txt", "file.cpp"};
768 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
769 1 : ASSERT_EQUALS(2, settings->includePaths.size());
770 1 : auto it = settings->includePaths.cbegin();
771 1 : ASSERT_EQUALS("path/sub/", *it++);
772 1 : ASSERT_EQUALS("path2/sub1/", *it);
773 : }
774 :
775 1 : void includesFileNoFile() {
776 1 : REDIRECT;
777 1 : const char * const argv[] = {"cppcheck", "--includes-file=fileThatDoesNotExist.txt", "file.cpp"};
778 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
779 1 : ASSERT_EQUALS("cppcheck: error: unable to open includes file at 'fileThatDoesNotExist.txt'\n", logger->str());
780 : }
781 :
782 1 : void configExcludesFile() {
783 1 : REDIRECT;
784 : ScopedFile file("excludes.txt",
785 : "path/sub\n"
786 4 : "path2/sub1\n");
787 1 : const char * const argv[] = {"cppcheck", "--config-excludes-file=excludes.txt", "file.cpp"};
788 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
789 1 : ASSERT_EQUALS(2, settings->configExcludePaths.size());
790 1 : auto it = settings->configExcludePaths.cbegin();
791 1 : ASSERT_EQUALS("path/sub/", *it++);
792 1 : ASSERT_EQUALS("path2/sub1/", *it);
793 : }
794 :
795 1 : void configExcludesFileNoFile() {
796 1 : REDIRECT;
797 1 : const char * const argv[] = {"cppcheck", "--config-excludes-file=fileThatDoesNotExist.txt", "file.cpp"};
798 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
799 1 : ASSERT_EQUALS("cppcheck: error: unable to open config excludes file at 'fileThatDoesNotExist.txt'\n", logger->str());
800 : }
801 :
802 1 : void enabledAll() {
803 1 : REDIRECT;
804 1 : const char * const argv[] = {"cppcheck", "--enable=all", "file.cpp"};
805 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
806 1 : ASSERT(settings->severity.isEnabled(Severity::error));
807 1 : ASSERT(settings->severity.isEnabled(Severity::style));
808 1 : ASSERT(settings->severity.isEnabled(Severity::warning));
809 1 : ASSERT(settings->checks.isEnabled(Checks::unusedFunction));
810 1 : ASSERT(settings->checks.isEnabled(Checks::missingInclude));
811 1 : ASSERT(!settings->checks.isEnabled(Checks::internalCheck));
812 : }
813 :
814 1 : void enabledStyle() {
815 1 : REDIRECT;
816 1 : const char * const argv[] = {"cppcheck", "--enable=style", "file.cpp"};
817 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
818 1 : ASSERT(settings->severity.isEnabled(Severity::error));
819 1 : ASSERT(settings->severity.isEnabled(Severity::style));
820 1 : ASSERT(settings->severity.isEnabled(Severity::warning));
821 1 : ASSERT(settings->severity.isEnabled(Severity::performance));
822 1 : ASSERT(settings->severity.isEnabled(Severity::portability));
823 1 : ASSERT(!settings->checks.isEnabled(Checks::unusedFunction));
824 1 : ASSERT(!settings->checks.isEnabled(Checks::internalCheck));
825 : }
826 :
827 1 : void enabledPerformance() {
828 1 : REDIRECT;
829 1 : const char * const argv[] = {"cppcheck", "--enable=performance", "file.cpp"};
830 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
831 1 : ASSERT(settings->severity.isEnabled(Severity::error));
832 1 : ASSERT(!settings->severity.isEnabled(Severity::style));
833 1 : ASSERT(!settings->severity.isEnabled(Severity::warning));
834 1 : ASSERT(settings->severity.isEnabled(Severity::performance));
835 1 : ASSERT(!settings->severity.isEnabled(Severity::portability));
836 1 : ASSERT(!settings->checks.isEnabled(Checks::unusedFunction));
837 1 : ASSERT(!settings->checks.isEnabled(Checks::missingInclude));
838 : }
839 :
840 1 : void enabledPortability() {
841 1 : REDIRECT;
842 1 : const char * const argv[] = {"cppcheck", "--enable=portability", "file.cpp"};
843 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
844 1 : ASSERT(settings->severity.isEnabled(Severity::error));
845 1 : ASSERT(!settings->severity.isEnabled(Severity::style));
846 1 : ASSERT(!settings->severity.isEnabled(Severity::warning));
847 1 : ASSERT(!settings->severity.isEnabled(Severity::performance));
848 1 : ASSERT(settings->severity.isEnabled(Severity::portability));
849 1 : ASSERT(!settings->checks.isEnabled(Checks::unusedFunction));
850 1 : ASSERT(!settings->checks.isEnabled(Checks::missingInclude));
851 : }
852 :
853 1 : void enabledInformation() {
854 1 : REDIRECT;
855 1 : const char * const argv[] = {"cppcheck", "--enable=information", "file.cpp"};
856 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
857 1 : ASSERT(settings->severity.isEnabled(Severity::error));
858 1 : ASSERT(settings->severity.isEnabled(Severity::information));
859 1 : ASSERT(settings->checks.isEnabled(Checks::missingInclude));
860 1 : ASSERT_EQUALS("cppcheck: '--enable=information' will no longer implicitly enable 'missingInclude' starting with 2.16. Please enable it explicitly if you require it.\n", logger->str());
861 : }
862 :
863 1 : void enabledUnusedFunction() {
864 1 : REDIRECT;
865 1 : const char * const argv[] = {"cppcheck", "--enable=unusedFunction", "file.cpp"};
866 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
867 1 : ASSERT(settings->severity.isEnabled(Severity::error));
868 1 : ASSERT(settings->checks.isEnabled(Checks::unusedFunction));
869 : }
870 :
871 1 : void enabledMissingInclude() {
872 1 : REDIRECT;
873 1 : const char * const argv[] = {"cppcheck", "--enable=missingInclude", "file.cpp"};
874 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
875 1 : ASSERT(settings->severity.isEnabled(Severity::error));
876 1 : ASSERT(settings->checks.isEnabled(Checks::missingInclude));
877 : }
878 :
879 1 : void disabledMissingIncludeWithInformation() {
880 1 : REDIRECT;
881 1 : const char * const argv[] = {"cppcheck", "--disable=missingInclude", "--enable=information", "file.cpp"};
882 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv));
883 1 : ASSERT(settings->severity.isEnabled(Severity::error));
884 1 : ASSERT(settings->severity.isEnabled(Severity::information));
885 1 : ASSERT(!settings->checks.isEnabled(Checks::missingInclude));
886 1 : ASSERT_EQUALS("", logger->str());
887 : }
888 :
889 1 : void enabledMissingIncludeWithInformation() {
890 1 : REDIRECT;
891 1 : const char * const argv[] = {"cppcheck", "--enable=information", "--enable=missingInclude", "file.cpp"};
892 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv));
893 1 : ASSERT(settings->severity.isEnabled(Severity::error));
894 1 : ASSERT(settings->severity.isEnabled(Severity::information));
895 1 : ASSERT(settings->checks.isEnabled(Checks::missingInclude));
896 1 : ASSERT_EQUALS("", logger->str());
897 : }
898 :
899 1 : void enabledMissingIncludeWithInformationReverseOrder() {
900 1 : REDIRECT;
901 1 : const char * const argv[] = {"cppcheck", "--enable=missingInclude", "--enable=information", "file.cpp"};
902 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv));
903 1 : ASSERT(settings->severity.isEnabled(Severity::error));
904 1 : ASSERT(settings->severity.isEnabled(Severity::information));
905 1 : ASSERT(settings->checks.isEnabled(Checks::missingInclude));
906 1 : ASSERT_EQUALS("", logger->str());
907 : }
908 :
909 : #ifdef CHECK_INTERNAL
910 : void enabledInternal() {
911 : REDIRECT;
912 : const char * const argv[] = {"cppcheck", "--enable=internal", "file.cpp"};
913 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
914 : ASSERT(settings->severity.isEnabled(Severity::error));
915 : ASSERT(settings->checks.isEnabled(Checks::internalCheck));
916 : }
917 : #endif
918 :
919 1 : void enabledMultiple() {
920 1 : REDIRECT;
921 1 : const char * const argv[] = {"cppcheck", "--enable=missingInclude,portability,warning", "file.cpp"};
922 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
923 1 : ASSERT(settings->severity.isEnabled(Severity::error));
924 1 : ASSERT(!settings->severity.isEnabled(Severity::style));
925 1 : ASSERT(settings->severity.isEnabled(Severity::warning));
926 1 : ASSERT(!settings->severity.isEnabled(Severity::performance));
927 1 : ASSERT(settings->severity.isEnabled(Severity::portability));
928 1 : ASSERT(!settings->checks.isEnabled(Checks::unusedFunction));
929 1 : ASSERT(settings->checks.isEnabled(Checks::missingInclude));
930 : }
931 :
932 1 : void enabledInvalid() {
933 1 : REDIRECT;
934 1 : const char * const argv[] = {"cppcheck", "--enable=warning,missingIncludeSystem,style", "file.cpp"};
935 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
936 1 : ASSERT_EQUALS("cppcheck: error: --enable parameter with the unknown name 'missingIncludeSystem'\n", logger->str());
937 : }
938 :
939 1 : void enabledError() {
940 1 : REDIRECT;
941 1 : const char * const argv[] = {"cppcheck", "--enable=error", "file.cpp"};
942 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
943 1 : ASSERT_EQUALS("cppcheck: error: --enable parameter with the unknown name 'error'\n", logger->str());
944 : }
945 :
946 1 : void enabledEmpty() {
947 1 : REDIRECT;
948 1 : const char * const argv[] = {"cppcheck", "--enable=", "file.cpp"};
949 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
950 1 : ASSERT_EQUALS("cppcheck: error: --enable parameter is empty\n", logger->str());
951 : }
952 :
953 :
954 1 : void disableAll() {
955 1 : REDIRECT;
956 1 : const char * const argv[] = {"cppcheck", "--enable=all", "--disable=all", "file.cpp"};
957 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv));
958 1 : ASSERT_EQUALS(true, settings->severity.isEnabled(Severity::error));
959 1 : ASSERT_EQUALS(false, settings->severity.isEnabled(Severity::warning));
960 1 : ASSERT_EQUALS(false, settings->severity.isEnabled(Severity::style));
961 1 : ASSERT_EQUALS(false, settings->severity.isEnabled(Severity::performance));
962 1 : ASSERT_EQUALS(false, settings->severity.isEnabled(Severity::portability));
963 1 : ASSERT_EQUALS(false, settings->severity.isEnabled(Severity::debug));
964 1 : ASSERT_EQUALS(false, settings->checks.isEnabled(Checks::unusedFunction));
965 1 : ASSERT_EQUALS(false, settings->checks.isEnabled(Checks::missingInclude));
966 1 : ASSERT_EQUALS(false, settings->checks.isEnabled(Checks::internalCheck));
967 : }
968 :
969 1 : void disableMultiple() {
970 1 : REDIRECT;
971 1 : const char * const argv[] = {"cppcheck", "--enable=all", "--disable=style", "--disable=unusedFunction", "file.cpp"};
972 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(5, argv));
973 1 : ASSERT_EQUALS(true, settings->severity.isEnabled(Severity::error));
974 1 : ASSERT_EQUALS(true, settings->severity.isEnabled(Severity::warning));
975 1 : ASSERT_EQUALS(false, settings->severity.isEnabled(Severity::style));
976 1 : ASSERT_EQUALS(true, settings->severity.isEnabled(Severity::performance));
977 1 : ASSERT_EQUALS(true, settings->severity.isEnabled(Severity::portability));
978 1 : ASSERT_EQUALS(true, settings->severity.isEnabled(Severity::debug));
979 1 : ASSERT_EQUALS(false, settings->checks.isEnabled(Checks::unusedFunction));
980 1 : ASSERT_EQUALS(true, settings->checks.isEnabled(Checks::missingInclude));
981 1 : ASSERT_EQUALS(false, settings->checks.isEnabled(Checks::internalCheck));
982 : }
983 :
984 : // make sure the implied "style" checks are not added when "--enable=style" is specified
985 1 : void disableStylePartial() {
986 1 : REDIRECT;
987 1 : const char * const argv[] = {"cppcheck", "--enable=style", "--disable=performance", "--enable=unusedFunction", "file.cpp"};
988 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(5, argv));
989 1 : ASSERT_EQUALS(true, settings->severity.isEnabled(Severity::error));
990 1 : ASSERT_EQUALS(true, settings->severity.isEnabled(Severity::warning));
991 1 : ASSERT_EQUALS(true, settings->severity.isEnabled(Severity::style));
992 1 : ASSERT_EQUALS(false, settings->severity.isEnabled(Severity::performance));
993 1 : ASSERT_EQUALS(true, settings->severity.isEnabled(Severity::portability));
994 1 : ASSERT_EQUALS(false, settings->severity.isEnabled(Severity::debug));
995 1 : ASSERT_EQUALS(true, settings->checks.isEnabled(Checks::unusedFunction));
996 1 : ASSERT_EQUALS(false, settings->checks.isEnabled(Checks::missingInclude));
997 1 : ASSERT_EQUALS(false, settings->checks.isEnabled(Checks::internalCheck));
998 : }
999 :
1000 1 : void disableInformationPartial() {
1001 1 : REDIRECT;
1002 1 : const char * const argv[] = {"cppcheck", "--enable=information", "--disable=missingInclude", "file.cpp"};
1003 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv));
1004 1 : ASSERT(settings->severity.isEnabled(Severity::information));
1005 1 : ASSERT(!settings->checks.isEnabled(Checks::missingInclude));
1006 1 : ASSERT_EQUALS("", logger->str());
1007 : }
1008 :
1009 1 : void disableInformationPartial2() {
1010 1 : REDIRECT;
1011 1 : const char * const argv[] = {"cppcheck", "--enable=missingInclude", "--disable=information", "file.cpp"};
1012 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv));
1013 1 : ASSERT(!settings->severity.isEnabled(Severity::information));
1014 1 : ASSERT(settings->checks.isEnabled(Checks::missingInclude));
1015 : }
1016 :
1017 1 : void disableInvalid() {
1018 1 : REDIRECT;
1019 1 : const char * const argv[] = {"cppcheck", "--disable=leaks", "file.cpp"};
1020 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
1021 1 : ASSERT_EQUALS("cppcheck: error: --disable parameter with the unknown name 'leaks'\n", logger->str());
1022 : }
1023 :
1024 1 : void disableError() {
1025 1 : REDIRECT;
1026 1 : const char * const argv[] = {"cppcheck", "--disable=error", "file.cpp"};
1027 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
1028 1 : ASSERT_EQUALS("cppcheck: error: --disable parameter with the unknown name 'error'\n", logger->str());
1029 : }
1030 :
1031 1 : void disableEmpty() {
1032 1 : REDIRECT;
1033 1 : const char * const argv[] = {"cppcheck", "--disable=", "file.cpp"};
1034 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
1035 1 : ASSERT_EQUALS("cppcheck: error: --disable parameter is empty\n", logger->str());
1036 : }
1037 :
1038 1 : void inconclusive() {
1039 1 : REDIRECT;
1040 1 : const char * const argv[] = {"cppcheck", "--inconclusive", "file.cpp"};
1041 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1042 1 : ASSERT_EQUALS(true, settings->certainty.isEnabled(Certainty::inconclusive));
1043 : }
1044 :
1045 1 : void errorExitcode() {
1046 1 : REDIRECT;
1047 1 : const char * const argv[] = {"cppcheck", "--error-exitcode=5", "file.cpp"};
1048 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1049 1 : ASSERT_EQUALS(5, settings->exitCode);
1050 : }
1051 :
1052 1 : void errorExitcodeMissing() {
1053 1 : REDIRECT;
1054 1 : const char * const argv[] = {"cppcheck", "--error-exitcode=", "file.cpp"};
1055 : // Fails since exit code not given
1056 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
1057 1 : ASSERT_EQUALS("cppcheck: error: argument to '--error-exitcode=' is not valid - not an integer.\n", logger->str());
1058 : }
1059 :
1060 1 : void errorExitcodeStr() {
1061 1 : REDIRECT;
1062 1 : const char * const argv[] = {"cppcheck", "--error-exitcode=foo", "file.cpp"};
1063 : // Fails since invalid exit code
1064 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
1065 1 : ASSERT_EQUALS("cppcheck: error: argument to '--error-exitcode=' is not valid - not an integer.\n", logger->str());
1066 : }
1067 :
1068 1 : void exitcodeSuppressionsOld() {
1069 1 : REDIRECT;
1070 1 : const char * const argv[] = {"cppcheck", "--exitcode-suppressions", "suppr.txt", "file.cpp"};
1071 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(4, argv));
1072 1 : ASSERT_EQUALS("cppcheck: error: unrecognized command line option: \"--exitcode-suppressions\".\n", logger->str());
1073 : }
1074 :
1075 1 : void exitcodeSuppressions() {
1076 1 : REDIRECT;
1077 : ScopedFile file("suppr.txt",
1078 : "uninitvar\n"
1079 4 : "unusedFunction\n");
1080 1 : const char * const argv[] = {"cppcheck", "--exitcode-suppressions=suppr.txt", "file.cpp"};
1081 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1082 1 : ASSERT_EQUALS(2, settings->supprs.nofail.getSuppressions().size());
1083 1 : auto it = settings->supprs.nofail.getSuppressions().cbegin();
1084 1 : ASSERT_EQUALS("uninitvar", (it++)->errorId);
1085 1 : ASSERT_EQUALS("unusedFunction", it->errorId);
1086 : }
1087 :
1088 1 : void exitcodeSuppressionsNoFile() {
1089 1 : REDIRECT;
1090 1 : const char * const argv[] = {"cppcheck", "--exitcode-suppressions", "file.cpp"};
1091 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
1092 1 : ASSERT_EQUALS("cppcheck: error: unrecognized command line option: \"--exitcode-suppressions\".\n", logger->str());
1093 : }
1094 :
1095 1 : void fileFilterStdin() {
1096 1 : REDIRECT;
1097 2 : RedirectInput input("file1.c\nfile2.cpp\n");
1098 1 : const char * const argv[] = {"cppcheck", "--file-filter=-"};
1099 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv));
1100 1 : ASSERT_EQUALS("cppcheck: error: no C or C++ source files found.\n", logger->str());
1101 1 : ASSERT_EQUALS(2U, settings->fileFilters.size());
1102 1 : ASSERT_EQUALS("file1.c", settings->fileFilters[0]);
1103 1 : ASSERT_EQUALS("file2.cpp", settings->fileFilters[1]);
1104 : }
1105 :
1106 1 : void fileList() {
1107 1 : REDIRECT;
1108 : ScopedFile file("files.txt",
1109 : "file1.c\n"
1110 4 : "file2.cpp\n");
1111 1 : const char * const argv[] = {"cppcheck", "--file-list=files.txt", "file.cpp"};
1112 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1113 1 : ASSERT_EQUALS(3, parser->getPathNames().size());
1114 1 : auto it = parser->getPathNames().cbegin();
1115 1 : ASSERT_EQUALS("file1.c", *it++);
1116 1 : ASSERT_EQUALS("file2.cpp", *it++);
1117 1 : ASSERT_EQUALS("file.cpp", *it);
1118 : }
1119 :
1120 1 : void fileListNoFile() {
1121 1 : REDIRECT;
1122 1 : const char * const argv[] = {"cppcheck", "--file-list=files.txt", "file.cpp"};
1123 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
1124 1 : ASSERT_EQUALS("cppcheck: error: couldn't open the file: \"files.txt\".\n", logger->str());
1125 : }
1126 :
1127 1 : void fileListStdin() {
1128 1 : REDIRECT;
1129 2 : RedirectInput input("file1.c\nfile2.cpp\n");
1130 1 : const char * const argv[] = {"cppcheck", "--file-list=-", "file.cpp"};
1131 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1132 1 : ASSERT_EQUALS(3, parser->getPathNames().size());
1133 1 : auto it = parser->getPathNames().cbegin();
1134 1 : ASSERT_EQUALS("file1.c", *it++);
1135 1 : ASSERT_EQUALS("file2.cpp", *it++);
1136 1 : ASSERT_EQUALS("file.cpp", *it);
1137 : }
1138 :
1139 1 : void fileListInvalid() {
1140 1 : REDIRECT;
1141 1 : const char * const argv[] = {"cppcheck", "--file-list", "files.txt", "file.cpp"};
1142 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(4, argv));
1143 1 : ASSERT_EQUALS("cppcheck: error: unrecognized command line option: \"--file-list\".\n", logger->str());
1144 : }
1145 :
1146 1 : void inlineSuppr() {
1147 1 : REDIRECT;
1148 1 : const char * const argv[] = {"cppcheck", "--inline-suppr", "file.cpp"};
1149 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1150 1 : ASSERT(settings->inlineSuppressions);
1151 : }
1152 :
1153 1 : void jobs() {
1154 1 : REDIRECT;
1155 1 : const char * const argv[] = {"cppcheck", "-j", "3", "file.cpp"};
1156 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv));
1157 1 : ASSERT_EQUALS(3, settings->jobs);
1158 : }
1159 :
1160 1 : void jobs2() {
1161 1 : REDIRECT;
1162 1 : const char * const argv[] = {"cppcheck", "-j3", "file.cpp"};
1163 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1164 1 : ASSERT_EQUALS(3, settings->jobs);
1165 : }
1166 :
1167 1 : void jobsMissingCount() {
1168 1 : REDIRECT;
1169 1 : const char * const argv[] = {"cppcheck", "-j", "file.cpp"};
1170 : // Fails since -j is missing thread count
1171 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
1172 1 : ASSERT_EQUALS("cppcheck: error: argument to '-j' is not valid - not an integer.\n", logger->str());
1173 : }
1174 :
1175 1 : void jobsInvalid() {
1176 1 : REDIRECT;
1177 1 : const char * const argv[] = {"cppcheck", "-j", "e", "file.cpp"};
1178 : // Fails since invalid count given for -j
1179 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(4, argv));
1180 1 : ASSERT_EQUALS("cppcheck: error: argument to '-j' is not valid - not an integer.\n", logger->str());
1181 : }
1182 :
1183 1 : void jobsNoJobs() {
1184 1 : REDIRECT;
1185 1 : const char * const argv[] = {"cppcheck", "-j0", "file.cpp"};
1186 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
1187 1 : ASSERT_EQUALS("cppcheck: error: argument for '-j' must be greater than 0.\n", logger->str());
1188 : }
1189 :
1190 1 : void jobsTooBig() {
1191 1 : REDIRECT;
1192 1 : const char * const argv[] = {"cppcheck", "-j1025", "file.cpp"};
1193 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
1194 1 : ASSERT_EQUALS("cppcheck: error: argument for '-j' is allowed to be 1024 at max.\n", logger->str());
1195 : }
1196 :
1197 1 : void maxConfigs() {
1198 1 : REDIRECT;
1199 1 : const char * const argv[] = {"cppcheck", "-f", "--max-configs=12", "file.cpp"};
1200 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv));
1201 1 : ASSERT_EQUALS(12, settings->maxConfigs);
1202 1 : ASSERT_EQUALS(false, settings->force);
1203 : }
1204 :
1205 1 : void maxConfigsMissingCount() {
1206 1 : REDIRECT;
1207 1 : const char * const argv[] = {"cppcheck", "--max-configs=", "file.cpp"};
1208 : // Fails since --max-configs= is missing limit
1209 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
1210 1 : ASSERT_EQUALS("cppcheck: error: argument to '--max-configs=' is not valid - not an integer.\n", logger->str());
1211 : }
1212 :
1213 1 : void maxConfigsInvalid() {
1214 1 : REDIRECT;
1215 1 : const char * const argv[] = {"cppcheck", "--max-configs=e", "file.cpp"};
1216 : // Fails since invalid count given for --max-configs=
1217 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
1218 1 : ASSERT_EQUALS("cppcheck: error: argument to '--max-configs=' is not valid - not an integer.\n", logger->str());
1219 : }
1220 :
1221 1 : void maxConfigsTooSmall() {
1222 1 : REDIRECT;
1223 1 : const char * const argv[] = {"cppcheck", "--max-configs=0", "file.cpp"};
1224 : // Fails since limit must be greater than 0
1225 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
1226 1 : ASSERT_EQUALS("cppcheck: error: argument to '--max-configs=' must be greater than 0.\n", logger->str());
1227 : }
1228 :
1229 1 : void premiumOptions1() {
1230 1 : REDIRECT;
1231 1 : asPremium();
1232 1 : const char * const argv[] = {"cppcheck", "--premium=autosar", "file.c"};
1233 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1234 1 : ASSERT(settings->severity.isEnabled(Severity::error));
1235 1 : ASSERT_EQUALS(true, settings->severity.isEnabled(Severity::warning));
1236 : }
1237 :
1238 1 : void premiumOptions2() {
1239 1 : REDIRECT;
1240 1 : asPremium();
1241 1 : const char * const argv[] = {"cppcheck", "--premium=misra-c-2012", "file.c"};
1242 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1243 1 : ASSERT(settings->severity.isEnabled(Severity::error));
1244 1 : ASSERT_EQUALS(true, settings->severity.isEnabled(Severity::warning));
1245 : }
1246 :
1247 1 : void premiumOptions3() {
1248 1 : REDIRECT;
1249 1 : asPremium();
1250 1 : const char * const argv[] = {"cppcheck", "--premium=misra-c++-2023", "file.c"};
1251 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1252 1 : ASSERT(settings->severity.isEnabled(Severity::error));
1253 1 : ASSERT_EQUALS(true, settings->severity.isEnabled(Severity::warning));
1254 : }
1255 :
1256 1 : void premiumOptions4() {
1257 1 : REDIRECT;
1258 1 : asPremium();
1259 1 : const char * const argv[] = {"cppcheck", "--premium=cert-c++-2016", "file.c"};
1260 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1261 1 : ASSERT(settings->severity.isEnabled(Severity::error));
1262 1 : ASSERT_EQUALS(true, settings->severity.isEnabled(Severity::warning));
1263 : }
1264 :
1265 1 : void premiumOptions5() {
1266 1 : REDIRECT;
1267 1 : asPremium();
1268 1 : const char * const argv[] = {"cppcheck", "--premium=safety", "file.c"};
1269 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1270 1 : ASSERT(settings->severity.isEnabled(Severity::error));
1271 1 : ASSERT_EQUALS(false, settings->severity.isEnabled(Severity::warning));
1272 : }
1273 :
1274 1 : void premiumOptionsInvalid1() {
1275 1 : REDIRECT;
1276 1 : asPremium();
1277 1 : const char * const argv[] = {"cppcheck", "--premium=misra", "file.c"};
1278 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
1279 1 : ASSERT_EQUALS("cppcheck: error: invalid --premium option 'misra'.\n", logger->str());
1280 : }
1281 :
1282 1 : void premiumOptionsInvalid2() {
1283 1 : REDIRECT;
1284 1 : asPremium();
1285 1 : const char * const argv[] = {"cppcheck", "--premium=cert", "file.c"};
1286 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
1287 1 : ASSERT_EQUALS("cppcheck: error: invalid --premium option 'cert'.\n", logger->str());
1288 : }
1289 :
1290 1 : void premiumSafety() {
1291 1 : REDIRECT;
1292 1 : asPremium();
1293 1 : const char * const argv[] = {"cppcheck", "--premium=safety", "file.cpp"};
1294 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1295 1 : ASSERT_EQUALS(true, settings->safety);
1296 : }
1297 :
1298 1 : void reportProgress1() {
1299 1 : REDIRECT;
1300 1 : const char * const argv[] = {"cppcheck", "--report-progress", "file.cpp"};
1301 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1302 1 : ASSERT_EQUALS(10, settings->reportProgress);
1303 : }
1304 :
1305 1 : void reportProgress2() {
1306 1 : REDIRECT;
1307 1 : const char * const argv[] = {"cppcheck", "--report-progress=", "file.cpp"};
1308 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
1309 1 : ASSERT_EQUALS("cppcheck: error: argument to '--report-progress=' is not valid - not an integer.\n", logger->str());
1310 : }
1311 :
1312 1 : void reportProgress3() {
1313 1 : REDIRECT;
1314 1 : const char * const argv[] = {"cppcheck", "--report-progress=-1", "file.cpp"};
1315 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
1316 1 : ASSERT_EQUALS("cppcheck: error: argument to '--report-progress=' needs to be a positive integer.\n", logger->str());
1317 : }
1318 :
1319 1 : void reportProgress4() {
1320 1 : REDIRECT;
1321 1 : const char * const argv[] = {"cppcheck", "--report-progress=0", "file.cpp"};
1322 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1323 1 : ASSERT_EQUALS(0, settings->reportProgress);
1324 : }
1325 :
1326 1 : void reportProgress5() {
1327 1 : REDIRECT;
1328 1 : const char * const argv[] = {"cppcheck", "--report-progress=1", "file.cpp"};
1329 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1330 1 : ASSERT_EQUALS(1, settings->reportProgress);
1331 : }
1332 :
1333 1 : void stdc99() {
1334 1 : REDIRECT;
1335 1 : const char * const argv[] = {"cppcheck", "--std=c99", "file.cpp"};
1336 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1337 1 : ASSERT(settings->standards.c == Standards::C99);
1338 : }
1339 :
1340 1 : void stdcpp11() {
1341 1 : REDIRECT;
1342 1 : const char * const argv[] = {"cppcheck", "--std=c++11", "file.cpp"};
1343 1 : settings->standards.cpp = Standards::CPP03;
1344 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1345 1 : ASSERT(settings->standards.cpp == Standards::CPP11);
1346 : }
1347 :
1348 1 : void stdunknown1() {
1349 1 : REDIRECT;
1350 1 : const char *const argv[] = {"cppcheck", "--std=d++11", "file.cpp"};
1351 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
1352 1 : ASSERT_EQUALS("cppcheck: error: unknown --std value 'd++11'\n", logger->str());
1353 : }
1354 :
1355 1 : void stdunknown2() {
1356 1 : REDIRECT;
1357 1 : const char *const argv[] = {"cppcheck", "--std=cplusplus11", "file.cpp"};
1358 1 : TODO_ASSERT_EQUALS(static_cast<int>(CmdLineParser::Result::Fail), static_cast<int>(CmdLineParser::Result::Success), static_cast<int>(parser->parseFromArgs(3, argv)));
1359 1 : TODO_ASSERT_EQUALS("cppcheck: error: unknown --std value 'cplusplus11'\n", "", logger->str());
1360 1 : }
1361 :
1362 1 : void platformWin64() {
1363 1 : REDIRECT;
1364 1 : const char * const argv[] = {"cppcheck", "--platform=win64", "file.cpp"};
1365 1 : ASSERT(settings->platform.set(Platform::Type::Unspecified));
1366 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1367 1 : ASSERT_EQUALS(Platform::Type::Win64, settings->platform.type);
1368 : }
1369 :
1370 1 : void platformWin32A() {
1371 1 : REDIRECT;
1372 1 : const char * const argv[] = {"cppcheck", "--platform=win32A", "file.cpp"};
1373 1 : ASSERT(settings->platform.set(Platform::Type::Unspecified));
1374 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1375 1 : ASSERT_EQUALS(Platform::Type::Win32A, settings->platform.type);
1376 : }
1377 :
1378 1 : void platformWin32W() {
1379 1 : REDIRECT;
1380 1 : const char * const argv[] = {"cppcheck", "--platform=win32W", "file.cpp"};
1381 1 : ASSERT(settings->platform.set(Platform::Type::Unspecified));
1382 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1383 1 : ASSERT_EQUALS(Platform::Type::Win32W, settings->platform.type);
1384 : }
1385 :
1386 1 : void platformUnix32() {
1387 1 : REDIRECT;
1388 1 : const char * const argv[] = {"cppcheck", "--platform=unix32", "file.cpp"};
1389 1 : ASSERT(settings->platform.set(Platform::Type::Unspecified));
1390 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1391 1 : ASSERT_EQUALS(Platform::Type::Unix32, settings->platform.type);
1392 : }
1393 :
1394 1 : void platformUnix32Unsigned() {
1395 1 : REDIRECT;
1396 1 : const char * const argv[] = {"cppcheck", "--platform=unix32-unsigned", "file.cpp"};
1397 1 : ASSERT(settings->platform.set(Platform::Type::Unspecified));
1398 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1399 1 : ASSERT_EQUALS(Platform::Type::Unix32, settings->platform.type);
1400 : }
1401 :
1402 1 : void platformUnix64() {
1403 1 : REDIRECT;
1404 1 : const char * const argv[] = {"cppcheck", "--platform=unix64", "file.cpp"};
1405 1 : ASSERT(settings->platform.set(Platform::Type::Unspecified));
1406 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1407 1 : ASSERT_EQUALS(Platform::Type::Unix64, settings->platform.type);
1408 : }
1409 :
1410 1 : void platformUnix64Unsigned() {
1411 1 : REDIRECT;
1412 1 : const char * const argv[] = {"cppcheck", "--platform=unix64-unsigned", "file.cpp"};
1413 1 : ASSERT(settings->platform.set(Platform::Type::Unspecified));
1414 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1415 1 : ASSERT_EQUALS(Platform::Type::Unix64, settings->platform.type);
1416 : }
1417 :
1418 1 : void platformNative() {
1419 1 : REDIRECT;
1420 1 : const char * const argv[] = {"cppcheck", "--platform=native", "file.cpp"};
1421 1 : ASSERT(settings->platform.set(Platform::Type::Unspecified));
1422 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1423 1 : ASSERT_EQUALS(Platform::Type::Native, settings->platform.type);
1424 : }
1425 :
1426 1 : void platformUnspecified() {
1427 1 : REDIRECT;
1428 1 : const char * const argv[] = {"cppcheck", "--platform=unspecified", "file.cpp"};
1429 1 : ASSERT(settings->platform.set(Platform::Type::Native));
1430 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1431 1 : ASSERT_EQUALS(Platform::Type::Unspecified, settings->platform.type);
1432 : }
1433 :
1434 1 : void platformPlatformFile() {
1435 1 : REDIRECT;
1436 1 : const char * const argv[] = {"cppcheck", "--platform=avr8", "file.cpp"};
1437 1 : ASSERT(settings->platform.set(Platform::Type::Unspecified));
1438 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1439 1 : ASSERT_EQUALS(Platform::Type::File, settings->platform.type);
1440 : }
1441 :
1442 1 : void platformUnknown() {
1443 1 : REDIRECT;
1444 1 : const char * const argv[] = {"cppcheck", "--platform=win128", "file.cpp"};
1445 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
1446 1 : ASSERT_EQUALS("cppcheck: error: unrecognized platform: 'win128'.\n", logger->str());
1447 : }
1448 :
1449 1 : void plistEmpty() {
1450 1 : REDIRECT;
1451 1 : const char * const argv[] = {"cppcheck", "--plist-output=", "file.cpp"};
1452 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1453 1 : ASSERT(settings->plistOutput == "./");
1454 : }
1455 :
1456 1 : void plistDoesNotExist() {
1457 1 : REDIRECT;
1458 1 : const char * const argv[] = {"cppcheck", "--plist-output=./cppcheck_reports", "file.cpp"};
1459 : // Fails since folder pointed by --plist-output= does not exist
1460 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
1461 1 : ASSERT_EQUALS("cppcheck: error: plist folder does not exist: 'cppcheck_reports'.\n", logger->str());
1462 : }
1463 :
1464 1 : void suppressionsOld() {
1465 1 : REDIRECT;
1466 1 : const char * const argv[] = {"cppcheck", "--suppressions", "suppr.txt", "file.cpp"};
1467 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(4, argv));
1468 1 : ASSERT_EQUALS("cppcheck: error: unrecognized command line option: \"--suppressions\".\n", logger->str());
1469 : }
1470 :
1471 1 : void suppressions() {
1472 1 : REDIRECT;
1473 : ScopedFile file("suppr.txt",
1474 : "uninitvar\n"
1475 4 : "unusedFunction\n");
1476 1 : const char * const argv[] = {"cppcheck", "--suppressions-list=suppr.txt", "file.cpp"};
1477 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1478 1 : ASSERT_EQUALS(2, settings->supprs.nomsg.getSuppressions().size());
1479 1 : auto it = settings->supprs.nomsg.getSuppressions().cbegin();
1480 1 : ASSERT_EQUALS("uninitvar", (it++)->errorId);
1481 1 : ASSERT_EQUALS("unusedFunction", it->errorId);
1482 : }
1483 :
1484 1 : void suppressionsNoFile1() {
1485 1 : REDIRECT;
1486 1 : const char * const argv[] = {"cppcheck", "--suppressions-list=", "file.cpp"};
1487 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
1488 1 : ASSERT_EQUALS(false, logger->str().find("If you want to pass two files") != std::string::npos);
1489 : }
1490 :
1491 1 : void suppressionsNoFile2() {
1492 1 : REDIRECT;
1493 1 : const char * const argv[] = {"cppcheck", "--suppressions-list=a.suppr,b.suppr", "file.cpp"};
1494 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
1495 1 : ASSERT_EQUALS(true, logger->str().find("If you want to pass two files") != std::string::npos);
1496 : }
1497 :
1498 1 : void suppressionsNoFile3() {
1499 1 : REDIRECT;
1500 1 : const char * const argv[] = {"cppcheck", "--suppressions-list=a.suppr b.suppr", "file.cpp"};
1501 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
1502 1 : ASSERT_EQUALS(true, logger->str().find("If you want to pass two files") != std::string::npos);
1503 : }
1504 :
1505 6 : static SuppressionList::ErrorMessage errorMessage(const std::string &errorId, const std::string &fileName, int lineNumber) {
1506 6 : SuppressionList::ErrorMessage e;
1507 6 : e.errorId = errorId;
1508 6 : e.setFileName(fileName);
1509 6 : e.lineNumber = lineNumber;
1510 6 : return e;
1511 : }
1512 :
1513 1 : void suppressionSingle() {
1514 1 : REDIRECT;
1515 1 : const char * const argv[] = {"cppcheck", "--suppress=uninitvar", "file.cpp"};
1516 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1517 1 : ASSERT_EQUALS(true, settings->supprs.nomsg.isSuppressed(errorMessage("uninitvar", "file.cpp", 1)));
1518 : }
1519 :
1520 1 : void suppressionSingleFile() {
1521 1 : REDIRECT;
1522 1 : const char * const argv[] = {"cppcheck", "--suppress=uninitvar:file.cpp", "file.cpp"};
1523 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1524 1 : ASSERT_EQUALS(true, settings->supprs.nomsg.isSuppressed(errorMessage("uninitvar", "file.cpp", 1U)));
1525 : }
1526 :
1527 1 : void suppressionTwo() {
1528 1 : REDIRECT;
1529 1 : const char * const argv[] = {"cppcheck", "--suppress=uninitvar,noConstructor", "file.cpp"};
1530 1 : TODO_ASSERT_EQUALS(static_cast<int>(CmdLineParser::Result::Success), static_cast<int>(CmdLineParser::Result::Fail), static_cast<int>(parser->parseFromArgs(3, argv)));
1531 1 : TODO_ASSERT_EQUALS(true, false, settings->supprs.nomsg.isSuppressed(errorMessage("uninitvar", "file.cpp", 1U)));
1532 1 : TODO_ASSERT_EQUALS(true, false, settings->supprs.nomsg.isSuppressed(errorMessage("noConstructor", "file.cpp", 1U)));
1533 1 : TODO_ASSERT_EQUALS("", "cppcheck: error: Failed to add suppression. Invalid id \"uninitvar,noConstructor\"\n", logger->str());
1534 1 : }
1535 :
1536 1 : void suppressionTwoSeparate() {
1537 1 : REDIRECT;
1538 1 : const char * const argv[] = {"cppcheck", "--suppress=uninitvar", "--suppress=noConstructor", "file.cpp"};
1539 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv));
1540 1 : ASSERT_EQUALS(true, settings->supprs.nomsg.isSuppressed(errorMessage("uninitvar", "file.cpp", 1U)));
1541 1 : ASSERT_EQUALS(true, settings->supprs.nomsg.isSuppressed(errorMessage("noConstructor", "file.cpp", 1U)));
1542 : }
1543 :
1544 1 : void templates() {
1545 1 : REDIRECT;
1546 1 : const char * const argv[] = {"cppcheck", "--template={file}:{line},{severity},{id},{message}", "--template-location={file}:{line}:{column} {info}", "file.cpp"};
1547 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv));
1548 1 : ASSERT_EQUALS("{file}:{line},{severity},{id},{message}", settings->templateFormat);
1549 1 : ASSERT_EQUALS("{file}:{line}:{column} {info}", settings->templateLocation);
1550 : }
1551 :
1552 1 : void templatesGcc() {
1553 1 : REDIRECT;
1554 1 : const char * const argv[] = {"cppcheck", "--template=gcc", "file.cpp"};
1555 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1556 1 : ASSERT_EQUALS("{file}:{line}:{column}: warning: {message} [{id}]\n{code}", settings->templateFormat);
1557 1 : ASSERT_EQUALS("{file}:{line}:{column}: note: {info}\n{code}", settings->templateLocation);
1558 : }
1559 :
1560 1 : void templatesVs() {
1561 1 : REDIRECT;
1562 1 : const char * const argv[] = {"cppcheck", "--template=vs", "file.cpp"};
1563 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1564 1 : ASSERT_EQUALS("{file}({line}): {severity}: {message}", settings->templateFormat);
1565 1 : ASSERT_EQUALS("", settings->templateLocation);
1566 : }
1567 :
1568 1 : void templatesEdit() {
1569 1 : REDIRECT;
1570 1 : const char * const argv[] = {"cppcheck", "--template=edit", "file.cpp"};
1571 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1572 1 : ASSERT_EQUALS("{file} +{line}: {severity}: {message}", settings->templateFormat);
1573 1 : ASSERT_EQUALS("", settings->templateLocation);
1574 : }
1575 :
1576 1 : void templatesCppcheck1() {
1577 1 : REDIRECT;
1578 1 : const char * const argv[] = {"cppcheck", "--template=cppcheck1", "file.cpp"};
1579 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1580 1 : ASSERT_EQUALS("{callstack}: ({severity}{inconclusive:, inconclusive}) {message}", settings->templateFormat);
1581 1 : ASSERT_EQUALS("", settings->templateLocation);
1582 : }
1583 :
1584 1 : void templatesDaca2() {
1585 1 : REDIRECT;
1586 1 : const char * const argv[] = {"cppcheck", "--template=daca2", "file.cpp"};
1587 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1588 1 : ASSERT_EQUALS("{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]", settings->templateFormat);
1589 1 : ASSERT_EQUALS("{file}:{line}:{column}: note: {info}", settings->templateLocation);
1590 1 : ASSERT_EQUALS(true, settings->daca);
1591 : }
1592 :
1593 1 : void templatesSelfcheck() {
1594 1 : REDIRECT;
1595 1 : const char * const argv[] = {"cppcheck", "--template=selfcheck", "file.cpp"};
1596 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1597 1 : ASSERT_EQUALS("{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\n{code}", settings->templateFormat);
1598 1 : ASSERT_EQUALS("{file}:{line}:{column}: note: {info}\n{code}", settings->templateLocation);
1599 : }
1600 :
1601 1 : void templatesSimple() {
1602 1 : REDIRECT;
1603 1 : const char * const argv[] = {"cppcheck", "--template=simple", "file.cpp"};
1604 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1605 1 : ASSERT_EQUALS("{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]", settings->templateFormat);
1606 1 : ASSERT_EQUALS("", settings->templateLocation);
1607 : }
1608 :
1609 : // TODO: we should bail out on this
1610 1 : void templatesNoPlaceholder() {
1611 1 : REDIRECT;
1612 1 : const char * const argv[] = {"cppcheck", "--template=selfchek", "file.cpp"};
1613 1 : TODO_ASSERT_EQUALS(static_cast<int>(CmdLineParser::Result::Fail), static_cast<int>(CmdLineParser::Result::Success), static_cast<int>(parser->parseFromArgs(3, argv)));
1614 1 : ASSERT_EQUALS("selfchek", settings->templateFormat);
1615 1 : ASSERT_EQUALS("", settings->templateLocation);
1616 : }
1617 :
1618 1 : void templateFormatInvalid() {
1619 1 : REDIRECT;
1620 1 : const char* const argv[] = { "cppcheck", "--template", "file.cpp" };
1621 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
1622 1 : ASSERT_EQUALS("cppcheck: error: unrecognized command line option: \"--template\".\n", logger->str());
1623 : }
1624 :
1625 : // will use the default
1626 : // TODO: bail out on empty?
1627 1 : void templateFormatEmpty() {
1628 1 : REDIRECT;
1629 1 : const char* const argv[] = { "cppcheck", "--template=", "file.cpp" };
1630 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1631 1 : ASSERT_EQUALS("{file}:{line}:{column}: {inconclusive:}{severity}:{inconclusive: inconclusive:} {message} [{id}]\n{code}", settings->templateFormat);
1632 1 : ASSERT_EQUALS("{file}:{line}:{column}: note: {info}\n{code}", settings->templateLocation);
1633 : }
1634 :
1635 1 : void templateLocationInvalid() {
1636 1 : REDIRECT;
1637 1 : const char* const argv[] = { "cppcheck", "--template-location", "--template={file}", "file.cpp" };
1638 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(4, argv));
1639 1 : ASSERT_EQUALS("cppcheck: error: unrecognized command line option: \"--template-location\".\n", logger->str());
1640 : }
1641 :
1642 : // will use the default
1643 : // TODO: bail out on empty?
1644 1 : void templateLocationEmpty() {
1645 1 : REDIRECT;
1646 1 : const char* const argv[] = { "cppcheck", "--template-location=", "file.cpp" };
1647 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1648 1 : ASSERT_EQUALS("{file}:{line}:{column}: {inconclusive:}{severity}:{inconclusive: inconclusive:} {message} [{id}]\n{code}", settings->templateFormat);
1649 1 : ASSERT_EQUALS("{file}:{line}:{column}: note: {info}\n{code}", settings->templateLocation);
1650 : }
1651 :
1652 1 : void xml() {
1653 1 : REDIRECT;
1654 1 : const char * const argv[] = {"cppcheck", "--xml", "file.cpp"};
1655 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1656 1 : ASSERT(settings->xml);
1657 1 : ASSERT_EQUALS(2, settings->xml_version);
1658 : }
1659 :
1660 1 : void xmlver2() {
1661 1 : REDIRECT;
1662 1 : const char * const argv[] = {"cppcheck", "--xml-version=2", "file.cpp"};
1663 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1664 1 : ASSERT(settings->xml);
1665 1 : ASSERT_EQUALS(2, settings->xml_version);
1666 : }
1667 :
1668 1 : void xmlver2both() {
1669 1 : REDIRECT;
1670 1 : const char * const argv[] = {"cppcheck", "--xml", "--xml-version=2", "file.cpp"};
1671 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv));
1672 1 : ASSERT(settings->xml);
1673 1 : ASSERT_EQUALS(2, settings->xml_version);
1674 : }
1675 :
1676 1 : void xmlver2both2() {
1677 1 : REDIRECT;
1678 1 : const char * const argv[] = {"cppcheck", "--xml-version=2", "--xml", "file.cpp"};
1679 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv));
1680 1 : ASSERT(settings->xml);
1681 1 : ASSERT_EQUALS(2, settings->xml_version);
1682 : }
1683 :
1684 1 : void xmlverunknown() {
1685 1 : REDIRECT;
1686 1 : const char * const argv[] = {"cppcheck", "--xml", "--xml-version=3", "file.cpp"};
1687 : // FAils since unknown XML format version
1688 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(4, argv));
1689 1 : ASSERT_EQUALS("cppcheck: error: '--xml-version' can only be 2.\n", logger->str());
1690 : }
1691 :
1692 1 : void xmlverinvalid() {
1693 1 : REDIRECT;
1694 1 : const char * const argv[] = {"cppcheck", "--xml", "--xml-version=a", "file.cpp"};
1695 : // FAils since unknown XML format version
1696 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(4, argv));
1697 1 : ASSERT_EQUALS("cppcheck: error: argument to '--xml-version=' is not valid - not an integer.\n", logger->str());
1698 : }
1699 :
1700 1 : void doc() {
1701 1 : REDIRECT;
1702 1 : const char * const argv[] = {"cppcheck", "--doc"};
1703 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Exit, parser->parseFromArgs(2, argv));
1704 1 : ASSERT(startsWith(logger->str(), "## "));
1705 : }
1706 :
1707 1 : void docExclusive() {
1708 1 : REDIRECT;
1709 1 : const char * const argv[] = {"cppcheck", "--library=missing", "--doc"};
1710 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Exit, parser->parseFromArgs(3, argv));
1711 1 : ASSERT(startsWith(logger->str(), "## "));
1712 : }
1713 :
1714 : void showtimeSummary() {
1715 : REDIRECT;
1716 : const char * const argv[] = {"cppcheck", "--showtime=summary", "file.cpp"};
1717 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1718 : ASSERT(settings->showtime == SHOWTIME_MODES::SHOWTIME_SUMMARY);
1719 : }
1720 :
1721 1 : void showtimeFile() {
1722 1 : REDIRECT;
1723 1 : const char * const argv[] = {"cppcheck", "--showtime=file", "file.cpp"};
1724 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1725 1 : ASSERT(settings->showtime == SHOWTIME_MODES::SHOWTIME_FILE);
1726 : }
1727 :
1728 1 : void showtimeFileTotal() {
1729 1 : REDIRECT;
1730 1 : const char * const argv[] = {"cppcheck", "--showtime=file-total", "file.cpp"};
1731 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1732 1 : ASSERT(settings->showtime == SHOWTIME_MODES::SHOWTIME_FILE_TOTAL);
1733 : }
1734 :
1735 1 : void showtimeTop5() {
1736 1 : REDIRECT;
1737 1 : const char * const argv[] = {"cppcheck", "--showtime=top5", "file.cpp"};
1738 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1739 1 : ASSERT(settings->showtime == SHOWTIME_MODES::SHOWTIME_TOP5_FILE);
1740 1 : ASSERT_EQUALS("cppcheck: --showtime=top5 is deprecated and will be removed in Cppcheck 2.14. Please use --showtime=top5_file or --showtime=top5_summary instead.\n", logger->str());
1741 : }
1742 :
1743 1 : void showtimeTop5File() {
1744 1 : REDIRECT;
1745 1 : const char * const argv[] = {"cppcheck", "--showtime=top5_file", "file.cpp"};
1746 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1747 1 : ASSERT(settings->showtime == SHOWTIME_MODES::SHOWTIME_TOP5_FILE);
1748 : }
1749 :
1750 1 : void showtimeTop5Summary() {
1751 1 : REDIRECT;
1752 1 : const char * const argv[] = {"cppcheck", "--showtime=top5_summary", "file.cpp"};
1753 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1754 1 : ASSERT(settings->showtime == SHOWTIME_MODES::SHOWTIME_TOP5_SUMMARY);
1755 : }
1756 :
1757 1 : void showtimeNone() {
1758 1 : REDIRECT;
1759 1 : const char * const argv[] = {"cppcheck", "--showtime=none", "file.cpp"};
1760 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1761 1 : ASSERT(settings->showtime == SHOWTIME_MODES::SHOWTIME_NONE);
1762 : }
1763 :
1764 1 : void showtimeEmpty() {
1765 1 : REDIRECT;
1766 1 : const char * const argv[] = {"cppcheck", "--showtime=", "file.cpp"};
1767 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
1768 1 : ASSERT_EQUALS("cppcheck: error: no mode provided for --showtime\n", logger->str());
1769 : }
1770 :
1771 1 : void showtimeInvalid() {
1772 1 : REDIRECT;
1773 1 : const char * const argv[] = {"cppcheck", "--showtime=top10", "file.cpp"};
1774 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
1775 1 : ASSERT_EQUALS("cppcheck: error: unrecognized --showtime mode: 'top10'. Supported modes: file, file-total, summary, top5, top5_file, top5_summary.\n", logger->str());
1776 : }
1777 :
1778 1 : void errorlist() {
1779 1 : REDIRECT;
1780 1 : const char * const argv[] = {"cppcheck", "--errorlist"};
1781 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Exit, parser->parseFromArgs(2, argv));
1782 1 : ASSERT_EQUALS("", logger->str()); // empty since it is logged via ErrorLogger
1783 1 : const std::string errout_s = GET_REDIRECT_OUTPUT;
1784 1 : ASSERT(startsWith(errout_s, ErrorMessage::getXMLHeader("")));
1785 1 : ASSERT(endsWith(errout_s, "</results>\n"));
1786 : }
1787 :
1788 1 : void errorlistWithCfg() {
1789 1 : REDIRECT;
1790 2 : ScopedFile file(Path::join(Path::getPathFromFilename(Path::getCurrentExecutablePath("")), "cppcheck.cfg"),
1791 4 : R"({"productName": "The Product"}\n)");
1792 1 : const char * const argv[] = {"cppcheck", "--errorlist"};
1793 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Exit, parser->parseFromArgs(2, argv));
1794 1 : ASSERT_EQUALS("", logger->str()); // empty since it is logged via ErrorLogger
1795 1 : ASSERT(startsWith(GET_REDIRECT_OUTPUT, ErrorMessage::getXMLHeader("The Product")));
1796 : }
1797 :
1798 1 : void errorlistExclusive() {
1799 1 : REDIRECT;
1800 1 : const char * const argv[] = {"cppcheck", "--library=missing", "--errorlist"};
1801 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Exit, parser->parseFromArgs(3, argv));
1802 1 : ASSERT_EQUALS("", logger->str()); // empty since it is logged via ErrorLogger
1803 1 : const std::string errout_s = GET_REDIRECT_OUTPUT;
1804 1 : ASSERT(startsWith(errout_s, ErrorMessage::getXMLHeader("")));
1805 1 : ASSERT(endsWith(errout_s, "</results>\n"));
1806 : }
1807 :
1808 1 : void errorlistWithInvalidCfg() {
1809 1 : REDIRECT;
1810 2 : ScopedFile file(Path::join(Path::getPathFromFilename(Path::getCurrentExecutablePath("")), "cppcheck.cfg"),
1811 4 : "{\n");
1812 1 : const char * const argv[] = {"cppcheck", "--errorlist"};
1813 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv));
1814 1 : ASSERT_EQUALS("cppcheck: error: could not load cppcheck.cfg - not a valid JSON - syntax error at line 2 near: \n", logger->str());
1815 : }
1816 :
1817 1 : void ignorepathsnopath() {
1818 1 : REDIRECT;
1819 1 : const char * const argv[] = {"cppcheck", "-i"};
1820 : // Fails since no ignored path given
1821 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv));
1822 1 : ASSERT_EQUALS("cppcheck: error: argument to '-i' is missing.\n", logger->str());
1823 : }
1824 :
1825 : #if defined(USE_WINDOWS_SEH) || defined(USE_UNIX_SIGNAL_HANDLING)
1826 1 : void exceptionhandling() {
1827 1 : REDIRECT;
1828 1 : const char * const argv[] = {"cppcheck", "--exception-handling", "file.cpp"};
1829 1 : CppCheckExecutor::setExceptionOutput(stderr);
1830 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1831 1 : ASSERT(settings->exceptionHandling);
1832 1 : ASSERT_EQUALS(stderr, CppCheckExecutor::getExceptionOutput());
1833 : }
1834 :
1835 1 : void exceptionhandling2() {
1836 1 : REDIRECT;
1837 1 : const char * const argv[] = {"cppcheck", "--exception-handling=stderr", "file.cpp"};
1838 1 : CppCheckExecutor::setExceptionOutput(stdout);
1839 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1840 1 : ASSERT(settings->exceptionHandling);
1841 1 : ASSERT_EQUALS(stderr, CppCheckExecutor::getExceptionOutput());
1842 : }
1843 :
1844 1 : void exceptionhandling3() {
1845 1 : REDIRECT;
1846 1 : const char * const argv[] = {"cppcheck", "--exception-handling=stdout", "file.cpp"};
1847 1 : CppCheckExecutor::setExceptionOutput(stderr);
1848 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1849 1 : ASSERT(settings->exceptionHandling);
1850 1 : ASSERT_EQUALS(stdout, CppCheckExecutor::getExceptionOutput());
1851 : }
1852 :
1853 1 : void exceptionhandlingInvalid() {
1854 1 : REDIRECT;
1855 1 : const char * const argv[] = {"cppcheck", "--exception-handling=exfile"};
1856 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv));
1857 1 : ASSERT_EQUALS("cppcheck: error: invalid '--exception-handling' argument\n", logger->str());
1858 : }
1859 :
1860 1 : void exceptionhandlingInvalid2() {
1861 1 : REDIRECT;
1862 1 : const char * const argv[] = {"cppcheck", "--exception-handling-foo"};
1863 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv));
1864 1 : ASSERT_EQUALS("cppcheck: error: unrecognized command line option: \"--exception-handling-foo\".\n", logger->str());
1865 : }
1866 : #else
1867 : void exceptionhandlingNotSupported() {
1868 : REDIRECT;
1869 : const char * const argv[] = {"cppcheck", "--exception-handling", "file.cpp"};
1870 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
1871 : ASSERT_EQUALS("cppcheck: error: Option --exception-handling is not supported since Cppcheck has not been built with any exception handling enabled.\n", logger->str());
1872 : }
1873 :
1874 : void exceptionhandlingNotSupported2() {
1875 : REDIRECT;
1876 : const char * const argv[] = {"cppcheck", "--exception-handling=stderr", "file.cpp"};
1877 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
1878 : ASSERT_EQUALS("cppcheck: error: Option --exception-handling is not supported since Cppcheck has not been built with any exception handling enabled.\n", logger->str());
1879 : }
1880 : #endif
1881 :
1882 1 : void clang() {
1883 1 : REDIRECT;
1884 1 : const char * const argv[] = {"cppcheck", "--clang", "file.cpp"};
1885 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1886 1 : ASSERT(settings->clang);
1887 1 : ASSERT_EQUALS("clang", settings->clangExecutable);
1888 : }
1889 :
1890 1 : void clang2() {
1891 1 : REDIRECT;
1892 1 : const char * const argv[] = {"cppcheck", "--clang=clang-14", "file.cpp"};
1893 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1894 1 : ASSERT(settings->clang);
1895 1 : ASSERT_EQUALS("clang-14", settings->clangExecutable);
1896 : }
1897 :
1898 1 : void clangInvalid() {
1899 1 : REDIRECT;
1900 1 : const char * const argv[] = {"cppcheck", "--clang-foo"};
1901 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv));
1902 1 : ASSERT_EQUALS("cppcheck: error: unrecognized command line option: \"--clang-foo\".\n", logger->str());
1903 : }
1904 :
1905 1 : void valueFlowMaxIterations() {
1906 1 : REDIRECT;
1907 1 : const char * const argv[] = {"cppcheck", "--valueflow-max-iterations=0", "file.cpp"};
1908 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1909 1 : ASSERT_EQUALS(0, settings->valueFlowMaxIterations);
1910 : }
1911 :
1912 1 : void valueFlowMaxIterations2() {
1913 1 : REDIRECT;
1914 1 : const char * const argv[] = {"cppcheck", "--valueflow-max-iterations=11", "file.cpp"};
1915 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1916 1 : ASSERT_EQUALS(11, settings->valueFlowMaxIterations);
1917 : }
1918 :
1919 1 : void valueFlowMaxIterationsInvalid() {
1920 1 : REDIRECT;
1921 1 : const char * const argv[] = {"cppcheck", "--valueflow-max-iterations"};
1922 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv));
1923 1 : ASSERT_EQUALS("cppcheck: error: unrecognized command line option: \"--valueflow-max-iterations\".\n", logger->str());
1924 : }
1925 :
1926 1 : void valueFlowMaxIterationsInvalid2() {
1927 1 : REDIRECT;
1928 1 : const char * const argv[] = {"cppcheck", "--valueflow-max-iterations=seven"};
1929 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv));
1930 1 : ASSERT_EQUALS("cppcheck: error: argument to '--valueflow-max-iterations=' is not valid - not an integer.\n", logger->str());
1931 : }
1932 :
1933 1 : void valueFlowMaxIterationsInvalid3() {
1934 1 : REDIRECT;
1935 1 : const char * const argv[] = {"cppcheck", "--valueflow-max-iterations=-1"};
1936 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv));
1937 1 : ASSERT_EQUALS("cppcheck: error: argument to '--valueflow-max-iterations=' is not valid - needs to be positive.\n", logger->str());
1938 : }
1939 :
1940 1 : void checksMaxTime() {
1941 1 : REDIRECT;
1942 1 : const char * const argv[] = {"cppcheck", "--checks-max-time=12", "file.cpp"};
1943 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1944 1 : ASSERT_EQUALS(12, settings->checksMaxTime);
1945 : }
1946 :
1947 1 : void checksMaxTime2() {
1948 1 : REDIRECT;
1949 1 : const char * const argv[] = {"cppcheck", "--checks-max-time=-1", "file.cpp"};
1950 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
1951 1 : ASSERT_EQUALS("cppcheck: error: argument to '--checks-max-time=' needs to be a positive integer.\n", logger->str());
1952 : }
1953 :
1954 1 : void checksMaxTimeInvalid() {
1955 1 : REDIRECT;
1956 1 : const char * const argv[] = {"cppcheck", "--checks-max-time=one", "file.cpp"};
1957 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
1958 1 : ASSERT_EQUALS("cppcheck: error: argument to '--checks-max-time=' is not valid - not an integer.\n", logger->str());
1959 : }
1960 :
1961 : #ifdef HAS_THREADING_MODEL_FORK
1962 1 : void loadAverage() {
1963 1 : REDIRECT;
1964 1 : const char * const argv[] = {"cppcheck", "-l", "12", "file.cpp"};
1965 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv));
1966 1 : ASSERT_EQUALS(12, settings->loadAverage);
1967 : }
1968 :
1969 1 : void loadAverage2() {
1970 1 : REDIRECT;
1971 1 : const char * const argv[] = {"cppcheck", "-l12", "file.cpp"};
1972 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1973 1 : ASSERT_EQUALS(12, settings->loadAverage);
1974 : }
1975 :
1976 1 : void loadAverageInvalid() {
1977 1 : REDIRECT;
1978 1 : const char * const argv[] = {"cppcheck", "-l", "one", "file.cpp"};
1979 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(4, argv));
1980 1 : ASSERT_EQUALS("cppcheck: error: argument to '-l' is not valid - not an integer.\n", logger->str());
1981 : }
1982 : #else
1983 : void loadAverageNotSupported() {
1984 : REDIRECT;
1985 : const char * const argv[] = {"cppcheck", "-l", "12", "file.cpp"};
1986 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(4, argv));
1987 : ASSERT_EQUALS("cppcheck: error: Option -l cannot be used as Cppcheck has not been built with fork threading model.\n", logger->str());
1988 : }
1989 : #endif
1990 :
1991 1 : void maxCtuDepth() {
1992 1 : REDIRECT;
1993 1 : const char * const argv[] = {"cppcheck", "--max-ctu-depth=12", "file.cpp"};
1994 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
1995 1 : ASSERT_EQUALS(12, settings->maxCtuDepth);
1996 : }
1997 :
1998 1 : void maxCtuDepthInvalid() {
1999 1 : REDIRECT;
2000 1 : const char * const argv[] = {"cppcheck", "--max-ctu-depth=one", "file.cpp"};
2001 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
2002 1 : ASSERT_EQUALS("cppcheck: error: argument to '--max-ctu-depth=' is not valid - not an integer.\n", logger->str());
2003 : }
2004 :
2005 1 : void performanceValueflowMaxTime() {
2006 1 : REDIRECT;
2007 1 : const char * const argv[] = {"cppcheck", "--performance-valueflow-max-time=12", "file.cpp"};
2008 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
2009 1 : ASSERT_EQUALS(12, settings->performanceValueFlowMaxTime);
2010 : }
2011 :
2012 1 : void performanceValueflowMaxTimeInvalid() {
2013 1 : REDIRECT;
2014 1 : const char * const argv[] = {"cppcheck", "--performance-valueflow-max-time=one", "file.cpp"};
2015 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
2016 1 : ASSERT_EQUALS("cppcheck: error: argument to '--performance-valueflow-max-time=' is not valid - not an integer.\n", logger->str());
2017 : }
2018 :
2019 1 : void performanceValueFlowMaxIfCount() {
2020 1 : REDIRECT;
2021 1 : const char * const argv[] = {"cppcheck", "--performance-valueflow-max-if-count=12", "file.cpp"};
2022 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
2023 1 : ASSERT_EQUALS(12, settings->performanceValueFlowMaxIfCount);
2024 : }
2025 :
2026 1 : void performanceValueFlowMaxIfCountInvalid() {
2027 1 : REDIRECT;
2028 1 : const char * const argv[] = {"cppcheck", "--performance-valueflow-max-if-count=one", "file.cpp"};
2029 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
2030 1 : ASSERT_EQUALS("cppcheck: error: argument to '--performance-valueflow-max-if-count=' is not valid - not an integer.\n", logger->str());
2031 : }
2032 :
2033 3 : void templateMaxTime() {
2034 3 : REDIRECT;
2035 3 : const char * const argv[] = {"cppcheck", "--template-max-time=12", "file.cpp"};
2036 3 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
2037 3 : ASSERT_EQUALS(12, settings->templateMaxTime);
2038 : }
2039 :
2040 1 : void templateMaxTimeInvalid() {
2041 1 : REDIRECT;
2042 1 : const char * const argv[] = {"cppcheck", "--template-max-time=one", "file.cpp"};
2043 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
2044 1 : ASSERT_EQUALS("cppcheck: error: argument to '--template-max-time=' is not valid - not an integer.\n", logger->str());
2045 : }
2046 :
2047 1 : void templateMaxTimeInvalid2() {
2048 1 : REDIRECT;
2049 1 : const char * const argv[] = {"cppcheck", "--template-max-time=-1", "file.cpp"};
2050 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
2051 1 : ASSERT_EQUALS("cppcheck: error: argument to '--template-max-time=' is not valid - needs to be positive.\n", logger->str());
2052 : }
2053 :
2054 1 : void typedefMaxTime() {
2055 1 : REDIRECT;
2056 1 : const char * const argv[] = {"cppcheck", "--typedef-max-time=12", "file.cpp"};
2057 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
2058 1 : ASSERT_EQUALS(12, settings->typedefMaxTime);
2059 : }
2060 :
2061 1 : void typedefMaxTimeInvalid() {
2062 1 : REDIRECT;
2063 1 : const char * const argv[] = {"cppcheck", "--typedef-max-time=one", "file.cpp"};
2064 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
2065 1 : ASSERT_EQUALS("cppcheck: error: argument to '--typedef-max-time=' is not valid - not an integer.\n", logger->str());
2066 : }
2067 :
2068 1 : void typedefMaxTimeInvalid2() {
2069 1 : REDIRECT;
2070 1 : const char * const argv[] = {"cppcheck", "--typedef-max-time=-1", "file.cpp"};
2071 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
2072 1 : ASSERT_EQUALS("cppcheck: error: argument to '--typedef-max-time=' is not valid - needs to be positive.\n", logger->str());
2073 : }
2074 :
2075 1 : void project() {
2076 1 : REDIRECT;
2077 : ScopedFile file("project.cppcheck",
2078 : "<project>\n"
2079 : "<paths>\n"
2080 : "<dir name=\"dir\"/>\n"
2081 : "</paths>\n"
2082 4 : "</project>");
2083 1 : const char * const argv[] = {"cppcheck", "--project=project.cppcheck"};
2084 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(2, argv));
2085 1 : ASSERT_EQUALS(1, parser->getPathNames().size());
2086 1 : auto it = parser->getPathNames().cbegin();
2087 1 : ASSERT_EQUALS("dir", *it);
2088 : }
2089 :
2090 1 : void projectMultiple() {
2091 1 : REDIRECT;
2092 4 : ScopedFile file("project.cppcheck", "<project></project>");
2093 1 : const char * const argv[] = {"cppcheck", "--project=project.cppcheck", "--project=project.cppcheck", "file.cpp"};
2094 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(4, argv));
2095 1 : ASSERT_EQUALS("cppcheck: error: multiple --project options are not supported.\n", logger->str());
2096 : }
2097 :
2098 1 : void projectAndSource() {
2099 1 : REDIRECT;
2100 4 : ScopedFile file("project.cppcheck", "<project></project>");
2101 1 : const char * const argv[] = {"cppcheck", "--project=project.cppcheck", "file.cpp"};
2102 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
2103 1 : ASSERT_EQUALS("cppcheck: error: --project cannot be used in conjunction with source files.\n", logger->str());
2104 : }
2105 :
2106 1 : void projectEmpty() {
2107 1 : REDIRECT;
2108 1 : const char * const argv[] = {"cppcheck", "--project=", "file.cpp"};
2109 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
2110 1 : ASSERT_EQUALS("cppcheck: error: failed to open project ''. The file does not exist.\n", logger->str());
2111 : }
2112 :
2113 1 : void projectMissing() {
2114 1 : REDIRECT;
2115 1 : const char * const argv[] = {"cppcheck", "--project=project.cppcheck", "file.cpp"};
2116 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
2117 1 : ASSERT_EQUALS("cppcheck: error: failed to open project 'project.cppcheck'. The file does not exist.\n", logger->str());
2118 : }
2119 :
2120 1 : void projectNoPaths() {
2121 4 : ScopedFile file("project.cppcheck", "<project></project>");
2122 1 : const char * const argv[] = {"cppcheck", "--project=project.cppcheck"};
2123 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv));
2124 1 : ASSERT_EQUALS("cppcheck: error: no C or C++ source files found.\n", logger->str());
2125 : }
2126 :
2127 1 : void addon() {
2128 1 : REDIRECT;
2129 1 : const char * const argv[] = {"cppcheck", "--addon=misra", "file.cpp"};
2130 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
2131 1 : ASSERT_EQUALS(1, settings->addons.size());
2132 1 : ASSERT_EQUALS("misra", *settings->addons.cbegin());
2133 : }
2134 :
2135 1 : void addonMissing() {
2136 1 : REDIRECT;
2137 1 : const char * const argv[] = {"cppcheck", "--addon=misra2", "file.cpp"};
2138 1 : ASSERT(!parser->fillSettingsFromArgs(3, argv));
2139 1 : ASSERT_EQUALS(1, settings->addons.size());
2140 1 : ASSERT_EQUALS("misra2", *settings->addons.cbegin());
2141 1 : ASSERT_EQUALS("Did not find addon misra2.py\n", logger->str());
2142 : }
2143 :
2144 1 : void signedChar() {
2145 1 : REDIRECT;
2146 1 : const char * const argv[] = {"cppcheck", "--fsigned-char", "file.cpp"};
2147 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
2148 1 : ASSERT_EQUALS('s', settings->platform.defaultSign);
2149 : }
2150 :
2151 1 : void signedChar2() {
2152 1 : REDIRECT;
2153 1 : const char * const argv[] = {"cppcheck", "--platform=avr8", "--fsigned-char", "file.cpp"};
2154 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv));
2155 1 : ASSERT_EQUALS('s', settings->platform.defaultSign);
2156 : }
2157 :
2158 1 : void unsignedChar() {
2159 1 : REDIRECT;
2160 1 : const char * const argv[] = {"cppcheck", "--funsigned-char", "file.cpp"};
2161 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
2162 1 : ASSERT_EQUALS('u', settings->platform.defaultSign);
2163 : }
2164 :
2165 1 : void unsignedChar2() {
2166 1 : REDIRECT;
2167 1 : const char * const argv[] = {"cppcheck", "--platform=mips32", "--funsigned-char", "file.cpp"};
2168 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv));
2169 1 : ASSERT_EQUALS('u', settings->platform.defaultSign);
2170 : }
2171 :
2172 1 : void signedCharUnsignedChar() {
2173 1 : REDIRECT;
2174 1 : const char * const argv[] = {"cppcheck", "--fsigned-char", "--funsigned-char", "file.cpp"};
2175 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv));
2176 1 : ASSERT_EQUALS('u', settings->platform.defaultSign);
2177 : }
2178 :
2179 : #ifdef HAVE_RULES
2180 : void rule() {
2181 : REDIRECT;
2182 : const char * const argv[] = {"cppcheck", "--rule=.+", "file.cpp"};
2183 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
2184 : ASSERT_EQUALS(1, settings->rules.size());
2185 : auto it = settings->rules.cbegin();
2186 : ASSERT_EQUALS(".+", it->pattern);
2187 : }
2188 :
2189 : void ruleMissingPattern() {
2190 : REDIRECT;
2191 : const char * const argv[] = {"cppcheck", "--rule=", "file.cpp"};
2192 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
2193 : ASSERT_EQUALS("cppcheck: error: no rule pattern provided.\n", logger->str());
2194 : }
2195 : #else
2196 1 : void ruleNotSupported() {
2197 1 : REDIRECT;
2198 1 : const char * const argv[] = {"cppcheck", "--rule=.+", "file.cpp"};
2199 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
2200 1 : ASSERT_EQUALS("cppcheck: error: Option --rule cannot be used as Cppcheck has not been built with rules support.\n", logger->str());
2201 : }
2202 : #endif
2203 :
2204 : #ifdef HAVE_RULES
2205 : void ruleFileMulti() {
2206 : REDIRECT;
2207 : ScopedFile file("rule.xml",
2208 : "<rules>\n"
2209 : "<rule>\n"
2210 : "<tokenlist>raw</tokenlist>\n"
2211 : "<pattern>.+</pattern>\n"
2212 : "<message>\n"
2213 : "<severity>error</severity>\n"
2214 : "<id>ruleId1</id>\n"
2215 : "<summary>ruleSummary1</summary>\n"
2216 : "</message>\n"
2217 : "</rule>\n"
2218 : "<rule>\n"
2219 : "<tokenlist>define</tokenlist>\n"
2220 : "<pattern>.*</pattern>\n"
2221 : "<message>\n"
2222 : "<severity>warning</severity>\n"
2223 : "<id>ruleId2</id>\n"
2224 : "<summary>ruleSummary2</summary>\n"
2225 : "</message>\n"
2226 : "</rule>\n"
2227 : "</rules>");
2228 : const char * const argv[] = {"cppcheck", "--rule-file=rule.xml", "file.cpp"};
2229 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
2230 : ASSERT_EQUALS(2, settings->rules.size());
2231 : auto it = settings->rules.cbegin();
2232 : ASSERT_EQUALS("raw", it->tokenlist);
2233 : ASSERT_EQUALS(".+", it->pattern);
2234 : ASSERT_EQUALS_ENUM(Severity::error, it->severity);
2235 : ASSERT_EQUALS("ruleId1", it->id);
2236 : ASSERT_EQUALS("ruleSummary1", it->summary);
2237 : ++it;
2238 : ASSERT_EQUALS("define", it->tokenlist);
2239 : ASSERT_EQUALS(".*", it->pattern);
2240 : ASSERT_EQUALS_ENUM(Severity::warning, it->severity);
2241 : ASSERT_EQUALS("ruleId2", it->id);
2242 : ASSERT_EQUALS("ruleSummary2", it->summary);
2243 : }
2244 :
2245 : void ruleFileSingle() {
2246 : REDIRECT;
2247 : ScopedFile file("rule.xml",
2248 : "<rule>\n"
2249 : "<tokenlist>define</tokenlist>\n"
2250 : "<pattern>.+</pattern>\n"
2251 : "<message>\n"
2252 : "<severity>error</severity>\n"
2253 : "<id>ruleId</id>\n"
2254 : "<summary>ruleSummary</summary>\n"
2255 : "</message>\n"
2256 : "</rule>\n");
2257 : const char * const argv[] = {"cppcheck", "--rule-file=rule.xml", "file.cpp"};
2258 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
2259 : ASSERT_EQUALS(1, settings->rules.size());
2260 : auto it = settings->rules.cbegin();
2261 : ASSERT_EQUALS("define", it->tokenlist);
2262 : ASSERT_EQUALS(".+", it->pattern);
2263 : ASSERT_EQUALS_ENUM(Severity::error, it->severity);
2264 : ASSERT_EQUALS("ruleId", it->id);
2265 : ASSERT_EQUALS("ruleSummary", it->summary);
2266 : }
2267 :
2268 : void ruleFileEmpty() {
2269 : REDIRECT;
2270 : const char * const argv[] = {"cppcheck", "--rule-file=", "file.cpp"};
2271 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
2272 : ASSERT_EQUALS("cppcheck: error: unable to load rule-file '' (XML_ERROR_FILE_NOT_FOUND).\n", logger->str());
2273 : }
2274 :
2275 : void ruleFileMissing() {
2276 : REDIRECT;
2277 : const char * const argv[] = {"cppcheck", "--rule-file=rule.xml", "file.cpp"};
2278 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
2279 : ASSERT_EQUALS("cppcheck: error: unable to load rule-file 'rule.xml' (XML_ERROR_FILE_NOT_FOUND).\n", logger->str());
2280 : }
2281 :
2282 : void ruleFileInvalid() {
2283 : REDIRECT;
2284 : ScopedFile file("rule.xml", "");
2285 : const char * const argv[] = {"cppcheck", "--rule-file=rule.xml", "file.cpp"};
2286 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
2287 : ASSERT_EQUALS("cppcheck: error: unable to load rule-file 'rule.xml' (XML_ERROR_EMPTY_DOCUMENT).\n", logger->str());
2288 : }
2289 :
2290 : void ruleFileNoRoot() {
2291 : REDIRECT;
2292 : ScopedFile file("rule.xml", "<?xml version=\"1.0\"?>");
2293 : const char * const argv[] = {"cppcheck", "--rule-file=rule.xml", "file.cpp"};
2294 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
2295 : ASSERT_EQUALS(0, settings->rules.size());
2296 : }
2297 :
2298 : void ruleFileEmptyElements1() {
2299 : REDIRECT;
2300 : ScopedFile file("rule.xml",
2301 : "<rule>"
2302 : "<tokenlist/>"
2303 : "<pattern/>"
2304 : "<message/>"
2305 : "</rule>"
2306 : );
2307 : const char * const argv[] = {"cppcheck", "--rule-file=rule.xml", "file.cpp"};
2308 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); // do not crash
2309 : ASSERT_EQUALS("cppcheck: error: unable to load rule-file 'rule.xml' - a rule is lacking a pattern.\n", logger->str());
2310 : }
2311 :
2312 : void ruleFileEmptyElements2() {
2313 : REDIRECT;
2314 : ScopedFile file("rule.xml",
2315 : "<rule>"
2316 : "<message>"
2317 : "<severity/>"
2318 : "<id/>"
2319 : "<summary/>"
2320 : "</message>"
2321 : "</rule>"
2322 : );
2323 : const char * const argv[] = {"cppcheck", "--rule-file=rule.xml", "file.cpp"};
2324 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); // do not crash
2325 : ASSERT_EQUALS("cppcheck: error: unable to load rule-file 'rule.xml' - a rule is lacking a pattern.\n", logger->str());
2326 : }
2327 :
2328 : void ruleFileUnknownElement1() {
2329 : REDIRECT;
2330 : ScopedFile file("rule.xml",
2331 : "<rule>"
2332 : "<messages/>"
2333 : "</rule>"
2334 : );
2335 : const char * const argv[] = {"cppcheck", "--rule-file=rule.xml", "file.cpp"};
2336 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
2337 : ASSERT_EQUALS("cppcheck: error: unable to load rule-file 'rule.xml' - unknown element 'messages' encountered in 'rule'.\n", logger->str());
2338 : }
2339 :
2340 : void ruleFileUnknownElement2() {
2341 : REDIRECT;
2342 : ScopedFile file("rule.xml",
2343 : "<rule>"
2344 : "<message>"
2345 : "<pattern/>"
2346 : "</message>"
2347 : "</rule>"
2348 : );
2349 : const char * const argv[] = {"cppcheck", "--rule-file=rule.xml", "file.cpp"};
2350 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
2351 : ASSERT_EQUALS("cppcheck: error: unable to load rule-file 'rule.xml' - unknown element 'pattern' encountered in 'message'.\n", logger->str());
2352 : }
2353 :
2354 : void ruleFileMissingTokenList() {
2355 : REDIRECT;
2356 : ScopedFile file("rule.xml",
2357 : "<rule>\n"
2358 : "<tokenlist/>\n"
2359 : "<pattern>.+</pattern>\n"
2360 : "</rule>\n");
2361 : const char * const argv[] = {"cppcheck", "--rule-file=rule.xml", "file.cpp"};
2362 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
2363 : ASSERT_EQUALS("cppcheck: error: unable to load rule-file 'rule.xml' - a rule is lacking a tokenlist.\n", logger->str());
2364 : }
2365 :
2366 : void ruleFileUnknownTokenList() {
2367 : REDIRECT;
2368 : ScopedFile file("rule.xml",
2369 : "<rule>\n"
2370 : "<tokenlist>simple</tokenlist>\n"
2371 : "<pattern>.+</pattern>\n"
2372 : "</rule>\n");
2373 : const char * const argv[] = {"cppcheck", "--rule-file=rule.xml", "file.cpp"};
2374 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
2375 : ASSERT_EQUALS("cppcheck: error: unable to load rule-file 'rule.xml' - a rule is using the unsupported tokenlist 'simple'.\n", logger->str());
2376 : }
2377 :
2378 : void ruleFileMissingId() {
2379 : REDIRECT;
2380 : ScopedFile file("rule.xml",
2381 : "<rule>\n"
2382 : "<pattern>.+</pattern>\n"
2383 : "<message>\n"
2384 : "<id/>"
2385 : "</message>\n"
2386 : "</rule>\n");
2387 : const char * const argv[] = {"cppcheck", "--rule-file=rule.xml", "file.cpp"};
2388 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
2389 : ASSERT_EQUALS("cppcheck: error: unable to load rule-file 'rule.xml' - a rule is lacking an id.\n", logger->str());
2390 : }
2391 :
2392 : void ruleFileInvalidSeverity1() {
2393 : REDIRECT;
2394 : ScopedFile file("rule.xml",
2395 : "<rule>\n"
2396 : "<pattern>.+</pattern>\n"
2397 : "<message>\n"
2398 : "<severity/>"
2399 : "</message>\n"
2400 : "</rule>\n");
2401 : const char * const argv[] = {"cppcheck", "--rule-file=rule.xml", "file.cpp"};
2402 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
2403 : ASSERT_EQUALS("cppcheck: error: unable to load rule-file 'rule.xml' - a rule has an invalid severity.\n", logger->str());
2404 : }
2405 :
2406 : void ruleFileInvalidSeverity2() {
2407 : REDIRECT;
2408 : ScopedFile file("rule.xml",
2409 : "<rule>\n"
2410 : "<pattern>.+</pattern>\n"
2411 : "<message>\n"
2412 : "<severity>none</severity>"
2413 : "</message>\n"
2414 : "</rule>\n");
2415 : const char * const argv[] = {"cppcheck", "--rule-file=rule.xml", "file.cpp"};
2416 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
2417 : ASSERT_EQUALS("cppcheck: error: unable to load rule-file 'rule.xml' - a rule has an invalid severity.\n", logger->str());
2418 : }
2419 : #else
2420 1 : void ruleFileNotSupported() {
2421 1 : REDIRECT;
2422 1 : const char * const argv[] = {"cppcheck", "--rule-file=rule.xml", "file.cpp"};
2423 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
2424 1 : ASSERT_EQUALS("cppcheck: error: Option --rule-file cannot be used as Cppcheck has not been built with rules support.\n", logger->str());
2425 : }
2426 : #endif
2427 :
2428 1 : void library() {
2429 1 : REDIRECT;
2430 1 : const char * const argv[] = {"cppcheck", "--library=posix", "file.cpp"};
2431 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
2432 1 : ASSERT_EQUALS(1, settings->libraries.size());
2433 1 : ASSERT_EQUALS("posix", *settings->libraries.cbegin());
2434 : }
2435 :
2436 1 : void libraryMissing() {
2437 1 : REDIRECT;
2438 1 : const char * const argv[] = {"cppcheck", "--library=posix2", "file.cpp"};
2439 1 : ASSERT_EQUALS(false, parser->fillSettingsFromArgs(3, argv));
2440 1 : ASSERT_EQUALS(1, settings->libraries.size());
2441 1 : ASSERT_EQUALS("posix2", *settings->libraries.cbegin());
2442 1 : ASSERT_EQUALS("cppcheck: Failed to load library configuration file 'posix2'. File not found\n", logger->str());
2443 : }
2444 :
2445 1 : void suppressXml() {
2446 1 : REDIRECT;
2447 : ScopedFile file("suppress.xml",
2448 : "<suppressions>\n"
2449 : "<suppress>\n"
2450 : "<id>uninitvar</id>\n"
2451 : "</suppress>\n"
2452 4 : "</suppressions>");
2453 1 : const char * const argv[] = {"cppcheck", "--suppress-xml=suppress.xml", "file.cpp"};
2454 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
2455 1 : const auto& supprs = settings->supprs.nomsg.getSuppressions();
2456 1 : ASSERT_EQUALS(1, supprs.size());
2457 1 : const auto it = supprs.cbegin();
2458 1 : ASSERT_EQUALS("uninitvar", it->errorId);
2459 : }
2460 :
2461 1 : void suppressXmlEmpty() {
2462 1 : REDIRECT;
2463 1 : const char * const argv[] = {"cppcheck", "--suppress-xml=", "file.cpp"};
2464 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
2465 1 : ASSERT_EQUALS("cppcheck: error: failed to load suppressions XML '' (XML_ERROR_FILE_NOT_FOUND).\n", logger->str());
2466 : }
2467 :
2468 1 : void suppressXmlMissing() {
2469 1 : REDIRECT;
2470 1 : const char * const argv[] = {"cppcheck", "--suppress-xml=suppress.xml", "file.cpp"};
2471 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
2472 1 : ASSERT_EQUALS("cppcheck: error: failed to load suppressions XML 'suppress.xml' (XML_ERROR_FILE_NOT_FOUND).\n", logger->str());
2473 : }
2474 :
2475 1 : void suppressXmlInvalid() {
2476 1 : REDIRECT;
2477 4 : ScopedFile file("suppress.xml", "");
2478 1 : const char * const argv[] = {"cppcheck", "--suppress-xml=suppress.xml", "file.cpp"};
2479 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
2480 1 : ASSERT_EQUALS("cppcheck: error: failed to load suppressions XML 'suppress.xml' (XML_ERROR_EMPTY_DOCUMENT).\n", logger->str());
2481 : }
2482 :
2483 1 : void suppressXmlNoRoot() {
2484 1 : REDIRECT;
2485 4 : ScopedFile file("suppress.xml", "<?xml version=\"1.0\"?>");
2486 1 : const char * const argv[] = {"cppcheck", "--suppress-xml=suppress.xml", "file.cpp"};
2487 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
2488 1 : ASSERT_EQUALS("cppcheck: error: failed to load suppressions XML 'suppress.xml' (no root node found).\n", logger->str());
2489 : }
2490 :
2491 1 : void executorDefault() {
2492 1 : REDIRECT;
2493 1 : const char * const argv[] = {"cppcheck", "file.cpp"};
2494 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(2, argv));
2495 : #if defined(HAS_THREADING_MODEL_FORK)
2496 1 : ASSERT_EQUALS_ENUM(Settings::ExecutorType::Process, settings->executor);
2497 : #elif defined(HAS_THREADING_MODEL_THREAD)
2498 : ASSERT_EQUALS_ENUM(Settings::ExecutorType::Thread, settings->executor);
2499 : #endif
2500 : }
2501 :
2502 1 : void executorAuto() {
2503 1 : REDIRECT;
2504 1 : const char * const argv[] = {"cppcheck", "-j2", "--executor=auto", "file.cpp"};
2505 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv));
2506 : #if defined(HAS_THREADING_MODEL_FORK)
2507 1 : ASSERT_EQUALS_ENUM(Settings::ExecutorType::Process, settings->executor);
2508 : #elif defined(HAS_THREADING_MODEL_THREAD)
2509 : ASSERT_EQUALS_ENUM(Settings::ExecutorType::Thread, settings->executor);
2510 : #endif
2511 : }
2512 :
2513 1 : void executorAutoNoJobs() {
2514 1 : REDIRECT;
2515 1 : const char * const argv[] = {"cppcheck", "--executor=auto", "file.cpp"};
2516 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
2517 : #if defined(HAS_THREADING_MODEL_FORK)
2518 1 : ASSERT_EQUALS_ENUM(Settings::ExecutorType::Process, settings->executor);
2519 : #elif defined(HAS_THREADING_MODEL_THREAD)
2520 : ASSERT_EQUALS_ENUM(Settings::ExecutorType::Thread, settings->executor);
2521 : #endif
2522 : }
2523 :
2524 : #if defined(HAS_THREADING_MODEL_THREAD)
2525 1 : void executorThread() {
2526 1 : REDIRECT;
2527 1 : const char * const argv[] = {"cppcheck", "-j2", "--executor=thread", "file.cpp"};
2528 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv));
2529 1 : ASSERT_EQUALS_ENUM(Settings::ExecutorType::Thread, settings->executor);
2530 : }
2531 :
2532 1 : void executorThreadNoJobs() {
2533 1 : REDIRECT;
2534 1 : const char * const argv[] = {"cppcheck", "--executor=thread", "file.cpp"};
2535 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
2536 1 : ASSERT_EQUALS_ENUM(Settings::ExecutorType::Thread, settings->executor);
2537 1 : ASSERT_EQUALS("cppcheck: '--executor' has no effect as only a single job will be used.\n", logger->str());
2538 : }
2539 : #else
2540 : void executorThreadNotSupported() {
2541 : REDIRECT;
2542 : const char * const argv[] = {"cppcheck", "-j2", "--executor=thread", "file.cpp"};
2543 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(4, argv));
2544 : ASSERT_EQUALS("cppcheck: error: executor type 'thread' cannot be used as Cppcheck has not been built with a respective threading model.\n", logger->str());
2545 : }
2546 : #endif
2547 :
2548 : #if defined(HAS_THREADING_MODEL_FORK)
2549 1 : void executorProcess() {
2550 1 : REDIRECT;
2551 1 : const char * const argv[] = {"cppcheck", "-j2", "--executor=process", "file.cpp"};
2552 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv));
2553 1 : ASSERT_EQUALS_ENUM(Settings::ExecutorType::Process, settings->executor);
2554 : }
2555 :
2556 1 : void executorProcessNoJobs() {
2557 1 : REDIRECT;
2558 1 : const char * const argv[] = {"cppcheck", "--executor=process", "file.cpp"};
2559 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
2560 1 : ASSERT_EQUALS_ENUM(Settings::ExecutorType::Process, settings->executor);
2561 1 : ASSERT_EQUALS("cppcheck: '--executor' has no effect as only a single job will be used.\n", logger->str());
2562 : }
2563 : #else
2564 : void executorProcessNotSupported() {
2565 : REDIRECT;
2566 : const char * const argv[] = {"cppcheck", "-j2", "--executor=process", "file.cpp"};
2567 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(4, argv));
2568 : ASSERT_EQUALS("cppcheck: error: executor type 'process' cannot be used as Cppcheck has not been built with a respective threading model.\n", logger->str());
2569 : }
2570 : #endif
2571 :
2572 1 : void checkLevelDefault() {
2573 1 : REDIRECT;
2574 1 : const char * const argv[] = {"cppcheck", "file.cpp"};
2575 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(2, argv));
2576 1 : ASSERT_EQUALS_ENUM(Settings::CheckLevel::normal, settings->checkLevel);
2577 1 : ASSERT_EQUALS(100, settings->performanceValueFlowMaxIfCount);
2578 1 : ASSERT_EQUALS(8, settings->performanceValueFlowMaxSubFunctionArgs);
2579 : }
2580 :
2581 1 : void checkLevelNormal() {
2582 1 : REDIRECT;
2583 1 : const char * const argv[] = {"cppcheck", "--check-level=normal", "file.cpp"};
2584 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
2585 1 : ASSERT_EQUALS_ENUM(Settings::CheckLevel::normal, settings->checkLevel);
2586 1 : ASSERT_EQUALS(100, settings->performanceValueFlowMaxIfCount);
2587 1 : ASSERT_EQUALS(8, settings->performanceValueFlowMaxSubFunctionArgs);
2588 : }
2589 :
2590 1 : void checkLevelExhaustive() {
2591 1 : REDIRECT;
2592 1 : const char * const argv[] = {"cppcheck", "--check-level=exhaustive", "file.cpp"};
2593 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
2594 1 : ASSERT_EQUALS_ENUM(Settings::CheckLevel::exhaustive, settings->checkLevel);
2595 1 : ASSERT_EQUALS(-1, settings->performanceValueFlowMaxIfCount);
2596 1 : ASSERT_EQUALS(256, settings->performanceValueFlowMaxSubFunctionArgs);
2597 : }
2598 :
2599 1 : void checkLevelUnknown() {
2600 1 : REDIRECT;
2601 1 : const char * const argv[] = {"cppcheck", "--check-level=default", "file.cpp"};
2602 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
2603 1 : ASSERT_EQUALS("cppcheck: error: unknown '--check-level' value 'default'.\n", logger->str());
2604 : }
2605 :
2606 1 : void ignorepaths1() {
2607 1 : REDIRECT;
2608 1 : const char * const argv[] = {"cppcheck", "-isrc", "file.cpp"};
2609 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
2610 1 : ASSERT_EQUALS(1, parser->getIgnoredPaths().size());
2611 1 : ASSERT_EQUALS("src", parser->getIgnoredPaths()[0]);
2612 : }
2613 :
2614 1 : void ignorepaths2() {
2615 1 : REDIRECT;
2616 1 : const char * const argv[] = {"cppcheck", "-i", "src", "file.cpp"};
2617 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv));
2618 1 : ASSERT_EQUALS(1, parser->getIgnoredPaths().size());
2619 1 : ASSERT_EQUALS("src", parser->getIgnoredPaths()[0]);
2620 : }
2621 :
2622 1 : void ignorepaths3() {
2623 1 : REDIRECT;
2624 1 : const char * const argv[] = {"cppcheck", "-isrc", "-imodule", "file.cpp"};
2625 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv));
2626 1 : ASSERT_EQUALS(2, parser->getIgnoredPaths().size());
2627 1 : ASSERT_EQUALS("src", parser->getIgnoredPaths()[0]);
2628 1 : ASSERT_EQUALS("module", parser->getIgnoredPaths()[1]);
2629 : }
2630 :
2631 1 : void ignorepaths4() {
2632 1 : REDIRECT;
2633 1 : const char * const argv[] = {"cppcheck", "-i", "src", "-i", "module", "file.cpp"};
2634 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(6, argv));
2635 1 : ASSERT_EQUALS(2, parser->getIgnoredPaths().size());
2636 1 : ASSERT_EQUALS("src", parser->getIgnoredPaths()[0]);
2637 1 : ASSERT_EQUALS("module", parser->getIgnoredPaths()[1]);
2638 : }
2639 :
2640 1 : void ignorefilepaths1() {
2641 1 : REDIRECT;
2642 1 : const char * const argv[] = {"cppcheck", "-ifoo.cpp", "file.cpp"};
2643 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
2644 1 : ASSERT_EQUALS(1, parser->getIgnoredPaths().size());
2645 1 : ASSERT_EQUALS("foo.cpp", parser->getIgnoredPaths()[0]);
2646 : }
2647 :
2648 1 : void ignorefilepaths2() {
2649 1 : REDIRECT;
2650 1 : const char * const argv[] = {"cppcheck", "-isrc/foo.cpp", "file.cpp"};
2651 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
2652 1 : ASSERT_EQUALS(1, parser->getIgnoredPaths().size());
2653 1 : ASSERT_EQUALS("src/foo.cpp", parser->getIgnoredPaths()[0]);
2654 : }
2655 :
2656 1 : void ignorefilepaths3() {
2657 1 : REDIRECT;
2658 1 : const char * const argv[] = {"cppcheck", "-i", "foo.cpp", "file.cpp"};
2659 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv));
2660 1 : ASSERT_EQUALS(1, parser->getIgnoredPaths().size());
2661 1 : ASSERT_EQUALS("foo.cpp", parser->getIgnoredPaths()[0]);
2662 : }
2663 :
2664 1 : void checkconfig() {
2665 1 : REDIRECT;
2666 1 : const char * const argv[] = {"cppcheck", "--check-config", "file.cpp"};
2667 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
2668 1 : ASSERT_EQUALS(true, settings->checkConfiguration);
2669 : }
2670 :
2671 1 : void unknownParam() {
2672 1 : REDIRECT;
2673 1 : const char * const argv[] = {"cppcheck", "--foo", "file.cpp"};
2674 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
2675 1 : ASSERT_EQUALS("cppcheck: error: unrecognized command line option: \"--foo\".\n", logger->str());
2676 : }
2677 :
2678 1 : void undefs() {
2679 1 : REDIRECT;
2680 1 : const char * const argv[] = {"cppcheck", "-U_WIN32", "file.cpp"};
2681 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
2682 1 : ASSERT_EQUALS(1, settings->userUndefs.size());
2683 1 : ASSERT(settings->userUndefs.find("_WIN32") != settings->userUndefs.end());
2684 : }
2685 :
2686 1 : void undefs2() {
2687 1 : REDIRECT;
2688 1 : const char * const argv[] = {"cppcheck", "-U_WIN32", "-UNODEBUG", "file.cpp"};
2689 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv));
2690 1 : ASSERT_EQUALS(2, settings->userUndefs.size());
2691 1 : ASSERT(settings->userUndefs.find("_WIN32") != settings->userUndefs.end());
2692 1 : ASSERT(settings->userUndefs.find("NODEBUG") != settings->userUndefs.end());
2693 : }
2694 :
2695 1 : void undefs_noarg() {
2696 1 : REDIRECT;
2697 1 : const char * const argv[] = {"cppcheck", "-U"};
2698 : // Fails since -U has no param
2699 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv));
2700 1 : ASSERT_EQUALS("cppcheck: error: argument to '-U' is missing.\n", logger->str());
2701 : }
2702 :
2703 1 : void undefs_noarg2() {
2704 1 : REDIRECT;
2705 1 : const char * const argv[] = {"cppcheck", "-U", "-v", "file.cpp"};
2706 : // Fails since -U has no param
2707 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(4, argv));
2708 1 : ASSERT_EQUALS("cppcheck: error: argument to '-U' is missing.\n", logger->str());
2709 : }
2710 :
2711 1 : void undefs_noarg3() {
2712 1 : REDIRECT;
2713 1 : const char * const argv[] = {"cppcheck", "-U", "--quiet", "file.cpp"};
2714 : // Fails since -U has no param
2715 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(4, argv));
2716 1 : ASSERT_EQUALS("cppcheck: error: argument to '-U' is missing.\n", logger->str());
2717 : }
2718 :
2719 1 : void cppcheckBuildDirExistent() {
2720 1 : REDIRECT;
2721 1 : const char * const argv[] = {"cppcheck", "--cppcheck-build-dir=.", "file.cpp"};
2722 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
2723 : }
2724 :
2725 1 : void cppcheckBuildDirNonExistent() {
2726 1 : REDIRECT;
2727 1 : const char * const argv[] = {"cppcheck", "--cppcheck-build-dir=non-existent-path"};
2728 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv));
2729 1 : ASSERT_EQUALS("cppcheck: error: Directory 'non-existent-path' specified by --cppcheck-build-dir argument has to be existent.\n", logger->str());
2730 : }
2731 :
2732 1 : void cppcheckBuildDirEmpty() {
2733 1 : REDIRECT;
2734 1 : const char * const argv[] = {"cppcheck", "--cppcheck-build-dir="};
2735 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv));
2736 1 : ASSERT_EQUALS("cppcheck: error: Directory '' specified by --cppcheck-build-dir argument has to be existent.\n", logger->str());
2737 : }
2738 :
2739 1 : void invalidCppcheckCfg() {
2740 1 : REDIRECT;
2741 2 : ScopedFile file(Path::join(Path::getPathFromFilename(Path::getCurrentExecutablePath("")), "cppcheck.cfg"),
2742 4 : "{\n");
2743 1 : const char * const argv[] = {"cppcheck", "test.cpp"};
2744 1 : ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv));
2745 1 : ASSERT_EQUALS("cppcheck: error: could not load cppcheck.cfg - not a valid JSON - syntax error at line 2 near: \n", logger->str());
2746 : }
2747 : };
2748 :
2749 : REGISTER_TEST(TestCmdlineParser)
|