/*
* (C) Copyright 2015 Kurento (http://kurento.org/)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.kurento.test.config;
import static org.kurento.commons.PropertiesManager.getProperty;
import static org.kurento.test.config.TestConfiguration.TEST_REPORT_DEFAULT;
import static org.kurento.test.config.TestConfiguration.TEST_REPORT_PROPERTY;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import org.kurento.commons.exception.KurentoException;
import org.kurento.test.browser.Browser;
import org.kurento.test.docker.Docker;
/**
* Test report, to compile information of the test result in a HTML page.
*
* @author Boni Garcia (bgarcia@gsyc.es)
* @since 6.0.0
*/
public class TestReport {
private static TestReport singleton;
protected String testReport = getProperty(TEST_REPORT_PROPERTY, TEST_REPORT_DEFAULT);
protected static final String RETURN = "\r\n";
protected static final int WIDTH_PERCENTAGE = 95;
protected PrintWriter writer;
protected String extraInfoHtml;
protected String extraErrorHtml;
protected int numRetries;
public static TestReport getSingleton(String name, int numRetries) {
if (singleton == null) {
synchronized (Docker.class) {
if (singleton == null) {
singleton = new TestReport(name, numRetries, null);
}
}
}
return singleton;
}
public static TestReport getSingleton(String name, int numRetries, String htmlHeader) {
if (singleton == null) {
synchronized (Docker.class) {
if (singleton == null) {
singleton = new TestReport(name, numRetries, htmlHeader);
}
}
}
return singleton;
}
public TestReport(String name, int numRetries, String htmlHeader) {
try {
this.numRetries = numRetries;
this.extraInfoHtml = "";
this.extraErrorHtml = "";
String title = name == null ? "Tests report [" + new Date() + "]" : name;
File file = new File(testReport);
boolean exists = file.exists();
writer = new PrintWriter(new BufferedWriter(new FileWriter(file, true)));
if (!exists) {
initPage();
if (htmlHeader != null) {
appendHtml(htmlHeader);
}
}
appendTitle(title);
writer.flush();
} catch (IOException e) {
throw new KurentoException(e);
}
}
public void initPage() {
String kurentoLogoPng = "http://files.kurento.org/img/kurento.png";
appendHtml("<link rel='shortcut icon' href='" + kurentoLogoPng + "' type='image/png' />");
appendHtml(
"<script src='https://cdn.rawgit.com/eligrey/FileSaver.js/master/FileSaver.js'></script>");
appendHtml("<script src='https://code.jquery.com/jquery-1.11.3.min.js'></script>");
appendHtml("<script>");
appendHtml("window.onload = function() {");
appendHtml("var allTextPage = $('body').text();");
appendHtml("var ok = (allTextPage.match(/Test ok/g) || []).length;");
appendHtml("var retries = (allTextPage.match(/Test failed in retry/g) || []).length;");
appendHtml("var errors = (allTextPage.match(/TEST ERROR/g) || []).length;");
appendHtml("var summary = document.getElementById('summary');");
appendHtml("var executions = ok + retries;");
appendHtml("var tests = ok + errors;");
appendHtml("var retriesOk = retries - errors*" + numRetries + ";");
appendHtml("summary.innerHTML += \"<p style='color:black;font-weight:bold;'>"
+ "Number of test(s): \" + tests + \"</p>\";");
appendHtml("if (tests != executions) summary.innerHTML += \"Number of test(s) executions:"
+ " \" + executions + \"</p>\";");
appendHtml("if (ok > 0) summary.innerHTML += \"<p style='color:green;font-weight:bold;'>"
+ "Number of test(s) ok: \" + ok + \"</p>\";");
appendHtml(
"if (retriesOk > 0) summary.innerHTML += \"<p style='color:orange;font-weight:bold;'>"
+ "Number of test(s) retried and succeeded: \" + retriesOk + \"</p>\";");
appendHtml("if (errors > 0) summary.innerHTML += \"<p style='color:red;font-weight:bold;'>"
+ "Number of test(s) with error (after " + numRetries
+ " retries): \" + errors + \"</p>\";");
appendHtml("}");
appendHtml("</script>");
appendHtml("<body>");
appendHtml("<div style='width:" + WIDTH_PERCENTAGE
+ "%; border: 1px solid grey;' id='summary'><h1><img src='" + kurentoLogoPng
+ "' style='vertical-align:middle'>Kurento Test Framework Report</h1><hr></div>");
}
public void appendTitle(String text) {
writer.println("<h1>" + escapeHtml(text) + "</h1>");
writer.flush();
}
public void appendHeader(String text) {
writer.println("<h2>" + escapeHtml(text) + "</h2>");
writer.flush();
}
public void carriageReturn() {
writer.println("<br>");
writer.flush();
}
public void appendLine() {
writer.println("<hr style='margin-left:0; width:" + WIDTH_PERCENTAGE + "%;'>");
writer.flush();
}
public String getCode(String text) {
String code = "<button type='button' onclick=\"saveAs(new Blob([$(this).next().val()], "
+ "{type: 'text/plain;charset=utf-8'}), ($(this).prev().text() ? "
+ "$(this).prev().text() : $(this).prev().prev().text()) + '.log');\">Save</button>";
code += "<textarea readonly style='width:" + WIDTH_PERCENTAGE + "%; height:150px;' wrap='off'>";
code += text;
code += "</textarea><br><br>";
return code;
}
public void appendCode(String text) {
writer.println(getCode(text));
writer.flush();
}
public void appendCode(Object[] text) {
String allText = "";
for (Object o : text) {
allText += o.toString() + RETURN;
}
appendCode(allText);
}
public void appendText(Object[] text) {
for (Object o : text) {
writer.println(escapeHtml(o.toString()) + "<br>");
}
writer.flush();
}
public void appendText(String text) {
writer.println(escapeHtml(text));
writer.flush();
}
public void appendSuccess(String text) {
writer.println("<p style='color:green;font-weight:bold;'>" + escapeHtml(text) + "</p>");
writer.flush();
}
public void appendWarning(String text) {
writer.println("<p style='color:orange;font-weight:bold;'>" + escapeHtml(text) + "</p>");
writer.flush();
}
public void appendError(String text) {
writer.println("<p style='color:red;font-weight:bold;'>" + escapeHtml(text) + "</p>");
writer.flush();
}
public void appendHtml(String html) {
writer.println(html);
writer.flush();
}
public void appendTrace(String text) {
writer.println("<pre style='width:" + WIDTH_PERCENTAGE + "%'>" + text + "</pre>");
writer.flush();
}
public String escapeHtml(String text) {
StringBuilder builder = new StringBuilder();
boolean previousWasASpace = false;
for (char c : text.toCharArray()) {
if (c == ' ') {
if (previousWasASpace) {
builder.append(" ");
previousWasASpace = false;
continue;
}
previousWasASpace = true;
} else {
previousWasASpace = false;
}
switch (c) {
case '<':
builder.append("<");
break;
case '>':
builder.append(">");
break;
case '&':
builder.append("&");
break;
case '"':
builder.append(""");
break;
case '\n':
builder.append("<br>");
break;
case '\t':
builder.append(" ");
break;
default:
if (c < 128) {
builder.append(c);
} else {
builder.append("").append((int) c).append(";");
}
}
}
return builder.toString();
}
public void appendException(Throwable throwable, TestScenario testScenario) {
appendHtml("<b>Error description</b>");
appendCode(throwable.getClass().getName() + " : " + throwable.getMessage());
appendHtml("<b>Error trace</b>");
appendCode(throwable.getStackTrace());
boolean saucelabsTitle = false;
if (testScenario != null) {
for (Browser bc : testScenario.getBrowserMap().values()) {
if (bc.getScope() == BrowserScope.SAUCELABS) {
if (!saucelabsTitle) {
appendHtml("<b>Saucelabs job(s)</b><br>");
saucelabsTitle = true;
}
String jobId = bc.getJobId();
appendHtml(
"<a href='https://saucelabs.com/tests/" + jobId + "'>" + bc.getId() + "</a><br>");
}
}
if (saucelabsTitle) {
carriageReturn();
}
}
}
public void addExtraInfoText(String text) {
extraInfoHtml += escapeHtml(text);
}
public void addExtraInfoHtml(String html) {
extraInfoHtml += html;
}
public void addExtraErrorText(String text) {
extraErrorHtml += escapeHtml(text);
}
public void addExtraErrorHtml(String html) {
extraErrorHtml += html;
}
public void flushExtraInfoHtml() {
if (!extraInfoHtml.isEmpty()) {
appendHtml(extraInfoHtml);
extraInfoHtml = "";
}
}
public void flushExtraErrorHtml() {
if (!extraErrorHtml.isEmpty()) {
appendHtml(extraErrorHtml);
extraErrorHtml = "";
}
}
}