1 /* 2 * Cppcheck - A tool for static C/C++ code analysis 3 * Copyright (C) 2007-2021 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 "cmdlineparser.h" 20 #include "platform.h" 21 #include "redirect.h" 22 #include "settings.h" 23 #include "standards.h" 24 #include "suppressions.h" 25 #include "testsuite.h" 26 #include "timer.h" 27 28 #include <list> 29 #include <set> 30 #include <string> 31 #include <vector> 32 33 class TestCmdlineParser : public TestFixture { 34 public: TestCmdlineParser()35 TestCmdlineParser() 36 : TestFixture("TestCmdlineParser") 37 , defParser(&settings) {} 38 39 private: 40 Settings settings; 41 CmdLineParser defParser; 42 run()43 void run() OVERRIDE { 44 TEST_CASE(nooptions); 45 TEST_CASE(helpshort); 46 TEST_CASE(helplong); 47 TEST_CASE(showversion); 48 TEST_CASE(onefile); 49 TEST_CASE(onepath); 50 TEST_CASE(optionwithoutfile); 51 TEST_CASE(verboseshort); 52 TEST_CASE(verboselong); 53 TEST_CASE(debugSimplified); 54 TEST_CASE(debugwarnings); 55 TEST_CASE(forceshort); 56 TEST_CASE(forcelong); 57 TEST_CASE(relativePaths); 58 TEST_CASE(quietshort); 59 TEST_CASE(quietlong); 60 TEST_CASE(defines_noarg); 61 TEST_CASE(defines_noarg2); 62 TEST_CASE(defines_noarg3); 63 TEST_CASE(defines); 64 TEST_CASE(defines2); 65 TEST_CASE(defines3); 66 TEST_CASE(defines4); 67 TEST_CASE(enforceLanguage); 68 TEST_CASE(includesnopath); 69 TEST_CASE(includes); 70 TEST_CASE(includesslash); 71 TEST_CASE(includesbackslash); 72 TEST_CASE(includesnospace); 73 TEST_CASE(includes2); 74 TEST_CASE(includesFile); 75 TEST_CASE(configExcludesFile); 76 TEST_CASE(enabledAll); 77 TEST_CASE(enabledStyle); 78 TEST_CASE(enabledPerformance); 79 TEST_CASE(enabledPortability); 80 TEST_CASE(enabledUnusedFunction); 81 TEST_CASE(enabledMissingInclude); 82 #ifdef CHECK_INTERNAL 83 TEST_CASE(enabledInternal); 84 #endif 85 TEST_CASE(enabledMultiple); 86 TEST_CASE(inconclusive); 87 TEST_CASE(errorExitcode); 88 TEST_CASE(errorExitcodeMissing); 89 TEST_CASE(errorExitcodeStr); 90 TEST_CASE(exitcodeSuppressionsOld); // TODO: Create and test real suppression file 91 TEST_CASE(exitcodeSuppressions); 92 TEST_CASE(exitcodeSuppressionsNoFile); 93 TEST_CASE(fileList); // TODO: Create and test real file listing file 94 // TEST_CASE(fileListStdin); // Disabled since hangs the test run 95 TEST_CASE(inlineSuppr); 96 TEST_CASE(jobs); 97 TEST_CASE(jobsMissingCount); 98 TEST_CASE(jobsInvalid); 99 TEST_CASE(maxConfigs); 100 TEST_CASE(maxConfigsMissingCount); 101 TEST_CASE(maxConfigsInvalid); 102 TEST_CASE(maxConfigsTooSmall); 103 TEST_CASE(reportProgressTest); // "Test" suffix to avoid hiding the parent's reportProgress 104 TEST_CASE(stdc99); 105 TEST_CASE(stdcpp11); 106 TEST_CASE(platform); 107 TEST_CASE(plistEmpty); 108 TEST_CASE(plistDoesNotExist); 109 TEST_CASE(suppressionsOld); // TODO: Create and test real suppression file 110 TEST_CASE(suppressions); 111 TEST_CASE(suppressionsNoFile); 112 TEST_CASE(suppressionSingle); 113 TEST_CASE(suppressionSingleFile); 114 TEST_CASE(suppressionTwo); 115 TEST_CASE(suppressionTwoSeparate); 116 TEST_CASE(templates); 117 TEST_CASE(templatesGcc); 118 TEST_CASE(templatesVs); 119 TEST_CASE(templatesEdit); 120 TEST_CASE(xml); 121 TEST_CASE(xmlver2); 122 TEST_CASE(xmlver2both); 123 TEST_CASE(xmlver2both2); 124 TEST_CASE(xmlverunknown); 125 TEST_CASE(xmlverinvalid); 126 TEST_CASE(doc); 127 TEST_CASE(showtime); 128 TEST_CASE(errorlist1); 129 TEST_CASE(errorlistverbose1); 130 TEST_CASE(errorlistverbose2); 131 TEST_CASE(ignorepathsnopath); 132 133 // Disabling these tests since they use relative paths to the 134 // testrunner executable. 135 //TEST_CASE(ignorepaths1); 136 //TEST_CASE(ignorepaths2); 137 //TEST_CASE(ignorepaths3); 138 //TEST_CASE(ignorepaths4); 139 //TEST_CASE(ignorefilepaths1); 140 //TEST_CASE(ignorefilepaths2); 141 142 TEST_CASE(checkconfig); 143 TEST_CASE(unknownParam); 144 145 TEST_CASE(undefs_noarg); 146 TEST_CASE(undefs_noarg2); 147 TEST_CASE(undefs_noarg3); 148 TEST_CASE(undefs); 149 TEST_CASE(undefs2); 150 } 151 152 nooptions()153 void nooptions() { 154 REDIRECT; 155 const char * const argv[] = {"cppcheck"}; 156 CmdLineParser parser(&settings); 157 ASSERT(parser.parseFromArgs(1, argv)); 158 ASSERT_EQUALS(true, parser.getShowHelp()); 159 } 160 helpshort()161 void helpshort() { 162 REDIRECT; 163 const char * const argv[] = {"cppcheck", "-h"}; 164 CmdLineParser parser(&settings); 165 ASSERT(parser.parseFromArgs(2, argv)); 166 ASSERT_EQUALS(true, parser.getShowHelp()); 167 } 168 helplong()169 void helplong() { 170 REDIRECT; 171 const char * const argv[] = {"cppcheck", "--help"}; 172 CmdLineParser parser(&settings); 173 ASSERT(parser.parseFromArgs(2, argv)); 174 ASSERT_EQUALS(true, parser.getShowHelp()); 175 } 176 showversion()177 void showversion() { 178 REDIRECT; 179 const char * const argv[] = {"cppcheck", "--version"}; 180 CmdLineParser parser(&settings); 181 ASSERT(parser.parseFromArgs(2, argv)); 182 ASSERT_EQUALS(true, parser.getShowVersion()); 183 } 184 onefile()185 void onefile() { 186 REDIRECT; 187 const char * const argv[] = {"cppcheck", "file.cpp"}; 188 CmdLineParser parser(&settings); 189 ASSERT(parser.parseFromArgs(2, argv)); 190 ASSERT_EQUALS(1, (int)parser.getPathNames().size()); 191 ASSERT_EQUALS("file.cpp", parser.getPathNames().at(0)); 192 } 193 onepath()194 void onepath() { 195 REDIRECT; 196 const char * const argv[] = {"cppcheck", "src"}; 197 CmdLineParser parser(&settings); 198 ASSERT(parser.parseFromArgs(2, argv)); 199 ASSERT_EQUALS(1, (int)parser.getPathNames().size()); 200 ASSERT_EQUALS("src", parser.getPathNames().at(0)); 201 } 202 optionwithoutfile()203 void optionwithoutfile() { 204 REDIRECT; 205 const char * const argv[] = {"cppcheck", "-v"}; 206 CmdLineParser parser(&settings); 207 ASSERT_EQUALS(false, parser.parseFromArgs(2, argv)); 208 ASSERT_EQUALS(0, (int)parser.getPathNames().size()); 209 } 210 verboseshort()211 void verboseshort() { 212 REDIRECT; 213 const char * const argv[] = {"cppcheck", "-v", "file.cpp"}; 214 settings.verbose = false; 215 ASSERT(defParser.parseFromArgs(3, argv)); 216 ASSERT_EQUALS(true, settings.verbose); 217 } 218 verboselong()219 void verboselong() { 220 REDIRECT; 221 const char * const argv[] = {"cppcheck", "--verbose", "file.cpp"}; 222 settings.verbose = false; 223 ASSERT(defParser.parseFromArgs(3, argv)); 224 ASSERT_EQUALS(true, settings.verbose); 225 } 226 debugSimplified()227 void debugSimplified() { 228 REDIRECT; 229 const char * const argv[] = {"cppcheck", "--debug-simplified", "file.cpp"}; 230 settings.debugSimplified = false; 231 ASSERT(defParser.parseFromArgs(3, argv)); 232 ASSERT_EQUALS(true, settings.debugSimplified); 233 } 234 debugwarnings()235 void debugwarnings() { 236 REDIRECT; 237 const char * const argv[] = {"cppcheck", "--debug-warnings", "file.cpp"}; 238 settings.debugwarnings = false; 239 ASSERT(defParser.parseFromArgs(3, argv)); 240 ASSERT_EQUALS(true, settings.debugwarnings); 241 } 242 forceshort()243 void forceshort() { 244 REDIRECT; 245 const char * const argv[] = {"cppcheck", "-f", "file.cpp"}; 246 settings.force = false; 247 ASSERT(defParser.parseFromArgs(3, argv)); 248 ASSERT_EQUALS(true, settings.force); 249 } 250 forcelong()251 void forcelong() { 252 REDIRECT; 253 const char * const argv[] = {"cppcheck", "--force", "file.cpp"}; 254 settings.force = false; 255 ASSERT(defParser.parseFromArgs(3, argv)); 256 ASSERT_EQUALS(true, settings.force); 257 } 258 relativePaths()259 void relativePaths() { 260 REDIRECT; 261 settings.relativePaths = false; 262 263 const char * const argvs[] = {"cppcheck", "-rp", "file.cpp"}; 264 ASSERT(defParser.parseFromArgs(3, argvs)); 265 ASSERT_EQUALS(true, settings.relativePaths); 266 267 settings.relativePaths = false; 268 269 const char * const argvl[] = {"cppcheck", "--relative-paths", "file.cpp"}; 270 ASSERT(defParser.parseFromArgs(3, argvl)); 271 ASSERT_EQUALS(true, settings.relativePaths); 272 273 settings.relativePaths = false; 274 settings.basePaths.clear(); 275 276 const char * const argvsp[] = {"cppcheck", "-rp=C:/foo;C:\\bar", "file.cpp"}; 277 ASSERT(defParser.parseFromArgs(3, argvsp)); 278 ASSERT_EQUALS(true, settings.relativePaths); 279 ASSERT_EQUALS(2, settings.basePaths.size()); 280 ASSERT_EQUALS("C:/foo", settings.basePaths[0]); 281 ASSERT_EQUALS("C:/bar", settings.basePaths[1]); 282 283 settings.relativePaths = false; 284 settings.basePaths.clear(); 285 286 const char * const argvlp[] = {"cppcheck", "--relative-paths=C:/foo;C:\\bar", "file.cpp"}; 287 ASSERT(defParser.parseFromArgs(3, argvlp)); 288 ASSERT_EQUALS(true, settings.relativePaths); 289 ASSERT_EQUALS(2, settings.basePaths.size()); 290 ASSERT_EQUALS("C:/foo", settings.basePaths[0]); 291 ASSERT_EQUALS("C:/bar", settings.basePaths[1]); 292 } 293 quietshort()294 void quietshort() { 295 REDIRECT; 296 const char * const argv[] = {"cppcheck", "-q", "file.cpp"}; 297 settings.quiet = false; 298 ASSERT(defParser.parseFromArgs(3, argv)); 299 ASSERT_EQUALS(true, settings.quiet); 300 } 301 quietlong()302 void quietlong() { 303 REDIRECT; 304 const char * const argv[] = {"cppcheck", "--quiet", "file.cpp"}; 305 settings.quiet = false; 306 ASSERT(defParser.parseFromArgs(3, argv)); 307 ASSERT_EQUALS(true, settings.quiet); 308 } 309 defines_noarg()310 void defines_noarg() { 311 REDIRECT; 312 const char * const argv[] = {"cppcheck", "-D"}; 313 // Fails since -D has no param 314 ASSERT_EQUALS(false, defParser.parseFromArgs(2, argv)); 315 } 316 defines_noarg2()317 void defines_noarg2() { 318 REDIRECT; 319 const char * const argv[] = {"cppcheck", "-D", "-v", "file.cpp"}; 320 // Fails since -D has no param 321 ASSERT_EQUALS(false, defParser.parseFromArgs(4, argv)); 322 } 323 defines_noarg3()324 void defines_noarg3() { 325 REDIRECT; 326 const char * const argv[] = {"cppcheck", "-D", "--quiet", "file.cpp"}; 327 // Fails since -D has no param 328 ASSERT_EQUALS(false, defParser.parseFromArgs(4, argv)); 329 } 330 defines()331 void defines() { 332 REDIRECT; 333 const char * const argv[] = {"cppcheck", "-D_WIN32", "file.cpp"}; 334 settings.userDefines.clear(); 335 ASSERT(defParser.parseFromArgs(3, argv)); 336 ASSERT_EQUALS("_WIN32=1", settings.userDefines); 337 } 338 defines2()339 void defines2() { 340 REDIRECT; 341 const char * const argv[] = {"cppcheck", "-D_WIN32", "-DNODEBUG", "file.cpp"}; 342 settings.userDefines.clear(); 343 ASSERT(defParser.parseFromArgs(4, argv)); 344 ASSERT_EQUALS("_WIN32=1;NODEBUG=1", settings.userDefines); 345 } 346 defines3()347 void defines3() { 348 REDIRECT; 349 const char * const argv[] = {"cppcheck", "-D", "DEBUG", "file.cpp"}; 350 settings.userDefines.clear(); 351 ASSERT(defParser.parseFromArgs(4, argv)); 352 ASSERT_EQUALS("DEBUG=1", settings.userDefines); 353 } 354 defines4()355 void defines4() { 356 REDIRECT; 357 const char * const argv[] = {"cppcheck", "-DDEBUG=", "file.cpp"}; // #5137 - defining empty macro 358 settings.userDefines.clear(); 359 ASSERT(defParser.parseFromArgs(3, argv)); 360 ASSERT_EQUALS("DEBUG=", settings.userDefines); 361 } 362 enforceLanguage()363 void enforceLanguage() { 364 REDIRECT; 365 { 366 const char * const argv[] = {"cppcheck", "file.cpp"}; 367 settings.enforcedLang = Settings::None; 368 ASSERT(defParser.parseFromArgs(2, argv)); 369 ASSERT_EQUALS(Settings::None, settings.enforcedLang); 370 } 371 { 372 const char * const argv[] = {"cppcheck", "-x", "c++", "file.cpp"}; 373 settings.enforcedLang = Settings::None; 374 ASSERT(defParser.parseFromArgs(4, argv)); 375 ASSERT_EQUALS(Settings::CPP, settings.enforcedLang); 376 } 377 { 378 const char * const argv[] = {"cppcheck", "-x"}; 379 ASSERT(!defParser.parseFromArgs(2, argv)); 380 } 381 { 382 const char * const argv[] = {"cppcheck", "-x", "--inconclusive", "file.cpp"}; 383 ASSERT(!defParser.parseFromArgs(4, argv)); 384 } 385 { 386 const char * const argv[] = {"cppcheck", "--language=c++", "file.cpp"}; 387 settings.enforcedLang = Settings::None; 388 ASSERT(defParser.parseFromArgs(3, argv)); 389 ASSERT_EQUALS(Settings::CPP, settings.enforcedLang); 390 } 391 { 392 const char * const argv[] = {"cppcheck", "--language=c", "file.cpp"}; 393 settings.enforcedLang = Settings::None; 394 ASSERT(defParser.parseFromArgs(3, argv)); 395 ASSERT_EQUALS(Settings::C, settings.enforcedLang); 396 } 397 { 398 const char * const argv[] = {"cppcheck", "--language=unknownLanguage", "file.cpp"}; 399 ASSERT(!defParser.parseFromArgs(3, argv)); 400 } 401 } 402 includesnopath()403 void includesnopath() { 404 REDIRECT; 405 const char * const argv[] = {"cppcheck", "-I"}; 406 // Fails since -I has no param 407 ASSERT_EQUALS(false, defParser.parseFromArgs(2, argv)); 408 } 409 includes()410 void includes() { 411 REDIRECT; 412 const char * const argv[] = {"cppcheck", "-I", "include", "file.cpp"}; 413 settings.includePaths.clear(); 414 ASSERT(defParser.parseFromArgs(4, argv)); 415 ASSERT_EQUALS("include/", settings.includePaths.front()); 416 } 417 includesslash()418 void includesslash() { 419 REDIRECT; 420 const char * const argv[] = {"cppcheck", "-I", "include/", "file.cpp"}; 421 settings.includePaths.clear(); 422 ASSERT(defParser.parseFromArgs(4, argv)); 423 ASSERT_EQUALS("include/", settings.includePaths.front()); 424 } 425 includesbackslash()426 void includesbackslash() { 427 REDIRECT; 428 const char * const argv[] = {"cppcheck", "-I", "include\\", "file.cpp"}; 429 settings.includePaths.clear(); 430 ASSERT(defParser.parseFromArgs(4, argv)); 431 ASSERT_EQUALS("include/", settings.includePaths.front()); 432 } 433 includesnospace()434 void includesnospace() { 435 REDIRECT; 436 const char * const argv[] = {"cppcheck", "-Iinclude", "file.cpp"}; 437 settings.includePaths.clear(); 438 ASSERT(defParser.parseFromArgs(3, argv)); 439 ASSERT_EQUALS("include/", settings.includePaths.front()); 440 } 441 includes2()442 void includes2() { 443 REDIRECT; 444 const char * const argv[] = {"cppcheck", "-I", "include/", "-I", "framework/", "file.cpp"}; 445 settings.includePaths.clear(); 446 ASSERT(defParser.parseFromArgs(6, argv)); 447 ASSERT_EQUALS("include/", settings.includePaths.front()); 448 settings.includePaths.pop_front(); 449 ASSERT_EQUALS("framework/", settings.includePaths.front()); 450 } 451 includesFile()452 void includesFile() { 453 REDIRECT; 454 const char * const argv[] = {"cppcheck", "--includes-file=fileThatDoesNotExist.txt", "file.cpp"}; 455 settings.includePaths.clear(); 456 ASSERT_EQUALS(false, defParser.parseFromArgs(3, argv)); 457 } 458 configExcludesFile()459 void configExcludesFile() { 460 REDIRECT; 461 const char * const argv[] = {"cppcheck", "--config-excludes-file=fileThatDoesNotExist.txt", "file.cpp"}; 462 settings.includePaths.clear(); 463 ASSERT_EQUALS(false, defParser.parseFromArgs(3, argv)); 464 } 465 enabledAll()466 void enabledAll() { 467 REDIRECT; 468 const char * const argv[] = {"cppcheck", "--enable=all", "file.cpp"}; 469 settings = Settings(); 470 ASSERT(defParser.parseFromArgs(3, argv)); 471 ASSERT(settings.severity.isEnabled(Severity::style)); 472 ASSERT(settings.severity.isEnabled(Severity::warning)); 473 ASSERT(settings.checks.isEnabled(Checks::unusedFunction)); 474 ASSERT(settings.checks.isEnabled(Checks::missingInclude)); 475 ASSERT(!settings.checks.isEnabled(Checks::internalCheck)); 476 } 477 enabledStyle()478 void enabledStyle() { 479 REDIRECT; 480 const char * const argv[] = {"cppcheck", "--enable=style", "file.cpp"}; 481 settings = Settings(); 482 ASSERT(defParser.parseFromArgs(3, argv)); 483 ASSERT(settings.severity.isEnabled(Severity::style)); 484 ASSERT(settings.severity.isEnabled(Severity::warning)); 485 ASSERT(settings.severity.isEnabled(Severity::performance)); 486 ASSERT(settings.severity.isEnabled(Severity::portability)); 487 ASSERT(!settings.checks.isEnabled(Checks::unusedFunction)); 488 ASSERT(!settings.checks.isEnabled(Checks::internalCheck)); 489 } 490 enabledPerformance()491 void enabledPerformance() { 492 REDIRECT; 493 const char * const argv[] = {"cppcheck", "--enable=performance", "file.cpp"}; 494 settings = Settings(); 495 ASSERT(defParser.parseFromArgs(3, argv)); 496 ASSERT(!settings.severity.isEnabled(Severity::style)); 497 ASSERT(!settings.severity.isEnabled(Severity::warning)); 498 ASSERT(settings.severity.isEnabled(Severity::performance)); 499 ASSERT(!settings.severity.isEnabled(Severity::portability)); 500 ASSERT(!settings.checks.isEnabled(Checks::unusedFunction)); 501 ASSERT(!settings.checks.isEnabled(Checks::missingInclude)); 502 } 503 enabledPortability()504 void enabledPortability() { 505 REDIRECT; 506 const char * const argv[] = {"cppcheck", "--enable=portability", "file.cpp"}; 507 settings = Settings(); 508 ASSERT(defParser.parseFromArgs(3, argv)); 509 ASSERT(!settings.severity.isEnabled(Severity::style)); 510 ASSERT(!settings.severity.isEnabled(Severity::warning)); 511 ASSERT(!settings.severity.isEnabled(Severity::performance)); 512 ASSERT(settings.severity.isEnabled(Severity::portability)); 513 ASSERT(!settings.checks.isEnabled(Checks::unusedFunction)); 514 ASSERT(!settings.checks.isEnabled(Checks::missingInclude)); 515 } 516 enabledUnusedFunction()517 void enabledUnusedFunction() { 518 REDIRECT; 519 const char * const argv[] = {"cppcheck", "--enable=unusedFunction", "file.cpp"}; 520 settings = Settings(); 521 ASSERT(defParser.parseFromArgs(3, argv)); 522 ASSERT(settings.checks.isEnabled(Checks::unusedFunction)); 523 } 524 enabledMissingInclude()525 void enabledMissingInclude() { 526 REDIRECT; 527 const char * const argv[] = {"cppcheck", "--enable=missingInclude", "file.cpp"}; 528 settings = Settings(); 529 ASSERT(defParser.parseFromArgs(3, argv)); 530 ASSERT(settings.checks.isEnabled(Checks::missingInclude)); 531 } 532 533 #ifdef CHECK_INTERNAL enabledInternal()534 void enabledInternal() { 535 REDIRECT; 536 const char * const argv[] = {"cppcheck", "--enable=internal", "file.cpp"}; 537 settings = Settings(); 538 ASSERT(defParser.parseFromArgs(3, argv)); 539 ASSERT(settings.checks.isEnabled(Checks::internalCheck)); 540 } 541 #endif 542 enabledMultiple()543 void enabledMultiple() { 544 REDIRECT; 545 const char * const argv[] = {"cppcheck", "--enable=missingInclude,portability,warning", "file.cpp"}; 546 settings = Settings(); 547 ASSERT(defParser.parseFromArgs(3, argv)); 548 ASSERT(!settings.severity.isEnabled(Severity::style)); 549 ASSERT(settings.severity.isEnabled(Severity::warning)); 550 ASSERT(!settings.severity.isEnabled(Severity::performance)); 551 ASSERT(settings.severity.isEnabled(Severity::portability)); 552 ASSERT(!settings.checks.isEnabled(Checks::unusedFunction)); 553 ASSERT(settings.checks.isEnabled(Checks::missingInclude)); 554 } 555 inconclusive()556 void inconclusive() { 557 REDIRECT; 558 const char * const argv[] = {"cppcheck", "--inconclusive"}; 559 settings.certainty.clear(); 560 ASSERT(defParser.parseFromArgs(2, argv)); 561 ASSERT_EQUALS(true, settings.certainty.isEnabled(Certainty::inconclusive)); 562 } 563 errorExitcode()564 void errorExitcode() { 565 REDIRECT; 566 const char * const argv[] = {"cppcheck", "--error-exitcode=5", "file.cpp"}; 567 settings.exitCode = 0; 568 ASSERT(defParser.parseFromArgs(3, argv)); 569 ASSERT_EQUALS(5, settings.exitCode); 570 } 571 errorExitcodeMissing()572 void errorExitcodeMissing() { 573 REDIRECT; 574 const char * const argv[] = {"cppcheck", "--error-exitcode=", "file.cpp"}; 575 settings.exitCode = 0; 576 // Fails since exit code not given 577 ASSERT_EQUALS(false, defParser.parseFromArgs(3, argv)); 578 } 579 errorExitcodeStr()580 void errorExitcodeStr() { 581 REDIRECT; 582 const char * const argv[] = {"cppcheck", "--error-exitcode=foo", "file.cpp"}; 583 settings.exitCode = 0; 584 // Fails since invalid exit code 585 ASSERT_EQUALS(false, defParser.parseFromArgs(3, argv)); 586 } 587 exitcodeSuppressionsOld()588 void exitcodeSuppressionsOld() { 589 // TODO: Fails since cannot open the file 590 REDIRECT; 591 const char * const argv[] = {"cppcheck", "--exitcode-suppressions", "suppr.txt", "file.cpp"}; 592 settings.exitCode = 0; 593 TODO_ASSERT_EQUALS(true, false, defParser.parseFromArgs(4, argv)); 594 } 595 exitcodeSuppressions()596 void exitcodeSuppressions() { 597 // TODO: Fails since cannot open the file 598 REDIRECT; 599 const char * const argv[] = {"cppcheck", "--exitcode-suppressions=suppr.txt", "file.cpp"}; 600 settings.exitCode = 0; 601 TODO_ASSERT_EQUALS(true, false, defParser.parseFromArgs(3, argv)); 602 } 603 exitcodeSuppressionsNoFile()604 void exitcodeSuppressionsNoFile() { 605 // TODO: Fails since cannot open the file 606 REDIRECT; 607 const char * const argv[] = {"cppcheck", "--exitcode-suppressions", "file.cpp"}; 608 settings.exitCode = 0; 609 TODO_ASSERT_EQUALS(true, false, defParser.parseFromArgs(3, argv)); 610 } 611 fileList()612 void fileList() { 613 // TODO: Fails since cannot open the file 614 REDIRECT; 615 const char * const argv[] = {"cppcheck", "--file-list", "files.txt", "file.cpp"}; 616 TODO_ASSERT_EQUALS(true, false, defParser.parseFromArgs(4, argv)); 617 } 618 619 /* void fileListStdin() { 620 // TODO: Give it some stdin to read from, fails because the list of 621 // files in stdin (_pathnames) is empty 622 REDIRECT; 623 const char * const argv[] = {"cppcheck", "--file-list=-", "file.cpp"}; 624 TODO_ASSERT_EQUALS(true, false, defParser.parseFromArgs(3, argv)); 625 } */ 626 inlineSuppr()627 void inlineSuppr() { 628 REDIRECT; 629 const char * const argv[] = {"cppcheck", "--inline-suppr", "file.cpp"}; 630 ASSERT(defParser.parseFromArgs(3, argv)); 631 } 632 jobs()633 void jobs() { 634 REDIRECT; 635 const char * const argv[] = {"cppcheck", "-j", "3", "file.cpp"}; 636 settings.jobs = 0; 637 ASSERT(defParser.parseFromArgs(4, argv)); 638 ASSERT_EQUALS(3, settings.jobs); 639 } 640 jobsMissingCount()641 void jobsMissingCount() { 642 REDIRECT; 643 const char * const argv[] = {"cppcheck", "-j", "file.cpp"}; 644 settings.jobs = 0; 645 // Fails since -j is missing thread count 646 ASSERT_EQUALS(false, defParser.parseFromArgs(3, argv)); 647 } 648 jobsInvalid()649 void jobsInvalid() { 650 REDIRECT; 651 const char * const argv[] = {"cppcheck", "-j", "e", "file.cpp"}; 652 settings.jobs = 0; 653 // Fails since invalid count given for -j 654 ASSERT_EQUALS(false, defParser.parseFromArgs(4, argv)); 655 } 656 maxConfigs()657 void maxConfigs() { 658 REDIRECT; 659 const char * const argv[] = {"cppcheck", "-f", "--max-configs=12", "file.cpp"}; 660 settings.force = false; 661 settings.maxConfigs = 12; 662 ASSERT(defParser.parseFromArgs(4, argv)); 663 ASSERT_EQUALS(12, settings.maxConfigs); 664 ASSERT_EQUALS(false, settings.force); 665 } 666 maxConfigsMissingCount()667 void maxConfigsMissingCount() { 668 REDIRECT; 669 const char * const argv[] = {"cppcheck", "--max-configs=", "file.cpp"}; 670 // Fails since --max-configs= is missing limit 671 ASSERT_EQUALS(false, defParser.parseFromArgs(3, argv)); 672 } 673 maxConfigsInvalid()674 void maxConfigsInvalid() { 675 REDIRECT; 676 const char * const argv[] = {"cppcheck", "--max-configs=e", "file.cpp"}; 677 // Fails since invalid count given for --max-configs= 678 ASSERT_EQUALS(false, defParser.parseFromArgs(3, argv)); 679 } 680 maxConfigsTooSmall()681 void maxConfigsTooSmall() { 682 REDIRECT; 683 const char * const argv[] = {"cppcheck", "--max-configs=0", "file.cpp"}; 684 // Fails since limit must be greater than 0 685 ASSERT_EQUALS(false, defParser.parseFromArgs(3, argv)); 686 } 687 reportProgressTest()688 void reportProgressTest() { 689 REDIRECT; 690 const char * const argv[] = {"cppcheck", "--report-progress", "file.cpp"}; 691 settings.reportProgress = false; 692 ASSERT(defParser.parseFromArgs(3, argv)); 693 ASSERT(settings.reportProgress); 694 } 695 stdc99()696 void stdc99() { 697 REDIRECT; 698 const char * const argv[] = {"cppcheck", "--std=c99", "file.cpp"}; 699 settings.standards.c = Standards::C89; 700 ASSERT(defParser.parseFromArgs(3, argv)); 701 ASSERT(settings.standards.c == Standards::C99); 702 } 703 stdcpp11()704 void stdcpp11() { 705 REDIRECT; 706 const char * const argv[] = {"cppcheck", "--std=c++11", "file.cpp"}; 707 settings.standards.cpp = Standards::CPP03; 708 ASSERT(defParser.parseFromArgs(3, argv)); 709 ASSERT(settings.standards.cpp == Standards::CPP11); 710 } 711 platform()712 void platform() { 713 REDIRECT; 714 const char * const argv[] = {"cppcheck", "--platform=win64", "file.cpp"}; 715 settings.platform(Settings::Unspecified); 716 ASSERT(defParser.parseFromArgs(3, argv)); 717 ASSERT(settings.platformType == Settings::Win64); 718 } 719 plistEmpty()720 void plistEmpty() { 721 REDIRECT; 722 const char * const argv[] = {"cppcheck", "--plist-output=", "file.cpp"}; 723 settings.plistOutput = ""; 724 ASSERT(defParser.parseFromArgs(3, argv)); 725 ASSERT(settings.plistOutput == "./"); 726 } 727 plistDoesNotExist()728 void plistDoesNotExist() { 729 REDIRECT; 730 const char * const argv[] = {"cppcheck", "--plist-output=./cppcheck_reports", "file.cpp"}; 731 settings.plistOutput = ""; 732 // Fails since folder pointed by --plist-output= does not exist 733 ASSERT_EQUALS(false, defParser.parseFromArgs(3, argv)); 734 } 735 suppressionsOld()736 void suppressionsOld() { 737 // TODO: Fails because there is no suppr.txt file! 738 REDIRECT; 739 const char * const argv[] = {"cppcheck", "--suppressions", "suppr.txt", "file.cpp"}; 740 ASSERT(!defParser.parseFromArgs(4, argv)); 741 } 742 suppressions()743 void suppressions() { 744 // TODO: Fails because there is no suppr.txt file! 745 REDIRECT; 746 const char * const argv[] = {"cppcheck", "--suppressions-list=suppr.txt", "file.cpp"}; 747 TODO_ASSERT_EQUALS(true, false, defParser.parseFromArgs(3, argv)); 748 } 749 suppressionsNoFile()750 void suppressionsNoFile() { 751 REDIRECT; 752 { 753 CLEAR_REDIRECT_OUTPUT; 754 const char * const argv[] = {"cppcheck", "--suppressions-list=", "file.cpp"}; 755 ASSERT_EQUALS(false, defParser.parseFromArgs(3, argv)); 756 ASSERT_EQUALS(false, GET_REDIRECT_OUTPUT.find("If you want to pass two files") != std::string::npos); 757 } 758 759 { 760 CLEAR_REDIRECT_OUTPUT; 761 const char * const argv[] = {"cppcheck", "--suppressions-list=a.suppr,b.suppr", "file.cpp"}; 762 ASSERT_EQUALS(false, defParser.parseFromArgs(3, argv)); 763 ASSERT_EQUALS(true, GET_REDIRECT_OUTPUT.find("If you want to pass two files") != std::string::npos); 764 } 765 766 { 767 CLEAR_REDIRECT_OUTPUT; 768 const char * const argv[] = {"cppcheck", "--suppressions-list=a.suppr b.suppr", "file.cpp"}; 769 ASSERT_EQUALS(false, defParser.parseFromArgs(3, argv)); 770 ASSERT_EQUALS(true, GET_REDIRECT_OUTPUT.find("If you want to pass two files") != std::string::npos); 771 } 772 } 773 errorMessage(const std::string & errorId,const std::string & fileName,int lineNumber)774 static Suppressions::ErrorMessage errorMessage(const std::string &errorId, const std::string &fileName, int lineNumber) { 775 Suppressions::ErrorMessage e; 776 e.errorId = errorId; 777 e.setFileName(fileName); 778 e.lineNumber = lineNumber; 779 return e; 780 } 781 suppressionSingle()782 void suppressionSingle() { 783 REDIRECT; 784 const char * const argv[] = {"cppcheck", "--suppress=uninitvar", "file.cpp"}; 785 settings = Settings(); 786 ASSERT(defParser.parseFromArgs(3, argv)); 787 ASSERT_EQUALS(true, settings.nomsg.isSuppressed(errorMessage("uninitvar", "file.cpp", 1))); 788 } 789 suppressionSingleFile()790 void suppressionSingleFile() { 791 REDIRECT; 792 const char * const argv[] = {"cppcheck", "--suppress=uninitvar:file.cpp", "file.cpp"}; 793 settings = Settings(); 794 ASSERT(defParser.parseFromArgs(3, argv)); 795 ASSERT_EQUALS(true, settings.nomsg.isSuppressed(errorMessage("uninitvar", "file.cpp", 1U))); 796 } 797 suppressionTwo()798 void suppressionTwo() { 799 REDIRECT; 800 const char * const argv[] = {"cppcheck", "--suppress=uninitvar,noConstructor", "file.cpp"}; 801 settings = Settings(); 802 TODO_ASSERT_EQUALS(true, false, defParser.parseFromArgs(3, argv)); 803 TODO_ASSERT_EQUALS(true, false, settings.nomsg.isSuppressed(errorMessage("uninitvar", "file.cpp", 1U))); 804 TODO_ASSERT_EQUALS(true, false, settings.nomsg.isSuppressed(errorMessage("noConstructor", "file.cpp", 1U))); 805 } 806 suppressionTwoSeparate()807 void suppressionTwoSeparate() { 808 REDIRECT; 809 const char * const argv[] = {"cppcheck", "--suppress=uninitvar", "--suppress=noConstructor", "file.cpp"}; 810 settings = Settings(); 811 ASSERT(defParser.parseFromArgs(4, argv)); 812 ASSERT_EQUALS(true, settings.nomsg.isSuppressed(errorMessage("uninitvar", "file.cpp", 1U))); 813 ASSERT_EQUALS(true, settings.nomsg.isSuppressed(errorMessage("noConstructor", "file.cpp", 1U))); 814 } 815 templates()816 void templates() { 817 REDIRECT; 818 const char * const argv[] = {"cppcheck", "--template", "{file}:{line},{severity},{id},{message}", "file.cpp"}; 819 settings.templateFormat.clear(); 820 ASSERT(defParser.parseFromArgs(4, argv)); 821 ASSERT_EQUALS("{file}:{line},{severity},{id},{message}", settings.templateFormat); 822 } 823 templatesGcc()824 void templatesGcc() { 825 REDIRECT; 826 const char * const argv[] = {"cppcheck", "--template", "gcc", "file.cpp"}; 827 settings.templateFormat.clear(); 828 ASSERT(defParser.parseFromArgs(4, argv)); 829 ASSERT_EQUALS("{bold}{file}:{line}:{column}: {magenta}warning:{default} {message} [{id}]{reset}\\n{code}", settings.templateFormat); 830 } 831 templatesVs()832 void templatesVs() { 833 REDIRECT; 834 const char * const argv[] = {"cppcheck", "--template", "vs", "file.cpp"}; 835 settings.templateFormat.clear(); 836 ASSERT(defParser.parseFromArgs(4, argv)); 837 ASSERT_EQUALS("{file}({line}): {severity}: {message}", settings.templateFormat); 838 } 839 templatesEdit()840 void templatesEdit() { 841 REDIRECT; 842 const char * const argv[] = {"cppcheck", "--template", "edit", "file.cpp"}; 843 settings.templateFormat.clear(); 844 ASSERT(defParser.parseFromArgs(4, argv)); 845 ASSERT_EQUALS("{file} +{line}: {severity}: {message}", settings.templateFormat); 846 } 847 xml()848 void xml() { 849 REDIRECT; 850 const char * const argv[] = {"cppcheck", "--xml", "file.cpp"}; 851 settings.xml_version = 1; 852 settings.xml = false; 853 ASSERT(defParser.parseFromArgs(3, argv)); 854 ASSERT(settings.xml); 855 ASSERT_EQUALS(1, settings.xml_version); 856 } 857 xmlver2()858 void xmlver2() { 859 REDIRECT; 860 const char * const argv[] = {"cppcheck", "--xml-version=2", "file.cpp"}; 861 settings.xml_version = 1; 862 settings.xml = false; 863 ASSERT(defParser.parseFromArgs(3, argv)); 864 ASSERT(settings.xml); 865 ASSERT_EQUALS(2, settings.xml_version); 866 } 867 xmlver2both()868 void xmlver2both() { 869 REDIRECT; 870 const char * const argv[] = {"cppcheck", "--xml", "--xml-version=2", "file.cpp"}; 871 settings.xml_version = 1; 872 settings.xml = false; 873 ASSERT(defParser.parseFromArgs(4, argv)); 874 ASSERT(settings.xml); 875 ASSERT_EQUALS(2, settings.xml_version); 876 } 877 xmlver2both2()878 void xmlver2both2() { 879 REDIRECT; 880 const char * const argv[] = {"cppcheck", "--xml-version=2", "--xml", "file.cpp"}; 881 settings.xml_version = 1; 882 settings.xml = false; 883 ASSERT(defParser.parseFromArgs(4, argv)); 884 ASSERT(settings.xml); 885 ASSERT_EQUALS(2, settings.xml_version); 886 } 887 xmlverunknown()888 void xmlverunknown() { 889 REDIRECT; 890 const char * const argv[] = {"cppcheck", "--xml", "--xml-version=3", "file.cpp"}; 891 // FAils since unknown XML format version 892 ASSERT_EQUALS(false, defParser.parseFromArgs(4, argv)); 893 } 894 xmlverinvalid()895 void xmlverinvalid() { 896 REDIRECT; 897 const char * const argv[] = {"cppcheck", "--xml", "--xml-version=a", "file.cpp"}; 898 // FAils since unknown XML format version 899 ASSERT_EQUALS(false, defParser.parseFromArgs(4, argv)); 900 } 901 doc()902 void doc() { 903 REDIRECT; 904 const char * const argv[] = {"cppcheck", "--doc"}; 905 ASSERT(defParser.parseFromArgs(2, argv)); 906 ASSERT(defParser.exitAfterPrinting()); 907 } 908 showtime()909 void showtime() { 910 REDIRECT; 911 const char * const argv[] = {"cppcheck", "--showtime=summary"}; 912 settings.showtime = SHOWTIME_MODES::SHOWTIME_NONE; 913 ASSERT(defParser.parseFromArgs(2, argv)); 914 ASSERT(settings.showtime == SHOWTIME_MODES::SHOWTIME_SUMMARY); 915 } 916 errorlist1()917 void errorlist1() { 918 REDIRECT; 919 const char * const argv[] = {"cppcheck", "--errorlist"}; 920 ASSERT(defParser.parseFromArgs(2, argv)); 921 ASSERT(defParser.getShowErrorMessages()); 922 } 923 errorlistverbose1()924 void errorlistverbose1() { 925 REDIRECT; 926 const char * const argv[] = {"cppcheck", "--verbose", "--errorlist"}; 927 settings.verbose = false; 928 ASSERT(defParser.parseFromArgs(3, argv)); 929 ASSERT(settings.verbose); 930 } 931 errorlistverbose2()932 void errorlistverbose2() { 933 REDIRECT; 934 const char * const argv[] = {"cppcheck", "--errorlist", "--verbose"}; 935 settings.verbose = false; 936 ASSERT(defParser.parseFromArgs(3, argv)); 937 ASSERT(settings.verbose); 938 } 939 ignorepathsnopath()940 void ignorepathsnopath() { 941 REDIRECT; 942 const char * const argv[] = {"cppcheck", "-i"}; 943 CmdLineParser parser(&settings); 944 // Fails since no ignored path given 945 ASSERT_EQUALS(false, parser.parseFromArgs(2, argv)); 946 ASSERT_EQUALS(0, parser.getIgnoredPaths().size()); 947 } 948 949 /* 950 void ignorepaths1() { 951 REDIRECT; 952 const char * const argv[] = {"cppcheck", "-isrc", "file.cpp"}; 953 CmdLineParser parser(&settings); 954 ASSERT(parser.parseFromArgs(3, argv)); 955 ASSERT_EQUALS(1, parser.getIgnoredPaths().size()); 956 ASSERT_EQUALS("src/", parser.getIgnoredPaths()[0]); 957 } 958 959 void ignorepaths2() { 960 REDIRECT; 961 const char * const argv[] = {"cppcheck", "-i", "src", "file.cpp"}; 962 CmdLineParser parser(&settings); 963 ASSERT(parser.parseFromArgs(4, argv)); 964 ASSERT_EQUALS(1, parser.getIgnoredPaths().size()); 965 ASSERT_EQUALS("src/", parser.getIgnoredPaths()[0]); 966 } 967 968 void ignorepaths3() { 969 REDIRECT; 970 const char * const argv[] = {"cppcheck", "-isrc", "-imodule", "file.cpp"}; 971 CmdLineParser parser(&settings); 972 ASSERT(parser.parseFromArgs(4, argv)); 973 ASSERT_EQUALS(2, parser.getIgnoredPaths().size()); 974 ASSERT_EQUALS("src/", parser.getIgnoredPaths()[0]); 975 ASSERT_EQUALS("module/", parser.getIgnoredPaths()[1]); 976 } 977 */ ignorepaths4()978 void ignorepaths4() { 979 REDIRECT; 980 const char * const argv[] = {"cppcheck", "-i", "src", "-i", "module", "file.cpp"}; 981 CmdLineParser parser(&settings); 982 ASSERT(parser.parseFromArgs(6, argv)); 983 ASSERT_EQUALS(2, parser.getIgnoredPaths().size()); 984 ASSERT_EQUALS("src/", parser.getIgnoredPaths()[0]); 985 ASSERT_EQUALS("module/", parser.getIgnoredPaths()[1]); 986 } 987 /* 988 void ignorefilepaths1() { 989 REDIRECT; 990 const char * const argv[] = {"cppcheck", "-ifoo.cpp", "file.cpp"}; 991 CmdLineParser parser(&settings); 992 ASSERT(parser.parseFromArgs(3, argv)); 993 ASSERT_EQUALS(1, parser.getIgnoredPaths().size()); 994 ASSERT_EQUALS("foo.cpp", parser.getIgnoredPaths()[0]); 995 } 996 */ ignorefilepaths2()997 void ignorefilepaths2() { 998 REDIRECT; 999 const char * const argv[] = {"cppcheck", "-isrc/foo.cpp", "file.cpp"}; 1000 CmdLineParser parser(&settings); 1001 ASSERT(parser.parseFromArgs(3, argv)); 1002 ASSERT_EQUALS(1, parser.getIgnoredPaths().size()); 1003 ASSERT_EQUALS("src/foo.cpp", parser.getIgnoredPaths()[0]); 1004 } 1005 checkconfig()1006 void checkconfig() { 1007 REDIRECT; 1008 const char * const argv[] = {"cppcheck", "--check-config", "file.cpp"}; 1009 settings.checkConfiguration = false; 1010 ASSERT(defParser.parseFromArgs(3, argv)); 1011 ASSERT_EQUALS(true, settings.checkConfiguration); 1012 } 1013 unknownParam()1014 void unknownParam() { 1015 REDIRECT; 1016 const char * const argv[] = {"cppcheck", "--foo", "file.cpp"}; 1017 ASSERT(!defParser.parseFromArgs(3, argv)); 1018 } 1019 undefs()1020 void undefs() { 1021 REDIRECT; 1022 const char * const argv[] = {"cppcheck", "-U_WIN32", "file.cpp"}; 1023 settings = Settings(); 1024 ASSERT(defParser.parseFromArgs(3, argv)); 1025 ASSERT_EQUALS(1, settings.userUndefs.size()); 1026 ASSERT(settings.userUndefs.find("_WIN32") != settings.userUndefs.end()); 1027 } 1028 undefs2()1029 void undefs2() { 1030 REDIRECT; 1031 const char * const argv[] = {"cppcheck", "-U_WIN32", "-UNODEBUG", "file.cpp"}; 1032 settings = Settings(); 1033 ASSERT(defParser.parseFromArgs(4, argv)); 1034 ASSERT_EQUALS(2, settings.userUndefs.size()); 1035 ASSERT(settings.userUndefs.find("_WIN32") != settings.userUndefs.end()); 1036 ASSERT(settings.userUndefs.find("NODEBUG") != settings.userUndefs.end()); 1037 } 1038 undefs_noarg()1039 void undefs_noarg() { 1040 REDIRECT; 1041 const char * const argv[] = {"cppcheck", "-U"}; 1042 // Fails since -U has no param 1043 ASSERT_EQUALS(false, defParser.parseFromArgs(2, argv)); 1044 } 1045 undefs_noarg2()1046 void undefs_noarg2() { 1047 REDIRECT; 1048 const char * const argv[] = {"cppcheck", "-U", "-v", "file.cpp"}; 1049 // Fails since -U has no param 1050 ASSERT_EQUALS(false, defParser.parseFromArgs(4, argv)); 1051 } 1052 undefs_noarg3()1053 void undefs_noarg3() { 1054 REDIRECT; 1055 const char * const argv[] = {"cppcheck", "-U", "--quiet", "file.cpp"}; 1056 // Fails since -U has no param 1057 ASSERT_EQUALS(false, defParser.parseFromArgs(4, argv)); 1058 } 1059 }; 1060 1061 REGISTER_TEST(TestCmdlineParser) 1062