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