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 }