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 sumtype;
16 
17 import dextool.type : AbsolutePath, Path;
18 import dextool.plugin.mutate.backend.type;
19 
20 import dextool.plugin.mutate.backend.database.schema : MarkedMutantTbl;
21 public import dextool.plugin.mutate.backend.database.schema : MutantTimeoutCtxTbl;
22 
23 alias MutantTimeoutCtx = MutantTimeoutCtxTbl;
24 
25 @safe:
26 
27 /// Primary key in the mutation table
28 struct MutationId {
29     long value;
30     alias value this;
31 }
32 
33 /// Primary key for mutation status
34 struct MutationStatusId {
35     long value;
36     alias value this;
37 }
38 
39 /// Primary key in the files table
40 struct FileId {
41     long value;
42     alias value this;
43 }
44 
45 /// Primary key in the test_case table
46 struct TestCaseId {
47     long value;
48     alias value this;
49 }
50 
51 /// Primary key for mutation schematas.
52 struct SchemataId {
53     long value;
54     alias value this;
55 }
56 
57 /// Primary key for a schemata fragment.
58 struct SchemataFragmentId {
59     long value;
60     alias value this;
61 }
62 
63 struct MutationEntry {
64     MutationId id;
65     Path file;
66     SourceLoc sloc;
67     MutationPoint mp;
68     Duration timeSpentMutating;
69     Language lang;
70 }
71 
72 struct NextMutationEntry {
73     import std.typecons : Nullable;
74 
75     enum Status {
76         /// Mutant retrieved.
77         ok,
78         /// All mutants tested.
79         done,
80     }
81 
82     Status st;
83     Nullable!MutationEntry entry;
84 }
85 
86 struct MutationPointEntry {
87     MutationPoint mp;
88     Path file;
89     /// Start of the mutation point.
90     SourceLoc sloc;
91     /// End of the mutation point.
92     SourceLoc slocEnd;
93 }
94 
95 /// The source code mutations for a mutation point.
96 struct MutationPointEntry2 {
97     Path file;
98     Offset offset;
99     /// Start of the mutation point.
100     SourceLoc sloc;
101     /// End of the mutation point.
102     SourceLoc slocEnd;
103     CodeMutant[] cms;
104 
105     void put(CodeMutant m) @safe pure nothrow {
106         cms ~= m;
107     }
108 }
109 
110 /// Report about mutants of a specific kind(s).
111 struct MutationReportEntry {
112     ///
113     long count;
114     /// Test time spent on the mutants.
115     Duration time;
116 }
117 
118 /// Mutants that are tagged with nomut of a specific kind(s).
119 struct MetadataNoMutEntry {
120     ///
121     long count;
122 }
123 
124 struct MutantInfo {
125     MutationId id;
126     Mutation.Status status;
127     Mutation.Kind kind;
128     SourceLoc sloc;
129 }
130 
131 struct TestCaseInfo {
132     /// The sum on the execution time of killing the mutants.
133     Duration time;
134     ///
135     long killedMutants;
136 }
137 
138 /// What mutants a test case killed.
139 struct TestCaseInfo2 {
140     TestCase name;
141     MutationId[] killed;
142 }
143 
144 struct MutationStatusTime {
145     import std.datetime : SysTime;
146 
147     MutationStatusId id;
148     SysTime updated;
149 }
150 
151 struct MutationStatus {
152     import std.datetime : SysTime;
153     import std.typecons : Nullable;
154 
155     MutationStatusId statusId;
156     Mutation.Status status;
157     MutantTestCount testCnt;
158     SysTime updated;
159     Nullable!SysTime added;
160 }
161 
162 /// Metadata about a line in a file.
163 struct LineMetadata {
164     FileId id;
165     uint line;
166     LineAttr attr;
167 
168     this(FileId fid, uint line) {
169         this(fid, line, LineAttr.init);
170     }
171 
172     this(FileId fid, uint line, LineAttr attr) {
173         this.id = fid;
174         this.line = line;
175         this.attr = attr;
176     }
177 
178     void set(NoMut a) @trusted pure nothrow @nogc {
179         attr = LineAttr(a);
180     }
181 
182     bool isNoMut() @safe pure nothrow const @nogc {
183         return attr.match!((NoMetadata a) => false, (NoMut a) => true);
184     }
185 }
186 
187 struct NoMetadata {
188 }
189 
190 /// A mutation suppression with optional tag and comment.
191 struct NoMut {
192     string tag;
193     string comment;
194 }
195 
196 /// Metadata attributes that may be attached to a mutant.
197 alias MutantAttr = SumType!(NoMetadata, NoMut);
198 
199 /// Metadata attributes that may be attached to a line.
200 alias LineAttr = SumType!(NoMetadata, NoMut);
201 
202 /// Metadata about a mutant.
203 struct MutantMetaData {
204     import std.range : isOutputRange;
205 
206     MutationId id;
207     MutantAttr attr;
208 
209     this(MutationId id) {
210         this(id, MutantAttr.init);
211     }
212 
213     this(MutationId id, MutantAttr attr) {
214         this.id = id;
215         this.attr = attr;
216     }
217 
218     void set(NoMut a) @trusted pure nothrow @nogc {
219         attr = MutantAttr(a);
220     }
221 
222     bool isNoMut() @safe pure nothrow const @nogc {
223         return attr.match!((NoMetadata a) => false, (NoMut a) => true);
224     }
225 
226     string kindToString() @safe pure const {
227         import std.array : appender;
228         import std.format : FormatSpec;
229 
230         auto buf = appender!string;
231         kindToString(buf);
232         return buf.data;
233     }
234 
235     void kindToString(Writer)(ref Writer w) const if (isOutputRange!(Writer, char)) {
236         import std.range : put;
237 
238         attr.match!((NoMetadata a) {}, (NoMut a) => put(w, "nomut"));
239     }
240 
241     import std.range : isOutputRange;
242 
243     string toString() @safe pure const {
244         import std.array : appender;
245 
246         auto buf = appender!string;
247         toString(buf);
248         return buf.data;
249     }
250 
251     void toString(Writer)(ref Writer w) const if (isOutputRange!(Writer, char)) {
252         kindToString(w);
253     }
254 }
255 
256 struct Rationale {
257     string payload;
258     alias payload this;
259 }
260 
261 struct MarkedMutant {
262     MutationStatusId statusId;
263     /// Checksum of the marked mutant.
264     Checksum statusChecksum;
265 
266     MutationId mutationId;
267 
268     SourceLoc sloc;
269     Path path;
270 
271     /// The status it should always be changed to.
272     Mutation.Status toStatus;
273 
274     /// Time when the mutant where marked.
275     SysTime time;
276 
277     Rationale rationale;
278 
279     string mutText;
280 }
281 
282 /// A fragment of a schemata which is one application.
283 struct SchemataFragment {
284     Path file;
285     Offset offset;
286     const(ubyte)[] text;
287 }
288 
289 struct Schemata {
290     SchemataId id;
291 
292     /// Sorted in the order they should be applied.
293     SchemataFragment[] fragments;
294 }