Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for not covered mutants #831

Merged
merged 1 commit into from
Jan 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/generated/CLIOptions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@

--coverage-info string Path to the coverage info file (LLVM's profdata)

--include-not-covered Include (but do not run) not covered mutants. Disabled by default
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: should this not say "non-covered" mutants? "not covered" sounds a little strange in plural.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it makes sense. There are some contexts (like "Include (but do not run) not covered mutants." above) where "not" is more appropriate, imo. So I think it's better to stick to one form to avoid any confusion.


--include-path regex File/directory paths to whitelist (supports regex)

--exclude-path regex File/directory paths to ignore (supports regex)
Expand Down
1 change: 1 addition & 0 deletions include/mull/Config/Configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ struct Configuration {
bool captureTestOutput;
bool captureMutantOutput;
bool skipSanityCheckRun;
bool includeNotCovered;

int timeout;
unsigned linkerTimeout;
Expand Down
5 changes: 4 additions & 1 deletion include/mull/ExecutionResult.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ enum ExecutionStatus {
Crashed = 4,
AbnormalExit = 5,
DryRun = 6,
FailFast = 7
FailFast = 7,
NotCovered = 8
};

static std::string executionStatusAsString(ExecutionStatus status) {
Expand All @@ -34,6 +35,8 @@ static std::string executionStatusAsString(ExecutionStatus status) {
return "DryRun";
case FailFast:
return "FailFast";
case NotCovered:
return "NotCovered";
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,17 @@ class Bitcode;

class FunctionUnderTest {
public:
explicit FunctionUnderTest(llvm::Function *function, Bitcode *bitcode);
FunctionUnderTest(llvm::Function *function, Bitcode *bitcode, bool covered = true);
llvm::Function *getFunction() const;
Bitcode *getBitcode() const;
const std::vector<llvm::Instruction *> &getSelectedInstructions() const;
bool isCovered() const;
void selectInstructions(const std::vector<InstructionFilter *> &filters);

private:
llvm::Function *function;
Bitcode *bitcode;
bool covered;
std::vector<llvm::Instruction *> selectedInstructions;
};

Expand Down
1 change: 1 addition & 0 deletions include/mull/Mutant.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class Mutant {
const std::string &getDiagnostics() const;
const std::string &getReplacement() const;
const std::string &getMutatorIdentifier() const;
bool isCovered() const;

private:
std::string identifier;
Expand Down
4 changes: 4 additions & 0 deletions include/mull/MutationPoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,17 @@ class MutationPoint {
const SourceLocation sourceLocation;
irm::IRMutation *irMutator;
std::string userIdentifier;
bool covered;

public:
MutationPoint(Mutator *mutator, irm::IRMutation *irMutator, llvm::Instruction *instruction,
std::string replacement, Bitcode *m, std::string diagnostics);

~MutationPoint() = default;

void setCovered(bool isCovered);
bool isCovered();

Mutator *getMutator();
Mutator *getMutator() const;

Expand Down
2 changes: 1 addition & 1 deletion include/mull/MutationsFinder.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
#include <map>
#include <vector>

#include "FunctionUnderTest.h"
#include "MutationPoint.h"
#include "ReachableFunction.h"
#include "mull/Mutators/Mutator.h"

namespace mull {
Expand Down
2 changes: 1 addition & 1 deletion include/mull/Mutators/CXX/TrivialCXXMutator.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#include "mull/Mutators/Mutator.h"
#include <irm/irm.h>
#include <memory>
#include <mull/ReachableFunction.h>
#include <mull/FunctionUnderTest.h>
#include <vector>

namespace mull {
Expand Down
2 changes: 1 addition & 1 deletion include/mull/Mutators/NegateConditionMutator.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#include "Mutator.h"
#include <irm/irm.h>
#include <memory>
#include <mull/ReachableFunction.h>
#include <mull/FunctionUnderTest.h>
#include <vector>

namespace llvm {
Expand Down
2 changes: 1 addition & 1 deletion include/mull/Mutators/RemoveVoidFunctionMutator.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#include "Mutator.h"
#include <irm/irm.h>
#include <memory>
#include <mull/ReachableFunction.h>
#include <mull/FunctionUnderTest.h>
#include <vector>

namespace llvm {
Expand Down
2 changes: 1 addition & 1 deletion include/mull/Mutators/ReplaceCallMutator.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#include "Mutator.h"
#include <irm/irm.h>
#include <memory>
#include <mull/ReachableFunction.h>
#include <mull/FunctionUnderTest.h>
#include <vector>

namespace mull {
Expand Down
2 changes: 1 addition & 1 deletion include/mull/Mutators/ScalarValueMutator.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#include "Mutator.h"
#include <irm/irm.h>
#include <memory>
#include <mull/ReachableFunction.h>
#include <mull/FunctionUnderTest.h>
#include <vector>

namespace llvm {
Expand Down
2 changes: 1 addition & 1 deletion include/mull/Parallelization/Tasks/FunctionFilterTask.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#pragma once

#include "mull/ReachableFunction.h"
#include "mull/FunctionUnderTest.h"
#include <vector>

namespace mull {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#pragma once

#include "mull/ReachableFunction.h"
#include "mull/FunctionUnderTest.h"
#include <vector>

namespace mull {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#pragma once

#include "mull/FunctionUnderTest.h"
#include "mull/MutationPoint.h"
#include "mull/Mutators/Mutator.h"
#include "mull/ReachableFunction.h"

namespace mull {

Expand Down
2 changes: 1 addition & 1 deletion lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ set(mull_sources

Bitcode.cpp
MutationPoint.cpp
ReachableFunction.cpp
FunctionUnderTest.cpp

IDEDiagnostics.cpp

Expand Down
2 changes: 1 addition & 1 deletion lib/Config/Configuration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ unsigned MullDefaultLinkerTimeoutMilliseconds = 30000;

Configuration::Configuration()
: debugEnabled(false), dryRunEnabled(false), captureTestOutput(true), captureMutantOutput(true),
skipSanityCheckRun(false), timeout(MullDefaultTimeoutMilliseconds),
skipSanityCheckRun(false), includeNotCovered(false), timeout(MullDefaultTimeoutMilliseconds),
linkerTimeout(MullDefaultLinkerTimeoutMilliseconds), diagnostics(IDEDiagnosticsKind::None),
parallelization(singleThreadParallelization()) {}

Expand Down
7 changes: 6 additions & 1 deletion lib/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
#include "mull/Diagnostics/Diagnostics.h"
#include "mull/Filters/Filters.h"
#include "mull/Filters/FunctionFilter.h"
#include "mull/FunctionUnderTest.h"
#include "mull/Mutant.h"
#include "mull/MutationResult.h"
#include "mull/MutationsFinder.h"
#include "mull/Parallelization/Parallelization.h"
#include "mull/Program/Program.h"
#include "mull/ReachableFunction.h"
#include "mull/Result.h"
#include "mull/Toolchain/Runner.h"

Expand Down Expand Up @@ -334,10 +334,15 @@ std::vector<FunctionUnderTest> Driver::getFunctionsUnderTest() {
}
if (covered) {
functionsUnderTest.emplace_back(&function, bitcode.get());
} else if (config.includeNotCovered) {
functionsUnderTest.emplace_back(&function, bitcode.get(), false);
}
}
}
} else {
if (config.includeNotCovered) {
diagnostics.warning("-include-not-covered is enabled, but there is no coverage info!");
}
for (auto &bitcode : program.bitcode()) {
for (llvm::Function &function : *bitcode->getModule()) {
functionsUnderTest.emplace_back(&function, bitcode.get());
Expand Down
10 changes: 7 additions & 3 deletions lib/ReachableFunction.cpp → lib/FunctionUnderTest.cpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
#include "mull/ReachableFunction.h"
#include "mull/FunctionUnderTest.h"
#include "mull/Filters/InstructionFilter.h"

#include <llvm/IR/InstIterator.h>

using namespace mull;

FunctionUnderTest::FunctionUnderTest(llvm::Function *function, Bitcode *bitcode)
: function(function), bitcode(bitcode) {}
FunctionUnderTest::FunctionUnderTest(llvm::Function *function, Bitcode *bitcode, bool covered)
: function(function), bitcode(bitcode), covered(covered) {}

llvm::Function *FunctionUnderTest::getFunction() const {
return function;
Expand All @@ -20,6 +20,10 @@ const std::vector<llvm::Instruction *> &FunctionUnderTest::getSelectedInstructio
return selectedInstructions;
}

bool FunctionUnderTest::isCovered() const {
return covered;
}

void FunctionUnderTest::selectInstructions(const std::vector<InstructionFilter *> &filters) {
for (llvm::Instruction &instruction : llvm::instructions(function)) {
bool selected = true;
Expand Down
10 changes: 10 additions & 0 deletions lib/Mutant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,16 @@ const std::string &Mutant::getReplacement() const {
return points.front()->getReplacement();
}

bool Mutant::isCovered() const {
for (MutationPoint *point : points) {
/// Consider a mutant covered if at least one of the mutation points is covered
if (point->isCovered()) {
return true;
}
}
return false;
}

bool MutantComparator::operator()(std::unique_ptr<Mutant> &lhs, std::unique_ptr<Mutant> &rhs) {
return operator()(*lhs, *rhs);
}
Expand Down
11 changes: 10 additions & 1 deletion lib/MutationPoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,21 @@ MutationPoint::MutationPoint(Mutator *mutator, irm::IRMutation *irMutator,
: mutator(mutator), address(MutationPointAddress::addressFromInstruction(instruction)),
bitcode(m), originalFunction(instruction->getFunction()), mutatedFunction(nullptr),
diagnostics(std::move(diagnostics)), replacement(std::move(replacement)),
sourceLocation(SourceLocation::locationFromInstruction(instruction)), irMutator(irMutator) {
sourceLocation(SourceLocation::locationFromInstruction(instruction)), irMutator(irMutator),
covered(true) {
userIdentifier = mutator->getUniqueIdentifier() + ':' + sourceLocation.filePath + ':' +
std::to_string(sourceLocation.line) + ':' +
std::to_string(sourceLocation.column);
}

void MutationPoint::setCovered(bool isCovered) {
covered = isCovered;
}

bool MutationPoint::isCovered() {
return covered;
}

Mutator *MutationPoint::getMutator() {
return mutator;
}
Expand Down
2 changes: 1 addition & 1 deletion lib/MutationsFinder.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#include "mull/MutationsFinder.h"

#include "mull/Config/Configuration.h"
#include "mull/FunctionUnderTest.h"
#include "mull/Parallelization/Parallelization.h"
#include "mull/Program/Program.h"
#include "mull/ReachableFunction.h"

using namespace mull;
using namespace llvm;
Expand Down
2 changes: 1 addition & 1 deletion lib/Mutators/CXX/LogicalAndToOr.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include "mull/Mutators/CXX/LogicalAndToOr.h"

#include "mull/FunctionUnderTest.h"
#include "mull/MutationPoint.h"
#include "mull/ReachableFunction.h"
#include "mull/SourceLocation.h"

#include <iterator>
Expand Down
2 changes: 1 addition & 1 deletion lib/Mutators/CXX/LogicalOrToAnd.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include "mull/Mutators/CXX/LogicalOrToAnd.h"

#include "mull/FunctionUnderTest.h"
#include "mull/MutationPoint.h"
#include "mull/ReachableFunction.h"
#include "mull/SourceLocation.h"

#include <iterator>
Expand Down
2 changes: 1 addition & 1 deletion lib/Mutators/CXX/TrivialCXXMutator.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "mull/Mutators/CXX/TrivialCXXMutator.h"
#include "mull/FunctionUnderTest.h"
#include "mull/MutationPoint.h"
#include "mull/ReachableFunction.h"
#include <irm/irm.h>

using namespace mull;
Expand Down
2 changes: 1 addition & 1 deletion lib/Mutators/NegateConditionMutator.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "mull/Mutators/NegateConditionMutator.h"
#include "mull/FunctionUnderTest.h"
#include "mull/MutationPoint.h"
#include "mull/ReachableFunction.h"
#include <cassert>
#include <irm/irm.h>
#include <sstream>
Expand Down
2 changes: 1 addition & 1 deletion lib/Mutators/RemoveVoidFunctionMutator.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "mull/Mutators/RemoveVoidFunctionMutator.h"
#include "mull/FunctionUnderTest.h"
#include "mull/MutationPoint.h"
#include "mull/ReachableFunction.h"
#include <irm/irm.h>
#include <llvm/IR/Instructions.h>
#include <sstream>
Expand Down
2 changes: 1 addition & 1 deletion lib/Mutators/ReplaceCallMutator.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "mull/Mutators/ReplaceCallMutator.h"
#include "mull/FunctionUnderTest.h"
#include "mull/MutationPoint.h"
#include "mull/ReachableFunction.h"
#include <cassert>
#include <irm/irm.h>
#include <llvm/IR/Instructions.h>
Expand Down
2 changes: 1 addition & 1 deletion lib/Mutators/ScalarValueMutator.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "mull/Mutators/ScalarValueMutator.h"
#include "mull/FunctionUnderTest.h"
#include "mull/MutationPoint.h"
#include "mull/ReachableFunction.h"
#include <irm/irm.h>

using namespace llvm;
Expand Down
4 changes: 3 additions & 1 deletion lib/Parallelization/Tasks/ApplyMutationTask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ void ApplyMutationTask::operator()(iterator begin, iterator end, Out &storage,
progress_counter &counter) {
for (auto it = begin; it != end; ++it, counter.increment()) {
auto point = *it;
point->applyMutation();
if (point->isCovered()) {
point->applyMutation();
}
}
}
2 changes: 1 addition & 1 deletion lib/Parallelization/Tasks/InstructionSelectionTask.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "mull/Parallelization/Tasks/InstructionSelectionTask.h"
#include "mull/FunctionUnderTest.h"
#include "mull/Parallelization/Progress.h"
#include "mull/ReachableFunction.h"
#include <cassert>

using namespace mull;
Expand Down
16 changes: 10 additions & 6 deletions lib/Parallelization/Tasks/MutantExecutionTask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,16 @@ void MutantExecutionTask::operator()(iterator begin, iterator end, Out &storage,
Runner runner(diagnostics);
for (auto it = begin; it != end; ++it, counter.increment()) {
auto &mutant = *it;
ExecutionResult result = runner.runProgram(executable,
{},
{ mutant->getIdentifier() },
baseline.runningTime * 10,
configuration.captureMutantOutput);

ExecutionResult result;
if (mutant->isCovered()) {
result = runner.runProgram(executable,
{},
{ mutant->getIdentifier() },
baseline.runningTime * 10,
configuration.captureMutantOutput);
} else {
result.status = NotCovered;
}
storage.push_back(std::make_unique<MutationResult>(result, mutant.get()));
}
}
Loading