From fe45744650a5c3b233e137221f6fedb996c4b77b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Tue, 9 Apr 2024 10:24:45 +0200 Subject: [PATCH] Fix #12601 (cli: Add --file-filter=- option that reads from stdin) (#6258) --- cli/cmdlineparser.cpp | 13 +++++++++++-- test/redirect.h | 15 +++++++++++++++ test/testcmdlineparser.cpp | 32 ++++++++++++++++++++++++-------- 3 files changed, 50 insertions(+), 10 deletions(-) diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index bb3787db0f2..1d5d8eeab5b 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -667,8 +667,17 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a } // use a file filter - else if (std::strncmp(argv[i], "--file-filter=", 14) == 0) - mSettings.fileFilters.emplace_back(argv[i] + 14); + else if (std::strncmp(argv[i], "--file-filter=", 14) == 0) { + const char *filter = argv[i] + 14; + if (std::strcmp(filter, "-") == 0) { + if (!addFilesToList(filter, mSettings.fileFilters)) { + mLogger.printError("Failed: --file-filter=-"); + return Result::Fail; + } + } else { + mSettings.fileFilters.emplace_back(filter); + } + } // file list specified else if (std::strncmp(argv[i], "--file-list=", 12) == 0) { diff --git a/test/redirect.h b/test/redirect.h index 10e101c6101..0518a3f81a5 100644 --- a/test/redirect.h +++ b/test/redirect.h @@ -114,4 +114,19 @@ class SuppressOutput { #define SUPPRESS SuppressOutput supprout + +class RedirectInput { +public: + explicit RedirectInput(const std::string &input) : _in(input) { + _oldCin = std::cin.rdbuf(); // back up cin's streambuf + std::cin.rdbuf(_in.rdbuf()); // assign streambuf to cin + } + ~RedirectInput() noexcept { + std::cin.rdbuf(_oldCin); // restore cin's original streambuf + } +private: + std::istringstream _in; + std::streambuf* _oldCin; +}; + #endif diff --git a/test/testcmdlineparser.cpp b/test/testcmdlineparser.cpp index 22a7627af05..4a42d56bc18 100644 --- a/test/testcmdlineparser.cpp +++ b/test/testcmdlineparser.cpp @@ -192,9 +192,10 @@ class TestCmdlineParser : public TestFixture { TEST_CASE(exitcodeSuppressionsOld); TEST_CASE(exitcodeSuppressions); TEST_CASE(exitcodeSuppressionsNoFile); + TEST_CASE(fileFilterStdin); TEST_CASE(fileList); TEST_CASE(fileListNoFile); - // TEST_CASE(fileListStdin); // Disabled since hangs the test run + TEST_CASE(fileListStdin); TEST_CASE(fileListInvalid); TEST_CASE(inlineSuppr); TEST_CASE(jobs); @@ -1083,6 +1084,17 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS("cppcheck: error: unrecognized command line option: \"--exitcode-suppressions\".\n", logger->str()); } + void fileFilterStdin() { + REDIRECT; + RedirectInput input("file1.c\nfile2.cpp\n"); + const char * const argv[] = {"cppcheck", "--file-filter=-"}; + ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv)); + ASSERT_EQUALS("cppcheck: error: no C or C++ source files found.\n", logger->str()); + ASSERT_EQUALS(2U, settings->fileFilters.size()); + ASSERT_EQUALS("file1.c", settings->fileFilters[0]); + ASSERT_EQUALS("file2.cpp", settings->fileFilters[1]); + } + void fileList() { REDIRECT; ScopedFile file("files.txt", @@ -1104,13 +1116,17 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS("cppcheck: error: couldn't open the file: \"files.txt\".\n", logger->str()); } - /* void fileListStdin() { - // TODO: Give it some stdin to read from, fails because the list of - // files in stdin (_pathnames) is empty - REDIRECT; - const char * const argv[] = {"cppcheck", "--file-list=-", "file.cpp"}; - TODO_ASSERT_EQUALS(true, false, parser->parseFromArgs(3, argv)); - } */ + void fileListStdin() { + REDIRECT; + RedirectInput input("file1.c\nfile2.cpp\n"); + const char * const argv[] = {"cppcheck", "--file-list=-", "file.cpp"}; + ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(3, parser->getPathNames().size()); + auto it = parser->getPathNames().cbegin(); + ASSERT_EQUALS("file1.c", *it++); + ASSERT_EQUALS("file2.cpp", *it++); + ASSERT_EQUALS("file.cpp", *it); + } void fileListInvalid() { REDIRECT;