Skip to content
Draft
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
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
#endif

// The following should be the only place in the project where protobuf files
// related to serialization are are directly included. This is so that they can
// related to serialization are directly included. This is so that they can
// be compiled in a manner where warnings are ignored.
#include "google/protobuf/stubs/status.h"
#include "google/protobuf/util/json_util.h"
Expand Down
48 changes: 45 additions & 3 deletions src/dredd/src/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

#include <fstream>
#include <memory>
#include <optional>
#include <sstream>
#include <string>

#include "clang/Tooling/CommonOptionsParser.h"
Expand Down Expand Up @@ -60,6 +62,19 @@ static llvm::cl::opt<bool> dump_asts(
llvm::cl::desc("Dump each AST that is processed; useful for debugging"),
llvm::cl::cat(mutate_category));
// NOLINTNEXTLINE
static llvm::cl::opt<bool> mutant_pass(
"mutant-pass",
llvm::cl::desc("Perform a pass to build the mutation tree. Must be passed "
"with --mutation_info_file."),
llvm::cl::cat(mutate_category));
// TODO(James Lee-Jones): Rename this to something more representative of what
// it does. NOLINTNEXTLINE
static llvm::cl::opt<std::string> enabled_mutations_file(
"enabled-mutations-file",
llvm::cl::desc(".json file containing information on which mutations "
"should be performed"),
llvm::cl::cat(mutate_category));
// NOLINTNEXTLINE
static llvm::cl::opt<std::string> mutation_info_file(
"mutation-info-file", llvm::cl::Required,
llvm::cl::desc(
Expand Down Expand Up @@ -96,10 +111,37 @@ int main(int argc, const char** argv) {
// including their hierarchical structure.
dredd::protobufs::MutationInfo mutation_info;

// Contains the mutations that the user wants to apply in each source
// file, including their hierarchical structure.
std::optional<dredd::protobufs::MutationInfo> enabled_mutation_info;

// If a set of mutants to instrument has been provided, convert them to
// a protobufs representation.
if (enabled_mutations_file.empty()) {
enabled_mutation_info = std::nullopt;
} else {
// TODO(James Lee-Jones): See if there is a nicer way to do this.
// TODO(James Lee-Jones): Add extra error checks if read fails.
enabled_mutation_info = dredd::protobufs::MutationInfo();
std::ifstream enabled_mutations_json_file;
std::stringstream enabled_mutations_json;
enabled_mutations_json_file.open(enabled_mutations_file);
enabled_mutations_json << enabled_mutations_json_file.rdbuf();
const std::string enabled_mutations_string = enabled_mutations_json.str();

auto json_read_status = google::protobuf::util::JsonStringToMessage(
enabled_mutations_string, &*enabled_mutation_info);
if (!json_read_status.ok()) {
llvm::errs() << "Error reading JSON data from " << enabled_mutations_file
<< "\n";
return 1;
}
}

const std::unique_ptr<clang::tooling::FrontendActionFactory> factory =
dredd::NewMutateFrontendActionFactory(!no_mutation_opts, dump_asts,
only_track_mutant_coverage,
mutation_id, mutation_info);
dredd::NewMutateFrontendActionFactory(
!no_mutation_opts, dump_asts, only_track_mutant_coverage, mutant_pass,
mutation_id, mutation_info, enabled_mutation_info);

const int return_code = Tool.run(factory.get());

Expand Down
4 changes: 3 additions & 1 deletion src/libdredd/include/libdredd/mutation.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,12 @@ class Mutation {
// The |dredd_declarations| argument provides a set of declarations that will
// be added to the start of the source file being mutated. This allows
// avoiding redundant repeat declarations.
// TODO(James Lee-Jones): Change 'mutation_pass' to something like
// 'apply_mutations'.
virtual protobufs::MutationGroup Apply(
clang::ASTContext& ast_context, const clang::Preprocessor& preprocessor,
bool optimise_mutations, bool only_track_mutant_coverage,
int first_mutation_id_in_file, int& mutation_id,
bool mutation_pass, int first_mutation_id_in_file, int& mutation_id,
clang::Rewriter& rewriter,
std::unordered_set<std::string>& dredd_declarations) const = 0;
};
Expand Down
2 changes: 1 addition & 1 deletion src/libdredd/include/libdredd/mutation_remove_stmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class MutationRemoveStmt : public Mutation {
protobufs::MutationGroup Apply(
clang::ASTContext& ast_context, const clang::Preprocessor& preprocessor,
bool optimise_mutations, bool only_track_mutant_coverage,
int first_mutation_id_in_file, int& mutation_id,
bool mutation_pass, int first_mutation_id_in_file, int& mutation_id,
clang::Rewriter& rewriter,
std::unordered_set<std::string>& dredd_declarations) const override;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class MutationReplaceBinaryOperator : public Mutation {
protobufs::MutationGroup Apply(
clang::ASTContext& ast_context, const clang::Preprocessor& preprocessor,
bool optimise_mutations, bool only_track_mutant_coverage,
int first_mutation_id_in_file, int& mutation_id,
bool mutation_pass, int first_mutation_id_in_file, int& mutation_id,
clang::Rewriter& rewriter,
std::unordered_set<std::string>& dredd_declarations) const override;

Expand Down
2 changes: 1 addition & 1 deletion src/libdredd/include/libdredd/mutation_replace_expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class MutationReplaceExpr : public Mutation {
protobufs::MutationGroup Apply(
clang::ASTContext& ast_context, const clang::Preprocessor& preprocessor,
bool optimise_mutations, bool only_track_mutant_coverage,
int first_mutation_id_in_file, int& mutation_id,
bool mutation_pass, int first_mutation_id_in_file, int& mutation_id,
clang::Rewriter& rewriter,
std::unordered_set<std::string>& dredd_declarations) const override;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class MutationReplaceUnaryOperator : public Mutation {
protobufs::MutationGroup Apply(
clang::ASTContext& ast_context, const clang::Preprocessor& preprocessor,
bool optimise_mutations, bool only_track_mutant_coverage,
int first_mutation_id_in_file, int& mutation_id,
bool mutation_pass, int first_mutation_id_in_file, int& mutation_id,
clang::Rewriter& rewriter,
std::unordered_set<std::string>& dredd_declarations) const override;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,19 @@
#define LIBDREDD_NEW_MUTATE_FRONTEND_ACTION_FACTORY_H

#include <memory>
#include <optional>

#include "clang/Tooling/Tooling.h"
#include "libdredd/protobufs/dredd_protobufs.h"

namespace dredd {

std::unique_ptr<clang::tooling::FrontendActionFactory>
NewMutateFrontendActionFactory(bool optimise_mutations, bool dump_asts,
bool only_track_mutant_coverage,
int& mutation_id,
protobufs::MutationInfo& mutation_info);
NewMutateFrontendActionFactory(
bool optimise_mutations, bool dump_asts, bool only_track_mutant_coverage,
bool mutation_pass, int& mutation_id,
protobufs::MutationInfo& mutation_info,
const std::optional<protobufs::MutationInfo>& enabled_mutation_info);

}

Expand Down
6 changes: 6 additions & 0 deletions src/libdredd/include/libdredd/protobufs/dredd.proto
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ message MutationRemoveStmt {
SourceLocation start = 2;
SourceLocation end = 3;
string snippet = 4;
bool enabled = 5;
}

enum MutationReplaceExprAction {
Expand Down Expand Up @@ -74,6 +75,7 @@ message MutationReplaceExpr {
SourceLocation end = 2;
string snippet = 3;
repeated MutationReplaceExprInstance instances = 4;
bool enabled = 5;
}

enum MutationReplaceBinaryOperatorAction {
Expand Down Expand Up @@ -113,6 +115,7 @@ enum MutationReplaceBinaryOperatorAction {
message MutationReplaceBinaryOperatorInstance {
MutationReplaceBinaryOperatorAction action = 1;
int32 mutation_id = 2;
bool enabled = 3;
}

enum BinaryOperator {
Expand Down Expand Up @@ -159,6 +162,7 @@ message MutationReplaceBinaryOperator {
string rhs_snippet = 9;
BinaryOperator operator = 10;
repeated MutationReplaceBinaryOperatorInstance instances = 11;
bool enabled = 12;
}

enum MutationReplaceUnaryOperatorAction {
Expand All @@ -175,6 +179,7 @@ enum MutationReplaceUnaryOperatorAction {
message MutationReplaceUnaryOperatorInstance {
MutationReplaceUnaryOperatorAction action = 1;
int32 mutation_id = 2;
bool enabled = 3;
}

enum UnaryOperator {
Expand All @@ -196,4 +201,5 @@ message MutationReplaceUnaryOperator {
string operand_snippet = 6;
UnaryOperator operator = 7;
repeated MutationReplaceUnaryOperatorInstance instances = 8;
bool enabled = 9;
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#define LIBDREDD_MUTATE_AST_CONSUMER_H

#include <memory>
#include <optional>
#include <string>
#include <unordered_set>

Expand All @@ -31,18 +32,21 @@ namespace dredd {

class MutateAstConsumer : public clang::ASTConsumer {
public:
MutateAstConsumer(const clang::CompilerInstance& compiler_instance,
bool optimise_mutations, bool dump_ast,
bool only_track_mutant_coverage, int& mutation_id,
protobufs::MutationInfo& mutation_info)
MutateAstConsumer(
const clang::CompilerInstance& compiler_instance, bool optimise_mutations,
bool mutation_pass, bool dump_ast, bool only_track_mutant_coverage,
int& mutation_id, protobufs::MutationInfo& mutation_info,
const std::optional<protobufs::MutationInfo>& enabled_mutation_info)
: compiler_instance_(&compiler_instance),
optimise_mutations_(optimise_mutations),
mutation_pass_(mutation_pass),
dump_ast_(dump_ast),
only_track_mutant_coverage_(only_track_mutant_coverage),
visitor_(std::make_unique<MutateVisitor>(compiler_instance,
optimise_mutations)),
mutation_id_(&mutation_id),
mutation_info_(&mutation_info) {}
mutation_info_(&mutation_info),
enabled_mutation_info_(&enabled_mutation_info) {}

void HandleTranslationUnit(clang::ASTContext& ast_context) override;

Expand All @@ -64,15 +68,18 @@ class MutateAstConsumer : public clang::ASTConsumer {
int initial_mutation_id) const;

protobufs::MutationTreeNode ApplyMutations(
const MutationTreeNode& mutation_tree_node, int initial_mutation_id,
clang::ASTContext& context,
const MutationTreeNode& mutation_tree_node,
std::optional<protobufs::MutationTreeNode>& enabled_mutation_tree_node,
int initial_mutation_id, clang::ASTContext& context,
std::unordered_set<std::string>& dredd_declarations);

const clang::CompilerInstance* compiler_instance_;

// True if and only if Dredd's optimisations are enabled.
bool optimise_mutations_;

bool mutation_pass_;

// True if and only if the AST being consumed should be dumped; useful for
// debugging.
bool dump_ast_;
Expand All @@ -88,6 +95,8 @@ class MutateAstConsumer : public clang::ASTConsumer {
int* mutation_id_;

protobufs::MutationInfo* mutation_info_;

const std::optional<protobufs::MutationInfo>* enabled_mutation_info_;
};

} // namespace dredd
Expand Down
Loading