1 /**
2 Copyright: Copyright (c) 2020, 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.report.html.page_test_case_full_overlap;
11 
12 import logger = std.experimental.logger;
13 import std.datetime : Clock, dur;
14 import std.format : format;
15 
16 import arsd.dom : Element, RawSource;
17 
18 import dextool.plugin.mutate.backend.database : Database;
19 import dextool.plugin.mutate.backend.report.analyzers : TestCaseOverlapStat,
20     reportTestCaseFullOverlap;
21 import dextool.plugin.mutate.backend.report.html.constants;
22 import dextool.plugin.mutate.backend.resource;
23 import dextool.plugin.mutate.backend.report.html.tmpl : tmplBasicPage,
24     tmplDefaultTable, dashboardCss;
25 import dextool.plugin.mutate.backend.type : Mutation;
26 import dextool.plugin.mutate.config : ConfigReport;
27 import dextool.plugin.mutate.type : MutationKind;
28 
29 string makeFullOverlapTestCase(ref Database db, ref const ConfigReport conf,
30         const(MutationKind)[] humanReadableKinds, const(Mutation.Kind)[] kinds) @trusted {
31     import dextool.plugin.mutate.type : ReportSection;
32     import my.set;
33 
34     auto sections = conf.reportSection.toSet;
35 
36     auto doc = tmplBasicPage.dashboardCss;
37     doc.title(format("Full Overlap Test Cases %(%s %) %s", humanReadableKinds, Clock.currTime));
38     doc.mainBody.setAttribute("onload", "init()");
39 
40     auto s = doc.root.childElements("head")[0].addChild("script");
41     s.addChild(new RawSource(doc, jsIndex));
42 
43     toHtml(reportTestCaseFullOverlap(db, kinds), doc.mainBody);
44 
45     return doc.toPrettyString;
46 }
47 
48 private:
49 
50 void toHtml(const TestCaseOverlapStat s, Element n) {
51     import std.algorithm : sort, map, filter;
52     import std.array : array;
53     import std.conv : to;
54     import std.range : enumerate;
55 
56     if (s.total == 0)
57         return;
58 
59     auto base = n.addChild("div").addClass("base");
60     auto heading = base.addChild("h1").addClass("tbl_header");
61     heading.addChild("i").addClass("right");
62     heading.appendText(" Overlapping Test Cases");
63 
64     base.addChild("p", "These test has killed exactly the same mutants. This is an indication that they verify the same aspects. This can mean that some of them may be redundant.");
65 
66     base.addChild("p", s.sumToString);
67 
68     auto tbl_container = base.addChild("div").addClass("tbl_container");
69 
70     auto tbl = tmplDefaultTable(tbl_container, [
71             "Test Case", "Count", "Mutation IDs"
72             ]);
73 
74     foreach (tcs; s.tc_mut.byKeyValue.filter!(a => a.value.length > 1).enumerate) {
75         bool first = true;
76         string cls = () {
77             if (tcs.index % 2 == 0)
78                 return Table.rowStyle;
79             return Table.rowDarkStyle;
80         }();
81 
82         // TODO this is a bit slow. use a DB row iterator instead.
83         foreach (name; tcs.value.value.map!(id => s.name_tc[id].idup).array.sort) {
84             auto r = tbl.appendRow();
85             if (first) {
86                 r.addChild("td", name).addClass(cls);
87                 r.addChild("td", s.mutid_mut[tcs.value.key].length.to!string).addClass(cls);
88                 r.addChild("td", format("%(%s %)", s.mutid_mut[tcs.value.key])).addClass(cls);
89             } else {
90                 r.addChild("td", name).addClass(cls);
91             }
92             first = false;
93         }
94     }
95 }