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_stats; 11 12 import logger = std.experimental.logger; 13 import std.datetime : Clock, dur; 14 import std.format : format; 15 16 import arsd.dom : Element, Link, Document; 17 import my.path : AbsolutePath; 18 19 import dextool.plugin.mutate.backend.database : Database; 20 import dextool.plugin.mutate.backend.report.analyzers : MutationStat, 21 reportStatistics, reportSyncStatus, SyncStatus; 22 import dextool.plugin.mutate.backend.report.html.constants; 23 import dextool.plugin.mutate.backend.report.html.tmpl : tmplDefaultTable, 24 PieGraph, TimeScalePointGraph; 25 import dextool.plugin.mutate.backend.type : Mutation; 26 import dextool.plugin.mutate.backend.report.html.utility; 27 28 void makeStats(ref Database db, string tag, Document doc, Element root, 29 const AbsolutePath workListFname) @trusted { 30 import dextool.plugin.mutate.backend.report.html.page_worklist; 31 32 DashboardCss.h2(root.addChild(new Link(tag, null)).setAttribute("id", tag[1 .. $]), "Overview"); 33 overallStat(reportStatistics(db), root.addChild("div")); 34 makeWorklistPage(db, root, workListFname); 35 syncStatus(reportSyncStatus(db, 100), root); 36 } 37 38 private: 39 40 // TODO: this function contains duplicated logic from the one in ../utility.d 41 void overallStat(const MutationStat s, Element base) { 42 import std.conv : to; 43 import std.typecons : tuple; 44 45 base.addChild("p").appendHtml(format("Mutation Score <b>%.3s</b>", s.score)); 46 auto time = base.addChild("div", "Time spent"); 47 generatePopupHelp(time, format("%s", s.totalTime)); 48 49 if (s.untested > 0 && s.predictedDone > 0.dur!"msecs") { 50 const pred = Clock.currTime + s.predictedDone; 51 base.addChild("p", format("Remaining: %s (%s)", s.predictedDone, pred.toISOExtString)); 52 } 53 54 PieGraph("score", [ 55 PieGraph.Item("alive", "red", s.alive - s.aliveNoMut), 56 PieGraph.Item("killed", "green", s.killed), 57 PieGraph.Item("Untested", "grey", s.untested), 58 PieGraph.Item("Timeout", "lightgreen", s.timeout) 59 ]).html(base, PieGraph.Width(50)); 60 61 auto tbl = tmplDefaultTable(base, ["Type", "Value"]); 62 63 foreach (const d; [ 64 tuple("Total", s.total), 65 tuple("Killed by compiler", cast(long) s.killedByCompiler), 66 tuple("Skipped", s.skipped), tuple("Equivalent", s.equivalent), 67 ]) { 68 tbl.appendRow(d[0], d[1]); 69 } 70 { 71 auto wlRow = tbl.appendRow; 72 auto wltd = wlRow.addChild("td"); 73 wltd.addChild("a", "Worklist").setAttribute("href", "worklist.html"); 74 generatePopupHelp(wltd, 75 "Worklist is the number of mutants that are in the same queue to be tested/retested"); 76 wltd.addChild("td", s.worklist.to!string); 77 } 78 79 if (s.aliveNoMut != 0) { 80 auto nmRow = tbl.appendRow; 81 auto nmtd = nmRow.addChild("td", "NoMut"); 82 generatePopupHelp(nmtd, "NoMut is the number of mutants that are alive but ignored. 83 They are suppressed. 84 This result in those mutants increasing the mutation score."); 85 nmtd.addChild("td", s.aliveNoMut.to!string); 86 87 auto nmtotalRow = tbl.appendRow; 88 auto nmtotaltd = nmtotalRow.addChild("td", "NoMut/total"); 89 generatePopupHelp(nmtotaltd, 90 "NoMut/total (Supressed/total) is how much the result has increased. 91 You should react if it is high."); 92 nmtotaltd.addChild("td", format("%.3s", s.suppressedOfTotal)); 93 } 94 } 95 96 void syncStatus(SyncStatus status, Element root) { 97 auto ts = TimeScalePointGraph("SyncStatus"); 98 99 ts.put("Test", TimeScalePointGraph.Point(status.test, 1.6)); 100 ts.setColor("Test", "lightBlue"); 101 102 ts.put("Code", TimeScalePointGraph.Point(status.code, 1.4)); 103 ts.setColor("Code", "lightGreen"); 104 105 ts.put("Coverage", TimeScalePointGraph.Point(status.coverage, 1.2)); 106 ts.setColor("Coverage", "purple"); 107 108 if (status.mutants.length != 0) { 109 double y = 0.8; 110 foreach (v; status.mutants) { 111 ts.put("Mutant", TimeScalePointGraph.Point(v.updated, y)); 112 y += 0.3 / status.mutants.length; 113 } 114 ts.setColor("Mutant", "red"); 115 } 116 ts.html(root, TimeScalePointGraph.Width(50)); 117 118 auto info = root.addChild("div", "Sync Status"); 119 generatePopupHelp(info, "Sync Status is how old the information about mutants and their status is compared to when the tests or source code where last changed."); 120 121 }