Bug 256349 rerun 3.5M3 with performance tests
diff --git a/bundles/org.eclipse.test.performance.ui/doc/help.html b/bundles/org.eclipse.test.performance.ui/doc/help.html new file mode 100644 index 0000000..03eefba --- /dev/null +++ b/bundles/org.eclipse.test.performance.ui/doc/help.html
@@ -0,0 +1,102 @@ +<html><head><meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> +<style type="text/css">p, table, td, th { font-family: arial, helvetica, geneva; font-size: 10pt} +pre { font-family: "Courier New", Courier, mono; font-size: 10pt} +h2 { font-family: arial, helvetica, geneva; font-size: 18pt; font-weight: bold ; line-height: 14px} +code { font-family: "Courier New", Courier, mono; font-size: 10pt} +sup { font-family: arial,helvetica,geneva; font-size: 10px} +h3 { font-family: arial, helvetica, geneva; font-size: 14pt; font-weight: bold} +li { font-family: arial, helvetica, geneva; font-size: 10pt} +h1 { font-family: arial, helvetica, geneva; font-size: 28px; font-weight: bold} +body { font-family: arial, helvetica, geneva; font-size: 10pt; clip: rect( ); margin-top: 5mm; margin-left: 3mm} +.indextop { font-size: x-large;; font-family: Verdana, Arial, Helvetica, sans-serif; font-weight: bold} +.indexsub { font-size: xx-small;; font-family: Arial, Helvetica, sans-serif; color: #8080FF} +</style> +<body> +<p> +Since 3.5, it's possible to see results in fingerprints with three different +kinds of scale: +<ul> +<li><a href="#percent">Percentage scale</a></li> +<li><a href="#time">Time linear scale</a></li> +<li><a href="#time">Time logarithmic scale</a></li> +<li><a href="#tips">Tips for time scales</a></li> +</ul> +</p> +<h1><a name="percent">Percentage scale</h1> +<p>The X axis represents percentage of the variation vs. the given baseline</p> +<p>This is the way fingerprints were displayed since the beginning: +<p><img src="images/percentage.png"> +<ul> +<li>Red bar means a regression, even if it's less than the 10% threshold.</li> +<li>Green bar means an improvement</li> +<li>Gray bar means an 'explained' regression.</li> +</ul> +</p> +<h1><a name="time">Linear and logarithmic time scales</h1> +<p>For these scales, the X axis represents the duration time of the test.<br> +The colors meanings are the same than for the percentage scale.<br> +These kind of graphs give a better idea of time duration for each test.</p> +<p>Typically use linear scale if you want to see the tests relativeness for all the component tests:</p> +<p><img src="images/linear.png"> +<p>But the logarithmic scale is more appropriate when there are a strong duration differences between tests, hence makes short duration tests easier to survey:</p> +<p><img src="images/log.png"> +<p>Each test have two bars: the former is white and shows the baseline result, the latter is colored (red, green or gray) and shows the current build result.<br> +The variation between the baseline and the build is displayed as a percentage on top of both bars.</p> +<h1><a name="tips">Tips for time scales</h1> +<p>Tips are almost the same for linear and logarithmic scales:</p> +<table border="0"> + <tr> + <td valign="top"><img src="images/light.gif"></td> + <td><b>Flying over a bar displays its time value<b>:</td></tr> + </tr> + <tr> + <td></td> + <td><img src="images/help_time_baseline.png"></td> + </tr> + <tr> + <td></td> + <td><img src="images/help_time_current.png"></td> + </tr> + <tr><td><br></td></tr> + <tr> + <td valign="top"><img src="images/light.gif"></td> + <td><b>For <u>linear scale only</u>, when the error on the time result is noticeable, + then the measurement uncertainty is shown in yellow at the end of the bar<b>:</td></tr> + </tr> + <tr> + <td></td> + <td><img src="images/help_time_error.png"></td> + </tr> + <tr><td><br></td></tr> + <tr> + <td valign="top"><img src="images/light.gif"></td> + <td><b>A performance regression may sometimes have a known good reason</b>.<br> + In this case, the current build bar is grayed and flying over it also shows the given explanation:</td></tr> + </tr> + <tr> + <td></td> + <td><img src="images/help_explained_regression.png"></td> + </tr> + <tr><td><br></td></tr> + <tr> + <td valign="top"><img src="images/light.gif"></td> + <td><b>Test result may have big error which can make the test result not fully reliable</b>.<br> + In this case, a warning icon is shown after the variation value and flying over it gives the offending error value:</td></tr> + </tr> + <tr> + <td></td> + <td><img src="images/help_error_warning.png"></td> + </tr> + <tr><td><br></td></tr> + <tr> + <td valign="top"><img src="images/light.gif"></td> + <td><b>Test may have no result for the used baseline, hence the first available build is used as a reference</b>.<br> + In this case, a warning icon is shown after the scenario title and flying over it gives the build ID used to compute the variation:</td></tr> + </tr> + <tr> + <td></td> + <td><img src="images/help_no_baseline.png"></td> + </tr> +</table> +</body> +</html>
diff --git a/bundles/org.eclipse.test.performance.ui/doc/images/help_error_warning.png b/bundles/org.eclipse.test.performance.ui/doc/images/help_error_warning.png new file mode 100644 index 0000000..399acaf --- /dev/null +++ b/bundles/org.eclipse.test.performance.ui/doc/images/help_error_warning.png Binary files differ
diff --git a/bundles/org.eclipse.test.performance.ui/doc/images/help_explained_regression.png b/bundles/org.eclipse.test.performance.ui/doc/images/help_explained_regression.png new file mode 100644 index 0000000..a7b7c84 --- /dev/null +++ b/bundles/org.eclipse.test.performance.ui/doc/images/help_explained_regression.png Binary files differ
diff --git a/bundles/org.eclipse.test.performance.ui/doc/images/help_no_baseline.png b/bundles/org.eclipse.test.performance.ui/doc/images/help_no_baseline.png new file mode 100644 index 0000000..f06762e --- /dev/null +++ b/bundles/org.eclipse.test.performance.ui/doc/images/help_no_baseline.png Binary files differ
diff --git a/bundles/org.eclipse.test.performance.ui/doc/images/help_time_baseline.png b/bundles/org.eclipse.test.performance.ui/doc/images/help_time_baseline.png new file mode 100644 index 0000000..594fdf2 --- /dev/null +++ b/bundles/org.eclipse.test.performance.ui/doc/images/help_time_baseline.png Binary files differ
diff --git a/bundles/org.eclipse.test.performance.ui/doc/images/help_time_current.png b/bundles/org.eclipse.test.performance.ui/doc/images/help_time_current.png new file mode 100644 index 0000000..5e913cb --- /dev/null +++ b/bundles/org.eclipse.test.performance.ui/doc/images/help_time_current.png Binary files differ
diff --git a/bundles/org.eclipse.test.performance.ui/doc/images/help_time_error.png b/bundles/org.eclipse.test.performance.ui/doc/images/help_time_error.png new file mode 100644 index 0000000..2ce272d --- /dev/null +++ b/bundles/org.eclipse.test.performance.ui/doc/images/help_time_error.png Binary files differ
diff --git a/bundles/org.eclipse.test.performance.ui/doc/images/light.gif b/bundles/org.eclipse.test.performance.ui/doc/images/light.gif new file mode 100644 index 0000000..11af180 --- /dev/null +++ b/bundles/org.eclipse.test.performance.ui/doc/images/light.gif Binary files differ
diff --git a/bundles/org.eclipse.test.performance.ui/doc/images/linear.png b/bundles/org.eclipse.test.performance.ui/doc/images/linear.png new file mode 100644 index 0000000..cd276a9 --- /dev/null +++ b/bundles/org.eclipse.test.performance.ui/doc/images/linear.png Binary files differ
diff --git a/bundles/org.eclipse.test.performance.ui/doc/images/log.png b/bundles/org.eclipse.test.performance.ui/doc/images/log.png new file mode 100644 index 0000000..7f2e84a --- /dev/null +++ b/bundles/org.eclipse.test.performance.ui/doc/images/log.png Binary files differ
diff --git a/bundles/org.eclipse.test.performance.ui/doc/images/percentage.png b/bundles/org.eclipse.test.performance.ui/doc/images/percentage.png new file mode 100644 index 0000000..6f965da --- /dev/null +++ b/bundles/org.eclipse.test.performance.ui/doc/images/percentage.png Binary files differ
diff --git a/bundles/org.eclipse.test.performance.ui/images/light.gif b/bundles/org.eclipse.test.performance.ui/images/light.gif new file mode 100644 index 0000000..11af180 --- /dev/null +++ b/bundles/org.eclipse.test.performance.ui/images/light.gif Binary files differ
diff --git a/bundles/org.eclipse.test.performance.ui/images/warning_obj.gif b/bundles/org.eclipse.test.performance.ui/images/warning_obj.gif new file mode 100644 index 0000000..2b2e50f --- /dev/null +++ b/bundles/org.eclipse.test.performance.ui/images/warning_obj.gif Binary files differ
diff --git a/bundles/org.eclipse.test.performance.ui/performanceui.jar b/bundles/org.eclipse.test.performance.ui/performanceui.jar index 3d0f83c..0244b35 100644 --- a/bundles/org.eclipse.test.performance.ui/performanceui.jar +++ b/bundles/org.eclipse.test.performance.ui/performanceui.jar Binary files differ
diff --git a/bundles/org.eclipse.test.performance.ui/scripts/Fingerprints.js b/bundles/org.eclipse.test.performance.ui/scripts/Fingerprints.js new file mode 100644 index 0000000..d1914e9 --- /dev/null +++ b/bundles/org.eclipse.test.performance.ui/scripts/Fingerprints.js
@@ -0,0 +1,32 @@ +function toggleFingerprints() { + var formSelect=document.forms[0].elements[0]; + var type=formSelect.selectedIndex; + var idx=document.URL.indexOf("php?"); + if (idx==-1) { + window.open(document.URL+"?fp_type="+type, "_self"); + } else { + window.open(document.URL.substring(0,idx)+"php?fp_type="+type, "_self"); + } +} + +function setFingerprintsType() { + var idx=document.URL.indexOf("?"); + var type=0; + if (idx != -1) { + var typeStr=document.URL.substring(idx+1, document.URL.length); + idx=typeStr.indexOf("="); + if (idx != -1) { + var ch=typeStr.substring(idx+1, idx+2) + switch (ch) { + case '1': + type=1; + break; + case '2': + type=2; + break; + } + } + } + var formSelect=document.forms[0].elements[0]; + formSelect.selectedIndex=type; +}
diff --git a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/BarGraph.java b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/BarGraph.java index 2dc79d0..a5cf5a1 100644 --- a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/BarGraph.java +++ b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/BarGraph.java
@@ -273,7 +273,7 @@ if (hasURL) { if (fAreaBuffer == null) fAreaBuffer= new StringBuffer(); - fAreaBuffer.append("<area shape=\"RECT\" coords=\"0," + y0 + ',' + width + ',' + y + "\" href=\"" + bar.url + "\">\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + fAreaBuffer.append(" echo '<area shape=\"RECT\" coords=\"0," + y0 + ',' + width + ',' + y + "\" href=\"" + bar.url + "\">';\n"); } }
diff --git a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/FingerPrint.java b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/FingerPrint.java index 648e7ed..2bd8243 100644 --- a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/FingerPrint.java +++ b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/FingerPrint.java
@@ -17,6 +17,7 @@ import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; +import java.util.ArrayList; import java.util.List; import org.eclipse.swt.SWT; @@ -42,7 +43,7 @@ File outputDir; public FingerPrint(String name, PrintStream ps, File outputDir) { - if (!name.equals("global")) this.component = name; + if (!name.startsWith("global")) this.component = name; this.stream = ps; this.outputDir = outputDir; } @@ -53,15 +54,9 @@ * @param performanceResults The performance results used to print the fingerprints */ public void print(PerformanceResults performanceResults) { - String baselineBuildName = performanceResults.getBaselineName(); String buildName = performanceResults.getName(); // Compute fingerprint output file name prefix - int referenceUnderscoreIndex = baselineBuildName.indexOf('_'); - String baselinePrefix = baselineBuildName; - if (referenceUnderscoreIndex != -1) { - baselinePrefix = baselineBuildName.substring(0, referenceUnderscoreIndex); - } int currentUnderscoreIndex = buildName.indexOf('_'); if (currentUnderscoreIndex != -1){ buildName = buildName.substring(0, currentUnderscoreIndex); @@ -71,11 +66,38 @@ buffer.append(this.component); buffer.append('_'); } - buffer.append(baselinePrefix); + buffer.append(AbstractResults.VERSION_REF); buffer.append('_'); buffer.append(buildName); - buffer.append('.'); String filePrefix = buffer.toString(); + + // Print the legend + this.stream.print("The following fingerprints show results for the most representative tests of the "); + if (this.component == null) { + this.stream.print("current build.<br>\n"); + } else { + this.stream.print(component); + this.stream.print(" component.<br>\n"); + } + this.stream.print("<table border=\"0\">\n"); + this.stream.print("<tr><td valign=\"top\">Select which kind of scale you want to use:</td>\n"); + this.stream.print("<td valign=\"top\">\n"); + this.stream.print(" <form>\n"); + this.stream.print(" <select onChange=\"toggleFingerprints();\">\n"); + this.stream.print(" <option>percentage</option>\n"); + this.stream.print(" <option>time (linear)</option>\n"); + this.stream.print(" <option>time (log)</option>\n"); + this.stream.print(" </select>\n"); + this.stream.print(" </form>\n"); + this.stream.print("</td>\n"); + this.stream.print("<td valign=\"top\">\n"); + this.stream.print("<a href=\"help.html\"><img hspace=\"10\" border=\"0\" src=\"light.gif\" title=\"Some tips on fingerprints\"/></a>\n"); + this.stream.print("</td></tr></table>\n"); + + // Print script to reset dropdown list selection + this.stream.print("<script type=\"text/javascript\">\n"); + this.stream.print(" setFingerprintsType();\n"); + this.stream.print("</script>\n"); // Create each fingerprint and save it String[] configNames = performanceResults.getConfigNames(false/* not sorted*/); @@ -87,8 +109,9 @@ if (scenarios == null) continue; // Create BarGraph -// BarGraph barGraph = new BarGraph(null); + // TODO use FingerPrintGraph instead BarGraph barGraph = null; + List allResults = new ArrayList(); String defaultDimName = AbstractResults.DEFAULT_DIM.getName(); for (int i=0, size=scenarios.size(); i<size; i++) { ScenarioResults scenarioResults = (ScenarioResults) scenarios.get(i); @@ -112,12 +135,15 @@ configName + "/" + scenarioResults.getFileName() + ".html", configResults.getCurrentBuildResults().getComment(), (Utils.confidenceLevel(results) & Utils.ERR) == 0); + + // add results + allResults.add(configResults); } } if (barGraph == null) continue; // Save image file - String fileName = filePrefix + configName ; + String fileName = filePrefix + '.' + configName ; File outputFile = new File(this.outputDir, fileName+".gif"); save(barGraph, outputFile); @@ -128,21 +154,33 @@ if (areas == null) areas = ""; this.stream.print("<h4>"); this.stream.print(boxName); - this.stream.print("</h4>"); - this.stream.print("<img src=\""); + this.stream.print("</h4>\n"); + this.stream.print("<?php\n"); + this.stream.print(" $type=$_SERVER['QUERY_STRING'];\n"); + this.stream.print(" if ($type==\"\" || $type==\"fp_type=0\") {\n"); + this.stream.print(" echo '<img src=\""); this.stream.print(fileName); this.stream.print(".gif\" usemap=\"#"); this.stream.print(fileName); - this.stream.print("\"><map name=\""); + this.stream.print("\" name=\""); + this.stream.print(configName); + this.stream.print("\">';\n"); + this.stream.print(" echo '<map name=\""); this.stream.print(fileName); - this.stream.print("\">"); + this.stream.print("\">';\n"); this.stream.print(areas); - this.stream.print("</map>\n"); + this.stream.print(" echo '</map>';\n"); + this.stream.print(" }\n"); } else { this.stream.print("<br><br>There is no fingerprint for "); this.stream.print(boxName); this.stream.print("<br><br>\n"); } + + // Create, paint and print the time bars graph + FingerPrintGraph graph = new FingerPrintGraph(this.outputDir, fileName, GRAPH_WIDTH, allResults); + graph.paint(this.stream); + this.stream.print("?>\n"); } } @@ -159,6 +197,14 @@ barGraph.paint(display, GRAPH_WIDTH, height, gc); gc.dispose(); + saveImage(outputFile, image); +} + +/** + * @param outputFile + * @param image + */ +private void saveImage(File outputFile, Image image) { // Save image ImageData data = Utils.downSample(image); ImageLoader imageLoader = new ImageLoader();
diff --git a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/FingerPrintGraph.java b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/FingerPrintGraph.java new file mode 100644 index 0000000..87fea0b --- /dev/null +++ b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/FingerPrintGraph.java
@@ -0,0 +1,671 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.test.performance.ui; + +import java.io.File; +import java.io.PrintStream; +import java.text.NumberFormat; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.FontData; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.ImageData; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.graphics.Resource; +import org.eclipse.swt.widgets.Display; +import org.eclipse.test.internal.performance.results.AbstractResults; +import org.eclipse.test.internal.performance.results.BuildResults; +import org.eclipse.test.internal.performance.results.ConfigResults; +import org.eclipse.test.internal.performance.results.ScenarioResults; + +/** + * Abstract class to build graph with bars + */ +public class FingerPrintGraph { + + // Dimensions + static final String DEFAULT_DIM_NAME = AbstractResults.DEFAULT_DIM.getName(); + + // Sizes + static final int MARGIN= 5; // margin on all four sides + static final int BAR_HEIGHT= 6; // height of bar + static final int GAP= 10; // gap between bars + static final int TGAP= 5; // gap between lines and labels + static final int LINE_HEIGHT = 2*BAR_HEIGHT + GAP; + + // fraction of width reserved for bar graph + static final double RATIO= 0.6; + + // Formatting constants + static final NumberFormat NUMBER_FORMAT; + static { + NUMBER_FORMAT = NumberFormat.getInstance(); + NUMBER_FORMAT.setMaximumFractionDigits(1); + } + + // Graphic constants + static final Display DEFAULT_DISPLAY = Display.getDefault(); + static final Color BLACK= DEFAULT_DISPLAY.getSystemColor(SWT.COLOR_BLACK); + static final Color BLUE= DEFAULT_DISPLAY.getSystemColor(SWT.COLOR_BLUE); + static final Color GREEN= DEFAULT_DISPLAY.getSystemColor(SWT.COLOR_GREEN); + static final Color RED = DEFAULT_DISPLAY.getSystemColor(SWT.COLOR_RED); + static final Color GRAY = DEFAULT_DISPLAY.getSystemColor(SWT.COLOR_GRAY); + static final Color DARK_GRAY = DEFAULT_DISPLAY.getSystemColor(SWT.COLOR_DARK_GRAY); + static final Color YELLOW = DEFAULT_DISPLAY.getSystemColor(SWT.COLOR_YELLOW); + static final Color WHITE = DEFAULT_DISPLAY.getSystemColor(SWT.COLOR_WHITE); + + // Bar graph kinds + static final int NO_TIME = 0; // i.e. percentage + static final int TIME_LINEAR = 1; + static final int TIME_LOG = 2; + static final int[] SUPPORTED_GRAPHS = { +// NO_TIME, + TIME_LINEAR, + TIME_LOG, + }; + + // Graphic fields + GC gc; + Image image; + int imageWidth; + int imageHeight; + int graphWidth; + int graphHeight; + Map resources = new HashMap(); + + // Data fields + int count = 0; + ConfigResults[] results = new ConfigResults[10]; + BarGraphArea[] areas; + + // Values + double maxValue = 0.0; + double minValue = Double.MAX_VALUE; + + // File info + File outputDir; + String imageName; + + /* + * Member class defining a bar graph area. + * This area applies to a configuration results and is made of several zones. + */ + class BarGraphArea { + List zones; + private ConfigResults configResults; + + /* + * Member class defining a zone inside a bar graph area. + * Typically made of a rectangle and an associated text used as tooltip. + */ + class AreaZone { + Rectangle zone; + String title; + + AreaZone(Rectangle zone, String tooltip) { + super(); + this.zone = zone; + this.title = tooltip; + } + + void print(String url, PrintStream stream) { + stream.print(" echo '<area shape=\"RECT\""); + if (this.title != null) { + stream.print(" title=\""+this.title+"\""); + } + stream.print("coords=\""); + stream.print(this.zone.x); + stream.print(','); + stream.print(this.zone.y); + stream.print(','); + stream.print(this.zone.x+this.zone.width); + stream.print(','); + stream.print(this.zone.y+this.zone.height); + stream.print('"'); + if (url != null) { + stream.print(" href=\""); + stream.print(url); + stream.print('"'); + } + stream.print(">';\n"); + } + } + + BarGraphArea(ConfigResults results) { + this.configResults = results; + this.zones = new ArrayList(); + } + + void print(PrintStream stream) { + String url = this.configResults.getName() + "/" + ((ScenarioResults) this.configResults.getParent()).getFileName() + ".html"; + int size = this.zones.size(); + for (int i=0; i<size; i++) { + AreaZone zone = (AreaZone) this.zones.get(i); + zone.print(url, stream); + } + } + + void addArea(Rectangle rec, String tooltip) { + AreaZone zone = new AreaZone(rec, tooltip); + this.zones.add(zone); + } + + } + + +FingerPrintGraph(File dir, String fileName, int width, List results) { + super(); + this.imageWidth = width; + this.count = results.size(); + this.results = new ConfigResults[this.count]; + results.toArray(this.results); + this.outputDir = dir; + this.imageName = fileName; +} + +/** + */ +void drawBars(int kind) { + + // Get/Set graphical resources + Font italicFont = (Font) this.resources.get("italicFont"); + if (italicFont == null) { + String fontDataName = this.gc.getFont().getFontData()[0].toString(); + FontData fdItalic = new FontData(fontDataName); + fdItalic.setStyle(SWT.ITALIC); + italicFont = new Font(DEFAULT_DISPLAY, fdItalic); + this.resources.put("italicFont", italicFont); + } + Color blueref = (Color) this.resources.get("blueref"); + if (blueref == null) { + blueref = new Color(DEFAULT_DISPLAY, 200, 200, 255); + this.resources.put("blueref", blueref); + } + Color lightyellow= (Color) this.resources.get("lightyellow"); + if (lightyellow == null) { + lightyellow = new Color(DEFAULT_DISPLAY, 255, 255, 160); + this.resources.put("lightyellow", lightyellow); + } + Color darkyellow= (Color) this.resources.get("darkyellow"); + if (darkyellow == null) { + darkyellow = new Color(DEFAULT_DISPLAY, 160, 160, 0); + this.resources.put("darkyellow", darkyellow); + } + Color lightgreen= (Color) this.resources.get("lightgreen"); + if (lightgreen == null) { + lightgreen = new Color(DEFAULT_DISPLAY, 160, 255, 160); + this.resources.put("lightgreen", lightgreen); + } + Color lightred = (Color) this.resources.get("lightred"); + if (lightred == null) { + lightred = new Color(DEFAULT_DISPLAY, 255, 160, 160); + this.resources.put("lightred", lightred); + } + + // Build each scenario bar graph + this.areas = new BarGraphArea[this.count]; + double max = kind == TIME_LOG ? Math.log(this.maxValue) : this.maxValue; + for (int i=0, y=MARGIN; i < this.count; i++, y+=LINE_HEIGHT) { + + // get builds info + ConfigResults configResults = this.results[i]; + this.areas[i] = new BarGraphArea(configResults); + BarGraphArea graphArea = this.areas[i]; + BuildResults currentBuildResults = configResults.getCurrentBuildResults(); + double currentValue = currentBuildResults.getValue(); + double currentError = currentBuildResults.getError(); + double error = configResults.getError(); + boolean singleTest = Double.isNaN(error); + boolean isSignificant = singleTest || error < Utils.STANDARD_ERROR_THRESHOLD; + boolean isCommented = currentBuildResults.getComment() != null; + BuildResults baselineBuildResults = configResults.getBaselineBuildResults(); + double baselineValue = baselineBuildResults.getValue(); + double baselineError = baselineBuildResults.getError(); + + // draw baseline build bar + Color whiteref = (Color) this.resources.get("whiteref"); + if (whiteref == null) { + whiteref = new Color(DEFAULT_DISPLAY, 240, 240, 248); + this.resources.put("whiteref", whiteref); + } + this.gc.setBackground(whiteref); + double baselineGraphValue = kind == TIME_LOG ? Math.log(baselineValue) : baselineValue; + int baselineBarLength= (int) (baselineGraphValue / max * this.graphWidth); + int baselineErrorLength= (int) (baselineError / max * this.graphWidth / 2); + int labelxpos = MARGIN + baselineBarLength; + if (kind == TIME_LOG || baselineErrorLength <= 1) { + this.gc.fillRectangle(MARGIN, y + (GAP/2), baselineBarLength, BAR_HEIGHT); + Rectangle rec = new Rectangle(MARGIN, y + (GAP/2), baselineBarLength, BAR_HEIGHT); + this.gc.drawRectangle(rec); + graphArea.addArea(rec, "Time for baseline build "+baselineBuildResults.getName()+": "+AbstractResults.timeString((long)baselineValue)); + } else { + int wr = baselineBarLength - baselineErrorLength; + Rectangle recValue = new Rectangle(MARGIN, y + (GAP/2), wr, BAR_HEIGHT); + this.gc.fillRectangle(recValue); + this.gc.setBackground(YELLOW); + Rectangle recError = new Rectangle(MARGIN+wr, y + (GAP/2), baselineErrorLength*2, BAR_HEIGHT); + this.gc.fillRectangle(recError); + Rectangle rec = new Rectangle(MARGIN, y + (GAP/2), baselineBarLength+baselineErrorLength, BAR_HEIGHT); + this.gc.drawRectangle(rec); + StringBuffer tooltip = new StringBuffer("Time for baseline build "); + tooltip.append(baselineBuildResults.getName()); + tooltip.append(": "); + tooltip.append(AbstractResults.timeString((long)baselineValue)); + tooltip.append(" [±"); + tooltip.append(AbstractResults.timeString((long)baselineError)); + tooltip.append(']'); + graphArea.addArea(rec, tooltip.toString()); + labelxpos += baselineErrorLength; + } + + // set current build bar color + if (baselineValue < currentValue) { + if (isCommented) { + this.gc.setBackground(GRAY); + } else { + this.gc.setBackground(RED); + } + } else { + this.gc.setBackground(GREEN); + } + + // draw current build bar + double currentGraphValue = kind == TIME_LOG ? Math.log(currentValue) : currentValue; + int currentBarLength= (int) (currentGraphValue / max * this.graphWidth); + int currentErrorLength= (int) (currentError / max * this.graphWidth / 2); + if (kind == TIME_LOG || currentErrorLength <= 1) { + this.gc.fillRectangle(MARGIN, y + (GAP/2) + BAR_HEIGHT, currentBarLength, BAR_HEIGHT); + Rectangle rec = new Rectangle(MARGIN, y + (GAP/2) + BAR_HEIGHT, currentBarLength, BAR_HEIGHT); + this.gc.drawRectangle(rec); + String tooltip = "Time for current build "+currentBuildResults.getName()+": "+AbstractResults.timeString((long)currentValue); + if (isCommented) { + tooltip += ". " + currentBuildResults.getComment(); + } + graphArea.addArea(rec, tooltip); + if (labelxpos < (MARGIN+currentBarLength)) { + labelxpos = MARGIN + currentBarLength; + } + } else { + int wr = currentBarLength - currentErrorLength; + Rectangle recValue = new Rectangle(MARGIN, y + (GAP/2) + BAR_HEIGHT, wr, BAR_HEIGHT); + this.gc.fillRectangle(recValue); + this.gc.setBackground(YELLOW); + Rectangle recError = new Rectangle(MARGIN+wr, y + (GAP/2) + BAR_HEIGHT, currentErrorLength*2, BAR_HEIGHT); + this.gc.fillRectangle(recError); + Rectangle rec = new Rectangle(MARGIN, y + (GAP/2) + BAR_HEIGHT, currentBarLength+currentErrorLength, BAR_HEIGHT); + this.gc.drawRectangle(rec); + StringBuffer tooltip = new StringBuffer("Time for current build "); + tooltip.append(currentBuildResults.getName()); + tooltip.append(": "); + tooltip.append(AbstractResults.timeString((long)currentValue)); + tooltip.append(" [±"); + tooltip.append(AbstractResults.timeString((long)currentError)); + tooltip.append(']'); + if (isCommented) { + tooltip.append(". "); + tooltip.append(currentBuildResults.getComment()); + } + graphArea.addArea(rec, tooltip.toString()); + if (labelxpos < (MARGIN+currentBarLength+currentErrorLength)) { + labelxpos = MARGIN + currentBarLength+currentErrorLength; + } + } + + // set delta value style and color + boolean hasFailure = currentBuildResults.getFailure() != null; + if (hasFailure) { + if (isCommented) { + this.gc.setForeground(DARK_GRAY); + } else { + this.gc.setForeground(RED); + } + } else { + this.gc.setForeground(BLACK); + } + + // draw delta value + double delta = -configResults.getDelta(); + String label = delta > 0 ? "+" : ""; + label += NUMBER_FORMAT.format(delta*100) + "%"; + Point labelExtent= this.gc.stringExtent(label); + int labelvpos= y + (LINE_HEIGHT - labelExtent.y) / 2; + this.gc.drawString(label, labelxpos+TGAP, labelvpos, true); + this.gc.setForeground(BLACK); + this.gc.setFont(null); + int titleStart = (int) (RATIO * this.imageWidth); + if (singleTest || !isSignificant) { + String deltaTooltip = null; + if (singleTest) { + deltaTooltip = "This test performed only one iteration; hence its reliability cannot be assessed"; + } else if (!isSignificant) { + deltaTooltip = "This test has a bad reliability: error is "+NUMBER_FORMAT.format(error*100)+"% (> 3%)!"; + } + Image warning = (Image) this.resources.get("warning"); + int xi = labelxpos+TGAP+labelExtent.x; + this.gc.drawImage(warning, xi, labelvpos); + ImageData imageData = warning.getImageData(); + // Set zones + // - first one is between end of bar and warning image beginning + Rectangle deltaZone = new Rectangle(labelxpos, labelvpos-2, xi-labelxpos, labelExtent.y+4); + graphArea.addArea(deltaZone, null); + // - second one is the warning image + Rectangle warningZone = new Rectangle(xi, labelvpos, imageData.width, imageData.height); + graphArea.addArea(warningZone, deltaTooltip); + // - last one is between end of the warning image and the scenario title beginning + int warningImageEnd = xi+imageData.width; + Rectangle emptyZone = new Rectangle(warningImageEnd, labelvpos, titleStart-warningImageEnd, imageData.height); + graphArea.addArea(emptyZone, deltaTooltip); + } else { + // No tooltip => delta zone is between end of bar and the scenario title beginning + Rectangle deltaZone = new Rectangle(labelxpos, labelvpos-2, titleStart-labelxpos, labelExtent.y+4); + graphArea.addArea(deltaZone, null); + } + + // set title style + Color oldfg= this.gc.getForeground(); + this.gc.setForeground(BLUE); + + // draw scenario title + int x= titleStart; + ScenarioResults scenarioResults = (ScenarioResults) configResults.getParent(); + String title = scenarioResults.getLabel() + " (" + DEFAULT_DIM_NAME + ")"; + Point e= this.gc.stringExtent(title); + this.gc.drawLine(x, labelvpos + e.y - 1, x + e.x, labelvpos + e.y - 1); + this.gc.drawString(title, x, labelvpos, true); + this.gc.setForeground(oldfg); + this.gc.setFont(null); + Rectangle titleZone = new Rectangle(x, labelvpos, e.x, e.y); + graphArea.addArea(titleZone, null/*no tooltip*/); + if (!configResults.isBaselined()) { + Image warning = (Image) this.resources.get("warning"); + this.gc.drawImage(warning, x+e.x, labelvpos); + ImageData imageData = warning.getImageData(); + Rectangle warningZone = new Rectangle(x+e.x, labelvpos, imageData.width, imageData.height); + String titleTooltip = "This test has no baseline result, hence use build "+configResults.getBaselineBuildName()+" for reference!"; + graphArea.addArea(warningZone, titleTooltip); + } + } +} + +void drawLinearScale() { + + // Draw scale background + drawScaleBackground(); + + // Draw scale grid lines + int gridValue = 100; + int n = (int) (this.maxValue / gridValue); + while (n > 10) { + switch (gridValue) { + case 100: + gridValue = 200; + break; + case 200: + gridValue = 500; + break; + case 500: + gridValue = 1000; + break; + default: + gridValue += 1000; + break; + } + n = (int) (this.maxValue / gridValue); + } + int gridWidth = (int) (this.graphWidth * gridValue / this.maxValue); + int x = MARGIN; + long value = 0; // TODO use minValue instead + while (x < this.graphWidth) { + + // draw line + this.gc.setForeground(GRAY); + if (x > 0) { + this.gc.setLineStyle(SWT.LINE_DOT); + this.gc.drawLine(x, MARGIN, x, this.graphHeight + TGAP); + } + + // draw value + this.gc.setForeground(BLACK); + String val= AbstractResults.timeString(value); + Point point= this.gc.stringExtent(val); + this.gc.drawString(val, x - point.x / 2, this.graphHeight + TGAP, true); + + // compute next grid position + x += gridWidth; + value += gridValue; // value is expressed in seconds + } + this.gc.setLineStyle(SWT.LINE_SOLID); + this.gc.drawLine(0, this.graphHeight, this.graphWidth, this.graphHeight); +} + +void drawLogarithmScale() { + + // Draw scale background + drawScaleBackground(); + + // Draw scale grid lines + double max = Math.log(this.maxValue); + int gridValue = 100; + int x = MARGIN; + long value = 0; // TODO use minValue instead + while (x < this.graphWidth) { + + // draw line + this.gc.setForeground(GRAY); + if (x > MARGIN) { + this.gc.setLineStyle(SWT.LINE_DOT); + this.gc.drawLine(x, MARGIN, x, this.graphHeight + TGAP); + } + + // draw value + this.gc.setForeground(BLACK); + String str = AbstractResults.timeString(value); + Point point= this.gc.stringExtent(str); + this.gc.drawString(str, x - point.x / 2, this.graphHeight + TGAP, true); + + // compute next grid position + value += gridValue; + int v = (int) (value / 100); + int c = 1; + while (v > 10) { + v = v / 10; + c *= 10; + } + switch (v) { + case 3: + gridValue = 200*c; + break; + case 5: + gridValue = 500*c; + break; + case 10: + gridValue = 1000*c; + break; + } + x = MARGIN + (int) (this.graphWidth * Math.log(value) / max); + } + this.gc.setLineStyle(SWT.LINE_SOLID); + this.gc.drawLine(0, this.graphHeight, this.graphWidth, this.graphHeight); +} + +/** + * Draw the scale depending on the bar time graph kind. + */ +void drawScale(int kind) { + switch (kind) { + case TIME_LINEAR: + drawLinearScale(); + break; + case TIME_LOG: + drawLogarithmScale(); + break; + } +} + +private void drawScaleBackground() { + + // Draw striped background + Color lightblue = (Color) this.resources.get("lightblue"); + if (lightblue == null) { + lightblue = new Color(DEFAULT_DISPLAY, 237, 243, 254); + this.resources.put("lightblue", lightblue); + } + this.gc.setBackground(lightblue); + for (int i= 0; i<this.count; i++) { + if (i % 2 == 0) { + this.gc.fillRectangle(0, MARGIN + i * LINE_HEIGHT, this.imageWidth, LINE_HEIGHT); + } + } + + // Draw bottom vertical line + int yy= MARGIN + this.count * LINE_HEIGHT; + this.gc.drawLine(MARGIN, MARGIN, MARGIN, yy + TGAP); +} + +String getImageName(int kind) { + switch (kind) { + case TIME_LINEAR: + return this.imageName+"_linear"; + case TIME_LOG: + return this.imageName+"_log"; + } + return this.imageName; +} + +void paint(int kind) { + + // Set image + this.graphHeight = MARGIN + this.count * LINE_HEIGHT; + this.imageHeight = this.graphHeight + GAP + 16 + MARGIN; + this.image = new Image(DEFAULT_DISPLAY, this.imageWidth, this.imageHeight); + this.gc = new GC(this.image); + + // draw white background + this.gc.setBackground(WHITE); + this.gc.fillRectangle(0, 0, this.imageWidth, this.imageHeight); + + // Set widths and heights + int width= (int) (RATIO * this.imageWidth); // width for results bar + this.graphWidth= width - this.gc.stringExtent("-999.9%").x - TGAP - MARGIN; // reserve space //$NON-NLS-1$ + + // Get warning image width + Image warning = (Image) this.resources.get("warning"); + if (warning == null) { + warning = new Image(this.gc.getDevice(), new File(this.outputDir, Utils.WARNING_OBJ).toString()); + this.resources.put("warning", warning); + } + this.graphWidth -= warning.getImageData().width; + + // Set maximum of values + for (int i= 0; i<this.count; i++) { + BuildResults baselineBuildResults = this.results[i].getBaselineBuildResults(); + double value = baselineBuildResults.getValue(); +// double error = baselineBuildResults.getError(); +// value += error; + if (value > this.maxValue) { + this.maxValue = value; + } + if (value < this.minValue) { + this.minValue = value; + } + BuildResults currentBuildResults = this.results[i].getCurrentBuildResults(); + value = currentBuildResults.getValue(); +// error = currentBuildResults.getError(); +// value += error; + if (value > this.maxValue) { + this.maxValue = value; + } + if (value < this.minValue) { + this.minValue = value; + } + } + this.minValue = 0; // do not use minValue for now... + + // Draw the scale + drawScale(kind); + + // Draw the bars + drawBars(kind); + + // Dispose + this.gc.dispose(); +} + +/** + * Create, paint and save all supported bar graphs and add the corresponding + * image and map references in the given stream. + * + * @param stream + */ +final public void paint(PrintStream stream) { + + // Paint supported graphs + int length = SUPPORTED_GRAPHS.length; + for (int i=0; i<length; i++) { + int kind = SUPPORTED_GRAPHS[i]; + paint(kind); + save(kind, stream); + } + + // Dispose created graphic resources + Iterator iterator = this.resources.values().iterator(); + while (iterator.hasNext()) { + Resource resource = (Resource) iterator.next(); + resource.dispose(); + } + this.resources.clear(); +} + +void print(int kind, PrintStream stream) { + String imgName = getImageName(kind); + stream.print(" if ($type==\"fp_type="+kind+"\") {\n"); + stream.print(" echo '<img src=\""); + stream.print(imgName); + stream.print(".gif\" usemap=\"#"); + stream.print(imgName); + stream.print("\" name=\""); + stream.print(imgName.substring(imgName.lastIndexOf('.'))); + stream.print("\">';\n"); + stream.print(" echo '<map name=\""); + stream.print(imgName); + stream.print("\">';\n"); + if (this.areas != null) { + for (int i=0; i<this.count; i++) { + this.areas[i].print(stream); + } + } + stream.print(" echo '</map>';\n"); + stream.print(" }\n"); +} + +void save(int kind, PrintStream stream) { + File file = new File(this.outputDir, getImageName(kind)+".gif"); + Utils.saveImage(file, this.image); + if (file.exists()) { + print(kind, stream); + } else { + stream.print("<br><br>There is no fingerprint for "); + stream.print(imageName); + stream.print(" (kind="); + stream.print(kind); + stream.print(")<br><br>\n"); + } +} +}
diff --git a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/Main.java b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/Main.java index c57b2db..88410b3 100644 --- a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/Main.java +++ b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/Main.java
@@ -165,14 +165,6 @@ private boolean print = false; /** - * Tells whether the generation is done for a PHP server or not. - * This field is set to <code>false</code> if <b>-nophp</b> argument is specified. - * <p> - * Default is <code>true</code> which means that the generation is done for the build server. - */ -private boolean use_php = true; // PerformanceTestPlugin.getDBLocation().startsWith("net://"); - -/** * Tells what should be the failure percentage threshold. * <p> * Default is 10%. @@ -418,12 +410,6 @@ i++; continue; } - if (arg.equals("-nophp")) { - this.use_php = false; - buffer.append(" ").append(arg).append('\n'); - i++; - continue; - } if (arg.equals("-failure.threshold")) { String value = args[i + 1]; try { @@ -476,28 +462,49 @@ if (this.print) System.out.print("."); File outputFile = new File(this.outputDir, component + ".php"); PrintStream stream = new PrintStream(new BufferedOutputStream(new FileOutputStream(outputFile))); - stream.println(Utils.HTML_OPEN); - stream.println("<link href=\"ToolTip.css\" rel=\"stylesheet\" type=\"text/css\"><script src=\"ToolTip.js\"></script>"); - stream.println(Utils.HTML_DEFAULT_CSS); - stream.println("<body>"); - - String baselineName = performanceResults.getBaselineName(); - String currentName = performanceResults.getName(); - boolean isGlobal = component.equals("global"); - StringBuffer title = new StringBuffer("<h3>Performance of "); - if (!isGlobal) { - title.append(component); - title.append(": "); + + // Print header + boolean isGlobal = component.startsWith("global"); + if (isGlobal) { + File globalFile = new File(this.outputDir, "global.php"); + PrintStream gStream = new PrintStream(new BufferedOutputStream(new FileOutputStream(globalFile))); + gStream.print(Utils.HTML_OPEN); + gStream.print("</head>\n"); + gStream.print("<body>\n"); + gStream.print("<?php\n"); + gStream.print(" include(\"global_fp.php\");\n"); + gStream.print("?>\n"); + gStream.print("<table border=0 cellpadding=2 cellspacing=5 width=\"100%\">\n"); + gStream.print("<tbody><tr> <td colspan=3 align=\"left\" bgcolor=\"#0080c0\" valign=\"top\"><b><font color=\"#ffffff\" face=\"Arial,Helvetica\">\n"); + gStream.print("Detailed performance data grouped by scenario prefix</font></b></td></tr></tbody></table>\n"); + gStream.print("<a href=\"org.eclipse.ant.php?\">org.eclipse.ant*</a><br>\n"); + gStream.print("<a href=\"org.eclipse.compare.php?\">org.eclipse.compare*</a><br>\n"); + gStream.print("<a href=\"org.eclipse.core.php?\">org.eclipse.core*</a><br>\n"); + gStream.print("<a href=\"org.eclipse.jdt.core.php?\">org.eclipse.jdt.core*</a><br>\n"); + gStream.print("<a href=\"org.eclipse.jdt.debug.php?\">org.eclipse.jdt.debug*</a><br>\n"); + gStream.print("<a href=\"org.eclipse.jdt.text.php?\">org.eclipse.jdt.text*</a><br>\n"); + gStream.print("<a href=\"org.eclipse.jdt.ui.php?\">org.eclipse.jdt.ui*</a><br>\n"); + gStream.print("<a href=\"org.eclipse.jface.php?\">org.eclipse.jface*</a><br>\n"); + gStream.print("<a href=\"org.eclipse.osgi.php?\">org.eclipse.osgi*</a><br>\n"); + gStream.print("<a href=\"org.eclipse.pde.ui.php?\">org.eclipse.pde.ui*</a><br>\n"); + gStream.print("<a href=\"org.eclipse.swt.php?\">org.eclipse.swt*</a><br>\n"); + gStream.print("<a href=\"org.eclipse.team.php?\">org.eclipse.team*</a><br>\n"); + gStream.print("<a href=\"org.eclipse.ua.php?\">org.eclipse.ua*</a><br>\n"); + gStream.print("<a href=\"org.eclipse.ui.php?\">org.eclipse.ui*</a><br><p><br><br>\n"); + gStream.print("</body>\n"); + gStream.print(Utils.HTML_CLOSE); + gStream.close(); + } else { + stream.print(Utils.HTML_OPEN); } - title.append(currentName); - title.append(" relative to "); - int index = baselineName.indexOf('_'); - title.append(baselineName.substring(0, index)); - title.append(" ("); - index = baselineName.lastIndexOf('_'); - title.append(baselineName.substring(index+1, baselineName.length())); - title.append(")</h3>"); - stream.println(title.toString()); + stream.print("<link href=\"ToolTip.css\" rel=\"stylesheet\" type=\"text/css\">\n"); + stream.print("<script src=\"ToolTip.js\"></script>\n"); + stream.print("<script src=\"Fingerprints.js\"></script>\n"); + stream.print(Utils.HTML_DEFAULT_CSS); + + // Print title + stream.print("<body>"); + printComponentTitle(performanceResults, component, isGlobal, stream); // print the html representation of fingerprint for each config if (genFingerPrints || genAll) { @@ -510,27 +517,7 @@ } // print scenario status table - if (isGlobal) { - if (!this.use_php) { - stream.println("<table border=0 cellpadding=2 cellspacing=5 width=\"100%\">"); - stream.println("<tbody><tr> <td colspan=3 align=\"left\" bgcolor=\"#0080c0\" valign=\"top\"><b><font color=\"#ffffff\" face=\"Arial,Helvetica\">"); - stream.println("Detailed performance data grouped by scenario prefix</font></b></td></tr></tbody></table>"); - stream.println("<a href=\"org.eclipse.ant.php?\">org.eclipse.ant*</a><br>"); - stream.println("<a href=\"org.eclipse.compare.php?\">org.eclipse.compare*</a><br>"); - stream.println("<a href=\"org.eclipse.core.php?\">org.eclipse.core*</a><br>"); - stream.println("<a href=\"org.eclipse.jdt.core.php?\">org.eclipse.jdt.core*</a><br>"); - stream.println("<a href=\"org.eclipse.jdt.debug.php?\">org.eclipse.jdt.debug*</a><br>"); - stream.println("<a href=\"org.eclipse.jdt.text.php?\">org.eclipse.jdt.text*</a><br>"); - stream.println("<a href=\"org.eclipse.jdt.ui.php?\">org.eclipse.jdt.ui*</a><br>"); - stream.println("<a href=\"org.eclipse.jface.php?\">org.eclipse.jface*</a><br>"); - stream.println("<a href=\"org.eclipse.osgi.php?\">org.eclipse.osgi*</a><br>"); - stream.println("<a href=\"org.eclipse.pde.ui.php?\">org.eclipse.pde.ui*</a><br>"); - stream.println("<a href=\"org.eclipse.swt.php?\">org.eclipse.swt*</a><br>"); - stream.println("<a href=\"org.eclipse.team.php?\">org.eclipse.team*</a><br>"); - stream.println("<a href=\"org.eclipse.ua.php?\">org.eclipse.ua*</a><br>"); - stream.println("<a href=\"org.eclipse.ui.php?\">org.eclipse.ui*</a><br><p><br><br>"); - } - } else if (component.length() > 0) { + if (!isGlobal) { // print the component scenario status table beneath the fingerprint ScenarioStatusTable sst = new ScenarioStatusTable(component, stream); try { @@ -540,10 +527,43 @@ } } - stream.println(Utils.HTML_CLOSE); + stream.print(Utils.HTML_CLOSE); stream.close(); } +private void printComponentTitle(PerformanceResults performanceResults, String component, boolean isGlobal, PrintStream stream) { + String baselineName = performanceResults.getBaselineName(); + String currentName = performanceResults.getName(); + + // Print title line + stream.print("<h3>Performance of "); + if (!isGlobal) { + stream.print(component); + stream.print(": "); + } + stream.print(currentName); + stream.print(" relative to "); + int index = baselineName.indexOf('_'); + stream.print(baselineName.substring(0, index)); + stream.print(" ("); + index = baselineName.lastIndexOf('_'); + stream.print(baselineName.substring(index+1, baselineName.length())); + stream.print(")</h3>\n"); + + // Print reference to global results + if (!isGlobal) { + stream.print("<?php\n"); + stream.print(" $type=$_SERVER['QUERY_STRING'];\n"); + stream.print(" if ($type==\"\") {\n"); + stream.print(" $type=\"fp_type=0\";\n"); + stream.print(" }\n"); + stream.print(" $href=\"<a href=\\\"performance.php?\";\n"); + stream.print(" $href=$href . $type . \"\\\">Back to global results</a><br><br>\";\n"); + stream.print(" echo $href;\n"); + stream.print("?>\n"); + } +} + /* * Print summary of coefficient of variation for each scenario of the given pattern * both for baseline and current builds. @@ -566,7 +586,7 @@ if (scenarioName == null) continue; ScenarioResults scenarioResults = performanceResults.getScenarioResults(scenarioName); if (scenarioResults != null) { - stream.println("<tr>"); + stream.print("<tr>\n"); for (int j=0; j<2; j++) { for (int c=0; c<configsLength; c++) { printSummaryScenarioLine(j, configs[c], scenarioResults, stream); @@ -574,13 +594,13 @@ } stream.print("<td>"); stream.print(scenarioName); - stream.println("</td></tr>"); + stream.print("</td></tr>\n"); } } } catch (Exception e) { e.printStackTrace(); } finally { - stream.println("</table></body></html>"); + stream.print("</table></body></html>\n"); stream.flush(); stream.close(); } @@ -591,31 +611,31 @@ * Print summary presentation (eg. file start and text presenting the purpose of this file contents).. */ private void printSummaryPresentation(PrintStream stream) { - stream.println(Utils.HTML_OPEN); + stream.print(Utils.HTML_OPEN); stream.print(Utils.HTML_DEFAULT_CSS); - stream.println("<title>Summary of Elapsed Process Variation Coefficients</title></head>"); - stream.println("<body><h3>Summary of Elapsed Process Variation Coefficients</h3>\n"); - stream.println("<p> This table provides a bird's eye view of variability in elapsed process times\n"); + stream.print("<title>Summary of Elapsed Process Variation Coefficients</title></head>\n"); + stream.print("<body><h3>Summary of Elapsed Process Variation Coefficients</h3>\n"); + stream.print("<p> This table provides a bird's eye view of variability in elapsed process times\n"); stream.print("for baseline and current build stream performance scenarios."); stream.print(" This summary is provided to facilitate the identification of scenarios that should be examined due to high variability."); - stream.println("The variability for each scenario is expressed as a <a href=\"http://en.wikipedia.org/wiki/Coefficient_of_variation\">coefficient\n"); - stream.println("of variation</a> (CV). The CV is calculated by dividing the <b>standard deviation\n"); - stream.println("of the elapse process time over builds</b> by the <b>average elapsed process\n"); - stream.println("time over builds</b> and multiplying by 100.\n"); - stream.println("</p><p>High CV values may be indicative of any of the following:<br></p>\n"); - stream.println("<ol><li> an unstable performance test. </li>\n"); - stream.println("<ul><li>may be evidenced by an erratic elapsed process line graph.<br><br></li></ul>\n"); - stream.println("<li>performance regressions or improvements at some time in the course of builds.</li>\n"); - stream.println("<ul><li>may be evidenced by plateaus in elapsed process line graphs.<br><br></li></ul>\n"); - stream.println("<li>unstable testing hardware.\n"); + stream.print("The variability for each scenario is expressed as a <a href=\"http://en.wikipedia.org/wiki/Coefficient_of_variation\">coefficient\n"); + stream.print("of variation</a> (CV). The CV is calculated by dividing the <b>standard deviation\n"); + stream.print("of the elapse process time over builds</b> by the <b>average elapsed process\n"); + stream.print("time over builds</b> and multiplying by 100.\n"); + stream.print("</p><p>High CV values may be indicative of any of the following:<br></p>\n"); + stream.print("<ol><li> an unstable performance test. </li>\n"); + stream.print("<ul><li>may be evidenced by an erratic elapsed process line graph.<br><br></li></ul>\n"); + stream.print("<li>performance regressions or improvements at some time in the course of builds.</li>\n"); + stream.print("<ul><li>may be evidenced by plateaus in elapsed process line graphs.<br><br></li></ul>\n"); + stream.print("<li>unstable testing hardware.\n"); stream.print("<ul><li>consistent higher CV values for one test configuration as compared to others across"); - stream.println(" scenarios may be related to hardward problems.</li></ul></li></ol>\n"); - stream.println("<p> Scenarios are listed in alphabetical order in the far right column. A scenario's\n"); - stream.println("variation coefficients (CVs) are in columns to the left for baseline and current\n"); - stream.println("build streams for each test configuration. Scenarios with CVs > 10% are highlighted\n"); - stream.println("in yellow (10%<CV><CV<20%) and orange(CV>20%). </p>\n"); - stream.println("<p> Each CV value links to the scenario's detailed results to allow viewers to\n"); - stream.println("investigate the variability.</p>\n"); + stream.print(" scenarios may be related to hardward problems.</li></ul></li></ol>\n"); + stream.print("<p> Scenarios are listed in alphabetical order in the far right column. A scenario's\n"); + stream.print("variation coefficients (CVs) are in columns to the left for baseline and current\n"); + stream.print("build streams for each test configuration. Scenarios with CVs > 10% are highlighted\n"); + stream.print("in yellow (10%<CV><CV<20%) and orange(CV>20%). </p>\n"); + stream.print("<p> Each CV value links to the scenario's detailed results to allow viewers to\n"); + stream.print("investigate the variability.</p>\n"); } /* @@ -628,7 +648,7 @@ stream.print(length); stream.print("\"><b>Baseline CVs</b></td><td colspan=\""); stream.print(length); - stream.println("\"><b>Current Build Stream CVs</b></td><td rowspan=\"2\"><b>Scenario Name</b></td></tr>"); + stream.print("\"><b>Current Build Stream CVs</b></td><td rowspan=\"2\"><b>Scenario Name</b></td></tr>\n"); stream.print("<tr>"); for (int n=0; n<2; n++) { for (int c=0; c<length; c++) { @@ -637,7 +657,7 @@ stream.print("</td>"); } } - stream.println("</tr>\n"); + stream.print("</tr>\n"); } /* @@ -766,15 +786,43 @@ // Copy images and scripts to output dir Bundle bundle = UiPlugin.getDefault().getBundle(); URL images = bundle.getEntry("images"); - URL scripts = bundle.getEntry("scripts"); if (images != null) { images = FileLocator.resolve(images); Utils.copyImages(new File(images.getPath()), this.outputDir); } + URL scripts = bundle.getEntry("scripts"); if (scripts != null) { scripts = FileLocator.resolve(scripts); Utils.copyScripts(new File(scripts.getPath()), this.outputDir); } + URL doc = bundle.getEntry("doc"); + if (doc != null) { + doc = FileLocator.resolve(doc); + File docDir = new File(doc.getPath()); + FileFilter filter = new FileFilter() { + public boolean accept(File pathname) { + return !pathname.getName().equals("CVS"); + } + }; + File[] docFiles = docDir.listFiles(filter); + for (int i=0; i<docFiles.length; i++) { + File file = docFiles[i]; + if (file.isDirectory()) { + File subdir = new File(this.outputDir, file.getName()); + subdir.mkdir(); + File[] subdirFiles = file.listFiles(filter); + for (int j=0; j<subdirFiles.length; j++) { + if (subdirFiles[i].isDirectory()) { + // expect only one sub-directory + } else { + AbstractResults.copyFile(subdirFiles[j], new File(subdir, subdirFiles[j].getName())); + } + } + } else { + AbstractResults.copyFile(file, new File(this.outputDir, file.getName())); + } + } + } // Print HTML pages and all linked files if (this.print) { @@ -782,7 +830,7 @@ System.out.print(" - components main page"); } long start = System.currentTimeMillis(); - printComponent(performanceResults, "global"); + printComponent(performanceResults, "global_fp"); Iterator components = performanceResults.getComponents().iterator(); while (components.hasNext()) { printComponent(performanceResults, (String) components.next());
diff --git a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/RawDataTable.java b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/RawDataTable.java index c18861e..bac35c3 100644 --- a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/RawDataTable.java +++ b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/RawDataTable.java
@@ -54,7 +54,7 @@ stream.print("<table border=\"1\">"); printSummary(); printDetails(); - stream.println("</table>"); + stream.print("</table>\n"); } /* @@ -77,7 +77,7 @@ private void printDetails() { stream.print("<tr><td><b>Build ID</b></td>"); printColumnHeaders(); - stream.println("</tr>"); + stream.print("</tr>\n"); List builds = this.configResults.getBuildsMatchingPrefixes(this.buildPrefixes); Collections.reverse(builds); @@ -98,7 +98,7 @@ stream.print("</td>"); } if (debug) System.out.println(); - stream.println("</tr>"); + stream.print("</tr>\n"); } if (debug) System.out.println("\n"); } @@ -109,7 +109,7 @@ private void printSummary() { stream.print("<tr><td><b>Stats</b></td>"); printColumnHeaders(); - stream.println("</tr>"); + stream.print("</tr>\n"); int length = this.dimensions.length; double[][] dimStats = new double[2][]; @@ -124,23 +124,23 @@ stream.print((int)dimStats[i][0]); stream.print("</td>"); } - stream.println("</tr>"); + stream.print("</tr>\n"); stream.print("<tr><td>MEAN</td>"); printRowDoubles(dimStats, 1); - stream.println("</tr>"); + stream.print("</tr>\n"); stream.print("<tr><td>STD DEV</td>"); printRowDoubles(dimStats, 2); - stream.println("</tr>"); + stream.print("</tr>\n"); stream.print("<tr><td>COEF. VAR</td>"); printRowDoubles(dimStats, 3); - stream.println("</tr>"); + stream.print("</tr>\n"); // Blank line stream.print("<tr>"); for (int i=0; i<length+1; i++){ stream.print("<td> </td>"); } - stream.println("</tr>"); + stream.print("</tr>\n"); } /*
diff --git a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/ScenarioData.java b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/ScenarioData.java index 8ac9846..8ee20a4 100644 --- a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/ScenarioData.java +++ b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/ScenarioData.java
@@ -211,39 +211,39 @@ if (stream == null) { stream = System.out; } - stream.println(Utils.HTML_OPEN); - stream.println(Utils.HTML_DEFAULT_CSS); + stream.print(Utils.HTML_OPEN); + stream.print(Utils.HTML_DEFAULT_CSS); - stream.println("<title>" + scenarioResults.getName() + "(" + configBox + ")" + "</title></head>"); //$NON-NLS-1$ - stream.println("<h4>Scenario: " + scenarioResults.getName() + " (" + configBox + ")</h4><br>"); //$NON-NLS-1$ //$NON-NLS-2$ + stream.print("<title>" + scenarioResults.getName() + "(" + configBox + ")" + "</title></head>\n"); //$NON-NLS-1$ + stream.print("<h4>Scenario: " + scenarioResults.getName() + " (" + configBox + ")</h4><br>\n"); //$NON-NLS-1$ //$NON-NLS-2$ String failureMessage = Utils.failureMessage(configResults.getCurrentBuildDeltaInfo(), true); if (failureMessage != null){ - stream.println("<table><tr><td><b>"+failureMessage+"</td></tr></table>\n"); + stream.print("<table><tr><td><b>"+failureMessage+"</td></tr></table>\n"); } BuildResults currentBuildResults = configResults.getCurrentBuildResults(); String comment = currentBuildResults.getComment(); if (comment != null) { - stream.println("<p><b>Note:</b><br>\n"); - stream.println(comment + "</p>"); + stream.print("<p><b>Note:</b><br>\n"); + stream.print(comment + "</p>\n"); } // Print link to raw data. String rawDataFile = "raw/" + scenarioFileName+".html"; - stream.println("<br><br><b><a href=\""+rawDataFile+"\">Raw data and Stats</a></b><br><br>\n"); - stream.println("<b>Click measurement name to view line graph of measured values over builds.</b><br><br>\n"); + stream.print("<br><br><b><a href=\""+rawDataFile+"\">Raw data and Stats</a></b><br><br>\n"); + stream.print("<b>Click measurement name to view line graph of measured values over builds.</b><br><br>\n"); try { // Print build result table - stream.println("<table border=\"1\">"); //$NON-NLS-1$ + stream.print("<table border=\"1\">\n"); //$NON-NLS-1$ stream.print("<tr><td><b>Build Id</b></td>"); //$NON-NLS-1$ Dim[] dimensions = AbstractResults.SUPPORTED_DIMS; int dimLength = dimensions.length; for (int d=0; d<dimLength; d++) { stream.print("<td><a href=\"#" + dimensions[d].getShortName() + "\"><b>" + dimensions[d].getName() + "</b></a></td>"); } - stream.println("</tr>\n"); + stream.print("</tr>\n"); // Write build lines printTableLine(stream, currentBuildResults); @@ -253,12 +253,12 @@ printDifferenceLine(stream, configResults); // End of table - stream.println("</table>"); - stream.println("*Delta values in red and green indicate degradation > 10% and improvement > 10%,respectively.<br><br>"); - stream.println("<br><hr>\n\n"); + stream.print("</table>\n"); + stream.print("*Delta values in red and green indicate degradation > 10% and improvement > 10%,respectively.<br><br>\n"); + stream.print("<br><hr>\n\n"); // print text legend. - stream.println("Black and yellow points plot values measured in integration and last seven nightly builds.<br>\n" + "Magenta points plot the repeated baseline measurement over time.<br>\n" + stream.print("Black and yellow points plot values measured in integration and last seven nightly builds.<br>\n" + "Magenta points plot the repeated baseline measurement over time.<br>\n" + "Boxed points represent previous releases, milestone builds, current reference and current build.<br><br>\n" + "Hover over any point for build id and value.\n"); @@ -270,18 +270,18 @@ String imgFileName = scenarioFileName + "_" + dimShortName; File imgFile = createFile(outputDir, "graphs", imgFileName, "gif"); saveGraph(lineGraph, imgFile); - stream.println("<br><a name=\"" + dimShortName + "\"></a>"); - stream.println("<br><b>" + dimensions[d].getName() + "</b><br>"); - stream.println(dimensions[d].getDescription() + "<br><br>\n"); + stream.print("<br><a name=\"" + dimShortName + "\"></a>\n"); + stream.print("<br><b>" + dimensions[d].getName() + "</b><br>\n"); + stream.print(dimensions[d].getDescription() + "<br><br>\n"); stream.print("<img src=\"graphs/"); stream.print(imgFile.getName()); stream.print("\" usemap=\"#" + lineGraph.fTitle + "\">"); stream.print("<map name=\"" + lineGraph.fTitle + "\">"); stream.print(lineGraph.getAreas()); - stream.println("</map>"); + stream.print("</map>\n"); } - stream.println("<br><br></body>"); - stream.println(Utils.HTML_CLOSE); + stream.print("<br><br></body>\n"); + stream.print(Utils.HTML_CLOSE); if (stream != System.out) stream.close(); @@ -309,7 +309,7 @@ stream.print("<td>"); stream.print(displayValue); if (stddev < 0) { - stream.println(" [n/a]"); + stream.print(" [n/a]\n"); } else if (stddev > 0) { stream.print(" ["); stream.print(dimensions[d].getDisplayValue(stddev)); @@ -317,7 +317,7 @@ } stream.print( "</td>"); } - stream.println("</tr>"); + stream.print("</tr>\n"); } /* @@ -380,21 +380,21 @@ if (stream == null) stream = System.out; RawDataTable currentResultsTable = new RawDataTable(configResults, this.buildIDStreamPatterns, stream); RawDataTable baselineResultsTable = new RawDataTable(configResults, this.baselinePrefix, stream); - stream.println(Utils.HTML_OPEN); - stream.println(Utils.HTML_DEFAULT_CSS); - stream.println("<title>" + scenarioName + "(" + configBox + ")" + " - Details</title></head>"); //$NON-NLS-1$ - stream.println("<h4>Scenario: " + scenarioName + " (" + configBox + ")</h4>"); //$NON-NLS-1$ - stream.println("<a href=\"../"+scenarioFileName+".html\">VIEW GRAPH</a><br><br>"); //$NON-NLS-1$ - stream.println("<table><td><b>Current Stream Test Runs</b></td><td><b>Baseline Test Runs</b></td></tr>\n"); - stream.println("<tr valign=\"top\">"); + stream.print(Utils.HTML_OPEN); + stream.print(Utils.HTML_DEFAULT_CSS); + stream.print("<title>" + scenarioName + "(" + configBox + ")" + " - Details</title></head>\n"); //$NON-NLS-1$ + stream.print("<h4>Scenario: " + scenarioName + " (" + configBox + ")</h4>\n"); //$NON-NLS-1$ + stream.print("<a href=\"../"+scenarioFileName+".html\">VIEW GRAPH</a><br><br>\n"); //$NON-NLS-1$ + stream.print("<table><td><b>Current Stream Test Runs</b></td><td><b>Baseline Test Runs</b></td></tr>\n"); + stream.print("<tr valign=\"top\">\n"); stream.print("<td>"); currentResultsTable.print(); - stream.println("</td>"); + stream.print("</td>\n"); stream.print("<td>"); baselineResultsTable.print(); - stream.println("</td>"); - stream.println("</tr>"); - stream.println("</table>"); + stream.print("</td>\n"); + stream.print("</tr>\n"); + stream.print("</table>\n"); stream.close(); } }
diff --git a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/ScenarioStatusTable.java b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/ScenarioStatusTable.java index 45494d2..ec257e2 100644 --- a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/ScenarioStatusTable.java +++ b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/ScenarioStatusTable.java
@@ -49,7 +49,7 @@ this.jsIdCount = 0; for (int i=0; i<size; i++) { ScenarioResults scenarioResults = (ScenarioResults) scenarios.get(i); - this.stream.println("<tr>"); + this.stream.print("<tr>\n"); this.stream.print("<td>"); boolean hasSummary = scenarioResults.hasSummary(); if (hasSummary) this.stream.print("<b>"); @@ -65,25 +65,25 @@ this.stream.print(scenarioResults.getShortName()); } if (hasSummary) this.stream.print("</b>"); - this.stream.println(); + this.stream.print("\n"); String[] configs = performanceResults.getConfigNames(true/*sort*/); int length = configs.length; for (int j=0; j<length; j++) { printConfigStats(scenarioResults, configs[j]); } } - this.stream.println("</table>"); + this.stream.print("</table>\n"); } /* * Print the table columns title. */ private void printColumnsTitle(int size, PerformanceResults performanceResults) { - this.stream.println("<table border=\"1\">"); - this.stream.println("<tr>"); + this.stream.print("<table border=\"1\">\n"); + this.stream.print("<tr>\n"); this.stream.print("<td><h4>All "); this.stream.print(size); - this.stream.println(" scenarios</h4></td>"); + this.stream.print(" scenarios</h4></td>\n"); String[] configNames = performanceResults.getConfigNames(true/*sort*/); String[] configBoxes = performanceResults.getConfigBoxes(true/*sort*/); int length = configNames.length; @@ -113,7 +113,7 @@ } this.stream.print("<td><h5>"); this.stream.print(columnTitle); - this.stream.println("</h5>"); + this.stream.print("</h5>\n"); } } @@ -140,10 +140,10 @@ this.stream.print(configResults.getName()); this.stream.print('/'); this.stream.print(scenarioResults.getFileName()); - this.stream.println(".html\">"); + this.stream.print(".html\">\n"); this.stream.print("<img hspace=\"10\" border=\"0\" src=\""); this.stream.print(image); - this.stream.println("\"/></a>"); + this.stream.print("\"/></a>\n"); } else { // create message with tooltip text including deviation with error plus failure message this.jsIdCount+=1; @@ -155,62 +155,63 @@ this.stream.print(configResults.getName()); this.stream.print('/'); this.stream.print(scenarioResults.getFileName()); - this.stream.println(".html\">"); + this.stream.print(".html\">\n"); this.stream.print("<img hspace=\"10\" border=\"0\" src=\""); this.stream.print(image); - this.stream.println("\"/>"); + this.stream.print("\"/>\n"); this.stream.print("<span class=\"hidden_tooltip\" id=\"toolTip"); this.stream.print(jsIdCount); this.stream.print("\">"); this.stream.print(failure); - this.stream.println("</span></a>"); + this.stream.print("</span></a>\n"); } String result = Utils.failureMessage(deviation, false); - this.stream.println(result); + this.stream.print(result); + this.stream.print("\n"); } /* * Print the status table explanationtitle. */ private void printTitle() { - this.stream.println("<br><h4>Scenario Status</h4>"); - this.stream.println("The following table gives a complete but compact view of performance results for the component.<br>"); - this.stream.println("Each line of the table shows the results for one scenario on all machines.<br><br>"); - this.stream.println("The name of the scenario is in <b>bold</b> when its results are also displayed in the fingerprints<br>"); - this.stream.println("and starts with an '*' when the scenario has no results in the last baseline run.<br><br>"); - this.stream.println("Here are information displayed for each test (ie. in each cell):"); - this.stream.println("<ul>"); - this.stream.println("<li>an icon showing whether the test fails or passes and whether it's reliable or not.<br>"); - this.stream.println("The legend for this icon is:"); - this.stream.println("<ul>"); + this.stream.print("<br><h4>Scenario Status</h4>\n"); + this.stream.print("The following table gives a complete but compact view of performance results for the component.<br>\n"); + this.stream.print("Each line of the table shows the results for one scenario on all machines.<br><br>\n"); + this.stream.print("The name of the scenario is in <b>bold</b> when its results are also displayed in the fingerprints<br>\n"); + this.stream.print("and starts with an '*' when the scenario has no results in the last baseline run.<br><br>\n"); + this.stream.print("Here are information displayed for each test (ie. in each cell):\n"); + this.stream.print("<ul>\n"); + this.stream.print("<li>an icon showing whether the test fails or passes and whether it's reliable or not.<br>\n"); + this.stream.print("The legend for this icon is:\n"); + this.stream.print("<ul>\n"); this.stream.print("<li>Green (<img src=\""); this.stream.print(Utils.OK_IMAGE); this.stream.print("\">): mark a <b>successful result</b>, which means this test has neither significant performance regression nor significant standard error</li>"); this.stream.print("<li>Red (<img src=\""); this.stream.print(Utils.FAIL_IMAGE); - this.stream.println("\">): mark a <b>failing result</b>, which means this test shows a significant performance regression (more than 10%)</li>"); + this.stream.print("\">): mark a <b>failing result</b>, which means this test shows a significant performance regression (more than 10%)</li>\n"); this.stream.print("<li>Gray (<img src=\""); this.stream.print(Utils.FAIL_IMAGE_EXPLAINED); - this.stream.println("\">): mark a <b>failing result</b> (see above) with a comment explaining this degradation.</li>"); + this.stream.print("\">): mark a <b>failing result</b> (see above) with a comment explaining this degradation.</li>\n"); this.stream.print("<li>Yellow (<img src=\""); this.stream.print(Utils.FAIL_IMAGE_WARN); this.stream.print("\"> or <img src=\""); this.stream.print(Utils.OK_IMAGE_WARN); this.stream.print("\">): mark a <b>failing or successful result</b> with a significant standard error (more than "); this.stream.print(Utils.STANDARD_ERROR_THRESHOLD_STRING); - this.stream.println(")</li>"); + this.stream.print(")</li>\n"); this.stream.print("<li>Black (<img src=\""); this.stream.print(Utils.UNKNOWN_IMAGE); this.stream.print("\">): mark an <b>undefined result</b>, which means that deviation on this test is not a number (<code>NaN</code>) or is infinite (happens when the reference value is equals to 0!)</li>"); - this.stream.println("<li>\"n/a\": mark a test for with <b>no</b> performance results</li>"); - this.stream.println("</ul></li>"); - this.stream.println("<li>the value of the deviation from the baseline as a percentage (ie. formula is: <code>(build_test_time - baseline_test_time) / baseline_test_time</code>)</li>"); - this.stream.println("<li>the value of the standard error of this deviation as a percentage (ie. formula is: <code>sqrt(build_test_stddev^2 / N + baseline_test_stddev^2 / N) / baseline_test_time</code>)<br>"); - this.stream.println("When test only has one measure, the standard error cannot be computed and is replaced with a '<font color=\"#CCCC00\">[n/a]</font>'.</li>"); - this.stream.println("</ul>"); - this.stream.println("<u>Hints</u>:<ul>"); - this.stream.println("<li>fly over image of failing tests to see the complete error message</li>"); - this.stream.println("<li>to look at the complete and detailed test results, click on its image</li>"); - this.stream.println("</ul>"); + this.stream.print("<li>\"n/a\": mark a test for with <b>no</b> performance results</li>\n"); + this.stream.print("</ul></li>\n"); + this.stream.print("<li>the value of the deviation from the baseline as a percentage (ie. formula is: <code>(build_test_time - baseline_test_time) / baseline_test_time</code>)</li>\n"); + this.stream.print("<li>the value of the standard error of this deviation as a percentage (ie. formula is: <code>sqrt(build_test_stddev^2 / N + baseline_test_stddev^2 / N) / baseline_test_time</code>)<br>\n"); + this.stream.print("When test only has one measure, the standard error cannot be computed and is replaced with a '<font color=\"#CCCC00\">[n/a]</font>'.</li>\n"); + this.stream.print("</ul>\n"); + this.stream.print("<u>Hints</u>:<ul>\n"); + this.stream.print("<li>fly over image of failing tests to see the complete error message</li>\n"); + this.stream.print("<li>to look at the complete and detailed test results, click on its image</li>\n"); + this.stream.print("</ul>\n"); } }
diff --git a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/Utils.java b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/Utils.java index 7055465..94fe523 100644 --- a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/Utils.java +++ b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/Utils.java
@@ -10,15 +10,22 @@ *******************************************************************************/ package org.eclipse.test.performance.ui; +import java.io.BufferedOutputStream; import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.Arrays; import java.util.Calendar; import java.util.HashMap; +import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.ImageData; +import org.eclipse.swt.graphics.ImageLoader; import org.eclipse.swt.graphics.PaletteData; import org.eclipse.swt.graphics.RGB; import org.eclipse.test.internal.performance.PerformanceTestPlugin; @@ -53,6 +60,8 @@ public final static String FAIL_IMAGE="FAIL.gif"; public final static String FAIL_IMAGE_WARN="FAIL_caution.gif"; public final static String FAIL_IMAGE_EXPLAINED="FAIL_greyed.gif"; + public final static String LIGHT="light.gif"; + public final static String WARNING_OBJ="warning_obj.gif"; public final static int OK = 0; public final static int NAN = 0x1; public final static int ERR = 0x2; @@ -61,24 +70,24 @@ * Return <html><head><meta http-equiv="Content-Type" * content="text/html; charset=iso-8859-1"> */ - public static String HTML_OPEN = "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\">"; + public final static String HTML_OPEN = "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\">\n"; /** * Return "</html>". */ - public static String HTML_CLOSE = "</html>"; + public final static String HTML_CLOSE = "</html>\n"; /** * Default style-sheet used on eclipse.org */ - public static String HTML_DEFAULT_CSS = "<style type=\"text/css\">" + "p, table, td, th { font-family: arial, helvetica, geneva; font-size: 10pt}\n" + public final static String HTML_DEFAULT_CSS = "<style type=\"text/css\">" + "p, table, td, th { font-family: arial, helvetica, geneva; font-size: 10pt}\n" + "pre { font-family: \"Courier New\", Courier, mono; font-size: 10pt}\n" + "h2 { font-family: arial, helvetica, geneva; font-size: 18pt; font-weight: bold ; line-height: 14px}\n" + "code { font-family: \"Courier New\", Courier, mono; font-size: 10pt}\n" + "sup { font-family: arial,helvetica,geneva; font-size: 10px}\n" + "h3 { font-family: arial, helvetica, geneva; font-size: 14pt; font-weight: bold}\n" + "li { font-family: arial, helvetica, geneva; font-size: 10pt}\n" + "h1 { font-family: arial, helvetica, geneva; font-size: 28px; font-weight: bold}\n" + "body { font-family: arial, helvetica, geneva; font-size: 10pt; clip: rect( ); margin-top: 5mm; margin-left: 3mm}\n" + ".indextop { font-size: x-large;; font-family: Verdana, Arial, Helvetica, sans-serif; font-weight: bold}\n" - + ".indexsub { font-size: xx-small;; font-family: Arial, Helvetica, sans-serif; color: #8080FF}\n" + "</style>"; + + ".indexsub { font-size: xx-small;; font-family: Arial, Helvetica, sans-serif; color: #8080FF}\n" + "</style>\n\n"; /** * Creates a Variations object using build id pattern, config and jvm. @@ -106,6 +115,8 @@ AbstractResults.copyFile(new File(images, OK_IMAGE), new File(output, OK_IMAGE)); AbstractResults.copyFile(new File(images, OK_IMAGE_WARN), new File(output, OK_IMAGE_WARN)); AbstractResults.copyFile(new File(images, UNKNOWN_IMAGE), new File(output, UNKNOWN_IMAGE)); + AbstractResults.copyFile(new File(images, LIGHT), new File(output, LIGHT)); + AbstractResults.copyFile(new File(images, WARNING_OBJ), new File(output, WARNING_OBJ)); } /** @@ -114,6 +125,24 @@ public static void copyScripts(File scripts, File output) { AbstractResults.copyFile(new File(scripts, "ToolTip.css"), new File(output, "ToolTip.css")); AbstractResults.copyFile(new File(scripts, "ToolTip.js"), new File(output, "ToolTip.js")); + AbstractResults.copyFile(new File(scripts, "Fingerprints.js"), new File(output, "Fingerprints.js")); + } + + /** + * Copy all doc files. + */ + public static void copyDoc(File docDir, File output) { + File[] docFiles = docDir.listFiles(); + for (int i=0; i<docFiles.length; i++) { + File file = docFiles[i]; + if (file.isDirectory()) { + File subdir = new File(output, file.getName()); + subdir.mkdir(); + copyDoc(file, subdir); + } else { + AbstractResults.copyFile(file, new File(output, file.getName())); + } + } } /** @@ -361,4 +390,31 @@ return image; } +/** + * @param outputFile + * @param image + */ +public static void saveImage(File outputFile, Image image) { + // Save image + ImageData data = downSample(image); + ImageLoader imageLoader = new ImageLoader(); + imageLoader.data = new ImageData[] { data }; + + OutputStream out = null; + try { + out = new BufferedOutputStream(new FileOutputStream(outputFile)); + imageLoader.save(out, SWT.IMAGE_GIF); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } finally { + image.dispose(); + if (out != null) { + try { + out.close(); + } catch (IOException e1) { + // silently ignored + } + } + } +} } \ No newline at end of file