Home | History | Annotate | Download | only in ui
      1 /*******************************************************************************
      2  * Copyright (c) 2000, 2009 IBM Corporation and others.
      3  * All rights reserved. This program and the accompanying materials
      4  * are made available under the terms of the Eclipse Public License v1.0
      5  * which accompanies this distribution, and is available at
      6  * http://www.eclipse.org/legal/epl-v10.html
      7  *
      8  * Contributors:
      9  *     IBM Corporation - initial API and implementation
     10  *******************************************************************************/
     11 package org.eclipse.test.performance.ui;
     12 
     13 import java.io.PrintStream;
     14 import java.util.List;
     15 import java.util.StringTokenizer;
     16 
     17 import org.eclipse.test.internal.performance.results.db.BuildResults;
     18 import org.eclipse.test.internal.performance.results.db.ConfigResults;
     19 import org.eclipse.test.internal.performance.results.db.PerformanceResults;
     20 import org.eclipse.test.internal.performance.results.db.ScenarioResults;
     21 
     22 /**
     23  * Class used to print a scenario status table.
     24  */
     25 public class ScenarioStatusTable {
     26 
     27 	private String component;
     28 	private PrintStream stream;
     29 	private int jsIdCount;
     30 
     31 /**
     32  * Creates an HTML table of red x/green check for a scenario for each
     33  * configuration.
     34  */
     35 public ScenarioStatusTable(String  name, PrintStream stream) {
     36     this.component = name;
     37     this.stream = stream;
     38 }
     39 
     40 /**
     41  * Prints the HTML representation of scenario status table into the given stream.
     42  */
     43 public void print(PerformanceResults performanceResults) {
     44 
     45 	String baselineName = performanceResults.getBaselineName();
     46 	List scenarios = performanceResults.getComponentScenarios(this.component);
     47 	int size = scenarios.size();
     48 
     49 	// Print titles
     50 	printTitle();
     51 	this.stream.print("<table border=\"1\">\n");
     52 	this.stream.print("<tr>\n");
     53 	this.stream.print("<td><h4>All ");
     54 	this.stream.print(computeSize(scenarios));
     55 	this.stream.print(" scenarios</h4></td>\n");
     56 	printColumnsTitle(size, performanceResults);
     57 
     58 	// Print one line per scenario results
     59 	this.jsIdCount = 0;
     60 	for (int i=0; i<size; i++) {
     61 		ScenarioResults scenarioResults = (ScenarioResults) scenarios.get(i);
     62 		if (!scenarioResults.isValid()) continue;
     63 		this.stream.print("<tr>\n");
     64 		this.stream.print("<td>");
     65 		boolean hasSummary = scenarioResults.hasSummary();
     66 		if (hasSummary) this.stream.print("<b>");
     67 		String scenarioBaseline = scenarioResults.getBaselineBuildName();
     68 		boolean hasBaseline = baselineName.equals(scenarioBaseline);
     69 		if (!hasBaseline) {
     70 			this.stream.print("*");
     71 			this.stream.print(scenarioResults.getShortName());
     72 			this.stream.print(" <small>(vs.&nbsp;");
     73 			this.stream.print(scenarioBaseline);
     74 			this.stream.print(")</small>");
     75 		} else {
     76 			this.stream.print(scenarioResults.getShortName());
     77 		}
     78 		if (hasSummary) this.stream.print("</b>");
     79 		this.stream.print("\n");
     80 		String[] configs = performanceResults.getConfigNames(true/*sort*/);
     81 		int length = configs.length;
     82 		for (int j=0; j<length; j++) {
     83 			printConfigStats(scenarioResults, configs[j]);
     84 		}
     85 	}
     86 	this.stream.print("</table>\n");
     87 }
     88 
     89 private int computeSize(List scenarios) {
     90 	int size = scenarios.size();
     91 	int n = 0;
     92 	for (int i=0; i<size; i++) {
     93 		ScenarioResults scenarioResults = (ScenarioResults) scenarios.get(i);
     94 		if (scenarioResults.isValid()) n++;
     95 	}
     96 	return n;
     97 }
     98 
     99 /*
    100  * Print the table columns title.
    101  */
    102 private void printColumnsTitle(int size, PerformanceResults performanceResults) {
    103 	String[] configNames = performanceResults.getConfigNames(true/*sort*/);
    104 	String[] configBoxes = performanceResults.getConfigBoxes(true/*sort*/);
    105 	int length = configNames.length;
    106 	for (int i=0; i<length; i++) {
    107 		String columnTitle = configNames[i];
    108 		String boxName = configBoxes[i];
    109 		int idx = boxName.indexOf('(');
    110 		if (idx < 0) {
    111 			columnTitle = boxName;
    112 		} else {
    113 			// first line
    114 			StringTokenizer tokenizer = new StringTokenizer(boxName.substring(0, idx).trim(), " ");
    115 			StringBuffer buffer = new StringBuffer(tokenizer.nextToken());
    116 			while (tokenizer.hasMoreTokens()) {
    117 				buffer.append("&nbsp;");
    118 				buffer.append(tokenizer.nextToken());
    119 			}
    120 			buffer.append(' ');
    121 			// second line
    122 			tokenizer = new StringTokenizer(boxName.substring(idx).trim(), " ");
    123 			buffer.append(tokenizer.nextToken());
    124 			while (tokenizer.hasMoreTokens()) {
    125 				buffer.append("&nbsp;");
    126 				buffer.append(tokenizer.nextToken());
    127 			}
    128 			columnTitle = buffer.toString();
    129 		}
    130 		this.stream.print("<td><h5>");
    131 		this.stream.print(columnTitle);
    132 		this.stream.print("</h5>\n");
    133 	}
    134 }
    135 
    136 /*
    137  * Print the scenario statistics value for the given configuration.
    138  */
    139 private void printConfigStats(ScenarioResults scenarioResults, String config) {
    140 	ConfigResults configResults = scenarioResults.getConfigResults(config);
    141 	if (configResults == null || !configResults.isValid()) {
    142 		this.stream.print("<td>n/a</td>");
    143 		return;
    144 	}
    145 	BuildResults currentBuildResults = configResults.getCurrentBuildResults();
    146 	String failure = currentBuildResults.getFailure();
    147 	double[] deviation = configResults.getCurrentBuildDeltaInfo();
    148 	int confidence = Utils.confidenceLevel(deviation);
    149 	boolean hasFailure = failure != null;
    150 	String comment = currentBuildResults.getComment();
    151 	String image = Utils.getImage(confidence, hasFailure, comment != null);
    152 	this.stream.print("<td><a ");
    153 	if (!hasFailure|| (confidence & Utils.NAN) != 0 || failure.length() == 0){
    154 		// write deviation with error in table when test pass
    155 		this.stream.print("href=\"");
    156 		this.stream.print(configResults.getName());
    157 		this.stream.print('/');
    158 		this.stream.print(scenarioResults.getFileName());
    159 		this.stream.print(".html\">\n");
    160 		this.stream.print("<img hspace=\"10\" border=\"0\" src=\"");
    161 		this.stream.print(image);
    162 		this.stream.print("\"/></a>\n");
    163 	} else {
    164 		// create message with tooltip text including deviation with error plus failure message
    165 		this.jsIdCount+=1;
    166 		this.stream.print("class=\"tooltipSource\" onMouseover=\"show_element('toolTip");
    167 		this.stream.print(this.jsIdCount);
    168 		this.stream.print("')\" onMouseout=\"hide_element('toolTip");
    169 		this.stream.print(this.jsIdCount);
    170 		this.stream.print("')\" \nhref=\"");
    171 		this.stream.print(configResults.getName());
    172 		this.stream.print('/');
    173 		this.stream.print(scenarioResults.getFileName());
    174 		this.stream.print(".html\">\n");
    175 		this.stream.print("<img hspace=\"10\" border=\"0\" src=\"");
    176 		this.stream.print(image);
    177 		this.stream.print("\"/>\n");
    178 		this.stream.print("<span class=\"hidden_tooltip\" id=\"toolTip");
    179 		this.stream.print(this.jsIdCount);
    180 		this.stream.print("\">");
    181 		this.stream.print(failure);
    182 		this.stream.print("</span></a>\n");
    183 	}
    184 	String result = Utils.failureMessage(deviation, false);
    185 	this.stream.print(result);
    186 	this.stream.print("\n");
    187 }
    188 
    189 /*
    190  * Print the status table explanationtitle.
    191  */
    192 private void printTitle() {
    193 	this.stream.print("<br><h4>Scenario Status</h4>\n");
    194 	this.stream.print("The following table gives a complete but compact view of performance results for the component.<br>\n");
    195 	this.stream.print("Each line of the table shows the results for one scenario on all machines.<br><br>\n");
    196 	this.stream.print("The name of the scenario is in <b>bold</b> when its results are also displayed in the fingerprints<br>\n");
    197 	this.stream.print("and starts with an '*' when the scenario has no results in the last baseline run.<br><br>\n");
    198 	this.stream.print("Here are information displayed for each test (ie. in each cell):\n");
    199 	this.stream.print("<ul>\n");
    200 	this.stream.print("<li>an icon showing whether the test fails or passes and whether it's reliable or not.<br>\n");
    201 	this.stream.print("The legend for this icon is:\n");
    202 	this.stream.print("<ul>\n");
    203 	this.stream.print("<li>Green (<img src=\"");
    204 	this.stream.print(Utils.OK_IMAGE);
    205 	this.stream.print("\">): mark a <b>successful result</b>, which means this test has neither significant performance regression nor significant standard error</li>");
    206 	this.stream.print("<li>Red (<img src=\"");
    207 	this.stream.print(Utils.FAIL_IMAGE);
    208 	this.stream.print("\">): mark a <b>failing result</b>, which means this test shows a significant performance regression (more than 10%)</li>\n");
    209 	this.stream.print("<li>Gray (<img src=\"");
    210 	this.stream.print(Utils.FAIL_IMAGE_EXPLAINED);
    211 	this.stream.print("\">): mark a <b>failing result</b> (see above) with a comment explaining this degradation.</li>\n");
    212 	this.stream.print("<li>Yellow (<img src=\"");
    213 	this.stream.print(Utils.FAIL_IMAGE_WARN);
    214 	this.stream.print("\"> or <img src=\"");
    215 	this.stream.print(Utils.OK_IMAGE_WARN);
    216 	this.stream.print("\">): mark a <b>failing or successful result</b> with a significant standard error (more than ");
    217 	this.stream.print(Utils.STANDARD_ERROR_THRESHOLD_STRING);
    218 	this.stream.print(")</li>\n");
    219 	this.stream.print("<li>Black (<img src=\"");
    220 	this.stream.print(Utils.UNKNOWN_IMAGE);
    221 	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>");
    222 	this.stream.print("<li>\"n/a\": mark a test for with <b>no</b> performance results</li>\n");
    223 	this.stream.print("</ul></li>\n");
    224 	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");
    225 	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");
    226 	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");
    227 	this.stream.print("</ul>\n");
    228 	this.stream.print("<u>Hints</u>:<ul>\n");
    229 	this.stream.print("<li>fly over image of failing tests to see the complete error message</li>\n");
    230 	this.stream.print("<li>to look at the complete and detailed test results, click on its image</li>\n");
    231 	this.stream.print("</ul>\n");
    232 }
    233 }
    234