Skip to content

Commit

Permalink
Extract overall stats table (#62)
Browse files Browse the repository at this point in the history
* Extract overall stats table to seperate class

* cleanup; disclaimer blocks

* tests for OverallStatsTable

* disclaimers

* test cleanup
  • Loading branch information
darkspirit510 authored Mar 25, 2024
1 parent faf3915 commit 3a7ea1a
Show file tree
Hide file tree
Showing 13 changed files with 980 additions and 78 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
import org.owasp.benchmarkutils.score.report.ScatterHome;
import org.owasp.benchmarkutils.score.report.ScatterInterpretation;
import org.owasp.benchmarkutils.score.report.ScatterVulns;
import org.owasp.benchmarkutils.score.report.html.OverallStatsTable;
import org.xml.sax.SAXException;

@Mojo(name = "create-scorecard", requiresProject = false, defaultPhase = LifecyclePhase.COMPILE)
Expand Down Expand Up @@ -490,17 +491,19 @@ public static void main(String[] args) {
ScatterHome.generateComparisonChart(tools, config.focus, scoreCardDir);

// Step 10: Generate the results table across all the tools in this test
String table = generateOverallStatsTable(tools);

try {
String html = new String(Files.readAllBytes(homeFilePath));
html = html.replace("${projectlink}", BenchmarkScore.PROJECTLINKENTRY);
html = html.replace("${table}", table);
html = html.replace("${tprlabel}", config.tprLabel);
html =
html.replace(
"${precisionkey}",
BenchmarkScore.PRECISIONKEYENTRY + BenchmarkScore.FSCOREKEYENTRY);
OverallStatsTable overallStatsTable = new OverallStatsTable(config, TESTSUITE);

String html =
new String(Files.readAllBytes(homeFilePath))
.replace("${projectlink}", BenchmarkScore.PROJECTLINKENTRY)
.replace("${table}", overallStatsTable.generateFor(tools))
.replace("${tprlabel}", config.tprLabel)
.replace(
"${precisionkey}",
BenchmarkScore.PRECISIONKEYENTRY
+ BenchmarkScore.FSCOREKEYENTRY);

Files.write(homeFilePath, html.getBytes());
} catch (IOException e) {
System.out.println("Error updating results table in: " + homeFilePath.getFileName());
Expand Down Expand Up @@ -1297,70 +1300,6 @@ else if (r.truePositiveRate > .7 && r.falsePositiveRate < .3)
return sb.toString();
}

/**
* Generate the overall stats table across all the tools for the bottom of the home page.
*
* @param tools - The set of all tools being scored. Each Tool includes it's scored results.
* @return The HTML of the overall stats table.
*/
private static String generateOverallStatsTable(Set<Tool> tools) {
StringBuilder sb = new StringBuilder();
sb.append("<table class=\"table\">\n");
sb.append("<tr>");
sb.append("<th>Tool</th>");
if (config.mixedMode) sb.append("<th>" + TESTSUITE + " Version</th>");
sb.append("<th>Type</th>");
if (config.includePrecision) sb.append("<th>Precision*</th><th>F-score*</th>");
sb.append("<th>${tprlabel}*</th>");
sb.append("<th>FPR*</th>");
sb.append("<th>Score*</th>");
sb.append("</tr>\n");

for (Tool tool : tools) {

if (!(config.showAveOnlyMode && tool.isCommercial())) {
ToolResults or = tool.getOverallResults();
String style = "";

if (Math.abs(or.getTruePositiveRate() - or.getFalsePositiveRate()) < .1)
style = "class=\"danger\"";
else if (or.getTruePositiveRate() > .7 && or.getFalsePositiveRate() < .3)
style = "class=\"success\"";
sb.append("<tr " + style + ">");
sb.append("<td>" + tool.getToolNameAndVersion() + "</td>");
if (config.mixedMode) sb.append("<td>" + tool.getTestSuiteVersion() + "</td>");
sb.append("<td>" + tool.getToolType() + "</td>");
if (config.includePrecision) {
sb.append(
"<td>"
+ new DecimalFormat("#0.00%").format(or.getPrecision())
+ "</td>");
sb.append(
"<td>" + new DecimalFormat("#0.0000").format(or.getFScore()) + "</td>");
}
sb.append(
"<td>"
+ new DecimalFormat("#0.00%").format(or.getTruePositiveRate())
+ "</td>");
sb.append(
"<td>"
+ new DecimalFormat("#0.00%").format(or.getFalsePositiveRate())
+ "</td>");
sb.append(
"<td>"
+ new DecimalFormat("#0.00%").format(or.getOverallScore())
+ "</td>");
sb.append("</tr>\n");
}
}

sb.append("</table>");
sb.append(
"<p>*-Please refer to each tool's scorecard for the data used to calculate these values.");

return sb.toString();
}

/**
* Updates the menus of all the scorecards previously generated so people can navigate between
* all the tool results. Also perform a few other tag replacements for things that need to be
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.util.Map;
import org.owasp.benchmarkutils.score.TestSuiteResults.ToolType;
Expand Down Expand Up @@ -53,8 +52,7 @@ public Tool(
Map<String, TP_FN_TN_FP_Counts> scores,
ToolResults toolResults,
String actualCSVResultsFileName,
boolean isCommercial)
throws IOException, URISyntaxException {
boolean isCommercial) {

this.isCommercial = isCommercial;
this.toolType = actualResults.toolType;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* OWASP Benchmark Project
*
* <p>This file is part of the Open Web Application Security Project (OWASP) Benchmark Project For
* details, please see <a
* href="https://owasp.org/www-project-benchmark/">https://owasp.org/www-project-benchmark/</a>.
*
* <p>The OWASP Benchmark is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Foundation, version 2.
*
* <p>The OWASP Benchmark is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* @author Sascha Knoop
* @created 2024
*/
package org.owasp.benchmarkutils.score.report;

import java.text.DecimalFormat;

public class Formats {

public static final DecimalFormat twoDecimalPlacesPercentage = new DecimalFormat("#0.00%");
public static final DecimalFormat fourDecimalPlacesNumber = new DecimalFormat("#0.0000");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/**
* OWASP Benchmark Project
*
* <p>This file is part of the Open Web Application Security Project (OWASP) Benchmark Project For
* details, please see <a
* href="https://owasp.org/www-project-benchmark/">https://owasp.org/www-project-benchmark/</a>.
*
* <p>The OWASP Benchmark is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Foundation, version 2.
*
* <p>The OWASP Benchmark is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* @author Sascha Knoop
* @created 2024
*/
package org.owasp.benchmarkutils.score.report.html;

public class HtmlStringBuilder {

private final StringBuilder sb = new StringBuilder();

public HtmlStringBuilder beginTable() {
sb.append("<table>");

return this;
}

public HtmlStringBuilder beginTable(String cssClass) {
if (cssClass == null) {
return beginTable();
}

sb.append("<table class=\"").append(cssClass).append("\">");

return this;
}

public HtmlStringBuilder beginTr() {
sb.append("<tr>");

return this;
}

public HtmlStringBuilder beginTr(String cssClass) {
if (cssClass == null) {
return beginTr();
}

sb.append("<tr class=\"").append(cssClass).append("\">");

return this;
}

public HtmlStringBuilder th(String content) {
sb.append("<th>").append(content).append("</th>");

return this;
}

public HtmlStringBuilder th(String content, String cssClass) {
if (cssClass == null) {
return th(content);
}

sb.append("<th class=\"").append(cssClass).append("\">").append(content).append("</th>");

return this;
}

public HtmlStringBuilder endTr() {
sb.append("</tr>");

return this;
}

public HtmlStringBuilder td(String content) {
sb.append("<td>").append(content).append("</td>");

return this;
}

public HtmlStringBuilder td(String content, String cssClass) {
if (cssClass == null) {
return td(content);
}

sb.append("<td class=\"").append(cssClass).append("\">").append(content).append("</td>");

return this;
}

public HtmlStringBuilder endTable() {
sb.append("</table>");

return this;
}

@Override
public String toString() {
return sb.toString();
}

public HtmlStringBuilder p(String content) {
sb.append("<p>").append(content).append("</p>");

return this;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/**
* OWASP Benchmark Project
*
* <p>This file is part of the Open Web Application Security Project (OWASP) Benchmark Project For
* details, please see <a
* href="https://owasp.org/www-project-benchmark/">https://owasp.org/www-project-benchmark/</a>.
*
* <p>The OWASP Benchmark is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Foundation, version 2.
*
* <p>The OWASP Benchmark is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* @author Sascha Knoop
* @created 2024
*/
package org.owasp.benchmarkutils.score.report.html;

import static org.owasp.benchmarkutils.score.report.Formats.fourDecimalPlacesNumber;
import static org.owasp.benchmarkutils.score.report.Formats.twoDecimalPlacesPercentage;

import java.util.Set;
import org.owasp.benchmarkutils.score.Configuration;
import org.owasp.benchmarkutils.score.Tool;
import org.owasp.benchmarkutils.score.ToolResults;

public class OverallStatsTable {

private final Configuration config;
private final String testSuite;

public OverallStatsTable(Configuration config, String testSuite) {
this.config = config;
this.testSuite = testSuite;
}

/**
* Generate the overall stats table across all the tools for the bottom of the home page.
*
* @param tools - The set of all tools being scored. Each Tool includes it's scored results.
* @return The HTML of the overall stats table.
*/
public String generateFor(Set<Tool> tools) {
HtmlStringBuilder htmlBuilder = new HtmlStringBuilder();

htmlBuilder.beginTable("table");

addHeaderTo(htmlBuilder);

tools.stream()
.filter(tool -> !(config.showAveOnlyMode && tool.isCommercial()))
.forEach(tool -> appendRowTo(htmlBuilder, tool));

htmlBuilder.endTable();

htmlBuilder.p(
"*-Please refer to each tool's scorecard for the data used to calculate these values.");

return htmlBuilder.toString();
}

private void addHeaderTo(HtmlStringBuilder htmlBuilder) {
htmlBuilder.beginTr();
htmlBuilder.th("Tool");

if (config.mixedMode) {
htmlBuilder.th(testSuite + " Version");
}

htmlBuilder.th("Type");

if (config.includePrecision) {
htmlBuilder.th("Precision*");
htmlBuilder.th("F-score*");
}

htmlBuilder.th("${tprlabel}*");
htmlBuilder.th("FPR*");
htmlBuilder.th("Score*");

htmlBuilder.endTr();
}

private void appendRowTo(HtmlStringBuilder htmlBuilder, Tool tool) {
ToolResults results = tool.getOverallResults();

htmlBuilder.beginTr(cssClassFor(results));
htmlBuilder.td(tool.getToolNameAndVersion());

if (config.mixedMode) {
htmlBuilder.td(tool.getTestSuiteVersion());
}

htmlBuilder.td(tool.getToolType().name());

if (config.includePrecision) {
htmlBuilder
.td(twoDecimalPlacesPercentage.format(results.getPrecision()))
.td(fourDecimalPlacesNumber.format(results.getFScore()));
}

htmlBuilder
.td(twoDecimalPlacesPercentage.format(results.getTruePositiveRate()))
.td(twoDecimalPlacesPercentage.format(results.getFalsePositiveRate()))
.td(twoDecimalPlacesPercentage.format(results.getOverallScore()))
.endTr();
}

private String cssClassFor(ToolResults results) {
String cssClass = null;

if (isDanger(results)) {
cssClass = "danger";
} else if (isSuccess(results)) {
cssClass = "success";
}

return cssClass;
}

private boolean isSuccess(ToolResults results) {
return results.getTruePositiveRate() > .7 && results.getFalsePositiveRate() < .3;
}

private boolean isDanger(ToolResults results) {
return Math.abs(results.getTruePositiveRate() - results.getFalsePositiveRate()) < .1;
}
}
Loading

0 comments on commit 3a7ea1a

Please sign in to comment.