From 6a018d02e1908d17c37a8a29e3cc65a47af4a874 Mon Sep 17 00:00:00 2001 From: Matthias Bilger Date: Tue, 9 Nov 2021 22:05:04 +0100 Subject: [PATCH 1/2] Create correct patchfiles for multiline changes --- include/mull/Reporters/SourceCodeReader.h | 2 +- lib/Reporters/PatchesReporter.cpp | 13 ++++++++----- lib/Reporters/SourceCodeReader.cpp | 10 ++++++---- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/include/mull/Reporters/SourceCodeReader.h b/include/mull/Reporters/SourceCodeReader.h index 2973956f1..06fccbdee 100644 --- a/include/mull/Reporters/SourceCodeReader.h +++ b/include/mull/Reporters/SourceCodeReader.h @@ -13,7 +13,7 @@ class SourceCodeReader { SourceCodeReader(); std::string getContext(const mull::SourceLocation &sourceLocation); std::string getSourceLineWithCaret(const SourceLocation &sourceLocation); - std::string getSourceLine(const SourceLocation &sourceLocation); + std::vector getSourceLines(const SourceLocation &sourceLocation, const SourceLocation &sourceEndLocation); private: SourceManager sourceManager; }; diff --git a/lib/Reporters/PatchesReporter.cpp b/lib/Reporters/PatchesReporter.cpp index 537180a43..65e72997e 100644 --- a/lib/Reporters/PatchesReporter.cpp +++ b/lib/Reporters/PatchesReporter.cpp @@ -68,7 +68,7 @@ void mull::PatchesReporter::reportResults(const Result &result) { const auto& sourceEndLocation = mutant.getEndLocation(); const std::string sourceBasename = std::regex_replace(sourceLocation.filePath.substr(sourceLocation.directory.size()+1), std::regex("([/]|\\.(?!patch))"), "_");; const auto mutator = factory.getMutator(mutant.getMutatorIdentifier()); - const std::string sourceLine = sourceCodeReader.getSourceLine(sourceLocation); + const std::vector sourceLines = sourceCodeReader.getSourceLines(sourceLocation, sourceEndLocation); const std::string sourcePath = std::regex_replace(sourceLocation.filePath, basePathRegex, ""); const std::string prefix = [&mutationExecutionResult](){ @@ -94,13 +94,16 @@ void mull::PatchesReporter::reportResults(const Result &result) { }(); diagnostics.debug(std::string("Writing Patchfile: ") + filename.c_str()); + const int lines = sourceEndLocation.line - sourceLocation.line + 1; std::ofstream myfile{filename}; myfile << "--- a" << sourcePath << " 0" << "\n" << "+++ b" << sourcePath << " 0" << "\n" - << "@@ -" << sourceLocation.line << ",1 +" << sourceLocation.line << ",1 @@\n" - << "-" << sourceLine - << "+" << sourceLine.substr(0, sourceLocation.column-1) - << mutator->getReplacement() << sourceLine.substr(sourceEndLocation.column-1) ; + << "@@ -" << sourceLocation.line << "," << lines << " +" << sourceLocation.line << ",1 @@\n"; + for (auto& currentLine : sourceLines){ + myfile << "-" << currentLine; + } + myfile << "+" << sourceLines.front().substr(0, sourceLocation.column-1) + << mutator->getReplacement() << sourceLines.back().substr(sourceEndLocation.column-1) ; myfile.flush(); if(!myfile.good()) diagnostics.warning(std::string("Writing Patchfile failed") + filename.c_str()); diff --git a/lib/Reporters/SourceCodeReader.cpp b/lib/Reporters/SourceCodeReader.cpp index dd70293c0..e3b0c8115 100644 --- a/lib/Reporters/SourceCodeReader.cpp +++ b/lib/Reporters/SourceCodeReader.cpp @@ -92,8 +92,10 @@ std::string SourceCodeReader::getSourceLineWithCaret(const SourceLocation &sourc return ss.str(); } -std::string SourceCodeReader::getSourceLine(const SourceLocation &sourceLocation) { - auto line = sourceManager.getLine(sourceLocation); - assert(sourceLocation.column < line.size()); - return line; +std::vector SourceCodeReader::getSourceLines(const SourceLocation &sourceLocation, const SourceLocation &sourceEndLocation) { + std::vector lines; + for (SourceLocation temp{sourceLocation}; temp.line <= sourceEndLocation.line; temp.line++){ + lines.push_back(sourceManager.getLine(temp)); + } + return lines; } From d2c661ccb3032f32d9a4a8b2399d067329b59655 Mon Sep 17 00:00:00 2001 From: Matthias Bilger Date: Tue, 9 Nov 2021 22:12:23 +0100 Subject: [PATCH 2/2] Add lit test for multiline patch --- .../patch-reporter/multiline_patch/main.cpp | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 tests-lit/tests/patch-reporter/multiline_patch/main.cpp diff --git a/tests-lit/tests/patch-reporter/multiline_patch/main.cpp b/tests-lit/tests/patch-reporter/multiline_patch/main.cpp new file mode 100644 index 000000000..33b06168e --- /dev/null +++ b/tests-lit/tests/patch-reporter/multiline_patch/main.cpp @@ -0,0 +1,41 @@ +void foobar(int b, bool x) { + b += x?4:5; +} + +int main() { +// clang-format off + foobar (4, + false); + foobar (4 + + 7 + + 9 + + 10, + false); +// clang-format on + return 0; +} + +// clang-format off +/** + +RUN: cd %S +RUN: mkdir -p %S/Output/sandbox +RUN: cp %S/main.cpp %S/Output/sandbox/main.cpp +RUN: cd %S/Output/sandbox + +/// We cd to the the test directory and compile using relative paths. +RUN: cd %S; %clang_cxx %sysroot -fembed-bitcode -g -O0 Output/sandbox/main.cpp -o Output/main.cpp.exe + +RUN: cd %S/Output && echo $PATH; (unset TERM; %mull_cxx -mutators=cxx_remove_void_call -linker-flags="%sysroot" --linker=%clang_cxx -debug main.cpp.exe --report-name test --reporters Patches --reporters IDE; test $? = 0; ls -R %S/Output/test-patches; cat %S/Output/test-patches/survived-Output_sandbox_main_cpp-cxx_remove_void_call-L7-C3.patch; cat %S/Output/test-patches/survived-Output_sandbox_main_cpp-cxx_remove_void_call-L9-C3.patch) | %filecheck %s --dump-input=fail --strict-whitespace --match-full-lines + +CHECK:[debug] Writing Patchfile: {{.*}} +CHECK:[info] Patchfiles can be found at './test-patches' +CHECK:{{.*}}main_cpp-cxx_remove_void{{.*}} +CHECK:--- a{{.*}}/Output/sandbox/main.cpp 0 +CHECK:-{{\s+}}false); +CHECK:-{{\s+}}7 + +CHECK:-{{\s+}}9 + +CHECK:-{{\s+}}false); +CHECK:+{{\s+}}; + +*/