Skip to content

Commit

Permalink
Merge pull request #837 from mull-project/inlined-header-functions
Browse files Browse the repository at this point in the history
White and black AST search: fix locations for mutations in header files
  • Loading branch information
stanislaw committed Mar 6, 2021
2 parents b9b1f5d + 143b218 commit af252cc
Show file tree
Hide file tree
Showing 27 changed files with 314 additions and 151 deletions.
11 changes: 7 additions & 4 deletions include/mull/AST/ASTMutationStorage.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,16 @@ using LineColumnHash = int;
using SourceFilePath = std::string;

using SingleMutationTypeBucket = std::unordered_map<LineColumnHash, ASTMutation>;
using SingleASTUnitMutations = std::unordered_map<mull::MutatorKind, SingleMutationTypeBucket>;
using SingleFileMutations = std::unordered_map<mull::MutatorKind, SingleMutationTypeBucket>;
/// Single AST Unit consists of mutations found in its .c/.cpp file and mutations
/// found in the header files that are inlined by that AST unit.
using SingleASTUnitMutations = std::unordered_map<SourceFilePath, SingleFileMutations>;

LineColumnHash lineColumnHash(int line, int column);

class ASTMutationStorage {
public:
std::unordered_map<SourceFilePath, SingleASTUnitMutations> storage;
std::unordered_map<SourceFilePath, SingleFileMutations> storage;
Diagnostics &diagnostics;

ASTMutationStorage(Diagnostics &diagnostics);
Expand All @@ -33,12 +36,12 @@ class ASTMutationStorage {
int line, int column) const;

bool mutationExists(const std::string &sourceFile, mull::MutatorKind mutatorKind, int line,
int column) const;
int column) const;

void saveMutation(const std::string &sourceFile, mull::MutatorKind mutatorKind,
const clang::Stmt *const expression, int line, int column);

