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

White and black AST search: fix locations for mutations in header files #837

Merged
merged 1 commit into from
Mar 6, 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
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);
}
Loading