diff --git a/CMakeLists.txt b/CMakeLists.txt index 5fb02fcae..61f9467ab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,9 @@ cmake_minimum_required(VERSION 3.7.0) +set (MULL_VERSION 0.5.0) + project(Mull - VERSION 0.5.0 + VERSION ${MULL_VERSION} LANGUAGES C CXX ) @@ -199,3 +201,4 @@ add_subdirectory(tools) add_subdirectory(tests) add_subdirectory(vendor/googletest) add_subdirectory(vendor/libirm) +add_subdirectory(docs) \ No newline at end of file diff --git a/LLVMCompatibility/3.9.x/LLVMCompatibility.cpp b/LLVMCompatibility/3.9.x/LLVMCompatibility.cpp index 49aef47ce..a596971f7 100644 --- a/LLVMCompatibility/3.9.x/LLVMCompatibility.cpp +++ b/LLVMCompatibility/3.9.x/LLVMCompatibility.cpp @@ -13,6 +13,7 @@ uint64_t JITSymbolAddress(JITSymbol &symbol) { return symbol.getAddress(); } + JITSymbolFlags JITSymbolFlagsFromObjectSymbol(const object::BasicSymbolRef &symbol) { return orc::JITSymbol::flagsFromObjectSymbol(symbol); } @@ -53,4 +54,8 @@ DICompileUnit *getUnit(const DebugLoc &debugLocation) { return scope ? llvm::cast(scope)->getUnit() : nullptr; } +bool parseCommandLineOptions(int argc, char **argv) { + return llvm::cl::ParseCommandLineOptions(argc, argv, "", true); +} + } // namespace llvm_compat diff --git a/LLVMCompatibility/3.9.x/LLVMCompatibility.h b/LLVMCompatibility/3.9.x/LLVMCompatibility.h index 1de13daff..2601607b6 100644 --- a/LLVMCompatibility/3.9.x/LLVMCompatibility.h +++ b/LLVMCompatibility/3.9.x/LLVMCompatibility.h @@ -36,4 +36,6 @@ void setVersionPrinter(void (*oldPrinter)(), void (*newPrinter)(raw_ostream &)); StringRef getSectionContent(const object::SectionRef §ion); DICompileUnit *getUnit(const DebugLoc &debugLocation); + +bool parseCommandLineOptions(int argc, char **argv); } // namespace llvm_compat diff --git a/LLVMCompatibility/4.x.x/LLVMCompatibility.cpp b/LLVMCompatibility/4.x.x/LLVMCompatibility.cpp index b316f029a..29ed5fc6b 100644 --- a/LLVMCompatibility/4.x.x/LLVMCompatibility.cpp +++ b/LLVMCompatibility/4.x.x/LLVMCompatibility.cpp @@ -51,4 +51,8 @@ DICompileUnit *getUnit(const DebugLoc &debugLocation) { return scope ? llvm::cast(scope)->getUnit() : nullptr; } +bool parseCommandLineOptions(int argc, char **argv) { + return llvm::cl::ParseCommandLineOptions(argc, argv, "", true); +} + } // namespace llvm_compat diff --git a/LLVMCompatibility/4.x.x/LLVMCompatibility.h b/LLVMCompatibility/4.x.x/LLVMCompatibility.h index bb3bc1881..70927a678 100644 --- a/LLVMCompatibility/4.x.x/LLVMCompatibility.h +++ b/LLVMCompatibility/4.x.x/LLVMCompatibility.h @@ -34,4 +34,5 @@ void setVersionPrinter(void (*oldPrinter)(), void (*newPrinter)(raw_ostream &)); StringRef getSectionContent(const object::SectionRef §ion); DICompileUnit *getUnit(const DebugLoc &debugLocation); +bool parseCommandLineOptions(int argc, char **argv); } // namespace llvm_compat diff --git a/LLVMCompatibility/5.x.x/LLVMCompatibility.cpp b/LLVMCompatibility/5.x.x/LLVMCompatibility.cpp index a18c91a61..bf7a35f0c 100644 --- a/LLVMCompatibility/5.x.x/LLVMCompatibility.cpp +++ b/LLVMCompatibility/5.x.x/LLVMCompatibility.cpp @@ -57,4 +57,8 @@ DICompileUnit *getUnit(const DebugLoc &debugLocation) { return scope ? llvm::cast(scope)->getUnit() : nullptr; } +bool parseCommandLineOptions(int argc, char **argv) { + return llvm::cl::ParseCommandLineOptions(argc, argv, "", &llvm::errs()); +} + } // namespace llvm_compat diff --git a/LLVMCompatibility/5.x.x/LLVMCompatibility.h b/LLVMCompatibility/5.x.x/LLVMCompatibility.h index bb3bc1881..70927a678 100644 --- a/LLVMCompatibility/5.x.x/LLVMCompatibility.h +++ b/LLVMCompatibility/5.x.x/LLVMCompatibility.h @@ -34,4 +34,5 @@ void setVersionPrinter(void (*oldPrinter)(), void (*newPrinter)(raw_ostream &)); StringRef getSectionContent(const object::SectionRef §ion); DICompileUnit *getUnit(const DebugLoc &debugLocation); +bool parseCommandLineOptions(int argc, char **argv); } // namespace llvm_compat diff --git a/LLVMCompatibility/6.x.x/LLVMCompatibility.cpp b/LLVMCompatibility/6.x.x/LLVMCompatibility.cpp index 08eb5e14c..f9d0dc7e0 100644 --- a/LLVMCompatibility/6.x.x/LLVMCompatibility.cpp +++ b/LLVMCompatibility/6.x.x/LLVMCompatibility.cpp @@ -57,4 +57,8 @@ DICompileUnit *getUnit(const DebugLoc &debugLocation) { return scope ? llvm::cast(scope)->getUnit() : nullptr; } +bool parseCommandLineOptions(int argc, char **argv) { + return llvm::cl::ParseCommandLineOptions(argc, argv, "", &llvm::errs()); +} + } // namespace llvm_compat diff --git a/LLVMCompatibility/6.x.x/LLVMCompatibility.h b/LLVMCompatibility/6.x.x/LLVMCompatibility.h index bb3bc1881..70927a678 100644 --- a/LLVMCompatibility/6.x.x/LLVMCompatibility.h +++ b/LLVMCompatibility/6.x.x/LLVMCompatibility.h @@ -34,4 +34,5 @@ void setVersionPrinter(void (*oldPrinter)(), void (*newPrinter)(raw_ostream &)); StringRef getSectionContent(const object::SectionRef §ion); DICompileUnit *getUnit(const DebugLoc &debugLocation); +bool parseCommandLineOptions(int argc, char **argv); } // namespace llvm_compat diff --git a/LLVMCompatibility/7.x.x/LLVMCompatibility.cpp b/LLVMCompatibility/7.x.x/LLVMCompatibility.cpp index 1a62d4666..297551357 100644 --- a/LLVMCompatibility/7.x.x/LLVMCompatibility.cpp +++ b/LLVMCompatibility/7.x.x/LLVMCompatibility.cpp @@ -64,4 +64,9 @@ DICompileUnit *getUnit(const DebugLoc &debugLocation) { } return scope ? llvm::cast(scope)->getUnit() : nullptr; } + +bool parseCommandLineOptions(int argc, char **argv) { + return llvm::cl::ParseCommandLineOptions(argc, argv, "", &llvm::errs()); +} + } // namespace llvm_compat diff --git a/LLVMCompatibility/7.x.x/LLVMCompatibility.h b/LLVMCompatibility/7.x.x/LLVMCompatibility.h index 985fb7b36..127b53c53 100644 --- a/LLVMCompatibility/7.x.x/LLVMCompatibility.h +++ b/LLVMCompatibility/7.x.x/LLVMCompatibility.h @@ -34,4 +34,5 @@ void setVersionPrinter(void (*oldPrinter)(), void (*newPrinter)(raw_ostream &)); StringRef getSectionContent(const object::SectionRef §ion); DICompileUnit *getUnit(const DebugLoc &debugLocation); +bool parseCommandLineOptions(int argc, char **argv); } // namespace llvm_compat diff --git a/LLVMCompatibility/8.x.x/LLVMCompatibility.cpp b/LLVMCompatibility/8.x.x/LLVMCompatibility.cpp index 137fd4437..a55638dd7 100644 --- a/LLVMCompatibility/8.x.x/LLVMCompatibility.cpp +++ b/LLVMCompatibility/8.x.x/LLVMCompatibility.cpp @@ -69,4 +69,8 @@ DICompileUnit *getUnit(const DebugLoc &debugLocation) { return scope ? llvm::cast(scope)->getUnit() : nullptr; } +bool parseCommandLineOptions(int argc, char **argv) { + return llvm::cl::ParseCommandLineOptions(argc, argv, "", &llvm::errs()); +} + } // namespace llvm_compat diff --git a/LLVMCompatibility/8.x.x/LLVMCompatibility.h b/LLVMCompatibility/8.x.x/LLVMCompatibility.h index 985fb7b36..127b53c53 100644 --- a/LLVMCompatibility/8.x.x/LLVMCompatibility.h +++ b/LLVMCompatibility/8.x.x/LLVMCompatibility.h @@ -34,4 +34,5 @@ void setVersionPrinter(void (*oldPrinter)(), void (*newPrinter)(raw_ostream &)); StringRef getSectionContent(const object::SectionRef §ion); DICompileUnit *getUnit(const DebugLoc &debugLocation); +bool parseCommandLineOptions(int argc, char **argv); } // namespace llvm_compat diff --git a/LLVMCompatibility/9.x.x/LLVMCompatibility.cpp b/LLVMCompatibility/9.x.x/LLVMCompatibility.cpp index 7068eb61a..47d645191 100644 --- a/LLVMCompatibility/9.x.x/LLVMCompatibility.cpp +++ b/LLVMCompatibility/9.x.x/LLVMCompatibility.cpp @@ -71,4 +71,8 @@ DICompileUnit *getUnit(const DebugLoc &debugLocation) { return scope ? llvm::cast(scope)->getUnit() : nullptr; } +bool parseCommandLineOptions(int argc, char **argv) { + return llvm::cl::ParseCommandLineOptions(argc, argv, "", &llvm::errs()); +} + } // namespace llvm_compat diff --git a/LLVMCompatibility/9.x.x/LLVMCompatibility.h b/LLVMCompatibility/9.x.x/LLVMCompatibility.h index bbf9862f6..919e34a12 100644 --- a/LLVMCompatibility/9.x.x/LLVMCompatibility.h +++ b/LLVMCompatibility/9.x.x/LLVMCompatibility.h @@ -36,4 +36,5 @@ StringRef getSectionContent(const object::SectionRef §ion); DICompileUnit *getUnit(const DebugLoc &debugLocation); +bool parseCommandLineOptions(int argc, char **argv); } // namespace llvm_compat diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt new file mode 100644 index 000000000..02e452159 --- /dev/null +++ b/docs/CMakeLists.txt @@ -0,0 +1,15 @@ +add_custom_target(generate-cli-options-doc + COMMAND $ --dump-cli > generated/CLIOptions.rst + DEPENDS mull-cxx + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} +) + +add_custom_target(generate-mutators-doc + COMMAND $ --dump-mutators > generated/Mutators.rst + DEPENDS mull-cxx + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} +) + +add_custom_target(build-docs + DEPENDS generate-mutators-doc generate-cli-options-doc +) \ No newline at end of file diff --git a/docs/CommandLineReference.rst b/docs/CommandLineReference.rst index fc3146539..99211589b 100644 --- a/docs/CommandLineReference.rst +++ b/docs/CommandLineReference.rst @@ -1,2 +1,4 @@ Command Line Reference -====================== \ No newline at end of file +====================== + +.. include:: generated/CLIOptions.rst diff --git a/docs/SupportedMutations.rst b/docs/SupportedMutations.rst index bdd0f67f5..33a058217 100644 --- a/docs/SupportedMutations.rst +++ b/docs/SupportedMutations.rst @@ -1,2 +1,4 @@ Supported Mutation Operators -============================ \ No newline at end of file +============================ + +.. include:: generated/Mutators.rst \ No newline at end of file diff --git a/docs/_static/custom.css b/docs/_static/custom.css new file mode 100644 index 000000000..829b494ab --- /dev/null +++ b/docs/_static/custom.css @@ -0,0 +1,3 @@ +td p { + margin-right: 20px; +} \ No newline at end of file diff --git a/docs/conf.py b/docs/conf.py index 697f17416..e27b9670d 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -14,17 +14,25 @@ # import sys # sys.path.insert(0, os.path.abspath('.')) +import re import guzzle_sphinx_theme # -- Project information ----------------------------------------------------- -project = 'Mull' -copyright = '2019, Alex Denisov' -author = 'Alex Denisov' +def project_version(): + with open("../CMakeLists.txt") as f: + for line in f: + m = re.search('MULL_VERSION (\d.\d.\d)', line) + if m: + return m.group(1) -# The full version, including alpha/beta/rc tags -release = '0.5.0' +project = 'Mull' +copyright = '2019, Mull Project' +author = 'Alex Denisov , Stanislav Pankevich ' +version = project_version() +release = version +print("Generating docs for Mull" + version) # -- General configuration --------------------------------------------------- @@ -52,8 +60,6 @@ extensions.append("guzzle_sphinx_theme") html_theme = 'guzzle_sphinx_theme' -# html_theme = 'pyramid' - html_theme_options = { "project_nav_name": "Mull", } @@ -63,4 +69,5 @@ # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] +html_css_files = [ 'custom.css' ] master_doc = 'index' \ No newline at end of file diff --git a/docs/generated/CLIOptions.rst b/docs/generated/CLIOptions.rst new file mode 100644 index 000000000..8e3caa284 --- /dev/null +++ b/docs/generated/CLIOptions.rst @@ -0,0 +1,168 @@ +--workers number How many threads to use + +--dry-run Skips real mutants execution. Disabled by default + +--cache-dir directory Where to store cache (defaults to /tmp/mull-cache) + +--disable-cache Disables cache (enabled by default) + +--report-name filename Filename for the report (only for supported reporters). Defaults to . + +--report-dir directory Where to store report (defaults to '.') + +--reporters reporter Choose reporters: + + :IDE: Prints compiler-like warnings into stdout + + :SQLite: Saves results into an SQLite database + + :Elements: Generates mutation-testing-elements compatible JSON file + +--compdb-path filename Path to a compilation database (compile_commands.json) for junk detection + +--compilation-flags string Extra compilation flags for junk detection + +--ld-search-path directory Library search path + +--include-path regex File/directory paths to whitelist (supports regex) + +--exclude-path regex File/directory paths to ignore (supports regex) + +--sandbox sandbox Choose sandbox approach: + + :None: No sandboxing + + :Watchdog: Uses 4 processes, not recommended + + :Timer: Fastest, Recommended + +--test-framework framework Choose test framework: + + :GoogleTest: Google Test Framework + + :CustomTest: Custom Test Framework + + :SimpleTest: Simple Test (For internal usage only) + +--mutators mutator Choose mutators: + + Groups: + :all: cxx_all, experimental + + :cxx_all: cxx_assignment, cxx_increment, cxx_decrement, cxx_arithmetic, cxx_logical, cxx_comparison, cxx_boundary + + :cxx_arithmetic: cxx_minus_to_noop, cxx_add_to_sub, cxx_sub_to_add, cxx_mul_to_div, cxx_div_to_mul, cxx_rem_to_div + + :cxx_arithmetic_assignment: cxx_add_assign_to_sub_assign, cxx_sub_assign_to_add_assign, cxx_mul_assign_to_div_assign, cxx_div_assign_to_mul_assign, cxx_rem_assign_to_div_assign + + :cxx_assignment: cxx_bitwise_assignment, cxx_arithmetic_assignment, cxx_const_assignment + + :cxx_bitwise: cxx_bitwise_not_to_noop, cxx_and_to_or, cxx_or_to_and, cxx_xor_to_or, cxx_lshift_to_rshift, cxx_rshift_to_lshift + + :cxx_bitwise_assignment: cxx_and_assign_to_or_assign, cxx_or_assign_to_and_assign, cxx_xor_assign_to_or_assign, cxx_lshift_assign_to_rshift_assign, cxx_bitwise_rshift_assign_to_lshift_assign + + :cxx_boundary: cxx_le_to_lt, cxx_lt_to_le, cxx_ge_to_gt, cxx_gt_to_ge + + :cxx_comparison: cxx_eq_to_ne, cxx_ne_to_eq, cxx_le_to_gt, cxx_lt_to_ge, cxx_ge_to_lt, cxx_gt_to_le + + :cxx_const_assignment: cxx_assign_const, cxx_init_const + + :cxx_decrement: cxx_pre_dec_to_pre_inc, cxx_post_dec_to_post_inc + + :cxx_default: cxx_increment, cxx_arithmetic, cxx_comparison, cxx_boundary + + :cxx_increment: cxx_pre_inc_to_pre_dec, cxx_post_inc_to_post_dec + + :cxx_logical: cxx_logical_and_to_or, cxx_logical_or_to_and + + :experimental: negate_mutator, remove_void_function_mutator, scalar_value_mutator, replace_call_mutator + + Single mutators: + :cxx_add_assign_to_sub_assign: Replaces += with -= + + :cxx_add_to_sub: Replaces + with - + + :cxx_and_assign_to_or_assign: Replaces &= with \|= + + :cxx_and_to_or: Replaces & with | + + :cxx_assign_const: Replaces 'a = b' with 'a = 42' + + :cxx_bitwise_not_to_noop: Replaces ~x with x + + :cxx_bitwise_rshift_assign_to_lshift_assign: Replaces >>= with <<= + + :cxx_div_assign_to_mul_assign: Replaces /= with \*= + + :cxx_div_to_mul: Replaces / with * + + :cxx_eq_to_ne: Replaces == with != + + :cxx_ge_to_gt: Replaces >= with > + + :cxx_ge_to_lt: Replaces >= with < + + :cxx_gt_to_ge: Replaces > with >= + + :cxx_gt_to_le: Replaces > with <= + + :cxx_init_const: Replaces 'T a = b' with 'T a = 42' + + :cxx_le_to_gt: Replaces <= with > + + :cxx_le_to_lt: Replaces <= with < + + :cxx_logical_and_to_or: Replaces && with || + + :cxx_logical_or_to_and: Replaces || with && + + :cxx_lshift_assign_to_rshift_assign: Replaces <<= with >>= + + :cxx_lshift_to_rshift: Replaces << with >> + + :cxx_lt_to_ge: Replaces < with >= + + :cxx_lt_to_le: Replaces < with <= + + :cxx_minus_to_noop: Replaces -x with x + + :cxx_mul_assign_to_div_assign: Replaces \*= with /= + + :cxx_mul_to_div: Replaces * with / + + :cxx_ne_to_eq: Replaces != with == + + :cxx_or_assign_to_and_assign: Replaces \|= with &= + + :cxx_or_to_and: Replaces | with & + + :cxx_post_dec_to_post_inc: Replaces x-- with x++ + + :cxx_post_inc_to_post_dec: Replaces x++ with x-- + + :cxx_pre_dec_to_pre_inc: Replaces --x with ++x + + :cxx_pre_inc_to_pre_dec: Replaces ++x with --x + + :cxx_rem_assign_to_div_assign: Replaces %= with /= + + :cxx_rem_to_div: Replaces % with / + + :cxx_rshift_to_lshift: Replaces << with >> + + :cxx_sub_assign_to_add_assign: Replaces -= with += + + :cxx_sub_to_add: Replaces - with + + + :cxx_xor_assign_to_or_assign: Replaces ^= with \|= + + :cxx_xor_to_or: Replaces ^ with | + + :negate_mutator: Negates conditionals !x to x and x to !x + + :remove_void_function_mutator: Removes calls to a function returning void + + :replace_call_mutator: Replaces call to a function with 42 + + :scalar_value_mutator: Replaces zeros with 42, and non-zeros with 0 + diff --git a/docs/generated/Mutators.rst b/docs/generated/Mutators.rst new file mode 100644 index 000000000..44ecf542d --- /dev/null +++ b/docs/generated/Mutators.rst @@ -0,0 +1,138 @@ +.. |op0| replace:: cxx_add_assign_to_sub_assign +.. |desc0| replace:: Replaces += with -= +.. |op1| replace:: cxx_add_to_sub +.. |desc1| replace:: Replaces + with - +.. |op2| replace:: cxx_and_assign_to_or_assign +.. |desc2| replace:: Replaces &= with \|= +.. |op3| replace:: cxx_and_to_or +.. |desc3| replace:: Replaces & with | +.. |op4| replace:: cxx_assign_const +.. |desc4| replace:: Replaces 'a = b' with 'a = 42' +.. |op5| replace:: cxx_bitwise_not_to_noop +.. |desc5| replace:: Replaces ~x with x +.. |op6| replace:: cxx_bitwise_rshift_assign_to_lshift_assign +.. |desc6| replace:: Replaces >>= with <<= +.. |op7| replace:: cxx_div_assign_to_mul_assign +.. |desc7| replace:: Replaces /= with \*= +.. |op8| replace:: cxx_div_to_mul +.. |desc8| replace:: Replaces / with * +.. |op9| replace:: cxx_eq_to_ne +.. |desc9| replace:: Replaces == with != +.. |op10| replace:: cxx_ge_to_gt +.. |desc10| replace:: Replaces >= with > +.. |op11| replace:: cxx_ge_to_lt +.. |desc11| replace:: Replaces >= with < +.. |op12| replace:: cxx_gt_to_ge +.. |desc12| replace:: Replaces > with >= +.. |op13| replace:: cxx_gt_to_le +.. |desc13| replace:: Replaces > with <= +.. |op14| replace:: cxx_init_const +.. |desc14| replace:: Replaces 'T a = b' with 'T a = 42' +.. |op15| replace:: cxx_le_to_gt +.. |desc15| replace:: Replaces <= with > +.. |op16| replace:: cxx_le_to_lt +.. |desc16| replace:: Replaces <= with < +.. |op17| replace:: cxx_logical_and_to_or +.. |desc17| replace:: Replaces && with || +.. |op18| replace:: cxx_logical_or_to_and +.. |desc18| replace:: Replaces || with && +.. |op19| replace:: cxx_lshift_assign_to_rshift_assign +.. |desc19| replace:: Replaces <<= with >>= +.. |op20| replace:: cxx_lshift_to_rshift +.. |desc20| replace:: Replaces << with >> +.. |op21| replace:: cxx_lt_to_ge +.. |desc21| replace:: Replaces < with >= +.. |op22| replace:: cxx_lt_to_le +.. |desc22| replace:: Replaces < with <= +.. |op23| replace:: cxx_minus_to_noop +.. |desc23| replace:: Replaces -x with x +.. |op24| replace:: cxx_mul_assign_to_div_assign +.. |desc24| replace:: Replaces \*= with /= +.. |op25| replace:: cxx_mul_to_div +.. |desc25| replace:: Replaces * with / +.. |op26| replace:: cxx_ne_to_eq +.. |desc26| replace:: Replaces != with == +.. |op27| replace:: cxx_or_assign_to_and_assign +.. |desc27| replace:: Replaces \|= with &= +.. |op28| replace:: cxx_or_to_and +.. |desc28| replace:: Replaces | with & +.. |op29| replace:: cxx_post_dec_to_post_inc +.. |desc29| replace:: Replaces x-- with x++ +.. |op30| replace:: cxx_post_inc_to_post_dec +.. |desc30| replace:: Replaces x++ with x-- +.. |op31| replace:: cxx_pre_dec_to_pre_inc +.. |desc31| replace:: Replaces --x with ++x +.. |op32| replace:: cxx_pre_inc_to_pre_dec +.. |desc32| replace:: Replaces ++x with --x +.. |op33| replace:: cxx_rem_assign_to_div_assign +.. |desc33| replace:: Replaces %= with /= +.. |op34| replace:: cxx_rem_to_div +.. |desc34| replace:: Replaces % with / +.. |op35| replace:: cxx_rshift_to_lshift +.. |desc35| replace:: Replaces << with >> +.. |op36| replace:: cxx_sub_assign_to_add_assign +.. |desc36| replace:: Replaces -= with += +.. |op37| replace:: cxx_sub_to_add +.. |desc37| replace:: Replaces - with + +.. |op38| replace:: cxx_xor_assign_to_or_assign +.. |desc38| replace:: Replaces ^= with \|= +.. |op39| replace:: cxx_xor_to_or +.. |desc39| replace:: Replaces ^ with | +.. |op40| replace:: negate_mutator +.. |desc40| replace:: Negates conditionals !x to x and x to !x +.. |op41| replace:: remove_void_function_mutator +.. |desc41| replace:: Removes calls to a function returning void +.. |op42| replace:: replace_call_mutator +.. |desc42| replace:: Replaces call to a function with 42 +.. |op43| replace:: scalar_value_mutator +.. |desc43| replace:: Replaces zeros with 42, and non-zeros with 0 + + +============= ================== +Operator Name Operator Semantics +============= ================== +|op0| |desc0| +|op1| |desc1| +|op2| |desc2| +|op3| |desc3| +|op4| |desc4| +|op5| |desc5| +|op6| |desc6| +|op7| |desc7| +|op8| |desc8| +|op9| |desc9| +|op10| |desc10| +|op11| |desc11| +|op12| |desc12| +|op13| |desc13| +|op14| |desc14| +|op15| |desc15| +|op16| |desc16| +|op17| |desc17| +|op18| |desc18| +|op19| |desc19| +|op20| |desc20| +|op21| |desc21| +|op22| |desc22| +|op23| |desc23| +|op24| |desc24| +|op25| |desc25| +|op26| |desc26| +|op27| |desc27| +|op28| |desc28| +|op29| |desc29| +|op30| |desc30| +|op31| |desc31| +|op32| |desc32| +|op33| |desc33| +|op34| |desc34| +|op35| |desc35| +|op36| |desc36| +|op37| |desc37| +|op38| |desc38| +|op39| |desc39| +|op40| |desc40| +|op41| |desc41| +|op42| |desc42| +|op43| |desc43| +============= ================== diff --git a/docs/requirements.txt b/docs/requirements.txt index 76fc55b5c..3f6e7c695 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,2 +1,2 @@ guzzle_sphinx_theme - +sphinx>=2.2.0 \ No newline at end of file diff --git a/include/mull/Mutators/MutatorsFactory.h b/include/mull/Mutators/MutatorsFactory.h index 4a29fcd0a..f5bde1e31 100644 --- a/include/mull/Mutators/MutatorsFactory.h +++ b/include/mull/Mutators/MutatorsFactory.h @@ -13,11 +13,13 @@ class MutatorsFactory { public: MutatorsFactory(); std::vector> mutators(const std::vector &groups); + void init(); + static std::string descriptionForGroup(const std::vector &groupMembers); std::vector> commandLineOptions(); + std::map> &getMutatorsMapping(); + std::map> &getGroupsMapping(); private: - void init(); - std::map> mutatorsMapping; std::map> groupsMapping; }; diff --git a/lib/Mutators/MutatorsFactory.cpp b/lib/Mutators/MutatorsFactory.cpp index 8a4d92c29..b47c0742a 100644 --- a/lib/Mutators/MutatorsFactory.cpp +++ b/lib/Mutators/MutatorsFactory.cpp @@ -238,7 +238,7 @@ vector> MutatorsFactory::mutators(const vector &grou /// Command Line Options -std::string descriptionForGroup(const std::vector &groupMembers) { +std::string MutatorsFactory::descriptionForGroup(const std::vector &groupMembers) { if (groupMembers.empty()) { return std::string("empty group?"); } @@ -270,3 +270,11 @@ std::vector> MutatorsFactory::commandLineOpt return options; } + +std::map> &MutatorsFactory::getMutatorsMapping() { + return mutatorsMapping; +} + +std::map> &MutatorsFactory::getGroupsMapping() { + return groupsMapping; +} diff --git a/tools/driver-cxx/CLIOptions.cpp b/tools/driver-cxx/CLIOptions.cpp index bf7cbaa27..b463af389 100644 --- a/tools/driver-cxx/CLIOptions.cpp +++ b/tools/driver-cxx/CLIOptions.cpp @@ -1,7 +1,9 @@ #include "CLIOptions.h" +#include #include #include #include +#include using namespace mull; using namespace tool; @@ -15,18 +17,21 @@ opt tool::InputFile( Positional, desc(""), Required, + value_desc("path"), cat(MullCXXCategory)); opt tool::Workers( "workers", desc("How many threads to use"), Optional, + value_desc("number"), cat(MullCXXCategory)); opt tool::ReportDirectory( "report-dir", desc("Where to store report (defaults to '.')"), Optional, + value_desc("directory"), init("."), cat(MullCXXCategory)); @@ -34,6 +39,7 @@ opt tool::ReportName( "report-name", desc("Filename for the report (only for supported reporters). Defaults to ."), Optional, + value_desc("filename"), init(""), cat(MullCXXCategory)); @@ -48,24 +54,27 @@ opt tool::CacheDir( "cache-dir", desc("Where to store cache (defaults to /tmp/mull-cache)"), Optional, + value_desc("directory"), init("/tmp/mull-cache"), cat(MullCXXCategory)); opt tool::CompilationDatabasePath( "compdb-path", desc("Path to a compilation database (compile_commands.json) for junk detection"), + value_desc("filename"), Optional, cat(MullCXXCategory)); opt tool::CompilationFlags( "compilation-flags", desc("Extra compilation flags for junk detection"), + value_desc("string"), Optional, cat(MullCXXCategory)); opt tool::DryRunOption( "dry-run", - desc("Skips real mutants execution"), + desc("Skips real mutants execution. Disabled by default"), Optional, init(false), cat(MullCXXCategory)); @@ -74,36 +83,42 @@ list tool::Mutators( "mutators", desc("Choose mutators:"), ZeroOrMore, + value_desc("mutator"), cat(MullCXXCategory)); opt tool::TestFrameworks( "test-framework", desc("Choose test framework:"), Required, + value_desc("framework"), cat(MullCXXCategory)); list tool::LDSearchPaths( "ld-search-path", desc("Library search path"), ZeroOrMore, + value_desc("directory"), cat(MullCXXCategory)); list tool::ExcludePaths( "exclude-path", desc("File/directory paths to ignore (supports regex)"), ZeroOrMore, + value_desc("regex"), cat(MullCXXCategory)); list tool::IncludePaths( "include-path", desc("File/directory paths to whitelist (supports regex)"), ZeroOrMore, + value_desc("regex"), cat(MullCXXCategory)); opt tool::SandboxOption( "sandbox", desc("Choose sandbox approach:"), Optional, + value_desc("sandbox"), init(SandboxKind::Timer), cat(MullCXXCategory)); @@ -111,8 +126,25 @@ list tool::ReportersOption( "reporters", desc("Choose reporters:"), ZeroOrMore, + value_desc("reporter"), cat(MullCXXCategory)); +opt tool::DumpCLIInterface( + "dump-cli", + desc("Prints CLI options in the Sphinx/RST friendly format"), + Optional, + init(false), + cat(MullCXXCategory), + Hidden); + +opt tool::DumpMutators( + "dump-mutators", + desc("Prints available mutators in the Sphinx/RST friendly format"), + Optional, + init(false), + cat(MullCXXCategory), + Hidden); + // clang-format on MutatorsCLIOptions::MutatorsCLIOptions(list ¶meter) @@ -133,6 +165,10 @@ std::vector> MutatorsCLIOptions::mutators() { return factory.mutators(selectedGroups); } +std::vector> &MutatorsCLIOptions::getOptions() { + return options; +} + TestFrameworkCLIOptions::TestFrameworkCLIOptions(opt ¶meter) : options(factory.commandLineOptions()), parameter(parameter) { int index = 0; @@ -147,11 +183,22 @@ TestFramework TestFrameworkCLIOptions::testFramework(Toolchain &toolchain, return factory.createTestFramework(name, toolchain, configuration); } +struct SandboxDefinition { + std::string name; + std::string description; + SandboxKind kind; +}; + +static std::vector sandboxes({ + { "None", "No sandboxing", SandboxKind::NoSandbox }, + { "Watchdog", "Uses 4 processes, not recommended", SandboxKind::Watchdog }, + { "Timer", "Fastest, Recommended", SandboxKind::Timer }, +}); + SandboxCLIOptions::SandboxCLIOptions(opt ¶meter) : parameter(parameter) { - parameter.getParser().addLiteralOption("None", SandboxKind::NoSandbox, "No sandboxing"); - parameter.getParser().addLiteralOption( - "Watchdog", SandboxKind::Watchdog, "Uses 4 processes, not recommended"); - parameter.getParser().addLiteralOption("Timer", SandboxKind::Timer, "Fastest, Recommended"); + for (auto &opt : sandboxes) { + parameter.getParser().addLiteralOption(opt.name.c_str(), opt.kind, opt.description.c_str()); + } } std::unique_ptr SandboxCLIOptions::sandbox() { @@ -165,15 +212,24 @@ std::unique_ptr SandboxCLIOptions::sandbox() { } } +struct ReporterDefinition { + std::string name; + std::string description; + ReporterKind kind; +}; + +static std::vector reporterOptions({ + { "IDE", "Prints compiler-like warnings into stdout", ReporterKind::IDE }, + { "SQLite", "Saves results into an SQLite database", ReporterKind::SQLite }, + { "Elements", + "Generates mutation-testing-elements compatible JSON file", + ReporterKind::Elements }, +}); + ReportersCLIOptions::ReportersCLIOptions(list ¶meter) : parameter(parameter) { - parameter.getParser().addLiteralOption( - "IDE", ReporterKind::IDE, "Prints compiler-like warnings into stdout"); - parameter.getParser().addLiteralOption( - "SQLite", ReporterKind::SQLite, "Saves results into an SQLite database"); - parameter.getParser().addLiteralOption( - "Elements", - ReporterKind::Elements, - "Generates mutation-testing-elements compatible JSON file"); + for (ReporterDefinition &opt : reporterOptions) { + parameter.getParser().addLiteralOption(opt.name.c_str(), opt.kind, opt.description.c_str()); + } } std::vector> ReportersCLIOptions::reporters(ReporterParameters params) { @@ -203,3 +259,142 @@ std::vector> ReportersCLIOptions::reporters(ReporterPa return reporters; } + +static void sanitizeString(std::string &input, const std::string &replacement) { + std::string escape("\\"); + auto pos = input.find(replacement); + if (pos != std::string::npos) { + input.replace(pos, replacement.size(), escape + replacement); + } +} + +static std::string sanitizeString(const std::string &input) { + std::string result = input; + sanitizeString(result, "|="); + sanitizeString(result, "*="); + return result; +} + +void tool::dumpCLIInterface() { + // Enumerating CLI options explicitly to control the order and what to show + Option *mutators = &(Option &)Mutators; + Option *reporters = &(Option &)ReportersOption; + std::vector