void saveMutations(std::unordered_map<SourceFilePath, SingleASTUnitMutations> &storage);
void saveMutations(std::unordered_map<SourceFilePath, SingleFileMutations> &storage);
};

} // namespace mull
2 changes: 1 addition & 1 deletion include/mull/JunkDetection/CXX/ASTStorage.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class ASTStorage {
void saveMutation(const std::string &sourceFile, mull::MutatorKind mutatorKind,
const clang::Stmt *const expression, int line, int column);

void saveMutations(std::unordered_map<SourceFilePath, SingleASTUnitMutations> &storage);
void saveMutations(std::unordered_map<SourceFilePath, SingleFileMutations> &storage);

bool mutationExists(const std::string &sourceFile, mull::MutatorKind mutatorKind, int line,
int column);
Expand Down
8 changes: 8 additions & 0 deletions include/mull/SourceLocation.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ class Function;
namespace mull {

struct SourceLocation {
/// The difference between (directory, filePath) and (unitDirectory, unitFilePath)
/// is as follows:
/// Both paths are the same when a mutation is located in the .c/.cpp file.
/// When a mutation is inlined into a preprocessed .c/.cpp file from a header file:
/// - the directory and filePath point to the location of the mutation in the
/// inlined header file.
/// - the unitDirectory and unitFilePath point to the location of the mutation
/// in the .c/.cpp file.
std::string unitDirectory;
std::string unitFilePath;
std::string directory;
Expand Down
22 changes: 18 additions & 4 deletions lib/AST/ASTFinder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,25 @@ void ASTFinder::findMutations(Diagnostics &diagnostics, const Configuration &con
tasks);
finder.execute();

std::unordered_map<SourceFilePath, SingleASTUnitMutations> mutations;
std::unordered_map<SourceFilePath, SingleFileMutations> totalMutations;

for (auto &unitMutationsPair : mutationsAsVector) {
mutations.emplace(unitMutationsPair.first, unitMutationsPair.second);
for (auto &singleFileMutations : unitMutationsPair.second) {
if (totalMutations.count(singleFileMutations.first) == 0) {
totalMutations.emplace(singleFileMutations.first, singleFileMutations.second);
continue;
}
SingleFileMutations &singleFileTotalMutations = totalMutations[singleFileMutations.first];
for (const auto &oneMutationBucket : singleFileMutations.second) {
if (singleFileTotalMutations.count(oneMutationBucket.first) == 0) {
singleFileTotalMutations.emplace(oneMutationBucket.first, oneMutationBucket.second);
continue;
}
singleFileTotalMutations[oneMutationBucket.first].insert(oneMutationBucket.second.begin(),
oneMutationBucket.second.end());
}
totalMutations.emplace(singleFileMutations.first, singleFileMutations.second);
}
}

storage.saveMutations(mutations);
storage.saveMutations(totalMutations);
}
24 changes: 12 additions & 12 deletions lib/AST/ASTMutationStorage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,9 @@ ASTMutationStorage::ASTMutationStorage(Diagnostics &diagnostics)

int ASTMutationStorage::count() const {
int count = 0;
for (const auto &singleUnitMutations : storage) {
for (const auto &oneMutationBucket :
singleUnitMutations.second) {
count += singleUnitMutations.second.at(oneMutationBucket.first).size();
for (const auto &singleFileMutations : storage) {
for (const auto &oneMutationBucket : singleFileMutations.second) {
count += singleFileMutations.second.at(oneMutationBucket.first).size();
}
}
return count;
Expand All @@ -36,10 +35,10 @@ const ASTMutation &ASTMutationStorage::getMutation(const std::string &sourceFile

assert(storage.count(sourceFile) > 0);

const SingleASTUnitMutations &astUnitMutations = storage.at(sourceFile);
assert(astUnitMutations.count(mutatorKind) > 0);
const SingleFileMutations &singleFileMutations = storage.at(sourceFile);
assert(singleFileMutations.count(mutatorKind) > 0);

const SingleMutationTypeBucket &oneMutationBucket = astUnitMutations.at(mutatorKind);
const SingleMutationTypeBucket &oneMutationBucket = singleFileMutations.at(mutatorKind);

LineColumnHash hash = lineColumnHash(line, column);
assert(oneMutationBucket.count(hash) > 0);
Expand All @@ -56,12 +55,12 @@ bool ASTMutationStorage::mutationExists(const std::string &sourceFile,
return false;
}

const SingleASTUnitMutations &astUnitMutations = storage.at(sourceFile);
if (astUnitMutations.count(mutatorKind) == 0) {
const SingleFileMutations &singleFileMutations = storage.at(sourceFile);
if (singleFileMutations.count(mutatorKind) == 0) {
return false;
}

const SingleMutationTypeBucket &oneMutationBucket = astUnitMutations.at(mutatorKind);
const SingleMutationTypeBucket &oneMutationBucket = singleFileMutations.at(mutatorKind);

LineColumnHash hash = lineColumnHash(line, column);
return oneMutationBucket.count(hash) > 0;
Expand All @@ -80,7 +79,7 @@ void ASTMutationStorage::saveMutation(const std::string &sourceFile, mull::Mutat
int hash = mull::lineColumnHash(line, column);

if (storage.count(sourceFile) == 0) {
storage.emplace(sourceFile, SingleASTUnitMutations());
storage.emplace(sourceFile, SingleFileMutations());
}

if (storage[sourceFile].count(mutatorKind) == 0) {
Expand All @@ -91,6 +90,7 @@ void ASTMutationStorage::saveMutation(const std::string &sourceFile, mull::Mutat
ASTMutation(mutatorKind, line, column, expression));
}

void ASTMutationStorage::saveMutations(std::unordered_map<SourceFilePath, SingleASTUnitMutations> &mutations) {
void ASTMutationStorage::saveMutations(
std::unordered_map<SourceFilePath, SingleFileMutations> &mutations) {
storage.swap(mutations);
}
10 changes: 7 additions & 3 deletions lib/AST/ASTVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -231,10 +231,14 @@ void ASTVisitor::saveMutationPoint(mull::MutatorKind mutatorKind, const clang::S

int hash = mull::lineColumnHash(beginLine, beginColumn);

if (singleUnitMutations.count(mutatorKind) == 0) {
singleUnitMutations.emplace(mutatorKind, SingleMutationTypeBucket());
if (singleUnitMutations.count(sourceFilePath) == 0) {
singleUnitMutations.emplace(sourceFilePath, SingleFileMutations());
}
SingleFileMutations &singleFileMutations = singleUnitMutations[sourceFilePath];
if (singleFileMutations.count(mutatorKind) == 0) {
singleFileMutations.emplace(mutatorKind, SingleMutationTypeBucket());
}

singleUnitMutations[mutatorKind].emplace(hash,
singleFileMutations[mutatorKind].emplace(hash,
ASTMutation(mutatorKind, beginLine, beginColumn, stmt));
}
2 changes: 1 addition & 1 deletion lib/JunkDetection/CXX/ASTStorage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ void ASTStorage::saveMutation(const std::string &sourceFile, mull::MutatorKind m
}

void ASTStorage::saveMutations(
std::unordered_map<SourceFilePath, SingleASTUnitMutations> &storage) {
std::unordered_map<SourceFilePath, SingleFileMutations> &storage) {
mutations.saveMutations(storage);
}

Expand Down
2 changes: 1 addition & 1 deletion lib/JunkDetection/CXX/CXXJunkDetector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ bool CXXJunkDetector::isJunk(MutationPoint *point) {
return true;
}

const std::string &sourceFile = point->getSourceLocation().unitFilePath;
const std::string &sourceFile = point->getSourceLocation().filePath;
int beginLine = sourceManager.getExpansionLineNumber(location, nullptr);
int beginColumn = sourceManager.getExpansionColumnNumber(location);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[
{
"arguments": [
"cc",
"-c",
"-fembed-bitcode",
"-g",
"-O0",
"-o",
"%PWD/sample.cpp.exe",
"%PWD/sample.cpp"
],
"directory": "/",
"file": "%PWD/sample.cpp"
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#include "sum.h"

int main() {
return sum(-2, 2);
}

// clang-format off

/**
RUN: cd / && %CLANG_EXEC -fembed-bitcode -g %s -o %s.exe
RUN: cd %CURRENT_DIR
RUN: sed -e "s:%PWD:%S:g" %S/compile_commands.json.template > %S/compile_commands.json
RUN: (unset TERM; %MULL_EXEC -linker=%clang_cxx -debug -enable-ast -mutators=cxx_add_to_sub -reporters=IDE -ide-reporter-show-killed -compdb-path %S/compile_commands.json %s.exe 2>&1; test $? = 0) | %FILECHECK_EXEC %s --dump-input=fail --strict-whitespace --match-full-lines
CHECK-NOT:{{^.*[Ee]rror.*$}}
CHECK-NOT:{{^.*[Ww]arning.*$}}
CHECK:[info] AST Search: looking for mutations in the source files (threads: 1)
CHECK:[debug] AST Search: recording mutation "Add to Sub": {{.*}}sum.h:4:12
CHECK:[info] Applying filter: AST mutation filter (threads: 1)
CHECK:[debug] ASTMutationFilter: whitelisting mutation "Add to Sub": {{.*}}sum.h:4:12
CHECK:[info] Applying filter: junk (threads: 1)
CHECK:[debug] ASTMutationStorage: recording mutation "Add to Sub": {{.*}}sum.h:4:12
CHECK:[info] Killed mutants (1/1):
CHECK:{{^.*}}sum.h:4:12: warning: Killed: Replaced + with - [cxx_add_to_sub]{{$}}
CHECK: return a + b;
CHECK: ^
CHECK:[info] Mutation score: 100%
CHECK:[info] Total execution time: {{.*}}
CHECK-EMPTY:
**/
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#pragma once

static int sum(int a, int b) {
return a + b;
}
40 changes: 25 additions & 15 deletions tests/AST/ASTVisitor/ASTVisitor_ArithmeticAssignment_Tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,12 @@ int add_assign(int a, int b) {
LineColumnHash locationHash = lineColumnHash(3, 5);

ASSERT_EQ(singleUnitMutations.size(), 1U);
ASSERT_EQ(singleUnitMutations.count(MutatorKind::CXX_AddAssignToSubAssign), 1U);

ASSERT_EQ(singleUnitMutations[MutatorKind::CXX_AddAssignToSubAssign].size(), 1U);
ASSERT_EQ(singleUnitMutations[MutatorKind::CXX_AddAssignToSubAssign].count(locationHash), 1U);
SingleFileMutations &singleFileMutations = singleUnitMutations[fakeSourceFilePath];
ASSERT_EQ(singleFileMutations.count(MutatorKind::CXX_AddAssignToSubAssign), 1U);

ASSERT_EQ(singleFileMutations[MutatorKind::CXX_AddAssignToSubAssign].size(), 1U);
ASSERT_EQ(singleFileMutations[MutatorKind::CXX_AddAssignToSubAssign].count(locationHash), 1U);
}

TEST(ASTVisitor_ArithmeticAssignment, subAssignToAddAssign) {
Expand Down Expand Up @@ -77,10 +79,12 @@ int sub_assign(int a, int b) {
LineColumnHash locationHash = lineColumnHash(3, 5);

ASSERT_EQ(singleUnitMutations.size(), 1U);
ASSERT_EQ(singleUnitMutations.count(MutatorKind::CXX_SubAssignToAddAssign), 1U);

ASSERT_EQ(singleUnitMutations[MutatorKind::CXX_SubAssignToAddAssign].size(), 1U);
ASSERT_EQ(singleUnitMutations[MutatorKind::CXX_SubAssignToAddAssign].count(locationHash), 1U);
SingleFileMutations &singleFileMutations = singleUnitMutations[fakeSourceFilePath];
ASSERT_EQ(singleFileMutations.count(MutatorKind::CXX_SubAssignToAddAssign), 1U);

ASSERT_EQ(singleFileMutations[MutatorKind::CXX_SubAssignToAddAssign].size(), 1U);
ASSERT_EQ(singleFileMutations[MutatorKind::CXX_SubAssignToAddAssign].count(locationHash), 1U);
}

TEST(ASTVisitor_ArithmeticAssignment, mulAssignToDivAssign) {
Expand Down Expand Up @@ -111,10 +115,12 @@ int mul_assign(int a, int b) {
LineColumnHash locationHash = lineColumnHash(3, 5);

ASSERT_EQ(singleUnitMutations.size(), 1U);
ASSERT_EQ(singleUnitMutations.count(MutatorKind::CXX_MulAssignToDivAssign), 1U);

ASSERT_EQ(singleUnitMutations[MutatorKind::CXX_MulAssignToDivAssign].size(), 1U);
ASSERT_EQ(singleUnitMutations[MutatorKind::CXX_MulAssignToDivAssign].count(locationHash), 1U);
SingleFileMutations &singleFileMutations = singleUnitMutations[fakeSourceFilePath];
ASSERT_EQ(singleFileMutations.count(MutatorKind::CXX_MulAssignToDivAssign), 1U);

ASSERT_EQ(singleFileMutations[MutatorKind::CXX_MulAssignToDivAssign].size(), 1U);
ASSERT_EQ(singleFileMutations[MutatorKind::CXX_MulAssignToDivAssign].count(locationHash), 1U);
}

TEST(ASTVisitor_ArithmeticAssignment, divAssignToMulAssign) {
Expand Down Expand Up @@ -145,10 +151,12 @@ int div_assign(int a, int b) {
LineColumnHash locationHash = lineColumnHash(3, 5);

ASSERT_EQ(singleUnitMutations.size(), 1U);
ASSERT_EQ(singleUnitMutations.count(MutatorKind::CXX_DivAssignToMulAssign), 1U);

ASSERT_EQ(singleUnitMutations[MutatorKind::CXX_DivAssignToMulAssign].size(), 1U);
ASSERT_EQ(singleUnitMutations[MutatorKind::CXX_DivAssignToMulAssign].count(locationHash), 1U);
SingleFileMutations &singleFileMutations = singleUnitMutations[fakeSourceFilePath];
ASSERT_EQ(singleFileMutations.count(MutatorKind::CXX_DivAssignToMulAssign), 1U);

ASSERT_EQ(singleFileMutations[MutatorKind::CXX_DivAssignToMulAssign].size(), 1U);
ASSERT_EQ(singleFileMutations[MutatorKind::CXX_DivAssignToMulAssign].count(locationHash), 1U);
}

TEST(ASTVisitor_ArithmeticAssignment, remAssignToDivAssign) {
Expand Down Expand Up @@ -179,8 +187,10 @@ int div_assign(int a, int b) {
LineColumnHash locationHash = lineColumnHash(3, 5);

ASSERT_EQ(singleUnitMutations.size(), 1U);
ASSERT_EQ(singleUnitMutations.count(MutatorKind::CXX_RemAssignToDivAssign), 1U);

ASSERT_EQ(singleUnitMutations[MutatorKind::CXX_RemAssignToDivAssign].size(), 1U);
ASSERT_EQ(singleUnitMutations[MutatorKind::CXX_RemAssignToDivAssign].count(locationHash), 1U);
SingleFileMutations &singleFileMutations = singleUnitMutations[fakeSourceFilePath];
ASSERT_EQ(singleFileMutations.count(MutatorKind::CXX_RemAssignToDivAssign), 1U);

ASSERT_EQ(singleFileMutations[MutatorKind::CXX_RemAssignToDivAssign].size(), 1U);
ASSERT_EQ(singleFileMutations[MutatorKind::CXX_RemAssignToDivAssign].count(locationHash), 1U);
}
40 changes: 25 additions & 15 deletions tests/AST/ASTVisitor/ASTVisitor_Arithmetic_Tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,12 @@ int add(int a, int b) {
LineColumnHash locationHash = lineColumnHash(3, 12);

ASSERT_EQ(singleUnitMutations.size(), 1U);
ASSERT_EQ(singleUnitMutations.count(MutatorKind::CXX_AddToSub), 1U);

ASSERT_EQ(singleUnitMutations[MutatorKind::CXX_AddToSub].size(), 1U);
ASSERT_EQ(singleUnitMutations[MutatorKind::CXX_AddToSub].count(locationHash), 1U);
SingleFileMutations &singleFileMutations = singleUnitMutations[fakeSourceFilePath];
ASSERT_EQ(singleFileMutations.count(MutatorKind::CXX_AddToSub), 1U);

ASSERT_EQ(singleFileMutations[MutatorKind::CXX_AddToSub].size(), 1U);
ASSERT_EQ(singleFileMutations[MutatorKind::CXX_AddToSub].count(locationHash), 1U);
}

TEST(ASTVisitor_Arithmetic, subToAdd) {
Expand Down Expand Up @@ -75,10 +77,12 @@ int sub(int a, int b) {
LineColumnHash locationHash = lineColumnHash(3, 12);

ASSERT_EQ(singleUnitMutations.size(), 1U);
ASSERT_EQ(singleUnitMutations.count(MutatorKind::CXX_SubToAdd), 1U);

ASSERT_EQ(singleUnitMutations[MutatorKind::CXX_SubToAdd].size(), 1U);
ASSERT_EQ(singleUnitMutations[MutatorKind::CXX_SubToAdd].count(locationHash), 1U);
SingleFileMutations &singleFileMutations = singleUnitMutations[fakeSourceFilePath];
ASSERT_EQ(singleFileMutations.count(MutatorKind::CXX_SubToAdd), 1U);

ASSERT_EQ(singleFileMutations[MutatorKind::CXX_SubToAdd].size(), 1U);
ASSERT_EQ(singleFileMutations[MutatorKind::CXX_SubToAdd].count(locationHash), 1U);
}

TEST(ASTVisitor_Arithmetic, mulToDiv) {
Expand Down Expand Up @@ -108,10 +112,12 @@ int mul(int a, int b) {
LineColumnHash locationHash = lineColumnHash(3, 12);

ASSERT_EQ(singleUnitMutations.size(), 1U);
ASSERT_EQ(singleUnitMutations.count(MutatorKind::CXX_MulToDiv), 1U);

ASSERT_EQ(singleUnitMutations[MutatorKind::CXX_MulToDiv].size(), 1U);
ASSERT_EQ(singleUnitMutations[MutatorKind::CXX_MulToDiv].count(locationHash), 1U);
SingleFileMutations &singleFileMutations = singleUnitMutations[fakeSourceFilePath];
ASSERT_EQ(singleFileMutations.count(MutatorKind::CXX_MulToDiv), 1U);

ASSERT_EQ(singleFileMutations[MutatorKind::CXX_MulToDiv].size(), 1U);
ASSERT_EQ(singleFileMutations[MutatorKind::CXX_MulToDiv].count(locationHash), 1U);
}

TEST(ASTVisitor_Arithmetic, divToMul) {
Expand Down Expand Up @@ -141,10 +147,12 @@ int mul(int a, int b) {
LineColumnHash locationHash = lineColumnHash(3, 12);

ASSERT_EQ(singleUnitMutations.size(), 1U);
ASSERT_EQ(singleUnitMutations.count(MutatorKind::CXX_DivToMul), 1U);

ASSERT_EQ(singleUnitMutations[MutatorKind::CXX_DivToMul].size(), 1U);
ASSERT_EQ(singleUnitMutations[MutatorKind::CXX_DivToMul].count(locationHash), 1U);
SingleFileMutations &singleFileMutations = singleUnitMutations[fakeSourceFilePath];
ASSERT_EQ(singleFileMutations.count(MutatorKind::CXX_DivToMul), 1U);

ASSERT_EQ(singleFileMutations[MutatorKind::CXX_DivToMul].size(), 1U);
ASSERT_EQ(singleFileMutations[MutatorKind::CXX_DivToMul].count(locationHash), 1U);
}

TEST(ASTVisitor_Arithmetic, remToDiv) {
Expand Down Expand Up @@ -174,8 +182,10 @@ int rem(int a, int b) {
LineColumnHash locationHash = lineColumnHash(3, 12);

ASSERT_EQ(singleUnitMutations.size(), 1U);
ASSERT_EQ(singleUnitMutations.count(MutatorKind::CXX_RemToDiv), 1U);

ASSERT_EQ(singleUnitMutations[MutatorKind::CXX_RemToDiv].size(), 1U);
ASSERT_EQ(singleUnitMutations[MutatorKind::CXX_RemToDiv].count(locationHash), 1U);
SingleFileMutations &singleFileMutations = singleUnitMutations[fakeSourceFilePath];
ASSERT_EQ(singleFileMutations.count(MutatorKind::CXX_RemToDiv), 1U);

ASSERT_EQ(singleFileMutations[MutatorKind::CXX_RemToDiv].size(), 1U);
ASSERT_EQ(singleFileMutations[MutatorKind::CXX_RemToDiv].count(locationHash), 1U);
}

0 comments on commit af252cc

Please sign in to comment.