Skip to content

Commit

Permalink
Deduplicate mutations by introducing a separate, higher-level entity
Browse files Browse the repository at this point in the history
Closes #782
  • Loading branch information
AlexDenisov committed Jan 8, 2021
1 parent 50841ed commit a0392b8
Show file tree
Hide file tree
Showing 15 changed files with 205 additions and 70 deletions.
9 changes: 6 additions & 3 deletions include/mull/Driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,15 @@ class Driver {
void selectInstructions(std::vector<FunctionUnderTest> &functions);

std::vector<std::unique_ptr<MutationResult>>
runMutations(std::vector<MutationPoint *> &mutationPoints);
runMutations(std::vector<MutationPoint *> &mutationPoints,
std::vector<std::unique_ptr<Mutant>> &mutants);

std::vector<std::unique_ptr<MutationResult>>
dryRunMutations(const std::vector<MutationPoint *> &mutationPoints);
dryRunMutations(const std::vector<MutationPoint *> &mutationPoints,
std::vector<std::unique_ptr<Mutant>> &mutants);
std::vector<std::unique_ptr<MutationResult>>
normalRunMutations(const std::vector<MutationPoint *> &mutationPoints);
normalRunMutations(const std::vector<MutationPoint *> &mutationPoints,
std::vector<std::unique_ptr<Mutant>> &mutants);

std::vector<FunctionUnderTest> getFunctionsUnderTest();
};
Expand Down
34 changes: 34 additions & 0 deletions include/mull/Mutant.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#pragma once

#include <memory>
#include <string>
#include <vector>

namespace mull {

class MutationPoint;
struct SourceLocation;

class Mutant {
public:
Mutant(std::string identifier, std::vector<MutationPoint *> points);

const std::string &getIdentifier() const;
const std::vector<MutationPoint *> &getMutationPoints() const;
const SourceLocation &getSourceLocation() const;
const std::string &getDiagnostics() const;
const std::string &getReplacement() const;
const std::string &getMutatorIdentifier() const;

private:
std::string identifier;
std::string mutatorIdentifier;
std::vector<MutationPoint *> points;
};

struct MutantComparator {
bool operator()(std::unique_ptr<Mutant> &lhs, std::unique_ptr<Mutant> &rhs);
bool operator()(Mutant &lhs, Mutant &rhs);
};

} // namespace mull
21 changes: 12 additions & 9 deletions include/mull/MutationResult.h
Original file line number Diff line number Diff line change
@@ -1,24 +1,27 @@
#pragma once

#include "ExecutionResult.h"
#include "MutationPoint.h"
#include "mull/ExecutionResult.h"
#include <utility>

