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.backend.database.type; 11 12 import core.time : Duration; 13 import std.datetime : SysTime; 14 15 import my.named_type; 16 import my.hash : Checksum64; 17 import sumtype; 18 19 import dextool.type : AbsolutePath, Path; 20 import dextool.plugin.mutate.backend.type; 21 22 public import dextool.plugin.mutate.backend.database.schema : MutantTimeoutCtxTbl; 23 public import dextool.plugin.mutate.backend.type : MutantTimeProfile; 24 25 @safe: 26 27 /// The context (state) of how the testing of the timeout mutants are going. 28 alias MutantTimeoutCtx = MutantTimeoutCtxTbl; 29 30 /// Primary key in the mutation table 31 alias MutationId = NamedType!(long, Tag!"MutationId", 0, Comparable, Hashable, ConvertStringable); 32 33 /// Primary key for mutation status 34 alias MutationStatusId = NamedType!(long, Tag!"MutationStatusId", long.init, 35 Comparable, Hashable, ConvertStringable); 36 37 /// Primary key in the files table 38 alias FileId = NamedType!(long, Tag!"FileId", long.init, Comparable, Hashable, TagStringable); 39 40 /// Primary key in the test files table 41 alias TestFileId = NamedType!(long, Tag!"TestFileId", long.init, Comparable, 42 Hashable, TagStringable); 43 44 /// Primary key in the test_case table 45 alias TestCaseId = NamedType!(long, Tag!"TestCaseId", long.init, Comparable, 46 Hashable, TagStringable); 47 48 /// Primary key for mutation schematas. 49 alias SchemataId = NamedType!(long, Tag!"SchemataId", long.init, Comparable, 50 Hashable, TagStringable); 51 52 /// Primary key for a schemata fragment. 53 alias SchemataFragmentId = NamedType!(long, Tag!"SchemataFragmentId", 54 long.init, Comparable, Hashable, TagStringable); 55 56 struct MutationEntry { 57 MutationId id; 58 Path file; 59 SourceLoc sloc; 60 MutationPoint mp; 61 MutantTimeProfile profile; 62 Language lang; 63 } 64 65 struct NextMutationEntry { 66 import std.typecons : Nullable; 67 68 enum Status { 69 /// Mutant retrieved. 70 ok, 71 /// All mutants tested. 72 done, 73 } 74 75 Status st; 76 Nullable!MutationEntry entry; 77 } 78 79 struct MutationPointEntry { 80 MutationPoint mp; 81 Path file; 82 /// Start of the mutation point. 83 SourceLoc sloc; 84 /// End of the mutation point. 85 SourceLoc slocEnd; 86 } 87 88 /// The source code mutations for a mutation point. 89 struct MutationPointEntry2 { 90 Path file; 91 Offset offset; 92 /// Start of the mutation point. 93 SourceLoc sloc; 94 /// End of the mutation point. 95 SourceLoc slocEnd; 96 CodeMutant[] cms; 97 98 void put(CodeMutant m) @safe pure nothrow { 99 cms ~= m; 100 } 101 } 102 103 /// Report about mutants of a specific kind(s). 104 struct MutationReportEntry { 105 /// 106 long count; 107 108 /// Test time spent on the mutants. 109 MutantTimeProfile time; 110 } 111 112 /// Mutants that are tagged with nomut of a specific kind(s). 113 struct MetadataNoMutEntry { 114 /// 115 long count; 116 } 117 118 struct MutantInfo { 119 MutationId id; 120 Mutation.Status status; 121 ExitStatus ecode; 122 Mutation.Kind kind; 123 SourceLoc sloc; 124 } 125 126 struct MutantInfo2 { 127 MutationId id; 128 Mutation.Status status; 129 ExitStatus exitStatus; 130 Path file; 131 SourceLoc sloc; 132 MutantPrio prio; 133 SysTime updated; 134 135 // number of test cases that killed the mutant 136 int tcKilled; 137 } 138 139 struct TestCaseInfo { 140 /// The sum on the execution time of killing the mutants. 141 MutantTimeProfile time; 142 143 /// 144 long killedMutants; 145 } 146 147 /// What mutants a test case killed. 148 struct TestCaseInfo2 { 149 TestCase name; 150 MutationId[] killed; 151 } 152 153 struct MutationStatusTime { 154 import std.datetime : SysTime; 155 156 MutationStatusId id; 157 SysTime updated; 158 } 159 160 struct MutantTestTime { 161 MutationStatusId id; 162 Mutation.Status status; 163 Duration compileTime; 164 Duration testTime; 165 } 166 167 alias MutantPrio = NamedType!(long, Tag!"MutantPriority", long.init, TagStringable); 168 169 struct MutationStatus { 170 import std.datetime : SysTime; 171 import std.typecons : Nullable; 172 173 MutationStatusId statusId; 174 Mutation.Status status; 175 MutantPrio prio; 176 SysTime updated; 177 Nullable!SysTime added; 178 ExitStatus exitStatus; 179 } 180 181 /// Metadata about a line in a file. 182 struct LineMetadata { 183 FileId id; 184 uint line; 185 LineAttr attr; 186 187 this(FileId fid, uint line) { 188 this(fid, line, LineAttr.init); 189 } 190 191 this(FileId fid, uint line, LineAttr attr) { 192 this.id = fid; 193 this.line = line; 194 this.attr = attr; 195 } 196 197 void set(NoMut a) @trusted pure nothrow @nogc { 198 attr = LineAttr(a); 199 } 200 201 bool isNoMut() @safe pure nothrow const @nogc { 202 return attr.match!((NoMetadata a) => false, (NoMut a) => true); 203 } 204 } 205 206 struct NoMetadata { 207 } 208 209 /// A mutation suppression with optional tag and comment. 210 struct NoMut { 211 string tag; 212 string comment; 213 } 214 215 /// Metadata attributes that may be attached to a mutant. 216 alias MutantAttr = SumType!(NoMetadata, NoMut); 217 218 /// Metadata attributes that may be attached to a line. 219 alias LineAttr = SumType!(NoMetadata, NoMut); 220 221 /// Metadata about a mutant. 222 struct MutantMetaData { 223 import std.range : isOutputRange; 224 225 MutationId id; 226 MutantAttr attr; 227 228 this(MutationId id) { 229 this(id, MutantAttr.init); 230 } 231 232 this(MutationId id, MutantAttr attr) { 233 this.id = id; 234 this.attr = attr; 235 } 236 237 void set(NoMut a) @trusted pure nothrow @nogc { 238 attr = MutantAttr(a); 239 } 240 241 bool isNoMut() @safe pure nothrow const @nogc { 242 return attr.match!((NoMetadata a) => false, (NoMut a) => true); 243 } 244 245 string kindToString() @safe pure const { 246 import std.array : appender; 247 import std.format : FormatSpec; 248 249 auto buf = appender!string; 250 kindToString(buf); 251 return buf.data; 252 } 253 254 void kindToString(Writer)(ref Writer w) const if (isOutputRange!(Writer, char)) { 255 import std.range : put; 256 257 attr.match!((NoMetadata a) {}, (NoMut a) => put(w, "nomut")); 258 } 259 260 import std.range : isOutputRange; 261 262 string toString() @safe pure const { 263 import std.array : appender; 264 265 auto buf = appender!string; 266 toString(buf); 267 return buf.data; 268 } 269 270 void toString(Writer)(ref Writer w) const if (isOutputRange!(Writer, char)) { 271 kindToString(w); 272 } 273 } 274 275 alias Rationale = NamedType!(string, Tag!"Rationale", string.init, TagStringable); 276 277 struct MarkedMutant { 278 MutationStatusId statusId; 279 280 /// Checksum of the marked mutant. 281 Checksum statusChecksum; 282 283 MutationId mutationId; 284 285 SourceLoc sloc; 286 Path path; 287 288 /// The status it should always be changed to. 289 Mutation.Status toStatus; 290 291 /// Time when the mutant where marked. 292 SysTime time; 293 294 Rationale rationale; 295 296 string mutText; 297 } 298 299 /// A fragment of a schemata which is one application. 300 struct SchemataFragment { 301 Path file; 302 Offset offset; 303 const(ubyte)[] text; 304 } 305 306 struct Schemata { 307 SchemataId id; 308 309 /// Sorted in the order they should be applied. 310 SchemataFragment[] fragments; 311 } 312 313 struct TestCmdRuntime { 314 SysTime timeStamp; 315 316 /// The execution time of the test suite. 317 Duration runtime; 318 } 319 320 struct MutationScore { 321 SysTime timeStamp; 322 NamedType!(double, Tag!"MutationScore", 0.0, TagStringable) score; 323 } 324 325 alias TestFilePath = NamedType!(Path, Tag!"TestFilePath", Path.init, Hashable, TagStringable); 326 alias TestFileChecksum = NamedType!(Checksum, Tag!"TestFileChecksum", 327 Checksum.init, TagStringable, Hashable); 328 329 struct TestFile { 330 TestFilePath file; 331 332 /// Checksum of the content. 333 TestFileChecksum checksum; 334 335 /// Last time the file was changed. 336 SysTime timeStamp; 337 } 338 339 alias CoverageRegionId = NamedType!(long, Tag!"CoverageRegionId", long.init, 340 Comparable, Hashable, ConvertStringable); 341 struct CovRegion { 342 CoverageRegionId id; 343 Offset region; 344 } 345 346 /// A file that a root is dependent on. 347 struct DepFile { 348 Path file; 349 Checksum checksum; 350 } 351 352 alias ToolVersion = NamedType!(long, Tag!"ToolVersion", long.init, TagStringable, Comparable); 353 354 alias ChecksumTestCmdOriginal = NamedType!(Checksum64, 355 Tag!"ChecksumTestCmdOriginal", Checksum64.init, TagStringable); 356 357 alias ChecksumTestCmdMutated = NamedType!(Checksum64, 358 Tag!"ChecksumTestCmdMutated", Checksum64.init, TagStringable); 359 360 enum SchemaStatus { 361 /// no status exist 362 none, 363 /// the schema compiled and the test suite executed OK 364 ok, 365 /// either it failed to compile or the test suite failed 366 broken, 367 /// the schema only contain killed mutants 368 allKilled, 369 } 370 371 struct WorklistItem { 372 MutationStatusId id; 373 MutantPrio prio; 374 }