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 *******************************************************************************/ 11package org.eclipse.test.performance.ui; 12 13import java.io.PrintStream; 14import java.util.List; 15import java.util.StringTokenizer; 16 17import org.eclipse.test.internal.performance.results.db.BuildResults; 18import org.eclipse.test.internal.performance.results.db.ConfigResults; 19import org.eclipse.test.internal.performance.results.db.PerformanceResults; 20import org.eclipse.test.internal.performance.results.db.ScenarioResults; 21 22/** 23 * Class used to print a scenario status table. 24 */ 25public 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 */ 35public 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 */ 43public 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. "); 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 89private 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 */ 102private 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(" "); 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(" "); 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 */ 139private 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 */ 192private 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