namespace mull {

class MutationResult {
ExecutionResult Result;
MutationPoint *MutPoint;
class Mutant;

class MutationResult {
public:
MutationResult(ExecutionResult R, MutationPoint *MP) : Result(std::move(R)), MutPoint(MP) {}
MutationResult(ExecutionResult result, Mutant *mutant)
: result(std::move(result)), mutant(mutant) {}

ExecutionResult &getExecutionResult() {
return Result;
return result;
}
MutationPoint *getMutationPoint() {
return MutPoint;
Mutant *getMutant() {
return mutant;
}

private:
ExecutionResult result;
Mutant *mutant;
};

} // namespace mull
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
#pragma once

#include <mull/MutationResult.h>
#include "mull/Mutant.h"
#include "mull/MutationResult.h"

namespace mull {
class progress_counter;
class MutationPoint;

class DryRunMutantExecutionTask {
public:
using In = const std::vector<MutationPoint *>;
using In = const std::vector<std::unique_ptr<Mutant>>;
using Out = std::vector<std::unique_ptr<MutationResult>>;
using iterator = In::const_iterator;

void operator()(iterator begin, iterator end, Out &storage,
progress_counter &counter);
void operator()(iterator begin, iterator end, Out &storage, progress_counter &counter);
};
} // namespace mull
5 changes: 2 additions & 3 deletions include/mull/Parallelization/Tasks/MutantExecutionTask.h
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
#pragma once

#include "mull/Mutant.h"
#include "mull/MutationResult.h"

namespace mull {

class MutationPoint;
class progress_counter;
class Diagnostics;

struct Configuration;

class MutantExecutionTask {
public:
using In = const std::vector<MutationPoint *>;
using In = const std::vector<std::unique_ptr<Mutant>>;
using Out = std::vector<std::unique_ptr<MutationResult>>;
using iterator = In::const_iterator;

Expand Down
19 changes: 14 additions & 5 deletions include/mull/Result.h
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
#pragma once

#include "Mutant.h"
#include "MutationPoint.h"
#include "MutationResult.h"
#include <vector>

namespace mull {

class Result {
std::vector<std::unique_ptr<MutationResult>> mutationResults;
std::vector<MutationPoint *> mutationPoints;

public:
Result(std::vector<std::unique_ptr<MutationResult>> mutationResults,
Result(std::vector<std::unique_ptr<Mutant>> mutants,
std::vector<std::unique_ptr<MutationResult>> mutationResults,
std::vector<MutationPoint *> mutationPoints)
: mutationResults(std::move(mutationResults)), mutationPoints(std::move(mutationPoints)) {}
: mutants(std::move(mutants)), mutationResults(std::move(mutationResults)),
mutationPoints(std::move(mutationPoints)) {}

std::vector<std::unique_ptr<Mutant>> const &getMutants() const {
return mutants;
}

std::vector<std::unique_ptr<MutationResult>> const &getMutationResults() const {
return mutationResults;
Expand All @@ -22,5 +26,10 @@ class Result {
std::vector<MutationPoint *> const &getMutationPoints() const {
return mutationPoints;
}

private:
std::vector<std::unique_ptr<Mutant>> mutants;
std::vector<std::unique_ptr<MutationResult>> mutationResults;
std::vector<MutationPoint *> mutationPoints;
};
} // namespace mull
1 change: 1 addition & 0 deletions lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ set(mull_sources
BitcodeLoader.cpp
BitcodeMetadataReader.cpp
MutationsFinder.cpp
Mutant.cpp

Parallelization/Tasks/LoadBitcodeFromBinaryTask.cpp

Expand Down
36 changes: 27 additions & 9 deletions lib/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "mull/Diagnostics/Diagnostics.h"
#include "mull/Filters/Filters.h"
#include "mull/Filters/FunctionFilter.h"
#include "mull/Mutant.h"
#include "mull/MutationResult.h"
#include "mull/MutationsFinder.h"
#include "mull/Parallelization/Parallelization.h"
Expand Down Expand Up @@ -34,9 +35,23 @@ Driver::~Driver() {
std::unique_ptr<Result> Driver::run() {
auto mutationPoints = findMutationPoints();
auto filteredMutations = filterMutations(std::move(mutationPoints));
auto mutationResults = runMutations(filteredMutations);

return std::make_unique<Result>(std::move(mutationResults), std::move(filteredMutations));
std::vector<std::unique_ptr<Mutant>> mutants;
singleTask.execute("Deduplicate mutants", [&]() {
std::unordered_map<std::string, std::vector<MutationPoint *>> mapping;
for (MutationPoint *point : filteredMutations) {
mapping[point->getUserIdentifier()].push_back(point);
}
for (auto &pair : mapping) {
mutants.push_back(std::make_unique<Mutant>(pair.first, pair.second));
}
std::sort(std::begin(mutants), std::end(mutants), MutantComparator());
});

auto mutationResults = runMutations(filteredMutations, mutants);

return std::make_unique<Result>(
std::move(mutants), std::move(mutationResults), std::move(filteredMutations));
}

std::vector<MutationPoint *> Driver::findMutationPoints() {
Expand Down Expand Up @@ -129,22 +144,24 @@ void Driver::selectInstructions(std::vector<FunctionUnderTest> &functions) {
}

std::vector<std::unique_ptr<MutationResult>>
Driver::runMutations(std::vector<MutationPoint *> &mutationPoints) {
Driver::runMutations(std::vector<MutationPoint *> &mutationPoints,
std::vector<std::unique_ptr<Mutant>> &mutants) {
if (mutationPoints.empty()) {
return std::vector<std::unique_ptr<MutationResult>>();
}

if (config.dryRunEnabled) {
return dryRunMutations(mutationPoints);
return dryRunMutations(mutationPoints, mutants);
}

return normalRunMutations(mutationPoints);
return normalRunMutations(mutationPoints, mutants);
}

#pragma mark -

std::vector<std::unique_ptr<MutationResult>>
Driver::dryRunMutations(const std::vector<MutationPoint *> &mutationPoints) {
Driver::dryRunMutations(const std::vector<MutationPoint *> &mutationPoints,
std::vector<std::unique_ptr<Mutant>> &mutants) {
std::vector<std::unique_ptr<MutationResult>> mutationResults;

std::vector<DryRunMutantExecutionTask> tasks;
Expand All @@ -153,14 +170,15 @@ Driver::dryRunMutations(const std::vector<MutationPoint *> &mutationPoints) {
tasks.emplace_back(DryRunMutantExecutionTask());
}
TaskExecutor<DryRunMutantExecutionTask> mutantRunner(
diagnostics, "Running mutants (dry run)", mutationPoints, mutationResults, std::move(tasks));
diagnostics, "Running mutants (dry run)", mutants, mutationResults, std::move(tasks));
mutantRunner.execute();

return mutationResults;
}

std::vector<std::unique_ptr<MutationResult>>
Driver::normalRunMutations(const std::vector<MutationPoint *> &mutationPoints) {
Driver::normalRunMutations(const std::vector<MutationPoint *> &mutationPoints,
std::vector<std::unique_ptr<Mutant>> &mutants) {
singleTask.execute("Prepare mutations", [&]() {
for (auto point : mutationPoints) {
point->getBitcode()->addMutation(point);
Expand Down Expand Up @@ -236,7 +254,7 @@ Driver::normalRunMutations(const std::vector<MutationPoint *> &mutationPoints) {
tasks.emplace_back(config, diagnostics, executable, baseline);
}
TaskExecutor<MutantExecutionTask> mutantRunner(
diagnostics, "Running mutants", mutationPoints, mutationResults, std::move(tasks));
diagnostics, "Running mutants", mutants, mutationResults, std::move(tasks));
mutantRunner.execute();

return mutationResults;
Expand Down
44 changes: 44 additions & 0 deletions lib/Mutant.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#include "mull/Mutant.h"
#include "mull/MutationPoint.h"
#include "mull/SourceLocation.h"

using namespace mull;

Mutant::Mutant(std::string identifier, std::vector<MutationPoint *> points)
: identifier(std::move(identifier)), mutatorIdentifier(points.front()->getMutatorIdentifier()),
points(std::move(points)) {}

const std::string &Mutant::getIdentifier() const {
return identifier;
}

const std::vector<MutationPoint *> &Mutant::getMutationPoints() const {
return points;
}

const SourceLocation &Mutant::getSourceLocation() const {
return points.front()->getSourceLocation();
}

const std::string &Mutant::getDiagnostics() const {
return points.front()->getDiagnostics();
}

const std::string &Mutant::getMutatorIdentifier() const {
return mutatorIdentifier;
}

const std::string &Mutant::getReplacement() const {
return points.front()->getReplacement();
}

bool MutantComparator::operator()(std::unique_ptr<Mutant> &lhs, std::unique_ptr<Mutant> &rhs) {
return operator()(*lhs, *rhs);
}

bool MutantComparator::operator()(Mutant &lhs, Mutant &rhs) {
const SourceLocation &l = lhs.getSourceLocation();
const SourceLocation &r = rhs.getSourceLocation();
return std::tie(l.filePath, l.line, l.column, lhs.getMutatorIdentifier()) <
std::tie(r.filePath, r.line, r.column, rhs.getMutatorIdentifier());
}
5 changes: 2 additions & 3 deletions lib/Parallelization/Tasks/DryRunMutantExecutionTask.cpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
#include "mull/Parallelization/Tasks/DryRunMutantExecutionTask.h"

#include "mull/Parallelization/Progress.h"

using namespace mull;

void DryRunMutantExecutionTask::operator()(iterator begin, iterator end, Out &storage,
progress_counter &counter) {
for (auto it = begin; it != end; it++, counter.increment()) {
auto mutationPoint = *it;
auto &mutant = *it;
ExecutionResult result;
result.status = DryRun;
storage.push_back(std::make_unique<MutationResult>(result, mutationPoint));
storage.push_back(std::make_unique<MutationResult>(result, mutant.get()));
}
}
6 changes: 3 additions & 3 deletions lib/Parallelization/Tasks/MutantExecutionTask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ void MutantExecutionTask::operator()(iterator begin, iterator end, Out &storage,
progress_counter &counter) {
Runner runner(diagnostics);
for (auto it = begin; it != end; ++it, counter.increment()) {
MutationPoint *mutationPoint = *it;
auto &mutant = *it;
ExecutionResult result = runner.runProgram(executable,
{},
{ mutationPoint->getUserIdentifier() },
{ mutant->getIdentifier() },
baseline.runningTime * 10,
configuration.captureMutantOutput);

storage.push_back(std::make_unique<MutationResult>(result, mutationPoint));
storage.push_back(std::make_unique<MutationResult>(result, mutant.get()));
}
}
Loading

0 comments on commit a0392b8

Please sign in to comment.