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