1 /** 2 Copyright: Copyright (c) 2018, Joakim Brännström. All rights reserved. 3 License: MPL-2 4 Author: Joakim Brännström (joakim.brannstrom@gmx.com) 5 6 This Source Code Form is subject to the terms of the Mozilla Public License, 7 v.2.0. If a copy of the MPL was not distributed with this file, You can obtain 8 one at http://mozilla.org/MPL/2.0/. 9 */ 10 module dextool.plugin.mutate.config; 11 12 import core.time : Duration, dur; 13 import std.typecons : Nullable; 14 15 import my.filter : GlobFilter; 16 import my.named_type; 17 import my.optional; 18 19 import dextool.plugin.mutate.type; 20 import dextool.type : AbsolutePath, Path; 21 public import dextool.plugin.mutate.backend : Mutation, TestGroup; 22 23 /// The mode the tool is operating in 24 enum ToolMode { 25 /// No mode set 26 none, 27 /// analyze for mutation points 28 analyzer, 29 /// center that can operate and control subcomponents 30 generate_mutant, 31 /// test mutation points with a test suite 32 test_mutants, 33 /// generate a report of the mutation points 34 report, 35 /// administrator interface for the mutation database 36 admin, 37 /// Dump the TOML configuration to the console 38 dumpConfig, 39 /// Write a TOML config to the filesystem 40 initConfig, 41 } 42 43 /// Config of the report. 44 struct ConfigReport { 45 ReportKind reportKind; 46 ReportSection[] reportSection = [ReportSection.summary]; 47 48 /// Directory to write logs to when writing to the filesystem. 49 AbsolutePath logDir; 50 51 /// Controls how to sort test cases by their kill statistics. 52 ReportKillSortOrder tcKillSortOrder; 53 int tcKillSortNum = 20; 54 55 /// User regex for reporting groups of tests 56 TestGroup[] testGroups; 57 58 /// If a unified diff should be used in the report 59 bool unifiedDiff; 60 61 /// If profiling data should be printed. 62 bool profile; 63 64 NamedType!(uint, Tag!"HighInterestMutantsNr", uint.init, TagStringable) highInterestMutantsNr = 5; 65 } 66 67 /// Configuration data for the compile_commands.json 68 struct ConfigCompileDb { 69 import dextool.compilation_db : CompileCommandFilter; 70 71 /// Raw user input via either config or cli 72 string[] rawDbs; 73 74 /// path to compilation databases. 75 AbsolutePath[] dbs; 76 77 /// Flags the user wants to be automatically removed from the compile_commands.json. 78 CompileCommandFilter flagFilter; 79 } 80 81 /// Configuration of how the mutation analyzer should act. 82 struct ConfigAnalyze { 83 /// User input of excludes before they are adjusted to relative root 84 string[] rawExclude; 85 /// User input of includes before they are adjusted to relative root 86 string[] rawInclude; 87 88 /// The constructed glob filter which based on rawExclude and rawinclude. 89 GlobFilter fileMatcher; 90 91 /// The size of the thread pool which affects how many files are analyzed in parallel. 92 int poolSize; 93 94 /// What files to analyze is derived from a diff. 95 bool unifiedDiffFromStdin; 96 97 /// Remove files from the database that aren't found when analyzing. 98 bool prune; 99 100 /// Turn off the sqlite synchronization safety 101 bool fastDbStore; 102 103 /// If profiling data should be printed. 104 bool profile; 105 106 /// Force the result from the files to always be saved 107 bool forceSaveAnalyze; 108 109 /// User file/directories containing tests to checksum and timestamp 110 string[] rawTestPaths; 111 AbsolutePath[] testPaths; 112 113 /// User input of excludes before they are adjusted to relative root 114 string[] rawTestExclude; 115 /// User input of includes before they are adjusted to relative root 116 string[] rawTestInclude; 117 118 /// The constructed glob filter which based on rawExclude and rawinclude. 119 GlobFilter testFileMatcher; 120 } 121 122 /// Settings for the compiler 123 struct ConfigCompiler { 124 import dextool.compilation_db : SystemCompiler = Compiler; 125 126 /// Additional flags the user wants to add besides those that are in the compile_commands.json. 127 string[] extraFlags; 128 129 /// True requires system includes to be passed on to the compiler via -I 130 bool forceSystemIncludes; 131 132 /// Deduce compiler flags from this compiler and not the one in the 133 /// supplied compilation database. / This is needed when the one specified 134 /// in the DB has e.g. a c++ stdlib that is not compatible with clang. 135 SystemCompiler useCompilerSystemIncludes; 136 137 NamedType!(bool, Tag!"AllowErrors", bool.init, TagStringable) allowErrors; 138 } 139 140 /// Settings for mutation testing 141 struct ConfigMutationTest { 142 ShellCommand[] mutationTester; 143 /// Find executables in this directory and add them to mutationTester. 144 Path[] testCommandDir; 145 /// Flags to add to all executables found in `testCommandDir` 146 string[] testCommandDirFlag; 147 148 ShellCommand mutationCompile; 149 ShellCommand[] mutationTestCaseAnalyze; 150 TestCaseAnalyzeBuiltin[] mutationTestCaseBuiltin; 151 152 /// If the user hard code a timeout for the test suite. 153 Nullable!Duration mutationTesterRuntime; 154 155 /// Timeout to use when compiling. 156 Duration buildCmdTimeout = 30.dur!"minutes"; 157 158 /// In what order to choose mutants to test. 159 MutationOrder mutationOrder = MutationOrder.bySize; 160 bool dryRun; 161 162 /// How to behave when new test cases are detected. 163 enum NewTestCases { 164 doNothing, 165 /// Automatically reset alive mutants 166 resetAlive, 167 } 168 169 NewTestCases onNewTestCases; 170 171 /// How to behave when test cases are detected of having been removed 172 enum RemovedTestCases { 173 doNothing, 174 /// Remove it and all results connectedto the test case 175 remove, 176 } 177 178 RemovedTestCases onRemovedTestCases; 179 180 /// How to behave when mutants have aged. 181 enum OldMutant { 182 nothing, 183 test, 184 } 185 186 OldMutant onOldMutants; 187 long oldMutantsNr; 188 NamedType!(double, Tag!"OldMutantPercentage", double.init, TagStringable) oldMutantPercentage = 0.0; 189 190 /// Max time to run mutation testing. 191 // note that Duration.max + Clock.currTime results in a negative time... 192 Duration maxRuntime = 52.dur!"weeks"; 193 194 // Constrain the mutation testing. 195 TestConstraint constraint; 196 197 /// If constraints should be read from a unified diff via stdin. 198 bool unifiedDiffFromStdin; 199 200 /// Stop after this many alive mutants are found. Only effective if constraint.empty is false. 201 Nullable!int maxAlive; 202 203 /// The size of the thread pool which affects how many tests are executed in parallel. 204 int testPoolSize; 205 206 /// If early stopping of test command execution should be used 207 bool useEarlyTestCmdStop; 208 209 enum LoadBehavior { 210 nothing, 211 /// Slow the testing until the load goes below the threshold 212 slowdown, 213 /// Stop mutation testing if the 15min load average reach this number. 214 halt, 215 } 216 217 LoadBehavior loadBehavior; 218 NamedType!(double, Tag!"LoadThreshold", double.init, TagStringable) loadThreshold; 219 220 /// Continuesly run the test suite to see that the test suite is OK when no mutants are injected. 221 NamedType!(bool, Tag!"ContinuesCheckTestSuite", bool.init, TagStringable) contCheckTestSuite; 222 NamedType!(int, Tag!"ContinuesCheckTestSuitePeriod", int.init, TagStringable) contCheckTestSuitePeriod = 100; 223 224 NamedType!(bool, Tag!"TestCmdChecksum", bool.init, TagStringable) testCmdChecksum; 225 226 NamedType!(long, Tag!"MaxTestCaseOutputCaptureMbyte", int.init, TagStringable) maxTestCaseOutput = 10; 227 } 228 229 /// Settings for the administration mode 230 struct ConfigAdmin { 231 AdminOperation adminOp; 232 Mutation.Status mutantStatus; 233 Mutation.Status mutantToStatus; 234 string testCaseRegex; 235 long mutationId; 236 string mutantRationale; 237 238 /// used to specify a kind of mutation 239 Mutation.Kind[] subKind; 240 } 241 242 struct ConfigWorkArea { 243 /// User input root. 244 string rawRoot; 245 246 AbsolutePath root; 247 248 /// User input of excludes before they are adjusted to relative root 249 string[] rawExclude; 250 /// User input of includes before they are adjusted to relative root 251 string[] rawInclude; 252 253 /// The constructed glob filter which based on rawExclude and rawinclude. 254 /// Only mutants whose location match will be generated. 255 GlobFilter mutantMatcher; 256 } 257 258 /// Configuration of the generate mode. 259 struct ConfigGenerate { 260 long mutationId; 261 } 262 263 struct ConfigSchema { 264 bool use; 265 266 SchemaRuntime runtime; 267 268 /// Number of mutants to at most put in a schema (soft limit) 269 NamedType!(long, Tag!"MutantsPerSchema", long.init, TagStringable) mutantsPerSchema = 1000; 270 271 /// Minimum number of mutants per schema for the schema to be saved in the database. 272 NamedType!(long, Tag!"MinMutantsPerSchema", long.init, TagStringable) minMutantsPerSchema = 3; 273 274 /// Sanity check a schemata before it is used. 275 bool sanityCheckSchemata; 276 277 /// If the schematas should be written to a separate file for offline inspection. 278 bool log; 279 280 /// Stop mutation testing after the last schemata has been executed 281 bool stopAfterLastSchema; 282 283 /// allows a user to control exactly which files the coverage and schemata 284 /// runtime is injected in. 285 UserRuntime[] userRuntimeCtrl; 286 } 287 288 struct ConfigCoverage { 289 bool use; 290 291 CoverageRuntime runtime; 292 293 /// If the generated coverage files should be saved. 294 bool log; 295 296 /// allows a user to control exactly which files the coverage and schemata 297 /// runtime is injected in. 298 UserRuntime[] userRuntimeCtrl; 299 }