Command Line Options
This document aims to improve usability for the Mutate plugin in Dextool by explaining flags and options in more detail. The following sections are divided into the current existing commands for Mutate.
The flags for the different commands will be listed in the following format:
--flag-long-version [-flag-short-version]
input_example
Note: Several of the commands listed below can be set in the configuration-file as well. It is recommended to generate an .toml-file and set the corresponding fields in that file instead of having long chains of commands to execute in the terminal (it is usually more simple that way, reduces clutter in the terminal and increase usability for coming test sessions). The information listed below can also be viewed by executing dextool mutate --help in a terminal window, but with a shorter and less detailed explanation.
General
This options are general and can be used for all the commands in Mutate.
--config [-c]
--db
--out
--help [-h]
Common
These are options that occur in multiple command groups.
--include
--exclude
"*"
for
include and none for exclude. All patterns are adjusted to be relative to root
(default: .). This option is mostly used by e.g. header only libraries because
dextool need to analyze the test case source code to see how the library is
instantiated but the test code should not be mutated. Another use case is when
the root contains source code that shouldn't be mutated then these options make
it possible to specify what inside the root should be mutated.
# only mutate files under include but exclude test
dextool mutate analyze --include "include/*" --exclude "test/*"
--compile-db
--diff-from-stdin
# only analyze and save mutants in the changed files
git diff|dextool mutate analyze --diff-from-stdin
# only test mutants on the changed lines
git diff|dextool mutate test --diff-from-stdin
# only report mutants on the changed lines
git diff|dextool mutate report --diff-from-stdin
--profile
# set logging for all modules
--verbose trace # same as debug
# set logging for a specific module, comma separated
--verbose-module analyze.pass_schema=trace,analyze=trace
--verbose-module
with some
nonsense and it will print them.
Admin
Admin-mode for the plugin. Is used to execute administrative commands and to initialize/setup mutation testing for a project.
--init
--dump-config
--operation
--to-status
)
- compact : run a sqlite vacuum on the database with the goal of reducing the
database size. This is automatically done after operations that normally
result in a potentially significant reduction of the database size so most
often this option is not needed.
- stopTimeoutTest : changes the states in the database and internal worklists
such that the test phase will finish the timeout testing faster. This may be
desired if there are many timeout mutants and it takes a long time to
execute each of them.
- resetMutantSubKind : same as resetMutant but only operates on the
sub-mutation kinds which have a higher precision of which ones are affected.
- clearWorklist : clear the worklist of mutants to test.
--test-case-regex
--status
--to-status
--id
--rationale
--mutant-sub-kind
Analyze
Analyze-mode for the plugin. Is used to find mutation points in the project by traversing the AST for the eligible files. Will write results into a database that will be used later for testing and generation of mutants.
--mutant
Mutants to operate on. - all : All mutants are generated. - aor : Arithmetical Operator Replacement. - dcr : Decision/Condition Requirement. - lcr : Logical Connector Replacement. - lcrb : Logical Connector Replacement (Bit-wise). - ror : Relational Operator Replacement. - rorp : Relational Operator Replacement (Pointer). - sdl : Statement Deletion. - uoi : Unary Operator Insertion.
--compile-db
--in
--file-include
--file-exclude
compile_commands.json
via
--compile-db
.
# to analyze all files under include and src but exclude tests
dextool mutate analyze --file-include "include/*" --file-include "src/*" --file-exclude "src/test/*"
--fast-db-store
--force-save
#include
s significantly changes your code base.
--no-prune
--diff-from-stdin
because only a couple of
files are in the diff. By using --no-prune
the files that are not changed
will be kept in the database.
--schemata-mutants
--schemata-min-mutants
--schema-train
analyze
first with --force-save
and then test
with --schema-train
and --schema-only
4-5 times it is
possible to finish a training round in a short time.
--threads
Generate
Generate-mode for the plugin.
--id
Report
Report-mode for the plugin. Is used to generate a result-report at any given moment (before, after or during mutation testing execution). Can also be used to generate specific result that helps a user improve test cases among other.
Not all --section
are supported by all report --style
s. plain
supports
all of them. The rest are implemented as needed and if it is feasible.
--logdir
--section
Section | plain | json | html |
---|---|---|---|
alive | x | x | |
all_mut | x | x | (x) |
diff | x | x | |
killed | x | x | |
marked_mutants | x | ||
mut_recommend_kill | (x) | ||
mut_stat | x | ||
summary | x | x | x |
tc_full_overlap | x | (x) | |
tc_full_overlap_with_mutation_id | x | x | |
tc_groups | x | ||
tc_groups_similarity | x | ||
tc_killed | x | ||
tc_killed_no_mutants | x | x | (x) |
tc_map | x | ||
tc_min_set | x | ||
tc_similarity | x | ||
tc_stat | x | x | |
tc_suggestion | x | ||
tc_unique | x | (x) | |
trend | x | x | x |
Note: styles may have automatic support for sections which are always on, indicated by a (x)..
alive: Only report alive mutants.
killed: Only report killed Mutants.
all_mut: Report all mutants.
summary: A summary of the result such as the mutation score.
mut_stat: The top N mutations from -> to that has survived (e.g. "-" -> "+").
tc_killed: The mutants that each test case killed.
tc_stat: Test case statistics based on the number of mutants that are killed.
tc_map: Deprecated.
tc_suggestion: Report per test case alive mutants that are in the same source code location as mutants the test case are killing.
tc_killed_no_mutants: Provide a list of tests that killed no mutant. These tests are probably flawed.
tc_full_overlap: Provide a list of tests that killed the exact same mutants. They may be redundant and candidates for removal.
tc_full_overlap_with_mutation_id: Same as tc_full_overlap but include the mutant too. It makes it possible to do a deeper analysis of test cases.
tc_groups: Test case groups.
tc_min_set: Provide the minimal set of test cases needed in order to achieve the mutation score. It can be used to e.g. define a smoke screen test suite because the minimal set has the same verification coverage as the full test suite.
tc_similarity: Provide a list of tests and to what degree they are similar in terms of mutants the kill. Use it to e.g. merge tests or remove redundant test cases.
tc_groups_similarity: Compare the similarity between test groups. This is a "group" view compared to tc_similarity.
mut_recommend_kill: Report a list of high priority mutants to kill.
diff: Add a page that shows the diff as git would do it together with the mutants on the changed lines.
tc_unique: For each test case report the mutants that the test case is the only one to kill. This can be used in the reverse that test cases that have no unique mutants may be redundant. Recommended to use in conjunction with tc_similarity for a deeper analysis.
marked_mutants: List all manually marked mutants.
trend: print the recorded mutation score, one for each day, and a trend of how it is predicted to change.
--section-tc_stat-num
--section-tc_stat-sort
--style
Test
Test-mode for the plugin. Injects a mutant into the source code, compiles the project to see if the mutants was valid and then executes the test suite in order to analyze whether or not the test suite detected the mutant. Will also check if the mutant caused an infinity-loop, or simply took longer time than usual, by utilizing the timeout-implementation.
--build-cmd
--dry-run
--order
--test-cmd
--test-case-analyze-builtin
--test-case-analyze-cmd
--test-timeout
--schema-check
--schema-log
--max-alive <nr>
nr
alive mutants have been found. Intended to
be used when integrating mutation testing with pull requests to have an early
halting condition.
--schema-only
--schema-use
--schemata-min-mutants
--schema-parallel-mutants
--use-early-stop
--max-runtime
dextool mutate test --max-runtime "1 hours 30 minutes 10 msecs"
--load-behavior
--load-threshold
--load-behavior
is
triggered. By default it is set to the number of virtual cores on the computer.
--metadata
Configuration File
The template that is generated by
dextool mutate admin --init
try to be self explaining. This section is thus focused on explaining the
different categories ([....]
).
[workarea]
Configuration of the directories that dextool is allowed to change files in.
root
: Defines the root directory that all phases of mutation testing will use.
* the analyze phase will only store mutants that reside in the root or
sub-directories.
* the test phase will only mutate files that is inside the root.
* the report will make all paths relative to the root.
include
: See below.
exclude
: A project may want to further restrict what directories/files should
be mutated inside the root. It could for example be so that the src and test is
inside the same root. To discover all available mutants, C++ templates, the
analyser must analyze test cases because templates are instantiated there. But
it is obviously so that the tests should not be mutated. By configuring this
option to include=["src/*"]
it means that only the mutants inside
{root}/src
are saved in the database. This can be combined with exclude
to
remove e.g. files inside src
for this example.
[generic]
Generic options that affect all phases that. The most important to configure
here is the mutation operators to use (mutants
). It affects what mutants are
saved in the database, which ones are mutated and reported.
[analyze]
Options that affects the analyze phase.
id_algo
: Configures what algorithm to use when generating unique IDs for
mutants.
The default algorithm is strict
. If any code in a file is changed
then all mutants in that file are re-tested. The diff for testing is
basically per file. The problem is obvious for this because the most common
change is just a couple of lines in a file. This algorithm is safe but lead
to unnecessary testing of mutants.
The second algorithm is relaxed
. It is scope aware. Mutants are unique
within a file and within a scope. Only mutants within a scope are re-tested if
the source code in the scope is changed. This thus basically mean that the
algorithm works like "git diff". It only test mutants in scopes that have
changed. It makes it faster to test a code change.
[schema]
Schemata is a technique that inject multiple mutants at the same time in the SUT with code that allow them to be toggled one at a time. This make it possible to compile once and have hundreds of mutants in the binary at the same time. In short it cuts down on the compile+link time. It is highly recommended to enable this option because mutation testing becomes 50-10000% times faster (depending on the test suite runtime).
use
: activate use of schematan.
runtime
: The option inject
mean that dextool inject the runtime needed for
mutation testing in all roots or those specified by inject_runtime_impl
. This
is a nice and automated process. If this doesn't work because you are running
on an embedded system and need a modified schema runtime, linking errors etc
then you can opt to use the library
option. It means that you precompile the
runtime and manually link with the library. Dextool will do no magic.
check_schemata
: This option check that there are no errors with the schema by
executing the test suite once, after the schema is injected. The test suite
should, if everything worked as expected, signal PASSED/no failure. If it
failed in any way it means that there is a bug in the schema generator and it
isn't just.
mutants_per_schema
: The approximate max number of mutants a schema should
contain. Some compiles fail to compile when the source code is too big. This
allows you to control how many mutants are injected.
min_mutants_per_schema
: Minimum number of mutants a schema must contain for it to be used.
inject_runtime_impl
: Inject the runtime in only these files.
[coverage]
An additional pass will be executed when either the program or the tests changes. This pass instrument the source code to see which functions are covered by the tests. Any mutants that is in a function that is not covered will be marked as alive. It is because for the test suite to even have a chance of killing a mutant it must execute the function/method the mutant reside in. This option can greatly speed up the testing of all mutants.
use
: activate use of coverage.
It is strongly recommended to also track the test files such that the coverage
is automatically updated when the tests are changed (generic.test_paths
).
runtime
: The option inject
mean that dextool inject the runtime needed for
mutation testing in all roots or those specified by inject_runtime_impl
. This
is a nice and automated process. If this doesn't work because you are running
on an embedded system and need a modified schema runtime, linking errors etc
then you can opt to use the library
option. It means that you precompile the
runtime and manually link with the library. Dextool will do no magic.
inject_runtime_impl
: Inject the runtime in only these files.
[database]
Database options.
[compiler]
Options for the compiler such as extra flags to add or if a specific compiler
should be used instead of the one found in the compile_commands.json
file.
use_compiler_system_includes
: Extract all system includes from this compiler
instead of the one that is used in compile_commands.json
. This is important
for e.g. cross compilers or older versions of GCC. A cross-compiler may point
to a C++ stdlib that isn't compatible with clang which would lead to a total
analysis failure. By fooling dextool to instead derived the system includes
from another compiler it is still possible to complete the analysis phase.
[compile_commands]
Configuration of which compile_commands.json
to use and how it should be
filtered.
filter
: Use to remove flags that aren't compatible with clang such as -W
that only exist in GCC.
skip_compiler_args
: Sometimes the first argument isn't the compiler. Dextool
need to know where the compiler "start" in the argument list because the system
includes are extracted from the compiler.
[mutant_test]
Configuration of the test phase. This contains the most options because it is also the one that has to be highly flexible.
build_cmd
: Program/script used to build the application. Will be called to
compile both the original program (sanity check) and to compile the program
each time a mutant is injected.
test_cmd_dir
: The directory is analyzed for executables. All executables that
are found then used as test case binaries. This is a convenient option to use
when they are all in a directory easily accessible.
test_cmd_dir_search
: How test_cmd_dir
is scanned for executables. Default
is to scan recursively but if this is a problem because there are e.g.
executable test data in sub directories the search mode can be changed to
shallow
.
test_cmd_dir_flag
: The flags here are used when executing binaries found via
test_cmd_dir
. It is a convenient way of inactivating test cases in e.g.
Googletest.
test_cmd
: If test_cmd_dir
isn't suitable to use then this allows a manual
specification of the test binaries to execute together with, for the complex
cases, also specifying the flags to use per command.
test_cmd_timeout
: Timeout of the test suite. This should normally not be
used. The default for dextool is to use a dynamic timeout that is derived by
measuring the test suites execution time together with a timeout-re-test
algorithm that re-execute timeouts together with increasing until no visible
change is detected. By setting this option dextool will not derive the
execution and will not use the timeout-re-test algorithm.
build_cmd_timeout
: Configures a timeout for the build command. Use if the
build system can have intermittent lockups. The default is one hour.
analyze_cmd
: Configures dextool to call this command to analyze the output of
the test suite to derived which test cases that exist, which ones that killed a
mutant and stability. The intended use case of this option is embedded
developers that use a minimal, custom test framework.
analyze_using_builtin
: Use one or more of the builtin test framework
analyzers.
detected_new_test_case
: A programs test suite that evolve over time may add
new test cases. This control how dextool will behave when it finds a new test
case. Either just ignore it or re-test all mutants that has survived (alive) to
see if the new test cases kill any of those that previously survived.
detected_dropped_test_case
: Configures what dextool should do with the stored
information about a test case which it detects has been removed. Either just
leave it as it is or remove it. If the test case is removed all mutants that
the test case uniquely killed will be reset to unknown
statues which will
trigger them to be re-tested.
oldest_mutants
: The tool is unaware of the tests and if they have changed.
This is a configuration that tell the tool to re-test old mutants to see if
anything has changed in the test suite. The re-test, if activated, of old
mutants will only be done if there is nothing else to be done (the worklist is
empty).
oldest_mutants_percentage
: Instead of hard coding a specific number of
mutants this allows you to configure a percentage of the total number to test.
This is the recommended way of configuring re-test of old mutants because then
you do not need to tune it when the SUT grow in size.
parallel_test
: How many test binaries to run in parallel. If this option
isn't set then dextool mutate will run as many as you have virtual cores.
use_early_stop
: The tool will stop executing test binaries as soon as one
reports failed. This is useful if you have many test binaries because it cuts
down on the test time. It is highly recommended to activate this option, which
is why it is active by default. Note though that the report section
dead_test_case
and overlap
will be less accurate because, obviously, not
all test binaries are executed for each mutant but rather a subset. This can be
alleviated somewhat by executing tests in random order. For google test this is
--gtest_shuffle
.
continues_check_test_suite
: This option activates a test suite check that is
ran periodically. It try to execute the test suite with zero mutants. If it
ever fails it means that there is something wrong with the computer the tool is
executing on and it will revert the previously gathered results and stop. This
can happen when e.g. the disk becomes full.
continues_check_test_suite_period
: Configures how often to run the check,
every X mutant.
test_cmd_checksum
: Compare the checksum of the test binaries with and without
a mutant injected to determine which test binaries need to be executed. Only
those that are different are executed because well, those where affected by the
mutant. If no test binary is changed when the mutant is injected then the
mutant is an equivalent mutant because the compiler managed to "optimize away"
the modification. This option is recommended to activate because it cuts down
on the test time and allows the tool to find equivalent mutants. But to use it
it means that all test_cmd
must binaries, it can not be e.g. "make test".
This is obvious when you think about it because "make test" is never changed
when a mutant is injected.
This option also activate a checksum table of test_cmd
- mutation
status. If the checksum of the test_cmd
match what is already known then that
mutation status is used instead.
max_test_cmd_output
: Limits the number of mbytes captured from the test_cmd
executions. The limit is per test_cmd
. This is used to prevent e.g.
test_cmd
s that execute in an infinite loop and spew out Gbyte of output from
consuming all the available memory which lead to a crash of the plugin. The
default limit is 10 Mbyte. It should be enough for most reasonable test_cmd
s.
max_mem_usage_percentage
: Limit the max used memory. The limit is global for
the host thus includes all programs that are executed. If the limit is reached
the tool will start terminating test_cmd
s to reduce the memory usage. A
terminated test_cmd
is marked as timeout. This is to re-test them later on to
be really sure that they actually result in the host running out of memory
and thus isn't a fluke.
[report]
Configuration of the generated reports.
style
: The default report style to use when none is specified via the CLI.
sections
: An array of the default sections to use when none are specified via
the CLI.
high_interest_mutants_nr
: The number of mutants to show in the high interest
mutants section.
Resources
The runtime resources that are installed together with the tool such as the header that is injected for schemata can be overridden. Dextool mutate searches the following directories, in this order, for the resources:
$XDG_RUNTIME_DIR
/dextool/mutatewhich dextool
/data/mutatedirname $(which dextool)
/data/mutate$XDG_DATA_DIRS
/dextool/data/mutate
A user that wants to change the injected schemata header would for example add
the schemata_header.c
to $XDG_RUNTIME_DIR/.local/share/dextool/data/mutate