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

Deduplicate mutations by introducing a separate, higher-level entity #829

Merged
merged 1 commit into from
Jan 9, 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
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