1 /**
2 Copyright: Copyright (c) 2019, 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_unique;
11 
12 import logger = std.experimental.logger;
13 import std.format : format;
14 
15 import arsd.dom : Element, RawSource;
16 
17 import dextool.plugin.mutate.backend.database : Database;
18 import dextool.plugin.mutate.backend.report.analyzers : TestCaseUniqueness,
19     reportTestCaseUniqueness;
20 import dextool.plugin.mutate.backend.report.html.constants : htmlFileDir;
21 import dextool.plugin.mutate.backend.report.html.js : js_similarity;
22 import dextool.plugin.mutate.backend.report.html.tmpl : tmplBasicPage, tmplDefaultTable;
23 import dextool.plugin.mutate.backend.type : Mutation;
24 import dextool.plugin.mutate.config : ConfigReport;
25 import dextool.plugin.mutate.type : MutationKind;
26 
27 auto makeTestCaseUnique(ref Database db, ref const ConfigReport conf,
28         const(MutationKind)[] humanReadableKinds, const(Mutation.Kind)[] kinds) @trusted {
29     import std.datetime : Clock;
30 
31     auto doc = tmplBasicPage;
32 
33     auto s = doc.root.childElements("head")[0].addChild("script");
34     s.addChild(new RawSource(doc, js_similarity));
35 
36     doc.title(format("Test Case Uniqueness %(%s %) %s", humanReadableKinds, Clock.currTime));
37     doc.mainBody.setAttribute("onload", "init()");
38     doc.mainBody.addChild("p", "This report contains the test cases that uniquely kill mutants, which those mutants are and test cases that aren't unique.");
39 
40     toHtml(db, reportTestCaseUniqueness(db, kinds), doc.mainBody);
41 
42     return doc.toPrettyString;
43 }
44 
45 private:
46 
47 void toHtml(ref Database db, TestCaseUniqueness result, Element root) {
48     import std.algorithm : sort, map;
49     import std.array : array;
50     import std.conv : to;
51     import std.path : buildPath;
52     import cachetools : CacheLRU;
53     import dextool.cachetools;
54     import dextool.plugin.mutate.backend.database : spinSql, MutationId;
55     import dextool.plugin.mutate.backend.report.html.page_files : pathToHtmlLink;
56     import dextool.type : Path;
57 
58     auto link_cache = new CacheLRU!(MutationId, string);
59     link_cache.ttl = 30; // magic number
60     Path getPath(MutationId id) {
61         return dextool.cachetools.cacheToolsRequire(link_cache, id, {
62             auto path = spinSql!(() => db.getPath(id)).get;
63             return format!"%s#%s"(buildPath(htmlFileDir, pathToHtmlLink(path)), id);
64         }()).Path;
65     }
66 
67     with (root.addChild("button", "expand all")) {
68         setAttribute("type", "button");
69         setAttribute("id", "expand_all");
70     }
71     with (root.addChild("button", "collapse all")) {
72         setAttribute("type", "button");
73         setAttribute("id", "collapse_all");
74     }
75 
76     foreach (const k; result.uniqueKills.byKey.array.sort) {
77         // Containers allows for hiding a table by clicking the corresponding header.
78         // Defaults to hiding tables.
79         auto comp_container = root.addChild("div").addClass("comp_container");
80         auto heading = comp_container.addChild("h2").addClass("tbl_header");
81         heading.addChild("i").addClass("right");
82         heading.appendText(" ");
83         heading.appendText(k.name);
84         auto tbl_container = comp_container.addChild("div").addClass("tbl_container");
85         tbl_container.setAttribute("style", "display: none;");
86         auto tbl = tmplDefaultTable(tbl_container, ["Mutation ID"]);
87 
88         auto r = tbl.appendRow();
89         auto mut_ids = r.addChild("td");
90         foreach (const m; result.uniqueKills[k].sort) {
91             auto link = mut_ids.addChild("a", m.to!string);
92             link.href = getPath(m);
93             mut_ids.appendText(" ");
94         }
95     }
96 
97     {
98         root.addChild("p", "These are test cases that have no unique kills");
99         auto tbl = tmplDefaultTable(root, ["Test Case"]);
100         foreach (const tc; result.noUniqueKills.sort) {
101             auto r = tbl.appendRow;
102             r.addChild("td", tc.name);
103         }
104     }
105 }