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 alias MutantPrio = NamedType!(long, Tag!"MutantPriority", long.init, TagStringable); 161 162 struct MutationStatus { 163 import std.datetime : SysTime; 164 import std.typecons : Nullable; 165 166 MutationStatusId statusId; 167 Mutation.Status status; 168 MutantPrio prio; 169 SysTime updated; 170 Nullable!SysTime added; 171 ExitStatus exitStatus; 172 } 173 174 /// Metadata about a line in a file. 175 struct LineMetadata { 176 FileId id; 177 uint line; 178 LineAttr attr; 179 180 this(FileId fid, uint line) { 181 this(fid, line, LineAttr.init); 182 } 183 184 this(FileId fid, uint line, LineAttr attr) { 185 this.id = fid; 186 this.line = line; 187 this.attr = attr; 188 } 189 190 void set(NoMut a) @trusted pure nothrow @nogc { 191 attr = LineAttr(a); 192 } 193 194 bool isNoMut() @safe pure nothrow const @nogc { 195 return attr.match!((NoMetadata a) => false, (NoMut a) => true); 196 } 197 } 198 199 struct NoMetadata { 200 } 201 202 /// A mutation suppression with optional tag and comment. 203 struct NoMut { 204 string tag; 205 string comment; 206 } 207 208 /// Metadata attributes that may be attached to a mutant. 209 alias MutantAttr = SumType!(NoMetadata, NoMut); 210 211 /// Metadata attributes that may be attached to a line. 212 alias LineAttr = SumType!(NoMetadata, NoMut); 213 214 /// Metadata about a mutant. 215 struct MutantMetaData { 216 import std.range : isOutputRange; 217 218 MutationId id; 219 MutantAttr attr; 220 221 this(MutationId id) { 222 this(id, MutantAttr.init); 223 } 224 225 this(MutationId id, MutantAttr attr) { 226 this.id = id; 227 this.attr = attr; 228 } 229 230 void set(NoMut a) @trusted pure nothrow @nogc { 231 attr = MutantAttr(a); 232 } 233 234 bool isNoMut() @safe pure nothrow const @nogc { 235 return attr.match!((NoMetadata a) => false, (NoMut a) => true); 236 } 237 238 string kindToString() @safe pure const { 239 import std.array : appender; 240 import std.format : FormatSpec; 241 242 auto buf = appender!string; 243 kindToString(buf); 244 return buf.data; 245 } 246 247 void kindToString(Writer)(ref Writer w) const if (isOutputRange!(Writer, char)) { 248 import std.range : put; 249 250 attr.match!((NoMetadata a) {}, (NoMut a) => put(w, "nomut")); 251 } 252 253 import std.range : isOutputRange; 254 255 string toString() @safe pure const { 256 import std.array : appender; 257 258 auto buf = appender!string; 259 toString(buf); 260 return buf.data; 261 } 262 263 void toString(Writer)(ref Writer w) const if (isOutputRange!(Writer, char)) { 264 kindToString(w); 265 } 266 } 267 268 alias Rationale = NamedType!(string, Tag!"Rationale", string.init, TagStringable); 269 270 struct MarkedMutant { 271 MutationStatusId statusId; 272 273 /// Checksum of the marked mutant. 274 Checksum statusChecksum; 275 276 MutationId mutationId; 277 278 SourceLoc sloc; 279 Path path; 280 281 /// The status it should always be changed to. 282 Mutation.Status toStatus; 283 284 /// Time when the mutant where marked. 285 SysTime time; 286 287 Rationale rationale; 288 289 string mutText; 290 } 291 292 /// A fragment of a schemata which is one application. 293 struct SchemataFragment { 294 Path file; 295 Offset offset; 296 const(ubyte)[] text; 297 } 298 299 struct Schemata { 300 SchemataId id; 301 302 /// Sorted in the order they should be applied. 303 SchemataFragment[] fragments; 304 } 305 306 struct TestCmdRuntime { 307 SysTime timeStamp; 308 309 /// The execution time of the test suite. 310 Duration runtime; 311 } 312 313 struct MutationScore { 314 SysTime timeStamp; 315 NamedType!(double, Tag!"MutationScore", 0.0, TagStringable) score; 316 } 317 318 alias TestFilePath = NamedType!(Path, Tag!"TestFilePath", Path.init, Hashable, TagStringable); 319 alias TestFileChecksum = NamedType!(Checksum, Tag!"TestFileChecksum", 320 Checksum.init, TagStringable, Hashable); 321 322 struct TestFile { 323 TestFilePath file; 324 325 /// Checksum of the content. 326 TestFileChecksum checksum; 327 328 /// Last time the file was changed. 329 SysTime timeStamp; 330 } 331 332 alias CoverageRegionId = NamedType!(long, Tag!"CoverageRegionId", long.init, 333 Comparable, Hashable, ConvertStringable); 334 struct CovRegion { 335 CoverageRegionId id; 336 Offset region; 337 } 338 339 /// A file that a root is dependent on. 340 struct DepFile { 341 Path file; 342 Checksum checksum; 343 } 344 345 alias ToolVersion = NamedType!(long, Tag!"ToolVersion", long.init, TagStringable, Comparable); 346 347 alias ChecksumTestCmdOriginal = NamedType!(Checksum64, 348 Tag!"ChecksumTestCmdOriginal", Checksum64.init, TagStringable); 349 350 alias ChecksumTestCmdMutated = NamedType!(Checksum64, 351 Tag!"ChecksumTestCmdMutated", Checksum64.init, TagStringable); 352 353 enum SchemaStatus { 354 /// no status exist 355 none, 356 /// the schema compiled and the test suite executed OK 357 ok, 358 /// either it failed to compile or the test suite failed 359 broken, 360 /// the schema only contain killed mutants 361 allKilled, 362 }